{Copyright (c) 1978 Regents of the University of California} SEGMENT PROCEDURE SYMTBLDUMP; TYPE SYMDUMPPTR=^SYMDUMPTYPE; SYMDUMPTYPE=RECORD SYM:SYMTABLEPTR; LLINK,RLINK:SYMDUMPPTR END; VAR HEAP:^INTEGER; BUCKET,DUMPCOUNT,SCREENWIDTH,PAGEWIDTH:INTEGER; TOPOFDUMP,NEWDUMP:SYMDUMPPTR; SAVETITLE,FILL,MSSG:STRING; PROCEDURE ALPHABETIZE(SYMDUMP:SYMDUMPPTR); BEGIN IF SYM^.NAME>SYMDUMP^.SYM^.NAME THEN IF SYMDUMP^.RLINK=NIL THEN BEGIN NEW(NEWDUMP); NEWDUMP^.RLINK:=NIL; NEWDUMP^.LLINK:=NIL; NEWDUMP^.SYM:=SYM; SYMDUMP^.RLINK:=NEWDUMP; END ELSE ALPHABETIZE(SYMDUMP^.RLINK) ELSE IF SYMDUMP^.LLINK=NIL THEN BEGIN NEW(NEWDUMP); NEWDUMP^.RLINK:=NIL; NEWDUMP^.LLINK:=NIL; NEWDUMP^.SYM:=SYM; SYMDUMP^.LLINK:=NEWDUMP; END ELSE ALPHABETIZE(SYMDUMP^.LLINK); END; PROCEDURE DUMPTABLE(SYMDUMP:SYMDUMPPTR); BEGIN IF SYMDUMP^.LLINK<>NIL THEN DUMPTABLE(SYMDUMP^.LLINK); SYM:=SYMDUMP^.SYM; WRITE(LISTFILE,SYM^.NAME); CASE SYM^.ATTRIBUTE OF ABS:MSSG:=' AB '; LABELS:MSSG:=' LB '; PROCS:MSSG:=' PR '; FUNCS:MSSG:=' FC '; PUBLICS:MSSG:=' PB '; PRIVATES:MSSG:=' PV '; REFS:MSSG:=' RF '; DEFS:MSSG:=' DF '; UNKNOWN:MSSG:=' UD '; MACROS:MSSG:=' MC ' END; WRITE(LISTFILE,MSSG); IF (SYM^.ATTRIBUTE=ABS) OR (SYM^.ATTRIBUTE=LABELS) THEN BEGIN PRINTNUM(SYM^.OFFSETORVALUE,FALSE); WRITE(LISTFILE,'| '); END ELSE WRITE(LISTFILE,FILL); DUMPCOUNT:=DUMPCOUNT + 1; IF ((DUMPCOUNT MOD PAGEWIDTH=0) AND NOT CONSOLE) OR ((DUMPCOUNT MOD SCREENWIDTH=0) AND CONSOLE) THEN BEGIN WRITELN(LISTFILE); LISTNUM:=LISTNUM + 1; IF (LISTNUM MOD PAGESIZE=0) THEN PRINTPAGE; END; IF SYMDUMP^.RLINK<>NIL THEN DUMPTABLE(SYMDUMP^.RLINK); END; BEGIN{SYMTBLDUMP} MARK(HEAP); IF LEXTOKEN=TEND THEN BEGIN PRINTLINE; TEXTLINE:=BLANKLINE; END; NEW(SYM); SYM^.NAME:=' '; NEW(TOPOFDUMP); TOPOFDUMP^.SYM:=SYM; TOPOFDUMP^.LLINK:=NIL; TOPOFDUMP^.RLINK:=NIL; FOR BUCKET:=0 TO HASHTOP DO BEGIN SYM:=HASH[BUCKET]; WHILE SYM<>NIL DO BEGIN CASE SYM^.ATTRIBUTE OF LABELS,ABS,MACROS,PUBLICS,PRIVATES,CONSTS,REFS,DEFS, PROCS,FUNCS,UNKNOWN: ALPHABETIZE(TOPOFDUMP); END; SYM:=SYM^.LINK; END; END; SAVETITLE:=TITLELINE; TITLELINE:='SYMBOLTABLE DUMP'; PRINTPAGE; WRITELN(LISTFILE, 'AB - Absolute LB - Label UD - Undefined MC - Macro'); WRITELN(LISTFILE, 'RF - Ref DF - Def PR - Proc FC - Func'); WRITELN(LISTFILE, 'PB - Public PV - Private CS - Consts'); WRITELN(LISTFILE); WRITELN(LISTFILE); LISTNUM:=LISTNUM + 5; DUMPCOUNT:=0; IF LISTRADIX=8 THEN BEGIN FILL:='------| '; SCREENWIDTH:=3; PAGEWIDTH:=6; END; IF LISTRADIX=16 THEN BEGIN FILL:='----| '; SCREENWIDTH:=4; PAGEWIDTH:=7 END; DUMPTABLE(TOPOFDUMP^.RLINK); TITLELINE:=SAVETITLE; WRITELN(LISTFILE); LISTNUM:=LISTNUM + 1; PRINTPAGE; RELEASE(HEAP); END; SEGMENT PROCEDURE PROCEND; TYPE LITYPES=(INVALID,LMODULE,LGLOBALREF,LPUBLIC,LPRIVATE,LCONSTANT, LGLOBALDEF,LPUBLICDEF,LCONSTDEF,LEXTPROC,LEXTFUNC, LSEPPROC,LSEPFUNC); LINKREC=RECORD CASE INTEGER OF 0:(REFS:ARRAY[0..7] OF INTEGER); 1:(NAME:PACKNAME; CASE LITYPE:LITYPES OF LMODULE,LPUBLIC,LPRIVATE,LCONSTANT,LGLOBALREF: (FORMAT:(LWORD,LBYTE,LBIG); NREFS:INTEGER; NWORDS:INTEGER); LGLOBALDEF:(PROCNUM:INTEGER; CODEOFFSET:INTEGER); LSEPPROC,LSEPFUNC:(FUNCNUM:INTEGER; NPARAMS:INTEGER)); 2:(CLASS:INTEGER; CASE BOOLEAN OF TRUE:(JUMPS:JTABREC); FALSE:(FWDREF:BACKLABEL)) END; VAR COUNT,PROCOFFSET,OUTBLKS:INTEGER; SWAPLC:WORDSWAP; SEGDICT:PACKED ARRAY[0..511] OF CHAR; LINKINFO:FILE; LINK:FILE OF LINKREC; VIEWDUMMY:ARRAY[0..0] OF INTEGER; PROCEDURE PROCEDE; PROCEDURE BUFRESET(NEWPOS:INTEGER); VAR OUTBLKS:INTEGER; BEGIN (*$I-*) IF DEBUG THEN WRITELN('Bufreset'); IF NEWPOSBUFBLKS THEN OUTBLKS:=BUFBLKS; IF BLOCKWRITE(USERINFO.WORKCODE^,BUFFER^,OUTBLKS,OUTBLKNO)OUTBLKTOP THEN OUTBLKTOP:=OUTBLKNO + OUTBLKS; OUTBLKNO:=NEWPOS DIV 512; IF IORESULT=0 THEN IF BLOCKREAD(USERINFO.WORKCODE^,BUFFER^,BUFBLKS,OUTBLKNO)=0 THEN; BUFBOTTOM:=OUTBLKNO*512; BUFFERPOS:=NEWPOS MOD 512; END ELSE IF NEWPOS>BUFBOTTOM + BUFLIMIT THEN BEGIN OUTBLKS:=(BUFFERTOP DIV 512 - OUTBLKNO) + 1; IF OUTBLKS>BUFBLKS THEN OUTBLKS:=BUFBLKS; IF BLOCKWRITE(USERINFO.WORKCODE^,BUFFER^,OUTBLKS,OUTBLKNO)OUTBLKTOP THEN OUTBLKTOP:=OUTBLKNO + OUTBLKS; OUTBLKNO:=NEWPOS DIV 512; IF OUTBLKNO>=OUTBLKTOP THEN BEGIN IF IORESULT=0 THEN IF BLOCKWRITE(USERINFO.WORKCODE^,BUFFER^,OUTBLKNO-OUTBLKTOP, OUTBLKTOP)SCRATCHEND THEN BEGIN SEEK(LINK,LINKEND); FOR LINKCOUNT:=LINKEND+1 TO SCRATCHEND DO BEGIN GET(LINK); IF LINK^.CLASS=CLASS THEN FOR I:=0 TO 6 DO IF LINK^.JUMPS[I]<>0 THEN BEGIN PUTWORD(BUFFERTOP - LINK^.JUMPS[I]); COUNT:=COUNT + 1; END; END; END; FOR I:=0 TO 6 DO IF JUMP[I]<>0 THEN BEGIN PUTWORD(BUFFERTOP - JUMP[I]); COUNT:=COUNT + 1; END; END; PUTWORD(COUNT); END; BEGIN {Putjumps} PUTJUMP(1,JUMP1); {Jumptable entries} PUTJUMP(2,JUMP2); PUTJUMP(3,JUMP3); END; PROCEDURE LINKSET; VAR BUCKET:INTEGER; BEGIN IF DEBUG THEN WRITELN('Linkset'); IF SCRATCHEND<>0 THEN SEEK(LINK,LINKEND); {ie. file not of length 0} FOR BUCKET:=0 TO HASHTOP DO BEGIN SYM:=HASH[BUCKET]; WHILE SYM<>NIL DO BEGIN CASE SYM^.ATTRIBUTE OF UNKNOWN: BEGIN IF DISPLAY THEN BEGIN WRITELN(LISTFILE); WRITE(LISTFILE,'>>>>>',SYM^.NAME); LISTNUM:=LISTNUM + 1; END; IF NOT (CONSOLE AND DISPLAY) THEN BEGIN WRITELN; WRITE('>>>>>',SYM^.NAME); END; ERROR(1{Undefined label}); END; PUBLICS,PRIVATES,CONSTS,REFS,DEFS,PROCS,FUNCS: {Linkfile info} BEGIN FILLCHAR(LINK^,SIZEOF(LINKREC),0); CASE SYM^.ATTRIBUTE OF PUBLICS:LINK^.LITYPE:=LPUBLIC; PRIVATES:LINK^.LITYPE:=LPRIVATE; CONSTS:LINK^.LITYPE:=LCONSTANT; REFS:LINK^.LITYPE:=LGLOBALREF; DEFS:LINK^.LITYPE:=LGLOBALDEF; PROCS:LINK^.LITYPE:=LSEPPROC; FUNCS:LINK^.LITYPE:=LSEPFUNC END; LINK^.NAME:=SYM^.NAME; CASE SYM^.ATTRIBUTE OF PUBLICS,PRIVATES,CONSTS,REFS: BEGIN LINK^.FORMAT:=LWORD; LINK^.NREFS:=SYM^.NREFS; LINK^.NWORDS:=SYM^.NWORDS; LINKEND:=LINKEND + 1; PUT(LINK); COUNT:=0; WHILE SYM^.LINKOFFSET<>NIL DO BEGIN LINK^.REFS[COUNT]:=SYM^.LINKOFFSET^.PCOFFSET; COUNT:=COUNT + 1; IF COUNT=8 THEN BEGIN PUT(LINK); FILLCHAR(LINK^,SIZEOF(LINKREC),0); LINKEND:=LINKEND + 1; COUNT:=0; END; SYM^.LINKOFFSET:=SYM^.LINKOFFSET^.LAST; END; IF COUNT<>0 THEN BEGIN PUT(LINK); LINKEND:=LINKEND + 1; END; END; DEFS: IF SYM^.CODEOFFSET=-1 THEN BEGIN WRITELN(LISTFILE); IF DISPLAY THEN WRITE(LISTFILE,SYM^.NAME); IF NOT (CONSOLE AND DISPLAY) THEN BEGIN WRITELN; WRITE(SYM^.NAME); END; ERROR(1{Undefined label}); END ELSE BEGIN LINK^.LITYPE:=LGLOBALDEF; LINK^.PROCNUM:=SYM^.PROCNUM; LINK^.CODEOFFSET:=SYM^.CODEOFFSET; LINKEND:=LINKEND + 1; PUT(LINK); END; PROCS,FUNCS: BEGIN IF SYM^.ATTRIBUTE=PROCS THEN LINK^.LITYPE:=LSEPPROC ELSE LINK^.LITYPE:=LSEPFUNC; LINK^.FUNCNUM:=SYM^.FUNCNUM; LINK^.NPARAMS:=SYM^.NPARAMS; PUT(LINK); LINK^.LITYPE:=LGLOBALDEF; LINK^.PROCNUM:=SYM^.FUNCNUM; LINK^.CODEOFFSET:=0; {proc's start at LC=0} PUT(LINK); LINKEND:=LINKEND + 2; END END; IF DEBUG THEN WRITELN('link entry:',SYM^.NAME); END; END; SYM:=SYM^.LINK; END; END; END; PROCEDURE LABELFIX; {fix label forward references} VAR SWAP:WORDSWAP; FWDREF:BACKLABEL; LINKCOUNT:INTEGER; KLUDGEPTR:^INTEGER; BEGIN RESET(LINK,'*LINKER.INFO'); MARK(KLUDGEPTR); IF SCRATCHEND<>LINKEND THEN SEEK(LINK,LINKEND); FOR LINKCOUNT:=LINKEND+1 TO SCRATCHEND DO BEGIN GET(LINK); IF LINK^.CLASS=0 THEN BEGIN FWDREF:=LINK^.FWDREF; BUFRESET(FWDREF.OFFSET); PATCHCODE(FWDREF,FWDREF.OFFSET-BUFBOTTOM); END; END; END; BEGIN {Procede} IF DEBUG THEN WRITELN('Procede'); IF DISPLAY THEN WRITELN(LISTFILE,'Current available space is ',MEMAVAIL,' words'); IF NOT (DISPLAY AND CONSOLE) THEN BEGIN WRITELN; WRITELN('Current available space is ',MEMAVAIL,' words'); WRITE('<',LINENUM:4,'>'); END; LLCHECK; CLOSE(SCRATCH,LOCK); LABELFIX; BUFRESET(MAXBUFTOP); BUFFERTOP:=BUFBOTTOM + BUFFERPOS; {BUFRESET doesn't affect BUFFERTOP} IF ODD(BUFFERPOS) THEN PUTBYTE(0); RELOCATE:=NULLREL; PUTJUMPS; {Jumptable entries} PUTWORD(BUFFERTOP - PROCSTART); {Enter IC} PUTWORD(0); {Proc #, Lex level} LINKSET; PROCTABLE[PROCNUM]:=BUFFERTOP - PROCSTART; SEGSIZE:=SEGSIZE + BUFFERTOP - PROCSTART; HASH:=HASHRES; RELEASE(HEAP); END; PROCEDURE FIRSTPROC; {Set up the buffer for output assembled code} VAR BUFSETUP:^BUFFERTYPE; BEGIN IF DEBUG THEN WRITELN('Procstart'); NEW(BUFSETUP); BUFFER:=BUFSETUP; HASHRES:=HASH; {For symboltable cutback} FOR COUNT:=2 TO BUFBLKS DO NEW(BUFSETUP); FILLCHAR(BUFFER^,BUFLIMIT,0);{Clear buffer to aid DEBUGGING} IF DISPLAY THEN WRITELN(LISTFILE, BUFBLKS,' blocks for procedure code ',MEMAVAIL,' words left'); IF NOT (DISPLAY AND CONSOLE) THEN BEGIN WRITELN; WRITELN(BUFBLKS,' blocks for procedure code ',MEMAVAIL,' words left'); WRITE('<',LINENUM:4,'>'); END; BUFBOTTOM:=512; BUFFERTOP:=512; MAXBUFTOP:=512; OUTBLKNO:=1; OUTBLKTOP:=1; BUFFERPOS:=0; SEGSIZE:=0; FILLCHAR(PROCTABLE,SIZEOF(PROCTABLE),0); (*$I-*) IF BLOCKWRITE(USERINFO.WORKCODE^,BUFFER^,1)=0 THEN ERROR(54); IOCHECK(TRUE); {Segment dictionary} (*$I+*) END; BEGIN {Segment Procend} IF VIEWSTACK THEN UNITWRITE(3,VIEWDUMMY[-1600],35); {reset display of heap} IF DEBUG THEN WRITELN('Procend'); IF PROCNUM>0 THEN PROCEDE ELSE FIRSTPROC; IF LEXTOKEN=TEND THEN BEGIN PROCOFFSET:=2; {Procedure table} FOR COUNT:=PROCNUM DOWNTO 1 DO BEGIN PUTWORD(PROCOFFSET); PROCOFFSET:=PROCOFFSET + PROCTABLE[COUNT] + 2; END; PUTBYTE(1); {Segment #} PUTBYTE(PROCNUM); {# of Procedures} SEGSIZE:=PROCOFFSET; COUNT:=(BUFFERPOS + 511) DIV 512; (*$I-*) IF BLOCKWRITE(USERINFO.WORKCODE^,BUFFER^,COUNT,OUTBLKNO)1 THEN BEGIN CLOSE(LINK,LOCK); RESET(SCRATCH,'*LINKER.INFO'); SEEK(SCRATCH,LINKEND); END; NEW(FULLLABEL); FULLLABEL^.NEXT:=NIL; FREELABEL:=NIL; PROCSTART:=BUFFERTOP; IF LEXTOKEN=PROC THEN CURRENTATRIB:=PROCS ELSE CURRENTATRIB:=FUNCS; LEX; IF LEXTOKEN<>TIDENTIFIER THEN ERROR(3{Must have procedure name}) ELSE BEGIN IF PROCNUM=1 THEN SEGNAME:=SYM^.NAME; PROCNAME:=SYM^.NAME; SYM^.FUNCNUM:=PROCNUM; LEX; IF LEXTOKEN=COMMA THEN BEGIN LEX; IF LEXTOKEN<>CONSTANT THEN ERROR(4{Number of parameters expected}) ELSE SYM^.NPARAMS:=CONSTVAL; LEX; END ELSE SYM^.NPARAMS:=0; END; CODE:=BLANKCODE; CODECOUNT:=0; IF DISPLAY THEN PRINTPAGE; IF LEXTOKEN<>ENDLINE THEN BEGIN ERROR(5{extra garbage on line}); WHILE LEXTOKEN<>ENDLINE DO LEX; END; PRINTLINE; TEXTLINE:=BLANKLINE; TEXTINDEX:=-1; CURRENTATRIB:=UNKNOWN; END; END;