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