diff options
Diffstat (limited to 'web/nuweb/msdos/latex.c')
-rw-r--r-- | web/nuweb/msdos/latex.c | 361 |
1 files changed, 361 insertions, 0 deletions
diff --git a/web/nuweb/msdos/latex.c b/web/nuweb/msdos/latex.c new file mode 100644 index 0000000000..05cdd4de65 --- /dev/null +++ b/web/nuweb/msdos/latex.c @@ -0,0 +1,361 @@ +#include <stdio.h> +#include <string.h> +#include <ctype.h> + +#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(); + + +static void copy_scrap(); /* formats the body of a scrap */ +static void print_scrap_numbers(); /* formats a list of scrap numbers */ +static void format_entry(); /* formats an index entry */ +static void format_user_entry(); +void write_tex(file_name, tex_name) + char *file_name; + char *tex_name; +{ + FILE *tex_file = fopen(tex_name, "w"); + if (tex_file) { + source_open(file_name); + { + int scraps = 1; + int c = source_get(); + while (c != EOF) { + if (c == '@') + { + int big_definition = FALSE; + c = source_get(); + switch (c) { + case 'O': big_definition = TRUE; + case 'o': { + Name *name = collect_file_name(); + { + fputs("\\begin{flushleft}\n", tex_file); + if (!big_definition) + fputs("\\begin{minipage}{\\linewidth}\n", tex_file); + } + fprintf(tex_file, "\\verb@\"%s\"@", name->spelling); + fprintf(tex_file, " {\\footnotesize %d }$\\equiv$\n", scraps++); + { + fputs("\\vspace{-1.5ex}\n\\begin{quote}\n", tex_file); + copy_scrap(tex_file); + fputs("$\\Diamond$\n\\end{quote}\n\\vspace{-2ex}\n", tex_file); + } + { + if (name->defs->next) { + fputs("{\\footnotesize File defined by scraps ", tex_file); + print_scrap_numbers(tex_file, name->defs); + fputs("}\n", tex_file); + } + } + { + if (!big_definition) + fputs("\\end{minipage}\\\\[4ex]\n", tex_file); + fputs("\\end{flushleft}\n", tex_file); + do + c = source_get(); + while (isspace(c)); + } + } + break; + case 'D': big_definition = TRUE; + case 'd': { + Name *name = collect_macro_name(); + { + fputs("\\begin{flushleft}\n", tex_file); + if (!big_definition) + fputs("\\begin{minipage}{\\linewidth}\n", tex_file); + } + fprintf(tex_file, "$\\langle$%s", name->spelling); + fprintf(tex_file, " {\\footnotesize %d}$\\rangle\\equiv$\n", scraps++); + { + fputs("\\vspace{-1.5ex}\n\\begin{quote}\n", tex_file); + copy_scrap(tex_file); + fputs("$\\Diamond$\n\\end{quote}\n\\vspace{-2ex}\n", tex_file); + } + { + fputs("{\\footnotesize ", tex_file); + if (name->defs->next) { + fputs("Macro defined by scraps ", tex_file); + print_scrap_numbers(tex_file, name->defs); + fputs("\\\\[-1ex]\n", tex_file); + } + } + { + if (name->uses) { + if (name->uses->next) { + fputs("Macro referenced in scraps ", tex_file); + print_scrap_numbers(tex_file, name->uses); + fputs("}\n", tex_file); + } + else + fprintf(tex_file, "Macro referenced in scrap %d.}\n", name->uses->scrap); + } + else { + fputs("Macro never referenced.}\n", tex_file); + fprintf(stderr, "%s: <%s> never referenced.\n", + command_name, name->spelling); + } + } + { + if (!big_definition) + fputs("\\end{minipage}\\\\[4ex]\n", tex_file); + fputs("\\end{flushleft}\n", tex_file); + do + c = source_get(); + while (isspace(c)); + } + } + break; + case 'f': { + if (file_names) { + fputs("\n\\begin{list}{}{\\setlength{\\itemsep}{-\\parsep}}\n", tex_file); + format_entry(file_names, tex_file, TRUE); + fputs("\\end{list}", tex_file); + } + c = source_get(); + } + break; + case 'm': { + if (macro_names) { + fputs("\n\\begin{list}{}{\\setlength{\\itemsep}{-\\parsep}}\n", tex_file); + format_entry(macro_names, tex_file, FALSE); + fputs("\\end{list}", tex_file); + } + c = source_get(); + } + break; + case 'u': { + if (user_names) { + fputs("\n\\begin{list}{}{\\setlength{\\itemsep}{-\\parsep}}\n", tex_file); + format_user_entry(user_names, tex_file); + fputs("\\end{list}", tex_file); + } + c = source_get(); + } + break; + case '@': putc(c, tex_file); + default: c = source_get(); + break; + } + } + else { + putc(c, tex_file); + c = source_get(); + } + } + } + fclose(tex_file); + } + else + fprintf(stderr, "%s: can't open %s\n", command_name, tex_name); +} +static void print_scrap_numbers(tex_file, scraps) + FILE *tex_file; + Scrap_Node *scraps; +{ + fprintf(tex_file, "%d", scraps->scrap); + scraps = scraps->next; + while (scraps->next) { + fprintf(tex_file, ", %d", scraps->scrap); + scraps = scraps->next; + } + fprintf(tex_file, " and~%d.", scraps->scrap); +} +static void copy_scrap(file) + FILE *file; +{ + int indent = 0; + int c = source_get(); + fputs("\\verb@", file); + while (1) { + switch (c) { + case '@': { + c = source_get(); + switch (c) { + case '@': fputs("@{\\tt @}\\verb@", file); + break; + case '|': { + do { + do + c = source_get(); + while (c != '@'); + c = source_get(); + } while (c != '}'); + } + case '}': putc('@', file); + return; + case '<': { + Name *name = collect_scrap_name(); + fprintf(file, "@$\\langle$%s {\\footnotesize ", name->spelling); + if (name->defs) + fprintf(file, "%d", name->defs->scrap); + else { + putc('?', file); + fprintf(stderr, "%s: scrap never defined <%s>\n", + command_name, name->spelling); + } + fputs("}$\\rangle$\\verb@", file); + } + break; + default: /* ignore these since pass1 will have warned about them */ + break; + } + } + break; + case '\n': fputs("@\\\\\n\\verb@", file); + indent = 0; + break; + case '\t': { + int delta = 8 - (indent % 8); + indent += delta; + while (delta > 0) { + putc(' ', file); + delta--; + } + } + break; + default: putc(c, file); + indent++; + break; + } + c = source_get(); + } +} +static void format_entry(name, tex_file, file_flag) + Name *name; + FILE *tex_file; + int file_flag; +{ + while (name) { + format_entry(name->llink, tex_file, file_flag); + { + fputs("\\item \\hspace{-\\leftmargin}", tex_file); + if (file_flag) { + fprintf(tex_file, "\\verb@\"%s\"@ ", name->spelling); + { + Scrap_Node *p = name->defs; + fputs("{\\footnotesize Defined by scrap", tex_file); + if (p->next) { + fputs("s ", tex_file); + print_scrap_numbers(tex_file, p); + } + else + fprintf(tex_file, " %d.", p->scrap); + putc('}', tex_file); + } + } + else { + fprintf(tex_file, "$\\langle$%s {\\footnotesize ", name->spelling); + { + Scrap_Node *p = name->defs; + if (p) { + while (1) { + fprintf(tex_file, "%d", p->scrap); + p = p->next; + if (!p) break; + fputs(", ", tex_file); + } + } + else + putc('?', tex_file); + } + fputs("}$\\rangle$ ", tex_file); + { + Scrap_Node *p = name->uses; + fputs("{\\footnotesize ", tex_file); + if (p) { + fputs("Referenced in scrap", tex_file); + if (p->next) { + fputs("s ", tex_file); + print_scrap_numbers(tex_file, p); + } + else + fprintf(tex_file, " %d.", p->scrap); + } + else + fputs("Not referenced.", tex_file); + putc('}', tex_file); + } + } + putc('\n', tex_file); + } + name = name->rlink; + } +} +static void format_user_entry(name, tex_file) + Name *name; + FILE *tex_file; +{ + while (name) { + format_user_entry(name->llink, tex_file); + { + Scrap_Node *uses = name->uses; + Scrap_Node *defs = name->defs; + fprintf(tex_file, "\\item \\hspace{-\\leftmargin}\\verb@%s@: ", + name->spelling); + do { + if (uses && (!defs || uses->scrap < defs->scrap)) { + fprintf(tex_file, "%d", uses->scrap); + uses = uses->next; + } + else if (defs && (!uses || defs->scrap <= uses->scrap)) { + if (uses && defs->scrap == uses->scrap) + uses = uses->next; + fprintf(tex_file, "\\underline{%d}", defs->scrap); + defs = defs->next; + } + if (uses || defs) fputs(", ", tex_file); + } while (uses || defs); + fputs(".\n", tex_file); + } + name = name->rlink; + } +} |