Mercurial > ~dholland > hg > ag > index.cgi
comparison examples/mpp/mpp.cpp @ 0:13d2b8934445
Import AnaGram (near-)release tree into Mercurial.
author | David A. Holland |
---|---|
date | Sat, 22 Dec 2007 17:52:45 -0500 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:13d2b8934445 |
---|---|
1 /* | |
2 * AnaGram, a System for Syntax Directed Programming | |
3 * C Macro preprocessor | |
4 * Global Data and Main Program | |
5 * | |
6 * Copyright 1993-2000 Parsifal Software. All Rights Reserved. | |
7 * | |
8 * This software is provided 'as-is', without any express or implied | |
9 * warranty. In no event will the authors be held liable for any damages | |
10 * arising from the use of this software. | |
11 * | |
12 * Permission is granted to anyone to use this software for any purpose, | |
13 * including commercial applications, and to alter it and redistribute it | |
14 * freely, subject to the following restrictions: | |
15 * | |
16 * 1. The origin of this software must not be misrepresented; you must not | |
17 * claim that you wrote the original software. If you use this software | |
18 * in a product, an acknowledgment in the product documentation would be | |
19 * appreciated but is not required. | |
20 * 2. Altered source versions must be plainly marked as such, and must not be | |
21 * misrepresented as being the original software. | |
22 * 3. This notice may not be removed or altered from any source distribution. | |
23 */ | |
24 | |
25 // for out of date compilers | |
26 #if defined(__IBMCPP__) | |
27 #define OLDCPLUSPLUS | |
28 #endif | |
29 | |
30 #include "mpp.h" | |
31 #include <stdlib.h> | |
32 #include <ctype.h> | |
33 | |
34 #ifdef OLDCPLUSPLUS | |
35 #include <new.h> | |
36 #else | |
37 #include <new> | |
38 #endif | |
39 | |
40 #include "array.h" // \ANAGRAM\CLASSLIB\INCLUDE\ARRAY.H | |
41 #include "util.h" // \ANAGRAM\CLASSLIB\INCLUDE\UTIL.H | |
42 | |
43 | |
44 // Global data definitions | |
45 | |
46 expression_evaluator condition; | |
47 unsigned defined_value; | |
48 int if_clause = 0; | |
49 char default_path[] = ""; //default include file path, if desired | |
50 macro_descriptor macro[N_MACROS]; | |
51 unsigned macro_id[N_SYMBOLS] = {0}; | |
52 int n_macros = 0; | |
53 unsigned n_reserved_words = 0; | |
54 int nest_comments = 0; | |
55 unsigned one_value; | |
56 stack<char *> paths(20,1); | |
57 string_accumulator sa(1000,20); | |
58 token_sink *scanner_sink; | |
59 token_accumulator ta(1000,20); | |
60 string_dictionary td(N_SYMBOLS); | |
61 unsigned token_handles[256]; | |
62 unsigned zero_value; | |
63 | |
64 | |
65 // Initialization data | |
66 | |
67 op_descriptor ops[] = { | |
68 {"&&" , ANDAND}, | |
69 {"&=" , ANDassign}, | |
70 {"->" , ARROW}, | |
71 {"##" , CONCAT}, | |
72 {"--" , DECR}, | |
73 {"/=" , DIVassign}, | |
74 {"..." , ELLIPSIS}, | |
75 {"==" , EQ}, | |
76 {"^=" , ERassign}, | |
77 {">=" , GE}, | |
78 {"++" , ICR}, | |
79 {"<=" , LE}, | |
80 {"<<" , LS}, | |
81 {"<<=" , LSassign}, | |
82 {"%=" , MODassign}, | |
83 {"-=" , MINUSassign}, | |
84 {"*=" , MULTassign}, | |
85 {"!=" , NE}, | |
86 {"|=" , ORassign}, | |
87 {"||" , OROR}, | |
88 {"+=" , PLUSassign}, | |
89 {">>" , RS}, | |
90 {">>=" , RSassign}, | |
91 {" " , SPACE}, | |
92 }; | |
93 | |
94 op_descriptor reserved_words[] = { | |
95 {NULL, END_OF_FILE }, | |
96 {"auto", AUTO }, | |
97 {"break", BREAK }, | |
98 {"case", CASE }, | |
99 {"char", CHAR }, | |
100 {"const", CONSTANT }, | |
101 {"continue", CONTINUE }, | |
102 {"default", DEFAULT }, | |
103 {"do", DO }, | |
104 {"double", DOUBLE }, | |
105 {"else", ELSE }, | |
106 {"enum", ENUM }, | |
107 {"extern", EXTERN }, | |
108 {"float", FLOAT }, | |
109 {"for", FOR }, | |
110 {"goto", GOTO }, | |
111 {"if", IF }, | |
112 {"int", INT }, | |
113 {"long", LONG }, | |
114 {"register", REGISTER }, | |
115 {"return", RETURN }, | |
116 {"short", SHORT }, | |
117 {"signed", SIGNED }, | |
118 {"sizeof", SIZEOF }, | |
119 {"static", STATIC }, | |
120 {"struct", STRUCT }, | |
121 {"switch", SWITCH }, | |
122 {"typedef", TYPEDEF }, | |
123 {"union", UNION }, | |
124 {"unsigned", UNSIGNED }, | |
125 {"void", VOIDkey }, | |
126 {"volatile", VOLATILE }, | |
127 {"while", WHILE }, | |
128 }; | |
129 | |
130 | |
131 // Data initializer | |
132 | |
133 static void init_data(void) { | |
134 unsigned k; | |
135 | |
136 memset(token_handles, 0, 256*sizeof(unsigned)); | |
137 | |
138 n_reserved_words = sizeof(reserved_words) / sizeof(op_descriptor); | |
139 | |
140 assert(size(td) == 0); | |
141 | |
142 for (k = 1; k < n_reserved_words; k++) { | |
143 unsigned index = td << reserved_words[k].op; | |
144 token_handles[reserved_words[k].id] = index; | |
145 assert(index == k); | |
146 } | |
147 | |
148 k = sizeof(ops) / sizeof(op_descriptor); | |
149 while (k--) token_handles[ops[k].id] = td << ops[k].op; | |
150 | |
151 for (k = 1; k < 127; k++) { | |
152 if (token_handles[k] || isalnum(k)) continue; | |
153 token_handles[k] = td << (char *) &k; | |
154 } | |
155 | |
156 defined_value = td << "defined"; | |
157 one_value = td << "1"; | |
158 zero_value = td << "0"; | |
159 } | |
160 | |
161 | |
162 // Field memory allocation failures | |
163 | |
164 #if defined(OLDCPLUSPLUS) && defined(_MSC_VER) | |
165 // Cope with peculiarity of MSVC++ | |
166 // (probably not needed any more - someone with a recent MSVC please advise) | |
167 static int out_of_space(size_t) { | |
168 printf("\nOut of space\n"); | |
169 exit(1); | |
170 // Cookie for the cookie monster | |
171 return 0; | |
172 } | |
173 #else | |
174 static void out_of_space(void) { | |
175 printf("\nOut of space\n"); | |
176 exit(1); | |
177 } | |
178 #endif | |
179 | |
180 // Extract and directory names from path statement | |
181 | |
182 static void extract_paths(const char *path_string) { | |
183 if (path_string == NULL) return; // exit if no default paths | |
184 ++sa << path_string; // temporary copy of path string | |
185 char *p = sa.top(); // init scan pointer | |
186 char *q = strrchr(p,';'); // look for rightmost semi-colon | |
187 while (q != NULL) { | |
188 *q++ = 0; // replace it with null | |
189 while (*q == ' ') q++; // skip over blanks | |
190 paths << memdup(q, 1+strlen(q)); // stack copy | |
191 q = strrchr(p, ';'); | |
192 } | |
193 while (*p == ' ') p++; // get rid of blanks | |
194 paths << memdup(p, 1+strlen(p)); // stack last path | |
195 --sa; | |
196 } | |
197 | |
198 | |
199 // Main Program | |
200 | |
201 int main(int argc, char *argv[]) { | |
202 int i; // for indexing args | |
203 c_parser cp; // initialize c parser | |
204 char *inpath = NULL; // input file name | |
205 char *outpath = NULL; // output file name | |
206 | |
207 #if defined(OLDCPLUSPLUS) | |
208 #ifdef _MSC_VER //Cope with peculiarity of MSVC++ | |
209 _set_new_handler(out_of_space); // field allocation errors | |
210 #else | |
211 set_new_handler(out_of_space); // field allocation errors | |
212 #endif | |
213 #else /* current standard C++ dialect */ | |
214 std::set_new_handler(out_of_space); // field allocation errors | |
215 #endif | |
216 init_data(); // initialize data | |
217 | |
218 extract_paths(default_path); // get default include directories | |
219 | |
220 for (i = 1; i < argc; i++) { | |
221 switch (*argv[i]) { | |
222 case '-': | |
223 case '/': | |
224 switch (argv[i][1]) { | |
225 case 'c': | |
226 scanner_sink = &cp; // output to c parser | |
227 break; | |
228 case 'n': | |
229 nest_comments = 1; // accept nested comments | |
230 break; | |
231 case 'i': | |
232 extract_paths(argv[i] + 2); // include path | |
233 break; | |
234 default: | |
235 printf("Unrecognized switch: %c\n", argv[i][1]); | |
236 } | |
237 continue; | |
238 } | |
239 break; | |
240 } | |
241 | |
242 extract_paths("./"); // add local directory to include paths | |
243 | |
244 assert(i < argc); // there always has to be an input | |
245 inpath = argv[i++]; | |
246 | |
247 if (i < argc) outpath = argv[i++]; // output file specified? | |
248 else outpath = NULL; | |
249 | |
250 output_file file(outpath); // open output file | |
251 token_translator tt(&file); // set up translator | |
252 | |
253 if (scanner_sink == NULL) // if compiler not selected | |
254 scanner_sink = &tt; // output to token translator | |
255 | |
256 scan_input(inpath); // do it! (see TS.SYN) | |
257 return 0; | |
258 } |