(* 31V4 Assignment 2 - PDP subset assembler *) (* Writen by: J.G.Harston, (C)HCE *) (* Symbols module. Holds the symbol table as a serial linked list *) IMPLEMENTATION MODULE Symbols; FROM Storage IMPORT ALLOCATE, DEALLOCATE; TYPE list_p=POINTER TO list; list=RECORD lbltxt:Label; (* The text of the label *) lblval:INTEGER; (* The value of the label *) lbllnk:list_p; (* The link to the next label *) END; VAR list_head,my_ptr:list_p; (* pointer to the head of the list, and the *) (* printout pointer *) PROCEDURE enter_label(l:Label; v:INTEGER); (* This procedure enters a label into the symbol table. If the label has already been defined (as they will be in pass 2), the label is amended *) VAR ptr,newp:list_p; test:INTEGER; BEGIN ptr:=looklbl(l,test); (* Search for the label *) IF test<>0 THEN (* ie this is a new entry *) NEW(newp); (* Create and link the new entry *) newp^.lbllnk:=ptr^.lbllnk; ptr^.lbllnk:=newp; END; ptr:=ptr^.lbllnk; (* Point at the entry concerned *) ptr^.lbltxt:=l; (* Set the label *) ptr^.lblval:=v; (* and set the value *) END enter_label; PROCEDURE find_label(l:Label; VAR v:INTEGER):BOOLEAN (* This procedure is called to find a label in the symbol table and return its value. If no matching label was found, the FALSE is returned *) VAR ptr:list_p; test:INTEGER; BEGIN ptr:=looklbl(l,test); (* Look for the label *) IF (test<>0) OR (ptr^.lbllnk=NIL) THEN (* If not found, return FALSE *) v:=0; RETURN FALSE; ELSE v:=ptr^.lbllnk^.lblval; (* Otherwise, return TRUE, and giving the *) RETURN TRUE; (* value of the label *) END; END find_label; PROCEDURE init_list(VAR n:INTEGER); (* This procedure is called to initialise the list pointer prior to displaying the symbol table *) VAR ptr:list_p; BEGIN my_ptr:=list_head^.lbllnk; (* Set the pointer to the start of the list *) ptr:=list_head; n:=0; REPEAT (* Count the entries in the list *) n:=n+1; ptr:=ptr^.lbllnk; UNTIL ptr=NIL; n:=n-1; (* The number of entries is one less than the number counted *) END init_list; PROCEDURE get_label(VAR l:Label; VAR v:INTEGER):BOOLEAN; (* This procedure is called to get the label and value from the next entry in the symbol table when listing out the symbol table *) BEGIN IF my_ptr<>NIL THEN (* If we're not at the end of the list, then *) l:=my_ptr^.lbltxt; (* Get the text of the label name *) v:=my_ptr^.lblval; (* Get the value *) my_ptr:=my_ptr^.lbllnk; (* Move the pointer to the next entry *) RETURN TRUE; ELSE RETURN FALSE; (* At the end of the list return FALSE *) END; END get_label; PROCEDURE looklbl(lbl:Label; VAR equal:INTEGER):list_p; (* Look through the symbol list for an entry. The entries are stored *) (* alphabetically, so the search terminates when an entry is reached that *) (* is larger or equal to the on we are looking for, equal is returned as 0 *) (* if the entry already exists, with ptr pointing before it, else ptr *) (* points to before where is should be. *) VAR ptr:list_p; found:BOOLEAN; test:INTEGER; BEGIN ptr:=list_head; found:=FALSE; WHILE (ptr^.lbllnk<>NIL) AND (NOT found) DO test:=compar(lbl,ptr^.lbllnk^.lbltxt); IF test<>1 THEN found:=TRUE; (* ptr points to the entry to be inserted after *) ELSE ptr:=ptr^.lbllnk; (* ie, lbl is still greater than next entry *) END; END; equal:=test; RETURN ptr; END looklbl; PROCEDURE compar(label1,label2:Label):INTEGER; (* This compares the two labels. If equal, returns 0. If label1label2, returns 1.*) VAR p:INTEGER; BEGIN p:=0; REPEAT p:=p+1; UNTIL (p=7) OR (label1[p-1]<>label2[p-1]) OR (label1[p-1]=0c) OR (label2[p-1]=0c); (* Move along until the two labels don't match *) IF label1[p-1]=label2[p-1] THEN RETURN 0; END; (* Equal *) IF (label1[p-1]=0c) OR (label1[p-1]