# kwic --- make keyword in context index define(FOLD,:140) define(MAX_KWDS,200) define(MAX_KWD_LEN,2048) character buf (MAXLINE) integer getlin call read_discards while (getlin (buf, STDIN) ~= EOF) call putrot (buf, STDOUT) stop end # putrot --- create lines with keyword at front subroutine putrot (buf, outfil) character buf (ARB) integer outfil integer i, outfil integer discard for (i = 1; buf (i) ~= NEWLINE && buf (i) ~= EOS; ) { if (buf (i) ~= ' 'c && buf (i) ~= TAB) { # start of a token if (discard (buf (i)) == NO) # not a throw-away call rotate (buf, i, outfil) repeat i += 1 until (buf (i) == ' 'c || buf (i) == TAB || buf (i) == NEWLINE || buf (i) == EOS) } while (buf (i) == ' 'c || buf (i) == TAB) i += 1 } return end # rotate --- output rotated line subroutine rotate (buf, n, outfil) character buf (ARB) integer i, n, outfil for (i = n; buf (i) ~= NEWLINE && buf (i) ~= EOS; i += 1) call putch (buf (i), outfil) call putch (FOLD, outfil) for (i = 1; i < n; i += 1) call putch (buf (i), outfil) call putch (NEWLINE, outfil) return end # discard --- see if first word in buf is in throw-away list integer function discard (buf) character buf (ARB) character word (MAXLINE) integer i integer search for (i = 1; buf (i) ~= ' 'c && buf (i) ~= TAB && buf (i) ~= EOS && buf (i) ~= NEWLINE && i < MAXLINE; i = i + 1) word (i) = buf (i) word (i) = EOS call mapstr (word, LOWER) if (search (word) == EOF) discard = NO # word not in list, don't throw it away else discard = YES return end # search --- search keyword list for word integer function search (word) character word (ARB) integer i, j, k integer compare common /kwdcom/ kwd_pos, kwd_text, num_kwds integer kwd_pos (MAX_KWDS) # keyword positions character kwd_text (MAX_KWD_LEN) # text of keywords integer num_kwds # number of keywords i = 1 j = num_kwds if (i <= j) repeat { # perform binary search of the throw-away list k = (i + j) / 2 select (compare (kwd_text (kwd_pos (k)), word)) when (1) # less i = k + 1 when (2) { # equal search = kwd_pos (k) return } when (3) # greater j = k - 1 } until (i > j) search = EOF return end # compare --- compare two strings and return 1 2 or 3 for < = or > integer function compare (str1, str2) character str1 (ARB), str2 (ARB) integer i for (i = 1; str1 (i) == str2 (i); i = i + 1) if (str1 (i) == EOS | str2 (i) == EOS) break if (str1 (i) == str2 (i)) # equal strings compare = 2 else if (str1 (i) == EOS || str1 (i) < str2 (i) & str2 (i) ~= EOS) # str1 < str2 compare = 1 else if (str2 (i) == EOS || str2 (i) < str1 (i) & str1 (i) ~= EOS) # str1 > str2 compare = 3 else call error ("in compare: can't happen.") return end # read_discards --- load throw-away list from file subroutine read_discards integer i, l, fd integer get_list, getlin character line (MAXLINE) common /kwdcom/ kwd_pos, kwd_text, num_kwds integer kwd_pos (MAX_KWDS) # keyword positions character kwd_text (MAX_KWD_LEN) # text of keywords integer num_kwds # number of keywords num_kwds = 0 # initially zero if (get_list (fd) == ERR) return i = 1 l = getlin (line, fd) while (l ~= EOF) { if (line (l) == NEWLINE) { line (l) = EOS l = l - 1 } if (MAX_KWD_LEN - i > l && num_kwds < MAX_KWDS) { # check for room num_kwds = num_kwds + 1 kwd_pos (num_kwds) = i call scopy (line, 1, kwd_text, i) i = i + l + 1 } else { call print (ERROUT, "*s: discard list too long*n.", line) break } l = getlin (line, fd) } if (fd ~= STDIN2) call close (fd) return end # get_list --- get throw-away list file descriptor integer function get_list (fd) integer fd character arg (MAXARG) integer getarg, open if (getarg (1, arg, MAXARG) ~= EOF) if (arg (1) == '-'c && (arg (2) == 'd'c | arg (2) == 'D'c)) { if (getarg (2, arg, MAXARG) ~= EOF) { fd = open (arg, READ) if (fd == ERR) call cant (arg) } else fd = STDIN2 } else call error ("Usage: kwic [ -d [ ] ].") else fd = ERR get_list = fd return end