rcref.red 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873
  1. module redio; % General Purpose I/O package, sorting and positioning.
  2. % Author: Martin L. Griss.
  3. % Modified by: Anthony C. Hearn.
  4. global '(!*formfeed lnnum!* maxln!* orig!* pgnum!* title!*);
  5. % This module is functionally equivalent to the PSL file PSL-CREFIO.RED.
  6. % FORMFEED (ON) controls ^L or spacer of ====;
  7. symbolic procedure initio();
  8. % Set-up common defaults;
  9. begin
  10. !*formfeed:=t;
  11. orig!*:=0;
  12. lnnum!*:=0;
  13. linelength(75);
  14. maxln!*:=55;
  15. title!*:=nil;
  16. pgnum!*:=1;
  17. end;
  18. symbolic procedure lposn();
  19. lnnum!*;
  20. initio();
  21. symbolic procedure setpgln(p,l);
  22. begin if p then maxln!*:=p;
  23. if l then linelength(l);
  24. end;
  25. % We use EXPLODE to produce a list of chars from atomname,
  26. % and TERPRI() to terminate a buffer..all else
  27. % done in package..spaces,tabs,etc. ;
  28. comment Character lists are (length . chars), for FITS;
  29. symbolic procedure getes u;
  30. % Returns for U , EE=(Length . List of char);
  31. begin scalar ee;
  32. if not idp u then return<<ee:=explode u;length(ee).ee>>;
  33. if not(ee:=get(u,'rccnam)) then <<ee:=explode(u);
  34. ee:=length(ee) . ee;
  35. put(u,'rccnam,ee)>>;
  36. return ee;
  37. end;
  38. % symbolic smacro procedure prtwrd u;
  39. % if numberp u then prtnum u else prtatm u;
  40. symbolic procedure prtatm u;
  41. prin2 u; % For a nice print;
  42. symbolic procedure prtlst u;
  43. if atom u then prin2 u else for each x in u do prin2 x;
  44. symbolic procedure prtnum n;
  45. % We use this kludge to defeat the new line that several LISPs
  46. % including PSL like to insert when printing a number near the line
  47. % boundary.
  48. for each x in explode2 n do prin2 x;
  49. symbolic procedure princn ee;
  50. % output a list of chars, update POSN();
  51. while (ee:=cdr ee) do prin2 car ee;
  52. symbolic procedure spaces n; for i:=1:n do prin2 '! ;
  53. symbolic procedure spaces!-to n;
  54. begin scalar x;
  55. x := n - posn();
  56. if x<1 then newline n
  57. else spaces x;
  58. end;
  59. symbolic procedure setpage(title,page);
  60. % Initialise current page and title;
  61. begin
  62. title!*:= title ;
  63. pgnum!*:=page;
  64. end;
  65. symbolic procedure newline n;
  66. % Begins a fresh line at posn N;
  67. begin
  68. lnnum!*:=lnnum!*+1;
  69. if lnnum!*>=maxln!* then newpage()
  70. else terpri();
  71. spaces(orig!*+n);
  72. end;
  73. symbolic procedure newpage();
  74. % Start a fresh page, with PGNUM and TITLE, if needed;
  75. begin scalar a;
  76. a:=lposn();
  77. lnnum!*:=0;
  78. if posn() neq 0 then newline 0;
  79. if a neq 0 then formfeed();
  80. if title!* then
  81. <<spaces!-to 5; prtlst title!*>>;
  82. spaces!-to (linelength(nil)-4);
  83. if pgnum!* then <<prtnum pgnum!*; pgnum!*:=pgnum!*+1>>
  84. else pgnum!*:=2;
  85. newline 10;
  86. newline 0;
  87. end;
  88. symbolic procedure underline2 n;
  89. if n>=linelength(nil) then
  90. <<n:=linelength(nil)-posn();
  91. for i:=0:n do prin2 '!- ;
  92. newline(0)>>
  93. else begin scalar j;
  94. j:=n-posn();
  95. for i:=0:j do prin2 '!-;
  96. end;
  97. symbolic procedure lprint(u,n);
  98. % prints a list of atoms within block LINELENGTH(NIL)-n;
  99. begin scalar ee; integer l,m;
  100. spaces!-to n;
  101. l := linelength nil-posn();
  102. if l<=0 then error(13,"WINDOW TOO SMALL FOR LPRINT");
  103. while u do
  104. <<ee:=getes car u; u:=cdr u;
  105. if linelength nil<posn() then newline n;
  106. if car ee<(m := linelength nil-posn()) then princn ee
  107. else if car ee<l then <<newline n; princn ee>>
  108. else begin
  109. ee := cdr ee;
  110. a: for i := 1:m do <<prin2 car ee; ee := cdr ee>>;
  111. newline n;
  112. if null ee then nil
  113. else if length ee<(m := l) then princn(nil . ee)
  114. else go to a
  115. end;
  116. if posn()<linelength nil then prin2 '! >>
  117. end;
  118. symbolic procedure rempropss(atmlst,lst);
  119. for each x in atmlst do
  120. for each y in lst do remprop(x,y);
  121. symbolic procedure remflagss(atmlst,lst);
  122. for each x in lst do remflag(atmlst,x);
  123. symbolic procedure formfeed;
  124. if !*formfeed then eject()
  125. else <<terpri();
  126. prin2 " ========================================= ";
  127. terpri()>>;
  128. endmodule;
  129. module rcref; % Cross reference program.
  130. % Author: Martin L. Griss.
  131. fluid '(!*backtrace !*cref !*defn !*mode calls!* curfun!* dfprint!*
  132. globs!* locls!* toplv!*);
  133. global '(undefg!* gseen!* btime!* expand!* haveargs!* notuse!* nolist!*
  134. dclglb!* entpts!* undefns!* seen!* tseen!* op!*!* cloc!*
  135. pfiles!* curlin!* pretitl!* !*creftime !*saveprops maxarg!*
  136. !*crefsummary !*comp !*raise !*rlisp !*globals !*algebraics);
  137. switch cref;
  138. !*algebraics:='t; % Default is normal parse of algebraic;
  139. !*globals:='t; % Do analyze globals;
  140. % !*RLISP:=NIL; % REDUCE as default;
  141. maxarg!*:=15; % Maximum args in Standard Lisp;
  142. % Requires REDIO and SORT support.
  143. deflist('((anlfn procstat) (crflapo procstat)),'stat);
  144. flag('(anlfn crflapo),'compile);
  145. comment EXPAND flag on these forces expansion of MACROS;
  146. expand!* := '(for foreach repeat while);
  147. nolist!* := nconc(deflist(slfns!*,'number!-of!-args),nolist!*)$
  148. nolist!* := append('(and cond endmodule lambda list max min module or
  149. plus prog prog2 progn times),
  150. nolist!*);
  151. flag ('(plus times and or lambda progn max min cond prog case list),
  152. 'naryargs);
  153. dclglb!*:='(!*comp emsg!* !*raise);
  154. if not getd 'begin then
  155. flag('(rds deflist flag fluid global remprop remflag unfluid
  156. setq crefoff),'eval);
  157. symbolic procedure crefon;
  158. begin scalar a,ocrfil,crfil;
  159. btime!*:=time();
  160. dfprint!* := 'refprint;
  161. !*defn := t;
  162. if not !*algebraics then put('algebraic,'newnam,'symbolic);
  163. flag(nolist!*,'nolist);
  164. flag(expand!*,'expand);
  165. flag(dclglb!*,'dclglb);
  166. % Global lists;
  167. entpts!*:=nil; % Entry points to package;
  168. undefns!*:=nil; % Functions undefined in package;
  169. seen!*:=nil; % List of all encountered functions;
  170. tseen!*:=nil; % List of all encountered types not flagged
  171. % FUNCTION;
  172. gseen!*:=nil; % All encountered globals;
  173. pfiles!*:=nil; % Processed files;
  174. undefg!*:=nil; % Undeclared globals encountered;
  175. curlin!*:=nil; % Position in file(s) of current command ;
  176. pretitl!*:=nil; % T if error or questionables found ;
  177. % Usages in specific function under analysis;
  178. globs!*:=nil; % Globals refered to in this ;
  179. calls!*:=nil; % Functions called by this;
  180. locls!*:=nil; % Defined local variables in this ;
  181. toplv!*:=t; % NIL if inside function body ;
  182. curfun!*:=nil; % Current function beeing analysed;
  183. op!*!*:=nil; % Current op. in LAP code;
  184. setpage(" Errors or questionables",nil);
  185. if getd 'begin then return nil; % In REDUCE;
  186. % The following loop is used when running in bare LISP;
  187. ndf: if not (a eq !$eof!$) then go lop;
  188. crfil:=nil;
  189. if null ocrfil then go lop;
  190. crfil:=caar ocrfil;
  191. rds cdar ocrfil;
  192. ocrfil:=cdr ocrfil;
  193. lop: a:=errorset('(!%nexttyi),t,!*backtrace);
  194. if atom a then go ndf;
  195. cloc!*:=if crfil then crfil . pgline() else nil;
  196. a:=errorset('(read),t,!*backtrace);
  197. if atom a then go ndf;
  198. a:=car a;
  199. if not pairp a then go lop;
  200. if car a eq 'dskin then
  201. <<ocrfil:=(crfil.rds open(cdr a,'input)).ocrfil;
  202. crfil:=cdr a; go lop>>;
  203. errorset(list('refprint,mkquote a),t,!*backtrace);
  204. if flagp(car a,'eval) and
  205. (car a neq 'setq or caddr a memq '(t nil) or
  206. constantp caddr a or eqcar(caddr a,'quote))
  207. then errorset(a,t,!*backtrace);
  208. if !*defn then go lop
  209. end;
  210. symbolic procedure undefdchk fn;
  211. if not flagp(fn,'defd) then undefns!* := fn . undefns!*;
  212. symbolic procedure princng u;
  213. princn getes u;
  214. symbolic procedure crefoff;
  215. % main call, sets up, alphabetizes and prints;
  216. begin scalar tim,x;
  217. dfprint!* := nil;
  218. !*defn:=nil;
  219. if not !*algebraics
  220. then remprop('algebraic,'newnam); %back to normal;
  221. tim:=time()-btime!*;
  222. for each fn in seen!* do
  223. <<if null get(fn,'calledby) then entpts!*:=fn . entpts!*;
  224. undefdchk fn>>;
  225. tseen!*:=for each z in idsort tseen!* collect
  226. <<remprop(z,'tseen);
  227. for each fn in (x:=get(z,'funs)) do
  228. <<undefdchk fn; remprop(fn,'rccnam)>>;
  229. z.x>>;
  230. for each z in gseen!* do
  231. if get(z,'usedunby) then undefg!*:=z . undefg!*;
  232. setpage(" Summary",nil);
  233. newpage();
  234. pfiles!*:=punused("Crossreference listing for files:",
  235. for each z in pfiles!* collect cdr z);
  236. entpts!*:=punused("Entry Points:",entpts!*);
  237. undefns!*:=punused("Undefined Functions:",undefns!*);
  238. undefg!*:=punused("Undeclared Global Variables:",undefg!*);
  239. gseen!*:=punused("Global variables:",gseen!*);
  240. seen!*:=punused("Functions:",seen!*);
  241. for each z in tseen!* do
  242. <<rplacd(z,punused(list(car z," procedures:"),cdr z));
  243. x:='!( . nconc(explode car z,list '!));
  244. for each fn in cdr z do
  245. <<fn:=getes fn; rplacd(fn,append(x,cdr fn));
  246. rplaca(fn,length cdr fn)>> >>;
  247. if !*crefsummary then goto xy;
  248. if !*globals and gseen!* then
  249. <<setpage(" Global Variable Usage",1);
  250. newpage();
  251. for each z in gseen!* do cref6 z>>;
  252. if seen!* then cref52(" Function Usage",seen!*);
  253. for each z in tseen!* do
  254. cref52(list(" ",car z," procedures"),cdr z);
  255. setpage(" Toplevel calls:",nil);
  256. x:=t;
  257. for each z in pfiles!* do
  258. if get(z,'calls) or get(z,'globs) then
  259. <<if x then <<newpage(); x:=nil>>;
  260. newline 0; newline 0; princng z;
  261. spaces!-to 15; underline2 (linelength(nil)-10);
  262. cref51(z,'calls,"Calls:");
  263. if !*globals then cref51(z,'globs,"Globals:")>>;
  264. xy: if !*saveprops then goto xx;
  265. rempropss(seen!*,'(gall calls globs calledby alsois sameas));
  266. remflagss(seen!*,'(seen cinthis defd));
  267. rempropss(gseen!*,'(usedby usedunby boundby setby));
  268. remflagss(gseen!*,'(dclglb gseen glb2rf glb2bd glb2st));
  269. for each z in tseen!* do remprop(car z,'funs);
  270. % for each z in haveargs!* do remprop(z,'number!-of!-args);
  271. haveargs!* := gseen!* := seen!* := tseen!* := nil;
  272. xx: newline 2;
  273. if not !*creftime then return;
  274. btime!*:=time()-btime!*;
  275. setpage(" Timing Information",nil);
  276. newpage(); newline 0;
  277. prtatm " Total Time="; prtnum btime!*;
  278. prtatm " (ms)";
  279. newline 0;
  280. prtatm " Analysis Time="; prtnum tim;
  281. newline 0;
  282. prtatm " Sorting Time="; prtnum (btime!*-tim);
  283. newline 0; newline 0
  284. end;
  285. symbolic procedure punused(x,y);
  286. if y then
  287. <<newline 2; prtlst x; newline 0;
  288. lprint(y := idsort y,8); newline 0; y>>;
  289. symbolic procedure cref52(x,y);
  290. <<setpage(x,1); newpage(); for each z in y do cref5 z>>;
  291. symbolic procedure cref5 fn;
  292. % Print single entry;
  293. begin scalar x,y;
  294. newline 0; newline 0;
  295. prin1 fn; spaces!-to 15;
  296. y:=get(fn,'gall);
  297. if y then <<prin1 cdr y; x:=car y>>
  298. else prin2 "Undefined";
  299. spaces!-to 25;
  300. if flagp(fn,'naryargs) then prin2 " Nary Args "
  301. else if (y:=get(fn,'number!-of!-args)) then
  302. <<prin2 " "; prin2 y; prin2 " Args ">>;
  303. underline2 (linelength(nil)-10);
  304. if x then
  305. <<newline 15; prtatm "Line:"; spaces!-to 27;
  306. prtnum cddr x; prtatm '!/; prtnum cadr x;
  307. prtatm " in "; prtatm car x>>;
  308. cref51(fn,'calledby,"Called by:");
  309. cref51(fn,'calls,"Calls:");
  310. cref51(fn,'alsois,"Is also:");
  311. cref51(fn,'sameas,"Same as:");
  312. if !*globals then cref51(fn,'globs,"Globals:")
  313. end;
  314. symbolic procedure cref51(x,y,z);
  315. if (x:=get(x,y)) then <<newline 15; prtatm z; lprint(idsort x,27)>>;
  316. symbolic procedure cref6 glb;
  317. % print single global usage entry;
  318. <<newline 0; prin1 glb; spaces!-to 15;
  319. notuse!*:=t;
  320. cref61(glb,'usedby,"Global in:");
  321. cref61(glb,'usedunby,"Undeclared:");
  322. cref61(glb,'boundby,"Bound in:");
  323. cref61(glb,'setby,"Set by:");
  324. if notuse!* then prtatm "*** Not Used ***">>;
  325. symbolic procedure cref61(x,y,z);
  326. if (x:=get(x,y)) then
  327. <<if not notuse!* then newline 15 else notuse!*:=nil;
  328. prtatm z; lprint(idsort x,27)>>;
  329. % Analyse bodies of LISP functions for
  330. % functions called, and globals used, undefined.
  331. smacro procedure flag1(u,v); flag(list u,v);
  332. smacro procedure remflag1(u,v); remflag(list u,v);
  333. smacro procedure isglob u;
  334. flagp(u,'dclglb);
  335. smacro procedure chkseen s;
  336. % Has this name been encountered already?;
  337. if not flagp(s,'seen) then
  338. <<flag1(s,'seen); seen!*:=s . seen!*>>;
  339. smacro procedure globref u;
  340. if not flagp(u,'glb2rf)
  341. then <<flag1(u,'glb2rf); globs!*:=u . globs!*>>;
  342. smacro procedure anatom u;
  343. % Global seen before local..ie detect extended from this;
  344. if !*globals and u and not(u eq 't)
  345. and idp u and not assoc(u,locls!*)
  346. then globref u;
  347. smacro procedure chkgseen g;
  348. if not flagp(g,'gseen) then <<gseen!*:=g . gseen!*;
  349. flag1(g,'gseen)>>;
  350. symbolic procedure do!-global l;
  351. % Catch global defns;
  352. % Distinguish FLUID from GLOBAL later;
  353. if pairp(l:=qcrf car l) and !*globals and toplv!* then
  354. <<for each v in l do chkgseen v; flag(l,'dclglb)>>;
  355. put('global,'anlfn,'do!-global);
  356. put('fluid,'anlfn,'do!-global);
  357. symbolic anlfn procedure unfluid l;
  358. if pairp(l:=qcrf car l) and !*globals and toplv!* then
  359. <<for each v in l do chkgseen v; remflag(l,'dclglb)>>;
  360. symbolic procedure add2locs ll;
  361. begin scalar oldloc;
  362. if !*globals then for each gg in ll do
  363. <<oldloc:=assoc(gg,locls!*);
  364. if not null oldloc then <<
  365. qerline 0;
  366. prin2 "*** Variable ";
  367. prin1 gg;
  368. prin2 " nested declaration in ";
  369. princng curfun!*;
  370. newline 0;
  371. rplacd(oldloc,nil.oldloc)>>
  372. else locls!*:=(gg . list nil) . locls!*;
  373. if isglob(gg) or flagp(gg,'glb2rf) then globind gg;
  374. if flagp(gg,'seen) then
  375. <<qerline 0;
  376. prin2 "*** Function ";
  377. princng gg;
  378. prin2 " used as variable in ";
  379. princng curfun!*;
  380. newline 0>> >>
  381. end;
  382. symbolic procedure globind gg;
  383. <<flag1(gg,'glb2bd); globref gg>>;
  384. symbolic procedure remlocs lln;
  385. begin scalar oldloc;
  386. if !*globals then for each ll in lln do
  387. <<oldloc:=assoc(ll,locls!*);
  388. if null oldloc then
  389. if getd 'begin then rederr list(" Lvar confused",ll)
  390. else error(0,list(" Lvar confused",ll));
  391. if cddr oldloc then rplacd(oldloc,cddr oldloc)
  392. else locls!*:=efface1(oldloc,locls!*)>>
  393. end;
  394. symbolic procedure add2calls fn;
  395. % Update local CALLS!*;
  396. if not(flagp(fn,'nolist) or flagp(fn,'cinthis))
  397. then <<calls!*:=fn . calls!*; flag1(fn,'cinthis)>>;
  398. symbolic procedure anform u;
  399. if atom u then anatom u
  400. else anform1 u;
  401. symbolic procedure anforml l;
  402. begin
  403. while not atom l do <<anform car l; l:=cdr l>>;
  404. if l then anatom l
  405. end;
  406. symbolic procedure anform1 u;
  407. begin scalar fn,x;
  408. fn:=car u; u:=cdr u;
  409. if not atom fn then return <<anform1 fn; anforml u>>;
  410. if not idp fn then return nil
  411. else if isglob fn then <<globref fn; return anforml u>>
  412. else if assoc(fn,locls!*) then return anforml u;
  413. add2calls fn;
  414. checkargcount(fn,length u);
  415. if flagp(fn,'noanl) then nil
  416. else if x:=get(fn,'anlfn) then apply(x,list u)
  417. else anforml u
  418. end;
  419. symbolic anlfn procedure lambda u;
  420. <<add2locs car u; anforml cdr u; remlocs car u>>;
  421. symbolic procedure anlsetq u;
  422. <<anforml u;
  423. if !*globals and flagp(u:=car u,'glb2rf) then flag1(u,'glb2st)>>;
  424. put('setq,'anlfn,'anlsetq);
  425. symbolic anlfn procedure cond u;
  426. for each x in u do anforml x;
  427. symbolic anlfn procedure prog u;
  428. <<add2locs car u;
  429. for each x in cdr u do
  430. if not atom x then anform1 x;
  431. remlocs car u>>;
  432. symbolic anlfn procedure function u;
  433. if pairp(u:=car u) then anform1 u
  434. else if isglob u then globref u
  435. else if null assoc(u,locls!*) then add2calls u;
  436. flag('(quote go),'noanl);
  437. symbolic anlfn procedure errorset u;
  438. begin scalar fn,x;
  439. anforml cdr u;
  440. if eqcar(u:=car u,'quote) then return ersanform cadr u
  441. else if not((eqcar(u,'cons) or (x:=eqcar(u,'list)))
  442. and quotp(fn:=cadr u))
  443. then return anform u;
  444. anforml cddr u;
  445. if pairp(fn:=cadr fn) then anform1 fn
  446. else if flagp(fn,'glb2rf) then nil
  447. else if isglob fn then globref fn
  448. else <<add2calls fn; if x then checkargcount(fn,length cddr u)>>
  449. end;
  450. symbolic procedure ersanform u;
  451. begin scalar locls!*;
  452. return anform u
  453. end;
  454. symbolic procedure anlmap u;
  455. <<anforml cdr u;
  456. if quotp(u:=caddr u) and idp(u:=cadr u)
  457. and not isglobl u and not assoc(u,locls!*)
  458. then checkargcount(u,1)>>;
  459. for each x in '(map mapc maplist mapcar mapcon mapcan) do
  460. put(x,'anlfn,'anlmap);
  461. symbolic anlfn procedure apply u;
  462. begin scalar fn;
  463. anforml cdr u;
  464. if quotp(fn:=cadr u) and idp(fn:=cadr fn) and eqcar(u:=caddr u,'list)
  465. then checkargcount(fn,length cdr u)
  466. end;
  467. symbolic procedure quotp u; eqcar(u,'quote) or eqcar(u,'function);
  468. put('cref ,'simpfg ,'((t (crefon)) (nil (crefoff))));
  469. symbolic procedure outref(s,varlis,body,type);
  470. begin scalar curfun!*,calls!*,globs!*,locls!*,toplv!*,a;
  471. a:=if varlis memq '(anp!!atom anp!!idb anp!!eq anp!!unknown)
  472. then nil
  473. else length varlis;
  474. s := outrdefun(s,type,if a then a else get(body,'number!-of!-args));
  475. if a then <<add2locs varlis; anform(body); remlocs varlis>>
  476. else if null body or not idp body then nil
  477. else if varlis eq 'anp!!eq
  478. then <<put(s,'sameas,list body); traput(body,'alsois,s)>>
  479. else add2calls body;
  480. outrefend s
  481. end;
  482. symbolic procedure traput(u,v,w);
  483. begin scalar a;
  484. if a:=get(u,v) then
  485. (if not(toplv!* or w memq a) then rplacd(a,w . cdr a))
  486. else put(u,v,list w)
  487. end;
  488. smacro procedure toput(u,v,w);
  489. if w then put(u,v,if toplv!* then union(w,get(u,v)) else w);
  490. symbolic procedure union(x,y);
  491. if null x then y
  492. else union(cdr x,if car x member y then y else car x . y);
  493. symbolic procedure outrefend s;
  494. <<toput(s,'calls,calls!*);
  495. for each x in calls!* do
  496. <<remflag1(x,'cinthis);
  497. if not x eq s then <<chkseen x; traput(x,'calledby,s)>> >>;
  498. toput(s,'globs,globs!*);
  499. for each x in globs!* do
  500. <<traput(x,if isglob x then 'usedby
  501. else <<chkgseen x; 'usedunby>>,s);
  502. remflag1(x,'glb2rf);
  503. if flagp(x,'glb2bd)
  504. then <<remflag1(x,'glb2bd); traput(x,'boundby,s)>>;
  505. if flagp(x,'glb2st)
  506. then <<remflag1(x,'glb2st); traput(x,'setby,s)>> >> >>;
  507. symbolic procedure recref(s,type);
  508. <<qerline 2;
  509. prtatm "*** Redefinition to ";
  510. prin1 type;
  511. prtatm " procedure, of:";
  512. cref5 s;
  513. rempropss(list s,'(calls globs sameas));
  514. newline 2>>;
  515. symbolic procedure outrdefun(s,type,v);
  516. begin
  517. s:=qtypnm(s,type);
  518. if flagp(s,'defd) then recref(s,type)
  519. else flag1(s,'defd);
  520. if flagp(type,'function) and (isglob s or assoc(s,locls!*)) then
  521. <<qerline 0;
  522. prin2 "**** Variable ";
  523. princng s;
  524. prin2 " defined as function";
  525. newline 0>>;
  526. if v and not flagp(type,'naryarg) then defineargs(s,v);
  527. put(s,'gall,curlin!* . type);
  528. globs!*:=nil;
  529. calls!*:=nil;
  530. return curfun!*:=s
  531. end;
  532. flag('(macro fexpr),'naryarg);
  533. symbolic procedure qtypnm(s,type);
  534. if flagp(type,'function) then <<chkseen s; s>>
  535. else begin scalar x,y,z;
  536. if (y:=get(type,'tseen)) and (x:=atsoc(s,cdr y))
  537. then return cdr x;
  538. if null y then
  539. <<y:=list ('!( . nconc(explode type,list '!)));
  540. put(type,'tseen,y); tseen!* := type . tseen!*>>;
  541. x := compress (z := explode s);
  542. rplacd(y,(s . x) . cdr y);
  543. y := append(car y,z);
  544. put(x,'rccnam,length y . y);
  545. traput(type,'funs,x);
  546. return x
  547. end;
  548. symbolic procedure defineargs(name,n);
  549. begin scalar calledwith,x;
  550. calledwith:=get(name,'number!-of!-args);
  551. if null calledwith then return hasarg(name,n);
  552. if n=calledwith then return nil;
  553. if x := get(name,'calledby) then instdof(name,n,calledwith,x);
  554. hasarg(name,n)
  555. end;
  556. symbolic procedure instdof(name,n,m,fnlst);
  557. <<qerline 0;
  558. prin2 "***** ";
  559. prin1 name;
  560. prin2 " called with ";
  561. prin2 m;
  562. prin2 " instead of ";
  563. prin2 n;
  564. prin2 " arguments in:";
  565. lprint(idsort fnlst,posn()+1);
  566. newline 0>>;
  567. symbolic procedure hasarg(name,n);
  568. <<haveargs!*:=name . haveargs!*;
  569. if n>maxarg!* then
  570. <<qerline 0;
  571. prin2 "**** "; prin1 name;
  572. prin2 " has "; prin2 n;
  573. prin2 " arguments";
  574. newline 0 >>;
  575. put(name,'number!-of!-args,n)>>;
  576. symbolic procedure checkargcount(name,n);
  577. begin scalar correctn;
  578. if flagp(name,'naryargs) then return nil;
  579. correctn:=get(name,'number!-of!-args);
  580. if null correctn then return hasarg(name,n);
  581. if not correctn=n then instdof(name,correctn,n,list curfun!*)
  582. end;
  583. symbolic procedure refprint u;
  584. begin scalar x,y;
  585. % x:=if cloc!* then filemk car cloc!* else "*ttyinput*";
  586. x:=if cloc!* then car cloc!* else "*TTYINPUT*";
  587. if (curfun!*:=assoc(x,pfiles!*)) then
  588. <<x:=car curfun!*; curfun!*:=cdr curfun!*>>
  589. else <<pfiles!*:=(x.(curfun!*:=gensym())).pfiles!*;
  590. y:=reversip cdr reversip cdr explode x;
  591. put(curfun!*,'rccnam,length y . y)>>;
  592. curlin!*:=if cloc!* and cdr cloc!* then x . cdr cloc!* else nil;
  593. calls!*:=globs!*:=locls!*:=nil;
  594. anform u;
  595. outrefend curfun!*
  596. end;
  597. symbolic procedure filemk u;
  598. % Convert a file specification from lisp format to a string.
  599. % This is essentially the inverse of MKFILE;
  600. begin scalar dev,name,flg,flg2;
  601. if null u then return nil
  602. else if atom u then name := explode2 u
  603. else for each x in u do
  604. if x eq 'dir!: then flg := t
  605. else if atom x then
  606. if flg then dev := '!< . nconc(explode2 x,list '!>)
  607. else if x eq 'dsk!: then dev:=nil
  608. else if !%devp x then dev := explode2 x
  609. else name := explode2 x
  610. else if atom cdr x then
  611. name := nconc(explode2 car x,'!. . explode2 cdr x)
  612. else <<flg2 := t;
  613. dev := '![ . nconc(explode2 car x,
  614. '!, . nconc(explode2 cadr x,list '!]))>>;
  615. u := if flg2 then nconc(name,dev)
  616. else nconc(dev,name);
  617. return compress('!" . nconc(u,'(!")))
  618. end;
  619. flag('(smacro nmacro),'cref);
  620. symbolic anlfn procedure put u;
  621. if toplv!* and qcputx cadr u then anputx u
  622. else anforml u;
  623. put('putc,'anlfn,get('put,'anlfn));
  624. symbolic procedure qcputx u;
  625. eqcar(u,'quote) and (flagp(cadr u,'cref) or flagp(cadr u,'compile));
  626. symbolic procedure anputx u;
  627. begin scalar nam,typ,body;
  628. nam:=qcrf car u;
  629. typ:=qcrf cadr u;
  630. u:=caddr u;
  631. if atom u then <<body:=qcrf u; u:='anp!!atom>>
  632. else if car u memq '(quote function) then
  633. if eqcar(u:=cadr u,'lambda) then <<body:=caddr u; u:=cadr u>>
  634. else if idp u then <<body:=u; u:='anp!!idb>>
  635. else return nil
  636. else if car u eq 'cdr and eqcar(cadr u,'getd) then
  637. <<body:=qcrf cadadr u; u:='anp!!eq>>
  638. else if car u eq 'get and qcputx caddr u then
  639. <<body:=qtypnm(qcrf cadr u,cadr caddr u); u:='anp!!eq>>
  640. else if car u eq 'mkcode then
  641. <<anform cadr u; u:=qcrf caddr u; body:=nil>>
  642. else <<body:=qcrf u; u:='anp!!unknown>>;
  643. outref(nam,u,body,typ)
  644. end;
  645. symbolic anlfn procedure putd u;
  646. if toplv!* then anputx u else anforml u;
  647. symbolic anlfn procedure de u;
  648. outdefr(u,'expr);
  649. symbolic anlfn procedure df u;
  650. outdefr(u,'fexpr);
  651. symbolic anlfn procedure dm u;
  652. outdefr(u,'macro);
  653. symbolic anlfn procedure dn u; % PSL function
  654. outdefr(u,'macro);
  655. symbolic anlfn procedure ds u; % PSL function
  656. outdefr(u,'smacro);
  657. symbolic procedure outdefr(u,type);
  658. outref(car u,cadr u,caddr u,type);
  659. symbolic procedure qcrf u;
  660. if null u or u eq t then u
  661. else if eqcar(u,'quote) then cadr u
  662. else <<anform u; compress explode '!?value!?!?>>;
  663. flag('(expr fexpr macro smacro nmacro),'function);
  664. symbolic anlfn procedure lap u;
  665. if pairp(u:=qcrf car u) then
  666. begin scalar globs!*,locls!*,calls!*,curfun!*,toplv!*,x;
  667. while u do
  668. <<if pairp car u then
  669. if x:=get(op!*!*:=caar u,'crflapo) then apply(x,list u)
  670. else if !*globals then for each y in cdar u do anlapev y;
  671. u:=cdr u>>;
  672. qoutrefe()
  673. end;
  674. symbolic crflapo procedure !*entry u;
  675. <<qoutrefe(); u:=cdar u; outrdefun(car u,cadr u,caddr u)>>;
  676. symbolic procedure qoutrefe;
  677. begin
  678. if null curfun!* then
  679. if globs!* or calls!* then
  680. <<curfun!*:=compress explode '!?lap!?!?; chkseen curfun!*>>
  681. else return;
  682. outrefend curfun!*
  683. end;
  684. symbolic crflapo procedure !*lambind u;
  685. for each x in caddar u do globind car x;
  686. symbolic crflapo procedure !*progbind u;
  687. for each x in cadar u do globind car x;
  688. symbolic procedure lincall u;
  689. <<add2calls car (u:=cdar u); checkargcount(car u,caddr u)>>;
  690. put('!*link,'crflapo,'lincall);
  691. put('!*linke,'crflapo,'lincall);
  692. symbolic procedure anlapev u;
  693. if pairp u then
  694. if car u memq '(global fluid) then
  695. <<u:=cadr u; globref u;
  696. if flagp(op!*!*,'store) then put(u,'glb2st,'t)>>
  697. else <<anlapev car u; anlapev cdr u>>;
  698. flag('(!*store),'store);
  699. symbolic procedure qerline u;
  700. if pretitl!* then newline u
  701. else <<pretitl!*:=t; newpage()>>;
  702. % These functions defined to be able to run in bare LISP;
  703. symbolic procedure eqcar(u,v);
  704. pairp u and car u eq v;
  705. symbolic procedure mkquote u; list('quote,u);
  706. symbolic procedure efface1(u,v);
  707. if null v then nil
  708. else if u eq car v then cdr v
  709. else rplacd(v,efface1(u,cdr v));
  710. % DECSystem 10/20 dependent part;
  711. flag('(pop movem setzm hrrzm),'store);
  712. symbolic procedure lapcallf u;
  713. begin scalar fn;
  714. return
  715. if eqcar(cadr (u:=cdar u),'e) then
  716. <<add2calls(fn:=cadadr u); checkargcount(fn,car u)>>
  717. else if !*globals then anlapev cadr u
  718. end;
  719. put('jcall,'crflapo,'lapcallf);
  720. put('callf,'crflapo,'lapcallf);
  721. put('jcallf,'crflapo,'lapcallf);
  722. symbolic crflapo procedure call u;
  723. if not(caddar u = '(e !*lambind!*)) then lapcallf u
  724. else while ((u:=cdr u) and pairp car u and caar u = 0) do
  725. globind cadr caddar u;
  726. endmodule;
  727. end;