|
|
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.