00001 // Copyright (C) 2001, Compaq Computer Corporation 00002 // 00003 // This file is part of Vesta. 00004 // 00005 // Vesta is free software; you can redistribute it and/or 00006 // modify it under the terms of the GNU Lesser General Public 00007 // License as published by the Free Software Foundation; either 00008 // version 2.1 of the License, or (at your option) any later version. 00009 // 00010 // Vesta is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 // Lesser General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU Lesser General Public 00016 // License along with Vesta; if not, write to the Free Software 00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00018 00019 // Created on Mon Jul 14 10:38:04 PDT 1997 by heydon 00020 00021 // ParseImports.H -- function for parsing a model's imports 00022 00023 #ifndef _PARSE_IMPORTS_H 00024 #define _PARSE_IMPORTS_H 00025 00026 #include <Basics.H> 00027 #include <FS.H> 00028 #include <Sequence.H> 00029 #include <Generics.H> 00030 #include <SRPC.H> 00031 00032 typedef TextSeq ImportID; 00033 00034 class Import { 00035 public: 00036 Text path; 00037 Text orig; 00038 ImportID id; 00039 int start, end; 00040 bool local; 00041 bool fromForm; 00042 bool noUpdate; 00043 Import(const Text &path, const Text &orig, const ImportID &id, int start, int end, 00044 bool local, bool fromForm=false, bool noUpdate=false) throw () 00045 : path(path), orig(orig), id(id), start(start), end(end), local(local), 00046 fromForm(fromForm), noUpdate(noUpdate) { /*SKIP*/ } 00047 Import(const Import &other) 00048 : path(other.path), orig(other.orig), id(other.id), start(other.start), end(other.end), 00049 local(other.local), fromForm(other.fromForm), noUpdate(other.noUpdate) 00050 { /*SKIP*/ } 00051 }; 00052 00053 /* An "Import" represents the importation of a model "m'" by a model "m". 00054 If "i: Import", then "i.path" is the full, absolute pathname of the 00055 imported model "m'", "i.orig" is the portion of "m" denoting the 00056 importation of "m'", [ "i.start", "i.end" ) is the half-open interval 00057 of zero-based character positions in the model "m" bounding the text 00058 "i.orig" of the imported model, "local" is true iff the model is named by 00059 a relative path, "fromForm" is true if and only if the imported model 00060 is named in a "from ... import" clause, and "noUpdate" is true if and 00061 only if the model specification "i.orig" was immediately preceeded by 00062 a "noupdate" or "NOUPDATE" pragma in the input. 00063 00064 If "!(i.fromForm)", then "i.orig" and "i.path" will be nearly identical, 00065 with two exceptions: 1) if "i.orig" is relative, then the model's directory 00066 has been prepended to "i.path", and 2) the "ResolvePath" function (see 00067 below) is applied to the resulting path. 00068 00069 If "i.fromForm", then the complete path is actually expressed in two 00070 parts: the one appearing after "from" but before "import", and the one 00071 appearing after "import". "i.orig" is set to the latter part of the path, 00072 while "i.path" is the result of applying the "ResolvePath" function below 00073 to the concatenation of the two parts (as above, the model's directory is 00074 prepended to the first part if it is relative). In this case, "i.start" 00075 and "i.end" bound the positions of the latter part of the path (the 00076 portion of the model "m" to which "i.orig" is set). */ 00077 00078 // a sequence of pointers to "Import" objects 00079 typedef Sequence<Import*> ImportSeq; 00080 00081 namespace ParseImports { 00082 // parsing error 00083 class Error { 00084 public: 00085 Error(const Text &msg) throw () : msg(msg) { /*SKIP*/ } 00086 Text const msg; // error message 00087 }; 00088 00089 class ModelSpace { 00090 // Space of files that can be opened for reading, with a limited 00091 // set of operations. Clients can subclass this interface and 00092 // pass an object of the appropriate type in to the P method. 00093 public: 00094 // Operations on files 00095 virtual char getC() throw (Error, FS::EndOfFile, SRPC::failure) = 0; 00096 virtual void ungetC(char c) throw () = 0; // limited to 1 character 00097 virtual long tell() throw () = 0; 00098 00099 // Create an object with no file associated; use one of these 00100 // as the argument to P below. The getc, ungetc, and tell 00101 // methods will not be called on it. 00102 ModelSpace() { }; 00103 00104 // Open a model file in the space. All the methods may be 00105 // used on it, including open() itself. The open method does 00106 // not use the object, but it cannot be static because it is 00107 // virtual; that is, we need an object to know which subclass 00108 // to take the method from. 00109 virtual ModelSpace* open(const Text &modelname) const 00110 throw(Error, FS::Failure, SRPC::failure, FS::DoesNotExist) = 0; 00111 00112 // Is name a file, directory, or neither? 00113 enum type { file, directory, none }; 00114 virtual type getType(const Text &name) const 00115 throw (Error, FS::Failure, SRPC::failure) = 0; 00116 00117 // Close the associated file, if any 00118 virtual ~ModelSpace() { }; 00119 }; 00120 00121 // 00122 // Default ModelSpace implementation using local file system 00123 // 00124 class LocalModelSpace : public ModelSpace 00125 { 00126 public: 00127 char getC() throw (ParseImports::Error, FS::EndOfFile); 00128 inline void ungetC(char c) throw () { ifs.putback(c); }; 00129 inline long tell() throw () { return ifs.tellg(); }; 00130 LocalModelSpace() throw() { } 00131 ParseImports::ModelSpace* open(const Text &modelname) const 00132 throw(ParseImports::Error, FS::Failure, FS::DoesNotExist); 00133 type getType(const Text &name) const throw (); 00134 LocalModelSpace(const Text &modelname) throw(FS::Failure, FS::DoesNotExist); 00135 ~LocalModelSpace() { FS::Close(ifs); }; 00136 private: 00137 std::ifstream ifs; 00138 }; 00139 00140 void P(const Text &modelname, /*INOUT*/ ImportSeq &seq, 00141 const ModelSpace* ms =NULL) 00142 throw(FS::DoesNotExist, FS::Failure, Error, SRPC::failure); 00143 /* Read the imports in the model named by the absolute pathname 00144 "modelname", and append new "Import" objects corresponding to any 00145 such models to "seq". The ModelSpace is used to look up the 00146 model name; if none is provided, the local file system is used. */ 00147 00148 Text ResolvePath(const Text &path, const Text &wd, 00149 const ModelSpace* ms =NULL) 00150 throw(Error, FS::Failure, SRPC::failure); 00151 /* Remove any double-quote characters from "path". If "path" is relative, 00152 prepend the working directory "wd", which is expected to end in '/'. 00153 Finally, if the resulting path is a directory, append "build.ves"; 00154 otherwise, if the resulting path does not end in ".ves", append that 00155 extension. Return the resulting path. */ 00156 } 00157 00158 std::ostream& operator<<(std::ostream &os, const ParseImports::Error &err) 00159 throw (); 00160 00161 #endif // _PARSE_IMPORTS_H