display_lisp_object_segment.pl1 11/20/86 1414.6r w 11/20/86 1145.0 135270 /* ************************************************************** * * * Copyright, (C) Massachusetts Institute of Technology, 1982 * * * ************************************************************** */ display_lisp_object_segment: dlos: proc options (variable); /* BSG 5/13/80 */ /* declarations */ dcl BAD_CHARS char (32) static init ("() |/'`#;.,"" ") options (constant); dcl error_table_$badopt ext static fixed bin (35); dcl (null, length, substr, addr, addrel, ltrim, copy, search) builtin; dcl (actionx, linkx, arrayx, subrx, quotx, constx, action_count, action_type) fixed bin; dcl (n_fixnums, n_flonums, n_strings, n_bignums, n_conses, n_atsyms) fixed bin; dcl (entryp, tempp, actionp, segp, defp, constp, blockp, arrayp, linkp, sblkp, bigp, symrtp) ptr; dcl bc fixed bin (24); dcl segtop fixed bin (18); dcl argno fixed bin; dcl dir char (168), ent char (32); dcl code fixed bin (35), arg char (argl) based (argp), argp ptr, argl fixed bin (21), myname char (32) init ("display_lisp_object_segment") static options (constant); dcl (doing_constants, doing_subr_links, doing_array_links) bit (1); dcl unalconst fixed bin (17) unaligned automatic; dcl 1 constant_index_format aligned structure, 2 load_time bit(1) unaligned, 2 constant_x fixed bin(16) unaligned; dcl 1 array_info unaligned, 2 type fixed bin (9) unsigned, 2 ndims fixed bin (9) unsigned, 2 sym_offset fixed bin (17) unaligned; dcl 1 link_info unaligned, /* format of 27 info bits in an ITP link */ 2 fcn_offset fixed bin(14), /* signed offset from ap or lp of function */ 2 snap bit(1), /* 1 if link can (should) be snapped */ 2 constant bit(1), /* 1 if fcn_offset is offset from lp of atom */ 2 fsubr bit(1), /* 1 for fsubr, 0 for subr/lsubr */ 2 nargs fixed bin (9) unsigned; /* 777 if arg count is in x5, else arg count */ dcl 1 oi aligned like object_info; dcl 1 sroot aligned like symbol_root based (symrtp); dcl 1 bignum aligned like lisp_bignum based (bigp); dcl cu_$arg_ptr entry (fixed bin, ptr, fixed bin (21), fixed bin (35)); dcl expand_pathname_ entry (char (*), char (*), char (*), fixed bin (35)); dcl hcs_$initiate_count entry (char (*), char (*), char (*), fixed bin (24), fixed bin (2), ptr, fixed bin (35)); dcl get_definition_ entry (ptr, char(*), char(*), ptr, fixed bin(35)); dcl hcs_$terminate_noname entry (ptr, fixed bin (35)); dcl object_info_$brief entry (ptr, fixed bin(24), ptr, fixed bin(35)); dcl (ioa_, com_err_) entry options (variable); %include definition; %include object_info; %include lisp_bignum_fmt; %include lisp_symb_tree; %include std_symbol_header; doing_constants, doing_array_links, doing_subr_links = "0"b; call cu_$arg_ptr (1, argp, argl, code); if code ^= 0 then do; call com_err_ (code, myname, "Usage: dlos "); return; end; call expand_pathname_ (arg, dir, ent, code); if code ^= 0 then do; call com_err_ (code, myname, "^a", arg); return; end; do argno = 2 by 1; call cu_$arg_ptr (argno, argp, argl, code); if code = 0 then do; if arg = "-long" | arg = "-lg" | arg = "-all" | arg = "-a" then doing_constants, doing_array_links, doing_subr_links = "1"b; else if arg = "-constant" | arg = "-constants" | arg = "-c" | arg = "-cc" | arg = "-compiled_constants" then doing_constants = "1"b; else if arg = "-l" | arg = "-lk" | arg = "link" | arg = "-links" then doing_subr_links = "1"b; else if arg = "-subr" | arg = "-s" | arg = "-subr_links" | arg = "-sl" then doing_subr_links = "1"b; else if arg = "-array" | arg = "-array_links" | arg = "-al" then doing_array_links = "1"b; else do; call com_err_ (error_table_$badopt, myname, "^a", arg); return; end; end; else go to no_more_args; end; no_more_args: call hcs_$initiate_count (dir, ent, "", bc, 0, segp, code); if segp = null () then do; call com_err_ (code, myname, "^a>^a", dir, ent); return; end; /* Get symbol table */ oi.version_number = object_info_version_2; call object_info_$brief (segp, bc, addr (oi), code); if code ^= 0 then do; call com_err_ (code, myname, "^a>^a", dir, ent); go to term; end; call get_definition_ (oi.defp, ent, "*segtop", defp, code); if code ^= 0 then do; call com_err_ (code, myname, "*segtop in ^a>^a", dir, ent); go to term; end; segtop = fixed (rel (addrel (oi.textp, defp -> definition.value)), 18); call get_definition_ (oi.defp, ent, "symbol_table", defp, code); if code ^= 0 then do; call com_err_ (code, myname, "symbol_table in ^a>^a", dir, ent); go to term; end; sblkp = addrel (oi.symbp, defp -> definition.value); if sblkp -> std_symbol_header.generator ^= "lisp" then do; call com_err_ (0, myname, "Not a Lisp object segment: ^a>^a", dir, ent); go to term; end; if sblkp -> std_symbol_header.gen_number ^= 2 then do; call com_err_ (0, myname, "Version ^d Lisp object seg not supported.", sblkp -> std_symbol_header.gen_number); go to term; end; /* Do it */ symrtp = addrel (sblkp, sblkp -> std_symbol_header.area_pointer); subrx = 1; entryp = addrel (symrtp, sroot.entry_blockp); n_fixnums = addrel (symrtp, sroot.objects.fixnum_blockp) -> fixnum_block.count; n_flonums = addrel (symrtp, sroot.objects.flonum_blockp) -> flonum_block.count; n_strings = addrel (symrtp, sroot.objects.string_blockp) -> string_block.count; n_bignums = addrel (symrtp, sroot.objects.bignum_blockp) -> bignum_block.count; n_atsyms = addrel (symrtp, sroot.objects.atsym_blockp) -> atsym_block.count; n_conses = addrel (symrtp, sroot.objects.cons_blockp) -> cons_block.count; blockp = addrel (symrtp, sroot.objects.atsym_blockp); do quotx = 1 to n_atsyms; tempp = addrel (symrtp, blockp -> atsym_block.atsym_offset (quotx)); if tempp -> string_chars.chars = "quote" then do; quotx = quotx + n_fixnums + n_flonums + n_strings + n_bignums; go to got_quotx; end; end; quotx = -1; got_quotx: actionp = addrel (symrtp, sroot.action_blockp); action_count = actionp -> action_block.count; if segtop ^= 0 then call ioa_ ("^a at offset ^o in segment", ent, segtop); call ioa_ ("^d action^[s^] defined:^/", action_count, action_count ^= 1); do actionx = 1 to action_count; action_type = actionp -> action_block.actions (actionx).action_code; if action_type = 0 then do; call ioa_ ("^3d EVAL: ^a", actionx, get_prinrep ((actionp -> action_block.actions (actionx).operand))); end; else do; call ioa_ ("^3d ^[ SUBR^;LSUBR^;FSUBR^]: ^a^30t^[^d arg^[s^] ^;^s^s^]@^o^[ (^o in seg)^]", actionx, action_type, get_prinrep ((actionp -> action_block.actions (actionx).operand)), action_type = 1, fixed (entryp -> entry_block.entry_info.nargs (subrx), 18), fixed (entryp -> entry_block.entry_info.nargs (subrx), 18) ^= 1, fixed (entryp -> entry_block.entry_info.entrypoint (subrx), 18), (segtop ^=0), fixed (entryp -> entry_block.entry_info.entrypoint (subrx), 18) + segtop); subrx = subrx + 1; end; end; constp = addrel (symrtp, sroot.const_blockp); if doing_subr_links then do; linkp = addrel (symrtp, sroot.links_blockp); if linkp -> links_block.count = 0 then call ioa_ ("^/No subr links."); else do; call ioa_ ("^/^d subr link^[s^]:^/", linkp -> links_block.count, linkp -> links_block.count ^= 1); do linkx = 1 to linkp -> links_block.count; unspec (link_info) = linkp -> links_block.link_info (linkx); if link_info.constant then call ioa_ ("lp|^o^8t^a^[ ^^SNAP^]^[^30t(fsubr)^]^[^30t(lsubr)^]^[^30t^d arg^[s^]^]", 2 * (linkx + constp -> const_block.count) - 1, get_prinrep ((constp -> const_block.constants ((link_info.fcn_offset+1)/2))), ^link_info.snap, link_info.fsubr, (link_info.nargs = 511), ^(link_info.fsubr|(link_info.nargs = 511)), link_info.nargs, link_info.nargs ^= 1); else call ioa_ ("lp|^o^8tap|^o ^[ ^^SNAP^]^[^30t(fsubr)^]^[^30t(lsubr)^]^[^30t^d arg^[s^]^]", 2 * (linkx + constp -> const_block.count) - 1, link_info.fcn_offset, ^link_info.snap, link_info.fsubr, (link_info.nargs = 511), ^(link_info.fsubr|(link_info.nargs = 511)), link_info.nargs, link_info.nargs ^= 1); end; end; end; if doing_array_links then do; arrayp = addrel (symrtp, sroot.array_links_blockp); if arrayp -> array_links_block.count = 0 then call ioa_ ("^/No array links.^/"); else do; call ioa_ ("^/^d array link^[s^]:^/", arrayp -> array_links_block.count, arrayp -> array_links_block.count ^= 1); do arrayx = 1 to arrayp -> array_links_block.count; unspec (array_info) = arrayp -> array_links_block.array_link.control_word (arrayx); call ioa_ ("lp|^o^8t^a^30t^d dim^[s^; ^] ^[Lisp objects^;nongc^;fixnum^;flonum^]", 2 * (addrel (symrtp, sroot.const_blockp) -> const_block.count + addrel (symrtp, sroot.links_blockp) -> links_block.count) -1 + 4 * arrayx, get_prinrep ((constp -> const_block.constants((array_info.sym_offset + 1)/2))), array_info.ndims, array_info.ndims ^= 1, array_info.type + 1); end; end; end; if doing_constants then do; if constp -> const_block.count = 0 then call ioa_ ("^/No subr-block constants.^/"); else call ioa_ ("^/^d subr-block constant^[s^]:^/", constp -> const_block.count, constp -> const_block.count ^= 1); do constx = 1 to constp -> const_block.count; unalconst = constp -> const_block.constants (constx); unspec (constant_index_format) = unspec (unalconst); call ioa_ ("lp|^o^8t^[LOAD TIME: ^]^a", 2 * constx - 1, constant_index_format.load_time, get_prinrep ((constant_index_format.constant_x))); end; end; term: call hcs_$terminate_noname (segp, (0)); get_prinrep: proc (a_x) returns (char (*)); dcl x fixed bin; dcl a_x fixed bin; dcl fvar char (40) varying; dcl ioa_$rsnnl entry options (variable); dcl requote_string_ entry (char (*)) returns (char (*)); dcl (car, cdr) fixed bin; dcl zlflag bit (1); dcl ncons fixed bin; dcl cv_bin_$oct entry (fixed bin) returns (char (12) aligned); zlflag = "1"b; go to join; get_prinrep_cdr: entry (a_x) returns (char (*)); x = a_x; if x <= n_fixnums + n_flonums + n_strings + n_bignums + n_atsyms then do; return (" . " || get_prinrep (x) || ")"); end; zlflag = "0"b; join: x = a_x; if x = 0 then return ("nil"); if x <= n_fixnums then do; blockp = addrel (symrtp, sroot.objects.fixnum_blockp); return (ltrim (cv_bin_$oct ((blockp -> fixnum_block.fixnums (x))))); end; x = x - n_fixnums; if x <= n_flonums then do; blockp = addrel (symrtp, sroot.objects.flonum_blockp); call ioa_$rsnnl ("^f", fvar, (0), blockp -> flonum_block.flonums (x)); return (fvar); end; x = x - n_flonums; if x <= n_strings then do; blockp = addrel (symrtp, sroot.objects.string_blockp); tempp = addrel (symrtp, blockp -> string_block.string_offset(x)); return (requote_string_ (tempp -> string_chars.chars)); end; x = x - n_strings; if x <= n_bignums then do; blockp = addrel (symrtp, sroot.objects.bignum_blockp); bigp = addrel (symrtp, blockp -> bignum_block.bignum_offsets (x)); return (bigna_representer ()); end; x = x - n_bignums; if x <= n_atsyms then do; blockp = addrel (symrtp, sroot.objects.atsym_blockp); tempp = addrel (symrtp, blockp -> atsym_block.atsym_offset (x)); if search (tempp -> string_chars.chars, BAD_CHARS) ^= 0 then return (hairy_atom (tempp -> string_chars.chars)); else return (tempp -> string_chars.chars); hairy_atom: proc (s) returns (char (*)); dcl s char (*), (sl, cx) fixed bin (24); sl = length (s); if sl = 0 then return (""); cx = search (s, BAD_CHARS); if cx = 0 then return (s); if cx = 1 & sl = 1 then return ("/" || s); if cx = 1 then return ("/" || substr (s, 1, 1) || hairy_atom (substr (s, 2))); if cx = sl then return (substr (s, 1, cx - 1) || "/" || substr (s, sl, 1)); else return (substr (s, 1, cx -1) || "/" || substr (s, cx, 1) || hairy_atom (substr (s, cx + 1))); end; end; x = x - n_atsyms; blockp = addrel (symrtp, sroot.objects.cons_blockp); car = blockp -> cons_block.conses (x).car; cdr = blockp -> cons_block.conses (x).cdr; if car = quotx then do; ncons = cdr - n_fixnums - n_flonums - n_bignums - n_strings - n_atsyms; if ncons > 0 then if blockp -> cons_block.conses (ncons).cdr = 0 then return ("'" || get_prinrep ((blockp -> cons_block.conses (ncons).car))); end; if zlflag then if cdr = 0 then return ("(" || get_prinrep (car) || ")"); else return ("(" || get_prinrep (car) || get_prinrep_cdr (cdr)); else if cdr = 0 then return (" " || get_prinrep (car) || ")"); else return (" " || get_prinrep (car) || get_prinrep_cdr (cdr)); bigna_representer: proc () returns (char (*)); dcl (octwds, decwds) (0:bignum.prec-1) fixed bin (35); dcl (octdigs, decdigs) char (12*bignum.prec + 5); dcl (octrem, decrem) fixed bin (35); dcl DIGITS char (10) init ("0123456789") static options (constant); dcl (octx, decx) fixed bin (21); dcl (octz, decz) bit (1) aligned; dcl wordx fixed bin (18); octx = length (octdigs); decx = length (decdigs); do wordx = 1 to bignum.prec; octwds (bignum.prec - wordx), decwds (bignum.prec - wordx) = bignum.words (wordx); end; decz, octz = "0"b; do while (^decz | ^octz); if ^octz then do; call divider (octz, octwds, octrem, 8); substr (octdigs, octx, 1) = substr (DIGITS, octrem + 1, 1); octx = octx - 1; end; if ^decz then do; call divider (decz, decwds, decrem, 10); substr (decdigs, decx, 1) = substr (DIGITS, decrem + 1, 1); decx = decx - 1; end; end; if bignum.sign then substr (decdigs, decx, 1), substr (octdigs, octx, 1) = "-"; else do; decx = decx + 1; octx = octx + 1; end; if index (substr (decdigs, decx), copy ("0", (length (decdigs) - decx)/3)) ^= 0 | index (substr (decdigs, decx), copy ("9", (length (decdigs) - decx)/3)) ^= 0 then return (substr (decdigs, decx) || "."); else return (substr (octdigs, octx)); divider: proc (done, words, rem, base); dcl done bit (1) aligned; dcl buf fixed bin (71); dcl x fixed bin; dcl words (0:*) fixed bin (35); dcl rem fixed bin (35); dcl saw_nzq bit (1); dcl base fixed bin; saw_nzq = "0"b; rem = 0; do x = 0 to hbound (words, 1); buf = fixed (bit (rem, 35) || bit (words (x), 35), 70); words (x) = divide (buf, base, 71, 0); rem = mod (buf, base); if words (x) ^= 0 then saw_nzq = "1"b; end; if ^saw_nzq then done = "1"b; end divider; end bigna_representer; end get_prinrep; end;  lisp_backquote_.lisp 07/06/83 0938.4r w 06/29/83 1542.9 74304 ;;; ************************************************************** ;;; * * ;;; * Copyright, (C) Massachusetts Institute of Technology, 1982 * ;;; * * ;;; ************************************************************** ;; -*- Lisp -*- ;;;BACKQUOTE: ;;; The flags passed back by BACKQUOTIFY can be interpreted as follows: ;;; ;;; |`,|: [a] => a ;;; NIL: [a] => a ;the NIL flag is used only when a is NIL ;;; T: [a] => a ;the T flag is used when a is self-evaluating ;;; QUOTE: [a] => (QUOTE a) ;;; APPEND: [a] => (APPEND . a) ;;; NCONC: [a] => (NCONC . a) ;;; LIST: [a] => (LIST . a) ;;; LIST*: [a] => (LIST* . a) ;;; ;;; The flags are combined according to the following set of rules: ;;; ([a] means that a should be converted according to the previous table) ;;; ;;; \ car || otherwise | QUOTE or | |`,@| | |`,.| | ;;; cdr \ || | T or NIL | | | ;;;==================================================================================== ;;; |`,| || LIST* ([a] [d]) | LIST* ([a] [d]) | APPEND (a [d]) | NCONC (a [d]) | ;;; NIL || LIST ([a]) | QUOTE (a) | a | a | ;;; QUOTE or T || LIST* ([a] [d]) | QUOTE (a . d) | APPEND (a [d]) | NCONC (a [d]) | ;;; APPEND || LIST* ([a] [d]) | LIST* ([a] [d]) | APPEND (a . d) | NCONC (a [d]) | ;;; NCONC || LIST* ([a] [d]) | LIST* ([a] [d]) | APPEND (a [d]) | NCONC (a . d) | ;;; LIST || LIST ([a] . d) | LIST ([a] . d) | APPEND (a [d]) | NCONC (a [d]) | ;;; LIST* || LIST* ([a] . d) | LIST* ([a] . d) | APPEND (a [d]) | NCONC (a [d]) | ;;; ;;; involves starting over again pretending you had read ".,a)" instead of ",@a)" (setsyntax '/` 'macro 'xr-backquote-macro) (setsyntax '/, 'macro 'xr-comma-macro) (declare (special **backquote-flag** **backquote-count** **backquote-/,-flag** **backquote-/,/@-flag** **backquote-/,/.-flag**)) (setq **backquote-flag**) (setq **backquote-count** 0) (setq **backquote-/,-flag** (copysymbol '|`,| nil)) (setq **backquote-/,/@-flag** (copysymbol '|`,@| nil)) (setq **backquote-/,/.-flag** (copysymbol '|`,.| nil)) (defun xr-backquote-macro () ((lambda (**backquote-count** **backquote-flag** thing) (setq thing (backquotify (read))) (cond ((eq **backquote-flag** **backquote-/,/@-flag**) (error " "",@"" right after a ""`"" : " thing 'fail-act)) ((eq **backquote-flag** **backquote-/,/.-flag**) (error " "",."" right after a ""`"" : " thing 'fail-act)) (t (backquotify-1 **backquote-flag** thing)))) (1+ **backquote-count**) nil nil)) (defun xr-comma-macro () (or (> **backquote-count** 0) (error "Comma not inside a backquote. " nil 'fail-act)) ((lambda (c **backquote-count**) (cond ((= c 100) ;#/@ (tyi) (cons **backquote-/,/@-flag** (read))) ((= c 56) ;#/. (tyi) (cons **backquote-/,/.-flag** (read))) (t (cons **backquote-/,-flag** (read))))) (tyipeek) (1- **backquote-count**))) (defun backquotify (code) (prog (aflag a dflag d) (cond ((atom code) (cond ((null code) (setq **backquote-flag** nil) (return nil)) ((or (numberp code) (eq code t)) (setq **backquote-flag** t) (return code)) (t (setq **backquote-flag** 'quote) (return code)))) ((eq (car code) **backquote-/,-flag**) (setq code (cdr code)) (go comma)) ((eq (car code) **backquote-/,/@-flag**) (setq **backquote-flag** **backquote-/,/@-flag**) (return (cdr code))) ((eq (car code) **backquote-/,/.-flag**) (setq **backquote-flag** **backquote-/,/.-flag**) (return (cdr code)))) (setq a (backquotify (car code))) (setq aflag **backquote-flag**) (setq d (backquotify (cdr code))) (setq dflag **backquote-flag**) (and (eq dflag **backquote-/,/@-flag**) (error " "",@"" after a ""."" : " code 'fail-act)) (and (eq dflag **backquote-/,/.-flag**) (error " "",."" after a ""."" : " code 'fail-act)) (cond ((eq aflag **backquote-/,/@-flag**) (cond ((null dflag) (setq code a) (go comma))) (setq **backquote-flag** 'append) (return (cond ((eq dflag 'append) (cons a d)) (t (list a (backquotify-1 dflag d)))))) ((eq aflag **backquote-/,/.-flag**) (cond ((null dflag) (setq code a) (go comma))) (setq **backquote-flag** 'nconc) (return (cond ((eq dflag 'nconc) (cons a d)) (t (list a (backquotify-1 dflag d)))))) ((null dflag) (cond ((memq aflag '(quote t nil)) (setq **backquote-flag** 'quote) (return (list a))) (t (setq **backquote-flag** 'list) (return (list (backquotify-1 aflag a)))))) ((memq dflag '(quote t)) (cond ((memq aflag '(quote t nil)) (setq **backquote-flag** 'quote) (return (cons a d))) (t (setq **backquote-flag** 'list*) (return (list (backquotify-1 aflag a) (backquotify-1 dflag d))))))) (setq a (backquotify-1 aflag a)) (and (memq dflag '(list list*)) (setq **backquote-flag** dflag) (return (cons a d))) (setq **backquote-flag** 'list*) (return (list a (backquotify-1 dflag d))) comma (cond ((atom code) (cond ((null code) (setq **backquote-flag** nil) (return nil)) ((or (numberp code) (eq code 't)) (setq **backquote-flag** t) (return code)) (t (setq **backquote-flag** **backquote-/,-flag**) (return code)))) ((eq (car code) 'quote) (setq **backquote-flag** 'quote) (return (cadr code))) ((memq (car code) '(append list list* nconc)) (setq **backquote-flag** (car code)) (return (cdr code))) ((eq (car code) 'cons) (setq **backquote-flag** 'list*) (return (cdr code))) (t (setq **backquote-flag** **backquote-/,-flag**) (return code))))) (defun backquotify-1 (flag thing) (cond ((or (eq flag **backquote-/,-flag**) (memq flag '(t nil))) thing) ((eq flag 'quote) (list 'quote thing)) ((eq flag 'list*) (cond ((null (cddr thing)) (cons 'cons thing)) (t (cons 'list* thing)))) (t (cons flag thing)))) (sstatus feature backquote)  lisp_defmacro_.lisp 07/06/83 0938.4r w 06/29/83 1542.9 50211 ;;; ************************************************************** ;;; * * ;;; * Copyright, (C) Massachusetts Institute of Technology, 1982 * ;;; * * ;;; ************************************************************** ;; -*- Mode: Lisp; Lowercase: True -*- ;; Written: January 1980 by Alan Bawden ;; Modified: March 1981 by Carl Hoffman ;; Observe compiler "macros" flag. Don't output an argument count check when ;; the lambda list is (&optional ... &rest ...) or (&rest ...). ;; Modified: March 1982 by Alan Bawden ;; Now includes a macro macro. That is, (macro foo (x) ...) is like ;; the good old (defun foo macro (x) ...). ;; Modified: October 1982 by Carl Hoffman for installation in bound_lisp_library_ (%include backquote) (%include destructuring_let) (declare (macros t)) (declare (special macros)) (declare (*expr let-macro-flush-declares let-macro-cons-declares)) ;; Note: The "let" package must also be loaded at run time since defmacro ;; expands into "let" forms. defmacro.incl.lisp does this. (declare (special *rest* *normal* *optional* *body*)) (defun grok-&keyword-list (pattern body) (prog (pat x) (setq pat pattern) (setq *body* body) norm (cond ((null pat) (return t)) ((atom pat) (setq *rest* pat) (return t))) (setq x (car pat)) (cond ((eq x '&optional) (go opt)) ((memq x '(&rest &body)) (go rst)) ((eq x '&aux) (go ax))) (setq *normal* (cons x *normal*) pat (cdr pat)) (go norm) opt (cond ((null (setq pat (cdr pat))) (return t)) ((atom pat) (setq *rest* pat) (return t))) (setq x (car pat)) (cond ((eq x '&optional) (go barf)) ((memq x '(&rest &body)) (go rst)) ((eq x '&aux) (go ax))) (cond ((atom x) (setq *optional* (cons (list x nil) *optional*))) (t (setq *optional* (cons x *optional*)))) (go opt) rst (or (and (not (null (setq pat (cdr pat)))) (not (atom pat)) (atom (setq x (car pat)))) (go barf)) (setq *rest* x) (or (setq pat (cdr pat)) (return t)) (and (or (atom pat) (not (eq (car pat) '&aux))) (go barf)) ax (setq *body* `((let* ,(cdr pat) . ,*body*))) (return t) barf (error "Bad &keyword argument list: " pattern 'fail-act))) (defprop defmacro defmacro/ macro macro) (defun defmacro/ macro (x) (displace x (let (((nil name pattern . body) x) (var (gensym)) *normal* *optional* *rest* *body* nname check-args guts tail) ;; make_atom returns an interned result. (setq nname (make_atom (catenate name " macro"))) (grok-&keyword-list pattern (let-macro-flush-declares body)) (setq check-args (length *normal*)) ;; nreconc is broken. This uses esoteric features of nconc: ;; (nconc '(a b c) 'd) --> (a b c . d) ;; (nconc nil 'x) -> x (setq *normal* (nconc (nreverse *normal*) (cond ((null *optional*) *rest*) (t (setq tail (gensym)))))) (setq check-args (let ((cnd (cond ((null *rest*) (cond ((null tail) `(= (length ,var) ,(1+ check-args))) (t `(and (> (length ,var) ,check-args) (< (length ,var) ,(+ 2 check-args (length *optional*))))))) ;; If we have a rest var, then there is no upper bound. ;; If *normal* is atomic, then there is no lower bound. ((and (atom *normal*) *rest*) nil) (t `(> (length ,var) ,check-args))))) (and cnd `((or ,cnd (error "Wrong number of args in macro form: " ,var 'fail-act)))))) (setq guts `((,var) .,(let-macro-cons-declares body `((comment args = ,pattern) ,@check-args (displace ,var (let ((,*normal* (cdr ,var))) . ,(cond (tail (do ((o *optional* (cdr o)) (ps nil (cond ((null (cddar o)) ps) (t (cons (caddar o) ps)))) (b (cond (*rest* `((let ((,*rest* (cdr ,tail))) . ,*body*))) (t *body*)) `((let ((,(caar o) (cond (,(cond ((null (cdr o)) tail) (t `(setq ,tail (cdr ,tail)))) ,@(cond ((null (cddar o)) nil) (t `((setq ,(caddar o) t)))) (car ,tail)) (t ,(cadar o))))) . ,b)))) ((null o) (cond ((null ps) b) (t `((let ,ps . ,b))))))) (t *body*)))))))) `(eval-when ,(cond ((and (boundp 'macros) macros) '(eval load compile)) (t '(eval compile))) (defprop ,name ,nname macro) (defun ,nname . ,guts))))) ;;;Probably defmacro should use this, but lets not toy with success. (defprop macro macro/ macro macro) (defun macro/ macro (x) (displace x (let (;; make_atom returns an interned result. (nname (make_atom (catenate (cadr x) " macro")))) `(eval-when ,(cond ((and (boundp 'macros) macros) `(eval load compile)) (t `(eval compile))) (defprop ,(cadr x) ,nname macro) (defun ,nname . ,(cddr x)))))) (sstatus feature defmacro)  lisp_defstruct_.lisp 07/06/83 0938.4r w 06/29/83 1542.9 511749 ;;; ************************************************************** ;;; * * ;;; * Copyright, (C) Massachusetts Institute of Technology, 1982 * ;;; * * ;;; ************************************************************** ;;; -*- Mode:Lisp; Package:SI; Lowercase:True -*- ;;; ** (c) Copyright 1980 Massachusetts Institute of Technology ** ;;; ** (c) Copyright 1981 Massachusetts Institute of Technology ** ;The master copy of this file is in MC:ALAN;NSTRUCT > ;The current PDP10 MacLisp copy is in MC:ALAN;STRUCT > ;The current Lisp machine copy is in AI:LISPM2;STRUCT > ;The current Multics MacLisp copy is in >udd>Mathlab>Bawden>defstruct.lisp ; on MIT-Multics ;The current VMS-NIL copy is in [NIL.SRC.SPEC]STRUCT.LSP on HTJR ;***** READ THIS PLEASE! ***** ;If you are thinking of munging anything in this file you might want to ;consider finding me (ALAN) and asking me to mung it for you. There is more ;than one copy of this file in the world (it runs in PDP10 and Multics MacLisp, ;NIL, Franz, PSL and on LispMachines) and whatever amazing features you are ;considering adding might be usefull to those people as well. If you still ;cannot contain yourself long enough to find me, AT LEAST send me a piece of ;mail describing what you did and why. Thanks for reading this flame. ; Alan Bawden (ALAN@MC) (eval-when (eval compile) (sstatus nofeature MacLisp-10)) (%include sharpsign) (%include defmacro) (%include other_other) (%include defstruct) (declare (genprefix defstruct-internal-) (*expr dpb ldb) (macros t)) (eval-when (eval compile) (setsyntax #/: (ascii #\space) nil)) (eval-when (eval compile load) #+MacLisp (defun defstruct-retry-keyword (x) (let ((l (exploden x))) (if (= (car l) #/:) (implode (cdr l)) x))) #+LispM (defun defstruct-retry-keyword (x) (intern (get-pname x) si:pkg-user-package)) #+NIL (defmacro defstruct-retry-keyword (x) `(to-keyword ,x)) );End of eval-when (eval compile load) ;;; Eval this before attempting incremental compilation (eval-when (eval compile) #+MacLisp-10 (defmacro append-symbols args (do ((l (reverse args) (cdr l)) (x) (a nil (if (or (atom x) (not (eq (car x) 'quote))) (if (null a) `(exploden ,x) `(nconc (exploden ,x) ,a)) (let ((l (exploden (cadr x)))) (cond ((null a) `',l) ((= 1 (length l)) `(cons ,(car l) ,a)) (t `(append ',l ,a))))))) ((null l) `(implode ,a)) (setq x (car l)))) #+Multics (defmacro append-symbols args `(make_atom (catenate ,@args))) #+LispM (defmacro append-symbols args `(intern (string-append ,@args))) #+NIL (defmacro append-symbols args `(symbolconc ,@args)) (defmacro defstruct-putprop (sym val ind) `(push `(defprop ,,sym ,,val ,,ind) returns)) #+Multics ;;;lcp gobbles (defprop ... macro) at compile time, so we have to use ;;;putprop to be certain macro definitions make it into the object: (defmacro defstruct-put-macro (sym fcn) `(push `(putprop ',,sym ',,fcn 'macro) returns)) #+MacLisp-10 (defmacro defstruct-put-macro (sym fcn) `(push `(defprop ,,sym ,,fcn macro) returns)) #+LispM (defmacro defstruct-put-macro (sym fcn) (setq fcn (if (and (not (atom fcn)) (eq (car fcn) 'quote)) `'(macro . ,(cadr fcn)) `(cons 'macro ,fcn))) `(push `(fdefine ',,sym ',,fcn t) returns)) #+NIL (defmacro defstruct-put-macro (sym fcn) `(push `(add-macro-definition ',,sym ',,fcn) returns)) (defmacro make-empty () `'%%defstruct-empty%%) (defmacro emptyp (x) `(eq ,x '%%defstruct-empty%%)) ;;;Here we must deal with the fact that error reporting works ;;;differently everywhere! #+MacLisp-10 ;;;first arg is ALWAYS a symbol or a quoted symbol: (defmacro defstruct-error (message &rest args) (let* ((chars (nconc (exploden (if (atom message) message (cadr message))) '(#/.))) ;"Bad frob" => "Bad frob." (new-message (maknam (if (null args) chars (let ((c (car chars))) ;"Bad frob." => "-- bad frob." (or (< c #/A) (> c #/Z) (rplaca chars (+ c #o40))) (append '(#/- #/- #\space) chars)))))) `(error ',new-message ,@(cond ((null args) `()) ((null (cdr args)) `(,(car args))) (t `((list ,@args))))))) #+Multics ;;;first arg is ALWAYS a string: (defmacro defstruct-error (message &rest args) `(error ,(catenate "defstruct: " message (if (null args) "." ": ")) ,@(cond ((null args) `()) ((null (cdr args)) `(,(car args))) (t `((list ,@args)))))) #+(or LispM NIL) ;;;first arg is ALWAYS a string: (defmacro defstruct-error (message &rest args) (do ((l args (cdr l)) (fs "") (na nil)) ((null l) `(ferror nil ,(string-append message (if (null args) "." (string-append ":" fs))) ,.(nreverse na))) (cond ((and (not (atom (car l))) (eq (caar l) 'quote) (symbolp (cadar l))) (setq fs (string-append fs " " (string-downcase (cadar l))))) (t (push (car l) na) (setq fs (string-append fs " ~S")))))) );End of eval-when (eval compile) ;;;If you mung the the ordering af any of the slots in this structure, ;;;be sure to change the version slot and the definition of the function ;;;get-defstruct-description. Munging the defstruct-slot-description ;;;structure should also cause you to change the version "number" in this ;;;manner. (defstruct (defstruct-description (:type :list) (:default-pointer description) (:conc-name defstruct-description-) (:alterant ()) #+stingy-defstruct (:eval-when (eval compile))) (version 'one) type dummy ;used to be the displace function slot-alist named-p constructors (default-pointer nil) (but-first nil) size (property-alist nil) ;;end of "expand-time" slots name include (initial-offset 0) (eval-when '(eval compile load)) alterant (conc-name nil) (callable-accessors #-(or LispM NIL) nil #+(or LispM NIL) t) (size-macro nil) (size-symbol nil) (predicate nil) (copier nil) (print nil) ) (defun get-defstruct-description (name) (let ((description (get name 'defstruct-description))) (cond ((null description) (defstruct-error "A structure with this name has not been defined" name)) ((not (eq (defstruct-description-version) 'one)) (defstruct-error "The internal description of this structure is incompatible with the currently loaded version of defstruct, you will need to recompile its definition" name)) (t description)))) ;;;See note above defstruct-description structure before munging this one. (defstruct (defstruct-slot-description (:type :list) (:default-pointer slot-description) (:conc-name defstruct-slot-description-) (:alterant ()) #+stingy-defstruct (:eval-when (eval compile))) number (ppss nil) init-code (type 'notype) (property-alist nil) ref-macro-name ) ;;;Perhaps this structure wants a version slot too? (defstruct (defstruct-type-description (:type :list) (:default-pointer type-description) (:conc-name defstruct-type-description-) (:alterant ()) #+stingy-defstruct (:eval-when (eval compile))) ref-expander ref-no-args cons-expander cons-flavor (cons-keywords nil) (named-type nil) (overhead 0) (defstruct-expander nil) (predicate nil) (copier nil) ) ;; (DEFSTRUCT ( . ) . ) or (DEFSTRUCT . ) ;; ;; is of the form (