|
|
DataMuseum.dkPresents historical artifacts from the history of: DANOSI |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DANOSI Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - download
Length: 35840 (0x8c00)
Types: TextFile
Names: »CROSS.ORG«
└─⟦e2123b2a1⟧ Bits:30010498 DVBS1.SW2103.src.1.8-1 Pascal TOOLS JTAS 1989-04-26 LEIF NIELSEN E.d.
└─⟦this⟧ »CROSS.ORG«
MODULE cross;\r
\r
$include(pscplm.ext)\r
$include(pscudi.ext)\r
$include(rtp86rmx.ext)\r
\r
PROGRAM cross;\r
(* version 84.08.22 *)\r
LABEL\r
9999; (* exit point *)\r
\r
CONST\r
test_output= false;\r
hashsize= 2039; (* 85 04 23 changed from 1373 *)\r
(* 88 08 05 changed from 1579 *)\r
default_maxline= 46;\r
default_max_columns= 15;\r
default_no_of_keywords= 48;\r
maxq= 35; (* maximum number of queued names *)\r
sp= ' ';\r
ff= 12;\r
space= 32;\r
blank= ' ';\r
alfalength= 12;\r
\r
TYPE\r
alfa= PACKED ARRAY [1..alfalength] OF char;\r
usestate= ( declaration, assign, labeldef, otheruse );\r
options= (dummy_opt, title_option, keywords_, nokeywords,\r
include_, noinclude, head_option, nohead_option, error_);\r
whats= (keyword, identifier);\r
hashindex= 0..hashsize;\r
\r
occptr= ^ occ_list;\r
prestname= ^restname;\r
\r
occ_list= PACKED RECORD\r
where: word;\r
usekind: usestate;\r
next: occptr\r
END;\r
\r
\r
restname= RECORD\r
next: prestname;\r
namepart: alfa;\r
END;\r
\r
hashrec= PACKED RECORD\r
id: alfa;\r
restofname: prestname;\r
following: hashindex;\r
CASE what: whats OF\r
identifier: (first, last: occptr);\r
keyword: (key_occ: integer);\r
END;\r
\r
hashc = RECORD\r
CASE con:integer OF\r
1: (int: integer);\r
2: (al : alfa)\r
END;\r
\r
VAR\r
option_text: ARRAY [options] OF alfa;\r
prio: byte;\r
exc: word;\r
\r
skipend, (* if eof infil then nextsymbol:= skipend *)\r
skipend1,\r
symbol: char;\r
table_full_at_line,\r
step, (* temporary variable used in for-statements *)\r
brackcount, (* counting number of unsatisfied left brackets *)\r
blockcount, (* begin-counter *)\r
othercount, (* record and case-statement counter *)\r
pasline, (* pascal line number *)\r
pagenumber,\r
linenumber: integer; (* number of lines on this page *)\r
current_date,\r
current_time,\r
title , (* input file name used as default heading on outputfil *)\r
newid: alfa;\r
\r
\r
currentnode,\r
occurrence: occptr;\r
hashconv: hashc;\r
top: hashindex;\r
keywordtop: hashindex;\r
\r
hash_table: ARRAY[hashindex] OF hashrec;\r
\r
inside_inclusion, (*if true then read from includefile *)\r
inclusion, (* option include/exclude externals *)\r
header, (* option header/noheader, if header then add printerheader *)\r
outputfile,\r
before_program,\r
endline: boolean;\r
opmess, (* opened to:co: for messages *)\r
outputfil, (* result file *)\r
include_file, (* file with externals or text to be incorporated during compilation *) \r
infil: text; (* input file to be cross referenced *)\r
incl_path: string;\r
incl_path_alfa, outpfile, inpfile: path_alfa;\r
\r
idlength: integer;\r
\r
current_name, (* current chunk *)\r
startofcurrent: prestname; (* start of current chunk chain *)\r
\r
alfanum: SET OF char;\r
\r
lastqueued: 0..maxq;\r
queue: ARRAY [1..maxq] OF occptr;\r
maxline, max_columns, no_of_keywords: integer;\r
\r
\r
\r
FUNCTION insert_id(nid: alfa; ide: whats): occptr; FORWARD;\r
\r
PROCEDURE error(e_text: alfa);\r
BEGIN\r
writeln(opmess, ' *** CROSS ERROR *** ', e_text);\r
GOTO 9999; (* exit program *)\r
END; (* error *)\r
\r
\r
\r
\r
PROCEDURE read_call_parameters;\r
CONST\r
e_ok = 0;\r
cr= 13;\r
\r
VAR\r
step, step1: integer;\r
d, key: byte;\r
e: word;\r
key_string,\r
inp_path, outp_path: string;\r
\r
PROCEDURE check_argument(d,key: byte;e: word);\r
BEGIN\r
\r
IF test_output THEN\r
writeln(opmess,'delim: ',d,' key: ',key);\r
\r
IF (e<>e_ok) OR\r
((d<>cr) AND (d<>space)) OR\r
(key = ord(error_)) THEN\r
BEGIN\r
writeln(opmess,'key: ',key:3);\r
error('argument err');\r
END;\r
END (*check_argument*);\r
\r
\r
BEGIN (** body of READ_PARAMS **)\r
\r
d:= get_argument(inp_path,key,e);\r
check_argument(d,key,e);\r
\r
(* default title *)\r
title:= blank;\r
IF test_output THEN\r
writeln(opmess, 'input path: ', inp_path.alfa: inp_path.length);\r
step:= inp_path.length;\r
WHILE (inp_path.alfa[step]<>':') AND (inp_path.alfa[step]<>'/') AND (step>1) DO\r
step:= step-1;\r
IF step=1 THEN\r
step:= 0;\r
FOR step1:= 1 TO inp_path.length-step DO\r
IF step1<=alfalength THEN\r
title[step1]:= inp_path.alfa[step+step1];\r
\r
IF file_exist(inp_path) THEN\r
BEGIN (* open inp-file *)\r
path_to_alfa(inp_path,inpfile);\r
reset(infil,inpfile);\r
END\r
ELSE\r
BEGIN\r
(* try file with default extension: ind *)\r
change_ext(inp_path, key_string, 'IND ');\r
IF file_exist(key_string) THEN\r
BEGIN (* open inp-file *)\r
path_to_alfa(key_string,inpfile);\r
reset(infil,inpfile);\r
END\r
ELSE\r
BEGIN (* non existent input file, stop program *)\r
writeln(opmess,inp_path.alfa:inp_path.length);\r
error('E$F_N_EXIST ');\r
END;\r
END; (* inp_path not found *)\r
\r
\r
(** set up default-outputfile **)\r
change_ext(inp_path,outp_path,'CRL ');\r
\r
(* open outputfile *)\r
path_to_alfa(outp_path,outpfile);\r
rewrite(outputfil, outpfile);\r
\r
WHILE d = space (*delimiter telling there are more arguments*) DO\r
BEGIN\r
d:= get_argument(key_string, key, e);\r
check_argument(d, key, e);\r
CASE options(key) OF\r
title_option: BEGIN\r
d:= get_argument(key_string, key, e);\r
check_argument(d, key, e);\r
IF test_output THEN writeln(opmess, 'option: title ',\r
key_string.alfa:key_string.length);\r
title:= blank;\r
IF key_string.length>alfalength THEN\r
key_string.length:= alfalength;\r
FOR step:= 1 TO key_string.length DO\r
title[step]:= key_string.alfa[step];\r
END;\r
\r
keywords_: BEGIN\r
no_of_keywords:= default_no_of_keywords;\r
IF test_output THEN writeln(opmess, 'option: keywords');\r
END;\r
\r
nokeywords: BEGIN\r
no_of_keywords:= 0;\r
IF test_output THEN writeln(opmess, 'option: nokeywords');\r
END;\r
\r
include_,\r
noinclude: inclusion:= options(key)=include_;\r
\r
head_option,\r
nohead_option: header:= options(key)=head_option;\r
\r
OTHERWISE BEGIN\r
writeln(opmess,key_string.alfa:key_string.length);\r
error('ill. option:');\r
END;\r
\r
END; (* case *)\r
\r
END; (*while*)\r
\r
END (* READ_CALLPARAMS *);\r
\r
\r
PROCEDURE init;\r
TYPE\r
string40= PACKED ARRAY [1..40] OF char;\r
\r
VAR\r
opt: options;\r
input_met: boolean;\r
int, int1, sys, sys1, paramno, (* variables for call interpretation *)\r
step, ii, i,j: integer;\r
id, id1: alfa;\r
tail: ARRAY [1..10] OF integer; (* for the entry tail *)\r
keywords: ARRAY[1..default_no_of_keywords] OF alfa;\r
\r
\r
PROCEDURE output_header;\r
CONST\r
lines= 14;\r
VAR\r
step: integer;\r
BEGIN\r
FOR step:= 1 TO lines DO\r
writeln(outputfil, '******************************');\r
FOR step:= 1 TO lines DO\r
writeln(outputfil, ' ': 30, title, ' ', current_date, current_time);\r
FOR step:= 1 TO lines DO\r
writeln(outputfil, '******************************');\r
END; (* output header *)\r
\r
PROCEDURE date_and_time(VAR date_alfa, time_alfa: alfa);\r
CONST\r
e_ok= 0;\r
VAR\r
d_t: coded_time;\r
exc: word;\r
step: integer;\r
BEGIN\r
exc:= e_ok;\r
WITH d_t DO\r
BEGIN\r
WITH system_time DO\r
BEGIN\r
word1:= 0; word2:= 0; (* get date and time *)\r
END; (* with dword *)\r
dqdecodetime(d_t, exc);\r
IF exc<>e_ok THEN error('dqdecodetime');\r
writeln(opmess, ' RC 3900 CROSS REFERENCE PROGRAM ');\r
write(opmess, 'date: ');\r
FOR step:= 1 TO 8 DO\r
write(opmess, date[step]);\r
write(opmess, ' time: ');\r
FOR step:= 1 TO 8 DO\r
write(opmess, time[step]);\r
writeln(opmess);\r
write(opmess, 'page: 0');\r
\r
date_alfa:= blank; time_alfa:= blank;\r
date_alfa[1]:= date[7]; date_alfa[2]:= date[8]; (* year *)\r
date_alfa[3]:= '.';\r
FOR step:= 4 TO 8 DO\r
date_alfa[step]:= date[step-3];\r
date_alfa[6]:= '.';\r
FOR step:= 1 TO 8 DO\r
time_alfa[step]:= time[step];\r
time_alfa[3]:= '.'; time_alfa[6]:= '.';\r
END; (* with *)\r
END; (* date and time *)\r
\r
\r
BEGIN\r
rewrite(opmess, ':CO:');\r
\r
date_and_time(current_date, current_time); (* get current date and time *)\r
\r
init_argument;\r
option_text[title_option]:= 'TITLE ';\r
option_text[keywords_]:= 'KEYWORDS ';\r
option_text[nokeywords]:= 'NOKEYWORDS ';\r
option_text[include_]:= 'INCLUDE ';\r
option_text[noinclude]:= 'NOINCLUDE ';\r
option_text[head_option]:= 'HEAD ';\r
option_text[nohead_option]:= 'NOHEAD ';\r
\r
FOR opt:= succ(dummy_opt) TO pred(error_) DO\r
j:= insert_key(option_text[opt]);\r
\r
\r
(* initialize global variables *)\r
inside_inclusion:= false;\r
inclusion:= true;\r
header:= true;\r
brackcount:= 0;\r
blockcount:= 0;\r
othercount:= 0;\r
pasline:= 0;\r
pagenumber:= 0;\r
newid:= blank; (* be ready for a new name *)\r
idlength:= 0; (* current name is empty *)\r
current_name:= nil; (* no chunks are in use *)\r
startofcurrent:= nil; (* current chain of chunks is empty *)\r
top:= hashsize; (* hashsize is stopmark for the lists ( one list of keywords \r
and one list of identifiers) *)\r
outputfile:= false;\r
endline:= true;\r
\r
alfanum:= ['a'..'z', 'A'..'Z', '0'..'9', '$', '_'] ;\r
\r
lastqueued:= 0; (* empty queue *)\r
FOR step:= 1 TO maxq DO\r
queue [step]:= nil;\r
\r
currentnode:= nil;\r
\r
table_full_at_line:= -1;\r
no_of_keywords:= default_no_of_keywords;\r
FOR i:= 0 TO hashsize DO\r
hash_table[i].id:= blank;\r
step:= 1;\r
keywords [step]:= 'WITH '; step:= step+1;\r
keywords [step]:= 'WHILE '; step:= step+1;\r
keywords [step]:= 'VAR '; step:= step+1;\r
keywords [step]:= 'UNTIL '; step:= step+1;\r
keywords [step]:= 'TYPE '; step:= step+1;\r
keywords [step]:= 'TO '; step:= step+1;\r
keywords [step]:= 'THEN '; step:= step+1;\r
keywords [step]:= 'SHARED '; step:= step+1;\r
keywords [step]:= 'SET '; step:= step+1;\r
keywords [step]:= 'REPEAT '; step:= step+1;\r
keywords [step]:= 'RECORD '; step:= step+1;\r
keywords [step]:= 'PUBLIC '; step:= step+1;\r
keywords [step]:= 'PROGRAM '; step:= step+1;\r
keywords [step]:= 'PROCEDURE '; step:= step+1;\r
keywords [step]:= 'PRIVATE '; step:= step+1;\r
keywords [step]:= 'PACKED '; step:= step+1;\r
keywords [step]:= 'OTHERWISE '; step:= step+1;\r
keywords [step]:= 'OR '; step:= step+1;\r
keywords [step]:= 'OF '; step:= step+1;\r
keywords [step]:= 'NOT '; step:= step+1;\r
keywords [step]:= 'MODULE '; step:= step+1;\r
keywords [step]:= 'MOD '; step:= step+1;\r
keywords [step]:= 'LOOP '; step:= step+1;\r
keywords [step]:= 'LOCK '; step:= step+1;\r
keywords [step]:= 'LABEL '; step:= step+1;\r
keywords [step]:= 'IN '; step:= step+1;\r
keywords [step]:= 'IF '; step:= step+1;\r
keywords [step]:= 'GOTO '; step:= step+1;\r
keywords [step]:= 'FUNCTION '; step:= step+1;\r
keywords [step]:= 'FORWARD '; step:= step+1;\r
keywords [step]:= 'FOR '; step:= step+1;\r
keywords [step]:= 'FILE '; step:= step+1;\r
keywords [step]:= 'EXTERNAL '; step:= step+1;\r
keywords [step]:= 'EXITLOOP '; step:= step+1;\r
keywords [step]:= 'EXIT '; step:= step+1;\r
keywords [step]:= 'ENDLOOP '; step:= step+1;\r
keywords [step]:= 'END '; step:= step+1;\r
keywords [step]:= 'ELSE '; step:= step+1;\r
keywords [step]:= 'DOWNTO '; step:= step+1;\r
keywords [step]:= 'DO '; step:= step+1;\r
keywords [step]:= 'DIV '; step:= step+1;\r
keywords [step]:= 'CONTINUELOOP'; step:= step+1;\r
keywords [step]:= 'CONST '; step:= step+1;\r
keywords [step]:= 'CASE '; step:= step+1;\r
keywords [step]:= 'BEGIN '; step:= step+1;\r
keywords [step]:= 'AS '; step:= step+1;\r
keywords [step]:= 'ARRAY '; step:= step+1;\r
keywords [step]:= 'AND ';\r
\r
(* default settings *)\r
maxline:= default_maxline;\r
max_columns:= default_max_columns;\r
\r
linenumber:= maxline; (* force newpage at start *)\r
\r
read_call_parameters;\r
\r
before_program:= false; (* do not remove the keywords *)\r
\r
FOR i:= 1 TO no_of_keywords DO\r
currentnode:= insert_id( keywords [i], keyword );\r
keywordtop:= top;\r
top:= hashsize;\r
\r
before_program:= true; (* decide on which keys to remove from now on *)\r
\r
IF header THEN\r
output_header;\r
\r
END;\r
\r
\r
PROCEDURE newpage;\r
BEGIN\r
page(outputfil);\r
pagenumber:= pagenumber+1;\r
write(outputfil, title, sp, current_date, current_time);\r
write(outputfil, 'page':50, pagenumber: 6);\r
writeln(outputfil);\r
writeln(outputfil);\r
linenumber:= 0;\r
write(opmess, chr(8), chr(8), chr(8), pagenumber:3);\r
END;\r
\r
\r
PROCEDURE checkbracket;\r
(* check: (brackcount=0) and (blockcount>0 ) *)\r
BEGIN\r
IF (blockcount>0) AND (brackcount<>0) THEN\r
BEGIN\r
writeln(opmess,'??? error in bracket structure, detected at line: ',\r
pasline: 6 );\r
brackcount:= 0; (* recover *)\r
END;\r
END; (* check bracket *)\r
\r
\r
\r
FUNCTION lookahead: char;\r
(* return next character of current input file, without reading *)\r
BEGIN\r
IF inside_inclusion THEN\r
lookahead:= include_file^\r
ELSE\r
lookahead:= infil^;\r
END;\r
\r
\r
PROCEDURE nextsymbol;\r
(* return next symbol in global variable 'symbol' *)\r
BEGIN\r
IF inside_inclusion THEN\r
BEGIN\r
IF eof(include_file) THEN\r
BEGIN\r
inside_inclusion:= false;\r
writeln(opmess); (* indicate end of include *)\r
write(opmess, 'page: ', pagenumber:3);\r
\r
symbol:= sp; (* dummy *)\r
END\r
ELSE\r
read(include_file, symbol);\r
END (* inside inclusion *)\r
ELSE (* normal reading *)\r
BEGIN\r
IF endline THEN\r
BEGIN\r
IF linenumber=maxline THEN newpage;\r
linenumber:= linenumber+1;\r
pasline:= pasline+1;\r
write(outputfil,pasline:5);\r
END;\r
IF eoln(infil) THEN\r
BEGIN\r
IF (infil^=chr(ff)) THEN \r
BEGIN\r
linenumber:= maxline; (* force newpage at next nl *)\r
endline:= false;\r
END\r
ELSE\r
BEGIN\r
endline:= true;\r
writeln(outputfil);\r
END;\r
\r
END\r
ELSE endline:= false;\r
(* LINENUMBER IS INCREMENTED JUST BEFORE READING THE\r
FIRST CHARACTER ON THE NEW LINE *)\r
IF eof(infil) THEN\r
symbol:= skipend\r
ELSE\r
read(infil, symbol);\r
\r
IF NOT endline AND (symbol>=' ') THEN write(outputfil,symbol);\r
END; (* normal input *)\r
\r
IF (symbol>='a') AND (symbol<='z') THEN\r
symbol:= chr(ord(symbol)-ord('a')+ord('A'));\r
END;\r
\r
\r
PROCEDURE remove_non_keys( VAR which_kind: alfa );\r
CONST\r
last_non_pascal=5; (* index in table of names to remove *)\r
no_of_non_pascal80=4;\r
VAR\r
d: integer; (* help variable in case of rehash *)\r
h: hashindex;\r
start_delete, end_delete, (* step limits *)\r
step: integer;\r
special_keys: ARRAY [1..9 (* total number of special keys *)] OF alfa;\r
\r
BEGIN\r
before_program:= false;\r
FOR step:= 1 TO 9 DO\r
CASE step OF\r
1: special_keys [step]:= 'AS ';\r
2: special_keys [step]:= 'LOCK ';\r
3: special_keys [step]:= 'PREFIX ';\r
4: special_keys [step]:= 'PROCESS ';\r
5: special_keys [step]:= 'CHANNEL ';\r
\r
(* non rtp keywords *)\r
6: special_keys [step]:= 'FILE ';\r
7: special_keys [step]:= 'VALUE ';\r
8: special_keys [step]:= 'MODULE ';\r
9: special_keys [step]:= 'PROGRAM ';\r
END; (* case *)\r
\r
IF which_kind='PROGRAM ' THEN\r
BEGIN\r
start_delete:= 1;\r
end_delete:= last_non_pascal;\r
END\r
ELSE\r
BEGIN\r
start_delete:= last_non_pascal+1;\r
end_delete:= start_delete+no_of_non_pascal80-1;\r
END;\r
FOR step:= start_delete TO end_delete DO\r
BEGIN\r
hashconv.al:= special_keys [step];\r
h:= abs( hashconv.int ) MOD hashsize; (* the hashfunction !!! *)\r
d:= 1; (* start value of rehash variable *)\r
WHILE hash_table [h].id<>special_keys [step] DO\r
BEGIN\r
(* rehash *)\r
h:= ( h+d ) MOD hashsize; d:= d+2;\r
END;\r
(* replace the name with a non-identifier, i.e. the entry will not be used *)\r
hash_table [h].id:= '------------';\r
END; (* for ... *)\r
END; (* remove non keys *)\r
\r
\r
\r
FUNCTION insert_id (nid: alfa; ide: whats): occptr; (* forward declared *)\r
VAR found:boolean;\r
h:hashindex;\r
step,\r
d:integer;\r
\r
BEGIN\r
insert_id:= nil;\r
IF nid<>blank THEN\r
BEGIN\r
\r
IF (nid [1]>= '0') AND (nid [1]<= '9' ) THEN\r
(* right justify numbers *)\r
FOR step:= 0 TO idlength-1 DO\r
BEGIN\r
nid [alfalength-step]:= nid [idlength-step] ;\r
nid [idlength-step]:= sp;\r
END; (* right justify *)\r
hashconv.al:= nid;\r
h:= abs(hashconv.int) MOD hashsize;\r
(*THE 2 MOST SIGNIFICANT CHARACTERS ARE USED AS AN INTEGER*)\r
found:= false;\r
d:= 1;\r
REPEAT\r
WITH hash_table [h] DO\r
BEGIN\r
\r
IF id=nid THEN\r
IF (startofcurrent<>nil) AND (restofname<>nil) THEN\r
found:= startofcurrent^.namepart=restofname^.namepart\r
ELSE\r
found:= (startofcurrent=nil) AND (restofname=nil) ;\r
IF found THEN\r
BEGIN (*ALL OK*)\r
IF startofcurrent<>nil THEN dispose( startofcurrent );\r
CASE what OF\r
identifier: BEGIN\r
new(occurrence);\r
last^.next:= occurrence;\r
occurrence^.where:= pasline;\r
IF blockcount<>0 THEN\r
BEGIN\r
occurrence^.usekind:= otheruse;\r
IF brackcount=0 THEN\r
insert_id:= occurrence; (* candidate for change to assign *)\r
END\r
ELSE\r
occurrence^.usekind:= declaration;\r
\r
last:= occurrence;\r
END;\r
keyword : BEGIN\r
\r
hash_table[h].key_occ:= hash_table[h].key_occ+1;\r
IF nid='BEGIN ' THEN\r
BEGIN\r
blockcount:= blockcount+1;\r
checkbracket;\r
END\r
ELSE\r
IF nid='END ' THEN\r
BEGIN\r
IF othercount>0 THEN (*record or case match *)\r
othercount:= othercount-1\r
ELSE\r
IF blockcount>0 THEN\r
BEGIN (* begin-match *)\r
checkbracket;\r
blockcount:= blockcount-1;\r
END\r
ELSE writeln(opmess,'??? error in blockstructure, detected at line:',\r
pasline:6);\r
END\r
ELSE\r
IF (nid='THEN ') OR (nid='ELSE ')\r
OR (nid='DO ') OR (nid='OF ')\r
OR (nid='UNTIL ') THEN\r
checkbracket\r
\r
ELSE\r
IF (nid='RECORD ') THEN\r
othercount:= othercount+1\r
ELSE\r
IF nid ='CASE ' THEN\r
IF blockcount>0 THEN (* case-statement *)\r
othercount:= othercount+1;\r
END;\r
END;\r
END\r
ELSE\r
IF id=blank THEN\r
BEGIN (*MAKE NEW ENTRY*)\r
IF test_output THEN\r
IF d>1 THEN writeln(opmess, nid, d, ' collision');\r
\r
found:= true;\r
id:= nid;\r
restofname:= startofcurrent;\r
what:= ide;\r
CASE ide OF\r
identifier: BEGIN\r
new(occurrence);\r
first:= occurrence;\r
\r
last:= occurrence;\r
occurrence^.where:= pasline;\r
IF blockcount<>0 THEN\r
BEGIN\r
occurrence^.usekind:= otheruse;\r
IF brackcount=0 THEN\r
insert_id:= occurrence;\r
END\r
ELSE\r
occurrence^.usekind:= declaration;\r
\r
END;\r
keyword : BEGIN\r
hash_table[h].key_occ:= 0;\r
END\r
END;\r
hash_table[h].following:= top;\r
top:= h;\r
END\r
ELSE\r
BEGIN (*COLLISION*)\r
h:= (h+d) MOD hashsize; d:= d+2;\r
IF d=hashsize THEN\r
BEGIN (*TABLE QUASI-FULL*)\r
IF table_full_at_line=-1 THEN table_full_at_line:= pasline;\r
found:= true; (*WE DO NOT INSERT THE NID*)\r
IF startofcurrent<>nil THEN dispose ( startofcurrent ) ;\r
END;\r
END; (* collision *)\r
\r
END; (* with hashtable [h] *)\r
\r
UNTIL found;\r
END;\r
nid:= blank;\r
idlength:= 0;\r
current_name:= nil;\r
startofcurrent:= nil;\r
\r
END; (*INSERT_ID*)\r
\r
\r
PROCEDURE add_to_id(VAR newid:alfa; symbol:char);\r
VAR old: prestname;\r
BEGIN\r
IF idlength<alfalength THEN\r
BEGIN\r
idlength:= idlength+1;\r
newid[idlength]:= symbol;\r
END\r
ELSE\r
BEGIN\r
IF idlength MOD alfalength=0 THEN\r
BEGIN\r
(* get a new chunk *)\r
old:= current_name;\r
new( current_name );\r
current_name^.next:= nil;\r
current_name^.namepart:= blank;\r
IF old<>nil THEN\r
old^.next:= current_name\r
ELSE (* first element after the head *)\r
startofcurrent:= current_name;\r
END;\r
\r
current_name^.namepart [(idlength MOD alfalength)+1]:= symbol;\r
idlength:= idlength+1;\r
\r
END;\r
\r
END;\r
\r
\r
\r
\r
\r
PROCEDURE sort_table;\r
VAR i,j,least:integer;\r
beforei,beforej,beforeleast:-1..hashsize;\r
nextid:alfa;\r
BEGIN\r
i:= top;\r
beforei:= -1;\r
WHILE i<hashsize DO\r
BEGIN\r
nextid:= hash_table[i].id;\r
least:= i;\r
beforeleast:= -1; beforej:= i;\r
j:= hash_table[i].following;\r
WHILE j<hashsize DO\r
BEGIN\r
IF hash_table[j].id<nextid THEN\r
BEGIN\r
least:= j;\r
nextid:= hash_table[j].id;\r
beforeleast:= beforej;\r
END;\r
beforej:= j;\r
j:= hash_table[j].following;\r
END;\r
(*CHANGE POINTERS*)\r
IF beforeleast>-1 THEN\r
BEGIN\r
hash_table[beforeleast].following\r
:= hash_table[least].following;\r
hash_table[least].following:= i;\r
IF beforei>-1 THEN\r
hash_table[beforei].following:= least\r
ELSE top:= least;\r
(*WE KEEP THE I*)\r
beforei:= least;\r
END\r
ELSE\r
BEGIN (*HASH_TABLE[I] WAS THE LEAST*)\r
IF beforei=-1 THEN top:= i;\r
beforei:= i;\r
i:= hash_table[i].following;\r
END;\r
\r
END; (*I<HASHSIZE*)\r
END;\r
\r
\r
PROCEDURE print_table;\r
VAR l,i:integer;\r
length_of_name: integer; (* number of alfas in a name *)\r
x: occptr;\r
\r
PROCEDURE writealfa( alf: alfa );\r
(* write the parameter with small letters *)\r
VAR step: integer;\r
BEGIN\r
FOR step:= 1 TO alfalength DO\r
IF (alf [step]>= 'A') AND (alf [step]<= 'Z') THEN\r
write(outputfil, chr( ord( alf [step] )+32 ) )\r
ELSE\r
write(outputfil, alf [step] );\r
END; (* writealfa *)\r
\r
\r
BEGIN\r
i:= top;\r
linenumber:= maxline; (* force a new page *)\r
WHILE i<hashsize DO\r
BEGIN\r
(* CLOSE END OF OCC_LIST *)\r
hash_table[i].last^.next:= nil;\r
IF linenumber>maxline-3 THEN\r
newpage; (* reserve room for at least 2 lines *)\r
length_of_name:= 1; (* at least one alfa *)\r
writealfa(hash_table [i].id );\r
current_name:= hash_table [i].restofname;\r
WHILE current_name<>nil DO\r
WITH current_name^ DO\r
BEGIN\r
length_of_name:= length_of_name+1;\r
writealfa( namepart );\r
current_name:= next;\r
END;\r
\r
IF hash_table [i].restofname<>nil THEN\r
BEGIN\r
write(outputfil, cr, lf, sp: alfalength );\r
linenumber:= linenumber+1;\r
END;\r
\r
l:= 0;\r
x:= hash_table[i].first;\r
REPEAT\r
IF l=max_columns THEN\r
BEGIN\r
writeln(outputfil);\r
linenumber:= linenumber+1;\r
IF (linenumber MOD maxline)=0 THEN newpage;\r
write(outputfil, sp: alfalength );\r
l:= 0;\r
END;\r
write(outputfil,(x^.where):5);\r
CASE x^.usekind OF\r
declaration: write(outputfil, '*');\r
assign : write(outputfil, '=');\r
labeldef : write(outputfil, ':');\r
otheruse : write(outputfil, sp);\r
END; (* case *)\r
\r
l:= l+1;\r
x:= x^.next;\r
UNTIL x=nil;\r
writeln(outputfil);\r
linenumber:= linenumber+1;\r
i:= hash_table[i].following;\r
END;\r
\r
IF no_of_keywords<>0 THEN\r
BEGIN\r
i:= keywordtop;\r
newpage;\r
WHILE i<hashsize DO\r
BEGIN\r
IF hash_table[i].key_occ>0 THEN\r
writeln(outputfil,hash_table[i].id,hash_table[i].key_occ:8);\r
i:= hash_table[i].following;\r
END;\r
END; (* key word table *)\r
END;\r
\r
\r
(*HOVEDPROGRAM*)\r
BEGIN\r
init;\r
skipend:= sp;\r
\r
REPEAT\r
nextsymbol;\r
\r
IF symbol IN alfanum THEN\r
BEGIN\r
IF symbol='$' THEN\r
BEGIN (* skip possible spaces between leading '$' and option name *)\r
add_to_id(newid, symbol);\r
REPEAT\r
nextsymbol;\r
UNTIL symbol<>sp;\r
END;\r
\r
WHILE symbol IN alfanum DO\r
BEGIN\r
add_to_id( newid, symbol );\r
nextsymbol;\r
END;\r
\r
IF (newid='$INCLUDE ') AND inclusion AND NOT inside_inclusion THEN\r
BEGIN\r
incl_path.length:= 0;\r
WHILE symbol<>'(' DO\r
nextsymbol;\r
nextsymbol;\r
WITH incl_path DO\r
WHILE symbol<>')' DO\r
BEGIN (* pick up name of file to be included *)\r
IF symbol<>sp THEN\r
BEGIN\r
length:= length+1;\r
alfa[length]:= symbol;\r
END;\r
nextsymbol;\r
END; (* while *)\r
IF file_exist(incl_path) THEN\r
BEGIN (* start of alternative input file *)\r
WITH incl_path DO\r
IF alfa[1]=':' THEN\r
IF (alfa[2]<>'S') OR (alfa[3]<>'D') THEN\r
BEGIN\r
FOR step:= length DOWNTO 2 DO\r
alfa[step+3]:= alfa[step];\r
length:= length+3;\r
alfa[2]:= 'S'; alfa[3]:= 'D'; alfa[4]:= ':';\r
step:= 5;\r
WHILE alfa[step]<>':' DO step:= step+1;\r
alfa[step]:='/';\r
END; (* insert:SD: *)\r
\r
path_to_alfa(incl_path, incl_path_alfa);\r
writeln(opmess);\r
write(opmess, '$include(', incl_path.alfa: incl_path.length, ')');\r
reset(include_file, incl_path_alfa);\r
inside_inclusion:= true;\r
END (* file exist *)\r
ELSE\r
WITH incl_path DO\r
writeln(opmess, 'include(', alfa: length, ') not possible');\r
\r
symbol:= sp;\r
END; (* $include met *)\r
\r
currentnode:= insert_id( newid, identifier);\r
newid:= blank;\r
IF currentnode<>nil THEN\r
BEGIN (* queue the element *)\r
IF lastqueued<maxq THEN\r
lastqueued:= lastqueued+1\r
ELSE \r
writeln(opmess, ' constant maxq too small ');\r
\r
queue [lastqueued]:= currentnode;\r
\r
END (* queue *)\r
\r
ELSE\r
\r
IF brackcount=0 THEN\r
lastqueued:= 0; (* empty the queue *)\r
\r
\r
END; (* symbol in alfanum *)\r
\r
\r
CASE symbol OF\r
sp, ',', '!': (* no action *) ;\r
\r
':': (* mark the queued elements as 'assign' or 'labeldef' *)\r
BEGIN\r
IF brackcount=0 THEN\r
BEGIN\r
FOR step:= 1 TO lastqueued DO\r
IF queue [step]<>nil THEN\r
WITH queue [step]^ DO\r
IF lookahead='=' THEN\r
usekind:= assign\r
ELSE\r
usekind:= labeldef;\r
\r
(* empty the queue *)\r
lastqueued:= 0;\r
\r
END; (* if brackcount=0 *)\r
\r
END; (* colon *)\r
\r
'"', '''': (* skip the string *)\r
BEGIN\r
skipend:= symbol;\r
\r
REPEAT\r
nextsymbol;\r
UNTIL symbol=skipend;\r
\r
END; (* string *)\r
\r
'(', '[', '<': (* prepare comment or push level *)\r
BEGIN\r
skipend:= symbol;\r
\r
IF (lookahead='*') AND (skipend<>'[') THEN\r
(* comment *)\r
BEGIN\r
nextsymbol;\r
\r
IF skipend='(' THEN\r
skipend1:= ')'\r
ELSE\r
skipend1:= '>';\r
\r
nextsymbol;\r
REPEAT\r
skipend:= '*'; (* prepare end-while in case of eof *)\r
WHILE symbol<>skipend DO\r
nextsymbol;\r
\r
skipend:= skipend1; (* prepare end-repeat in case of eof *)\r
nextsymbol;\r
UNTIL symbol=skipend;\r
\r
END (* comment *)\r
\r
ELSE\r
\r
IF symbol<>'<' THEN\r
(* push bracket level *)\r
brackcount:= brackcount+1\r
ELSE (* '<' as an operator *)\r
IF brackcount=0 THEN\r
lastqueued:= 0; (* mark the queue as otheruse *)\r
\r
END; (* left bracket *)\r
\r
')', ']': (* not '>' *)\r
(* unstack bracket level *)\r
brackcount:= brackcount-1;\r
\r
';': (* syntax check and recovery *)\r
(* if not declaration part then brackcount must be 0 *)\r
BEGIN\r
checkbracket;\r
lastqueued:= 0; (* empty the queue, the elements are marked as otheruse *)\r
END;\r
\r
OTHERWISE\r
(* anything else *)\r
(* empty the queue, the elements are marked as otheruse *)\r
IF brackcount=0 THEN\r
lastqueued:= 0;\r
END; (* case *)\r
\r
UNTIL eof(infil);\r
\r
\r
sort_table;\r
print_table;\r
\r
9999: (* exit label *)\r
\r
writeln(opmess);\r
IF table_full_at_line<>-1 THEN\r
writeln(opmess,cr,lf,lf,lf,'***** warning: hash table overflow at line: '\r
,table_full_at_line:1 );\r
END.\r
«eof»