Mercurial > ~dholland > hg > ag > index.cgi
comparison anagram/agcore/bpu.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 * Copyright 1993-1999 Parsifal Software. All Rights Reserved. | |
4 * See the file COPYING for license and usage terms. | |
5 * | |
6 * bpu.cpp - Utility routines for bpe3 | |
7 */ | |
8 | |
9 #include <ctype.h> | |
10 #include <stdarg.h> | |
11 #include "port.h" | |
12 | |
13 #include "arrays.h" | |
14 #include "bpe3.h" | |
15 #include "bpu.h" | |
16 #include "cd.h" | |
17 #include "data.h" | |
18 #include "dict.h" | |
19 #include "engdef.h" | |
20 #include "keyword.h" | |
21 #include "myalloc.h" | |
22 #include "q1glbl.h" | |
23 #include "rule.h" | |
24 #include "stacks.h" | |
25 #include "symbol.h" | |
26 #include "token.h" | |
27 | |
28 //#define INCLUDE_LOGGING | |
29 #include "log.h" | |
30 | |
31 | |
32 void template_string(const char *name, const char *tp, const char tc) { | |
33 ics(); | |
34 while (*tp) { | |
35 char c = *tp++; | |
36 if (c == tc) { | |
37 ass(name); | |
38 continue; | |
39 } | |
40 acs(c); | |
41 } | |
42 tss(); | |
43 } | |
44 | |
45 AgString subs_template(const char *name, const char *tp, const char tc) { | |
46 template_string(name, tp, tc); | |
47 return buildAgString(); | |
48 } | |
49 | |
50 unsigned find_token_number(const char *name) { | |
51 return Symbol(name)->token_number; | |
52 //return map_token_name[identify_string(name,tkn_dict)].token_number; | |
53 } | |
54 | |
55 int find_completions(int s, const unsigned **q) { | |
56 state_number_map *sp = &map_state_number[s]; | |
57 const unsigned *p = lstptr(*sp, chain_completions); | |
58 int n = sp->n_chain_completions; | |
59 if (n == 0 && sp->chain_gotos_index == 0) { | |
60 p = lstptr(*sp, completions); | |
61 n = sp->n_completions; | |
62 } | |
63 *q = p; | |
64 return n; | |
65 } | |
66 | |
67 void select_actions(int k) { | |
68 int n = tis()/3; | |
69 int *lb; | |
70 | |
71 list_space(n+1); | |
72 lb = list_base; | |
73 iws(); | |
74 while (n--) { | |
75 aws(lb[k]); | |
76 k += 3; | |
77 } | |
78 } | |
79 | |
80 void find_key_tokens(const int *pl, int n, int tw /*, int ct */) { | |
81 LOGSECTION("find_key_tokens"); | |
82 LOGV(n); | |
83 for (; n--; pl += tw) { | |
84 //int tn = *pl; | |
85 Token token = *pl; | |
86 LOGV(token); | |
87 //if (map_token_number[tn].key == 0) continue; | |
88 //if (token->key == 0) continue; | |
89 if (token->key.isNull()) { | |
90 continue; | |
91 } | |
92 isws(token); | |
93 } | |
94 } | |
95 | |
96 | |
97 /* | |
98 * Note that the text of the defined format must not contain a newline. | |
99 * Failure to abide by this rule will cause the line count to be | |
100 * incorrect. | |
101 */ | |
102 | |
103 void define_macro(const char *n, const char *fmt, ...) { | |
104 va_list ap; | |
105 fprintf(pe_file, "#define %s ", n); | |
106 va_start(ap, fmt); | |
107 vfprintf(pe_file, fmt, ap); | |
108 va_end(ap); | |
109 fputc('\n', pe_file); | |
110 pe_line_count++; | |
111 } | |
112 | |
113 void define_macro_default(const char *n, const char *fmt, ...) { | |
114 va_list ap; | |
115 char name_only[80]; | |
116 char *ptr; | |
117 | |
118 strcpy(name_only, n); | |
119 ptr = strchr(name_only, '('); | |
120 | |
121 if (ptr != NULL) { | |
122 *ptr = 0; | |
123 } | |
124 | |
125 fprintf(pe_file, "#ifndef %s\n#define %s ", name_only, n); | |
126 va_start(ap, fmt); | |
127 vfprintf(pe_file, fmt, ap); | |
128 va_end(ap); | |
129 fprintf(pe_file, "\n#endif\n"); | |
130 pe_line_count += 3; | |
131 } | |
132 | |
133 unsigned char *key_string(int tn) { | |
134 LOGSECTION("key_string"); | |
135 Keyword key = map_token_number[tn].key; | |
136 LOGV(tn) LCV(key) LCV(Keyword::count()); | |
137 | |
138 if (key.isNull()) { | |
139 return NULL; | |
140 } | |
141 LOGV(key->string); | |
142 return (unsigned char *) key->string.pointer(); | |
143 } | |
144 | |
145 /* | |
146 * Function: reducing_token | |
147 * Arguments: | |
148 * token number, tn | |
149 * state number, sn | |
150 * Returns: 0 if tn is _not_ a reducing token in the given state | |
151 * Otherwise, returns the number of the rule it reduces. | |
152 */ | |
153 | |
154 #if 0 /* no longer used */ | |
155 unsigned reducing_token(unsigned tn, unsigned sn) { | |
156 state_number_map *sp = &map_state_number[sn]; | |
157 const unsigned *p; | |
158 unsigned n = sp->n_reductions; /* number of reductions in this state */ | |
159 | |
160 if (n) { | |
161 p = lstptr(*sp, reductions); | |
162 while (n--) { | |
163 if (*p++ == tn) { | |
164 return *p; | |
165 } | |
166 p++; | |
167 } | |
168 return 0; | |
169 } | |
170 if (sp->n_completed_forms != 1) { | |
171 return 0; | |
172 } | |
173 if (shift_token(tn, sn)) { | |
174 return 0; | |
175 } | |
176 return *(lstptr(*sp,completed_forms)); | |
177 } | |
178 #endif /* 0 - no longer used */ | |
179 | |
180 Rule ruleReducedBy(Token token, unsigned sn) { | |
181 state_number_map *sp = &map_state_number[sn]; | |
182 const unsigned *p; | |
183 unsigned n = sp->n_reductions; /* number of reductions in this state */ | |
184 | |
185 if (n) { | |
186 p = lstptr(*sp, reductions); | |
187 while (n--) { | |
188 if (*p++ == (unsigned) token) { | |
189 return *p; | |
190 } | |
191 p++; | |
192 } | |
193 return 0; | |
194 } | |
195 if (sp->n_completed_forms != 1) { | |
196 // Exit if more than one completed rule | |
197 return 0; | |
198 } | |
199 if (shift_token(token, sn)) { | |
200 // Exit if there's a shift | |
201 return 0; | |
202 } | |
203 // Default reduction, return rule # | |
204 return *(lstptr(*sp, completed_forms)); | |
205 } | |
206 | |
207 void select_write_fragment(const char *name, const char *modes, | |
208 const char *suffix) { | |
209 char fragment[80]; | |
210 | |
211 strcpy(fragment, name); | |
212 strcat(fragment, modes); | |
213 strcat(fragment, suffix); | |
214 write_code_segment(fragment); | |
215 } | |
216 | |
217 int shift_token(unsigned tn, unsigned sn) { | |
218 const unsigned *p; | |
219 unsigned n; | |
220 | |
221 n = find_gotos(sn, &p); | |
222 while (n--) { | |
223 if (*p == tn) { | |
224 return 1; | |
225 } | |
226 else { | |
227 p += 2; | |
228 } | |
229 } | |
230 | |
231 n = find_completions(sn, &p); | |
232 while (n--) { | |
233 if (*p == tn) { | |
234 return 1; | |
235 } | |
236 else { | |
237 p += 2; | |
238 } | |
239 } | |
240 | |
241 return 0; | |
242 } | |
243 | |
244 void count_pe_line(const char *s, int k) { | |
245 LOGSECTION("count_pe_line"); | |
246 | |
247 while (k--) { | |
248 if (s[k] == '\n') { | |
249 pe_line_count++; | |
250 } | |
251 } | |
252 LOGV(pe_line_count); | |
253 } | |
254 | |
255 int wps(const char *s) { | |
256 LOGSECTION("wps"); | |
257 int k = strlen(s); | |
258 | |
259 fputs(s, pe_file); | |
260 count_pe_line(s, k); | |
261 return k; | |
262 } | |
263 | |
264 int wss(void) { | |
265 count_pe_line(string_base, tis()); | |
266 fputs(string_base, pe_file); | |
267 return rcs(); | |
268 } | |
269 | |
270 int wpe(const char *fs, ...) { | |
271 LOGSECTION("wpe"); | |
272 va_list ap; | |
273 char buf[2000]; | |
274 | |
275 va_start(ap, fs); | |
276 vsprintf(buf, fs, ap); | |
277 va_end(ap); | |
278 return wps(buf); | |
279 } | |
280 | |
281 void write_code_segment(const char *name) { | |
282 LOGSECTION("write_code_segment"); | |
283 LOGV(name); | |
284 if (name == NULL) { | |
285 return; | |
286 } | |
287 AgString text = code_segment(name); | |
288 if (!text.exists()) { | |
289 return; | |
290 } | |
291 char *buf = text.pointer(); | |
292 wps(buf); | |
293 wps("\n\n"); | |
294 } | |
295 | |
296 static AgString expand_my_macros(const char *s) { | |
297 LOGSECTION("expand_my_macros"); | |
298 char *p; | |
299 int col_no = 0, lb = 0, k; | |
300 | |
301 LOGV(s); | |
302 if (my_macros == NULL) { | |
303 return AgString(s); | |
304 } | |
305 ics(); | |
306 while (*s) { | |
307 char *word; | |
308 int index; | |
309 | |
310 while (*s && !isalpha(*s) && *s != '_') { | |
311 if (*s == '\n') { | |
312 acs(*s++); | |
313 col_no = 0; | |
314 while (*s && *s == ' ') { | |
315 col_no++, s++; | |
316 } | |
317 lb = col_no; | |
318 continue; | |
319 } | |
320 if (lb == col_no) { | |
321 for (k = lb; k--; ) { | |
322 acs(' '); | |
323 } | |
324 } | |
325 col_no++; | |
326 acs(*s++); | |
327 } | |
328 if (*s == 0) { | |
329 break; | |
330 } | |
331 ics(); | |
332 while (*s && (isalpha(*s) || *s == '_')) { | |
333 acs(*s++); | |
334 } | |
335 word = build_string(); | |
336 index = identify_string(word, my_macros); | |
337 if (index == 0) { | |
338 if (lb == col_no) { | |
339 for (k = lb; k--; ) { | |
340 acs(' '); | |
341 } | |
342 } | |
343 col_no += strlen(word); | |
344 ass(word); | |
345 DEALLOCATE(word); | |
346 continue; | |
347 } | |
348 DEALLOCATE(word); | |
349 p = my_macros_subs[index]; | |
350 if (*p == 0 && lb == col_no && (*s == '\n' || strncmp(s,"\\\n",2) == 0)) { | |
351 if (*s == '\\') { | |
352 s++; | |
353 } | |
354 s++; | |
355 col_no = 0; | |
356 while (*s && *s == ' ') { | |
357 col_no++; | |
358 s++; | |
359 } | |
360 lb = col_no; | |
361 continue; | |
362 } | |
363 if (lb == col_no) for (k = lb; k--;) acs(' '); | |
364 for (; *p; p++ ) { | |
365 acs(*p); | |
366 col_no++; | |
367 if (*p == '\n') { | |
368 for (k = lb; k--; ) { | |
369 acs(' '); | |
370 } | |
371 col_no = lb; | |
372 continue; | |
373 } | |
374 } | |
375 if (*s == '#') { | |
376 s++; | |
377 } | |
378 } | |
379 LOGV(string_base); | |
380 return buildAgString(); | |
381 } | |
382 | |
383 | |
384 AgString code_segment(const char *name) { | |
385 LOGSECTION("code_segment"); | |
386 | |
387 const char *rawtext = engdef_get(name); | |
388 LOGV(rawtext); | |
389 | |
390 AgString mx = expand_my_macros(rawtext); | |
391 LOGV(mx); | |
392 | |
393 return mx; | |
394 } |