# include "align.h" /* VAX VMS # include */ # include /* #define INC_COLUMNS */ /* externals from slurp */ extern char nextchar(); extern char peekchar(); extern int fetchline(); extern void writeline(); extern void skip_to(); extern FILE *outstream; /* externals from words */ extern void readword(); extern void initstore(); /* types */ struct tnode { word name; int branch, term, tri; struct tnode *mother, *daughters, *next; char tag[10]; /* text of tag held in charstore */ }; typedef struct tnode treenode; /* error stuff */ int sinned = FALSE; /* error has occurred in run */ int error = FALSE; /* error has occurred in current example */ FILE *error_file; char error_name[50]; void goof(s) char *s; { if (!sinned) { error_file = fopen(error_name,"w"); sinned = TRUE; } fprintf(stderr,"%s at line %d\n",s,linecount()); fprintf(error_file,"%s at line %d\n",s,linecount); error = TRUE; } char delmark = '|'; /* delimiter */ int tagcount; /* keeps track of tags */ /* strequ */ int strequ(s1,s2) char *s1, *s2; { if (strcmp(s1,s2) == 0) return(TRUE); else return(FALSE); } /* local node label & annotation-ending function */ static int endlabel(c) char c; { if (eoln() || c == delmark) { return(TRUE); } else return(FALSE); } /* local command-word ending function */ static int endcom(c) char c; { if (c == ' ' || c == delmark) { return(TRUE); } else return(FALSE); } /* adapted from K&R itoa */ void convert(n,s) int n; char s[]; { int i; i = 0; do { s[i++] = n % 26 + 'a'; } while ((n /= 26) > 0); s[i] = '\0'; } char grabchar() { char c; c = nextchar(); if (c == '%') { fetchline(); return(grabchar()); } else return (c); } /* allocates nodespace, reads in info, etc. */ treenode *build_node() { int go; treenode *node; word holder; char **pointer; pointer = &(holder.loc); node = (treenode *)malloc(sizeof(treenode)); readword(&node->name,&go,endlabel,grabchar,FALSE); node->next = NULL; node->daughters = NULL; node->mother = NULL; node->tri = FALSE; node->term = TRUE; node->tag[0]='\0'; while (go) { readword(&holder,&go,endcom,nextchar,FALSE); if (strequ(*pointer,"tri")) node->tri=TRUE; else if (strequ(*pointer,"tag")) { readword(&holder,&go,endcom,nextchar,FALSE); strcpy(node->tag,*pointer); } } if (node->tag[0] == '\0') { node->tag[0] = 'Z'; convert(tagcount++,&(node->tag[1])); } return(node); } /* gets a node, assuming that the line the node is on is already read in */ treenode *get_node() { int pos,dpos; treenode *node; advanceeoln_pos(&pos); if (eoln()) { goof("blank line in tree"); fetchline(); return(NULL); } node = build_node(); fetchline(); advanceeoln_pos(&dpos); if (dpos > pos) { get_daughters(node,dpos); } return(node); } get_daughters(node,dpos) treenode *node; /* node of which daughters are being read */ int dpos; /* position where daughters are supposed to be */ { int pos; treenode *current; current = get_node(); current->mother = node; node->daughters = current; node->term = FALSE; while (currentpos() == dpos && !error) { /* as long as we're getting daughters */ current->next = get_node(); current = current->next; current->mother = node; } } void show_tree(node, ind) treenode *node; int ind; { int i; if (node != NULL) { for (i = 1; i<=ind; i++) putc(' ', outstream); fprintf(outstream,"%s\n",node->name.loc); if (node->tri) printf("TRI\n"); printf("tag = %s\n",node->tag); for (node = node->daughters; node !=NULL; node=node->next) show_tree(node,ind+2); } } void write_tree(node, ind) treenode *node; int ind; { int i; treenode *mother; if (node != NULL) { mother = node; for (i = 1; i<=ind; i++) /* print indentation */ putc(' ', outstream); if (node->term) { fprintf(outstream,"{\\tnode{%s}{%s}}",node->tag,node->name.loc); } else { fprintf(outstream,"{\\ntnode{%s}{%s},\n",node->tag,node->name.loc); for (node = node->daughters; node !=NULL; node=node->next) write_tree(node,ind+2); /* for (i = 1; i<=ind; i++) putc(' ', outstream); */ putc('}',outstream); }; if (mother->next != NULL) fprintf(outstream,",\n"); /* else fprintf(outstream,"%\n"); if (node->next != NULL && node->mother != NULL) putc(',',outstream); putc('\n',outstream); */ } } void draw_lines(node) treenode *node; { int i; char *m; /* mother & daughter tags */ treenode *mother; /* mother */ if (node != NULL) { mother = node; m = mother->tag; for (node = mother->daughters; node !=NULL; node=node->next) { if (node->tri) fprintf(outstream,"\\nodetriangle{%s}{%s}%%\n",m,node->tag); else fprintf(outstream,"\\nodeconnect{%s}{%s}%%\n",m,node->tag); } for (node = mother->daughters; node !=NULL; node=node->next) draw_lines(node); } } void free_tree(node) treenode *node; { if (node !=NULL) { for (node = node->daughters; node !=NULL; node=node->next) free_tree(node); free(node); node=NULL; } } void tree() { treenode *node; delmark = '|'; error = FALSE; tagcount = 0; init_store(); fetchline(); node=get_node(); if (!matchstr(".]") && !error) goof("bad tree indentation"); if (error) { fprintf(outstream,"\nBAD TREE\n"); error = FALSE; } else { fprintf(outstream,"\\tree"); write_tree(node,0); fprintf(outstream,"%%\n"), draw_lines(node); } free_tree(node); } void extendfilename(name,extension,result) /* chris: fix parameter declarations */ char name[]; char extension[]; char result[]; { strcpy(result,name); strcat(result,extension); } main(argc, argv) int argc; char *argv[]; { char infile[200]; char outfile[200]; char c; /* chris - let it run as filter */ if (argc < 2) { strcpy(infile, "stdin"); strcpy(error_name, "trees.err"); } else { extendfilename(argv[1],".txp",infile); extendfilename(argv[1],"_tx2.tex",outfile); extendfilename(argv[1],".err",error_name); } /* VAX/VMS reading from logical `source', writing to logical `product' open_source("source"); outstream = fopen("product","w"); */ if (open_source(infile)) { /* chris - letting it run as a filter still */ if (argc < 2) outstream = stdout; else outstream = fopen(outfile,"w"); while (fetchline()) { /* as long as there's input */ if (nextchar() == '.') { if ((c = nextchar()) == '[') { tree(); } #ifdef INC_COLUMNS else if (c == '<') { columns(); } #endif } else { writeline(); } } } else printf("file `%s' not found\n",infile); return(sinned); }