Annotation of 43BSDTahoe/ucb/lisp/liszt/lxref.l, revision 1.1

1.1     ! root        1: (setq rcs-lxref-ident
        !             2:    "$Header: lxref.l,v 1.2 84/02/03 08:04:37 jkf Exp $")
        !             3: 
        !             4: ;------   lxref: lisp cross reference program        
        !             5: ;-- author: j foderaro
        !             6: ;  This program generates a cross reference listing of a set of one or
        !             7: ; more lisp files.  It reads the output of cross reference files 
        !             8: ; generated by the compiler.  These files usually have the extension .x .
        !             9: ; the .x files are lisp readable.  There format is:
        !            10: ; The first s-expression is (File  <filename>) where <filename> is the
        !            11: ; name of the lisp source file.
        !            12: ; Then there is one s-expression for each function (including macros)
        !            13: ; which is defined in the file.  The car of each expression is the function
        !            14: ; name, the cadr is the function type and the cddr is a list of those
        !            15: ; functions called
        !            16: ; 
        !            17: ; lxref can be run from the command level
        !            18: ; % lxref foo.x bar.x
        !            19: ; or in this way
        !            20: ; % lxref
        !            21: ; -> (lxref foo.x bar.x)
        !            22: ;
        !            23: ; There is one option, that is changing the ignorelevel.  If a function
        !            24: ; is called by more than ignorelevel functions then all those functions
        !            25: ; are listed, instead a summary of the number of calls is printed.  This
        !            26: ; is useful for preventing  the printing of massive lists for common
        !            27: ; system functions such as setq.
        !            28: ; To change the ignorelevel to 40 you would type:
        !            29: ;
        !            30: ; % lxref -40 foo.x bar.x
        !            31: ;
        !            32: ;; internal data structures used in lxref:
        !            33: ;   funcs : list of functions mentioned either as caller or as callee
        !            34: ;  on each function in funcs, the property list contains some of these
        !            35: ;  indicators:
        !            36: ;      i-seen : always contains t [this is so we can avoid (memq foo funcs)
        !            37: ;      i-type : list of the types this function was declared as. In 1-1
        !            38: ;               corresp with i-home
        !            39: ;      i-home : list of files this function was declared in. In 1-1 corresp
        !            40: ;               with i-type
        !            41: ;      i-callers: list of functions calling this function
        !            42: 
        !            43: 
        !            44: 
        !            45: 
        !            46: 
        !            47: ; insure we have plenty of space to grow into
        !            48: (opval 'pagelimit 9999)
        !            49: 
        !            50: 
        !            51: (declare (special xref-readtable width ignorefuncs ignorelevel readtable 
        !            52:                  user-top-level poport i-seen i-type i-callers docseen
        !            53:                  i-Chome i-Doc i-home funcs
        !            54:                  callby-marker debug-mode
        !            55:                  anno-off-marker liszt-internal
        !            56:                  anno-on-marker))
        !            57: 
        !            58: (setq ignorelevel 50)
        !            59: (setq callby-marker   (exploden ";.. ")        
        !            60:       anno-off-marker (exploden ";.-") 
        !            61:       anno-on-marker  (exploden ";.+"))        
        !            62: 
        !            63: ; internal liszt functions
        !            64: (setq liszt-internal '(Internal-bcdcall liszt-internal-do))
        !            65: 
        !            66: ;--- xrefinit :: called automatically upon startup
        !            67: ;
        !            68: (def xrefinit
        !            69:    (lambda nil
        !            70:       (let ((args (command-line-args))
        !            71:            (retval))
        !            72:         ; readtable should be the same as it was when liszt wrote
        !            73:         ; the xref file
        !            74:         (if args
        !            75:            then (signal 2 'exit)       ; die on interrupt
        !            76:                 (signal 15 'exit)      ; die on sigterm
        !            77:                 (setq user-top-level nil)
        !            78:                 (let ((retval (car (errset (funcall 'lxref args)))))
        !            79:                    (exit (if retval thenret else -1)))
        !            80:            else (patom "Lxref - lisp cross reference program")
        !            81:                 (terpr poport)
        !            82:                 (setq user-top-level nil)))))
        !            83: 
        !            84: (setq user-top-level 'xrefinit)
        !            85: 
        !            86: ;--- lxref :: main function
        !            87: ;
        !            88: (defun lxref fexpr (files)
        !            89:    (prog (p funcs i-seen i-home i-type i-callers filenm caller callee name
        !            90:            home type caller temp fname callers clength i-Chome i-Doc docseen
        !            91:            Chome Doc anno-mode debug-mode)
        !            92: 
        !            93:       (setq xref-readtable (makereadtable t))
        !            94:       (setq i-seen (gensym) i-home (gensym) i-type (gensym)
        !            95:            i-callers (gensym) i-Chome (gensym) i-Doc (gensym))
        !            96: 
        !            97:       ; check for the ignorelevel option
        !            98:       ; it must be the first option given.
        !            99:       ;
        !           100:       (If (and files (eq #/- (getcharn (car files) 1)))
        !           101:         then (If (fixp
        !           102:                     (setq temp (readlist (cdr (explode (car files))))))
        !           103:                 then (setq ignorelevel temp)
        !           104:                      (setq files (cdr files))))
        !           105: 
        !           106:       ; process all files.  if a -a is seen, go into annotate mode.
        !           107:       ; otherwise generate an xref file.
        !           108:       ;
        !           109:       (do ((ii files (cdr ii)))
        !           110:          ((null ii))
        !           111:          (if (eq '-d (car ii))
        !           112:             then (setq debug-mode t)
        !           113:           elseif anno-mode
        !           114:             then (process-annotate-file (car ii))
        !           115:           elseif (eq '-a (car ii))
        !           116:             then (setq anno-mode t)
        !           117:             else (process-xref-file (car ii))))
        !           118:       (if (not anno-mode) (generate-xref-file))
        !           119:       (return 0)))
        !           120: 
        !           121: ;.. process-xref-file
        !           122: (defun illegal-file (name)
        !           123:    (msg "File " name " is not a valid cross reference file" N))
        !           124: 
        !           125: ;--- process-xref-file :: scan the information in an xref file
        !           126: ; if the name ends in .l then change it to .x
        !           127: ;
        !           128: ;.. lxref
        !           129: (defun process-xref-file (name)
        !           130:    (if debug-mode then (msg "process-xref-file: " name N))
        !           131:    (let (p fname filenm)
        !           132:       ; convert foo.l to foo.x
        !           133:       (setq fname (nreverse (exploden name)))
        !           134:       (If (and (eq #/l (car fname)) (eq #/. (cadr fname)))
        !           135:         then (setq fname (implode (nreverse (cons #/x (cdr fname)))))
        !           136:         else (setq fname name))
        !           137: 
        !           138:       ; now look for foo or foo.x
        !           139:       (If (and (null (errset (setq p (infile fname)) nil))
        !           140:               (null (errset (setq p (infile (concat fname ".x"))) nil)))
        !           141:         then (msg "Couldn't open " name N)
        !           142:         else (setq filenm (car (errset (read p))))
        !           143:              (If (dtpr filenm)
        !           144:                 then (If (eq 'File (car filenm))
        !           145:                         then (setq filenm (cadr filenm))
        !           146:                              (process-File p filenm)
        !           147:                       elseif (eq 'Chome (car filenm))
        !           148:                         then (process-Chome p)
        !           149:                       elseif (eq 'Doc (car filenm))
        !           150:                         then (setq docseen t) (process-Doc p)
        !           151:                         else (illegal-file name))
        !           152:                 else (illegal-file name))
        !           153:              (close p))))
        !           154: 
        !           155: 
        !           156: ;--- process-File :: process an xref file from liszt
        !           157: ;
        !           158: ;.. process-xref-file
        !           159: (defun process-File (p filenm)
        !           160:    (let ((readtable xref-readtable))
        !           161:       (do ((jj (read p) (read p))
        !           162:           (caller)
        !           163:           (callee))
        !           164:          ((null jj) (close p))
        !           165:          (setq caller (car jj))
        !           166:          (If (not (get caller i-seen))
        !           167:             then (putprop caller t i-seen)
        !           168:                  (push caller funcs))  ; add to global list
        !           169:          ; remember home of this function (and allow multiple homes)
        !           170:          (push filenm (get caller i-home))
        !           171: 
        !           172:          ; remember type of this function (and allow multiple types)
        !           173:          (push (cadr jj) (get caller i-type))
        !           174: 
        !           175:          ; for each function the caller calls
        !           176:          (do ((kk (cddr jj) (cdr kk)))
        !           177:              ((null kk))
        !           178:              (setq callee (car kk))
        !           179:              (If (not (get callee i-seen)) then (putprop callee t i-seen)
        !           180:                  (push callee funcs))
        !           181:              (push (cons caller filenm) (get callee i-callers))))))
        !           182: 
        !           183: ;.. process-xref-file
        !           184: (defun process-Chome (p)
        !           185:    (do ((jj (read p) (read p))
        !           186:        (caller))
        !           187:        ((null jj) (close p))
        !           188:        (setq caller (car jj))
        !           189:        (If (not (get caller i-seen))
        !           190:           then (putprop caller t i-seen)
        !           191:           (push caller funcs)) ; add to global list
        !           192:        ; remember home of this function (and allow multiple homes)
        !           193:        (putprop caller (cons (cdr jj) (get caller i-Chome)) i-Chome)))
        !           194: 
        !           195: ;--- process-Doc :: process a Doc file
        !           196: ;
        !           197: ; A doc file begins with an entry (Doc).
        !           198: ; subsequent entries are (Name File)  and this means that function
        !           199: ; Name is defined in file File.  This type of file is generated
        !           200: ; by a sed and awk script passing over the franz manual. (see the
        !           201: ; Makefile in the doc directory).
        !           202: ;
        !           203: ;.. process-xref-file
        !           204: (defun process-Doc (p)
        !           205:    (do ((jj (read p) (read p))
        !           206:        (caller))
        !           207:        ((null jj) (close p))
        !           208:        (setq caller (car jj))
        !           209:        (If (not (get caller i-seen))
        !           210:           then (putprop caller t i-seen)
        !           211:           (push caller funcs)) ; add to global list
        !           212:        ; remember home of this function (and allow multiple homes)
        !           213:        (putprop caller (cons (cadr jj) (get caller i-Doc)) i-Doc)))
        !           214: 
        !           215: ;.. generate-xref-file
        !           216: (defun terprchk (wid)
        !           217:   (cond ((> (setq width (+ wid width)) 78.) 
        !           218:         (terpr)
        !           219:         (patom "       ")
        !           220:         (setq width (+ 8 wid)))))
        !           221: 
        !           222: ; determine type of function
        !           223: ;.. generate-xref-file
        !           224: (defun typeit (fcn)
        !           225:   (cond ((bcdp fcn) (getdisc fcn))
        !           226:        ((dtpr fcn) (car fcn))))
        !           227: 
        !           228: 
        !           229: ;.. lxref
        !           230: (defun generate-xref-file ()
        !           231:    ; sort alphabetically
        !           232:    (setq funcs (sort funcs 'alphalessp))
        !           233: 
        !           234:    ; now print out the cross reference
        !           235:    (do ((ii funcs (cdr ii))
        !           236:        (name) (home) (type) (callers) (Chome) (Doc) (clength))
        !           237:        ((null ii))
        !           238:        (setq name (car ii)
        !           239:             home (get name i-home)
        !           240:             type (get name i-type)
        !           241:             callers (get name i-callers)
        !           242:             Chome (get name i-Chome)
        !           243:             Doc (get name i-Doc))
        !           244: 
        !           245:        (If (lessp (setq clength (length callers)) ignorelevel)
        !           246:          then (setq callers (sortcar callers 'alphalessp)))
        !           247: 
        !           248:        (do ((xx Chome (cdr xx)))
        !           249:           ((null xx))
        !           250:           (setq home (cons (concat "<C-code>:" (caar xx))
        !           251:                            home)
        !           252:                 type (cons (cadar xx) type)))
        !           253: 
        !           254:        (If (null home)
        !           255:          then (setq home (If (getd name)
        !           256:                             then (setq type
        !           257:                                        (ncons (typeit (getd name))))
        !           258:                                  '(Franz-initial)
        !           259:                           elseif (memq name liszt-internal)
        !           260:                             then '(liszt-internal-function)
        !           261:                           elseif (get name 'autoload)
        !           262:                             then (list (concat "autoload: "
        !           263:                                                (get name 'autoload)))
        !           264:                             else '(Undefined))))
        !           265: 
        !           266:        (patom name)
        !           267:        (patom "        ")
        !           268: 
        !           269: 
        !           270:        (If (null (cdr type))
        !           271:          then (patom (car type))
        !           272:               (patom " ")
        !           273:               (patom (car home))
        !           274:          else (patom "Mult def: ")
        !           275:               (mapcar '(lambda (typ hom)
        !           276:                           (patom typ)
        !           277:                           (patom " in ")
        !           278:                           (patom hom)
        !           279:                           (patom ", "))
        !           280:                       type
        !           281:                       home))
        !           282: 
        !           283: 
        !           284:        (If docseen
        !           285:          then (If Doc then (msg "  [Doc: " (If (cdr Doc) then Doc
        !           286:                                               else (car Doc)) "]")
        !           287:                  else (msg "  [**undoc**]")))
        !           288:        (If (null callers) then (msg "  *** Unreferenced ***"))
        !           289:        (terpr)
        !           290:        (patom "        ")
        !           291:        (cond ((null callers))
        !           292:             ((not (lessp clength ignorelevel))
        !           293:              (patom "Called by ")
        !           294:              (print clength)
        !           295:              (patom " functions"))
        !           296:             (t (do ((jj callers (cdr jj))
        !           297:                     (calle)
        !           298:                     (width 8))
        !           299:                    ((null jj))
        !           300:                    ; only print name if in same file
        !           301:                    (setq calle (caar jj))
        !           302:                    (cond ((memq (cdar jj) home)
        !           303:                           (terprchk (+ (flatc calle) 2))
        !           304:                           (patom calle))
        !           305:                          (t (terprchk (+ (flatc calle) 6 (flatc (cdar jj))))
        !           306:                             (patom calle)
        !           307:                             (patom " in ")
        !           308:                             (patom (cdar jj))))
        !           309:                    (If (cdr jj) then (patom ", ")))))
        !           310:        (terpr)
        !           311:        (terpr)
        !           312:        botloop ))
        !           313: 
        !           314: 
        !           315: ;--- annotate code
        !           316: 
        !           317: 
        !           318:                   
        !           319: ;--- process-annotate-file :: anotate a file
        !           320: ;
        !           321: ;.. lxref
        !           322: (defun process-annotate-file (filename)
        !           323:    (let (sourcep outp)
        !           324:       ; make sure file exists and write annotate file as a
        !           325:       ; file with the prefix #,
        !           326:       (if (null (errset (setq sourcep (infile filename))))
        !           327:         then (msg "will ignore that file " N)
        !           328:         else ; will write to file.A (erasing the final l)
        !           329:              (let ((filen (concat "#," filename)))
        !           330:                 (setq outp (outfile filen))
        !           331:                 (anno-it sourcep outp)
        !           332:                 (close outp)
        !           333:                 (close sourcep)
        !           334:                 ; now mv the original filename to #dfilename
        !           335:                 ; and the annotated file to the original file
        !           336:                 (let ((oldcopy (concat "#." filename)))
        !           337:                    (if (null (errset
        !           338:                                 (progn (if (probef oldcopy)
        !           339:                                           then (sys:unlink oldcopy))
        !           340:                                        (sys:link filename oldcopy)
        !           341:                                        (sys:unlink filename)
        !           342:                                        (sys:link filen filename)
        !           343:                                        (sys:unlink filen))))
        !           344:                       then (msg "An error occured while mving files around "
        !           345:                                 N
        !           346:                                 "files possibly affected "
        !           347:                                 filename oldcopy filen)))))))
        !           348: 
        !           349: 
        !           350: ;.. process-annotate-file
        !           351: (defun anno-it (inp outp)
        !           352:    (do ((xx (read-a-line inp) (read-a-line inp))
        !           353:        (anno-it t))
        !           354:        ((null xx))
        !           355:        (if (match xx 1 callby-marker)  ; flush anno lines
        !           356:          then (flush-a-line outp inp)
        !           357:        elseif (match xx 1 anno-off-marker)
        !           358:          then (setq anno-it nil)       ; ';#-'  turns off annotating
        !           359:               (write-a-line xx outp inp)
        !           360:        elseif (match xx 1 anno-on-marker)
        !           361:          then (setq anno-it t)
        !           362:               (write-a-line xx outp inp)
        !           363:          else (if anno-it then (anno-check xx outp))
        !           364:               (write-a-line xx outp inp))))
        !           365: 
        !           366: 
        !           367: ;;; file reading code for annotate function
        !           368: ; lines are read with (read-a-line port).  It will read up to the
        !           369: ; first 127 characters in the line, returning a hunk whose cxr 0 is the
        !           370: ; max(index) + 1 of the characters in the hunk.  the oversize-line flag
        !           371: ; will be set if there are still more character to be read from this line.
        !           372: ;
        !           373: ; the line should be printed by calling (print-a-line buffer) or if it isn't
        !           374: ; to be printed, (flush-a-line) should be called (which will check the
        !           375: ; oversize-line flag and flush unread input too).
        !           376: ;
        !           377: (declare (special inp-buffer oversize-line))
        !           378: 
        !           379: (setq inp-buffer (makhunk 128))
        !           380: 
        !           381: ;.. anno-it
        !           382: (defun read-a-line (port)
        !           383:    (setq oversize-line nil)
        !           384:    (do ((i 1 (1+ i))
        !           385:        (ch (tyi port) (tyi port)))
        !           386:        ((or (eq #\newline ch)
        !           387:            (eq #\eof ch))
        !           388:        (if (or (eq #\newline ch) (>& i 1))
        !           389:           then (rplacx 0 inp-buffer i)         ; store size
        !           390:                inp-buffer                      ; return buffer
        !           391:           else nil))   ; return nil upon eof
        !           392:        (rplacx i inp-buffer ch)
        !           393:        (if (>& i 126)
        !           394:          then (setq oversize-line t)
        !           395:               (rplacx 0 inp-buffer (1+ i))
        !           396:               (return inp-buffer))))
        !           397: 
        !           398: ;--- write-a-line :: write the given buffer and check for oversize-line
        !           399: ;
        !           400: ;.. anno-it
        !           401: (defun write-a-line (buf oport iport)
        !           402:    (do ((max (cxr 0 buf))
        !           403:        (i 1 (1+ i)))
        !           404:        ((not (<& i max))
        !           405:        (if oversize-line
        !           406:            then (oversize-check oport iport t)
        !           407:            else (terpr oport)))
        !           408:        (tyo (cxr i buf) oport)))
        !           409: 
        !           410: ;.. anno-it
        !           411: (defun flush-a-line (oport iport)
        !           412:    (oversize-check oport iport nil))
        !           413: 
        !           414: ;.. flush-a-line, write-a-line
        !           415: (defun oversize-check (oport iport printp)
        !           416:    (if oversize-line
        !           417:       then (do ((ch (tyi iport) (tyi iport)))
        !           418:               ((or (eq ch #\eof) (eq ch #\newline))
        !           419:                (cond ((and printp (eq ch #\newline))
        !           420:                       (tyo ch oport))))
        !           421:               (if printp then (tyo ch oport)))))
        !           422: 
        !           423:        
        !           424:                       
        !           425: ;.. anno-it
        !           426: (defun anno-check (buffer outp)
        !           427:    (if (match buffer 1 '(#\lpar #/d #/e #/f))
        !           428:       then (let (funcname)
        !           429:              (if (setq funcname (find-func buffer))
        !           430:                  (let ((recd (get funcname i-callers)))
        !           431:                     (if recd
        !           432:                        then (printrcd recd outp)))))))
        !           433: 
        !           434: ;--- printrcd :: print a description
        !           435: ;
        !           436: ;.. anno-check
        !           437: (defun printrcd (fcns port)
        !           438:    (let ((functions (sortcar fcns 'alphalessp)))
        !           439:       (print-rec functions port 0)))
        !           440: 
        !           441: ;.. print-rec, printrcd
        !           442: (defun print-rec (fcns p wide)
        !           443:    (if fcns
        !           444:       then (let ((size (flatc (caar fcns))))
        !           445:              (if (>& (+ size wide 2) 78)
        !           446:                 then (msg (P p) N )
        !           447:                      (setq wide 0))
        !           448:              (if (=& wide 0)
        !           449:                 then (mapc '(lambda (x) (tyo x p)) callby-marker)
        !           450:                      (setq wide (length callby-marker)))
        !           451:              (if (not (=& wide 4))
        !           452:                 then (msg (P p) ", ")
        !           453:                      (setq wide (+ wide 2)))
        !           454:              (msg (P p) (caar fcns))
        !           455:              (print-rec (cdr fcns) p (+ wide size 2)))
        !           456:       else (msg (P p) N)))
        !           457: 
        !           458:                      
        !           459:                    
        !           460: ;--- match :: try to locate pattern in buffer
        !           461: ; start at 'start' in buf.
        !           462: ;.. anno-check, anno-it, match
        !           463: (defun match (buf start pattern)
        !           464:    (if (null pattern)
        !           465:       then t
        !           466:     elseif (and (<& start (cxr 0 buf))
        !           467:            (eq (car pattern) (cxr start buf)))
        !           468:       then (match buf (1+ start) (cdr pattern))))
        !           469: 
        !           470: ;--- find-func :: locate function name on line
        !           471: ;
        !           472: ;.. anno-check
        !           473: (defun find-func (buf)
        !           474:    ; first locate first space or tab
        !           475:    (do ((i 1 (1+ i))
        !           476:        (max (cxr 0 buf))
        !           477:        (die))
        !           478:        ((or (setq die (not (<& i max)))
        !           479:            (memq (cxr i buf) '(#\space #\tab)))
        !           480:        (if die
        !           481:           then nil     ; can find it, so give up
        !           482:           else ; find first non blank
        !           483:                (do ((ii i (1+ ii)))
        !           484:                    ((or (setq die (not (<& ii max)))
        !           485:                         (not (memq (cxr ii buf) '(#\space #\tab))))
        !           486:                     (if (or die (eq (cxr ii buf) #\lpar))
        !           487:                        then nil
        !           488:                        else ; fid first sep or left paren
        !           489:                             (do ((iii (1+ ii) (1+ iii)))
        !           490:                                 ((or (not (<& iii max))
        !           491:                                      (memq (cxr iii buf)
        !           492:                                            '(#\space #\tab #\lpar)))
        !           493:                                  (implode-fun buf ii (1- iii)))))))))))
        !           494: 
        !           495: ;--- implode-fun :: return implode of everything between from and to in buf
        !           496: ;
        !           497: ;.. find-func
        !           498: (defun implode-fun (buf from to)
        !           499:    (do ((xx (1- to) (1- xx))
        !           500:        (res (list (cxr to buf)) (cons (cxr xx buf) res)))
        !           501:        ((not (<& from xx))
        !           502:        (implode (cons (cxr from buf) res)))))
        !           503: 
        !           504: 
        !           505: 
        !           506: 
        !           507: 

unix.superglobalmegacorp.com

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