xref: /csrg-svn/usr.bin/pascal/pxref/pxref.p (revision 62199)
122268Sdist(*
2*62199Sbostic * Copyright (c) 1980, 1993
3*62199Sbostic *	The Regents of the University of California.  All rights reserved.
423654Smckusick *
548114Sbostic * %sccs.include.redist.c%
648114Sbostic *
7*62199Sbostic *	@(#)pxref.p	8.1 (Berkeley) 06/06/93
822268Sdist *)
922268Sdist
102843Swnj{$t-,p-,b2,w+}
112843Swnjprogram xref(input, output);
122843Swnjlabel
132843Swnj    99, 100;
142843Swnjconst
152843Swnj    alfasize = 18;
162843Swnj    linesize = 10;
172843Swnj    namesize = 64;
182843Swnj    linelength = 133;
192843Swnj    maxlineno = 30000;
202843Swnj    charclassize = 127;
212843Swnj    p = 1000;
222843Swnj    nk = 36;
232843Swnj    blanks = '  ';
242843Swnjtype
252843Swnj    alfa =
262843Swnj      array[1..alfasize] of
272843Swnj	char;
282843Swnj    index = 0..p;
292843Swnj    linptr = 0..linelength;
302843Swnj    linebuf = array[1..linelength] of char;
312843Swnj    ref = ^item;
322843Swnj    filename = array [1..namesize] of char;
332843Swnj    charclasses = (digit, letter, separator, illegal);
342843Swnj    charclasstype = array[0..charclassize] of charclasses;
352843Swnj    word =
362843Swnj      record
372843Swnj	key: alfa;
382843Swnj	first, last: ref;
392843Swnj	fol: index
402843Swnj      end;
412843Swnj    item =   packed
422843Swnj      record
432843Swnj	lno: 0..maxlineno;
442843Swnj	next: ref
452843Swnj      end;
462843Swnjvar
472843Swnj    i, top: index;
482843Swnj    formfeed :char;
492843Swnj    scr: alfa;
502843Swnj    list: boolean;
512843Swnj    k, k1: integer;
522843Swnj    n: integer;
532843Swnj    c1, c2: integer;
542843Swnj    inputfile : filename;
552843Swnj    lineptr :linptr;
562843Swnj    line :linebuf;
572843Swnj    charclass :charclasstype;
582843Swnj    id:
592843Swnj      record
602843Swnj	case boolean of
612843Swnj	  false:(
622843Swnj	    a: alfa
632843Swnj	  );
642843Swnj	  true:(
652843Swnj	    ord: integer
662843Swnj	  )
672843Swnj      end;
682843Swnj    a: array [1..alfasize] of char;
692843Swnj    t: array [index] of word;
702843Swnj    key: array [1..nk] of alfa;
712843Swnj    empty: alfa;
722843Swnj
732843Swnj    function nokey(x: alfa): Boolean;
742843Swnj    var
752843Swnj	i, j, k: integer;
762843Swnj    begin
772843Swnj	i := 1;
782843Swnj	j := nk;
792843Swnj	repeat
802843Swnj	    k := (i + j) div 2;
812843Swnj	    if key[k] <= x then
822843Swnj		i := k + 1;
832843Swnj	    if key[k] >= x then
842843Swnj		j := k - 1
852843Swnj	until i > j;
862843Swnj	nokey := key[k] <> x
872843Swnj    end { nokey };
882843Swnj
892843Swnj    procedure search;
902843Swnj    var
912843Swnj	h, d: index;
922843Swnj	x: ref;
932843Swnj	f: Boolean;
942843Swnj    begin
952843Swnj	h := id.ord div 4096 mod p;
962843Swnj	f := false;
972843Swnj	d := 1;
982843Swnj	c2 := c2 + 1;
992843Swnj	new(x);
1002843Swnj	x^.lno := n;
1012843Swnj	x^.next := nil;
1022843Swnj	repeat
1032843Swnj	    if t[h].key = id.a then begin
1042843Swnj		f := true;
1052843Swnj		t[h].last^.next := x;
1062843Swnj		t[h].last := x
1072843Swnj	    end else if t[h].key = empty then begin
1082843Swnj		f := true;
1092843Swnj		c1 := c1 + 1;
1102843Swnj		t[h].key := id.a;
1112843Swnj		t[h].first := x;
1122843Swnj		t[h].last := x;
1132843Swnj		t[h].fol := top;
1142843Swnj		top := h
1152843Swnj	    end else begin
1162843Swnj		h := (h + d) mod p;
1172843Swnj		d := d + 2;
1186043Smckusic		if d >= p then begin
1192843Swnj		    writeln;
1202843Swnj		    writeln(' **** table full');
1212843Swnj		    goto 99
1222843Swnj		end
1232843Swnj	    end
1242843Swnj	until f
1252843Swnj    end { search };
1262843Swnj
1272843Swnj    procedure printword(w: word);
1282843Swnj    var
1292843Swnj	l: integer;
1302843Swnj	x: ref;
1312843Swnj    begin
1322843Swnj	write(' ', w.key);
1332843Swnj	x := w.first;
1342843Swnj	l := 0;
1352843Swnj	repeat
1362843Swnj	    if l = linesize then begin
1372843Swnj		l := 0;
1382843Swnj		writeln;
1392843Swnj		write(' ', empty)
1402843Swnj	    end;
1412843Swnj	    l := l + 1;
1422843Swnj	    write(x^.lno: 6);
1432843Swnj	    x := x^.next
1442843Swnj	until x = nil;
1452843Swnj	writeln
1462843Swnj    end { printword };
1472843Swnj
1482843Swnj    procedure printtable;
1492843Swnj    var
1502843Swnj	i, j, m: index;
1512843Swnj    begin
1522843Swnj	i := top;
1532843Swnj	while i <> p do begin
1542843Swnj	    m := i;
1552843Swnj	    j := t[i].fol;
1562843Swnj	    while j <> p do begin
1572843Swnj		if t[j].key < t[m].key then
1582843Swnj		    m := j;
1592843Swnj		j := t[j].fol
1602843Swnj	    end;
1612843Swnj	    printword(t[m]);
1622843Swnj	    if m <> i then begin
1632843Swnj		t[m].key := t[i].key;
1642843Swnj		t[m].first := t[i].first;
1652843Swnj		t[m].last := t[i].last
1662843Swnj	    end;
1672843Swnj	    i := t[i].fol
1682843Swnj	end
1692843Swnj    end { printtable };
1702843Swnj
1712843Swnj    procedure readinput(var inpfile :filename);
1722843Swnj    var
1732843Swnj    inp :file of char;
1742843Swnj
1752843Swnj    procedure lwriteln;
1762843Swnj    begin
1772843Swnj	if list then begin
17815775Saoki	    { write sans trailing blanks }
17915775Saoki	    if lineptr > 0 then
18015775Saoki		writeln(line: lineptr)
18115775Saoki	    else
18215775Saoki		writeln;
1832843Swnj	end;
1842843Swnj	get(inp);
1852843Swnj	lineptr:=0
1862843Swnj    end { lwriteln };
1872843Swnj
1882843Swnj    procedure newline;
1892843Swnj    begin
1902843Swnj	n:=n+1;
1912843Swnj	if n = maxlineno then begin
1922843Swnj	    writeln(' text too long');
1932843Swnj	    goto 99
1942843Swnj	end;
1952843Swnj	if inp^ = formfeed then begin
1962843Swnj	    if list then
1972843Swnj		page(output);
1982843Swnj	    get(inp)
1992843Swnj	end;
2002843Swnj	if list then
2012843Swnj	    if not eoln(inp) then
2022843Swnj		write(n:6,'  ')
2032843Swnj    end { newline };
2042843Swnj
2052843Swnj    begin
2062843Swnj	reset(inp,inpfile);
2072843Swnj	while not eof(inp) do begin
2082843Swnj	    newline;
2092843Swnj	    if inp^ = '#' then begin
2102843Swnj		while inp^ <> '"' do begin
2112843Swnj		    lineptr:=lineptr+1;
2122843Swnj		    read(inp,line[lineptr])
2132843Swnj		end;
2142843Swnj		lineptr:=lineptr+1;
2152843Swnj		read(inp,line[lineptr]);
2162843Swnj		k:=0;
2172843Swnj		inputfile:=blanks;
2182843Swnj		repeat
2192843Swnj		    k:=k+1;
2202843Swnj		    if k <= namesize then
2212843Swnj			inputfile[k]:=inp^;
2222843Swnj		    lineptr:=lineptr+1;
2232843Swnj		    read(inp,line[lineptr])
2242843Swnj		until inp^ = '"';
2252843Swnj		while not eoln(inp) do begin
2262843Swnj		    lineptr:=lineptr+1;
2272843Swnj		    read(inp,line[lineptr])
2282843Swnj		end;
2292843Swnj		id.a := '#include';
2302843Swnj		search;
2312843Swnj		lwriteln;
2322843Swnj		readinput(inputfile);
2332843Swnj	    end else begin
2342843Swnj		while not eoln(inp) do begin
2352843Swnj		    if (inp^ = ' ') or (inp^ = tab) then begin
2362843Swnj			lineptr:=lineptr+1;
2372843Swnj			read(inp,line[lineptr])
2382843Swnj		    end else if charclass[ord(inp^)] = letter then begin
2392843Swnj		        k := 0;
2402843Swnj			a:=blanks;
2412843Swnj		        repeat
2422843Swnj			    k := k + 1;
2432843Swnj			    if k <= alfasize then
2442843Swnj			        a[k] := inp^;
2452843Swnj			    lineptr:=lineptr+1;
2462843Swnj			    read(inp,line[lineptr])
2472843Swnj		        until (charclass[ord(inp^)] <> letter) and
2482843Swnj			      (charclass[ord(inp^)] <> digit);
2492843Swnj		        pack(a, 1, id.a);
2502843Swnj		        if nokey(id.a) then
2512843Swnj			    search
2522843Swnj		    end else if charclass[ord(inp^)] = digit then
2532843Swnj		        repeat
2542843Swnj			    lineptr:=lineptr+1;
2552843Swnj			    read(inp,line[lineptr])
2562843Swnj		        until charclass[ord(inp^)] <> digit
2572843Swnj		    else if inp^='''' then begin
2582843Swnj		        repeat
2592843Swnj			    lineptr:=lineptr+1;
2602843Swnj			    read(inp,line[lineptr])
2612843Swnj		        until inp^ = '''';
2622843Swnj			lineptr:=lineptr+1;
2632843Swnj			read(inp,line[lineptr])
2642843Swnj		    end else if inp^ = '{' then begin
2652843Swnj		        repeat
2662843Swnj			    lineptr:=lineptr+1;
2672843Swnj			    read(inp,line[lineptr]);
2682843Swnj			    while eoln(inp) do begin
2692843Swnj			        lwriteln;
2702843Swnj				newline
2712843Swnj			    end
2722843Swnj		        until inp^ = '}';
2732843Swnj			lineptr:=lineptr+1;
2742843Swnj			read(inp,line[lineptr])
2752843Swnj		    end else if inp^ = '(' then begin
2762843Swnj			lineptr:=lineptr+1;
2772843Swnj			read(inp,line[lineptr]);
2782843Swnj		        if inp^ = '*' then begin
2792843Swnj			    lineptr:=lineptr+1;
2802843Swnj			    read(inp,line[lineptr]);
2812843Swnj			    repeat
2822843Swnj			        while inp^ <> '*' do
2832843Swnj				    if eoln(inp) then begin
2842843Swnj				        lwriteln;
2852843Swnj					newline
2862843Swnj				    end else begin
2872843Swnj					lineptr:=lineptr+1;
2882843Swnj					read(inp,line[lineptr])
2892843Swnj			            end;
2902843Swnj				lineptr:=lineptr+1;
2912843Swnj				read(inp,line[lineptr])
2922843Swnj			    until inp^ = ')';
2932843Swnj			    lineptr:=lineptr+1;
2942843Swnj			    read(inp,line[lineptr])
2952843Swnj		        end
2962843Swnj		    end else begin
2972843Swnj			lineptr:=lineptr+1;
2982843Swnj			read(inp,line[lineptr]);
2992843Swnj		    end
3002843Swnj		end; { scan of token }
3012843Swnj		lwriteln;
3022843Swnj	    end; { scan of line }
3032843Swnj	end; { while not eof }
3042843Swnj    end; {readinput }
3052843Swnj
3062843Swnjbegin { xref }
3072843Swnj    empty := blanks;
3082843Swnj    list := true;
3092843Swnj    if argc = 3 then begin
3102843Swnj	argv(1, scr);
3112843Swnj	if (scr[1] <> '-') or (scr[2] <> ' ') then begin
3122843Swnj	    writeln('usage: pxref [ - ] file');
3132843Swnj	    goto 100
3142843Swnj	end;
3152843Swnj	list := false
3162843Swnj    end;
3172843Swnj    if (argc < 2) or (argc > 3) then begin
3182843Swnj	writeln('usage: pxref [ - ] file');
3192843Swnj	goto 100
3202843Swnj    end;
3212843Swnj    for i := 0 to p - 1 do
3222843Swnj	t[i].key := empty;
3232843Swnj    c1 := 0;
3242843Swnj    c2 := 0;
3252843Swnj    key[1] := 'and';
3262843Swnj    key[2] := 'array';
3272843Swnj    key[3] := 'assert';
3282843Swnj    key[4] := 'begin';
3292843Swnj    key[5] := 'case';
3302843Swnj    key[6] := 'const';
3312843Swnj    key[7] := 'div';
3322843Swnj    key[8] := 'do';
3332843Swnj    key[9] := 'downto';
3342843Swnj    key[10] := 'else';
3352843Swnj    key[11] := 'end';
3362843Swnj    key[12] := 'file';
3372843Swnj    key[13] := 'for';
3382843Swnj    key[14] := 'function';
3392843Swnj    key[15] := 'hex';
3402843Swnj    key[16] := 'if';
3412843Swnj    key[17] := 'in';
3422843Swnj    key[18] := 'mod';
3432843Swnj    key[19] := 'nil';
3442843Swnj    key[20] := 'not';
3452843Swnj    key[21] := 'oct';
3462843Swnj    key[22] := 'of';
3472843Swnj    key[23] := 'or';
3482843Swnj    key[24] := 'packed';
3492843Swnj    key[25] := 'procedure';
3502843Swnj    key[26] := 'program';
3512843Swnj    key[27] := 'record';
3522843Swnj    key[28] := 'repeat';
3532843Swnj    key[29] := 'set';
3542843Swnj    key[30] := 'then';
3552843Swnj    key[31] := 'to';
3562843Swnj    key[32] := 'type';
3572843Swnj    key[33] := 'until';
3582843Swnj    key[34] := 'var';
3592843Swnj    key[35] := 'while';
3602843Swnj    key[36] := 'with';
3612843Swnj    for k:= 0 to charclassize do
3622843Swnj	charclass[k]:=illegal;
3632843Swnj    for k:=ord('a') to ord('z') do
3642843Swnj	charclass[k]:=letter;
3652843Swnj    for k:=ord('A') to ord('Z') do
3662843Swnj	charclass[k]:=letter;
3672843Swnj    for k:=ord('0') to ord('9') do
3682843Swnj	charclass[k]:=digit;
3692843Swnj    charclass[ord('_')]:=letter;
3702843Swnj    charclass[ord(' ')]:=separator;
3712843Swnj    charclass[ord(tab)]:=separator;
3722843Swnj    n := 0;
3732843Swnj    lineptr:=0;
3742843Swnj    line:=blanks;
3752843Swnj    top := p;
3762843Swnj    k1 := alfasize;
3772843Swnj    formfeed:=chr(12);
3782843Swnj    if list then
3792843Swnj        argv(1,inputfile)
3802843Swnj    else
3812843Swnj        argv(2,inputfile);
3822843Swnj    readinput(inputfile);
3832843Swnj99:
3842843Swnj    if list then begin
3852843Swnj	page(output);
3862843Swnj        writeln;
3872843Swnj        end;
3882843Swnj    printtable;
3892843Swnj    writeln;
3902843Swnj    writeln(c1, ' identifiers', c2, ' occurrences');
3912843Swnj100:
3922843Swnj    {nil}
3932843Swnjend { xref }.
394