|
|
1.1 root 1: BEGIN {
2: myname = "a4:"
3: list["\["] = "\]"; list["{"] = "}"; list["("] = "\\)"; list["<"] = ">"
4: # it is unclear what the proper format is,
5: # but let's give it a try
6: if (summary) {
7: summary = summary ".sum"
8: print "\n\n" summary, "doc", "type\n" > summary
9: summarypipe = "sort -u" ">> " summary
10: }
11: while(--ARGC) {
12: i++
13: include(ARGV[i])
14: }
15: }
16:
17: function show(a) { # debugging aid
18: print ">>>", a |"cat 1>&2"
19: # print ">>>", a
20: }
21:
22: function include(file, l,m,i) { # include file handling
23: gsub( / +|\)/, "", file)
24: push( file )
25: while( (i = getline l < file ) > 0) {
26: NR++
27: if (match(l, /^\|include\(/)) {
28: include( substr(l, RSTART+RLENGTH))
29: } else {
30: if ((m = process(l)) !~ /^$/ ) {
31: print m
32: }
33: }
34: }
35: if ( i < 0 )
36: error("Cannot open: " file)
37: else {
38: close file
39: pop()
40: }
41: }
42:
43: function push(new) {
44: stack[top++] = NR " " FILENAME
45: NR = 0; FILENAME = new
46: }
47:
48: function pop( a) {
49: if (--top < 0)
50: error("Internal error include stack")
51: split(stack[top], a)
52: NR = a[1]; FILENAME = a[2]
53: }
54:
55: function error(s) {
56: print myname, s | "cat 1>&2"; exit -1
57: }
58:
59: function warn(b1, b2) {
60: print myname, FILENAME", line", NR ":", b1, b2 | "cat 1>&2"
61: warned++
62: }
63:
64: function process(line, s, t) { # does all the work
65: # show(line)
66:
67: if (summary && line ~ /\|comment<summary: /) {
68: sub(/[ \t]*\|comment<summary: /, "", line)
69: sub(/>$/, "", line)
70: print line | summarypipe
71: return ""
72: }
73: if (comment == 0 && line ~ /\|comment[\[{(<]/ ) {
74: match(line, /\|comment[\[{(<]/)
75: comment = substr(line, RSTART+RLENGTH-1, 1)
76: closecomment = list[comment]
77: }
78: if (comment != 0 && line ~ /[\]})>]/) {
79: if (match(line, closecomment))
80: comment = 0 ;
81: return ""
82: }
83: if (comment != 0) {
84: return ""
85: }
86:
87: if (line ~ /^$/) { # ignore empty lines
88: return ""
89: }
90: if (line ~ /^[\.'][ \t]*\\"/) { # wipe out lines of troff comments
91: return ""
92: }
93: if (line ~ /[ \t]+\\".*/) { # wipe out more troff comments
94: sub(/[ \t]+\\".*/, "", line)
95: }
96:
97: if (line ~ /\|REGISTER\(/) {
98: sub(/\|REGISTER\(/, "", line)
99: match(line, /[A-Za-z][A-Za-z_0-9]*/)
100: s = substr(line, RSTART, RLENGTH)
101: line = substr(line, RLENGTH+1)
102: if (s in name) {
103: warn("redefinition of register name:", s)
104: }
105: match(line, /[@-Za-z0-0%|:;.][@-Za-z0-9%|%;.]*/)
106: t = substr(line, RSTART, RLENGTH)
107: chklen2(t)
108: name[s] = t
109: type[s] = "register"
110: return ""
111: }
112:
113: if (line ~ /\|LITERAL\(/) {
114: sub(/\|LITERAL\(/, "", line)
115: match(line, /[A-Za-z][A-Za-z_0-9]*/)
116: s = substr(line, RSTART, RLENGTH)
117: line = substr(line, RSTART+RLENGTH)
118: # show(line)
119: if (s in name) {
120: warn("redefinition of constant name:", s)
121: }
122: sub(/, */, "", line); sub(/ *\).*/, "", line)
123: t = hunt(line)
124: name[s] = t
125: type[s] = "value"
126: return ""
127: }
128:
129: if (line ~ /\|STRING\(/) {
130: sub(/\|STRING\(/, "", line)
131: match(line, /[A-Za-z][A-Za-z_0-9]*/)
132: s = substr(line, RSTART, RLENGTH)
133: line = substr(line, RLENGTH+1)
134: # show(line)
135: if (s in name) {
136: warn("redefinition of string name:", s)
137: }
138: match(line, /[@-Za-z0-;%][@-Za-z0-;%]*/)
139: t = substr(line, RSTART, RLENGTH)
140: chklen2(t)
141: name[s] = t
142: type[s] = "string"
143: return ""
144: }
145:
146: if (line ~ /\|STRING_ARRAY\(/) {
147: sub(/\|STRING_ARRAY\(/, "", line)
148: match(line, /[A-Za-z][A-Za-z_0-9]*/)
149: s = substr(line, RSTART, RLENGTH)
150: line = substr(line, RLENGTH+1)
151: if (s in name) {
152: warn("redefinition of string array:", s)
153: }
154: match(line, /[@-Za-z0-;%][@-Za-z0-;%]*/)
155: t = substr(line, RSTART, RLENGTH)
156: chklen1(t)
157: name[s] = t
158: type[s] = "string_array"
159: return ""
160: }
161:
162: # anything else
163: t = hunt(line)
164: gsub(/^[ \t]+/, "", t) # remove leading blanks
165: if (match(t, /^(\\!)?[\.'][ \t]/)) { # remove space after troff's control char
166: sub(/[ \t]+/, "", t)
167: }
168: if (match(t, /^(\\!)?[\.'][a-z][a-z] /)) { # remove space after troff request
169: sub(/ /, "", t)
170: }
171: return t
172: }
173:
174: function chklen2(s) {
175: if (length(s) > 2) {
176: warn("name too long:", t)
177: }
178: }
179:
180: function chklen1(s) {
181: if (length(s) > 1) {
182: warn("name too long:", t)
183: }
184: }
185:
186: # match up to a closing parenthesis, while ignoring matching parentheses
187:
188: function parmatch(s, l, r) {
189: l = match(s, /\(/)
190: r = match(s, /\)/)
191:
192: if ( l == 0 || r < l ) {
193: return r
194: } else {
195: sub(/\(/, " ", s)
196: sub(/\)/, " ", s)
197: r = parmatch(s)
198: return r
199: }
200:
201: }
202:
203:
204: # find all occurrences of macros in s and replace as text
205: function hunt(s, r, b, t, before, after, i, j) {
206:
207: # 'operator' stuff
208: while(match(s, /[A-Z][A-Z]*[_A-Z][_A-Z]*\(/)) {
209: b = substr(s, 1, RSTART-1)
210: i = RLENGTH
211: j = RSTART
212: if(parmatch(substr(s, RSTART + i))) {
213: t = substr(s, j, RSTART + i -1)
214: s = substr(s, j+i+RSTART)
215: r = operator(t, i)
216: } else {
217: warn("syntax error:", s)
218: return s
219: }
220: before = before b r
221: }
222: before = before s
223: s = before
224: before = ""
225: # find macro stuff
226: while(match(s, /[A-Za-z][A-Za-z_0-9]*/)) {
227: b = substr(s, 1, RSTART-1)
228: t = substr(s, RSTART, RLENGTH)
229: s = substr(s, RSTART+RLENGTH)
230: r = replace(t)
231: if( r !~ t) {
232: if ( t in name && type[t] == "string_array") {
233: if (!match(s, /^\[[\$A-Za-z0-9][A-Za-z_0-9]*\]/)) {
234: warn("Illegal or missing subscript of:", t)
235: } else
236: r = r subscript(substr(s, RSTART+1, RLENGTH-2))
237: s = substr(s, RSTART+RLENGTH)
238: } else {
239: if (match(b, /'$/) && match(s, /^'/)) {
240: sub(/'$/, "", b)
241: sub(/^'/, "", s)
242: }
243: }
244: r = hunt(r)
245: }
246: before = before b r
247: after = s
248: }
249: if ( before || after) {
250: s = before after
251: }
252: return s
253: }
254:
255: # replace string s with defined name, if in table
256: function replace(s) {
257: if (s in name)
258: return name[s]
259: else
260: return s
261: }
262:
263: # check and maybe generate form for substript
264: function subscript(s) {
265: if ( s ~ /^[0-9]$/) {
266: return s
267: }
268: if ( s ~ /^\$/ )
269: return s
270: if ( s in name && type[s] == "register") {
271: return interpolreg(name[s])
272: } else {
273: warn("Illegal subscript")
274: }
275: return s
276: }
277:
278: # turn register suitable for troff interpolation
279: function interpolreg(r) {
280: if (length(r) == 1 )
281: return "\\n" r
282: else if (length(r) == 2)
283: return "\\n(" r
284: else
285: warn("Register name too long")
286: return r
287: }
288:
289: function interpolstr(r) {
290: if (length(r) == 1 )
291: return "\\*" r
292: else
293: return "\\*(" r
294: }
295:
296: function operator(s,i, t,u,a) {
297: oper = substr(s, 1, i - 1)
298: # match(s, /\)/)
299: # t = substr(s, i + 1, RSTART - 1 + RLENGTH - (i + 1))
300: t = substr(s, i+1)
301: gsub(/ /, "", t)
302: i = split(t, a, ",")
303: if ( oper ~ "^GE$") {
304: if (!chckargs(oper, i, 2))
305: return t
306: t = sprintf("\"%s>=%s\"", args(a[1]), args(a[2]))
307: } else if (oper ~ "^GT$") {
308: if (!chckargs(oper, i, 2))
309: return t
310: t = sprintf("\"%s>%s\"", args(a[1]), args(a[2]))
311: } else if (oper ~ "^LE$") {
312: if (!chckargs(oper, i, 2))
313: return t
314: t = sprintf("\"%s<=%s\"", args(a[1]), args(a[2]))
315: } else if (oper ~ "^LT$") {
316: if (!chckargs(oper, i, 2))
317: return t
318: t = sprintf("\"%s<%s\"", args(a[1]), args(a[2]))
319: } else if (oper ~ "^NULL$") {
320: if (!chckargs(oper, i, 1))
321: return t
322: t = sprintf("\"@%s@@\"", args(a[1]))
323: } else if (oper ~ "^NOTNULL$") {
324: if (!chckargs(oper, i, 1))
325: return t
326: t = sprintf("\"!@%s@@\"", args(a[1]))
327: } else if (oper ~ "^EQUAL$") {
328: if (!chckargs(oper, i, 2))
329: return t
330: u = args(a[1])
331: if (u ~ /\\n\(\.z$/) {# diversion!
332: t = sprintf("\"@%s@%s@\"", u, args(a[2]))
333: } else if ( argtype ~ /^register$/ ) {
334: t = sprintf("\"%s=%s\"", u, args(a[2]))
335: } else
336: t = sprintf("\"@%s@%s@\"", u, args(a[2]))
337: } else if (oper ~ "^UNEQUAL$") {
338: if (!chckargs(oper, i, 2))
339: return t
340: u = args(a[1])
341: if (u ~ /^\\n\(\.z$/) {# diversion!
342: t = sprintf("\"!@%s@%s@\"", u, a[2])
343: } else if ( argtype ~ /^register$/ ) {
344: t = sprintf("\"%s!=%s\"", u, args(a[2]))
345: } else
346: t = sprintf("\"!@%s@%s@\"", u, args(a[2]))
347: } else if (oper ~ "^VALUE$") {
348: if (!chckargs(oper, i, 1))
349: return t
350: t = sprintf("\"%s\"", args(a[1]))
351: } else
352: warn("Unknown operation: " oper)
353: return t
354: }
355:
356: function chckargs(o, i, ii) {
357: if ( i != ii) {
358: warn(ii " arguments required for " oper " (is " i ")")
359: return 0
360: } else
361: return 1
362: }
363:
364: function args(a, after, result, i, j) {
365: if ( a ~ /^$/ ) {
366: warn("Missing argument", a)
367: return a
368: }
369: if (match(a, /^'/)) {
370: a = substr(a, 2)
371: match(a, /'/)
372: after = substr(a, RSTART+1)
373: a = substr(a, 1, RSTART-1)
374: }
375: if (match(a, /\[/)) {
376: i = RSTART
377: if (!match(a, /\]/)) {
378: warn("syntax error")
379: return a after
380: } else
381: j = substr(a, i+1, RSTART - 1 - i)
382: a = substr(a, 1, i -1)
383: }
384:
385: if ( a ~ /^[0-9]+$/ && type[a] !~ "string_array")
386: return a after
387: if ( a ~ /\$/ ) # possible monk variable
388: return a after
389: if ( a in name ) {
390: # show("a: " a " name[a]: " name[a] " type[a]: " type[a])
391: argtype = type[a]
392: if (argtype ~ "^register$" )
393: result = interpolreg(name[a])
394: else if (argtype ~ "^value$")
395: result = name[a]
396: else if (argtype ~ "^string$")
397: result = interpolstr(name[a])
398: else if (argtype ~ "^string_array$")
399: result = interpolstr(name[a] args(j))
400: else
401: warn("Internal error, unknown type: " type[a] " (" a ")")
402: } else {
403: warn("Unknown variable: ", a)
404: result = a after
405: }
406: return result after
407: }
408:
409: END {
410: # to signal make etc. that not everything is dandy
411: # if (warned)
412: # exit -1
413: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.