casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Aipsrc.h
Go to the documentation of this file.
00001 //# Aipsrc.h: Class to read the casa general resource files
00002 //# Copyright (C) 1995,1996,1997,1998,1999,2002,2004
00003 //# Associated Universities, Inc. Washington DC, USA.
00004 //#
00005 //# This library is free software; you can redistribute it and/or modify it
00006 //# under the terms of the GNU Library General Public License as published by
00007 //# the Free Software Foundation; either version 2 of the License, or (at your
00008 //# option) any later version.
00009 //#
00010 //# This library is distributed in the hope that it will be useful, but WITHOUT
00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00013 //# License for more details.
00014 //#
00015 //# You should have received a copy of the GNU Library General Public License
00016 //# along with this library; if not, write to the Free Software Foundation,
00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
00018 //#
00019 //# Correspondence concerning AIPS++ should be addressed as follows:
00020 //#        Internet email: aips2-request@nrao.edu.
00021 //#        Postal address: AIPS++ Project Office
00022 //#                        National Radio Astronomy Observatory
00023 //#                        520 Edgemont Road
00024 //#                        Charlottesville, VA 22903-2475 USA
00025 //#
00026 //# $Id: Aipsrc.h 21067 2011-05-06 13:58:12Z gervandiepen $
00027 
00028 #ifndef CASA_AIPSRC_H
00029 #define CASA_AIPSRC_H
00030 
00031 #include <casa/aips.h>
00032 #include <casa/BasicSL/String.h>
00033 #include <casa/Containers/Block.h>
00034 #include <casa/Arrays/Vector.h>
00035 #include <casa/OS/Mutex.h>
00036 
00037 namespace casa { //# NAMESPACE CASA - BEGIN
00038 
00039 //# Forward declarations
00040 template <class T> class AipsrcValue;
00041 template <class T> class AipsrcVector;
00042 class Aipsrc;
00043 
00044 //# Typedefs
00045 typedef AipsrcValue<Double> AipsrcDouble;
00046 typedef AipsrcValue<Int> AipsrcInt;
00047 typedef AipsrcValue<Bool> AipsrcBool;
00048 typedef Aipsrc AipsrcString;
00049 typedef AipsrcVector<Double> AipsrcVDouble;
00050 typedef AipsrcVector<Int> AipsrcVInt;
00051 typedef AipsrcVector<Bool> AipsrcVBool;
00052 typedef AipsrcVector<String> AipsrcVString;
00053 
00054 
00055 // <summary> Class to read the casa general resource files </summary>
00056 
00057 // <use visibility=export>
00058 
00059 // <reviewed reviewer="wyoung" date="1996/11/25" tests="tAipsrc" demos="">
00060 // </reviewed>
00061 
00062 // <prerequisite>
00063 //  <li> None
00064 // </prerequisite>
00065 //
00066 // <etymology>
00067 // A class for getting values from the casa resource files
00068 // </etymology>
00069 //
00070 // <synopsis>
00071 // The static Aipsrc class can get information from the casa resource files.
00072 // It has the same functionality as getrc (c program used for aips++ 
00073 // installation scripts).<br>
00074 // In addition it acts as a central clearing house between system and
00075 // software by providing functionality to obtain aips++ system parameters (like
00076 // AIPSPATH elements), and the possibility of storing system wide information
00077 // provided by a class for reference by other classes. <br>
00078 // The format of a line in a resource file is:
00079 // <srcblock>
00080 //      # Line starting with an # in column 1 is a comment (as is an empty line)
00081 //      keyword:   value
00082 //      keyword:   value
00083 // </srcblock>
00084 // The keyword (starting at first non-blank) 
00085 // consists in general of keyword fields separated by periods:  
00086 //<srcblock>
00087 //      printer.ps.page
00088 //      measures.precession.d_interval
00089 //      measures.nutation.d_interval
00090 // </srcblock>
00091 // and, by preference, in lower case (but
00092 // search is case sensitive) with an <src>_</src> as word-parts separator. <br>
00093 // The keyword and value are separated by a <src>:</src>. The value is the string
00094 // from the first non-whitespace character after the separator to the end of
00095 // the line. Interpretation of the string is in general the program's 
00096 // responsibility, but special <src>find()</src> calls (see below) exist to 
00097 // aid.<br>
00098 // Any part of the keyword string can be replaced by a wildcard <src>*</src>
00099 // to indicate all values with that structure (e.g.
00100 // <src>*.d_interval</src> would indicate in the example above both the
00101 // precession and the nutation <src>d_interval</src>.<br>
00102 // A match between a keyword to be found and a keyword in the resource files
00103 // will be the first match (taking wildcards into account) encountered in the
00104 // search through the resource files.
00105 // The resource files to be looked at can be defined in the environment
00106 // variable CASARCFILES. If undefined, the resource files searched are (in the
00107 // given order):
00108 // <srcblock>
00109 //   ~/.casarc
00110 //   ~/.casa/rc
00111 //   ~/.aipsrc
00112 //   $AIPSROOT/.aipsrc
00113 //   $AIPSHOST/aipsrc
00114 //   $AIPSSITE/aipsrc
00115 //   $AIPSARCH/aipsrc
00116 // </srcblock> 
00117 // It is not an error for any of the aipsrc files to be absent or empty.
00118 // However, it is an error if <em>HOME</em> has not been set:
00119 // an exception will occur. AIPSPATH will in general be
00120 // read from the global environment variables, but can, before any other
00121 // <src>Aipsrc</src> related call, be set with the
00122 // <src>setAipsPath()</src> call.<br>
00123 // If AIPSPATH is not set in either way, it is set to the home directory.
00124 // <p>
00125 // The basic interaction with the class is with the static keyword match function
00126 // <srcblock>Bool Aipsrc::find(String &result, const String &keyword)
00127 // </srcblock>
00128 // A set of 
00129 // <srcblock>Bool AipsrcValue::find(Type &result, const String &keyword, ...)
00130 // </srcblock>
00131 // are available to interpret the string value found.
00132 // (see <linkto class="AipsrcValue">AipsrcValue</linkto>).<br>
00133 // All the <src>find</src>
00134 // functions have the ability to set a default if there is no match,
00135 // while also unit conversion is possible.<br>
00136 // The Bool return indicates if the keyword was found, and, in the case of the
00137 // interpretative finds, if an 'important' format error was found (e.g.
00138 // '+12a' will be accepted as a Double, with a result of '12', since the
00139 // standard double conversion in <src>>></src> will produce this result.) 
00140 // <note role=caution> The search keyword (unlike the file keyword) has no
00141 // wildcards. The real name should, of course, be looked for.</note>
00142 // To aid in other places, the following (static) methods are available
00143 // to get the requested information (derived from <src>HOME</src> and
00144 // <src>AIPSPATH</src>, computer system information and/or aipsrc keywords):
00145 //  <ul>
00146 //   <li> const String &Aipsrc::aipsRoot()
00147 //   <li> const String &Aipsrc::aipsArch()
00148 //   <li> const String &Aipsrc::aipsSite()
00149 //   <li> const String &Aipsrc::aipsHost()
00150 //   <li> const String &Aipsrc::aipsHome() -- <src>~/aips++</src>
00151 //  </ul>
00152 // Other, numeric, system information can be found in
00153 // <linkto class=AipsrcValue>AipsrcValue</linkto>.<br>
00154 //
00155 // Given an AIPSPATH of 
00156 // <srcblock>/epp/aips++ sun4sol_gnu epping norma</srcblock>
00157 // aipsSite will return
00158 // <srcblock>/epp/aips++/sun4sol_gnu/epping</srcblock>.
00159 //
00160 // The basic find above reacts with the aipsrc files available. If regular 
00161 // access is necessary (e.g. a lot of routines have to check independently a
00162 // certain integration time limit), keywords can be <em>registered</em> to
00163 // enable:
00164 // <ul>
00165 //   <li> fast access with integer code, rather than string
00166 //   <li> ability to set values from programs if no aipsrc information given
00167 //              (a dynamic default)
00168 //   <li> update the <src>$HOME/.aipsrc</src> keyword/value list with save() 
00169 // </ul>
00170 // <note role=tip> The registered value is never equal to zero, hence a zero
00171 // value can be used to check if registration is done. Also, registering the
00172 // same keyword twice is safe, and will produce the same value.</note>
00173 // When saving a keyword/value pair in <src>$HOME/.aipsrc</src>, the old
00174 // version is saved in <src>$HOME/.aipsrc.old</src>, before the keyword/value
00175 // pair is prepended to the file. A limited number of edits of the same keyword
00176 // is preserved only (default 5, changeable with the
00177 // <src>user.aipsrc.edit.keep</src> keyword.
00178 // </synopsis>
00179 //
00180 // <example>
00181 // <srcblock>
00182 //  String printerPage;         // result of keyword find
00183 //  if(!Aipsrc::find(printerPage, "printer.ps.page")) { // look for keyword match
00184 //    printerPage = "notSet";
00185 //  };
00186 // </srcblock>
00187 // A more convenient way of accomplishing the same result is:
00188 // <srcblock>
00189 //    Aipsrc::find(printerPage, "printer.ps.page", "notSet");
00190 // </srcblock>
00191 // Here the final argument is the default to use if the keyword is not found
00192 // at all.<br>
00193 // If you often want to know, dynamically, the current 'printer.ps.page'
00194 // value, you could do something like:
00195 // <srcblock>
00196 //      static uInt pp = Aipsrc::registerRC("printer.ps.page", "noSet");
00197 //      String printerPage = Aipsrc::get(pp);
00198 // // Processing, and maybe somewhere else:
00199 //      Aipsrc::set(pp, "nowSet");
00200 // // ...
00201 //      printerPage = Aipsrc::get(pp);
00202 // // and save it to the <src>$HOME/.aipsrc</src> list
00203 //      Aipsrc::save(pp);
00204 // </srcblock>
00205 // </example>
00206 //
00207 // <motivation>
00208 // Programs need a way to interact with the aipsrc files.
00209 // </motivation>
00210 //
00211 // <thrown>
00212 //    <li>AipsError if the environment variables HOME and/or AIPSPATH not set.
00213 // </thrown>
00214 //
00215 // <todo asof="1997/08/07">
00216 // </todo>
00217 
00218 class Aipsrc {
00219 
00220 public:
00221   //# Constructors
00222 
00223   //# Destructor
00224 
00225   //# Copy assignment
00226 
00227   //# Member functions
00228   // <thrown>
00229   // <li> AipsError if HOME environment variable not set
00230   // </thrown> 
00231   // The <src>find()</src> functions will, given a keyword, return the value
00232   // with a matched keyword found in the files. If no match found the
00233   // function will be False. The <src>findNoHome()</src> emulates the <src>-i</src>
00234   // switch of getrc by bypassing the <src>~/.aipsrc</src> file.
00235   // <group>
00236   static Bool find(String &value, const String &keyword);
00237   static Bool findNoHome(String &value, const String &keyword);
00238   // </group>
00239 
00240   // These finds check a (possible) value of the keyword against a list
00241   // of coded values provided, and return an index into the list (N if not
00242   // found). Matching is minimax, case insensitive. Always better to use
00243   // the one with default. return is False if no keyword or no match.
00244   // <group>
00245   static Bool find(uInt &value, const String &keyword,
00246                    Int Nname, const String tname[]);
00247   static Bool find(uInt &value, const String &keyword,
00248                    const Vector<String> &tname);
00249   // </group>
00250   // This find usually saves you some lines of code, since you can supply the
00251   // default you want to use when no such keyword is defined.
00252   // If the return value is False, the keyword was not found and the default
00253   // was used.
00254   // <group>
00255   static Bool find(String &value, const String &keyword, 
00256                    const String &deflt);
00257   static Bool findNoHome(String &value, const String &keyword,
00258                          const String &deflt);
00259   static Bool find(uInt &value, const String &keyword,
00260                    Int Nname, const String tname[], const String &deflt);
00261   static Bool find(uInt &value, const String &keyword,
00262                    const Vector<String> &tname, const String &deflt);
00263   // </group>
00264 
00265   // Sets foundDir to the first /firstPart/lastPart path that it finds
00266   // present on the system, where /firstPart comes from, in order,
00267   // this list:
00268   //   contents of prepends
00269   //   + useStd ? (., aipsHome(), aipsRoot()) : ()
00270   //   + contents of appends
00271   static Bool findDir(String& foundDir, const String& lastPart="",
00272                       const Vector<String>& prepends=Vector<String>(),
00273                       const Vector<String>& appends=Vector<String>(),
00274                       Bool useStds=True);
00275 
00276   // Functions to register keywords for later use in get() and set(). The
00277   // returned value is the index for get() and set().
00278   // <group>
00279   static uInt registerRC(const String &keyword,
00280                          const String &deflt);
00281   static uInt registerRC(const String &keyword,
00282                          Int Nname, const String tname[], const String &deflt);
00283   static uInt registerRC(const String &keyword,
00284                          const Vector<String> &tname, const String &deflt);
00285   // </group>
00286 
00287   // Gets are like find, but using registered integers rather than names.
00288   // <group>
00289   static const String &get(uInt keyword);
00290   // get for code
00291   static const uInt &get(uInt &code, uInt keyword);
00292   // </group>
00293 
00294   // Sets allow registered values to be set
00295   // <group>
00296   static void set(uInt keyword, const String &deflt);
00297   static void set(uInt keyword,
00298                   Int Nname, const String tname[], const String &deflt);
00299   static void set(uInt keyword,
00300                   const Vector<String> &tname, const String &deflt);
00301   // </group>
00302 
00303   // Save a registered keyword value to <src>$HOME/.aipsrc</src>
00304   // <group>
00305   static void save(uInt keyword);
00306   static void save(uInt keyword, const String tname[]);
00307   static void save(uInt keyword, const Vector<String> &tname);
00308   // </group>
00309 
00310   // Set an AIPSPATH that should be used in stead of a global AIPSPATH.
00311   // This call should be made before any Aipsrc related call. The AIPSPATH
00312   // will have up to 4 fields (which can all be empty) giving the root, host,
00313   // site and arch directory that will be searched for possible
00314   // <src>[.]aipsrc</src> files.
00315   static void setAipsPath(const String &path = String());
00316 
00317   // Returns the appropriate AIPS++ or system variable values
00318   // <group>
00319   static const String &aipsRoot();
00320   static const String &aipsArch();
00321   static const String &aipsSite();
00322   static const String &aipsHost();
00323   // Returns: <src>~/aips++</src>
00324   static const String &aipsHome();
00325   // </group>
00326   
00327   // The <src>reRead()</src> function, will reinitialise the static maps and read the
00328   // aipsrc files again. It could be useful in some interactive or multi-processor 
00329   // circumstances. <src>lastRead()</src> returns the time last reRead.
00330   // <group>
00331   static void reRead();
00332   static Double lastRead();
00333   // </group>
00334   
00335 
00336   // The following functions return the full lists of available data. They could
00337   // be useful for debugging purposes.
00338   // <group>
00339   static const Block<String> &values();
00340   static const Block<String> &patterns();
00341   // </group>
00342   
00343   // The following <src>show()</src> function, useful for debugging, outputs 
00344   // all keyword/value pairs found
00345   static void show(ostream &oStream);
00346   // Prints all info on cout
00347   static void show();
00348   // The following set is a general set of functions
00349   // <group>
00350   // Read aipsrc type files (without wildcards), and return the unique names
00351   // and values in the Vector arguments. The return value is number of names.
00352   static uInt genRestore(Vector<String> &namlst, Vector<String> &vallst,
00353                     const String &fileList);
00354   // Save the names/values in file
00355   static void genSave(Vector<String> &namlst, Vector<String> &vallst,
00356                       const String &fnam);
00357   // Set (new or overwrite) keyword/value pair
00358   static void genSet(Vector<String> &namlst, Vector<String> &vallst,
00359                      const String &nam, const String &val);
00360   // Remove a keyword from list (False if not in list)
00361   static Bool genUnSet(Vector<String> &namlst, Vector<String> &vallst,
00362                        const String &nam);
00363   // Get the value of a keyword
00364   static Bool genGet(String &val, Vector<String> &namlst, Vector<String> &vallst,
00365                      const String &nam);
00366   // </group>
00367 
00368 protected:
00369   // Actual find function
00370   static Bool find(String &value, const String &keyword,
00371                    uInt start);
00372   // The registration function
00373   static uInt registerRC(const String &keyword, Block<String> &nlst);
00374   // Actual saving
00375   static void save(const String keyword, const String val);
00376   
00377 private:
00378   //# Data
00379   static Mutex theirMutex;
00380   // Indicate files read
00381   static volatile Bool doInit;
00382   // Last time data was (re)read
00383   static Double lastParse; 
00384   // List of values belonging to keywords found
00385   static Block<String> keywordValue;
00386   // List of patterns deducted from names
00387   static Block<String> keywordPattern;
00388   // The start of the non-home values
00389   static uInt fileEnd;
00390   // The possibly set external AIPSPATH
00391   static String extAipsPath;
00392   // AIPSROOT
00393   static String root;
00394   // AIPSARCH
00395   static String arch;
00396   // AIPSSITE
00397   static String site;
00398   // AIPSHOST
00399   static String host;
00400   // AIPSHOME
00401   static String home;
00402   // HOME
00403   static String uhome;
00404   // Indicate above filled
00405   static Bool filled;
00406   // String register list
00407   // <group>
00408   static Block<String> strlst;
00409   static Block<String> nstrlst;
00410   static Block<uInt> codlst;
00411   static Block<String> ncodlst;
00412   // </group>
00413 
00414   //# General member functions
00415   // Read in the aipsrc files, returning the number of lines found
00416   // <group>
00417   static void parse(Bool force=False);
00418   static void doParse(String &fileList);
00419   // </group>
00420   
00421   // The following parse function can be used for any list of files. It will
00422   // return the list of Patterns and values found, and the last keyword number
00423   // of first file in list.
00424   static uInt genParse(Block<String> &keywordPattern, 
00425                        Block<String> &keywordValue,
00426                        uInt &fileEnd, const String &fileList);
00427 
00428   // Locate the right keyword in the static maps
00429   static Bool matchKeyword(uInt &where, const String &keyword,
00430                            uInt start);
00431   // Fill in root, arch, site, host and home, and return requested nam
00432   static const String &fillAips(const String &nam);
00433 };
00434 
00435 
00436 } //# NAMESPACE CASA - END
00437 
00438 #endif
00439 
00440