Annotation of 43BSD/ucb/lisp/lisplib/common1.l, revision 1.1.1.1

1.1       root        1: (setq rcs-common1-
                      2:    "$Header: common1.l,v 1.9 84/01/06 14:21:46 sklower Exp $")
                      3: 
                      4: ;;
                      5: ;; common1.l                           -[Sun Sep  4 14:04:15 1983 by jkf]-
                      6: ;;
                      7: ;;   common lisp functions.  These are the most common lisp functions
                      8: ;; [which don't have to be defined in common0.l in order to support 
                      9: ;;  the macros]
                     10: ;;
                     11: 
                     12: (declare (macros t))           ;; compile macros in this file
                     13: 
                     14: ;--- Section 0 - variables
                     15: (declare (special Standard-Input Standard-Output Standard-Error
                     16:                  lisp-library-directory))
                     17: 
                     18: (or (boundp 'lisp-library-directory)
                     19:    (setq lisp-library-directory '/usr/lib/lisp))
                     20: 
                     21: 
                     22: ;--- Section 0 - equivalences
                     23: ; 
                     24: (defmacro make-equivalent (a b)
                     25:    `(progn (putd ',a (getd ',b))
                     26:           (putprop ',a (get ',b 'fcn-info) 'fcn-info)))
                     27: 
                     28: (make-equivalent abs absval)
                     29: (make-equivalent add sum)
                     30: (make-equivalent bcdcall funcall)
                     31: (make-equivalent chrct charcnt)
                     32: (make-equivalent diff difference)
                     33: (make-equivalent numbp  numberp)
                     34: (make-equivalent remainder mod)
                     35: (make-equivalent terpri terpr)
                     36: (make-equivalent typep type)
                     37: (make-equivalent symeval eval)
                     38: (make-equivalent < lessp)
                     39: (make-equivalent <& lessp)     ; fixnum version
                     40: (make-equivalent = equal)
                     41: (make-equivalent =& equal)     ; fixnum version
                     42: (make-equivalent > greaterp)
                     43: (make-equivalent >& greaterp)  ; fixnum version
                     44: (make-equivalent *dif difference)
                     45: (make-equivalent \\ mod) 
                     46: (make-equivalent \1+$ add1)
                     47: (make-equivalent \1-$ sub1)
                     48: (make-equivalent *$ times)
                     49: (make-equivalent /$ quotient)
                     50: (make-equivalent +$ add)
                     51: (make-equivalent -$ difference)
                     52: 
                     53: ;--- Section I - functions and macros
                     54: 
                     55: 
                     56: ;--- max - arg1 arg2 ... : sequence of numbe
                     57: ;      returns the maximum
                     58: ;
                     59: (def max
                     60:   (lexpr (nargs)
                     61:         (do ((i nargs (1- i))
                     62:              (max (arg 1)))
                     63:             ((< i 2) max)
                     64:             (cond ((greaterp (arg i) max) (setq max (arg i)))))))
                     65: 
                     66: 
                     67: ;--- catch form [tag]  
                     68: ;  catch is now a macro which translates to (*catch 'tag form)
                     69: ;
                     70: (def catch
                     71:   (macro (l)
                     72:         `(*catch ',(caddr l) ,(cadr l))))
                     73: 
                     74: ;--- throw form [tag]
                     75: ;  throw isnow a macro
                     76: ;
                     77: (def throw
                     78:   (macro (l)
                     79:         `(*throw ',(caddr l) ,(cadr l))))
                     80: 
                     81: 
                     82:       
                     83: ;--- desetq
                     84: ;      - pattern - pattern containing vrbl names
                     85: ;      - expr    - expression to be evaluated
                     86: ;
                     87: (defmacro desetq (&rest forms &aux newgen destrs)
                     88:   (do ((xx forms (cddr xx))
                     89:        (res)
                     90:        (patt)
                     91:        (expr))
                     92:       ((null xx) (cond ((null (cdr res)) (car res))
                     93:                       (t (cons 'progn (nreverse res)))))
                     94:       (setq patt (car xx) expr (cadr xx))
                     95:       (setq res 
                     96:            (cons (cond ((atom patt) `(setq ,patt ,expr))       ;trivial case
                     97:                        (t (setq newgen (gensym)
                     98:                                 destrs (de-compose patt '(r)))
                     99:                           `((lambda (,newgen)
                    100:                                     ,@(mapcar '(lambda (frm)
                    101:                                                        `(setq  ,(cdr frm) 
                    102:                                                                (,(car frm) ,newgen)))
                    103:                                               destrs)
                    104:                                     ,newgen)
                    105:                             ,expr)))
                    106:                  res))))
                    107: 
                    108: ;--- sassoc
                    109: ;      - x : form
                    110: ;      - y : assoc list
                    111: ;      - fcn : function or lambda expression
                    112: ; If (assoc x y) is non nil, then we apply the function fcn to nil.  
                    113: ; This must be written as a macro if we expect to handle the case of
                    114: ; a lambda expression as fcn in the compiler.  
                    115: ;
                    116: (defmacro sassoc (x y fcn)
                    117:   (cond ((or (atom fcn) (not (eq 'quote (car fcn))))
                    118:         `(or (assoc ,x ,y)
                    119:              (funcall ,fcn)))
                    120:        (t `(or (assoc ,x ,y)
                    121:                (,(cadr fcn))))))
                    122: 
                    123: ;--- sassq
                    124: ;      - x : form
                    125: ;      - y : assoc list
                    126: ;      - fcn : function or lambda expression
                    127: ; like sassoc above except it uses assq instead of assoc.
                    128: ;
                    129: (defmacro sassq (x y fcn)
                    130:   (cond ((or (atom fcn) (not (eq 'quote (car fcn))))
                    131:         `(or (assq ,x ,y)
                    132:              (funcall ,fcn)))
                    133:        (t `(or (assq ,x ,y)
                    134:                (,(cadr fcn))))))
                    135: 
                    136:                    
                    137: 
                    138: ;--- signp - test - unevaluated atom
                    139: ;         - value - evaluated value
                    140: ; test can be l, le, e, n, ge or g   with the obvious meaning
                    141: ; we return t if value compares to 0 by test
                    142: 
                    143: (defmacro signp (tst val)
                    144:   (setq tst  (cond ((eq 'l tst)  `(minusp signp-arg))
                    145:                   ((eq 'le tst) `(not (greaterp signp-arg 0)))
                    146:                   ((eq 'e tst)  `(zerop signp-arg))
                    147:                   ((eq 'n tst)  `(not (zerop signp-arg)))
                    148:                   ((eq 'ge tst) `(not (minusp signp-arg)))
                    149:                   ((eq 'g tst)  `(greaterp signp-arg 0))
                    150:                   (t (error "bad arg to signp " tst))))
                    151:   (cond ((atom val) `(and (numberp ,val) ,(subst val 'signp-arg tst)))
                    152:        (t `((lambda (signp-arg) (and (numberp signp-arg) ,tst))
                    153:             ,val))))
                    154: 
                    155: 
                    156: 
                    157: ;--- unwind-protect
                    158: ;  The form of a call to unwind-protect is
                    159: ;   (unwind-protect pform
                    160: ;                  form1 form2 ...)
                    161: ; and it works as follows:
                    162: ;  pform is evaluated, if nothing unusual happens, form1 form2 etc are
                    163: ;      then evaluated and unwind-protect returns the value of pform.
                    164: ;  if while evaluating pform, a throw or error caught by an errset which
                    165: ;   would cause control to pass through the unwind-protect, then
                    166: ;   form1 form2 etc are evaluated and then the error or throw continues.
                    167: ; Thus, no matter what happens, form1, form2 etc will be evaluated.
                    168: ;
                    169: (defmacro unwind-protect (protected &rest conseq &aux (localv (gensym 'G)))
                    170:   `((lambda (,localv)
                    171:            (setq ,localv (*catch 'ER%unwind-protect ,protected))
                    172:            ,@conseq
                    173:            (cond ((and (dtpr ,localv) (eq 'ER%unwind-protect (car ,localv)))
                    174:                   (I-throw-err (cdr ,localv)))
                    175:                  (t ,localv)))
                    176:     nil))
                    177: 
                    178: 
                    179: ;----Section III -- Interrupt handlers 
                    180: ; 
                    181: 
                    182: (def sys:fpeint-serv
                    183:    (lambda (x$) (error "Floating Exception ")))
                    184: 
                    185: (def sys:int-serv
                    186:    (lambda (dummy) (patom '"Interrupt:  ") (drain) (break)))
                    187: 
                    188: 
                    189: (signal 8 'sys:fpeint-serv)
                    190: (signal 2 'sys:int-serv)
                    191: 
                    192: 
                    193: ;---- Section IV - interrupt handlers
                    194: ;
                    195: (cond ((null (boundp '$gcprint))
                    196:        (setq $gcprint nil)))           ; dont print gc stats by default
                    197: 
                    198: (cond ((null (boundp '$gccount$))
                    199:        (setq $gccount$ 0)))
                    200: 
                    201: ;--- prtpagesused - [arg] : type of page allocated last time.
                    202: ;      prints a summary of pages used for certain selected types
                    203: ;      of pages.  If arg is given we put a star beside that type
                    204: ;      of page.  This is normally called after a gc.
                    205: ;
                    206: (def prtpagesused
                    207:   (lambda (space tottime gctime)
                    208:          (patom "[")
                    209:          (do ((curtypl (cond ((memq space '(list fixnum ))
                    210:                               '(list fixnum))
                    211:                              (t (cons space '(list fixnum))))
                    212:                        (cdr curtypl))
                    213:               (temp))
                    214:              ((null curtypl) (print 'ut:)
                    215:               (print (max 0 (quotient (times 100 (difference tottime gctime))
                    216:                                       tottime)))
                    217:               (patom "%]") (terpr))
                    218:              (setq temp (car curtypl))
                    219:              (cond ((greaterp (cadr (opval temp)) 0)
                    220:                     (cond ((eq space temp)
                    221:                            (patom '*)))
                    222:                     (patom temp)
                    223:                     (patom '":")
                    224:                     (print (cadr (opval temp)))
                    225:                     (patom '"{")
                    226:                     (print (fix (quotient 
                    227:                                  (times 100.0
                    228:                                         (car (opval temp)))
                    229:                                  (* (cadr (opval temp))
                    230:                                         (caddr (opval temp))))))
                    231:                     (patom '"%}")
                    232:                     (patom '"; "))))))
                    233: 
                    234: (declare (special gcafter-panic-mode $gccount$ $gc_midlim $gc_minalloc 
                    235:                  $gc_pct $gc_lowlim $gcprint ptimeatlastgc))
                    236: 
                    237: (setq gcafter-panic-mode nil)
                    238: (setq $gc_minalloc 10)
                    239: (setq $gc_lowlim 60)
                    240: (setq $gc_midlim 85)
                    241: (setq $gc_pct    .10)
                    242: (setq ptimeatlastgc (ptime))
                    243: 
                    244: ;--- gcafter - [s] : type of item which ran out forcing garbage collection.
                    245: ;      This is called after each gc.
                    246: ; the form of an opval element is  (number_of_items_in_use
                    247: ;                                  number_of_pages_allocated
                    248: ;                                  number_of_items_per_page)
                    249: ;
                    250: ;
                    251: (def gcafter 
                    252:   (nlambda (s)
                    253:           (prog (x pct amt-to-allocate thisptime diffptime difftottime
                    254:                    diffgctime)
                    255:                 (cond ((null s) (return)))  
                    256:                 (cond ((null (boundp '$gccount$)) (setq $gccount$ 0)))
                    257:                 (setq $gccount$ (1+ $gccount$))
                    258:                 (setq x (opval (car s)))
                    259:                 (setq thisptime (ptime)
                    260:                       difftottime (max  (difference (car thisptime)
                    261:                                                     (car ptimeatlastgc))
                    262:                                         1)
                    263:                       diffgctime (difference (cadr thisptime)
                    264:                                              (cadr ptimeatlastgc))
                    265:                       ptimeatlastgc thisptime)
                    266:                 ; pct is the percentage of space used
                    267:                 (setq pct (quotient (times 100 (car x))
                    268:                                     (max 1 (times (cadr x) (caddr x)))))
                    269:                 (setq amt-to-allocate
                    270:                       (cond (gcafter-panic-mode 
                    271:                              (cond ((greaterp pct 95) 
                    272:                                     (patom "[Storage space totally exhausted]")
                    273:                                     (terpr)
                    274:                                     (error "Space exhausted when allocating "
                    275:                                            (car s)))
                    276:                                    (t 0)))
                    277:                             ((greaterp pct $gc_midlim)
                    278:                              (max $gc_minalloc (fix (times $gc_pct (cadr x)))))
                    279:                             ((greaterp pct $gc_lowlim)
                    280:                              $gc_minalloc)
                    281:                             ((lessp (cadr x) 100)
                    282:                              $gc_minalloc)
                    283:                             (t 0)))
                    284:                 (cond ((and (null gcafter-panic-mode) (greaterp amt-to-allocate
                    285:                                                                 0))
                    286:                        (cond ((atom (errset (allocate (car s) amt-to-allocate)))
                    287:                               (cond ($gcprint 
                    288:                                        (patom "[Now in storage allocation panic mode]")
                    289:                                        (terpr)))
                    290:                               (setq gcafter-panic-mode t)))))
                    291: 
                    292:                 (cond ($gcprint (prtpagesused (car s) difftottime diffgctime)
                    293:                                 (comment (cond ((and (getd 'gcstat)
                    294:                                             (eq $gcprint '$all))
                    295:                                        (print (gcstat))
                    296:                                        (terpr)))))))))
                    297: 
                    298: ;----Section V - the functions
                    299: ; 
                    300: 
                    301: 
                    302: ;--- bigp - x : lispval
                    303: ;      returns t if x is a bignum
                    304: ;
                    305: (def bigp (lambda (arg) (equal (type arg) 'bignum)))
                    306: 
                    307: ;--- comment - any
                    308: ;      ignores the rest of the things in the list
                    309: (def comment
                    310:   (nlambda (x) 'comment))
                    311: 
                    312: 
                    313: ;--- copy - l : list (will work if atom but will have no effect)
                    314: ;      makes a copy of the list.
                    315: ; will also copy vector and vectori's, if their property list
                    316: ; doesn't have the 'unique' flag
                    317: ;
                    318: (def copy
                    319:    (lambda (l)
                    320:       (cond ((dtpr l) (cons (copy (car l)) (copy (cdr l))))
                    321:            ((vectorp l)
                    322:             (if (vget l 'unique)
                    323:                then l
                    324:                else (let ((size (vsize l)))
                    325:                        (do ((newv (new-vector size))
                    326:                             (i 0 (1+ i)))
                    327:                            ((not (<& i size))
                    328:                             (vsetprop newv (copy (vprop l)))
                    329:                             newv)
                    330:                            (vset newv i (copy (vref l i)))))))
                    331:            ((vectorip l)
                    332:             (if (vget l 'unique)
                    333:                then l
                    334:                else (let ((size (vsize-byte l)))
                    335:                        (do ((newv (new-vectori-byte size))
                    336:                             (i 0 (1+ i)))
                    337:                            ((not (<& i size))
                    338:                             (vsetprop newv (copy (vprop l)))
                    339:                             newv)
                    340:                            (vseti-byte newv i (vrefi-byte l i))))))
                    341:            (t l))))
                    342: 
                    343: 
                    344: ;--- copysymbol - sym : symbol to copy
                    345: ;              - flag : t or nil
                    346: ;  generates an uninterned symbol with the same name as sym.  If flag is t
                    347: ; then the value, function binding and property list of sym are placed
                    348: ; in the uninterned symbol.
                    349: ;
                    350: (def copysymbol 
                    351:   (lambda (sym flag)
                    352:          ((lambda (newsym)
                    353:                   (cond (flag (cond ((boundp sym) (set newsym (eval sym))))
                    354:                               (putd newsym (getd sym))
                    355:                               (setplist newsym (plist sym))))
                    356: 
                    357:                   newsym)
                    358:           (uconcat sym))))
                    359: 
                    360: 
                    361: ;--- cvttointlisp -- convert reader syntax to conform to interlisp
                    362: ;
                    363: (def cvttointlisp
                    364:   (lambda nil
                    365:          (setsyntax '\% 'vescape)              ; escape character
                    366:          (setsyntax '\\ 'vcharacter)           ; normal character
                    367:          (setsyntax '\` 'vcharacter)           ; normal character
                    368:          (setsyntax '\, 'vcharacter)           ; normal character
                    369:          (sstatus uctolc t)                    ; one case
                    370:          ))
                    371: 
                    372: 
                    373: ;--- cvttomaclisp - converts the readtable to a maclisp character syntax
                    374: ;
                    375: (def cvttomaclisp
                    376:   (lambda nil
                    377:          (setsyntax '\/ 'vescape)              ; escape
                    378:          (setsyntax '\\ 'vcharacter)           ; normal char
                    379:          (setsyntax '\[ 'vcharacter)           ; normal char
                    380:          (setsyntax '\] 'vcharacter)           ; normal char
                    381:          (sstatus uctolc t)))
                    382: 
                    383: (declare (special readtable))
                    384: ;--- cvttoucilisp - converts the readtable to a ucilisp character syntax
                    385: ;
                    386: (def cvttoucilisp
                    387:   (lambda nil
                    388:          (sstatus uctolc t)            ; upper case to lower case
                    389:                                        ; change backquote character.
                    390:                                        ; to ` and ! and !@ from ` , and ,@
                    391:                                        ; undo comma.
                    392:        (setsyntax '\! 'splicing (get '\, readtable))
                    393:        (setsyntax '\, 'vcharacter)
                    394:                ; 
                    395:                ; ~ as comment character, not ; and / instead of \ for escape
                    396:        (setsyntax '\~ 'splicing 'zapline)
                    397:        (setsyntax '\; 'vcharacter)
                    398:        (setsyntax '\/ 'vescape)
                    399:        (setsyntax '\\   'vcharacter)))
                    400: 
                    401: 
                    402: ;--- cvttofranzlisp - converts the readtable to the standard franz readtable
                    403: ; this just does the obvious conversions, assuming that the user was
                    404: ; in the maclisp syntax before.
                    405: (def cvttofranzlisp
                    406:    (lambda nil
                    407:       (setsyntax '\/ 'vcharacter)
                    408:       (setsyntax '\\ 'vescape)
                    409:       (setsyntax '\[ 'vleft-bracket)
                    410:       (setsyntax '\] 'vright-bracket)
                    411:       (sstatus uctolc nil)))
                    412: 
                    413: ;--- defprop - like putprop except args are not evaled
                    414: ;
                    415: (def defprop 
                    416:     (nlambda (argl)
                    417:        (putprop (car argl) (cadr argl) (caddr argl) )))
                    418: 
                    419: ;--- delete
                    420: ;      - val - lispval
                    421: ;      - lst - list
                    422: ;      - n   - Optional arg, number of occurances to delete
                    423: ; removes up to n occurances of val from the top level of lst.
                    424: ; if n is not given, all occurances will be removed.
                    425: ;
                    426: (def delete
                    427:   (lexpr (nargs)
                    428:         (prog (val lst cur ret nmb)
                    429:               (cond ((= nargs 2)
                    430:                      (setq nmb -1))
                    431:                     ((= nargs 3) 
                    432:                      (setq nmb (arg 3)))
                    433:                     (t (error " wrong number of args to delete "
                    434:                               (cons 'delete (listify nargs)))))
                    435:               (setq val (arg 1) lst (arg 2))
                    436:               (cond ((and (atom lst) (not (null lst)))         
                    437:                      (error " non-list arg to delete " 
                    438:                               (cons 'delete (listify nargs)))))
                    439:               (setq cur (cons nil lst)
                    440:                     ret cur)
                    441:           loop
                    442:               (cond ((or (atom lst) (zerop nmb))
                    443:                      (return (cdr ret)))
                    444:                     ((equal val (car lst))
                    445:                      (rplacd cur (cdr lst))
                    446:                      (setq nmb (1- nmb)))
                    447:                     (t (setq cur (cdr cur))))
                    448:               (setq lst (cdr lst))
                    449:               (go loop))))
                    450: 
                    451: ;--- delq 
                    452: ;  same as delete except eq is used for testing.
                    453: ;
                    454: (def delq
                    455:   (lexpr (nargs)
                    456:         (prog (val lst cur ret nmb)
                    457:               (cond ((= nargs 2)
                    458:                      (setq nmb -1))
                    459:                     ((= nargs 3) 
                    460:                      (setq nmb (arg 3)))
                    461:                     (t (error " wrong number of args to delq "
                    462:                               (cons 'delq (listify nargs)))))
                    463:               (setq val (arg 1) lst (arg 2))
                    464:               (cond ((and (atom lst) (not (null lst)))         
                    465:                      (error " non-list arg to delq " 
                    466:                               (cons 'delq (listify nargs)))))
                    467:               (setq cur (cons nil lst)
                    468:                     ret cur)
                    469:           loop
                    470:               (cond ((or (atom lst) (zerop nmb))
                    471:                      (return (cdr ret)))
                    472:                     ((eq val (car lst))
                    473:                      (rplacd cur (cdr lst))
                    474:                      (setq nmb (1- nmb)))
                    475:                     (t (setq cur (cdr cur))))
                    476:               (setq lst (cdr lst))
                    477:               (go loop))))
                    478: 
                    479: ;--- evenp : num   -  return 
                    480: ;
                    481: ;
                    482: (def evenp
                    483:   (lambda (n)
                    484:          (cond ((not (zerop (boole 4 1 n))) t))))
                    485: 
                    486: ;--- ex [name] : unevaluated name of file to edit.
                    487: ;      the ex editor is forked to edit the given file, if no
                    488: ;      name is given the previous name is used
                    489: ;
                    490: (def ex (nlambda (x) (exvi 'ex x nil)))
                    491: 
                    492: (declare (special edit_file))
                    493: 
                    494: (def exvi 
                    495:   (lambda (cmd x doload) 
                    496:           (prog (handy handyport bigname)
                    497:                 (cond ((null x) (setq x (list edit_file)))
                    498:                       (t (setq edit_file (car x))))             
                    499:                 (setq bigname (concat (car x) ".l"))
                    500:                 (cond ((setq handyport (car (errset (infile bigname) nil)))
                    501:                        (close handyport)
                    502:                        (setq handy bigname))
                    503:                       (t (setq handy (car x))))
                    504:                 (setq handy (concat cmd " '+set lisp' " handy))
                    505:                 (setq handy (list 'process handy))
                    506:                 (eval handy)
                    507:                 (cond (doload (load edit_file))))))
                    508: 
                    509: ;--- exec - arg1 [arg2 [arg3 ...] ] unevaluated atoms
                    510: ;      A string of all the args concatenated together seperated by 
                    511: ;      blanks is forked as a process.
                    512: ;
                    513: (def exec
                    514:  (nlambda (list)
                    515:      (do ((xx list (cdr xx))
                    516:          (res "" (concat res " " (car xx))))
                    517:         ((null xx) (*process res)))))
                    518: 
                    519: ;--- exl - [name] : unevaluated name of file to edit and load.
                    520: ;      If name is not given the last file edited will be used.
                    521: ;      After the file is edited it will be `load'ed into lisp.
                    522: ;
                    523: (def exl (nlambda (x) (exvi 'ex x t)))
                    524: 
                    525: ;----- explode functions -------
                    526: ; These functions, explode , explodec and exploden, implement the 
                    527: ; maclisp explode functions completely.
                    528: ; They have a similar structure and are written with efficiency, not
                    529: ; beauty in mind (and as a result they are quite ugly)
                    530: ; The basic idea in all of them is to keep a pointer to the last
                    531: ; thing added to the list, and rplacd the last cons cell of it each time.
                    532: ;
                    533: ;--- explode - arg : lispval
                    534: ;      explode returns a list of characters which print would use to
                    535: ; print out arg.  Slashification is included.
                    536: ;
                    537: (def explode
                    538:   (lambda (arg)
                    539:          (cond ((atom arg) (aexplode arg))
                    540:                ((vectorp arg)
                    541:                 (aexplode (concat "vector[" (vsize arg) "]")))
                    542:                ((vectorip arg)
                    543:                 (aexplode (concat "vectori[" (vsize-byte arg) "]")))
                    544:                (t (do ((ll (cdr arg) (cdr ll))
                    545:                        (sofar (setq arg (cons '|(| (explode (car arg)))))
                    546:                        (xx))
                    547:                       ((cond ((null ll) (rplacd (last sofar) (ncons '|)| )) 
                    548:                               t)
                    549:                              ((atom ll) (rplacd (last sofar)
                    550:                                                 `(| | |.| | | ,@(explode ll) 
                    551:                                                     ,@(ncons '|)|)))
                    552:                               t))
                    553:                        arg)
                    554:                       (setq xx (last sofar)
                    555:                             sofar (cons '| | (explode (car ll))))
                    556:                       (rplacd xx sofar))))))
                    557: 
                    558: ;--- explodec - arg : lispval
                    559: ; returns the list of character which would be use to print arg assuming that
                    560: ; patom were used to print all atoms.
                    561: ; that is, no slashification would be used.
                    562: ;
                    563: (def explodec
                    564:   (lambda (arg)
                    565:          (cond ((atom arg) (aexplodec arg))
                    566:                ((vectorp arg)
                    567:                 (aexplodec (concat "vector[" (vsize arg) "]")))
                    568:                ((vectorip arg)
                    569:                 (aexplodec (concat "vectori[" (vsize-byte arg) "]")))
                    570:                (t (do ((ll (cdr arg) (cdr ll))
                    571:                        (sofar (setq arg (cons '|(| (explodec (car arg)))))
                    572:                        (xx))
                    573:                       ((cond ((null ll) (rplacd (last sofar) (ncons '|)| )) 
                    574:                               t)
                    575:                              ((atom ll) (rplacd (last sofar)
                    576:                                                 `(| | |.| | | ,@(explodec ll) 
                    577:                                                     ,@(ncons '|)|)))
                    578:                               t))
                    579:                        arg)
                    580:                       (setq xx (last sofar)
                    581:                             sofar (cons '| | (explodec (car ll))))
                    582:                       (rplacd xx sofar))))))
                    583: 
                    584: ;--- exploden - arg : lispval
                    585: ;      returns a list just like explodec, except we return fixnums instead
                    586: ; of characters.
                    587: ;
                    588: (def exploden
                    589:   (lambda (arg)
                    590:          (cond ((atom arg) (aexploden arg))
                    591:                ((vectorp arg)
                    592:                 (aexploden (concat "vector[" (vsize arg) "]")))
                    593:                ((vectorip arg)
                    594:                 (aexploden (concat "vectori[" (vsize-byte arg) "]")))
                    595:                (t (do ((ll (cdr arg) (cdr ll))
                    596:                        (sofar (setq arg (cons 40. (exploden (car arg)))))
                    597:                        (xx))
                    598:                       ((cond ((null ll) (rplacd (last sofar) (ncons 41.)) 
                    599:                               t)
                    600:                              ((atom ll) (rplacd (last sofar)
                    601:                                                 `(32. 46. 32. ,@(exploden ll) 
                    602:                                                     ,@(ncons 41.)))
                    603:                               t))
                    604:                        arg)
                    605:                       (setq xx (last sofar)
                    606:                             sofar (cons 32. (exploden (car ll))))
                    607:                       (rplacd xx sofar))))))
                    608: 
                    609: ;-- expt  - x
                    610: ;        - y
                    611: ;
                    612: ;         y
                    613: ; returns x
                    614: ;
                    615: (defun expt (x y)
                    616:   (cond ((equal x 1) x)
                    617:        ((zerop x) x)   ; Maclisp does this 
                    618:        ((lessp y 0) (quotient 1.0 (expt x (times -1 y))))
                    619:        ((floatp y) 
                    620:         (exp (times y (log x)))) ; bomb out for (-3)^4 or (-3)^4.0 or 0^y.
                    621:        ((bigp y)
                    622:         (error "expt: Can't compute number to a bignum power" y))
                    623:        (t ; y is integer, y>= 0
                    624:           (prog (res)
                    625:                 (setq res 1)
                    626:                 loop
                    627:                 (cond ((equal y 0) (return res))
                    628:                       ((oddp y)(setq res (times  res x) y (1- y)))
                    629:                       (t (setq x (times x x) y (/ y 2))))
                    630:                 (go loop)))))
                    631: 
                    632: 
                    633: 
                    634: ;--- ffasl :: fasl in a fortran file
                    635: ;  arg #
                    636: ;   1  - fnam : file name
                    637: ;   2  - entry : entry point name
                    638: ;   3  - fcn  : entry name
                    639: ;   4   - disc : optional discipline
                    640: ;   5   - lib  ; optional library specifier
                    641: ;
                    642: (defun ffasl (fnam entry fcn &optional (disc 'subroutine) (lib " "))
                    643:   (cfasl fnam entry fcn disc (concat lib " -lI77 -lF77 -lm")))
                    644: 
                    645: 
                    646: ;
                    647: ; filepos function (maclisp compatibility)
                    648: ;
                    649: (defun filepos n
                    650:   (cond ((zerop n) nil)
                    651:        ((onep n)
                    652:         (fseek (arg 1) 0 1))
                    653:        ((equal n 2)
                    654:         (fseek (arg 1) (arg 2) 0))))
                    655: 
                    656: ;--- fixp - l : lispval
                    657: ;      returns t if l is a fixnum or bignum
                    658: ;
                    659: (defun fixp (x) (or (equal (type x) 'fixnum)
                    660:                    (equal (type x) 'bignum)))
                    661: 
                    662: 
                    663: 
                    664: ;--- flatsize - l : lispval
                    665: ;           the second arg should be:
                    666: ;            - n : limit for what we care about
                    667: ;           but we dont care about this at present, since we have
                    668: ;           to explode the whole thing anyway.
                    669: ;      returns the number of characters which print would
                    670: ;      use to print l
                    671: ;
                    672: (defun flatsize n
                    673:   (length (explode (arg 1))))
                    674: 
                    675: 
                    676: ;--- floatp - l : lispval
                    677: ;      returns t if l is a flonum
                    678: ;
                    679: (defun floatp (x) (equal 'flonum (type x)))
                    680: 
                    681: 
                    682: ;--- getchar,getcharn   - x : atom
                    683: ;                      - n : fixnum
                    684: ; returns the n'th character of x's pname (the first corresponds to n=1)
                    685: ; if n is negative then it counts from the end of the pname
                    686: ; if n is out of bounds, nil is returned
                    687: 
                    688: (def getchar
                    689:   (lambda (x n)
                    690:          (concat (substring x n 1))))
                    691: 
                    692: 
                    693: (def getcharn
                    694:   (lambda (x n)
                    695:          (substringn x n 0)))
                    696: 
                    697: 
                    698: (def getl 
                    699:   (lambda (atm lis)
                    700:          (do ((ll (cond ((atom atm) (plist atm))
                    701:                         (t (cdr atm)))
                    702:                   (cddr ll)))
                    703:              ((null ll) nil)
                    704:              (cond ((memq (car ll) lis) (return ll))))))
                    705: 
                    706: 
                    707: ;--- help
                    708: ; retrive selected portions of the Franz Lisp manual.
                    709: ; There are four types of help offered:
                    710: ; (help) prints a description of the other three options
                    711: ; (help tc) prints a table of contents.
                    712: ; (help n) {where n is a number or b or c} prints the whole chapter.
                    713: ; (help fcn) prints info on function fcn
                    714: ;
                    715: ; An index to the functions is kept in the documentation directory.
                    716: ; The index has entries like (append ch2.r).  
                    717: ; When asked to print info on a function, it locates the chapter
                    718: ; using the index then asks more to locate the definition.
                    719: ;
                    720: (declare (localf locatefunction))
                    721: 
                    722: (defun help fexpr (lis)
                    723:   (cond ((null lis) 
                    724:  (patom "type (help fnc) for info on function fnc")(terpr)
                    725:  (patom "type (help n) to see chapter n")(terpr)
                    726:  (patom "type (help tc) for a table of contents")(terpr))
                    727:        (t (do ((ll lis (cdr ll))
                    728:                (fcn))
                    729:               ((null ll))
                    730:               (cond ((not (atom (setq fcn (car ll))))
                    731:                      (patom "Bad option to help ")(print fcn)(terpr))
                    732:                     ((and (stringp fcn) (setq fcn (concat fcn)) nil))
                    733:                     ((eq fcn 'tc)
                    734:                      (patom "Table of contents")(terpr)
                    735:  (patom "1 - intro; 2 - data structure; 3 - arithmetic; 4 - special")(terpr)
                    736:  (patom "5 - i/o; 6 - system; 7 - reader; 8 - functions; 9 - arrays")(terpr)
                    737:  (patom "10 - exceptions; 11 - trace package; 12 - Liszt;")(terpr)
                    738:  (patom "14 - step package; 15 - fixit package") (terpr)
                    739:  (patom "b - special symbols; c - gc & debugging & top level ")(terpr))
                    740:                     ((or (and (numberp fcn) (lessp fcn 16) (greaterp fcn -1))
                    741:                          (memq fcn '(b c)))
                    742:                      (apply 'process 
                    743:                         (ncons (concat "/usr/ucb/ul "
                    744:                                        lisp-library-directory
                    745:                                        "/manual/ch"
                    746:                                       fcn ".r | /usr/ucb/more -f" ))))
                    747:                     ((locatefunction fcn))
                    748:                     (t (patom "Unknown function: ")(print fcn)(terpr)))))))
                    749: 
                    750: (declare (special readtable))
                    751: 
                    752: (defun locatefunction (fc)
                    753:   (let (x inf )
                    754:        (cond ((null (get 'append 'helplocation)) 
                    755:              (patom "[Reading help index]")(drain)
                    756:              (setq inf (infile (concat lisp-library-directory
                    757:                                        "/manual/helpindex")))
                    758:              (do ((readtable (makereadtable t))
                    759:                   (x (read inf) (read inf)))
                    760:                  ((null x) (close inf) (terpr))
                    761:                  (cond ((null (cddr x))
                    762:                         (putprop (car x) (cadr x) 'helplocation))
                    763:                        (t (putprop (concat (car x) " " (cadr x))
                    764:                                    (caddr x)
                    765:                                    'helplocation))))))
                    766:        (cond ((setq x (get fc 'helplocation))
                    767:              (apply 'process (ncons (concat "/usr/ucb/ul "
                    768:                                             lisp-library-directory
                    769:                                             "/manual/"
                    770:                                             x 
                    771:                                             " | /usr/ucb/more -f \"+/(" 
                    772:                                             fc 
                    773:                                             "\"")))
                    774:              t))))
                    775: 
                    776: ;
                    777: ; (hunk 'g_arg1 [...'g_argn])
                    778: ;
                    779: ; This function makes a hunk. The hunk is preinitialized to the
                    780: ; arguments present. The size of the hunk is determined by the
                    781: ; number of arguments present.
                    782: ;
                    783: 
                    784: (defun hunk n
                    785:   (prog (size)
                    786:        (setq size -1)
                    787:        (cond ((> n 128) (error "hunk: size is too big" n))
                    788:              ((eq n 1) (setq size 0))
                    789:              ((eq n 0) (return nil))   ; hunk of zero length
                    790:              (t (setq size (1- (haulong (1- n))))))
                    791:        (setq size (*makhunk size))
                    792:        (do
                    793:         ((argnum 0 (1+ argnum)))
                    794:         ((eq argnum n))
                    795:         (*rplacx argnum size (arg (1+ argnum))))
                    796:        (return size)))
                    797: 
                    798: 
                    799: ;--- last - l : list
                    800: ;      returns the last cons cell of the list, NOT the last element
                    801: ;
                    802: (def last 
                    803:   (lambda (a)
                    804:          (do ((ll a (cdr ll)))
                    805:              ((null (cdr ll))  ll))))
                    806: 
                    807: ;---- load 
                    808: ; load will either load (read-eval)  or fasl in the file.
                    809: ; it is affected by these global flags
                    810: ;  tilde-expansion :: expand filenames preceeded by ~ just like
                    811: ;      csh does (we do the expansion here so each i/o function we call
                    812: ;      doesn't have to do it).
                    813: ;  load-most-recent :: if there is a choice between a .o and a .l file,
                    814: ;      load the youngest one
                    815: ;
                    816: (declare (localf load-a-file))
                    817: (declare (special gcdisable load-most-recent tilde-expansion))
                    818: 
                    819: (or (boundp 'load-most-recent) (setq load-most-recent nil))
                    820: (or (boundp 'tilde-expansion) (setq tilde-expansion t))
                    821: 
                    822: (defun load (filename &rest fasl-args)
                    823:   (cond ((not (or (symbolp filename) (stringp filename))) 
                    824:         (error "load: illegal filename " filename)))
                    825:   (let ( load-only fasl-only no-ext len search-path name pred shortname explf
                    826:         faslfile loadfile)
                    827: 
                    828:        
                    829:        (cond (tilde-expansion (setq filename (tilde-expand filename))))
                    830:                
                    831:        ; determine the length of the filename, ignoring the possible
                    832:        ; list of directories.  set explf to the reversed exploded filename
                    833:        (setq len (do ((xx (setq explf (nreverse (exploden filename))) (cdr xx))
                    834:                      (i 0 (1+ i)))
                    835:                     ((null xx) i)
                    836:                     (cond ((eq #// (car xx)) (return i)))))
                    837: 
                    838:        (cond ((> len 2)
                    839:              (cond ((eq (cadr explf) #/.)
                    840:                     (cond ((eq (car explf) #/o)
                    841:                            (setq fasl-only t))
                    842:                           ((eq (car explf) #/l)
                    843:                            (setq load-only t))
                    844:                           (t (setq no-ext t))))
                    845:                    (t (setq no-ext t))))
                    846:             (t (setq no-ext t)))
                    847: 
                    848:        ; a short name is less or equal 12 characters.  If a name is not
                    849:        ; short, then load will not try to append .l or .o
                    850:        (cond ((or (< len 13) (status feature long-filenames))
                    851:              (setq shortname t)))
                    852: 
                    853:        (cond ((and (> len 0) (eq (getchar filename 1) '/))
                    854:              (setq search-path '(||)))
                    855:             (t (setq search-path (status load-search-path))))
                    856:        (do ((xx search-path (cdr xx)))
                    857:           ((null xx) (error "load: file not found " filename))
                    858:           (setq pred (cond ((memq (car xx) '(|| |.|)) '||)
                    859:                            (t (concat (car xx) "/"))))
                    860:           (cond (no-ext
                    861:                  (cond ((and shortname
                    862:                              load-most-recent
                    863:                              (probef
                    864:                                 (setq faslfile (concat pred filename ".o")))
                    865:                              (probef
                    866:                                 (setq loadfile (concat pred filename ".l"))))
                    867:                         ; both an object and a source file exist.
                    868:                         ; load the last modified one (fasl wins in ties)
                    869:                         (let ((faslstat (filestat faslfile))
                    870:                               (loadstat (filestat loadfile)))
                    871:                            (cond ((< (filestat:mtime faslstat)
                    872:                                      (filestat:mtime loadstat))
                    873:                                   (return (load-a-file loadfile)))
                    874:                                  (t (return
                    875:                                        (fasl-a-file faslfile
                    876:                                                     (car fasl-args)
                    877:                                                     (cadr fasl-args)))))))
                    878:                        ((and shortname
                    879:                              (probef (setq name
                    880:                                            (concat pred filename ".o"))))
                    881:                         (return (fasl-a-file name (car fasl-args)
                    882:                                              (cadr fasl-args))))
                    883:                        ((and shortname
                    884:                              (probef (setq name
                    885:                                            (concat pred filename ".l"))))
                    886:                         (return (load-a-file name)))
                    887:                        ((probef (setq name (concat pred filename)))
                    888:                         (cond (fasl-args (return
                    889:                                             (fasl-a-file name
                    890:                                                          (car fasl-args)
                    891:                                                          (cadr fasl-args))))
                    892:                               (t (return (load-a-file name)))))))
                    893:                 (fasl-only
                    894:                  (cond ((probef (setq name (concat  pred  filename)))
                    895:                         (return (fasl-a-file name (car fasl-args)
                    896:                                              (cadr fasl-args))))))
                    897:                 (load-only
                    898:                  (cond ((probef (setq name (concat pred filename)))
                    899:                         (return (load-a-file name)))))))))
                    900: 
                    901: ;--- tilde-expand :: given a ~filename, expand it
                    902: ;
                    903: (defun tilde-expand (name)
                    904:    (cond ((or (symbolp name) (stringp name))
                    905:          (cond ((eq (getcharn name 1) #/~)
                    906:                 (let ((form (exploden name)))
                    907:                    (do ((xx (cdr form) (cdr xx))
                    908:                         (res)
                    909:                         (val))
                    910:                        ((or (null xx) (eq (car xx) #//))
                    911:                         ;; if this is the current user, just get value
                    912:                         ;; from environment variable HOME
                    913:                         (cond ((or (null res)
                    914:                                    (equal (setq res (implode (nreverse res)))
                    915:                                           (getenv 'USER)))
                    916:                                (setq val (getenv 'HOME)))
                    917:                               (t (setq val (username-to-dir res))))
                    918:                         (cond ((null val)
                    919:                                (error "tilde-expand: unknown user " res))
                    920:                               (t (concat val (implode xx)))))
                    921:                        (setq res (cons (car xx) res)))))
                    922:                (t name)))
                    923:         (t (error "tilde-expand: illegal argument " name))))
                    924: 
                    925:       
                    926: 
                    927: ;--- fasl-a-file
                    928: ; The arguments are just like those to fasl.  This fasl's a file
                    929: ; and if the translink's are set, it does the minimum work necessary to rebind
                    930: ; the links (so that the new functions just fasl'ed in will be used).
                    931: ; 
                    932: (defun fasl-a-file (name map warnflag)
                    933:    (let ((translinkarg (status translink)))
                    934:       (prog1
                    935:         (fasl name map warnflag)
                    936:         (cond ((and translinkarg (setq translinkarg (status translink)))
                    937:                ; if translink was set before and is still set
                    938:                (cond ((eq translinkarg t)
                    939:                       (sstatus translink nil)  ; clear all links
                    940:                       (sstatus translink t))   ; set to make links
                    941:                      (t ; must be 'on'
                    942:                         (sstatus translink on) ; recompute all links
                    943:                         ))))))) 
                    944: 
                    945: (declare (special $ldprint))   ; print message before loading
                    946: (declare (special prinlevel prinlength))
                    947: 
                    948: (defun load-a-file (fname)
                    949:    (cond ($ldprint (patom "[load ")(patom fname)(patom "]")(terpr)))
                    950:    (let ((translinkarg (status translink)))
                    951:       (prog1
                    952:         (let ((Piport (infile fname))
                    953:               ; (gcdisable t)  ; too dangerous: removed for now
                    954:               ; don't gc when loading, it slows things down
                    955:               (eof (list nil)))
                    956:            (do ((form (errset (read Piport eof)) (errset (read Piport eof)))
                    957:                 (lastform "<no form read successfully>"))
                    958:                ((eq eof (car form)) (close Piport) t)
                    959:                (cond ((null form)
                    960:                       (error "load aborted due to read error after form "
                    961:                              lastform))
                    962:                      (t (setq lastform (car form))
                    963:                         (eval (car form))))))
                    964:         (cond ((and translinkarg (setq translinkarg (status translink)))
                    965:                ; if translink was set before and is still set
                    966:                (cond ((eq translinkarg t)
                    967:                       (sstatus translink nil)  ; clear all links
                    968:                       (sstatus translink t))   ; set to make links
                    969:                      (t ; must be 'on'
                    970:                         (sstatus translink on) ; recompute all links
                    971:                         )))))))
                    972: 
                    973: (funcall 'sstatus (list 'load-search-path (list '|.| lisp-library-directory)))
                    974: ;--- include - read in the file name given, the name not evaluated
                    975: ;
                    976: (def include (nlambda (l) (load (car l))))
                    977: 
                    978: ;--- includef - read in the file name given and eval the first arg
                    979: ;
                    980: (def includef (lambda (l) (load l)))
                    981: 
                    982: 
                    983: ;--- list-to-bignum
                    984: ;  convert a list of fixnums to a bignum.
                    985: ; there is a function bignum-to-list but it is written in C
                    986: ;
                    987: ;(author: kls)
                    988: ;
                    989: (def list-to-bignum
                    990:  (lambda (x) (cond (x (scons (car x) (list-to-bignum (cdr x))))
                    991:                   (t nil))))
                    992: 
                    993: 
                    994: 
                    995: ;--- macroexpand - form 
                    996: ;      expands out all macros it can
                    997: ;
                    998: (def macroexpand
                    999:   (lambda (form)
                   1000:     (prog nil
                   1001:   top (cond ((atom form) (return form))
                   1002:            ((atom (car form))
                   1003:             (return
                   1004:              (let ((nam (car form)) def disc)
                   1005:                   (setq def (getd nam))
                   1006:                   (setq disc (cond ((bcdp def) (getdisc def))
                   1007:                                    ((arrayp def) 'array)
                   1008:                                    ((dtpr def) (car def))))
                   1009:                   (cond ((and (null def)
                   1010:                               (get nam 'macro-autoload))
                   1011:                          (setq disc 'macro)))
                   1012:                   (cond ((memq disc '(array lambda lexpr nil))
                   1013:                          (cons nam (mapcar 'macroexpand (cdr form))))
                   1014:                         ((eq disc 'macro)
                   1015:                          (setq form (apply nam form))
                   1016:                          (go top))
                   1017:                         ((eq nam 'prog)
                   1018:                          (cons nam
                   1019:                                (cons (cadr form)
                   1020:                                      (mapcar 'macroexpand (cddr form)))))
                   1021:                         (t form)))))
                   1022:            (t (return (cons (macroexpand (car form))
                   1023:                             (mapcar 'macroexpand (cdr form)))))))))
                   1024: 
                   1025: 
                   1026: 
                   1027: 
                   1028: ;
                   1029: ; (makhunk 'n)
                   1030: ;
                   1031: ; This function is similar to hunk, except that:
                   1032: ;
                   1033: ; n can be a fixnum, which specifies the length of the hunk.
                   1034: ;      The hunk is preinitialized to nil's
                   1035: ; n can be a list which is used to preinitialize the hunk.
                   1036: ;
                   1037: (defun makhunk (n)
                   1038:   (prog (size Hunk)
                   1039:        (setq size -1)
                   1040:        (cond ((numberp n)
                   1041: ;
                   1042: ; If n is a number then build a nil hunk of the right size
                   1043: ;
                   1044:               (cond ((greaterp n 128) (error "makhunk: size is too big" n))
                   1045:                     ((= n 1) (setq size 0))
                   1046:                     (t (setq size (1- (haulong (1- n))))))
                   1047:               (cond ((minusp size) (return nil)))
                   1048:               (setq Hunk (*makhunk size))
                   1049:               (do ((i 0 (1+ i)))
                   1050:                   ((=& i n))
                   1051:                   (*rplacx i Hunk nil))
                   1052:               (return Hunk))
                   1053: ;
                   1054: ; If it isn't a number, then try hunk on it
                   1055: ;
                   1056:              (t (return (apply 'hunk n))))))
                   1057: 
                   1058: ;--- member - VAL : lispval
                   1059: ;          - LIS : list
                   1060: ;      returns that portion of LIS beginning with the first occurance
                   1061: ;      of VAL  if  VAL is found at the top level of list LIS.
                   1062: ;      uses equal for comparisons.
                   1063: ;
                   1064: (def member 
                   1065:   (lambda ($a$ $l$)
                   1066:          (do ((ll $l$ (cdr ll)))
                   1067:              ((null ll) nil)
                   1068:              (cond ((equal $a$ (car ll)) (return ll))))))
                   1069: 
                   1070: ;--- memq - arg : (probably a symbol)
                   1071: ;        - lis : list
                   1072: ; returns part of lis beginning with arg if arg is in lis
                   1073: ;      
                   1074: ; [ defintion moved to top of file to allow backquote macro to work ]
                   1075: 
                   1076: ;--- min - arg1 ... numbers 
                   1077: ;
                   1078: ;      returns minimum of n numbers. 
                   1079: ;
                   1080: 
                   1081: (def min
                   1082:   (lexpr (nargs)
                   1083:         (do ((i nargs (1- i))
                   1084:              (min (arg 1)))
                   1085:             ((lessp i 2) min)
                   1086:             (cond ((lessp (arg i) min) (setq min (arg i)))))))
                   1087: 
                   1088: 
                   1089: ;
                   1090: (def oddp
                   1091:   (lambda (n)
                   1092:          (cond ((not (zerop (boole 1 1 n))) t))))
                   1093: 
                   1094: ;--- plusp : x - number
                   1095: ; returns t iff x is greater than zero
                   1096: 
                   1097: (def plusp
                   1098:   (lambda (x)
                   1099:          (greaterp x 0)))
                   1100: 
                   1101: 
                   1102: ;--- princ : l - any s-expression
                   1103: ;          [p] - port to write to
                   1104: ; prints using patom for atoms (unslashified)
                   1105: ;
                   1106: (def princ
                   1107:   (lexpr (n)
                   1108:         (prog (port val)
                   1109:               (cond ((eq n 2) (setq port (arg 2))))
                   1110:               (cond ((dtpr (setq val (arg 1)))
                   1111:                      (cond ((and (eq 'quote (car val))
                   1112:                                  (dtpr (cdr val))
                   1113:                                  (null (cddr val)))
                   1114:                             (patom "'" port)
                   1115:                             (princ (cadr val) port))
                   1116:                            (t 
                   1117:                             (patom "(" port)
                   1118:                             (do ((xx val))
                   1119:                                 ((null xx) (patom ")" port))
                   1120:                                 (princ (car xx) port)
                   1121:                                 (cond ((null (setq xx (cdr xx))))
                   1122:                                       ((not (dtpr xx))
                   1123:                                        (patom " . " port)
                   1124:                                        (princ xx port)
                   1125:                                        (setq xx nil))
                   1126:                                       (t (patom " " port)))))))
                   1127:                     (t (patom val port)))
                   1128:               (return t))))
                   1129: 
                   1130: ;--- prog1 : return the first value computed in a list of forms
                   1131: ;
                   1132: (def prog1
                   1133:   (lexpr (n)
                   1134:         (arg 1)))
                   1135: 
                   1136: ;--- reverse : l - list
                   1137: ;      returns the list reversed using cons to create new list cells.
                   1138: ;
                   1139: (def reverse 
                   1140:   (lambda (x)
                   1141:          (cond ((null x) nil)
                   1142:                (t (do ((cur (cons (car x) nil) 
                   1143:                             (cons (car res) cur))
                   1144:                        (res (cdr x) (cdr res)))
                   1145:                       ((null res) cur))))))
                   1146: 
                   1147: 
                   1148: ;--- shell - invoke a new c shell
                   1149: ;
                   1150: (def shell 
                   1151:   (lambda nil 
                   1152:          ((lambda (shellname)
                   1153:                   (cond ((lessp (flatc shellname) 1) (setq shellname 'csh)))
                   1154:                   (apply 'process (ncons shellname)))
                   1155:           (getenv 'SHELL))))
                   1156: 
                   1157: 
                   1158: 
                   1159: ; S L O A D  stuff
                   1160: ;
                   1161: (defvar $sldprint t)
                   1162: (declare (special sload-print))
                   1163: (setq sload-print nil)
                   1164: 
                   1165: (defmacro sl-print (&rest args)
                   1166:    `(cond ((and sload-print
                   1167:                (getd sload-print))
                   1168:           (funcall sload-print . ,args))
                   1169:          (t (print . ,args))))
                   1170: 
                   1171: ;--- sload : fn - file name (must include the .l)
                   1172: ;      loads in the file printing each result as it is seen
                   1173: ;
                   1174: (defun sload (&rest files)
                   1175:    (mapc '(lambda (fn)
                   1176:             (prog (por eof argnum result)
                   1177:                (cond ((setq por (infile fn))
                   1178:                       (and $sldprint
                   1179:                            (progn (princ "[sload ")
                   1180:                                   (princ fn)
                   1181:                                   (princ "]")
                   1182:                                   (terpr))))
                   1183:                      (t (patom "bad file name: ")
                   1184:                         (patom fn)
                   1185:                         (terpr)
                   1186:                         (return nil)))
                   1187:                (setq eof (gensym))
                   1188:                (do ((input (read por eof) (read por eof)))
                   1189:                    ((eq eof input) (close por))
                   1190:                    (and $sldprint
                   1191:                         (cond ((and (dtpr input)
                   1192:                                     (setq argnum
                   1193:                                           (get (car input) 'sloadprintarg)))
                   1194:                                (print (nth argnum input)))
                   1195:                               (t (print input))))
                   1196:                    (setq result (eval input))
                   1197:                    (and (eq 'value $sldprint)
                   1198:                         (progn (princ ": ")
                   1199:                                (sl-print result)))
                   1200:                    (and $sldprint
                   1201:                         (terpr)))
                   1202:                (return t)))
                   1203:         files))
                   1204: 
                   1205: (defprop def 1 sloadprintarg)
                   1206: (defprop defun 1 sloadprintarg)
                   1207: 
                   1208: (defprop setq 1 sloadprintarg)
                   1209: (defprop declare 1 sloadprintarg)
                   1210: 
                   1211: 
                   1212: 
                   1213: 
                   1214: 
                   1215: ;---- bubble merge sort 
                   1216: ; it recursively splits the list to sort until the list is small.  At that
                   1217: ; point it uses a bubble sort.  Finally the sorted lists are merged.
                   1218: 
                   1219: (declare (special sort-function))
                   1220: 
                   1221: ;--- sort :: sort a lisp list
                   1222: ; args: lst - list of items
                   1223: ;       fcn - function to compare two items.
                   1224: ; returns: the list with such that for each pair of adjacent elements,
                   1225: ;         either the elements are equal, or fcn applied to the two 
                   1226: ;         args returns a non nil value.
                   1227: ;
                   1228: (defun sort (lst fcn)
                   1229:   (setq sort-function (cond (fcn)   ; store function name in global cell
                   1230:                            (t 'alphalessp)))
                   1231:   ; (setq sort-compares 0)             ; count number of comparisons
                   1232:   (sortmerge lst (length lst)))
                   1233: 
                   1234: 
                   1235: ;--- sortmerge :: utility routine to sort
                   1236: ; args: lst - list of items to sort
                   1237: ;      nitems - a rough idea of how many items are in the list
                   1238: ;
                   1239: ; result - sorted list (see the result of sort above)
                   1240: ;
                   1241: (defun sortmerge (lst nitems)
                   1242:   (prog (tmp tmp2)
                   1243:        (cond ((greaterp nitems 7)
                   1244:               ; do a split and merge
                   1245:               (setq tmp (splitlist lst (setq tmp2 (quotient nitems 2))))
                   1246:               (return (mergelists (sortmerge (car tmp) tmp2)
                   1247:                              (sortmerge (cdr tmp) tmp2))))
                   1248:              (t ; do a bubble sort
                   1249:                 (do ((l lst (cdr l))
                   1250:                      (fin))
                   1251:                     ((null l))
                   1252:                     (do ((ll lst (cdr ll)))
                   1253:                         ((eq fin (cdr ll)) (setq fin ll))
                   1254:                         ;(setq sort-compares (1+ sort-compares))
                   1255:                         (cond ((not (funcall sort-function (car ll) (cadr ll)))
                   1256:                                (rplaca ll (prog1 (cadr ll)
                   1257:                                                 (rplaca (cdr ll)
                   1258:                                                         (car ll))))))))
                   1259:                 (return lst)))))
                   1260: 
                   1261: ;--- splitlist :: utility routine to split a list
                   1262: ; args : lst - list to split
                   1263: ;        spliton - number of items to put in the first list
                   1264: ;
                   1265: ; returns: a cons cell whose car is the first part of the list
                   1266: ;         and whose cdr is the second part.
                   1267: ;
                   1268: (defun splitlist (lst spliton)
                   1269:   (prog (second)
                   1270:        (do ((i spliton (sub1 i))
                   1271:             (l lst))
                   1272:            ((or (null (cdr l)) (zerop i))
                   1273:             (setq second (cdr l))
                   1274:             (rplacd l nil))
                   1275:            (setq l (cdr l)))
                   1276:        (return (cons lst second))))
                   1277: 
                   1278: 
                   1279: ;--- mergelists ::utility routine to merge two lists based on predicate function
                   1280: ; args: ls1 - lisp list
                   1281: ;      ls2 - lisp list
                   1282: ;      sort-function (global) - compares items of the lists
                   1283: ;
                   1284: ; returns: a sorted list containing the elements of the two lists.
                   1285: ; 
                   1286: (defun mergelists  (ls1 ls2)
                   1287:   (prog (result current)
                   1288:        ; initialize
                   1289:        (setq current (setq result (cons nil nil)))
                   1290: loop   (cond ((null ls1)
                   1291:               (rplacd current ls2)
                   1292:               (return (cdr result)))
                   1293:              ((null ls2)
                   1294:               (rplacd current ls1)
                   1295:               (return (cdr result)))
                   1296:              ((funcall sort-function (car ls1) (car ls2))
                   1297:               ;(setq sort-compares (1+ sort-compares))
                   1298:               (rplacd current ls1)
                   1299:               (setq current ls1
                   1300:                     ls1 (cdr ls1)))
                   1301:              (t ;(setq sort-compares (1+ sort-compares))
                   1302:                 (rplacd current ls2)
                   1303:                 (setq current ls2
                   1304:                       ls2 (cdr ls2))))
                   1305:        (go loop)))
                   1306: 
                   1307: ;--- end bubble merge sort
                   1308: (declare (localf exchange2))
                   1309: 
                   1310: (defun sortcar (a fun)
                   1311:    (prog (n)
                   1312:        (if (null fun) then (setq fun 'alphalessp))
                   1313:        (cond ((null a) (return nil)) ;no elements
                   1314:             (t (setq n (length a))
                   1315:                (do i 1 (1+ i) (greaterp i n) (sortcarhelp a fun))
                   1316:                (return a)))))
                   1317: 
                   1318: (defun sortcarhelp (a fun)
                   1319:   (cond ((null (cdr a)) a)
                   1320:         ((funcall fun (caadr a) (caar a))  
                   1321:         (exchange2 a)
                   1322:         (sortcarhelp (cdr a) fun))
                   1323:        (t (sortcarhelp (cdr a) fun))))
                   1324: 
                   1325: 
                   1326: (defun exchange2 (a)
                   1327:   (prog (temp)
                   1328:        (setq temp (cadr a))
                   1329:        (rplaca (cdr a) (car a))
                   1330:        (rplaca a temp)))
                   1331: 
                   1332: ;--- sublis: alst - assoc list ((a . val) (b . val2) ...)
                   1333: ;           exp  - s-expression
                   1334: ; for each atom in exp which corresponds to a key in alst, the associated
                   1335: ; value from alst is substituted.  The substitution is done by adding
                   1336: ; list cells, no struture mangling is done.  Only the minimum number
                   1337: ; of list cells will be created.
                   1338: ;
                   1339: (def sublis
                   1340:   (lambda (alst exp)
                   1341:      (let (tmp)
                   1342:          (cond ((atom exp) 
                   1343:                 (cond ((setq tmp (assoc exp alst))
                   1344:                        (cdr tmp))
                   1345:                       (t exp)))
                   1346:                ((setq tmp (sublishelp alst exp))
                   1347:                 (car tmp))
                   1348:                (t exp)))))
                   1349: 
                   1350: ;--- sublishelp : alst - assoc list
                   1351: ;                exp  - s-expression
                   1352: ; this function helps sublis work.  it is different from sublis in that
                   1353: ; it return nil if no change need be made to exp, or returns a list of
                   1354: ; one element which is the changed exp.
                   1355: ;
                   1356: (def sublishelp
                   1357:   (lambda (alst exp)
                   1358:      (let (carp cdrp)
                   1359:          (cond ((atom exp)
                   1360:                 (cond ((setq carp (assoc exp alst))
                   1361:                        (list (cdr carp)))
                   1362:                       (t nil)))
                   1363:                (t (setq carp (sublishelp alst (car exp))
                   1364:                         cdrp (sublishelp alst (cdr exp)))
                   1365:                   (cond ((not (or carp cdrp)) nil)             ; no change
                   1366:                         ((and carp (not cdrp))                 ; car change
                   1367:                          (list (cons (car carp) (cdr exp))))   
                   1368:                         ((and (not carp) cdrp)                 ; cdr change
                   1369:                          (list (cons (car exp) (car cdrp))))   
                   1370:                         (t                                     ; both change 
                   1371:                          (list (cons (car carp) (car cdrp))))))))))
                   1372: 
                   1373: 
                   1374: ;--- subst : new - sexp
                   1375: ;           old - sexp
                   1376: ;           pat - sexp
                   1377: ; substitutes in patrn all occurrences equal to old with new and returns the
                   1378: ; result
                   1379: ; MUST be put in the manual
                   1380: 
                   1381: (declare (special new old))
                   1382: 
                   1383: (def subst 
                   1384:   (lambda (new old pat)
                   1385:          (cond ((symbolp old) (substeq pat))
                   1386:                (t (substequal pat)))))
                   1387: 
                   1388: ;use this function for substituting for symbols
                   1389: (def substeq
                   1390:   (lambda (pat)
                   1391:          (cond ((eq old pat) new)
                   1392:                ((atom pat) pat)
                   1393:                (t (cons (substeq (car pat))(substeq (cdr pat)))))))
                   1394: 
                   1395: (def substequal
                   1396:   (lambda (pat)
                   1397:          (cond ((equal old pat) new)
                   1398:                ((atom pat) pat)
                   1399:                (t (cons (substequal (car pat))
                   1400:                         ; in interlisp, the next line would be
                   1401:                         ;(substeq (cdr pat))
                   1402:                         ; for maclisp compatibility, we do this.
                   1403:                         (substequal (cdr pat)))))))
                   1404: 
                   1405: (declare (unspecial new old))
                   1406: ;--- vi: arg is unevaluated name of function to run vi on
                   1407: ;
                   1408: (def vi (nlambda (x) (exvi 'vi x nil)))
                   1409: 
                   1410: ;--- vil : arg is unevaluated, edits file and then loads it
                   1411: ;
                   1412: (def vil (nlambda (x) (exvi 'vi x t)))
                   1413: 
                   1414: ;--- *quo : returns integer part of x/y
                   1415: ; x and y must be fixnums.
                   1416: ;
                   1417: (putd '*quo (getd 'quotient))
                   1418: 
                   1419: ;--- xcons : a - sexp
                   1420: ;           b - sexp
                   1421: ; returns (b . a)   that is, it is an exchanged cons
                   1422: ;
                   1423: (def xcons  (lambda (a b) (cons b a)))
                   1424: 
                   1425: 
                   1426: 
                   1427: 
                   1428: 
                   1429: 
                   1430: ;--- mode lines, must be last lines of the file
                   1431: ; vi: set lisp :
                   1432: ;

unix.superglobalmegacorp.com

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