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 }