rcref.red 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  1. module rcref; % Cross reference program.
  2. % Author: Martin L. Griss, with modifications by Anthony C. Hearn.
  3. % Requires REDIO and SORT support.
  4. create!-package('(rcref redio),'(util));
  5. fluid '(!*backtrace !*cref !*defn !*mode !*nocrefpri calls!* curfun!*
  6. dfprint!* globs!* locls!* toplv!*);
  7. global '(undefg!* gseen!* btime!* expand!* haveargs!* notuse!* nolist!*
  8. dclglb!* entpts!* undefns!* seen!* tseen!* xseen!* op!*!* cloc!*
  9. pfiles!* curlin!* pretitl!* !*creftime !*saveprops maxarg!*
  10. !*crefsummary !*comp !*raise !*rlisp !*globals !*algebraics);
  11. switch cref;
  12. !*algebraics:='t; % Default is normal parse of algebraic.
  13. !*globals:='t; % Do analyze globals.
  14. % !*rlisp:=nil; % REDUCE as default.
  15. maxarg!*:=15; % Maximum args in Standard Lisp.
  16. deflist('((anlfn procstat) (crflapo procstat)),'stat);
  17. flag('(anlfn crflapo),'compile);
  18. comment EXPAND flag on these forces expansion of MACROS;
  19. expand!* := '(for foreach repeat while);
  20. nolist!* := nconc(for each j in slfns!* collect car j,nolist!*);
  21. nolist!* := append('(and cond endmodule lambda list max min module or
  22. plus prog prog2 progn putc switch times),
  23. nolist!*);
  24. flag ('(plus times and or lambda progn max min cond prog case list),
  25. 'naryargs);
  26. dclglb!*:='(!*comp emsg!* !*raise);
  27. if not getd 'begin then
  28. flag('(rds deflist flag fluid global remprop remflag unfluid
  29. setq crefoff),'eval);
  30. symbolic procedure crefon;
  31. begin btime!*:=time();
  32. dfprint!* := 'refprint;
  33. !*defn := t;
  34. if not !*algebraics then put('algebraic,'newnam,'symbolic);
  35. flag(nolist!*,'nolist);
  36. flag(expand!*,'expand);
  37. flag(dclglb!*,'dclglb);
  38. % Global lists.
  39. entpts!*:=nil; % Entry points to package.
  40. undefns!*:=nil; % Functions undefined in package.
  41. seen!*:=nil; % List of all encountered functions.
  42. tseen!*:=nil; % List of all encountered types not flagged
  43. % FUNCTION.
  44. gseen!*:=nil; % All encountered globals.
  45. pfiles!*:=nil; % Processed files.
  46. undefg!*:=nil; % Undeclared globals encountered.
  47. curlin!*:=nil; % Position in file(s) of current command.
  48. pretitl!*:=nil; % T if error or questionables found.
  49. % Usages in specific function under analysis.
  50. globs!*:=nil; % Globals refered to in this.
  51. calls!*:=nil; % Functions called by this.
  52. locls!*:=nil; % Defined local variables in this.
  53. toplv!*:=t; % NIL if inside function body.
  54. curfun!*:=nil; % Current function beeing analyzed.
  55. op!*!*:=nil; % Current op. in LAP code.
  56. if not !*nocrefpri
  57. then setpage(" Errors or questionables",nil);
  58. if not getd 'begin then crefonlsp() % In Lisp.
  59. end;
  60. symbolic procedure undefdchk fn;
  61. if not flagp(fn,'defd) then undefns!* := fn . undefns!*;
  62. symbolic procedure princng u;
  63. princn getes u;
  64. symbolic procedure crefoff;
  65. % Main call, sets up, alphabetizes and prints.
  66. begin scalar tim,x;
  67. crefoff1();
  68. tim:=time()-btime!*;
  69. setpage(" Summary",nil);
  70. newpage();
  71. pfiles!*:=punused("Crossreference listing for files:",
  72. for each z in pfiles!* collect cdr z);
  73. entpts!*:=punused("Entry Points:",entpts!*);
  74. undefns!*:=punused("Undefined Functions:",undefns!*);
  75. undefg!*:=punused("Undeclared Global Variables:",undefg!*);
  76. gseen!*:=punused("Global variables:",gseen!*);
  77. seen!*:=punused("Functions:",seen!*);
  78. for each z in tseen!* do
  79. <<rplacd(z,punused(list(car z," procedures:"),cdr z));
  80. x:='!( . nconc(explode car z,list '!));
  81. for each fn in cdr z do
  82. <<fn:=getes fn; rplacd(fn,append(x,cdr fn));
  83. rplaca(fn,length cdr fn)>> >>;
  84. if !*crefsummary then goto xy;
  85. if !*globals and gseen!* then
  86. <<setpage(" Global Variable Usage",1);
  87. newpage();
  88. for each z in gseen!* do cref6 z>>;
  89. if seen!* then cref52(" Function Usage",seen!*);
  90. for each z in tseen!* do
  91. cref52(list(" ",car z," procedures"),cdr z);
  92. setpage(" Toplevel calls:",nil);
  93. x:=t;
  94. for each z in pfiles!* do
  95. if get(z,'calls) or get(z,'globs) then
  96. <<if x then <<newpage(); x:=nil>>;
  97. newline 0; newline 0; princng z;
  98. spaces!-to 15; underline2 (linelength(nil)-10);
  99. cref51(z,'calls,"Calls:");
  100. if !*globals then cref51(z,'globs,"Globals:")>>;
  101. xy: if !*saveprops then goto xx;
  102. rempropss(seen!*,'(gall calls globs calledby alsois sameas));
  103. remflagss(seen!*,'(seen cinthis defd));
  104. rempropss(gseen!*,'(usedby usedunby boundby setby));
  105. remflagss(gseen!*,'(dclglb gseen glb2rf glb2bd glb2st));
  106. for each z in tseen!* do remprop(car z,'funs);
  107. % for each z in haveargs!* do remprop(z,'number!-of!-args);
  108. haveargs!* := gseen!* := seen!* := tseen!* := nil;
  109. xx: newline 2;
  110. if not !*creftime then return;
  111. btime!*:=time()-btime!*;
  112. setpage(" Timing Information",nil);
  113. newpage(); newline 0;
  114. prtatm " Total Time="; prtnum btime!*;
  115. prtatm " (ms)";
  116. newline 0;
  117. prtatm " Analysis Time="; prtnum tim;
  118. newline 0;
  119. prtatm " Sorting Time="; prtnum (btime!*-tim);
  120. newline 0; newline 0
  121. end;
  122. symbolic procedure crefoff1;
  123. begin scalar x;
  124. dfprint!* := nil;
  125. !*defn := nil;
  126. if not !*algebraics
  127. then remprop('algebraic,'newnam); % Back to normal.
  128. for each fn in seen!* do
  129. <<if null get(fn,'calledby) then entpts!*:=fn . entpts!*;
  130. undefdchk fn>>;
  131. tseen!*:=for each z in idsort tseen!* collect
  132. <<remprop(z,'tseen);
  133. for each fn in (x:=get(z,'funs)) do
  134. <<undefdchk fn; remprop(fn,'rccnam)>>;
  135. z.x>>;
  136. for each z in gseen!* do
  137. if get(z,'usedunby) then undefg!*:=z . undefg!*;
  138. end;
  139. symbolic procedure punused(x,y);
  140. if y then
  141. <<newline 2; prtlst x; newline 0;
  142. lprint(y := idsort y,8); newline 0; y>>;
  143. symbolic procedure cref52(x,y);
  144. <<setpage(x,1); newpage(); for each z in y do cref5 z>>;
  145. symbolic procedure cref5 fn;
  146. % Print single entry.
  147. begin scalar x,y;
  148. newline 0; newline 0;
  149. prin1 fn; spaces!-to 15;
  150. y:=get(fn,'gall);
  151. if y then <<prin1 cdr y; x:=car y>>
  152. else prin2 "Undefined";
  153. spaces!-to 25;
  154. if flagp(fn,'naryargs) then prin2 " Nary Args "
  155. else if (y:=get(fn,'number!-of!-args)) then
  156. <<prin2 " "; prin2 y; prin2 " Args ">>;
  157. underline2 (linelength(nil)-10);
  158. if x then
  159. <<newline 15; prtatm "Line:"; spaces!-to 27;
  160. prtnum cddr x; prtatm '!/; prtnum cadr x;
  161. prtatm " in "; prtatm car x>>;
  162. cref51(fn,'calledby,"Called by:");
  163. cref51(fn,'calls,"Calls:");
  164. cref51(fn,'alsois,"Is also:");
  165. cref51(fn,'sameas,"Same as:");
  166. if !*globals then cref51(fn,'globs,"Globals:")
  167. end;
  168. symbolic procedure cref51(x,y,z);
  169. if (x:=get(x,y)) then <<newline 15; prtatm z; lprint(idsort x,27)>>;
  170. symbolic procedure cref6 glb;
  171. % Print single global usage entry.
  172. <<newline 0; prin1 glb; spaces!-to 15;
  173. notuse!*:=t;
  174. cref61(glb,'usedby,"Global in:");
  175. cref61(glb,'usedunby,"Undeclared:");
  176. cref61(glb,'boundby,"Bound in:");
  177. cref61(glb,'setby,"Set by:");
  178. if notuse!* then prtatm "*** Not Used ***">>;
  179. symbolic procedure cref61(x,y,z);
  180. if (x:=get(x,y)) then
  181. <<if not notuse!* then newline 15 else notuse!*:=nil;
  182. prtatm z; lprint(idsort x,27)>>;
  183. % Analyze bodies of LISP functions for functions called, and globals
  184. % used, undefined.
  185. smacro procedure flag1(u,v); flag(list u,v);
  186. smacro procedure remflag1(u,v); remflag(list u,v);
  187. smacro procedure isglob u;
  188. flagp(u,'dclglb);
  189. smacro procedure chkseen s;
  190. % Has this name been encountered already?
  191. if not flagp(s,'seen) then
  192. <<flag1(s,'seen); seen!*:=s . seen!*>>;
  193. smacro procedure globref u;
  194. if not flagp(u,'glb2rf)
  195. then <<flag1(u,'glb2rf); globs!*:=u . globs!*>>;
  196. smacro procedure anatom u;
  197. % Global seen before local..ie detect extended from this.
  198. if !*globals and u and not(u eq 't)
  199. and idp u and not assoc(u,locls!*)
  200. then globref u;
  201. smacro procedure chkgseen g;
  202. if not flagp(g,'gseen) then <<gseen!*:=g . gseen!*;
  203. flag1(g,'gseen)>>;
  204. symbolic procedure do!-global l;
  205. % Catch global defns.
  206. % Distinguish FLUID from GLOBAL later.
  207. if pairp(l:=qcrf car l) and !*globals and toplv!* then
  208. <<for each v in l do chkgseen v; flag(l,'dclglb)>>;
  209. put('global,'anlfn,'do!-global);
  210. put('fluid,'anlfn,'do!-global);
  211. symbolic anlfn procedure unfluid l;
  212. if pairp(l:=qcrf car l) and !*globals and toplv!* then
  213. <<for each v in l do chkgseen v; remflag(l,'dclglb)>>;
  214. symbolic procedure add2locs ll;
  215. begin scalar oldloc;
  216. if !*globals then for each gg in ll do
  217. <<oldloc:=assoc(gg,locls!*);
  218. if not null oldloc then <<
  219. qerline 0;
  220. prin2 "*** Variable ";
  221. prin1 gg;
  222. prin2 " nested declaration in ";
  223. princng curfun!*;
  224. newline 0;
  225. rplacd(oldloc,nil.oldloc)>>
  226. else locls!*:=(gg . list nil) . locls!*;
  227. if isglob(gg) or flagp(gg,'glb2rf) then globind gg;
  228. if flagp(gg,'seen) then
  229. <<qerline 0;
  230. prin2 "*** Function ";
  231. princng gg;
  232. prin2 " used as variable in ";
  233. princng curfun!*;
  234. newline 0>> >>
  235. end;
  236. symbolic procedure qerline u;
  237. if !*nocrefpri then nil
  238. else if pretitl!* then newline u
  239. else <<pretitl!*:=t; newpage()>>;
  240. symbolic procedure globind gg;
  241. <<flag1(gg,'glb2bd); globref gg>>;
  242. symbolic procedure remlocs lln;
  243. begin scalar oldloc;
  244. if !*globals then for each ll in lln do
  245. <<oldloc:=assoc(ll,locls!*);
  246. if null oldloc then
  247. if getd 'begin then rederr list(" Lvar confused",ll)
  248. else error(0,list(" Lvar confused",ll));
  249. if cddr oldloc then rplacd(oldloc,cddr oldloc)
  250. else locls!*:=efface1(oldloc,locls!*)>>
  251. end;
  252. symbolic procedure efface1(u,v);
  253. if null v then nil
  254. else if u eq car v then cdr v
  255. else rplacd(v,efface1(u,cdr v));
  256. symbolic procedure add2calls fn;
  257. % Update local CALLS!*.
  258. not flagp(fn,'cinthis) and
  259. <<if flagp(fn,'nolist) then xseen!* := fn . xseen!*
  260. else calls!* := fn . calls!*;
  261. flag1(fn,'cinthis)>>;
  262. symbolic procedure anform u;
  263. if atom u then anatom u else anform1 u;
  264. symbolic procedure anforml l;
  265. begin
  266. while not atom l do <<anform car l; l:=cdr l>>;
  267. if l then anatom l
  268. end;
  269. symbolic procedure anform1 u;
  270. begin scalar fn,x;
  271. fn:=car u; u:=cdr u;
  272. if not atom fn then return <<anform1 fn; anforml u>>;
  273. if not idp fn then return nil
  274. else if isglob fn then <<globref fn; return anforml u>>
  275. else if assoc(fn,locls!*) then return anforml u;
  276. add2calls fn;
  277. checkargcount(fn,length u);
  278. if flagp(fn,'noanl) then nil
  279. else if x:=get(fn,'anlfn) then apply1(x,u)
  280. else anforml u
  281. end;
  282. symbolic anlfn procedure lambda u;
  283. <<add2locs car u; anforml cdr u; remlocs car u>>;
  284. symbolic procedure anlsetq u;
  285. <<anforml u;
  286. if !*globals and flagp(u:=car u,'glb2rf) then flag1(u,'glb2st)>>;
  287. put('setq,'anlfn,'anlsetq);
  288. symbolic anlfn procedure cond u;
  289. for each x in u do anforml x;
  290. symbolic anlfn procedure prog u;
  291. <<add2locs car u;
  292. for each x in cdr u do
  293. if not atom x then anform1 x;
  294. remlocs car u>>;
  295. symbolic anlfn procedure function u;
  296. if pairp(u:=car u) then anform1 u
  297. else if isglob u then globref u
  298. else if null assoc(u,locls!*) then add2calls u;
  299. flag('(quote go),'noanl);
  300. symbolic anlfn procedure errorset u;
  301. begin scalar fn,x;
  302. anforml cdr u;
  303. if eqcar(u:=car u,'quote) then return ersanform cadr u
  304. else if not((eqcar(u,'cons) or (x:=eqcar(u,'list)))
  305. and quotp(fn:=cadr u))
  306. then return anform u;
  307. anforml cddr u;
  308. if pairp(fn:=cadr fn) then anform1 fn
  309. else if flagp(fn,'glb2rf) then nil
  310. else if isglob fn then globref fn
  311. else <<add2calls fn; if x then checkargcount(fn,length cddr u)>>
  312. end;
  313. symbolic procedure ersanform u;
  314. begin scalar locls!*;
  315. return anform u
  316. end;
  317. symbolic procedure anlmap u;
  318. <<anforml u;
  319. if quotp(u:=cadr u) and idp(u:=cadr u)
  320. and not isglob u and not assoc(u,locls!*)
  321. then checkargcount(u,1)>>;
  322. for each x in '(map mapc maplist mapcar mapcon mapcan) do
  323. put(x,'anlfn,'anlmap);
  324. symbolic anlfn procedure lispapply u;
  325. begin scalar fn;
  326. anforml cdr u;
  327. if quotp(fn:=cadr u) and idp(fn:=cadr fn) and eqcar(u:=caddr u,'list)
  328. then checkargcount(fn,length cdr u)
  329. end;
  330. symbolic anlfn procedure apply u;
  331. begin scalar fn;
  332. anforml cdr u;
  333. if quotp(fn:=cadr u) and idp(fn:=cadr fn) and eqcar(u:=caddr u,'list)
  334. then checkargcount(fn,length cdr u)
  335. end;
  336. symbolic procedure quotp u; eqcar(u,'quote) or eqcar(u,'function);
  337. put('cref ,'simpfg ,'((t (crefon)) (nil (crefoff))));
  338. symbolic procedure outref(s,varlis,body,type);
  339. begin scalar curfun!*,calls!*,globs!*,locls!*,toplv!*,a;
  340. a:=if varlis memq '(anp!!atom anp!!idb anp!!eq anp!!unknown)
  341. then nil
  342. else length varlis;
  343. s := outrdefun(s,type,if a then a else get(body,'number!-of!-args));
  344. if a then <<add2locs varlis; anform(body); remlocs varlis>>
  345. else if null body or not idp body then nil
  346. else if varlis eq 'anp!!eq
  347. then <<put(s,'sameas,list body); traput(body,'alsois,s)>>
  348. else add2calls body;
  349. outrefend s
  350. end;
  351. symbolic procedure traput(u,v,w);
  352. begin scalar a;
  353. if a:=get(u,v) then
  354. (if not(toplv!* or w memq a) then rplacd(a,w . cdr a))
  355. else put(u,v,list w)
  356. end;
  357. smacro procedure toput(u,v,w);
  358. if w then put(u,v,if toplv!* then union(w,get(u,v)) else w);
  359. symbolic procedure outrefend s;
  360. <<toput(s,'calls,calls!*);
  361. for each x in calls!* do
  362. <<remflag1(x,'cinthis);
  363. if not(x eq s) then <<chkseen x; traput(x,'calledby,s)>> >>;
  364. toput(s,'globs,globs!*);
  365. for each x in globs!* do
  366. <<traput(x,if isglob x then 'usedby
  367. else <<chkgseen x; 'usedunby>>,s);
  368. remflag1(x,'glb2rf);
  369. if flagp(x,'glb2bd)
  370. then <<remflag1(x,'glb2bd); traput(x,'boundby,s)>>;
  371. if flagp(x,'glb2st)
  372. then <<remflag1(x,'glb2st); traput(x,'setby,s)>> >> >>;
  373. symbolic procedure recref(s,type);
  374. <<qerline 2;
  375. prtatm "*** Redefinition to ";
  376. prin1 type;
  377. prtatm " procedure, of:";
  378. cref5 s;
  379. rempropss(list s,'(calls globs sameas));
  380. newline 2>>;
  381. symbolic procedure outrdefun(s,type,v);
  382. begin
  383. s:=qtypnm(s,type);
  384. if flagp(s,'defd) then recref(s,type)
  385. else flag1(s,'defd);
  386. if flagp(type,'function) and (isglob s or assoc(s,locls!*)) then
  387. <<qerline 0;
  388. prin2 "**** Variable ";
  389. princng s;
  390. prin2 " defined as function";
  391. newline 0>>;
  392. if v and not flagp(type,'naryarg) then defineargs(s,v)
  393. else if flagp(type,'naryarg) and not flagp(s,'naryargs)
  394. then flag1(s,'naryargs);
  395. put(s,'gall,curlin!* . type);
  396. globs!*:=nil;
  397. calls!*:=nil;
  398. return curfun!*:=s
  399. end;
  400. flag('(macro fexpr),'naryarg);
  401. symbolic procedure qtypnm(s,type);
  402. if flagp(type,'function) then <<chkseen s; s>>
  403. else begin scalar x,y,z;
  404. if (y:=get(type,'tseen)) and (x:=atsoc(s,cdr y))
  405. then return cdr x;
  406. if null y then
  407. <<y:=list ('!( . nconc(explode type,list '!)));
  408. put(type,'tseen,y); tseen!* := type . tseen!*>>;
  409. x := compress (z := explode s);
  410. rplacd(y,(s . x) . cdr y);
  411. y := append(car y,z);
  412. put(x,'rccnam,length y . y);
  413. traput(type,'funs,x);
  414. return x
  415. end;
  416. symbolic procedure defineargs(name,n);
  417. begin scalar calledwith,x;
  418. calledwith:=get(name,'number!-of!-args);
  419. if null calledwith then return hasarg(name,n);
  420. if n=calledwith then return nil;
  421. if x := get(name,'calledby) then instdof(name,n,calledwith,x);
  422. hasarg(name,n)
  423. end;
  424. symbolic procedure instdof(name,n,m,fnlst);
  425. <<qerline 0;
  426. prin2 "***** ";
  427. prin1 name;
  428. prin2 " called with ";
  429. prin2 m;
  430. prin2 " instead of ";
  431. prin2 n;
  432. prin2 " arguments in:";
  433. lprint(idsort fnlst,posn()+1);
  434. newline 0>>;
  435. symbolic procedure hasarg(name,n);
  436. <<haveargs!*:=name . haveargs!*;
  437. if n>maxarg!* then
  438. <<qerline 0;
  439. prin2 "**** "; prin1 name;
  440. prin2 " has "; prin2 n;
  441. prin2 " arguments";
  442. newline 0 >>;
  443. put(name,'number!-of!-args,n)>>;
  444. symbolic procedure checkargcount(name,n);
  445. begin scalar correctn;
  446. if flagp(name,'naryargs) then return nil;
  447. correctn:=get(name,'number!-of!-args);
  448. if null correctn then return hasarg(name,n);
  449. if not(correctn=n) then instdof(name,correctn,n,list curfun!*)
  450. end;
  451. symbolic procedure refprint u;
  452. begin scalar x,y;
  453. % x:=if cloc!* then filemk car cloc!* else "*ttyinput*";
  454. x:=if cloc!* then car cloc!* else "*TTYINPUT*";
  455. if (curfun!*:=assoc(x,pfiles!*)) then
  456. <<x:=car curfun!*; curfun!*:=cdr curfun!*>>
  457. else <<pfiles!*:=(x.(curfun!*:=gensym())).pfiles!*;
  458. y:=reversip cdr reversip cdr explode x;
  459. put(curfun!*,'rccnam,length y . y)>>;
  460. curlin!*:=if cloc!* and cdr cloc!* then x . cdr cloc!* else nil;
  461. calls!*:=globs!*:=locls!*:=nil;
  462. anform u;
  463. outrefend curfun!*
  464. end;
  465. symbolic procedure filemk u;
  466. % Convert a file specification from lisp format to a string.
  467. % This is essentially the inverse of MKFILE.
  468. begin scalar dev,name,flg,flg2;
  469. if null u then return nil
  470. else if atom u then name := explode2 u
  471. else for each x in u do
  472. if x eq 'dir!: then flg := t
  473. else if atom x then
  474. if flg then dev := '!< . nconc(explode2 x,list '!>)
  475. else if x eq 'dsk!: then dev:=nil
  476. else if !%devp x then dev := explode2 x
  477. else name := explode2 x
  478. else if atom cdr x then
  479. name := nconc(explode2 car x,'!. . explode2 cdr x)
  480. else <<flg2 := t;
  481. dev := '![ . nconc(explode2 car x,
  482. '!, . nconc(explode2 cadr x,list '!]))>>;
  483. u := if flg2 then nconc(name,dev)
  484. else nconc(dev,name);
  485. return compress('!" . nconc(u,'(!")))
  486. end;
  487. flag('(smacro nmacro),'cref);
  488. symbolic anlfn procedure put u;
  489. if toplv!* and qcputx cadr u then anputx u
  490. else anforml u;
  491. put('putc,'anlfn,get('put,'anlfn));
  492. symbolic procedure qcputx u;
  493. eqcar(u,'quote) and (flagp(cadr u,'cref) or flagp(cadr u,'compile));
  494. symbolic procedure anputx u;
  495. begin scalar nam,typ,body;
  496. nam:=qcrf car u;
  497. typ:=qcrf cadr u;
  498. u:=caddr u;
  499. if atom u then <<body:=qcrf u; u:='anp!!atom>>
  500. else if car u memq '(quote function) then
  501. if eqcar(u:=cadr u,'lambda) then <<body:=caddr u; u:=cadr u>>
  502. else if idp u then <<body:=u; u:='anp!!idb>>
  503. else return nil
  504. else if car u eq 'cdr and eqcar(cadr u,'getd) then
  505. <<body:=qcrf cadadr u; u:='anp!!eq>>
  506. else if car u eq 'get and qcputx caddr u then
  507. <<body:=qtypnm(qcrf cadr u,cadr caddr u); u:='anp!!eq>>
  508. else if car u eq 'mkcode then
  509. <<anform cadr u; u:=qcrf caddr u; body:=nil>>
  510. else <<body:=qcrf u; u:='anp!!unknown>>;
  511. outref(nam,u,body,typ)
  512. end;
  513. symbolic anlfn procedure putd u;
  514. if toplv!* then anputx u else anforml u;
  515. symbolic anlfn procedure de u;
  516. outdefr(u,'expr);
  517. symbolic anlfn procedure df u;
  518. outdefr(u,'fexpr);
  519. symbolic anlfn procedure dm u;
  520. outdefr(u,'macro);
  521. symbolic anlfn procedure dn u; % PSL function.
  522. outdefr(u,'macro);
  523. symbolic anlfn procedure ds u; % PSL function.
  524. outdefr(u,'smacro);
  525. symbolic procedure outdefr(u,type);
  526. outref(car u,cadr u,caddr u,type);
  527. symbolic procedure qcrf u;
  528. if null u or u eq t then u
  529. else if eqcar(u,'quote) then cadr u
  530. else <<anform u; compress explode '!?value!?!?>>;
  531. flag('(expr fexpr macro smacro nmacro),'function);
  532. endmodule;
  533. end;