|
|
1.1 ! root 1: (include-if (null (get 'chead 'version)) "../chead.l") ! 2: (Liszt-file tlev ! 3: "$Header: tlev.l,v 1.16 84/01/13 15:06:43 jkf Exp $") ! 4: ! 5: ;;; ---- t l e v top level interface ! 6: ;;; ! 7: ;;; -[Tue Nov 22 09:21:27 1983 by jkf]- ! 8: ! 9: ;--- lisztinit : called upon compiler startup. If there are any args ! 10: ; on the command line, we build up a call to liszt, which ! 11: ; will do the compile. Afterwards we exit. ! 12: ; ! 13: (def lisztinit ! 14: (lambda nil ! 15: (setq fl-asm nil) ; insure it as correct value in case of int ! 16: (let ((args (command-line-args))) ! 17: (if args ! 18: then (signal 2 'liszt-interrupt-signal) ; die on int ! 19: (signal 15 'liszt-interrupt-signal) ; die on sigterm ! 20: (setq user-top-level nil) ! 21: (exit (apply 'liszt args)) ! 22: else (patom compiler-name) ! 23: (patom " [")(patom franz-minor-version-number)(patom "]") ! 24: (terpr poport) ! 25: (setq user-top-level nil))))) ! 26: ! 27: (setq user-top-level 'lisztinit) ! 28: ! 29: ;--- liszt - v-x : list containing file name to compile and optionaly ! 30: ; and output file name for the assembler source. ! 31: ; ! 32: (def liszt ! 33: (nlambda (v-x) ! 34: (prog (piport v-root v-ifile v-sfile v-ofile ! 35: vp-ifile vp-sfile vps-crap ! 36: vps-include vns-include ! 37: asm-exit-status ntem temgc temcp ! 38: rootreal g-arrayspecs out-path ! 39: g-decls g-stdref pre-eval include-files ! 40: g-fname g-trueop g-falseop g-didvectorcode ! 41: tem temr starttime startptime startgccount ! 42: fl-asm fl-warn fl-warnfatal fl-verb fl-inter ! 43: fl-xref fl-uci fl-run fl-case fl-anno g-optionalp ! 44: liszt-process-forms in-line-lambda-number ! 45: g-skipcode g-dropnpcnt g-complrname g-fname) ! 46: ! 47: ;in case "S" switch given, set asm-exit-status ! 48: ; to 0 (so garbage won't be returned). ! 49: (setq asm-exit-status 0) ! 50: ! 51: ; turn on monitoring if it exists ! 52: #+monitoring ! 53: (errset (progn (monitor t) ; turn it on ! 54: (print 'monitor-on) ! 55: (terpr)) ! 56: nil) ! 57: (setq starttime (sys:time) ; real time in seconds ! 58: startptime (ptime) ! 59: startgccount $gccount$) ! 60: (setq in-line-lambda-number (sys:time)) ! 61: (cond ((null (boundp 'internal-macros)) ! 62: (setq internal-macros nil))) ! 63: (cond ((null (boundp 'macros)) ! 64: (setq macros nil))) ! 65: (setq er-fatal 0 er-warn 0) ! 66: (setq vps-include nil ! 67: vns-include nil) ;stack of ports and names ! 68: (setq twa-list nil) ! 69: (setq liszt-eof-forms nil) ! 70: ! 71: ; look for lisztrc file and return if error occured ! 72: ; in reading it ! 73: (cond ((eq (do-lisztrc-check) 'error) ! 74: (return 1))) ! 75: ! 76: ; set up once only g variables ! 77: (setq g-comments nil ! 78: g-current nil ; current function name ! 79: g-funcs nil ! 80: g-lits nil ! 81: g-trueloc nil ! 82: g-tran nil ! 83: g-allf nil ; used in xrefs ! 84: g-reguse #+for-vax (copy '((r4 0 . nil) (r3 0 . nil) ! 85: (r2 0 . nil); (r7 0 . nil) ! 86: (r1 0 . nil))) ! 87: #+for-68k (copy '((a0 0 . nil) (a1 0 . nil) ! 88: (d1 0 . nil) (d2 0 . nil) ! 89: (d4 0 . nil) (d5 0 . nil))) ! 90: g-trancnt 0 ! 91: g-ignorereg nil ! 92: g-trueop #+for-vax 'jneq ; used in e-gotot ! 93: #+for-68k 'jne ! 94: g-falseop #+for-vax 'jeql ; used in e-gotonil ! 95: #+for-68k 'jeq ! 96: g-compfcn nil ! 97: g-litcnt 0) ! 98: (setq g-spec (gensym 'S)) ; flag for special atom ! 99: (setq g-fname "") ; no function yet ! 100: (setq special nil) ; t if all vrbs are special ! 101: (setq g-functype (gensym) ! 102: g-vartype (gensym) ! 103: g-bindtype (gensym) ! 104: g-calltype (gensym) ! 105: g-bindloc (gensym) ! 106: g-localf (gensym) ! 107: g-arrayspecs (gensym) ! 108: g-tranloc (gensym) ! 109: g-stdref (gensym) ! 110: g-optionalp (gensym)) ! 111: ! 112: ; declare these special ! 113: ! 114: (sstatus feature complr) ! 115: (d-makespec 't) ; always special ! 116: ! 117: ; process input form ! 118: (setq fl-asm t ; assembler file assembled ! 119: fl-warn t ; print warnings ! 120: fl-warnfatal nil ; warnings are fatal ! 121: fl-verb t ; be verbose ! 122: fl-macl nil ; compile maclisp file ! 123: fl-anno nil ; annotate ! 124: fl-inter nil ; do interlisp compatablity ! 125: fl-tty nil ; put .s on tty ! 126: fl-comments nil ; put in comments ! 127: fl-profile nil ; profiling ! 128: fl-tran t ; use transfer tables ! 129: fl-vms nil ; vms hacks ! 130: fl-case nil ; trans uc to lc ! 131: fl-xref nil ; xrefs ! 132: fl-run nil ; autorun capability ! 133: fl-uci nil ; uci lisp compatibility ! 134: ) ! 135: ! 136: ; look in the environment for a LISZT variable ! 137: ; if it exists, make it the first argument ! 138: (if (not (eq '|| (setq tem (getenv 'LISZT)))) ! 139: then (setq v-x (cons (concat "-" tem) v-x))) ! 140: ! 141: (do ((i v-x (cdr i))) ; for each argument ! 142: ((null i)) ! 143: (setq tem (aexplodec (car i))) ! 144: ! 145: (cond ((eq '- (car tem)) ; if switch ! 146: (do ((j (cdr tem) (cdr j))) ! 147: ((null j)) ! 148: (cond ((eq 'S (car j)) (setq fl-asm nil)) ! 149: ((eq 'C (car j)) (setq fl-comments t)) ! 150: ((eq 'm (car j)) (setq fl-macl t)) ! 151: ((eq 'o (car j)) (setq v-ofile (cadr i) ! 152: i (cdr i))) ! 153: ((eq 'e (car j)) (setq pre-eval (cadr i) ! 154: i (cdr i))) ! 155: ((eq 'i (car j)) (push (cadr i) ! 156: include-files) ! 157: (pop i)) ! 158: ((eq 'w (car j)) (setq fl-warn nil)) ! 159: ((eq 'W (car j)) (setq fl-warnfatal t)) ! 160: ((eq 'q (car j)) (setq fl-verb nil)) ! 161: ((eq 'Q (car j)) (setq fl-verb t)) ! 162: ((eq 'T (car j)) (setq fl-tty t)) ! 163: ((eq 'a (car j)) (setq fl-anno t)) ! 164: ((eq 'i (car j)) (setq fl-inter t)) ! 165: ((eq 'p (car j)) (setq fl-profile t)) ! 166: ((eq 'F (car j)) (setq fl-tran nil)) ! 167: ((eq 'v (car j)) (setq fl-vms t)) ! 168: ((eq 'r (car j)) (setq fl-run t)) ! 169: ((eq 'x (car j)) (setq fl-xref t)) ! 170: ((eq 'c (car j)) (setq fl-case t)) ! 171: ((eq 'u (car j)) (setq fl-uci t)) ! 172: ((eq '- (car j))) ; ignore extra -'s ! 173: (t (comp-gerr "Unknown switch: " ! 174: (car j)))))) ! 175: ((null v-root) ! 176: (setq temr (reverse tem)) ! 177: (cond ((and (eq 'l (car temr)) ! 178: (eq '\. (cadr temr))) ! 179: (setq rootreal nil) ! 180: (setq v-root ! 181: (apply 'concat ! 182: (reverse (cddr temr))))) ! 183: (t (setq v-root (car i) ! 184: rootreal t)))) ! 185: ! 186: (t (comp-gerr "Extra input file name: " (car i))))) ! 187: ! 188: ;no transfer tables in vms ! 189: (cond (fl-vms (setq fl-tran nil))) ! 190: ! 191: ; if verbose mode, print out the gc messages and ! 192: ; fasl messages, else turn them off. ! 193: (cond (fl-verb (setq $gcprint t ! 194: $ldprint t)) ! 195: (t (setq $gcprint nil ! 196: $ldprint nil))) ! 197: ! 198: ; eval arg after -e ! 199: (if pre-eval ! 200: then (if (null (errset ! 201: (eval (readlist (exploden pre-eval))))) ! 202: then (comp-gerr "-e form caused error: " ! 203: pre-eval))) ! 204: ! 205: ; load file after -i arg ! 206: (if include-files ! 207: then (catch ! 208: (mapc ! 209: '(lambda (file) ! 210: (if (null (errset (load file))) ! 211: then (comp-err ! 212: "error when loading -i file: " ! 213: file))) ! 214: include-files) ! 215: Comp-error)) ! 216: ! 217: ; -c says set reader to xlate uc to lc ! 218: (cond (fl-case (sstatus uctolc t))) ! 219: ! 220: ; If we are a cross compiler, then don't try to ! 221: ; assemble our output... ! 222: ; ! 223: #+for-vax ! 224: (if (status feature 68k) ! 225: then (setq fl-asm nil)) ! 226: #+for-68k ! 227: (if (status feature vax) ! 228: then (setq fl-asm nil)) ! 229: ! 230: ; now see what the arguments have left us ! 231: (cond ((null v-root) ! 232: (comp-gerr "No file for input")) ! 233: ((or (portp ! 234: (setq vp-ifile ! 235: (car (errset (infile ! 236: (setq v-ifile ! 237: (concat v-root '".l"))) ! 238: nil)))) ! 239: (and rootreal ! 240: (portp ! 241: (setq vp-ifile ! 242: (car (errset ! 243: (infile (setq v-ifile v-root)) ! 244: nil))))))) ! 245: (t (comp-gerr "Couldn't open the source file :" ! 246: (or v-ifile)))) ! 247: ! 248: ! 249: ; determine the name of the .s file ! 250: ; strategy: if fl-asm is t (assemble) use (v-root).s ! 251: ; else use /tmp/(PID).s ! 252: ; ! 253: ; direct asm to tty temporarily ! 254: (setq v-sfile "tty") ! 255: (setq vp-sfile nil) ! 256: (if (null fl-tty) then ! 257: (cond (fl-asm (setq v-sfile ! 258: (concat '"/tmp/Lzt" ! 259: (boole 1 65535 ! 260: (sys:getpid)) ! 261: '".s"))) ! 262: (t (setq v-sfile ! 263: (if v-ofile ! 264: then v-ofile ! 265: else (concat v-root '".s"))))) ! 266: ! 267: (cond ((not (portp (setq vp-sfile ! 268: (car (errset (outfile v-sfile) ! 269: nil))))) ! 270: (comp-gerr "Couldn't open the .s file: " ! 271: (or v-sfile))))) ! 272: ! 273: ! 274: ; determine the name of the .o file (object file) ! 275: ; strategy: if we aren't supposed to assemble the .s file ! 276: ; don't worry about a name ! 277: ; else if a name is given, use it ! 278: ; else if use (v-root).o ! 279: ; if profiling, use .o ! 280: (cond ((or v-ofile (null fl-asm))) ;ignore ! 281: ((null fl-profile) (setq v-ofile (concat v-root ".o"))) ! 282: (t (setq v-ofile (concat v-root ".o")))) ! 283: ! 284: ; determine the name of the .x file (xref file) ! 285: ; strategy: if fl-xref and v-ofile is true, then use ! 286: ; v-ofile(minus .o).x, else use (v-root).x ! 287: ; ! 288: (if fl-xref ! 289: then ; check for ending with .X for any X ! 290: (setq v-xfile ! 291: (if v-ofile ! 292: then (let ((ex (nreverse ! 293: (exploden v-ofile)))) ! 294: (if (eq #/. (cadr ex)) ! 295: then (implode ! 296: (nreverse ! 297: `(#/x #/. ! 298: ,@(cddr ex)))) ! 299: else (concat v-ofile ".x"))) ! 300: else (concat v-root ".x"))) ! 301: (if (portp ! 302: (setq vp-xfile ! 303: (car (errset (outfile v-xfile))))) ! 304: thenret ! 305: else (comp-gerr "Can't open the .x file: " ! 306: v-xfile))) ! 307: (cond ((checkfatal) (return 1))) ! 308: ! 309: ; g-complrname is a symbol which should be unique to ! 310: ; each fasl'ed file. It will contain the string which ! 311: ; describes the name of this file and the compiler ! 312: ; version. ! 313: (if fl-anno ! 314: then (setq g-complrname (concat "fcn-in-" v-ifile)) ! 315: (Push g-funcs ! 316: `(eval (setq ,g-complrname ! 317: ,(get_pname ! 318: (concat v-ifile ! 319: " compiled by " ! 320: compiler-name ! 321: " on " ! 322: (status ctime))))))) ! 323: ! 324: ! 325: (setq readtable (makereadtable nil)) ; use new readtable ! 326: ! 327: ! 328: ; if the macsyma flag is set, change the syntax to the ! 329: ; maclisp standard syntax. We must be careful that we ! 330: ; dont clobber any syntax changes made by files preloaded ! 331: ; into the compiler. ! 332: ! 333: (cond (fl-macl (setsyntax '\/ 'vescape) ; 143 = vesc ! 334: ! 335: (cond ((eq 'vescape (getsyntax '\\)) ! 336: (setsyntax '\\ 'vcharacter))) ! 337: ! 338: (cond ((eq 'vleft-bracket (getsyntax '\[)) ! 339: (setsyntax '\[ 'vcharacter) ! 340: (setsyntax '\] 'vcharacter))) ! 341: (setq ibase 8.) ! 342: (sstatus uctolc t) ! 343: ! 344: (d-makespec 'ibase) ; to be special ! 345: (d-makespec 'base) ! 346: (d-makespec 'tty) ! 347: ! 348: (errset (cond ((null (getd 'macsyma-env)) ! 349: (load 'machacks))) ! 350: nil)) ! 351: (fl-uci (load "ucifnc") ! 352: (cvttoucilisp))) ! 353: ! 354: (cond (fl-inter (putprop '* 'cc-ignore 'fl-exprcc) ;comment ! 355: (remprop '* 'fl-expr) ! 356: )) ! 357: ! 358: (cond ((checkfatal) (return 1))) ; leave if fatal errors ! 359: ! 360: (if fl-verb ! 361: then (comp-msg "Compilation begins with " compiler-name ) ! 362: (comp-msg "source: " v-ifile ", result: " ! 363: (cond (fl-asm v-ofile) (t v-sfile)))) ! 364: ! 365: (setq piport vp-ifile) ; set to standard input ! 366: (setq liszt-root-name v-root ! 367: liszt-file-name v-ifile) ! 368: ! 369: ! 370: (if fl-run then (d-printautorun)) ! 371: ! 372: (if fl-profile then (e-write1 '".globl mcount")) ! 373: loop ! 374: ! 375: ; main loop of the compiler. It reads a form and ! 376: ; compiles it. It continues to compile forms from ! 377: ; liszt-process-forms was long at that list is ! 378: ; non-empty. This allows one form to spawn off other ! 379: ; forms to be compiled (an alternative to (progn 'compile)) ! 380: ; ! 381: (cond ((atom (errset ; list for debugging, ! 382: ; errset for production. ! 383: (do ((i (read piport '<<end-of-file>>) ! 384: (read piport '<<end-of-file>>))) ! 385: ((eq i '<<end-of-file>>) nil) ! 386: (setq liszt-process-forms ! 387: (cons i liszt-process-forms)) ! 388: (do ((this (car liszt-process-forms) ! 389: (car liszt-process-forms))) ! 390: ((null liszt-process-forms)) ! 391: (unpush liszt-process-forms) ! 392: (catch (liszt-form this) Comp-error))))) ! 393: (catch (comp-err "Lisp error during compilation") ! 394: Comp-error) ! 395: (setq piport nil) ! 396: (setq er-fatal (1+ er-fatal)) ! 397: (return 1))) ! 398: ! 399: (close piport) ! 400: ! 401: ; if doing special character stuff (maclisp) reassert ! 402: ; the state ! 403: ! 404: (cond (vps-include ! 405: (comp-note " done include") ! 406: (setq piport (car vps-include) ! 407: vps-include (cdr vps-include) ! 408: v-ifile (car vns-include) ! 409: vns-include (cdr vns-include)) ! 410: (go loop))) ! 411: ! 412: (cond (liszt-eof-forms ! 413: (do ((ll liszt-eof-forms (cdr ll))) ! 414: ((null ll)) ! 415: (cond ((atom (errset (liszt-form (car ll)))) ! 416: (catch ! 417: (comp-note "Lisp error during eof forms") ! 418: Comp-error) ! 419: (setq piport nil) ! 420: (return 1)))))) ! 421: ! 422: ; reset input base ! 423: (setq ibase 10.) ! 424: (setq readtable (makereadtable t)) ! 425: (sstatus uctolc nil) ; turn off case conversion ! 426: ; so bindtab will not have |'s ! 427: ; to quote lower case ! 428: (d-bindtab) ! 429: ! 430: (d-printdocstuff) ; describe this compiler ! 431: ! 432: (cond ((portp vp-sfile) ! 433: (close vp-sfile))) ; close assembler language file ! 434: ! 435: ; if warnings are to be considered fatal, and if we ! 436: ; have seen to many warnings, make it fatal ! 437: (cond ((and fl-warnfatal (> er-warn 0)) ! 438: (comp-gerr "Too many warnings"))) ! 439: ! 440: ; check for fatal errors and don't leave if so ! 441: (cond ((checkfatal) ! 442: (if fl-asm ; unlink .s file ! 443: then (sys:unlink v-sfile)) ; if it is a tmp ! 444: (return 1))) ; and ret with error status ! 445: ! 446: (comp-note "Compilation complete") ! 447: ! 448: (setq tem (Divide (difference (sys:time) starttime) 60)) ! 449: (setq ntem (ptime)) ! 450: ! 451: (setq temcp (Divide (difference (car ntem) (car startptime)) ! 452: 3600)) ! 453: ! 454: (setq temgc (Divide (difference (cadr ntem) (cadr startptime)) ! 455: 3600)) ! 456: ! 457: (comp-note " Time: Real: " (car tem) ":" (cadr tem) ! 458: ", CPU: " (car temcp) ":" (quotient (cadr temcp) 60.0) ! 459: ", GC: " (car temgc) ":" (quotient (cadr temgc) 60.0) ! 460: " for " ! 461: (difference $gccount$ startgccount) ! 462: " gcs") ! 463: ! 464: (cond (fl-xref ! 465: (comp-note "Cross reference being generated") ! 466: (print (list 'File v-ifile) vp-xfile) ! 467: (terpr vp-xfile) ! 468: (do ((ii g-allf (cdr ii))) ! 469: ((null ii)) ! 470: (print (car ii) vp-xfile) ! 471: (terpr vp-xfile)) ! 472: (close vp-xfile))) ! 473: ! 474: ! 475: ; the assember we use must generate the new a.out format ! 476: ; with a string table. We will assume that the assembler ! 477: ; is in /usr/lib/lisp/as so that other sites can run ! 478: ; the new assembler without installing the new assembler ! 479: ; as /bin/as ! 480: (cond (fl-asm ; assemble file ! 481: (comp-note "Assembly begins") ! 482: (cond ((not ! 483: (zerop ! 484: (setq asm-exit-status ! 485: (*process ! 486: (concat ! 487: lisp-library-directory ! 488: "/as " ! 489: #+for-vax "-V" ; use virt mem ! 490: " -o " ! 491: v-ofile ! 492: " " ! 493: v-sfile))))) ! 494: (comp-gerr "Assembler detected error, code: " ! 495: asm-exit-status) ! 496: (comp-note "Assembler temp file " v-sfile ! 497: " is not unlinked")) ! 498: (t (comp-note "Assembly completed successfully") ! 499: (errset (sys:unlink v-sfile)); unlink tmp ! 500: ; file ! 501: (if fl-run ! 502: then (errset ! 503: (sys:chmod v-ofile #O775))))))) ! 504: ! 505: #+(and sun (not unisoft)) ! 506: (if (and v-ofile fl-run) ! 507: then (if (null ! 508: (errset (let ((port (fileopen v-ofile "r+"))) ! 509: (fseek port 20 0) ! 510: (tyo 0 port) ! 511: (tyo 0 port) ! 512: (tyo 128 port) ! 513: (tyo 0 port) ! 514: (close port)))) ! 515: then (comp-err ! 516: "Error while fixing offset in object file: " ! 517: v-ofile))) ! 518: ! 519: (setq readtable original-readtable) ! 520: #+monitoring ! 521: (errset (progn (monitor) ; turn off monitoring ! 522: (print 'monitor-off)) ! 523: nil) ! 524: (sstatus nofeature complr) ! 525: (return asm-exit-status)))) ! 526: ! 527: (def checkfatal ! 528: (lambda nil ! 529: (cond ((greaterp er-fatal 0) ! 530: (catch (comp-err "Compilation aborted due to previous errors") ! 531: Comp-error) ! 532: t)))) ! 533: ! 534: ;--- do-lisztrc-check ! 535: ; look for a liszt init file named ! 536: ; .lisztrc or lisztrc or $HOME/.lisztrc or $HOME/lisztrc ! 537: ; followed by .o or .l or nothing ! 538: ; return the symbol 'error' if an error occured while reading. ! 539: ; ! 540: (defun do-lisztrc-check nil ! 541: (do ((dirs `("." ,(getenv 'HOME)) (cdr dirs)) ! 542: (val) ! 543: ($gcprint nil) ! 544: ($ldprint nil)) ! 545: ((null dirs)) ! 546: (if (setq val ! 547: (do ((name '(".lisztrc" "lisztrc") (cdr name)) ! 548: (val)) ! 549: ((null name)) ! 550: (if (setq val ! 551: (do ((ext '(".o" ".l" "") (cdr ext)) ! 552: (file)) ! 553: ((null ext)) ! 554: (if (probef ! 555: (setq file (concat (car dirs) ! 556: "/" ! 557: (car name) ! 558: (car ext)))) ! 559: then (if (atom (errset (load file))) ! 560: then (comp-msg ! 561: "Error loading liszt init file " ! 562: file N ! 563: "Compilation aborted" N) ! 564: (return 'error) ! 565: else (return t))))) ! 566: then (return val)))) ! 567: then (return val)))) ! 568: ! 569: ! 570: ;--- liszt-form - i : form to compile ! 571: ; This compiles one form. ! 572: ; ! 573: (def liszt-form ! 574: (lambda (i) ! 575: (prog (tmp v-x) ! 576: ; macro expand ! 577: loop ! 578: (setq i (d-macroexpand i)) ! 579: ; now look at what is left ! 580: (cond ((not (dtpr i)) (Push g-funcs `(eval ,i))) ! 581: ((eq (car i) 'def) ! 582: (cond (fl-verb (print (cadr i)) (terpr)(drain))) ! 583: (d-dodef i)) ! 584: ((memq (car i) '(liszt-declare declare)) ! 585: (funcall 'liszt-declare (cdr i))) ! 586: ((eq (car i) 'eval-when) (doevalwhen i)) ! 587: ((and (eq (car i) 'progn) (equal (cadr i) '(quote compile))) ! 588: ((lambda (internal-macros) ; compile macros too ! 589: (mapc 'liszt-form (cddr i))) ! 590: t)) ! 591: ((or (and (eq (car i) 'includef) (setq tmp (eval (cadr i)))) ! 592: (and (eq (car i) 'include ) (setq tmp (cadr i)))) ! 593: (cond ((or (portp (setq v-x ! 594: (car (errset (infile tmp) nil)))) ! 595: (portp (setq v-x ! 596: (car ! 597: (errset ! 598: (infile ! 599: (concat ! 600: lisp-library-directory ! 601: "/" ! 602: tmp)) ! 603: nil)))) ! 604: (portp (setq v-x ! 605: (car (errset (infile (concat tmp ! 606: '".l")) ! 607: nil))))) ! 608: (setq vps-include (cons piport vps-include)) ! 609: (setq piport v-x) ! 610: (comp-note " INCLUDEing file: " tmp) ! 611: (setq vns-include (cons v-ifile vns-include) ! 612: v-ifile tmp)) ! 613: (t (comp-gerr "Cannot open include file: " tmp)))) ! 614: ((eq (car i) 'comment) nil) ; just ignore comments ! 615: (t ; we have to macro expand ! 616: ; certain forms we would normally ! 617: ; just dump in the eval list. This is due to hacks in ! 618: ; the mit lisp compiler which are relied upon by certain ! 619: ; code from mit. ! 620: (setq i (d-fullmacroexpand i)) ! 621: ! 622: (Push g-funcs `(eval ,i))))))) ! 623: ! 624: ;--- d-dodef :: handle the def form ! 625: ; - form : a def form: (def name (type args . body)) ! 626: ; ! 627: (defun d-dodef (form) ! 628: (prog (g-ftype g-args body lambdaform symlab g-arginfo g-compfcn g-decls) ! 629: ! 630: ! 631: (setq g-arginfo 'empty) ! 632: ! 633: loop ! 634: ; extract the components of the def form ! 635: (setq g-fname (cadr form)) ! 636: (if (dtpr (caddr form)) ! 637: then (setq g-ftype (caaddr form) ! 638: g-args (cadaddr form) ! 639: body (cddaddr form) ! 640: lambdaform (caddr form) ! 641: symlab (gensym 'F)) ! 642: else (comp-gerr "bad def form " form)) ! 643: ! 644: ; check for a def which uses the mit hackish &xxx forms. ! 645: ; if seen, convert to a standard form and reexamine ! 646: ; the vax handles these forms in a special way. ! 647: #+for-68k ! 648: (if (or (memq '&rest g-args) ! 649: (memq '&optional g-args) ! 650: (memq '&aux g-args)) ! 651: then (setq form ! 652: `(def ,(cadr form) ,(lambdacvt (cdr lambdaform)))) ! 653: (go loop)) ! 654: ! 655: ; check for legal function name. ! 656: ; then look at the type of the function and update the data base. ! 657: (if (null (atom g-fname)) ! 658: then (comp-err "bad function name") ! 659: else (setq g-flocal (get g-fname g-localf)) ; check local decl. ! 660: ; macros are special, they are always evaluated ! 661: ; and sometimes compiled. ! 662: (if (and (not g-flocal) (eq g-ftype 'macro)) ! 663: then (eval form) ! 664: (if (and (null macros) ! 665: (null internal-macros)) ! 666: then (comp-note g-fname ! 667: " macro will not be compiled") ! 668: (return nil)) ! 669: (Push g-funcs `(macro ,symlab ,g-fname)) ! 670: (if fl-anno then (setq g-arginfo nil)) ; no arg info ! 671: elseif g-flocal ! 672: then (if (null (or (eq g-ftype 'lambda) ! 673: (eq g-ftype 'nlambda))) ! 674: then (comp-err ! 675: "bad type for local fcn: " g-ftype)) ! 676: (if (or (memq '&rest g-args) ! 677: (memq '&optional g-args) ! 678: (memq '&aux g-args)) ! 679: then (comp-err ! 680: "local functions can't use &keyword's " ! 681: g-fname)) ! 682: elseif (or (eq g-ftype 'lambda) ! 683: (eq g-ftype 'lexpr)) ! 684: then (push `(lambda ,symlab ,g-fname) g-funcs) ! 685: (putprop g-fname 'lambda g-functype) ! 686: elseif (eq g-ftype 'nlambda) ! 687: then (Push g-funcs `(nlambda ,symlab ,g-fname)) ! 688: (putprop g-fname 'nlambda g-functype) ! 689: else (comp-err " bad function type " g-ftype))) ! 690: (setq g-skipcode nil) ;make sure we aren't skipping code ! 691: (forcecomment `(fcn ,g-ftype ,g-fname)) ! 692: (if g-flocal ! 693: then (comp-note g-fname " is a local function") ! 694: (e-writel (car g-flocal)) ! 695: else (if (null fl-vms) then (e-write2 '".globl" symlab)) ! 696: (e-writel symlab)) ! 697: (setq g-locs nil g-loccnt 0 g-labs nil g-loc 'reg g-cc nil ! 698: g-ret t g-topsym (d-genlab)) ! 699: (if fl-xref then (setq g-refseen (gensym) g-reflst nil)) ! 700: (d-clearreg) ! 701: #+for-68k (init-regmaskvec) ! 702: ; set up global variables which maintain knowledge about ! 703: ; the stack. these variables are set up as if the correct ! 704: ; number of args were passed. ! 705: (setq g-compfcn t) ; now compiling a function ! 706: (push nil g-labs) ; no labels in a lambda ! 707: (setq g-currentargs (length g-args)) ! 708: (d-prelude) ; do beginning stuff ! 709: ! 710: ; on the vax, we handle & keywords in a special way in ! 711: ; d-outerlambdacomp. This function also sets g-arginfo. ! 712: #+for-vax ! 713: (d-outerlambdacomp g-fname g-args (cddr lambdaform)) ! 714: ! 715: #+for-68k ! 716: (progn ! 717: (push (cons 'lambda 0) g-locs) ! 718: (mapc '(lambda (x) ! 719: (push nil g-locs) ! 720: (incr g-loccnt)) ! 721: g-args) ! 722: ; set g-arginfo if this is a lambda. If it is a lexpr, then ! 723: ; we don't give all the info we could. ! 724: (setq g-arginfo ! 725: (if (eq g-ftype 'lambda) ! 726: then (cons g-loccnt g-loccnt))) ! 727: (d-lambbody lambdaform)) ! 728: ! 729: (d-fini) ! 730: (setq g-compfcn nil) ; done compiling a fcn ! 731: (if fl-xref then ! 732: (Push g-allf ! 733: (cons g-fname ! 734: (cons (cond (g-flocal (cons g-ftype 'local)) ! 735: (t g-ftype)) ! 736: g-reflst)))) ! 737: (if (and fl-anno (not (eq 'empty g-arginfo))) ! 738: then (Push g-funcs `(eval (putprop ! 739: ',g-fname ! 740: (list ',g-arginfo ! 741: ,g-complrname) ! 742: 'fcn-info)))) ! 743: ; by storing argument count information during compilation ! 744: ; we can arg number check calls to this function which occur ! 745: ; further on. ! 746: (if (not (eq 'empty g-arginfo)) ! 747: then (putprop g-fname (list g-arginfo) 'fcn-info)))) ! 748: ! 749: ;--- d-lambdalistcheck :: scan lambda var list for & forms ! 750: ; return ! 751: ; (required optional rest op-p body) ! 752: ; required - list of required args ! 753: ; optional - list of (variable default [optional-p]) ! 754: ; rest - either nil or the name of a variable for optionals ! 755: ; op-p - list of variables set to t or nil depending if optional exists ! 756: ; body - body to compile (has &aux's wrapped around it in lambdas) ! 757: ; ! 758: #+for-vax ! 759: (defun d-lambdalistcheck (list body) ! 760: (do ((xx list (cdr xx)) ! 761: (state 'req) ! 762: (statechange) ! 763: (arg) ! 764: (req)(optional)(rest)(op-p)(aux)) ! 765: ((null xx) ! 766: (list (nreverse req) ! 767: (nreverse optional) ! 768: rest ! 769: (nreverse op-p) ! 770: (d-lambda-aux-body-convert body (nreverse aux)))) ! 771: (setq arg (car xx)) ! 772: (if (memq arg '(&optional &rest &aux)) ! 773: then (setq statechange arg) ! 774: else (setq statechange nil)) ! 775: (caseq state ! 776: (req ! 777: (if statechange ! 778: then (setq state statechange) ! 779: elseif (and (symbolp arg) arg) ! 780: then (push arg req) ! 781: else (comp-err " illegal lambda variable " arg))) ! 782: (&optional ! 783: (if statechange ! 784: then (if (memq statechange '(&rest &aux)) ! 785: then (setq state statechange) ! 786: else (comp-err "illegal form in lambda list " ! 787: xx)) ! 788: elseif (symbolp arg) ! 789: then ; optional which defaults to nil ! 790: (push (list arg nil) optional) ! 791: elseif (dtpr arg) ! 792: then (if (and (symbolp (car arg)) ! 793: (symbolp (caddr arg))) ! 794: then ; optional with default ! 795: (push arg optional) ! 796: ; save op-p ! 797: (if (cddr arg) ! 798: then (push (caddr arg) op-p))) ! 799: else (comp-err "illegal &optional form " ! 800: arg))) ! 801: (&rest ! 802: (if statechange ! 803: then (if (eq statechange '&aux) ! 804: then (setq state statechange) ! 805: else (comp-err "illegal lambda variable form " ! 806: xx)) ! 807: elseif rest ! 808: then (comp-err ! 809: "more than one rest variable in lambda list" ! 810: arg) ! 811: else (setq rest arg))) ! 812: (&aux ! 813: (if statechange ! 814: then (comp-err "illegal lambda form " xx) ! 815: elseif (and (symbolp arg) arg) ! 816: then (push (list arg nil) aux) ! 817: elseif (and (dtpr arg) (and (symbolp (car arg)) ! 818: (car arg))) ! 819: then (push arg aux))) ! 820: (t (comp-err "bizzarro internal compiler error "))))) ! 821: ! 822: ;--- d-lambda-aux-body-convert :: convert aux's to lambdas ! 823: ; give a function body and a list of aux variables ! 824: ; and their inits, place a lambda initializing body around body ! 825: ; for each lambda (basically doing a let*). ! 826: ; ! 827: #+for-vax ! 828: (defun d-lambda-aux-body-convert (body auxlist) ! 829: (if (null auxlist) ! 830: then body ! 831: else `(((lambda (,(caar auxlist)) ! 832: ,@(d-lambda-aux-body-convert body (cdr auxlist))) ! 833: ,(cadar auxlist))))) ! 834: ! 835: ;--- d-outerlambdacomp :: compile a functions outer lambda body ! 836: ; This function compiles the lambda expression which defines ! 837: ; the function. This lambda expression differs from the kind that ! 838: ; appears within a function because ! 839: ; 1. we aren't sure that the correct number of arguments have been stacked ! 840: ; 2. the keywords &optional, &rest, and &aux may appear ! 841: ; ! 842: ; funname - name of function ! 843: ; lambdalist - the local argument list, (with possible keywords) ! 844: ; body - what follows the lambdalist ! 845: ; ! 846: ; ! 847: ; ! 848: #+for-vax ! 849: (defun d-outerlambdacomp (funname lambdalist body) ! 850: (let (((required optional rest op-p newbody) ! 851: (d-lambdalistcheck lambdalist body)) ! 852: (g-decls g-decls) ! 853: (reqnum 0) maxwithopt labs (maxnum -1) args) ! 854: (d-scanfordecls body) ! 855: ; if this is a declared lexpr, we aren't called ! 856: ; ! 857: (if (and (null optional) (null rest)) ! 858: then ; simple, the number of args is required ! 859: ; if lexpr or local function, then don't bother ! 860: (if (and (not g-flocal) ! 861: (not (eq g-ftype 'lexpr))) ! 862: then (d-checkforfixedargs ! 863: funname ! 864: (setq reqnum (setq maxnum (length required))))) ! 865: else ; complex, unknown number of args ! 866: ; cases: ! 867: ; optional, no rest ! 868: ; optional, with rest ! 869: ; no optional, rest + required ! 870: ; no optional, rest + no required ! 871: (setq reqnum (length required) ! 872: maxwithopt (+ reqnum (length optional)) ! 873: maxnum (if rest then -1 else maxwithopt)) ! 874: ; determine how many args were given ! 875: (e-sub3 '#.lbot-reg '#.np-reg '#.lbot-reg) ! 876: (e-write4 'ashl '$-2 '#.lbot-reg '#.lbot-reg) ! 877: ; ! 878: (if (null optional) ! 879: then ; just a rest ! 880: (let ((oklab (d-genlab)) ! 881: (lllab (d-genlab)) ! 882: (nopushlab (d-genlab))) ! 883: (if (> reqnum 0) ! 884: then (e-cmp '#.lbot-reg `($ ,reqnum)) ! 885: (e-write2 'jgeq oklab) ! 886: ; not enough arguments given ! 887: (d-wnaerr funname reqnum -1) ! 888: (e-label oklab)) ! 889: (e-pushnil 1) ! 890: (if (> reqnum 0) ! 891: then (e-sub `($ ,reqnum) '#.lbot-reg) ! 892: else (e-tst '#.lbot-reg)) ! 893: (e-write2 'jleq nopushlab) ! 894: (e-label lllab) ! 895: (e-quick-call '_qcons) ! 896: (d-move 'reg 'stack) ! 897: (e-write3 'sobgtr '#.lbot-reg lllab) ! 898: (e-label nopushlab)) ! 899: else ; has optional args ! 900: ; need one label for each optional plus 2 ! 901: (do ((xx optional (cdr xx)) ! 902: (res (list (d-genlab) (d-genlab)))) ! 903: ((null xx) (setq labs res)) ! 904: (push (d-genlab) res)) ! 905: ; push nils for missing optionals ! 906: ; one case for required amount and one for ! 907: ; each possible number of optionals ! 908: (e-write4 'casel ! 909: '#.lbot-reg `($ ,reqnum) ! 910: `($ ,(- maxwithopt reqnum))) ! 911: (e-label (car labs)) ! 912: (do ((xx (cdr labs) (cdr xx)) ! 913: (head (car labs))) ! 914: ((null xx)) ! 915: (e-write2 '.word (concat (car xx) "-" head))) ! 916: ; get here (when running code) if there are more ! 917: ; than the optional number of args or if there are ! 918: ; too few args. If &rest is given, it is permitted ! 919: ; to have more than the required number ! 920: (let ((dorest (d-genlab)) ! 921: (again (d-genlab)) ! 922: (afterpush (d-genlab))) ! 923: (if rest ! 924: then ; check if there are greater than ! 925: ; the required number ! 926: ; preserve arg # ! 927: (C-push '#.lbot-reg) ! 928: (e-sub `($ ,maxwithopt) '#.lbot-reg) ! 929: (e-write2 'jgtr dorest) ! 930: (C-pop '#.lbot-reg)) ! 931: ; wrong number of args ! 932: (d-wnaerr funname reqnum maxnum) ! 933: (if rest ! 934: then ; now cons the rest forms ! 935: (e-label dorest) ! 936: (e-pushnil 1) ; list ends with nil ! 937: (e-label again) ! 938: (e-quick-call '_qcons) ! 939: (d-move 'reg 'stack) ! 940: ; and loop ! 941: (e-write3 'sobgtr '#.lbot-reg again) ! 942: ; arg # ! 943: (C-pop '#.lbot-reg) ! 944: (e-goto afterpush)) ! 945: ; push the nils on the optionals ! 946: (do ((xx (cdr labs) (cdr xx))) ! 947: ((null xx)) ! 948: (e-label (car xx)) ! 949: ; if we have exactly as many arguments given ! 950: ; as the number of optionals, then we stack ! 951: ; a nil if there is a &rest after ! 952: ; the optionals ! 953: (if (null (cdr xx)) ! 954: then (if rest ! 955: then (e-pushnil 1)) ! 956: else (e-pushnil 1))) ! 957: (e-label afterpush)))) ! 958: ; for optional-p's stack t's ! 959: (mapc '(lambda (form) (d-move 'T 'stack)) op-p) ! 960: ! 961: ; now the variables must be shallow bound ! 962: ; creat a list of all arguments ! 963: (setq args (append required ! 964: (mapcar 'car optional) ! 965: (if rest then (list rest)) ! 966: op-p)) ! 967: ! 968: (push (cons 'lambda 0) g-locs) ! 969: (mapc '(lambda (x) ! 970: (push nil g-locs)) ! 971: args) ! 972: (setq g-loccnt (length args)) ! 973: (d-bindlamb args) ; do shallow binding if necessary ! 974: ; ! 975: ; if any of the optionals have non null defaults or ! 976: ; optional-p's, we have to evaluate their defaults ! 977: ; or set their predicates. ! 978: ; first, see if it is necessary ! 979: (if (do ((xx optional (cdr xx))) ! 980: ((null xx) nil) ! 981: (if (or (cadar xx) ; if non null default ! 982: (caddar xx)); or predicate ! 983: then (return t))) ! 984: then (makecomment '(do optional defaults and preds)) ! 985: ; create labels again ! 986: ; need one label for each optional plus 1 ! 987: (do ((xx optional (cdr xx)) ! 988: (res (list (d-genlab) ))) ! 989: ((null xx) (setq labs res)) ! 990: (push (d-genlab) res)) ! 991: ; we need to do something if the argument count ! 992: ; is between the number of required arguments and ! 993: ; the maximum number of args with optional minus 1. ! 994: ; we have one case for the required number and ! 995: ; one for each optional except the last optional number ! 996: ; ! 997: (let ((afterthis (d-genlab))) ! 998: (e-write4 'casel ! 999: '#.lbot-reg `($ ,reqnum) ! 1000: `($ ,(- maxwithopt reqnum 1))) ! 1001: (e-label (car labs)) ! 1002: (do ((xx (cdr labs) (cdr xx)) ! 1003: (head (car labs))) ! 1004: ((null xx)) ! 1005: (e-write2 '.word (concat (car xx) "-" head))) ! 1006: (e-goto afterthis) ! 1007: (do ((ll (cdr labs) (cdr ll)) ! 1008: (op optional (cdr op)) ! 1009: (g-loc nil) ! 1010: (g-cc nil) ! 1011: (g-ret nil)) ! 1012: ((null ll)) ! 1013: (e-label (car ll)) ! 1014: (if (caddar op) ! 1015: then (d-exp `(setq ,(caddar op) nil))) ! 1016: (if (cadar op) ! 1017: then (d-exp `(setq ,(caar op) ,(cadar op))))) ! 1018: (e-label afterthis))) ! 1019: ! 1020: ; now compile the function ! 1021: (d-clearreg) ! 1022: (setq g-arginfo ! 1023: (if (eq g-ftype 'nlambda) ! 1024: then nil ! 1025: else (cons reqnum (if (>& maxnum 0) then maxnum else nil)))) ! 1026: (makecomment '(begin-fcn-body)) ! 1027: (d-exp (do ((ll newbody (cdr ll)) ! 1028: (g-loc) ! 1029: (g-cc) ! 1030: (g-ret)) ! 1031: ((null (cdr ll)) (car ll)) ! 1032: (d-exp (car ll)))) ! 1033: (d-unbind))) ! 1034: ! 1035: #+for-vax ! 1036: (defun d-checkforfixedargs (fcnname number) ! 1037: (let ((oklab (d-genlab))) ! 1038: (makecomment `(,fcnname should-have-exactly ,number args)) ! 1039: ; calc -4*# of args ! 1040: (e-sub '#.np-reg '#.lbot-reg) ! 1041: (e-cmp '#.lbot-reg `($ ,(- (* number 4)))) ! 1042: (e-write2 'jeql oklab) ! 1043: (d-wnaerr fcnname number number) ! 1044: (e-label oklab))) ! 1045: ! 1046: ;--- d-wnaerr :: generate code to call wrong number of args error ! 1047: ; name is the function name, ! 1048: ; min is the minumum number of args for this function ! 1049: ; max is the maximum number (-1 if there is no maximum) ! 1050: ; we encode the min and max in the way shown below. ! 1051: ; ! 1052: #+for-vax ! 1053: (defun d-wnaerr (name min max) ! 1054: (makecomment `(arg error for fcn ,name min ,min max ,max)) ! 1055: (e-move 'r10 '#.lbot-reg) ! 1056: (C-push `($ ,(+ (* min 1000) (+ max 1)))) ! 1057: (C-push (e-cvt (d-loclit name nil))) ! 1058: (e-write3 'calls '$2 '_wnaerr)) ! 1059: ! 1060: ;--- d-genlab :: generate a pseudo label ! 1061: ; ! 1062: (defun d-genlab nil ! 1063: (gensym 'L)) ! 1064: ! 1065: ;--- liszt-interrupt-signal ! 1066: ; if we receive a interrupt signal (commonly a ^C), then ! 1067: ; unlink the .s file if we are generating a temporary one ! 1068: ; and exit ! 1069: (defun liszt-interrupt-signal (sig) ! 1070: (if (and fl-asm (boundp 'v-sfile) v-sfile) ! 1071: then (sys:unlink v-sfile)) ! 1072: (exit 1))
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.