From e0c6872cf40896c7be36b11dcc744620f10adf1d Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Mon, 2 Sep 2019 13:46:59 +0900 Subject: Initial commit --- web/nuweb/msdos/scraps.c | 542 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 542 insertions(+) create mode 100644 web/nuweb/msdos/scraps.c (limited to 'web/nuweb/msdos/scraps.c') diff --git a/web/nuweb/msdos/scraps.c b/web/nuweb/msdos/scraps.c new file mode 100644 index 0000000000..ecc35ea856 --- /dev/null +++ b/web/nuweb/msdos/scraps.c @@ -0,0 +1,542 @@ +#include +#include +#include + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE (!0) +#endif +typedef struct scrap_node { + struct scrap_node *next; + int scrap; +} Scrap_Node; +typedef struct name { + char *spelling; + struct name *llink; + struct name *rlink; + Scrap_Node *defs; + Scrap_Node *uses; + int mark; + char tab_flag; + char indent_flag; + char debug_flag; +} Name; + +int tex_flag; /* if FALSE, don't emit the .tex file */ +int output_flag; /* if FALSE, don't emit the output files */ +int compare_flag; /* if FALSE, overwrite without comparison */ +char *command_name; +char *source_name; /* name of the current file */ +int source_line; /* current line in the source file */ +Name *file_names; +Name *macro_names; +Name *user_names; + +void pass1(); +void write_tex(); +void write_files(); +void source_open(); /* pass in the name of the source file */ +int source_get(); /* no args; returns the next char or EOF */ +void init_scraps(); +int collect_scrap(); +int write_scraps(); +Name *collect_file_name(); +Name *collect_macro_name(); +Name *collect_scrap_name(); +Name *name_add(); +Name *prefix_add(); +char *save_string(); +void reverse_lists(); +void *arena_getmem(); +void arena_free(); + + +#define SLAB_SIZE 500 + +typedef struct slab { + struct slab *next; + char chars[SLAB_SIZE]; +} Slab; +typedef struct { + char *file_name; + int file_line; + Slab *slab; +} ScrapEntry; +ScrapEntry *SCRAP[256]; + +#define scrap_array(i) SCRAP[(i) >> 8][(i) & 255] + +int scraps; +void init_scraps() +{ + scraps = 1; + SCRAP[0] = (ScrapEntry *) arena_getmem(256 * sizeof(ScrapEntry)); +} +typedef struct { + Slab *scrap; + int index; +} Manager; +static void push(c, manager) + char c; + Manager *manager; +{ + Slab *scrap = manager->scrap; + int index = manager->index; + scrap->chars[index++] = c; + if (index == SLAB_SIZE) { + Slab *new = (Slab *) arena_getmem(sizeof(Slab)); + scrap->next = new; + manager->scrap = new; + index = 0; + } + manager->index = index; +} +static void pushs(s, manager) + char *s; + Manager *manager; +{ + while (*s) + push(*s++, manager); +} +int collect_scrap() +{ + Manager writer; + { + Slab *scrap = (Slab *) arena_getmem(sizeof(Slab)); + if ((scraps & 255) == 0) + SCRAP[scraps >> 8] = (ScrapEntry *) arena_getmem(256 * sizeof(ScrapEntry)); + scrap_array(scraps).slab = scrap; + scrap_array(scraps).file_name = save_string(source_name); + scrap_array(scraps).file_line = source_line; + writer.scrap = scrap; + writer.index = 0; + } + { + int c = source_get(); + while (1) { + switch (c) { + case EOF: fprintf(stderr, "%s: unexpect EOF in scrap (%s, %d)\n", + command_name, scrap_array(scraps).file_name, + scrap_array(scraps).file_line); + exit(-1); + case '@': { + c = source_get(); + switch (c) { + case '@': pushs("@@", &writer); + c = source_get(); + break; + case '|': { + do { + char new_name[100]; + char *p = new_name; + do + c = source_get(); + while (isspace(c)); + if (c != '@') { + Name *name; + do { + *p++ = c; + c = source_get(); + } while (c != '@' && !isspace(c)); + *p = '\0'; + name = name_add(&user_names, new_name); + if (!name->defs || name->defs->scrap != scraps) { + Scrap_Node *def = (Scrap_Node *) arena_getmem(sizeof(Scrap_Node)); + def->scrap = scraps; + def->next = name->defs; + name->defs = def; + } + } + } while (c != '@'); + c = source_get(); + if (c != '}') { + fprintf(stderr, "%s: unexpected @%c in scrap (%s, %d)\n", + command_name, c, source_name, source_line); + exit(-1); + } + } + case '}': push('\0', &writer); + return scraps++; + case '<': { + Name *name = collect_scrap_name(); + { + char *s = name->spelling; + int len = strlen(s) - 1; + pushs("@<", &writer); + while (len > 0) { + push(*s++, &writer); + len--; + } + if (*s == ' ') + pushs("...", &writer); + else + push(*s, &writer); + pushs("@>", &writer); + } + { + if (!name->uses || name->uses->scrap != scraps) { + Scrap_Node *use = (Scrap_Node *) arena_getmem(sizeof(Scrap_Node)); + use->scrap = scraps; + use->next = name->uses; + name->uses = use; + } + } + c = source_get(); + } + break; + default : fprintf(stderr, "%s: unexpected @%c in scrap (%s, %d)\n", + command_name, c, source_name, source_line); + exit(-1); + } + } + break; + default: push(c, &writer); + c = source_get(); + break; + } + } + } +} +static char pop(manager) + Manager *manager; +{ + Slab *scrap = manager->scrap; + int index = manager->index; + char c = scrap->chars[index++]; + if (index == SLAB_SIZE) { + manager->scrap = scrap->next; + index = 0; + } + manager->index = index; + return c; +} +static Name *pop_scrap_name(manager) + Manager *manager; +{ + char name[100]; + char *p = name; + int c = pop(manager); + while (TRUE) { + if (c == '@') + { + c = pop(manager); + if (c == '@') { + *p++ = c; + c = pop(manager); + } + else if (c == '>') { + if (p - name > 3 && p[-1] == '.' && p[-2] == '.' && p[-3] == '.') { + p[-3] = ' '; + p -= 2; + } + *p = '\0'; + return prefix_add(¯o_names, name); + } + else { + fprintf(stderr, "%s: found an internal problem (1)\n", command_name); + exit(-1); + } + } + else { + *p++ = c; + c = pop(manager); + } + } +} +int write_scraps(file, defs, global_indent, indent_chars, + debug_flag, tab_flag, indent_flag) + FILE *file; + Scrap_Node *defs; + int global_indent; + char *indent_chars; + char debug_flag; + char tab_flag; + char indent_flag; +{ + int indent = 0; + while (defs) { + { + char c; + Manager reader; + int line_number = scrap_array(defs->scrap).file_line; + if (debug_flag) { + fprintf(file, "\n#line %d \"%s\"\n", + line_number, scrap_array(defs->scrap).file_name); + { + if (indent_flag) { + if (tab_flag) + for (indent=0; indentscrap).slab; + reader.index = 0; + c = pop(&reader); + while (c) { + switch (c) { + case '@': { + c = pop(&reader); + switch (c) { + case '@': putc(c, file); + indent_chars[global_indent + indent] = ' '; + indent++; + break; + case '<': { + Name *name = pop_scrap_name(&reader); + if (name->mark) { + fprintf(stderr, "%s: recursive macro discovered involving <%s>\n", + command_name, name->spelling); + exit(-1); + } + if (name->defs) { + name->mark = TRUE; + indent = write_scraps(file, name->defs, global_indent + indent, + indent_chars, debug_flag, tab_flag, indent_flag); + indent -= global_indent; + name->mark = FALSE; + } + else if (!tex_flag) + fprintf(stderr, "%s: macro never defined <%s>\n", + command_name, name->spelling); + } + if (debug_flag) { + fprintf(file, "\n#line %d \"%s\"\n", + line_number, scrap_array(defs->scrap).file_name); + { + if (indent_flag) { + if (tab_flag) + for (indent=0; indent 0) { + putc(' ', file); + delta--; + } + } + else { + putc('\t', file); + indent_chars[global_indent + indent] = '\t'; + indent++; + } + } + break; + default: putc(c, file); + indent_chars[global_indent + indent] = ' '; + indent++; + break; + } + c = pop(&reader); + } + } + defs = defs->next; + } + return indent + global_indent; +} + +typedef struct name_node { + struct name_node *next; + Name *name; +} Name_Node; + +typedef struct goto_node { + struct goto_node *next; /* next goto node with same depth */ + struct goto_node *fail; + struct move_node *moves; + Name_Node *output; +} Goto_Node; + +typedef struct move_node { + struct move_node *next; + Goto_Node *state; + char c; +} Move_Node; + +static Goto_Node *root[128]; +static int max_depth; +static Goto_Node **depths; +static Goto_Node *goto_lookup(c, g) + char c; + Goto_Node *g; +{ + Move_Node *m = g->moves; + while (m && m->c != c) + m = m->next; + if (m) + return m->state; + else + return NULL; +} + +static void build_gotos(); + +void search() +{ + int i; + for (i=0; i<128; i++) + root[i] = NULL; + max_depth = 10; + depths = (Goto_Node **) arena_getmem(max_depth * sizeof(Goto_Node *)); + for (i=0; imoves; + while (m) { + char a = m->c; + Goto_Node *s = m->state; + Goto_Node *state = r->fail; + while (state && !goto_lookup(a, state)) + state = state->fail; + if (state) + s->fail = goto_lookup(a, state); + else + s->fail = root[a]; + if (s->fail) { + Name_Node *p = s->fail->output; + while (p) { + Name_Node *q = (Name_Node *) arena_getmem(sizeof(Name_Node)); + q->name = p->name; + q->next = s->output; + s->output = q; + p = p->next; + } + } + m = m->next; + } + r = r->next; + } + } + } + { + for (i=1; ifail; + if (state) + state = goto_lookup(c, state); + else + state = root[c]; + if (state && state->output) { + Name_Node *p = state->output; + do { + Name *name = p->name; + if (!name->uses || name->uses->scrap != i) { + Scrap_Node *new_use = + (Scrap_Node *) arena_getmem(sizeof(Scrap_Node)); + new_use->scrap = i; + new_use->next = name->uses; + name->uses = new_use; + } + p = p->next; + } while (p); + } + c = pop(&reader); + } + } + } +} +static void build_gotos(tree) + Name *tree; +{ + while (tree) { + { + int depth = 2; + char *p = tree->spelling; + char c = *p++; + Goto_Node *q = root[c]; + if (!q) { + q = (Goto_Node *) arena_getmem(sizeof(Goto_Node)); + root[c] = q; + q->moves = NULL; + q->fail = NULL; + q->moves = NULL; + q->output = NULL; + q->next = depths[1]; + depths[1] = q; + } + while (c = *p++) { + Goto_Node *new = goto_lookup(c, q); + if (!new) { + Move_Node *new_move = (Move_Node *) arena_getmem(sizeof(Move_Node)); + new = (Goto_Node *) arena_getmem(sizeof(Goto_Node)); + new->moves = NULL; + new->fail = NULL; + new->moves = NULL; + new->output = NULL; + new_move->state = new; + new_move->c = c; + new_move->next = q->moves; + q->moves = new_move; + if (depth == max_depth) { + int i; + Goto_Node **new_depths = + (Goto_Node **) arena_getmem(2*depth*sizeof(Goto_Node *)); + max_depth = 2 * depth; + for (i=0; inext = depths[depth]; + depths[depth] = new; + } + q = new; + depth++; + } + q->output = (Name_Node *) arena_getmem(sizeof(Name_Node)); + q->output->next = NULL; + q->output->name = tree; + } + build_gotos(tree->rlink); + tree = tree->llink; + } +} -- cgit v1.2.3