Annotation of 43BSD/ucb/vlp/vlp.l, revision 1.1.1.1

1.1       root        1: ;$Header: vlp.l,v 1.5 84/05/07 15:09:59 jkf Exp $
                      2: ;$Locker: layer $
                      3: ;
                      4: ;                      -[Mon May  7 15:04:34 1984 by jkf]-
                      5: ;
                      6: ;  Filter for nroffing or troffing Lisp code.
                      7: ;  This program reads files containing Lisp code and writes them out
                      8: ;  along with the nroff (troff) commands required to make the Lisp line up.
                      9: ;  It does this alignment by insuring that the leftmost
                     10: ;  blank character lines up with the closest non blank character above it.
                     11: ;
                     12: ;  The program operates in one of two modes: filter mode or non-filter mode.
                     13: ;
                     14: ;  In filter mode, only characters between lines beginning with .Ls and .Le
                     15: ;  are processed.  The directive .Ls accepts an optional argument that is 
                     16: ;  the point size of the output.  Pages have no titles and point size is set
                     17: ;  by the macro, so most shell arguments are ignored.
                     18: ;
                     19: ;  In non-filter mode, all lines in the file are processed.
                     20: ;
                     21: ;  The output goes to the standard output, unless the v switch is set,
                     22: ;  in which case it goes to vtroff.
                     23: ;
                     24: ;  Usage:
                     25: ;    vlp [-p size] [-d] [-f] [-l] [-v] [-T title1] file1 ....
                     26: ;
                     27: ;      where,
                     28: ;              -p      Sets the point size to "size"
                     29: ;              -d      Turn on debugging mode
                     30: ;              -f      Run in filtered mode
                     31: ;              -l      Turns OFF the labeling of functions 
                     32: ;              -v      Sends the output to vtroff
                     33: ;              -T      Sets the title of the next file to "titleN"
                     34: ;
                     35: ;  NOTE: If vlp is on the right side of a pipe, the "-T" switch can not be
                     36: ;       used.  
                     37: ;
                     38: ;
                     39: ;  Written by John Foderaro
                     40: ;  Modified by:
                     41: ;      Kevin Layer to have enough tags.
                     42: ;      Jim Larus to work in filtered mode.
                     43: ;
                     44: 
                     45: (declare (macros t))
                     46: 
                     47: (allocate 'list 220)
                     48: 
                     49: (declare (special user-top-level EOF lines g-psize inport
                     50:                  spaces sps chs tls trname errport outfilename
                     51:                  filtermode g-title rest funcname readstdin debug
                     52:                  spout outfile tagsleft LabelFunctions)) 
                     53: 
                     54: (defvar space-count 500.)      ; large number
                     55: 
                     56: ;--- toplev :: top level lisp 
                     57: ;
                     58: (defun toplev nil
                     59:    (let ((args (command-line-args)))
                     60:        (signal 2 'vlp-interrupt-routine)
                     61:        (signal 15 'vlp-interrupt-routine)
                     62:        (errset (apply 'vlp args))
                     63:        (exit 0)))
                     64: 
                     65: (eval-when (load) (setq user-top-level 'toplev))
                     66: 
                     67: (setq g-psize 8
                     68:       debug nil
                     69:       g-filtmode nil
                     70:       readstdin nil
                     71:       filtermode nil
                     72:       outfilename nil
                     73:       LabelFunctions t)
                     74: 
                     75: 
                     76: (defun GetModTime (FileName)
                     77:   ;
                     78:   ; Returns the last modification time as a string.
                     79:   ;
                     80:   (time-string (filestat:mtime (filestat (get_pname FileName)))))
                     81: 
                     82: 
                     83: (defun vlp fexpr (args)
                     84:    (prog (inport outfile)
                     85:        ;check command line for switches
                     86:        (setq args (do ((i args (cdr i)) (ll) (tem))
                     87:                      ((null i) (reverse ll))
                     88:                      (setq tem (aexplodec (car i)))
                     89:                      (cond ((eq '- (car tem))  ; if switch
                     90:                             (cond ((eq 'd (cadr tem))
                     91:                                    (setq debug t))
                     92:                                   ((eq 'f (cadr tem))
                     93:                                    (setq filtermode t))
                     94:                                   ((eq 'l (cadr tem))
                     95:                                    (setq LabelFunctions nil))
                     96:                                   ((eq 'p (cadr tem))
                     97:                                    (setq g-psize
                     98:                                          (cond ((eq '|6| (cadr i)) 6)
                     99:                                                ((eq '|10| (cadr i)) 10)
                    100:                                                ((eq '|12| (cadr i)) 12)
                    101:                                                (t 8)))
                    102:                                    (setq i (cdr i)))
                    103:                                   ((eq 'v (cadr tem))
                    104:                                    (setq outfilename
                    105:                                          (concat "/tmp/vlp" (sys:getpid))))
                    106:                                   (t (setq ll (cons (car i) ll)))))
                    107:                            (t (setq ll (cons (car i) ll)))))) ; else skip it
                    108:        ;
                    109:        (if debug then (msg (P errport) "args = " args N))
                    110:        ;
                    111:        ; insure all file names given actually exist before starting.
                    112:        (cond ((null (do ((xx args (cdr xx)))
                    113:                        ((null xx) t)
                    114:                        (if (eq '- (getchar (car xx) 1))
                    115:                            then (setq xx (cdr xx)) ; skip switches
                    116:                            else (if (not (probef (car xx))) 
                    117:                                     then (msg (P errport)
                    118:                                               "File does not exist: "
                    119:                                               (car xx))
                    120:                                          (return nil)))))
                    121:              (return nil)))
                    122:        ;
                    123:        ; do before-starting-first-file actions
                    124:        ;
                    125:        (if outfilename then (setq outfile (outfile outfilename)))
                    126:        (if (null args) then (setq readstdin t))
                    127: 
                    128:        (if (and LabelFunctions (null filtermode))
                    129:           then ;; NOTE: the following concat'ing of strings 
                    130:                ;; is neccessary because when vlp'ing vlp.l 
                    131:                ;; soelim would source the file.
                    132:                (msg (P outfile) (concat "." "so /usr/lib/vlpmacs") N))
                    133:        (setq g-title "")
                    134:        ;
                    135:        ;
                    136:        (if readstdin
                    137:           then (setq EOF nil)
                    138:                (setq lines nil)
                    139:                (if (not filtermode)
                    140:                    then (msg (P outfile) ".ps " g-psize N
                    141:                              ".vs " (+ g-psize 2) "p" N)
                    142:                         (msg (P outfile) ".Ti " '\" g-title '\" N)
                    143:                         (msg (P outfile) ".wh -1.25i He" N)
                    144:                         (msg (P outfile) ".nf" N))
                    145:                (do ()
                    146:                    (EOF t)
                    147:                    (if filtermode then (skiptostarter))
                    148:                    (processblock))
                    149:           else (do ((files args (cdr files)))
                    150:                    ((null files) t)
                    151:                    (if (eq '- (getchar (car files) 1))
                    152:                        then (if (eq '-p (car files))
                    153:                                 then (if (null (setq g-psize
                    154:                                                      (cdr (assoc (cadr files)
                    155:                                                                  '((\6 . 6)
                    156:                                                                    (\8 . 8)
                    157:                                                                    (\10 . 10)
                    158:                                                                    (\12 . 12))))))
                    159:                                          then (error "bad point size"
                    160:                                                      (cadr files)))
                    161:                              elseif (eq '-T (car files))
                    162:                                 then (setq g-title (cadr files))
                    163:                                 else (error "bad switch " (car files)))
                    164:                             (setq files (cdr files))
                    165:                        else (setq EOF nil)
                    166:                             (setq lines nil)
                    167:                             (cond ((null (errset
                    168:                                              (setq inport (infile (car files)))))
                    169:                                    (msg (P errport) "Can't open file: "
                    170:                                         (car args))
                    171:                                    (return nil)))
                    172:                             (if (not filtermode)
                    173:                                 then (msg (P outfile)
                    174:                                           ".ps " g-psize N
                    175:                                           ".vs " (+ g-psize 2) "p" N)
                    176:                                      (msg (P outfile)
                    177:                                           ".Fi " (car files)
                    178:                                           " \"" (GetModTime (car files)) '\"
                    179:                                           " \"" (time-string) '\"
                    180:                                           N)
                    181:                                      (msg (P outfile)
                    182:                                           ".Ti " '\" g-title '\" N)
                    183:                                      (msg (P outfile) ".wh -1.25i He" N)
                    184:                                      (msg (P outfile) ".nf" N))
                    185:                             (do ()
                    186:                                 (EOF)
                    187:                                 (if filtermode then (skiptostarter))
                    188:                                 (processblock))
                    189:                             (close inport))))
                    190:        (if outfilename
                    191:           then
                    192:                (close outfile)
                    193:                (apply 'process
                    194:                       (ncons (concat "/bin/cat " outfilename
                    195:                                      " | /usr/ucb/vtroff")))
                    196:                (if debug
                    197:                    then (msg (P errport)
                    198:                              "Troff filename is " outfilename N)
                    199:                    else (sys:unlink outfilename)))))
                    200: 
                    201: 
                    202: ;--- skiptostarter :: skip to start directive (.Ls)
                    203: ;
                    204: (defun skiptostarter nil
                    205:    ;
                    206:    ; Define a simple finite state machine that reads and prints everything
                    207:    ; up-to and including the directive .Ls.
                    208:    ; All text outside of the .Ls directive is simply sent on to the output.
                    209:    ;
                    210:    (do ((State 0)
                    211:        (c (tyi inport) (tyi inport)))
                    212:        ((=& 4 State))
                    213:        (cond ((and (=& State 0) (=& c #/.))
                    214:              (setq State 1))
                    215:             ((and (=& State 1) (=& c #/L))
                    216:              (setq State 2))
                    217:             ((and (=& State 2) (=& c #/s))
                    218:              (setq State 3))
                    219:             ((=& State 3)                      ; Read through arguments
                    220:              (cond ((=& c #\lf)
                    221:                     (setq State 4)
                    222:                     (untyi c inport))))        ; In case text starts immed.
                    223:             ((=& c #\eof)
                    224:              (setq EOF t)
                    225:              (return))
                    226:             (t
                    227:                 (setq State 0)))
                    228:        (tyo c outfile)))
                    229: 
                    230: (defun processblock nil
                    231:    ;
                    232:    ; Read lines until we come to one that has no blank space at its begining.
                    233:    ; Then process the previously accumulated lines.
                    234:    ; If the last line contains the directive .Le, then find the next block
                    235:    ; enclosed by .Ls.
                    236:    ;
                    237:    (do ((newline (getline) (getline)))
                    238:        (nil)
                    239:        (if (or EOF (and (zerop (car newline)) (cadr newline))) 
                    240:           then (flushlines)
                    241:                (setq lines nil)
                    242:                (if (=& (caadr newline) #/')    ;then must quote ' for troff
                    243:                    then (msg (P outfile) "\\")
                    244:                 elseif (and filtermode
                    245:                             (=& (caadr newline) #/.)
                    246:                             (=& (cadadr newline) #/L)
                    247:                             (=& (caddadr newline) #/e))
                    248:                    then (msg (P outfile) ".Le" N)
                    249:                         (return nil))
                    250:                (if EOF then (return nil)))
                    251:        (setq lines (cons newline lines))))
                    252: 
                    253: 
                    254: ;--- getline :: read in new line and return structure:
                    255: ; (spaces chars)
                    256: ; spaces is a fixnum giving the number of spaces before the first
                    257: ; non-blank on the line.
                    258: ; chars is the list of characters appearing on the line, in order.
                    259: ;
                    260: (defun getline nil
                    261:    (do ((col 1)
                    262:        (spaces 0)
                    263:        (chars nil)
                    264:        (spacemode t)
                    265:        (newc (tyi inport) (tyi inport) ))
                    266:        (nil)
                    267:        (if (=& #\eof newc) 
                    268:           then (if (null chars) 
                    269:                    then (setq EOF t)
                    270:                         (return nil)
                    271:                    else (setq newc #\lf)))
                    272:        (if (=& #\lf newc)
                    273:          then (if (null chars)
                    274:                  then ; for totally blank lines return a large
                    275:                       ; space count so this won't be used for tags
                    276:                       (return (list space-count nil))
                    277:                  else (return (list spaces (nreverse chars)))))
                    278:        (if (=& #\ff newc)
                    279:           then (return (list spaces (nreverse (cons newc chars)))))
                    280:        (if spacemode 
                    281:           then (if (=& #\sp newc)
                    282:                    then (setq spaces (1+ spaces))
                    283:                 elseif (=& #\tab newc)
                    284:                    then (setq spaces  (* (/ (+ spaces 8) 8) 8))
                    285:                    else (setq spacemode nil
                    286:                               chars (list newc)))
                    287:           else (setq chars (cons newc chars)))))
                    288:                        
                    289: 
                    290: ;--- flushlines
                    291: ; go back on all lines and determine where to put tags and reference
                    292: ; tags.
                    293: ;
                    294: (defun flushlines nil
                    295:   (let (thistag tagref rlines tagloc)
                    296:        (inittagslist '(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
                    297:                         a b c d e f g h i j k l m n o p q r s t u v w x y z
                    298:                         1 2 3 4 5 6 7 8 9 0))
                    299:        (setq tagref nil tagloc nil rlines nil)
                    300:        (do ((xx lines (cdr xx))
                    301:            (thistagloc nil nil)
                    302:            (pendingtags)
                    303:            (thistagref))
                    304:           ((null xx))
                    305:           (setq rlines (cons (car xx) rlines)
                    306:                 spaces (caar xx)
                    307:                 thistag (alloctag))
                    308:           ; determine which of the pending tags we can insert at this level
                    309:           (do ((yy pendingtags (cdr yy)))
                    310:               ((or (null yy) (>& spaces (caar yy)))
                    311:                (setq pendingtags yy))
                    312:               (setq thistagloc (cons (car yy) thistagloc)))
                    313:           (setq tagloc (cons thistagloc tagloc))
                    314:           ; free up the tags we allocated at this level.
                    315:           (mapc '(lambda (x) (freetag (cadr x))) thistagloc)
                    316:           ;
                    317:           ; we only need to refer to a tags at this level if 
                    318:           ; we are not at the left edge of the paper
                    319:           ;
                    320:           (if (and (greaterp spaces 0) (cdr xx))
                    321:               then (setq tagref (cons thistag tagref))
                    322:                    (setq pendingtags (addtotags spaces thistag pendingtags))
                    323:               else (setq tagref (cons nil tagref))))
                    324:        (if debug then (msg " **tagref = " tagref N " **tagloc = " tagloc N))
                    325:        ;
                    326:        ; print out the lines. 
                    327:        ; the lines we want to print are in the list rlines.  They are 
                    328:        ; in the correct order.
                    329:        ;
                    330:        (do ((yy rlines (cdr yy))
                    331:            (commentmode nil nil)
                    332:            (escapemode nil nil))
                    333:           ((null yy))
                    334:           ; first print out spaces
                    335:           (setq sps (caar yy) 
                    336:                 chs (cadar yy)
                    337:                 tls (car tagloc)
                    338:                 trname (car tagref))
                    339:           (headercheck sps chs)
                    340:           (if debug
                    341:               then (msg " spaces " sps N " chs " chs N
                    342:                         " tagloc " (car tagloc) N " tagref " (car tagref) N))
                    343:           (setq spout 0)
                    344:           ; if there are characters on this line, print out
                    345:           ; leading spaces
                    346:           (if chs
                    347:              then (do ()
                    348:                       ((eq spout sps))
                    349:                       (tyo #\sp outfile)
                    350:                       (setq spout (1+ spout)))
                    351: 
                    352:                   (if trname then (tagrefprint trname)))
                    353:           
                    354:           (do ((xx chs (cdr xx)))
                    355:               ((null xx)
                    356:                (if (and tls (not (<& (caar tls) spout)))
                    357:                    then (do ((i spout (1+ i)))
                    358:                             ((null tls))
                    359:                             (if (=& (caar tls) i) 
                    360:                                 then (taglocprint (cadar tls))
                    361:                                      (setq tls (cdr tls)))))
                    362:                (if commentmode then (msg (P outfile) "\\fP"))
                    363:                (terpr outfile))
                    364:               (if (and tls (eq (caar tls) spout))
                    365:                   then (taglocprint (cadar tls))
                    366:                        (setq tls (cdr tls)))
                    367:               (if (and (not escapemode) 
                    368:                        (null commentmode) 
                    369:                        (=& #/; (car xx)))
                    370:                   then (msg (P outfile) "\\fI")
                    371:                        (setq commentmode t)
                    372:                elseif (=& #/\ (car xx))
                    373:                   then (tyo #/\ outfile))      ; escape backslashes
                    374:               (if (memq (car xx) '(#/\ #//))
                    375:                   then (setq escapemode t)
                    376:                   else (setq escapemode nil))
                    377:               (if (=& (car xx) #\ff)
                    378:                   then (msg (P outfile) N ".bp" N)
                    379:                   else (tyo (car xx) outfile))
                    380:               (setq spout (1+ spout)))
                    381:           (setq tagloc (cdr tagloc)
                    382:                 tagref (cdr tagref)))))
                    383: 
                    384: 
                    385: ; headercheck :: check if this is a function declaration.
                    386: ; currently this means that there are no more than 2 spaces before
                    387: ; the line begins and that the line begins with (defxxx  <name>)
                    388: (defun headercheck (spaces chars)
                    389:   (if (<& spaces 3)
                    390:       then (if (setq rest (match chars '(#/( #/d #/e #/f)))
                    391:               then (setq funcname (skippastblkn rest))
                    392:                    (if (and funcname LabelFunctions)
                    393:                        then (msg (P outfile) ".Lf " funcname N)))))
                    394: 
                    395: ;--- match :: match lists 
                    396: ;      list1 - list of characters (fixnum rep)
                    397: ;      list2 - master list of characters (fixnum rep)
                    398: ; list2 should be shorter than list1. If list2 is a substring of list1
                    399: ; then the rest of list1 will be returned.  Otherwise nil is returned.
                    400: ;
                    401: (defun match (list1 list2)
                    402:   (cond ((null list1) nil)
                    403:        ((null list2) list1)
                    404:        ((or (eq (car list1) (car list2))
                    405:             (eq (car list1) (uppercase (car list2))))
                    406:         (match (cdr list1) (cdr list2)))
                    407:        (t nil)))
                    408: 
                    409: ;--- uppercase :: convert fixnum rep to upper case
                    410: ;      char - fixnum representation of character
                    411: ; convert character to upper case.
                    412: ;
                    413: (defun uppercase (ch)
                    414:   (if (and (not (<& ch #/a)) (not (>& ch #/z)))
                    415:       then (- ch #.(- #/a #/A))))
                    416: 
                    417: 
                    418: 
                    419: ;--- skippastblnk :: skip to and past blank field and return following name
                    420: ;      list - list of characters (fixnums)
                    421: ;
                    422: ; We skip past all non blanks then all blanks and finally implode the next 
                    423: ; word after that and return it.  
                    424: ;
                    425: ; bug- we can't tell the difference between a function named nil and
                    426: ; no valid function, but then again you can't have a function named nil.
                    427: ;
                    428: (defun skippastblkn (list)
                    429:    (let (res)
                    430:       ; skip to first blank
                    431:       (do ()
                    432:          ((null list) nil)
                    433:          (if (=& (car list) #\sp) then (return nil))
                    434:          (setq list (cdr list)))
                    435:       ; skip to first non-blank
                    436:       (do ()
                    437:          ((null list) nil)
                    438:          (if (not (=& (car list) #\sp)) then (return nil))
                    439:          (setq list (cdr list)))
                    440:       ; collect non blanks
                    441:       (if list 
                    442:         then (do ()
                    443:                  ((null list))
                    444:                  (if (and (=& #\lpar (car list))
                    445:                           (null res))
                    446:                     then (setq list (cdr list)) ; form like "defun (foo ..)"
                    447:                   elseif (or (=& #\lpar (car list))
                    448:                              (=& #\rpar (car list))
                    449:                              (=& #\sp (car list)))
                    450:                     then (return nil)
                    451:                     else (setq res (cons (car list) res))
                    452:                          (setq list (cdr list))))
                    453:              (if res then (implode (nreverse res))))))
                    454: 
                    455: ;
                    456: ; add (spaces character) to list so that the spaces number are in 
                    457: ; ascending order.
                    458: ;
                    459: (defun addtotags (spaces character oldlist)
                    460:   (if (or (null oldlist) (>& spaces (caar oldlist)))
                    461:       then (cons (list spaces character) oldlist)
                    462:       else (do ((prevtag oldlist (cdr prevtag))
                    463:                (thistag (cdr oldlist) (cdr thistag)))
                    464:               ((or (null thistag) (>& spaces (caar thistag)))
                    465:                (setq thistag (cons (list spaces character) thistag))
                    466:                (rplacd prevtag thistag)))))
                    467: 
                    468: (defun inittagslist (list)
                    469:   (setq tagsleft list))
                    470: 
                    471: (defun alloctag nil
                    472:   (if (null tagsleft) 
                    473:       then (msg "Out of tags, aauuuuggh " N) 
                    474:            (exit)
                    475:       else (prog1 (car tagsleft) (setq tagsleft (cdr tagsleft)))))
                    476: 
                    477: (defun freetag (tagname)
                    478:   (setq tagsleft (cons tagname tagsleft)))
                    479: 
                    480: 
                    481: (defun taglocprint (name)
                    482:   (msg (P outfile) "\\k" name))
                    483: 
                    484: 
                    485: (defun tagrefprint (name)
                    486:   (msg (P outfile)  "\\h'|\\n" name "u'"))
                    487: 
                    488: 
                    489: ;---new stuff
                    490: ;
                    491: ;--- programs deal in lineblk's
                    492: ; A lineblk has these components:
                    493: ;      class : normal or comment
                    494: ;              comment is a line beginning with ;, in which case it is
                    495: ;              not counted as far as spacing goes.
                    496: ;      spaces : number of spaces before first useful info
                    497: ;      dead : list of dead linblk's, that is those ready to print but
                    498: ;             waiting for this line to be done.
                    499: ;      tagref: tag to go to at the beginning of this line
                    500: ;      tagloc : tags defined on this line
                    501: ;      chars : list of characters to print
                    502: 
                    503: (defun make-lineblk (class spaces chars)
                    504:    (list class spaces nil nil nil chars))
                    505: (defmacro get:class (lineblk) `(car ,lineblk))
                    506: (defmacro set:class (lineblk val) `(setf (get:class ,lineblk) ,val))
                    507: (defmacro get:spaces (lineblk) `(cadr ,lineblk))
                    508: (defmacro set:spaces (lineblk val) `(setf (get:spaces ,lineblk) ,val))
                    509: (defmacro get:dead (lineblk) `(caddr ,lineblk))
                    510: (defmacro set:dead (lineblk val) `(setf (get:dead ,lineblk) ,val))
                    511: (defmacro get:tagref (lineblk) `(cadddr ,lineblk))
                    512: (defmacro set:tagref (lineblk val) `(setf (get:tagref ,lineblk) ,val))
                    513: (defmacro get:tagloc (lineblk) `(caddddr ,lineblk))
                    514: (defmacro set:tagloc (lineblk val) `(setf (get:tagloc ,lineblk) ,val))
                    515: (defmacro get:chars (lineblk) `(cadddddr ,lineblk))
                    516: (defmacro set:chars (lineblk val) `(setf (get:chars ,lineblk) ,val))
                    517: 
                    518:    
                    519: (defun vlp-interrupt-routine (sig)
                    520:    (if (and (boundp 'outfilename) outfilename)
                    521:       then (sys:unlink outfilename))
                    522:    (exit 1))

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.