Mercurial > ~dholland > hg > ag > index.cgi
comparison cgbigen/cgbigen.syn @ 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 /* | |
3 * AnaGram, a System for Syntax Directed Programming | |
4 * Copyright 1993 Parsifal Software. All Rights Reserved. | |
5 * Copyright 2006 David A. Holland. All Rights Reserved. | |
6 * See the file COPYING for license and usage terms. | |
7 * | |
8 * cgbigen.syn - Syntax for CG source file (cg46.cgs) | |
9 * Generates cg46.h. | |
10 */ | |
11 | |
12 #include <stdio.h> | |
13 #include <stdlib.h> | |
14 #include <string.h> | |
15 #include <errno.h> | |
16 #include <assert.h> | |
17 } | |
18 | |
19 | |
20 { | |
21 | |
22 static FILE *infile, *outfile; | |
23 #define GET_INPUT ((PCB).input_code = getc(infile)) | |
24 | |
25 #define TEMPFILE ".cgstemp" | |
26 | |
27 ////////////////////////////// | |
28 | |
29 #define STRBUFSIZE 32768 | |
30 static char strbuf[STRBUFSIZE]; | |
31 static size_t strbufpos = 0; | |
32 | |
33 static void addstr(int ch) { | |
34 if (strbufpos >= sizeof(strbuf)) { | |
35 fprintf(stderr, "compile-cgs: string buffer overflow; make it larger\n"); | |
36 exit(1); | |
37 } | |
38 strbuf[strbufpos++] = ch; | |
39 } | |
40 | |
41 static const char *getstr(void) { | |
42 addstr(0); | |
43 strbufpos = 0; | |
44 return strbuf; | |
45 } | |
46 | |
47 ////////////////////////////// | |
48 | |
49 /* remove a character from strbuf[] */ | |
50 static void strsnip(size_t pos) { | |
51 assert(pos < strbufpos); | |
52 strbufpos--; | |
53 memmove(strbuf+pos, strbuf+pos+1, strbufpos); | |
54 } | |
55 | |
56 /* munge newlines in strbuf[]. for exact regression test compliance. */ | |
57 static void fudgenewlines(void) { | |
58 while (strbufpos > 0 && strbuf[0] == '\n') { | |
59 strsnip(0); | |
60 } | |
61 while (strbufpos > 1 && | |
62 strbuf[strbufpos-1] == '\n' && | |
63 strbuf[strbufpos-2] == '\n') { | |
64 strbufpos--; | |
65 } | |
66 } | |
67 | |
68 ////////////////////////////// | |
69 | |
70 static void emitstring(const char *s) { | |
71 size_t i, len; | |
72 unsigned pos = 0; | |
73 | |
74 len = strlen(s); | |
75 if (len==0) { | |
76 fprintf(outfile, " \"\"\n"); | |
77 return; | |
78 } | |
79 | |
80 for (i=0; i<len; i++) { | |
81 if (pos==0) { | |
82 fprintf(outfile, " \""); | |
83 } | |
84 switch (s[i]) { | |
85 case '\r': if (pos==0) pos++; continue; | |
86 case '\n': fputs("\\n", outfile); pos+=3; break; | |
87 case '?': fputs("\\077", outfile); pos+=4; break; | |
88 case '"': fputs("\\\"", outfile); pos+=4; break; | |
89 case '\\': fputs("\\\\", outfile); pos+=4; break; | |
90 default: | |
91 if (s[i]>=32 && s[i]<127) { | |
92 fputc(s[i], outfile); | |
93 pos++; | |
94 } | |
95 else { | |
96 fprintf(outfile, "\\%03o", (unsigned)(unsigned char)s[i]); | |
97 pos+=4; | |
98 } | |
99 break; | |
100 } | |
101 if (pos>=72) { | |
102 fprintf(outfile, "\"\n"); | |
103 pos = 0; | |
104 } | |
105 } | |
106 if (pos>0) { | |
107 fprintf(outfile, "\"\n"); | |
108 } | |
109 } | |
110 | |
111 ////////////////////////////// | |
112 | |
113 static unsigned bodynum = 0, titlenum = 0; | |
114 static int havetitle = 0; | |
115 | |
116 static void emitbody(const char *s) { | |
117 unsigned num; | |
118 | |
119 num = bodynum; | |
120 bodynum = titlenum; | |
121 havetitle = 0; | |
122 | |
123 fprintf(outfile, "static const char cgbody_%u[] =\n", num); | |
124 emitstring(s); | |
125 fprintf(outfile, ";\n"); | |
126 } | |
127 | |
128 static void emittitle(const char *s) { | |
129 unsigned num; | |
130 | |
131 num = titlenum++; | |
132 if (havetitle) { | |
133 fprintf(outfile, "#define cgbody_%u cgbody_%u\n", num, bodynum); | |
134 } | |
135 else { | |
136 havetitle = 1; | |
137 } | |
138 | |
139 fprintf(outfile, "static const char cgtitle_%u[] =\n", num); | |
140 emitstring(s); | |
141 fprintf(outfile, ";\n"); | |
142 } | |
143 | |
144 static void emittable(void) { | |
145 unsigned i; | |
146 | |
147 assert(bodynum == titlenum); | |
148 | |
149 fprintf(outfile, "struct cgentry {\n"); | |
150 fprintf(outfile, " const char *name;\n"); | |
151 fprintf(outfile, " const char *data;\n"); | |
152 fprintf(outfile, "};\n\n"); | |
153 | |
154 fprintf(outfile, "static const unsigned cgtablenum = %u;\n", bodynum); | |
155 fprintf(outfile, "static struct cgentry cgtable[%u] = {\n", bodynum); | |
156 for (i=0; i<bodynum; i++) { | |
157 fprintf(outfile, " { cgtitle_%u, cgbody_%u },\n", i, i); | |
158 } | |
159 fprintf(outfile, "};\n\n"); | |
160 } | |
161 | |
162 ////////////////////////////// | |
163 | |
164 static void compile(const char *inpath, const char *outpath) { | |
165 infile = fopen(inpath, "rt"); | |
166 if (!infile) { | |
167 fprintf(stderr, "compile-cgs: %s: %s\n", inpath, strerror(errno)); | |
168 exit(1); | |
169 } | |
170 | |
171 outfile = fopen(TEMPFILE, "wt"); | |
172 if (!outfile) { | |
173 fprintf(stderr, "compile-cgs: %s: %s\n", TEMPFILE, strerror(errno)); | |
174 exit(1); | |
175 } | |
176 | |
177 fprintf(outfile, "/* Automatically generated; do not edit */\n\n"); | |
178 | |
179 cgbigen(); | |
180 if (PCB.exit_flag != AG_SUCCESS_CODE) { | |
181 exit(1); | |
182 } | |
183 | |
184 emittable(); | |
185 | |
186 fclose(outfile); | |
187 fclose(infile); | |
188 | |
189 rename(TEMPFILE, outpath); | |
190 } | |
191 | |
192 int main(int argc, char *argv[]) { | |
193 if (argc != 3) { | |
194 fprintf(stderr, "Usage: compile-cgs input-file output-file\n"); | |
195 exit(1); | |
196 } | |
197 | |
198 compile(argv[1], argv[2]); | |
199 return 0; | |
200 } | |
201 | |
202 } | |
203 | |
204 [ | |
205 default token type = void | |
206 //error trace | |
207 line numbers | |
208 line numbers path = "cgbigen.syn" | |
209 ] | |
210 | |
211 eof = -1 | |
212 range = 0..255 | |
213 blank = ' ' + '\t' | |
214 cr = '\r' | |
215 nl = '\n' | |
216 textchar = range - cr - nl | |
217 namechar = textchar - blank - ';' - ',' | |
218 | |
219 ////////////////////////////// | |
220 | |
221 (void) file $ | |
222 -> blank lines?, block..., eof | |
223 | |
224 (void) block | |
225 -> title line, | |
226 body line?..., | |
227 "##", blank lines? = fudgenewlines(), emitbody(getstr()); | |
228 | |
229 (void) title line | |
230 -> titles, comment?, newline | |
231 | |
232 ////////////////////////////// | |
233 | |
234 (void) titles | |
235 -> title | |
236 -> titles, ',', blank?..., [comment?, newline, blank?...], title | |
237 | |
238 (void) title | |
239 -> name, blank?... = emittitle(getstr()); | |
240 | |
241 (void) name | |
242 -> namechar:c = addstr(c); | |
243 -> name, namechar:c = addstr(c); | |
244 -> name, blank..., namechar:c = addstr(' '), addstr(c); | |
245 | |
246 ////////////////////////////// | |
247 | |
248 (void) body line | |
249 -> newline = addstr('\n'); | |
250 -> text, newline = addstr('\n'); | |
251 | |
252 (void) text | |
253 -> textchar:c = addstr(c); | |
254 -> text, textchar:c = addstr(c); | |
255 | |
256 ////////////////////////////// | |
257 | |
258 (void) comment | |
259 -> {';' | "//"}, textchar... | |
260 | |
261 (void) newline | |
262 -> cr?, nl | |
263 | |
264 (void) blank lines | |
265 -> blank line... | |
266 | |
267 (void) blank line | |
268 -> blank?..., newline | |
269 |