/* * Utilities to dump parse trees and symtabs. */ #include #include #include "std-macros.h" #include "parse-tree.h" #include "tokens.h" #include "sym.h" #include "parser.h" #include "type-preds.h" #include "translator.h" #include "utilities.h" /* * Check the command-line options: * * -b batch mode (don't enter interactive interpreter) * -c generate code * -n no type checking (disables execution) * -x no execution (implies batch mode) * -t dump parse tree * -s dump symtab * -m dump memory (implies type checking and execution) * -h print options * other print options * */ CheckCommandLineOptions(argc, argv) int argc; char **argv; { int n, i; char c; Interactive = true; GenCodeOption = false; DoTypecheckOption = true; DoExecutionOption = true; DumpParseTreeOption = false; DumpSymtabOption = false; DumpMemOption = false; InFiles = NewList(); for (n = 1; n < argc; n++) { /* * If arg has '-' prefix, treat as option switch, else treat is input * file. */ if (*argv[n] == '-') { if (not (argv[n][1])) { printf("Empty option (ignored)\n"); continue; } for (i = 1; c = argv[n][i]; i++) { switch (c) { case 'b': Interactive = false; break; case 'c': GenCodeOption = true; break; case 'n': DoTypecheckOption = false; break; case 'x': DoExecutionOption = false; break; case 't': DumpParseTreeOption = true; break; case 's': DumpSymtabOption = true; break; case 'm': DumpMemOption = true; break; case 'h': PrintOptions(); exit(0); default: printf("Illegal option '%c'.\n", argv[n][1]); PrintOptions(); exit(0); } } } else { /* Add input file to list. */ AddInFile(argv[n]); } } } /* * Print out available options. */ PrintOptions() { printf("Usage:\n\tt [-options ...] infiles"); printf("\n\nwhere options are:\n"); printf(" -b batch mode (don't enter interactive interpreter)\n"); printf(" -c generate code\n"); printf(" -n no type checking\n"); printf(" -x no execution\n"); printf(" -t dump parse tree\n"); printf(" -s dump symbol tab\n"); printf(" -m dump memory\n"); printf(" -h print options\n"); printf(" other print options\n"); } /* * Add an input file to the list of such files. This list is subsequently * processed in top-level of the translator. */ AddInFile(filename) char *filename; { PutList(InFiles, filename); } /* * Pretty print a parse tree. Actually, "ugly" print is a better name, since * "pretty" is generally the term used to describe a printer that prints source * code from a tree. Here we just print a direct representation of the tree * itself. * */ pp(t) nodep t; { printf("\nPARSE TREE:\n"); pp1(t,0); } pp1(t,level) nodep t; int level; { int i; nodep t1; char *name; if ((t == null) or ((t->header.kind == STMT_NODE) and (t->header.name == NULL)) or ((t->header.kind == DECL_NODE) and (t->header.name == NULL))) return; for (i=2*level; i>0; printf(" "), i--); switch (t->header.kind) { case MODULE_NODE: name = t->components.module.name-> components.atom.val.text; switch (t->header.name) { case YMODULE: printf("PROGRAM_MODULE %s:\n", name); break; case YIMPLE: printf("IMPLEMENTATION_MODULE %s:\n", name); break; case YDEF: printf("DEFINITION_MODULE %s:\n", name); break; } pp1(t->components.module.parms,level+1); pp1(t->components.module.priority,level+1); pp1(t->components.module.imports,level+1); pp1(t->components.module.exports,level+1); pp1(t->components.module.body,level+1); break; case BLOCK_NODE: printf("BLOCK_NODE:\n"); pp1(t->components.block.decls,level+1); pp1(t->components.block.stmts,level+1); break; case DECL_NODE: switch (t->header.name) { case YCONST: printf("CONST_DECL_NODE:\n"); pp1(t->components.decl.kind.consta.name,level+1); pp1(t->components.decl.kind.consta.expr,level+1); pp1(t->components.decl.kind.consta.next,level); break; case YTYPE: printf("TYPE_DECL_NODE:\n"); pp1(t->components.decl.kind.type.name,level+1); pp1(t->components.decl.kind.type.type,level+1); pp1(t->components.decl.kind.type.next,level); break; case YVAR: printf("VAR_DECL_NODE:\n"); pp1(t->components.decl.kind.var.vars,level+1); pp1(t->components.decl.kind.var.type,level+1); pp1(t->components.decl.kind.var.next,level); break; case YAX: printf("AXIOM_DECL_NODE:\n"); pp1(t->components.decl.kind.var.vars,level+1); pp1(t->components.decl.kind.formaldef.expr,level+1); break; case YTHM: printf("THM_DECL_NODE:\n"); pp1(t->components.decl.kind.var.vars,level+1); pp1(t->components.decl.kind.formaldef.expr,level+1); break; case YPROCEDURE: printf("PROC_DECL_NODE:\n"); pp1(t->components.decl.kind.proc.name,level+1); pp1(t->components.decl.kind.proc.formals,level+1); pp1(t->components.decl.kind.proc.type,level+1); pp1(t->components.decl.kind.proc.body,level+1); break; case ':': printf("RECORD_FIELD_NODE:\n"); pp1(t->components.decl.kind.field.vars,level+1); pp1(t->components.decl.kind.field.type,level+1); break; case '(': if (t->components.decl.kind.parm.isvar) printf("VAR "); if (t->components.decl.kind.parm.isarray) printf("OPEN_ARRAY "); printf("PARM_DECL_NODE:\n"); pp1(t->components.decl.kind.parm.vars,level+1); pp1(t->components.decl.kind.parm.type,level+1); break; case YCASE: printf("VARIANT_PART_NODE:\n"); pp1(t->components.decl.kind.variant.tagfield,level+1); pp1(t->components.decl.kind.variant.casefields,level+1); pp1(t->components.decl.kind.variant.elsefield,level+1); break; case '|': printf("VARIANT_FIELD_NODE:\n"); pp1(t->components.decl.kind.variantfield.caselabels,level+1); pp1(t->components.decl.kind.variantfield.fields,level+1); break; case YDOTDOT: printf("CASE LABEL(S):\n"); pp1(t->components.decl.kind.caselab.lower,level+1); pp1(t->components.decl.kind.caselab.upper,level+1); break; case YMODULE: printf("LOCAL_MODULE_DECL_NODE:\n"); pp1(t->components.decl.kind.module,level+1); break; case YIMPORT: printf("IMPORT_DECL_NODE:\n"); if (t->components.decl.kind.import.from) { for (i=2*level+1; i>0; printf(" "), i--); printf("FROM "); pp1(t->components.decl.kind.import.from,level+1); } pp1(t->components.decl.kind.import.names,level+1); break; case YEXPORT: printf("EXPORT_DECL_NODE:\n"); if (t->components.decl.kind.export.isqual) { printf("QUALIFIED "); } pp1(t->components.decl.kind.export.names,level+1); break; } pp1(t->components.decl.next,level); break; case STMT_NODE: switch (t->header.name) { case YASSMNT_OP: printf("ASSMNT_STMT_NODE:\n"); pp1(t->components.stmt.kind.assmnt.var,level+1); pp1(t->components.stmt.kind.assmnt.expr,level+1); break; case YPROCEDURE: printf("PROC_CALL_NODE:\n"); for (i=2*level+1; i>0; printf(" "), i--); printf("DESIGNATOR:\n"); pp1(t->components.stmt.kind.proccallstmt-> components.proccall.desig,level+1); for (i=2*level+1; i>0; printf(" "), i--); printf("ACTUALS:\n"); pp1(t->components.stmt.kind.proccallstmt-> components.proccall.actuals,level+1); break; case YIF: printf("IF_STMT_NODE:\n"); pp1(t->components.stmt.kind.ifstmt.expr,level+1); for (i=2*level+1; i>0; printf(" "), i--); printf("THEN_PART:\n"); pp1(t->components.stmt.kind.ifstmt.thenpart,level+1); pp1(t->components.stmt.kind.ifstmt.elsifparts,level+1); if (t->components.stmt.kind.ifstmt.elsepart) { for (i=2*level+1; i>0; printf(" "), i--); printf("ELSE_PART:\n"); pp1(t->components.stmt.kind.ifstmt.elsepart,level+1); } break; case YELSIF: printf("ELSIF_PART:\n"); pp1(t->components.stmt.kind.elsif.expr,level+1); pp1(t->components.stmt.kind.elsif.thenpart,level+1); break; case YCASE: printf("CASE_STMT_NODE:\n"); for (i=2*level+1; i>0; printf(" "), i--); printf("EXPR:\n"); pp1(t->components.stmt.kind.casestmt.expr,level+1); for (i=2*level+1; i>0; printf(" "), i--); printf("CASES:\n"); pp1(t->components.stmt.kind.casestmt.cases,level+1); if (t->components.stmt.kind.casestmt.elsepart) { for (i=2*level+1; i>0; printf(" "), i--); printf("ELSE_PART:\n"); pp1(t->components.stmt.kind.casestmt.elsepart,level+1); } break; case YOF: printf(" CASE LABEL LIST:\n"); pp1(t->components.stmt.kind.ofpart.labellist, level+1); for (i=2*level+1; i>0; printf(" "), i--); printf("CASE STMT SEQ:\n"); pp1(t->components.stmt.kind.ofpart.stmtseq, level+1); break; case YWHILE: printf("WHILE_STMT_NODE:\n"); for (i=2*level+1; i>0; printf(" "), i--); printf("EXPR:\n"); pp1(t->components.stmt.kind.whilestmt.expr,level+1); for (i=2*level+1; i>0; printf(" "), i--); printf("BODY:\n"); pp1(t->components.stmt.kind.whilestmt.body,level+1); break; case YREPEAT: printf("REPEAT_STMT_NODE:\n"); pp1(t->components.stmt.kind.repeatstmt.expr,level+1); pp1(t->components.stmt.kind.repeatstmt.body,level+1); break; case YLOOP: printf("LOOP_STMT_NODE:\n"); pp1(t->components.stmt.kind.loopstmt.body,level+1); break; case YFOR: printf("FOR_STMT_NODE:\n"); for (i=2*level+1; i>0; printf(" "), i--); printf("START EXPR:\n"); pp1(t->components.stmt.kind.forstmt.startexpr,level+1); for (i=2*level+1; i>0; printf(" "), i--); printf("END EXPR:\n"); pp1(t->components.stmt.kind.forstmt.endexpr,level+1); for (i=2*level+1; i>0; printf(" "), i--); printf("BY EXPR:\n"); pp1(t->components.stmt.kind.forstmt.byexpr,level+1); for (i=2*level+1; i>0; printf(" "), i--); printf("BODY:\n"); pp1(t->components.stmt.kind.forstmt.body,level+1); break; case YWITH: printf("WITH_STMT_NODE:\n"); for (i=2*level+1; i>0; printf(" "), i--); printf("EXPR:\n"); pp1(t->components.stmt.kind.withstmt.desig,level+1); for (i=2*level+1; i>0; printf(" "), i--); printf("BODY:\n"); pp1(t->components.stmt.kind.withstmt.body,level+1); break; case YRETURN: printf("RETURN_STMT_NODE:\n"); pp1(t->components.stmt.kind.returnstmt,level+1); break; } pp1(t->components.stmt.next,level); break; case EXPR_LIST_NODE: printf("EXPR_LIST_NODE:\n"); for (t1=t; t; t=t->components.exprlist.next) pp1(t->components.exprlist.expr, level+1); break; case EXPR_NODE: printf("EXPR_NODE, OPERATOR: "); switch (t->header.name) { case YASSMNT_OP: printf(":="); break; case '=': case '#': case '<': case '>': case '+': case '-': case '*': case '/': case '.': case '^': printf("%c", t->header.name); break; case '[': printf("[]"); break; case YLE_OP: printf("<="); break; case YGE_OP: printf(">="); break; case YIN: printf("in"); break; case YOR: printf("or"); break; case YAND: printf("and"); break; case YDIV: printf("div"); break; case YMOD: printf("mod"); break; case YUNYPLUS: printf("+"); break; case YUNYMINUS: printf("-"); break; } printf("\n"); if (t->components.expr.left_operand && t->components.expr.right_operand) { for (i=2*level+1; i>0; printf(" "), i--); printf("LEFT_OPRND:\n"); pp1(t->components.expr.left_operand, level+1); for (i=2*level+1; i>0; printf(" "), i--); printf("RIGHT_OPRND:\n"); pp1(t->components.expr.right_operand, level+1); } else { for (i=2*level+1; i>0; printf(" "), i--); printf("OPRND:\n"); if (t->components.expr.left_operand) pp1(t->components.expr.left_operand, level+1); else pp1(t->components.expr.right_operand, level+1); } break; case PROC_CALL_NODE: printf("PROC_CALL_NODE:\n"); for (i=2*level+1; i>0; printf(" "), i--); printf("DESIGNATOR:\n"); pp1(t->components.proccall.desig,level+1); for (i=2*level+1; i>0; printf(" "), i--); printf("ACTUALS:\n"); pp1(t->components.proccall.actuals,level+1); break; case TYPE_NODE: switch (t->header.name) { case Yident: printf("TYPE_IDENT_NODE:\n"); pp1(t->components.type.kind.name,level+1); break; case '(': printf("ENUM_TYPE_NODE:\n"); pp1(t->components.type.kind.enumtype.idents,level+1); break; case '[': printf("SUBRANGE_TYPE_NODE:\n"); pp1(t->components.type.kind.subrange.basetype,level+1); pp1(t->components.type.kind.subrange.lower,level+1); pp1(t->components.type.kind.subrange.upper,level+1); break; case YARRAY: printf("ARRAY_TYPE_NODE:\n"); pp1(t->components.type.kind.arraytype.bounds,level+1); pp1(t->components.type.kind.arraytype.basetype,level+1); break; case YOR: printf("UNION_TYPE_NODE:\n"); pp1(t->components.type.kind.record.fields,level+1); break; case YRECORD: printf("RECORD_TYPE_NODE:\n"); pp1(t->components.type.kind.record.fields,level+1); break; case YSET: printf("SET_TYPE_NODE:\n"); pp1(t->components.type.kind.settype.basetype,level+1); break; case YPOINTER: printf("POINTER_TYPE_NODE:\n"); pp1(t->components.type.kind.pointer.basetype,level+1); break; case YPROCEDURE: printf("PROCEDURE_TYPE_NODE:\n"); pp1(t->components.type.kind.proc.formals,level+1); pp1(t->components.type.kind.proc.type,level+1); break; } break; case ATOM_NODE: printf("ATOM_NODE: "); switch (t->header.name) { /* * YQUALIFIED case is vestigial */ case YQUALIFIED: for (t1=t; t1->components.atom.next; t1=t1->components.atom.next) printf("%s.", t1->components.atom.val.text); printf("%s", t1->components.atom.val.text); break; case Yident: for (t1=t; t1->components.atom.next; t1=t1->components.atom.next) printf("%s.", t1->components.atom.val.text); printf("%s", t1->components.atom.val.text); break; case Yreal: printf("%f ",t->components.atom.val.real); break; case Yinteger: printf("%d ",t->components.atom.val.integer); break; case Ychar: printf("%c ",t->components.atom.val.character); break; case Ystring: printf("%c ",t->components.atom.val.string); break; } printf("\n"); } } /* Dump out the contents of the symbol table. */ DumpSymtab(Tab, Level, tchk) Symtab *Tab; int Level; bool tchk; { int i; SymtabEntry *e; nodep im, im1, ex; char *name; /* * Print Level 0 header message. */ if (Level == 0) printf("\nSYMTAB DUMP:\n"); for (i=Level*4; i>0; i--) printf(" "); /* * Print symtab name, level, size, and offset total. */ printf("%s's Symtab Contents, at Level %d, Size %d:, Offset total: %d\n", Tab->ParentEntry->Symbol, Tab->Level, Tab->Size, Tab->Offset); /* * Print imports, if any. */ if (im = Tab->Imports) { for (i=Level*4+2; i>0; i--) printf(" "); printf("Imports:\n"); for (; im; im = im->components.decl.next) { for (i=Level*4+3; i>0; i--) printf(" "); if (im1 = (im->components.decl.kind.import.from)) printf("From %s ", im1->components.atom.val.text); for (im1 = im->components.decl.kind.import.names; im1; im1 = im1->components.atom.next) { printf("%s", im1->components.atom.val.text); if (im->components.atom.next) printf (", "); } printf("\n"); } } /* * Print exports, if any. */ if (ex = Tab->Exports) { for (i=Level*4+2; i>0; i--) printf(" "); printf("Exports: "); if (ex->components.decl.kind.export_.isqual) printf("qualified"); printf(": "); for (ex = ex->components.decl.kind.export_.names; ex; ex = ex->components.atom.next) { printf("%s", ex->components.atom.val.text); if (ex->components.atom.next) printf (", "); } printf("\n"); } /* * Print the entries (only the non-null ones). */ for (i=0; iSize; i++) for (e=Tab->Entries[i]; e; e=e->Next) DumpSymtabEntry(e, i, Level, tchk); } /* * Dump a symtab entry, including all elements on the hash overflow chain. */ DumpSymtabEntry(Entry, Index, Level, tchk) SymtabEntry *Entry; int Index; int Level; bool tchk; { int i; SymtabEntry *e; for (i=Level*4; i>0; i--) printf(" "); printf("Entry %d: Symbol: %s, Type: 0x%x, Class: %d", Index, Entry->Symbol, Entry->Type, Entry->Class); /* * Print out offset if symbol has one. */ switch (Entry->Class) { case C_Var: printf(", Offset: %d", Entry->Info.Var.Offset); break; case C_Parm: printf(", Offset: %d", Entry->Info.Parm.Offset); break; case C_Proc: printf(", Offset: %d", Entry->Info.Proc.Offset); break; } printf("\n"); /* * Print proc parms and symtab. */ if (Entry->Class == C_Proc) { for (i=Level*4+2; i>0; i--) printf(" "); printf("Parm Chain: "); for (e=Entry->Info.Proc.Parms; e; e=e->Info.Parm.Link) { printf("%s", e->Symbol); if (e->Info.Parm.Link) printf(", "); } printf("\n"); if ((not ChkSymFlag(Entry, specialProc)) and (not ChkSymFlag(Entry, compiledProc))) DumpSymtab(Entry->Info.Proc.Symtab, Level + 1, tchk); } /* * Print module symtab. */ if (Entry->Class == C_Module) { DumpSymtab(Entry->Info.Module.Symtab, Level + 1, tchk); } /* * Print out record symtabs. (Only if typechking succeeded.) */ if (tchk and Entry->Type) DumpRecordType(Entry->Type, Level, tchk); } /* * Recursively descend into a structured type, dumping all record symtabs. */ DumpRecordType(t, level, tchk) TypeStruct t; int level; { switch (t->header.name) { case YRECORD: DumpSymtab( t->components.type.kind.record.fieldstab,level+1,tchk); break; case YARRAY: DumpRecordType( t->components.type.kind.arraytype.basetype,level,tchk); break; case YPOINTER: DumpRecordType( t->components.type.kind.pointer.basetype,level,tchk); break; default: return; } } /* * Dump out the values of all global variables. */ DumpVars(Tab) Symtab *Tab; { int i; SymtabEntry *e; printf("\nSTATIC MEMORY DUMP:\n"); for (i=0; iSize; i++) for (e=Tab->Entries[i]; e; e=e->Next) if (e->Class == C_Var) DumpVarVal(e); } DumpVarVal(Entry) SymtabEntry *Entry; { int i; switch (Entry->Type->components.type.tag) { case NilTag: { printf(" var %s: pointer = nil\n"); break; } case IntTag: { int v; bcopy(&(StaticPool[Entry->Info.Var.Offset]), &v, sizeof(int)); printf(" var %s: integer = %d\n", Entry->Symbol, v); break; } case LIntTag: { long v; bcopy(&(StaticPool[Entry->Info.Var.Offset]), &v, sizeof(long)); printf(" var %s: longinteger = %d\n", Entry->Symbol, v); break; } case RealTag: { double v; bcopy(&(StaticPool[Entry->Info.Var.Offset]), &v, sizeof(double)); printf(" var %s: real = %g\n", Entry->Symbol, v); break; } case LRealTag: { double v; bcopy(&(StaticPool[Entry->Info.Var.Offset]), &v, sizeof(double)); printf(" var %s: longreal = %g\n", Entry->Symbol, v); break; } case CharTag: { char v; bcopy(&(StaticPool[Entry->Info.Var.Offset]), &v, sizeof(char)); printf(" var %s: char = '%c'\n", Entry->Symbol, v); break; } case BoolTag: { bool v; bcopy(&(StaticPool[Entry->Info.Var.Offset]), &v, sizeof(bool)); printf(" var %s: boolean = %s\n", Entry->Symbol, v ? "true" : "false"); break; } case StringTag: { char *v; bcopy(&(StaticPool[Entry->Info.Var.Offset]), &v, sizeof(char *)); printf(" var %s: string = %s\n", Entry->Symbol, v); break; } case SetTag: { char *v; bcopy(&(StaticPool[Entry->Info.Var.Offset]), &v, sizeof(char *)); printf(" var %s: set = %x\n", Entry->Symbol, v); break; } case PtrTag: { char *v; printf(" var %s: pointer = ", Entry->Symbol); bcopy(&(StaticPool[Entry->Info.Var.Offset]), &v, sizeof(char *)); if (not v) printf("nil\n"); else { printf ("\n"); HexMemDump(v, TypeSize( Entry->Type->components.type.kind.pointer.basetype)); } break; } case StructTag: { if (isArray(Entry->Type)) printf(" var %s: array = \n", Entry->Symbol); else printf(" var %s: record = \n", Entry->Symbol); HexMemDump(&(StaticPool[Entry->Info.Var.Offset]), TypeSize(Entry->Type)); break; } case ProcTag: { SymtabEntry *v; bcopy(&(StaticPool[Entry->Info.Var.Offset]), &v, sizeof(char *)); if (not v) printf(" var %s: procedure = nil\n", Entry->Symbol); else printf(" var %s: procedure = %s\n", Entry->Symbol, v->Symbol); break; } } } /* * Dump a segment of memory as hex words. */ HexMemDump(startaddr, size) char *startaddr; int size; { char *endaddr = startaddr + size; char *p; long l; int i, j; printf("\t"); for (p = startaddr, i=1; p < endaddr; p += sizeof(long), i++) { bcopy(p, &l, sizeof(long)); printf("0x%08x ", l); if (((i % 4) == 0) and (p < endaddr - 4)) printf("\n\t"); } printf("\n"); /* * p as a long, as used below, wont work on a sparc because of alignment * errors. Cf. doForIncr and IntegerizeL in interp.c. * long *p; int i; printf("\t"); for (p = (long *)startaddr, i=1; p < (long *) endaddr; p++, i++) { printf("0x%08x ", *p); if (((i % 4) == 0) and (p < ((long *) endaddr - 1))) printf("\n\t"); } printf("\n"); */ }