superv.red 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. module superv; % REDUCE supervisory functions.
  2. % Author: Anthony C. Hearn.
  3. % Modified by: Jed B. Marti, Francis J. Wright.
  4. % Copyright (c) 1998 Anthony C. Hearn. All rights reserved.
  5. fluid '(!*debug
  6. !*defn
  7. !*demo
  8. !*echo
  9. !*errcont
  10. !*int
  11. !*lisp!_hook
  12. !*mode
  13. !*output
  14. !*pret
  15. !*reduce4
  16. !*slin
  17. !*time
  18. dfprint!*
  19. errmsg!*
  20. lispsystem!*
  21. loopdelimslist!*
  22. lreadfn!*
  23. newrule!*
  24. semic!*
  25. tslin!*);
  26. global '(!$eof!$
  27. !*byeflag!*
  28. !*extraecho
  29. !*lessspace
  30. !*micro!-version
  31. !*nosave!*
  32. !*strind
  33. !*struct
  34. cloc!*
  35. cmsg!*
  36. crbuf!*
  37. crbuflis!*
  38. crbuf1!*
  39. curline!*
  40. cursym!*
  41. eof!*
  42. erfg!*
  43. forkeywords!*
  44. ifl!*
  45. ipl!*
  46. initl!*
  47. inputbuflis!*
  48. key!*
  49. ofl!*
  50. opl!*
  51. ogctime!*
  52. otime!*
  53. program!*
  54. programl!*
  55. promptexp!*
  56. repeatkeywords!*
  57. resultbuflis!*
  58. st!*
  59. statcounter
  60. symchar!*
  61. tok!*
  62. ttype!*
  63. whilekeywords!*
  64. ws);
  65. !*output := t;
  66. eof!* := 0;
  67. initl!* := '(fname!* outl!*);
  68. statcounter := 0;
  69. % The true REDUCE supervisory function is BEGIN, again defined in the
  70. % system dependent part of this program. However, most of the work is
  71. % done by BEGIN1, which is called by BEGIN for every file encountered
  72. % on input;
  73. symbolic procedure errorp u;
  74. %returns true if U is an ERRORSET error format;
  75. atom u or cdr u;
  76. symbolic procedure printprompt u;
  77. %Prints the prompt expression for input;
  78. progn(ofl!* and wrs nil, prin2 u, ofl!* and wrs cdr ofl!*);
  79. symbolic procedure setcloc!*;
  80. % Used to set for file input a global variable CLOC!* to dotted pair
  81. % of file name and dotted pair of line and page being read.
  82. % Currently a place holder for system specific function, since not
  83. % supported in Standard LISP. CLOC!* is used in the INTER and RCREF
  84. % modules.
  85. cloc!* := if null ifl!* then nil else car ifl!* . (1 . curline!*);
  86. symbolic procedure commdemo;
  87. begin scalar echo,x,y,z,!*demo;
  88. echo := !*echo;
  89. !*echo := nil;
  90. x := ifl!*;
  91. terpri();
  92. rds nil;
  93. y:=readch();
  94. if null seprp y then
  95. % Read command line from terminal.
  96. begin scalar crbuf,crbuf1,crchar,ifl;
  97. crbuf := crbuf!*;
  98. crbuf!* := nil;
  99. crbuf1 := crbuf1!*;
  100. crbuf1!* := list y;
  101. crchar := crchar!*;
  102. crchar!* := '! ;
  103. ifl := ifl!*;
  104. ifl!* := nil;
  105. z := errorset!*('(command),t);
  106. z := if errorp z then '(algebraic(aeval 0))
  107. else car z;
  108. % eat rest of line quietly.
  109. q: y := readch();
  110. if y neq !$eol!$ then go to q;
  111. rds cadr x;
  112. crbuf!* := crbuf;
  113. crbuf1!* := crbuf1;
  114. crchar!* := crchar;
  115. ifl!* := ifl;
  116. !*echo := echo;
  117. end
  118. else
  119. % Read command from current input.
  120. progn(rds cadr x, !*echo := echo, z := command());
  121. return z
  122. end;
  123. symbolic procedure command1;
  124. % Innermost part of COMMAND. Can be used as hook to editor if needed.
  125. begin
  126. scan();
  127. setcloc!*();
  128. key!* := cursym!*;
  129. return xread1 nil
  130. end;
  131. symbolic procedure command;
  132. begin scalar errmsg!*,loopdelimslist!*,mode,x,y;
  133. if !*demo and ifl!* then return commdemo()
  134. else if null !*slin or !*reduce4 then go to a;
  135. % Note key!* not set in this case.
  136. setcloc!*();
  137. y := if lreadfn!* then lispapply(lreadfn!*,nil) else read();
  138. go to b;
  139. a: crchar!* := readch1(); % Initialize crchar!*.
  140. if crchar!* = !$eol!$ then go to a;
  141. % Parse input.
  142. y := command1();
  143. b: if !*reduce4 then go to c
  144. else if !*struct then y := structchk y;
  145. if !*pret and (atom y or null (car y memq '(in out shut)))
  146. then if null y and cursym!* eq 'end then rprint 'end
  147. else progn(rprint y,terpri());
  148. if !*slin then return list('symbolic,y);
  149. x := form y;
  150. % Determine target mode.
  151. if flagp(key!*,'modefn) then mode := key!*
  152. else if null atom x % and null !*micro!-version
  153. and null(car x eq 'quote)
  154. and (null(idp car x
  155. and (flagp(car x,'nochange)
  156. or flagp(car x,'intfn)
  157. or car x eq 'list))
  158. or car x memq '(setq setel setf)
  159. and eqcar(caddr x,'quote))
  160. then mode := 'symbolic
  161. else mode := !*mode;
  162. return list(mode,convertmode1(x,nil,'symbolic,mode));
  163. c: if !*debug then progn(prin2 "Parse: ",prettyprint y);
  164. % Mode analyze input.
  165. if key!* eq '!*semicol!* then go to a; % Should be a comment.
  166. if null !*reduce4 then y := form y else y := n!_form y;
  167. % y := n!_form y;
  168. if !*debug then progn(terpri(),prin2 "Form: ",prettyprint y);
  169. return y
  170. end;
  171. symbolic procedure update!_prompt;
  172. begin
  173. statcounter := statcounter + 1;
  174. promptexp!* :=
  175. compress('!! . append(explode statcounter,
  176. explode if null symchar!* or !*mode eq 'algebraic
  177. then '!:! else '!*! ));
  178. setpchar promptexp!*
  179. end;
  180. symbolic procedure begin1;
  181. begin scalar parserr,result,x;
  182. otime!* := time();
  183. % The next line is that way for bootstrapping purposes.
  184. if getd 'gctime then ogctime!* := gctime() else ogctime!* := 0;
  185. cursym!* := '!*semicol!*;
  186. a: if terminalp()
  187. then progn((if !*nosave!* or statcounter=0 then nil
  188. else add2buflis()),
  189. update!_prompt());
  190. !*nosave!* := nil;
  191. !*strind := 0; % Used by some versions of input editor.
  192. parserr := nil;
  193. if !*time then lispeval '(showtime); % Since a STAT.
  194. if !*output and null ofl!* and terminalp() and null !*defn
  195. and null !*lessspace
  196. then terpri();
  197. if tslin!*
  198. then progn(!*slin := car tslin!*,
  199. lreadfn!* := cdr tslin!*,
  200. tslin!* := nil);
  201. x := initl!*;
  202. b: if x then progn(sinitl car x, x := cdr x, go to b);
  203. remflag(forkeywords!*,'delim);
  204. remflag(repeatkeywords!*,'delim);
  205. remflag( whilekeywords!*,'delim);
  206. if !*int then erfg!* := nil; % To make editing work properly.
  207. if cursym!* eq 'end then progn(comm1 'end, return nil)
  208. % Note that key* was set from *previous* command in following.
  209. else if terminalp() and null(key!* eq 'ed)
  210. then printprompt promptexp!*;
  211. x := errorset!*('(command),t);
  212. condterpri();
  213. if errorp x then go to err1;
  214. x := car x;
  215. if car x eq 'symbolic and eqcar(cadr x,'xmodule)
  216. then result := xmodloop eval cadr x
  217. else result := begin11 x;
  218. if null result then go to a
  219. else if result eq 'end then return nil
  220. else if result eq 'err2 then go to err2
  221. else if result eq 'err3 then go to err3;
  222. c: if crbuf1!* then
  223. progn(lprim "Closing object improperly removed. Redo edit.",
  224. crbuf1!* := nil, return nil)
  225. else if eof!*>4
  226. then progn(lprim "End-of-file read", return lispeval '(bye))
  227. else if terminalp()
  228. then progn(crbuf!* := nil,!*nosave!* := t,go to a)
  229. else return nil;
  230. err1:
  231. if eofcheck() or eof!*>0 then go to c
  232. else if x="BEGIN invalid" then go to a;
  233. parserr := t;
  234. err2:
  235. resetparser(); % In case parser needs to be modified.
  236. err3:
  237. erfg!* := t;
  238. if null !*int and null !*errcont
  239. then progn(!*defn := t,
  240. !*echo := t,
  241. (if null cmsg!*
  242. then lprie "Continuing with parsing only ..."),
  243. cmsg!* := t)
  244. else if null !*errcont
  245. then progn(result := pause1 parserr,
  246. (if result then return null lispeval result),
  247. erfg!* := nil)
  248. else erfg!* := nil;
  249. go to a
  250. end;
  251. % Newrule!* is initialized in the following function, since it is not
  252. % always reinitialized by the rule code.
  253. symbolic procedure begin11 x;
  254. begin scalar errmsg!*,mode,result,newrule!*;
  255. if cursym!* eq 'end
  256. then if terminalp() and null !*lisp!_hook
  257. then progn(cursym!* := '!*semicol!*, !*nosave!* := t,
  258. return nil)
  259. else progn(comm1 'end, return 'end)
  260. else if eqcar((if !*reduce4 then x else cadr x),'retry)
  261. then if programl!* then x := programl!*
  262. else progn(lprim "No previous expression",return nil);
  263. if null !*reduce4 then progn(mode := car x,x := cadr x);
  264. program!* := x; % Keep it around for debugging purposes.
  265. if eofcheck() then return 'c else eof!* := 0;
  266. add2inputbuf(x,if !*reduce4 then nil else mode);
  267. if null atom x
  268. and car x memq '(bye quit)
  269. then if getd 'bye
  270. then progn(lispeval x, !*nosave!* := t, return nil)
  271. else progn(!*byeflag!* := t, return nil)
  272. else if null !*reduce4 and eqcar(x,'ed)
  273. then progn((if getd 'cedit and terminalp()
  274. then cedit cdr x
  275. else lprim "ED not supported"),
  276. !*nosave!* := t, return nil)
  277. else if !*defn
  278. then if erfg!* then return nil
  279. else if null flagp(key!*,'ignore)
  280. and null eqcar(x,'quote)
  281. then progn((if x then dfprint x else nil),
  282. if null flagp(key!*,'eval) then return nil);
  283. if !*output and ifl!* and !*echo and null !*lessspace
  284. then terpri();
  285. result := errorset!*(x,t);
  286. if errorp result or erfg!*
  287. then progn(programl!* := list(mode,x),return 'err2)
  288. else if !*defn then return nil;
  289. if null !*reduce4
  290. then if null(mode eq 'symbolic) then x := getsetvars x else nil
  291. else progn(result := car result,
  292. (if null result then result := mkobject(nil,'noval)),
  293. mode := type result,
  294. result := value result);
  295. add2resultbuf((if null !*reduce4 then car result else result),
  296. mode);
  297. if null !*output then return nil
  298. else if null(semic!* eq '!$)
  299. then if !*reduce4 then (begin
  300. terpri();
  301. if mode eq 'noval then return nil
  302. else if !*debug then prin2t "Value:";
  303. rapply1('print,list list(mode,result))
  304. end)
  305. else if mode eq 'symbolic
  306. then if null car result and null(!*mode eq 'symbolic)
  307. then nil
  308. else begin
  309. terpri();
  310. result:=
  311. errorset!*(list('print,mkquote car result),t)
  312. end
  313. else if car result
  314. then result := errorset!*(list('assgnpri,mkquote car result,
  315. (if x then 'list . x else nil),
  316. mkquote 'only),
  317. t);
  318. if null !*reduce4
  319. then return if errorp result then 'err3 else nil
  320. else if null(!*mode eq 'noval) % and !*debug
  321. then progn(terpri(), prin2 "of type: ", print mode);
  322. return nil
  323. end;
  324. symbolic procedure getsetvarlis u;
  325. if null u then nil
  326. else if atom u then errach list("getsetvarlis",u)
  327. else if atom car u then car u . getsetvarlis cdr u
  328. else if caar u memq '(setel setk) % setk0.
  329. then getsetvarlis cadar u . getsetvarlis cdr u
  330. else if caar u eq 'setq then mkquote cadar u . getsetvarlis cdr u
  331. else car u . getsetvarlis cdr u;
  332. symbolic procedure getsetvars u;
  333. if atom u then nil
  334. else if car u memq '(setel setk) % setk0.
  335. then getsetvarlis cadr u . getsetvars caddr u
  336. else if car u eq 'setq then mkquote cadr u . getsetvars caddr u
  337. else nil;
  338. flag ('(deflist flag fluid global remflag remprop unfluid),'eval);
  339. symbolic procedure close!-input!-files;
  340. % Close all input files currently open;
  341. begin
  342. if ifl!* then progn(rds nil,ifl!* := nil);
  343. aa: if null ipl!* then return nil;
  344. close cadar ipl!*;
  345. ipl!* := cdr ipl!*;
  346. go to aa
  347. end;
  348. symbolic procedure close!-output!-files;
  349. % Close all output files currently open;
  350. begin
  351. if ofl!* then progn(wrs nil,ofl!* := nil);
  352. aa: if null opl!* then return nil;
  353. close cdar opl!*;
  354. opl!* := cdr opl!*;
  355. go to aa
  356. end;
  357. symbolic procedure add2buflis;
  358. begin
  359. if null crbuf!* then return nil;
  360. crbuf!* := reversip crbuf!*; %put in right order;
  361. a: if crbuf!* and seprp car crbuf!*
  362. then progn(crbuf!* := cdr crbuf!*, go to a);
  363. crbuflis!* := (statcounter . crbuf!*) . crbuflis!*;
  364. crbuf!* := nil
  365. end;
  366. symbolic procedure add2inputbuf(u,mode);
  367. begin
  368. if null terminalp() or !*nosave!* then return nil;
  369. inputbuflis!* := list(statcounter,mode,u) . inputbuflis!*
  370. end;
  371. symbolic procedure add2resultbuf(u,mode);
  372. begin
  373. if mode eq 'symbolic
  374. or (null u and (null !*reduce4 or null(mode eq 'empty!_list)))
  375. or !*nosave!* then return nil;
  376. if !*reduce4 then putobject('ws,u,mode) else ws := u;
  377. if terminalp()
  378. then resultbuflis!* := (statcounter . u) . resultbuflis!*
  379. end;
  380. symbolic procedure condterpri;
  381. !*output and !*echo and !*extraecho and (null !*int or ifl!*)
  382. and null !*defn and null !*demo and terpri();
  383. symbolic procedure eofcheck;
  384. % true if an end-of-file has been read in current input sequence;
  385. program!* eq !$eof!$ and ttype!*=3 and (eof!* := eof!*+1);
  386. symbolic procedure resetparser;
  387. %resets the parser after an error;
  388. if null !*slin then comm1 t;
  389. symbolic procedure terminalp;
  390. %true if input is coming from an interactive terminal;
  391. !*int and null ifl!*;
  392. symbolic procedure dfprint u;
  393. % Looks for special action on a form, otherwise prettyprints it.
  394. if dfprint!* then lispapply(dfprint!*,list u)
  395. else if cmsg!* then nil
  396. else if null eqcar(u,'progn) then prettyprint u
  397. else begin
  398. a: u := cdr u;
  399. if null u then return nil;
  400. dfprint car u;
  401. go to a
  402. end;
  403. remprop('showtime,'lose); % Temporary.
  404. symbolic procedure showtime;
  405. begin scalar x,y;
  406. x := otime!*;
  407. otime!* := time();
  408. x := otime!* - x;
  409. y := ogctime!*;
  410. ogctime!* := gctime();
  411. y := ogctime!* - y;
  412. if 'psl memq lispsystem!* then x := x - y;
  413. terpri();
  414. prin2 "Time: "; prin2 x; prin2 " ms";
  415. if null(y=0)
  416. then progn(prin2 " plus GC time: ", prin2 y, prin2 " ms");
  417. terpri();
  418. return if !*reduce4 then mknovalobj() else nil
  419. end;
  420. symbolic procedure sinitl u;
  421. set(u,eval get(u,'initl));
  422. symbolic procedure read!-init!-file name;
  423. % Read a resource file in REDUCE syntax. Quiet input.
  424. % Algebraic mode is used unless rlisp88 is on.
  425. % Look for file in home directory. If no home directory
  426. % is defined, use the current directory.
  427. begin scalar !*errcont,!*int,base,fname,oldmode,x,y;
  428. base := getenv "home" or getenv "HOME" or
  429. ((x := getenv "HOMEDRIVE") and (y := getenv "HOMEPATH")
  430. and concat2(x,y)) or ".";
  431. if not(car reversip explode2 base eq '!/)
  432. then base := concat2(base,"/"); % FJW
  433. fname := if filep(x := concat2(base,concat2(".", % FJW
  434. concat2(name,"rc"))))
  435. then x
  436. else if filep(x := concat2(base,concat2(name,".rc"))) % FJW
  437. then x
  438. else if filep
  439. (x := concat2(getenv "HOME",concat2(name,".INI")))
  440. then x; % for (Open) VMS
  441. if null fname then return nil
  442. else if !*mode neq 'algebraic and null !*rlisp88
  443. then progn(oldmode := !*mode, !*mode := 'algebraic);
  444. x := errorset(list('in!_list1,fname,nil),nil,nil);
  445. if errorp x or erfg!* then
  446. progn(terpri(),
  447. prin2 "***** Error processing resource file ",
  448. prin2t fname);
  449. close!-input!-files();
  450. erfg!*:= cmsg!* := !*defn := nil;
  451. if oldmode then !*mode := oldmode;
  452. terpri();
  453. statcounter := 0
  454. end;
  455. endmodule;
  456. end;