#include #include #include #include #include #include #include #include #include "lkb-avm.h" #include int yzPostScriptSetScale(float scale); extern int current_offset_x, current_offset_y; extern char *non_empty_list_type, *empty_list_type, *list_type; int was_endline = 1; void do_latex_avm(lkb_avm *avm, int width, int height, char *fname) { FILE *lf; lf = fopen(fname, "w"); if(!lf) { perror(fname); return; } fprintf(lf, "\\begin{avm}\n"); was_endline = 1; latex_avm_item(0, lf, avm, avm_structure, 0); fprintf(lf, "\n\\end{avm}\n"); fclose(lf); } #define latex_avm_tag(t) latex_avm_item(ind, lf, t, avm_tag, 0) #define latex_printf(lf, ... ) do {indent(lf, ind);escape_fprintf(lf, __VA_ARGS__);} while(0) indent(FILE *lf, int i) { if(was_endline)was_endline = 0; else return; for(;i>0;i--) fprintf(lf, "\t"); } escape_fprintf(FILE *lf, ...) { va_list va; char line[1024], *fmt; int i; va_start(va, lf); fmt = va_arg(va, char*); vsprintf(line, fmt, va); if(!strchr(line, '_')) fprintf(lf, "%s", line); else for(i=0;line[i];i++) { if(line[i]=='_')fprintf(lf, "\\_"); else fputc(line[i], lf); } if(line[strlen(line)-1]=='\n')was_endline = 1; va_end(va); } latex_avm_item(int ind, FILE *lf, void *item, int type, lkb_avm_tag *tag) { int i; lkb_avm *avm = item; lkb_avm_list *list = item; lkb_avm_tag *atag = item; if(tag)latex_avm_tag(tag); if(item)switch(type) { case avm_structure: if(!avm->expand || !avm->nattr) { // suprpess [ ]'s for collapsed structures item = avm->type; goto terminal; } latex_printf(lf, "\\[ \\avmspan{\\it %s} \\\\\n", avm->type); if(avm->expand)for(i=0;inattr;i++) { latex_printf(lf, "%s & ", avm->attr_name[i]); latex_avm_item(ind+1, lf, avm->attr_value[i], avm->attr_what[i], avm->attr_tag[i]); if(i+1 < avm->nattr)latex_printf(lf, " \\\\ \n"); else latex_printf(lf, " \\\\ \\]"); } break; case avm_list: latex_avm_list(ind, lf, list, tag); break; case avm_terminal: terminal: if(tag)latex_printf(lf, "\\ "); latex_printf(lf, "{\\it %s}", item); break; case avm_tag: latex_printf(lf, "\\@{%s}", atag->name); break; } else latex_printf(lf, "\\ "); // tags with no item need breathing room } int small_item(lkb_avm *item, int type) { if(!item)return 1; switch(type) { case avm_structure: if(!item->expand || !item->nattr) return 1; return 0; case avm_list: return 0; case avm_terminal: return 1; case avm_tag: return 1; } } char *sublist_small(lkb_avm_list *list, int i) { char *small = "q"; while(ilength) { if(!small_item(list->items[i], list->what[i])) small = ""; if(list->rtags[i])break; i++; } return small; } latex_avm_list(int ind, FILE *lf, lkb_avm_list *list, lkb_avm_tag *tag) { int i, open_i; char *small_b; if(tag)latex_printf(lf, "\\ "); open_i = 0; small_b = sublist_small(list, open_i); if(list->type[0] && strcmp(list->type[0], non_empty_list_type) && strcmp(list->type[0], empty_list_type) && strcmp(list->type[0], list_type)) latex_printf(lf, "\\it %s", list->type[0]); latex_printf(lf, "\\%s<", small_b); for(i=0;ilength;i++) { latex_printf(lf, "\n"); latex_avm_item(ind+1, lf, list->items[i], list->what[i], list->tags[i]); if(list->rtags[i] || list->type[i+1]) { if(i+1==open_i) // empty lists have spaces in them latex_printf(lf, "\\ "); latex_printf(lf, "\\%s>\n", small_b); latex_printf(lf, "\\ $\\oplus$\\ "); ind++; if(list->rtags[i])latex_avm_tag(list->rtags[i]); if(list->type[i+1])latex_printf(lf, "\\it %s", list->type[i+1]); ind--; open_i = i+1; if(open_i==list->length)goto draw_weird; small_b = sublist_small(list, open_i); latex_printf(lf, "\\ \\%s<", small_b); } else if(i+1length)latex_printf(lf, ", "); } if(i==open_i) latex_printf(lf, "\\ "); latex_printf(lf, "\\%s>", small_b); if(list->open_ended) { latex_printf(lf, "\\ $\\oplus$\\ \\q< \\ldots \\q>"); } if(list->rest_weird) latex_printf(lf, "\\ $\\oplus$\\ "); draw_weird: if(list->rest_weird) latex_avm_item(ind+1, lf, list->rest_weird, list->rest_type, 0); }