00001 #ifndef __MACRO__ 00002 #define __MACRO__ 00003 00004 #include "common/MString.h" 00005 #include <string.h> 00006 #include "macroBase.h" 00007 00008 // A macro exapnder 00009 // 00010 // 00011 // A Note on object_type_name 00012 // 00013 // This is now overridden to provide a domain specific identifer. The default is 00014 // still the object ClassName, but it is overridden, for example, in the parser, to 00015 // give the name of the production that created the object 00016 // 00017 // The old functionality is now given by get_instance_class_name 00018 00019 00020 // Implementation of the simple case of a list of MacroObjects 00021 00022 class MacroListObject : public AbstractMacroListObject 00023 { 00024 static const LString ClassName; 00025 ref_stack<MacroObjectPtr > list; 00026 bool owns_contents; 00027 bool _performing_cleanup; 00028 00029 LString type_name; 00030 00031 00032 public: 00033 00034 MacroListObject(bool owner = false) : owns_contents(owner),_performing_cleanup(false) {} 00035 MacroListObject(const MacroListObject &obj) : list(obj.list),owns_contents(obj.owns_contents),_performing_cleanup(false) {} 00036 00037 void AddObject(MacroObjectPtr object); 00038 00039 MacroObjectPtr get_item(int i) const {return list[i];} 00040 00041 virtual ~MacroListObject(); 00042 00043 virtual void Print(int indent = 0) const; 00044 00045 virtual int length() const {return list.len();} 00046 00047 virtual LString get_instance_class_name() const {return ClassName;} 00048 virtual LString object_type_name() const {return type_name;} 00049 void set_type_name(const LString &type) {type_name = type;} 00050 static const LString & get_ClassName() {return ClassName;} 00051 virtual bool isKindOf( const LString &kind ) const 00052 { return ((kind == ClassName) || AbstractMacroListObject::isKindOf(kind)); 00053 } 00054 00055 virtual void CutBack(int new_top_pos) { 00056 list.cut(new_top_pos); 00057 } 00058 00059 MacroIterPtr get_iter() {return MacroIterPtr(new simple_stack_MacroIter<MacroObjectPtr >(list));} 00060 00061 void reset() {list.reset();} 00062 00063 void AddObjectList(const AbstractMacroListObject &x); 00064 00065 void perform_final_cleanup(); 00066 00067 }; 00068 00069 MacroListObject * to_MacroListObject(MacroObjectPtr ); 00070 00071 00072 00073 // Only one parameter gets passed in. This has no name. To pass in real parameters, 00074 // you generally want to pass an instance of the following class. The top level name resolution 00075 // will then be done in the class object 00076 00077 typedef DerivedRCPointer<MacroListObject,MacroObjectPtr> MacroListObjectPtr; 00078 00079 class NamedList : public AbstractNamedList 00080 { 00081 simple_stack<LString> names; 00082 MacroListObjectPtr list; 00083 static const LString ClassName; 00084 LString type_name; 00085 public: 00086 00087 NamedList(bool owner = false) : list(new MacroListObject(owner)) {} 00088 00089 virtual void Print(int indent = 0) const; 00090 00091 void set_type_name(const LString &type) {type_name = type;} 00092 virtual LString object_type_name() const {return type_name;} 00093 virtual LString get_instance_class_name() const {return ClassName;} 00094 static const LString & get_ClassName() {return ClassName;} 00095 virtual bool isKindOf( const LString &kind ) const 00096 { return ((kind == ClassName) || AbstractNamedList::isKindOf(kind)); 00097 } 00098 00099 00100 virtual void AddObject(const LString &name, MacroObjectPtr object) 00101 { 00102 list->AddObject(object); 00103 names.push(name); 00104 } 00105 00106 virtual int length() const {return list->length();} 00107 00108 virtual void CutBack(int new_len) 00109 { 00110 while (names.len() > new_len) 00111 names.pop(); 00112 list->CutBack(new_len); 00113 } 00114 00115 MacroIterPtr get_iter() {return new SingleMacroIter(this);} 00116 00117 MacroObjectPtr get_item(int i) const {return list->get_item(i);} 00118 00119 MacroObjectPtr get_child(const LString &name) const; 00120 00121 virtual String child_name_list() const; 00122 00123 MacroObjectPtr get_as_list() {return list;} 00124 00125 void perform_final_cleanup() { 00126 list->perform_final_cleanup(); 00127 } 00128 }; 00129 00130 typedef DerivedRCPointer<NamedList,MacroObjectPtr> NamedListPtr; 00131 00132 00133 NamedList * to_NamedList(MacroObjectPtr ); 00134 00135 // Implementation of the simple string valued macro object 00136 00137 00138 class StringMacroObject : public AbstractStringMacroObject 00139 { 00140 String text; 00141 static const LString ClassName; 00142 LString type_name; 00143 00144 public: 00145 StringMacroObject(String s) : text(s) {} 00146 00147 void set_text(const String &the_text) {text = the_text;} 00148 00149 const String get_text() const {return text;} 00150 00151 MacroIterPtr get_iter() {return new SingleMacroIter(this);} 00152 00153 virtual LString object_type_name() const {return type_name;} 00154 void set_type_name(const LString &type) {type_name = type;} 00155 virtual LString get_instance_class_name() const {return ClassName;} 00156 static const LString & get_ClassName() {return ClassName;} 00157 virtual bool isKindOf( const LString &kind ) const 00158 { return ((kind == ClassName) || AbstractStringMacroObject::isKindOf(kind)); 00159 } 00160 00161 }; 00162 00163 StringMacroObject* to_StringMacroObject(MacroObjectPtr ); 00164 00165 00166 00167 class MacroDef; 00168 00169 class parameter; 00170 00171 class foreach_stack_entry; 00172 00173 class OutputFile; 00174 00175 00176 00177 // MacroExpansion is the class that performs the macro expansion. The expanded text is 00178 // returned as a set of "files". Each file has a name and a body of text. Either of these 00179 // may be empty - in particular the name of the first (index 0) file is always empty. This 00180 // is the default output file. 00181 00182 class Breakpoint 00183 { 00184 public: 00185 int lineno; 00186 const char *text; // position in text of breakpoint 00187 int filenbr; // non zero if stop when file a given no of lines 00188 Breakpoint(int line,const char *t) 00189 : lineno(line),text(t),filenbr(0) {} 00190 Breakpoint() 00191 : lineno(0),text(NULL),filenbr(0) {} 00192 Breakpoint(int line,int file) 00193 : lineno(line),filenbr(file) {} 00194 }; 00195 00196 class MacroExpansion 00197 { 00198 simple_stack <MacroDef *>macro_defs; 00199 00200 simple_stack<OutputFile *> files; 00201 simple_stack<foreach_stack_entry *> foreach_stack; 00202 bool expanded; 00203 00204 00205 simple_stack<const char *> filename_positions; 00206 simple_stack<const char *> start_positions; 00207 simple_stack<const char *> saved_positions; 00208 00209 simple_stack<MacroDef *>macro_calls; 00210 00211 MacroObjectPtr par; 00212 00213 const char *text; // current position in text 00214 const char *filename; // current filename in text 00215 const char * start; // start of text being processed 00216 int text_len; 00217 00218 bool is_in_range(const char *text); 00219 00220 bool expand_macro(String name); 00221 00222 void expand_inner(const char *filename, const char *text); 00223 00224 void error_message(const char *message,bool use_stdout = false); 00225 00226 bool skip_keyword(const char * keyword,const char *error_msg); 00227 00228 MacroObjectPtr get_named_object(const LString &name, bool diagnose, MacroObjectPtr add_object); 00229 00230 MacroObjectPtr get_named_object(bool diagnose, MacroObjectPtr add_object); 00231 00232 parameter condition_true(); 00233 00234 void skip_brackets(char left,char right); 00235 00236 String get_expanded_value(const char *start,int len); 00237 00238 foreach_stack_entry *get_foreach_object(const LString &name); 00239 00240 void process_foreach_clause(); 00241 00242 void process_let(); 00243 00244 bool skipping_white_space; 00245 00246 void select_file(const String &x); 00247 void parse_file(const String &name); 00248 00249 simple_stack<Breakpoint> breakpoints; 00250 00251 simple_stack<String> include_dirs; 00252 00253 void pop_foreach_stack(); 00254 00255 bool debug_it; 00256 String last_command; 00257 bool step; 00258 bool step_over; 00259 00260 const char * normalize_pos(const char *text); 00261 00262 bool define_name(const char *par_name); 00263 00264 class source_files { 00265 String name; 00266 const char *start; 00267 const char *end; 00268 public: 00269 const String &get_name() {return name;} 00270 const char *get_text() {return start;} 00271 bool is_in(const char *c) {return ((c >= start) && (c < end));} 00272 source_files(const String &n,const char *t) : name(n),start(t),end(t + strlen(t)) {} 00273 }; 00274 00275 simple_stack <source_files *> sources; 00276 00277 int find_name(const LString &name); 00278 void add_macro(MacroDef *def); 00279 MacroDef *resolve_macro(const LString &name, 00280 simple_stack<foreach_stack_entry *>&pars,int par_offset,int par_len); 00281 void reset(); 00282 00283 00284 public: 00285 MacroExpansion(int start=100,int expand=100); 00286 virtual ~MacroExpansion(); 00287 bool is_expanded() {return expanded;} 00288 00289 // Note that there is exactly one parameter. See NamedPars above. 00290 00291 // Expand will expand the given text and return the text as output. Note that no 00292 // initialization is done by expand. Hence, any defs you already had from a previous 00293 // call are still present and, in addition, the text previously expanded is still 00294 // present, so the new expansion will be appended to the old 00295 // 00296 // (The reset_defs and reset_text routines clear these) 00297 00298 void Expand(const char *filename, const char *text,MacroObjectPtr param); 00299 00300 // The following two virtual functions can be overridden to 00301 // expand body text and parameter text respectively. This allows 00302 // differeing translation to be supported 00303 // 00304 // The implementations in this routine just copy characters 00305 // You can also use the push routine inherited from simple_stack to 00306 // push single characters 00307 00308 virtual void push_body_text(const char *text,int len); 00309 virtual void push_par_text(const char *text); 00310 00311 // Execute a command ("function") on the text 00312 // 00313 // commands take the form <!<command> <parameter_name> <extra text> 00314 // 00315 // this version can handle the following commands (calling push_par_text to push output) 00316 // !' enclose parameter in single quotes 00317 // !" enclose in double quotes 00318 // !CAPS output in all caps 00319 // !LOWS output in all lower case 00320 // !CPZ capitalizes text. First character is captalized. Underlines are removed and the 00321 // next character is capitalized 00322 // !UNL lower cases text and puts an underline in front of capitals 00323 // !POS position in iterator (number) 00324 // 00325 // 00326 // 00327 // NB = the shriek (!) is not passed as part of the command. It is used to invoke the command 00328 virtual void push_par_text_command(String command,const MacroObjectPtr p,String extras); 00329 00330 // Clear the macro definitions 00331 00332 // Clear the text 00333 00334 void reset_text(); 00335 00336 void inherit_pars(MacroExpansion &y); 00337 00338 // These routines retrieve the actual bodies of text. 00339 // The first file is always nameless and is the default output device 00340 int file_count() {return files.len();} 00341 00342 const String & get_file_name(int i); 00343 String get_file_text(int i); 00344 00345 // set flag that this needs debugging 00346 00347 void set_debug(bool d) {debug_it = d;} 00348 00349 void add_break(int lineno); 00350 void show_breaks(); 00351 void delete_break(int no); 00352 void clear_breaks(); 00353 00354 bool get_at_breakpoint(); 00355 void set_at_breakpoint(bool b); 00356 void get_lineno(const char *text,int &line_no,int &file_no); 00357 void show_pos(const char *text); 00358 void print_lines(const char *start,int from,int to); 00359 00360 void process_debug_commands(); 00361 00362 void add_include(const String &x) 00363 { 00364 include_dirs.push(x); 00365 } 00366 00367 virtual int derivation_distance(const LString &required,const MacroObjectPtr found); 00368 }; 00369 00370 void print_indent(int indent); 00371 00372 void print_start(int indent,const char *type,const char * dynamic_type); 00373 00374 void print_end(int indent); 00375 00376 #endif