|
|
1.1 root 1: # IPXREF
2: #
3: # Create Icon program cross-reference
4: #
5: # Allan J. Anderson
6: #
7: # Last modified 4/29/86 by Ralph E. Griswold
8: #
9:
10: global resword, linenum, letters, digits, var, buffer, qflag, f, fflag, xflag
11: global inmaxcol, inlmarg, inchunk, localvar, lin
12:
13: record procrec(pname,begline,lastline)
14:
15: procedure main(a)
16: local word, w2, p, prec, i, L, ln
17: initial {
18: resword := ["break","by","case","default","do","dynamic","else",
19: "end","every","fail","global","if","initial","link",
20: "local","next","not","of","procedure",
21: "record","repeat","return","static","suspend","then",
22: "to","until","while"]
23: linenum := 0
24: var := table() # var[variable[proc]] is list of line numbers
25: prec := [] # list of procedure records
26: localvar := [] # list of local variables of current routine
27: buffer := [] # a put-back buffer for getword
28: proc := "global"
29: letters := &lcase ++ &ucase ++ '_'
30: digits := '1234567890'
31: }
32: i := 0
33: while p := a[i +:= 1] do
34: case p of {
35: "-q": qflag := 1
36: "-x": xflag := 1
37: "-w": inmaxcol := integer(a[i +:= 1])
38: "-l": inlmarg := integer(a[i +:= 1])
39: "-c": inchunk := integer(a[i +:= 1])
40: default: if f := open(p,"r") then fflag := 1
41: else stop("usage: [-q -x -w -l -c] file")
42: }
43: while word := getword() do
44: if word == "link" then {
45: buffer := []
46: lin := ""
47: next
48: }
49: else if word == "procedure" then {
50: put(prec,procrec("",linenum,0))
51: proc := getword() | break
52: p := pull(prec)
53: p.pname := proc
54: put(prec,p)
55: }
56: else if word == ("global" | "link" | "record") then {
57: word := getword() | break
58: addword(word,"global",linenum)
59: while (w2 := getword()) == "," do {
60: if Find(word,resword) then break
61: word := getword() | break
62: addword(word,"global",linenum)
63: }
64: put(buffer,w2)
65: }
66: else if word == ("local" | "dynamic" | "static") then {
67: word := getword() | break
68: put(localvar,word)
69: addword(word,proc,linenum)
70: while (w2 := getword()) == "," do {
71: if Find(word,resword) then break
72: word := getword() | break
73: put(localvar,word)
74: addword(word,proc,linenum)
75: }
76: put(buffer,w2)
77: }
78: else if word == "end" then {
79: proc := "global"
80: localvar := []
81: p := pull(prec)
82: p.lastline := linenum
83: put(prec,p)
84: }
85: else if Find(word,resword) then
86: next
87: else {
88: ln := linenum
89: if (w2 := getword()) == "(" then
90: word ||:= " *" # special mark for procedures
91: else
92: put(buffer,w2) # put back w2
93: addword(word,proc,ln)
94: }
95: every write(!format(var))
96: write("\n\nprocedures:\tlines:\n")
97: L := []
98: every p := !prec do
99: put(L,left(p.pname,16," ") || p.begline || "-" || p.lastline)
100: every write(!(sort(L)))
101: end
102:
103: procedure addword(word,proc,lineno)
104: if any(letters,word) | \xflag then {
105: /var[word] := table()
106: if /var[word]["global"] | Find(word,\localvar) then {
107: /(var[word])[proc] := [word,proc]
108: put((var[word])[proc],lineno)
109: }
110: else {
111: /var[word]["global"] := [word,"global"]
112: put((var[word])["global"],lineno)
113: }
114: }
115: end
116:
117: procedure getword()
118: local j, c
119: static i, nonwhite
120: nonwhite := ~' \t\n'
121: repeat {
122: if *buffer > 0 then return get(buffer)
123: if /lin | i = *lin + 1 then
124: if lin := myread() then {
125: i := 1
126: linenum +:= 1
127: }
128: else fail
129: if i := upto(nonwhite,lin,i) then { # skip white space
130: j := i
131: if lin[i] == ("'" | '"') then { # don't xref quoted words
132: if /qflag then {
133: c := lin[i]
134: i +:= 1
135: repeat
136: if i := upto(c ++ '\\',lin,i) + 1 then
137: if lin[i - 1] == c then break
138: else i +:= 1
139: else {
140: i := 1
141: linenum +:= 1
142: lin := myread() | fail
143: }
144: }
145: else i +:= 1
146: }
147: else if lin[i] == "#" then { # don't xref comments; get next line
148: i := *lin + 1
149: }
150: else if i := many(letters ++ digits,lin,i) then
151: return lin[j:i]
152: else {
153: i +:= 1
154: return lin[i - 1]
155: }
156: }
157: else
158: i := *lin + 1
159: } # repeat
160: end
161:
162: procedure format(T)
163: local V, block, n, L, lin, maxcol, lmargin, chunk, col
164: initial {
165: maxcol := \inmaxcol | 80
166: lmargin := \inlmarg | 40
167: chunk := \inchunk | 4
168: }
169: L := []
170: col := lmargin
171: every V := !T do
172: every block := !V do {
173: lin := left(block[1],16," ") || left(block[2],lmargin - 16," ")
174: every lin ||:= center(block[3 to *block],chunk," ") do {
175: col +:= chunk
176: if col >= maxcol - chunk then {
177: lin ||:= "\n\t\t\t\t\t"
178: col := lmargin
179: }
180: }
181: if col = lmargin then lin := lin[1:-6] # came out exactly even
182: put(L,lin)
183: col := lmargin
184: }
185: L := sort(L)
186: push(L,"variable\tprocedure\t\tline numbers\n")
187: return L
188: end
189:
190: procedure Find(w,L)
191: every if w == !L then return
192: end
193:
194: procedure myread()
195: if \fflag then return read(f) else return read()
196: end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.