Mercurial > ~dholland > hg > ag > index.cgi
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cgbigen/cgbigen.syn Sat Dec 22 17:52:45 2007 -0500 @@ -0,0 +1,269 @@ +{ +/* + * AnaGram, a System for Syntax Directed Programming + * Copyright 1993 Parsifal Software. All Rights Reserved. + * Copyright 2006 David A. Holland. All Rights Reserved. + * See the file COPYING for license and usage terms. + * + * cgbigen.syn - Syntax for CG source file (cg46.cgs) + * Generates cg46.h. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <assert.h> +} + + +{ + +static FILE *infile, *outfile; +#define GET_INPUT ((PCB).input_code = getc(infile)) + +#define TEMPFILE ".cgstemp" + +////////////////////////////// + +#define STRBUFSIZE 32768 +static char strbuf[STRBUFSIZE]; +static size_t strbufpos = 0; + +static void addstr(int ch) { + if (strbufpos >= sizeof(strbuf)) { + fprintf(stderr, "compile-cgs: string buffer overflow; make it larger\n"); + exit(1); + } + strbuf[strbufpos++] = ch; +} + +static const char *getstr(void) { + addstr(0); + strbufpos = 0; + return strbuf; +} + +////////////////////////////// + +/* remove a character from strbuf[] */ +static void strsnip(size_t pos) { + assert(pos < strbufpos); + strbufpos--; + memmove(strbuf+pos, strbuf+pos+1, strbufpos); +} + +/* munge newlines in strbuf[]. for exact regression test compliance. */ +static void fudgenewlines(void) { + while (strbufpos > 0 && strbuf[0] == '\n') { + strsnip(0); + } + while (strbufpos > 1 && + strbuf[strbufpos-1] == '\n' && + strbuf[strbufpos-2] == '\n') { + strbufpos--; + } +} + +////////////////////////////// + +static void emitstring(const char *s) { + size_t i, len; + unsigned pos = 0; + + len = strlen(s); + if (len==0) { + fprintf(outfile, " \"\"\n"); + return; + } + + for (i=0; i<len; i++) { + if (pos==0) { + fprintf(outfile, " \""); + } + switch (s[i]) { + case '\r': if (pos==0) pos++; continue; + case '\n': fputs("\\n", outfile); pos+=3; break; + case '?': fputs("\\077", outfile); pos+=4; break; + case '"': fputs("\\\"", outfile); pos+=4; break; + case '\\': fputs("\\\\", outfile); pos+=4; break; + default: + if (s[i]>=32 && s[i]<127) { + fputc(s[i], outfile); + pos++; + } + else { + fprintf(outfile, "\\%03o", (unsigned)(unsigned char)s[i]); + pos+=4; + } + break; + } + if (pos>=72) { + fprintf(outfile, "\"\n"); + pos = 0; + } + } + if (pos>0) { + fprintf(outfile, "\"\n"); + } +} + +////////////////////////////// + +static unsigned bodynum = 0, titlenum = 0; +static int havetitle = 0; + +static void emitbody(const char *s) { + unsigned num; + + num = bodynum; + bodynum = titlenum; + havetitle = 0; + + fprintf(outfile, "static const char cgbody_%u[] =\n", num); + emitstring(s); + fprintf(outfile, ";\n"); +} + +static void emittitle(const char *s) { + unsigned num; + + num = titlenum++; + if (havetitle) { + fprintf(outfile, "#define cgbody_%u cgbody_%u\n", num, bodynum); + } + else { + havetitle = 1; + } + + fprintf(outfile, "static const char cgtitle_%u[] =\n", num); + emitstring(s); + fprintf(outfile, ";\n"); +} + +static void emittable(void) { + unsigned i; + + assert(bodynum == titlenum); + + fprintf(outfile, "struct cgentry {\n"); + fprintf(outfile, " const char *name;\n"); + fprintf(outfile, " const char *data;\n"); + fprintf(outfile, "};\n\n"); + + fprintf(outfile, "static const unsigned cgtablenum = %u;\n", bodynum); + fprintf(outfile, "static struct cgentry cgtable[%u] = {\n", bodynum); + for (i=0; i<bodynum; i++) { + fprintf(outfile, " { cgtitle_%u, cgbody_%u },\n", i, i); + } + fprintf(outfile, "};\n\n"); +} + +////////////////////////////// + +static void compile(const char *inpath, const char *outpath) { + infile = fopen(inpath, "rt"); + if (!infile) { + fprintf(stderr, "compile-cgs: %s: %s\n", inpath, strerror(errno)); + exit(1); + } + + outfile = fopen(TEMPFILE, "wt"); + if (!outfile) { + fprintf(stderr, "compile-cgs: %s: %s\n", TEMPFILE, strerror(errno)); + exit(1); + } + + fprintf(outfile, "/* Automatically generated; do not edit */\n\n"); + + cgbigen(); + if (PCB.exit_flag != AG_SUCCESS_CODE) { + exit(1); + } + + emittable(); + + fclose(outfile); + fclose(infile); + + rename(TEMPFILE, outpath); +} + +int main(int argc, char *argv[]) { + if (argc != 3) { + fprintf(stderr, "Usage: compile-cgs input-file output-file\n"); + exit(1); + } + + compile(argv[1], argv[2]); + return 0; +} + +} + +[ + default token type = void + //error trace + line numbers + line numbers path = "cgbigen.syn" +] + +eof = -1 +range = 0..255 +blank = ' ' + '\t' +cr = '\r' +nl = '\n' +textchar = range - cr - nl +namechar = textchar - blank - ';' - ',' + +////////////////////////////// + +(void) file $ + -> blank lines?, block..., eof + +(void) block + -> title line, + body line?..., + "##", blank lines? = fudgenewlines(), emitbody(getstr()); + +(void) title line + -> titles, comment?, newline + +////////////////////////////// + +(void) titles + -> title + -> titles, ',', blank?..., [comment?, newline, blank?...], title + +(void) title + -> name, blank?... = emittitle(getstr()); + +(void) name + -> namechar:c = addstr(c); + -> name, namechar:c = addstr(c); + -> name, blank..., namechar:c = addstr(' '), addstr(c); + +////////////////////////////// + +(void) body line + -> newline = addstr('\n'); + -> text, newline = addstr('\n'); + +(void) text + -> textchar:c = addstr(c); + -> text, textchar:c = addstr(c); + +////////////////////////////// + +(void) comment + -> {';' | "//"}, textchar... + +(void) newline + -> cr?, nl + +(void) blank lines + -> blank line... + +(void) blank line + -> blank?..., newline +