build37.lsp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978
  1. %
  2. % Build a CSL REDUCE.
  3. %
  4. % Depending on how this file is used it will EITHER create a bootstrap
  5. % version of REDUCE or a full and optimised one.
  6. %
  7. % The behaviour is determined by whether the version of CSL used to
  8. % run it has a full complement of functions in the modules u01.c to u12.c.
  9. %
  10. %
  11. % slowr37 -z build37.lsp -- log/boot37.log
  12. %
  13. % Builds a system "slowr37.img" that does not depend on any
  14. % custom C code. The main use of this slow system is for profiling
  15. % REDUCE and then compiling the hot-spots into C. Once that has been
  16. % done this image is logically unnecessary.
  17. %
  18. %
  19. % r37 -z build37.lsp -l log/full37.log
  20. %
  21. % Here the files u01.c to u12.c and u01.lsp to u12.lsp must already
  22. % have been created, and that the r37 executable has them compiled in.
  23. % The REDUCE source files that are compiled *MUST* be the same as those used
  24. % to create this C code.
  25. % Author: Anthony C. Hearn, Stanley L. Kameny and Arthur Norman
  26. (verbos 3)
  27. (window!-heading "basic CSL")
  28. (setq !*savedef (lessp (cdr (assoc 'c!-code lispsystem!*)) 20))
  29. (cond ((null !*savedef) (progn
  30. (de c!:install (name env c!-version !&optional c1)
  31. (cond
  32. (c1 (check!-c!-code name env c!-version c1))
  33. (t (progn
  34. (put name 'c!-version c!-version)
  35. (cond (env (prog (v n)
  36. (setq v (mkvect (sub1 (length env))))
  37. (setq n 0)
  38. top (cond
  39. ((null env) (progn
  40. (put name 'funarg v)
  41. (return (symbol!-set!-env name v)))))
  42. (putv v n (car env))
  43. (setq n (add1 n))
  44. (setq env (cdr env))
  45. (go top))))
  46. name))))
  47. (rdf "../csl-c/u01.lsp")
  48. (rdf "../csl-c/u02.lsp")
  49. (rdf "../csl-c/u03.lsp")
  50. (rdf "../csl-c/u04.lsp")
  51. (rdf "../csl-c/u05.lsp")
  52. (rdf "../csl-c/u06.lsp")
  53. (rdf "../csl-c/u07.lsp")
  54. (rdf "../csl-c/u08.lsp")
  55. (rdf "../csl-c/u09.lsp")
  56. (rdf "../csl-c/u10.lsp")
  57. (rdf "../csl-c/u11.lsp")
  58. (rdf "../csl-c/u12.lsp") )))
  59. (rdf "../util/fastgets.lsp")
  60. (rdf "../cslbase/compat.lsp")
  61. (rdf "../cslbase/extras.lsp")
  62. (rdf "../cslbase/compiler.lsp")
  63. (compile!-all)
  64. (setq !*comp t) % It's faster if we compile the boot file.
  65. % Tidy up be deleting any modules that are left over in this image
  66. (dolist (a (library!-members)) (delete!-module a))
  67. % Build fasl files for the compatibility code and the two
  68. % versions of the compiler.
  69. (faslout 'cslcompat)
  70. (rdf "../util/fastgets.lsp")
  71. (rdf "../cslbase/compat.lsp")
  72. (rdf "../cslbase/extras.lsp")
  73. (faslend)
  74. (faslout 'compiler)
  75. (rdf "../cslbase/compiler.lsp")
  76. (faslend)
  77. (faslout 'ccomp)
  78. (rdf "../cslbase/ccomp.lsp")
  79. (faslend)
  80. (setq !*comp t)
  81. (de concat (u v)
  82. (compress (cons '!" (append (explode2 u)
  83. (nconc (explode2 v) (list '!"))))))
  84. (global '(oldchan!*))
  85. (setq prolog_file 'cslprolo)
  86. (setq rend_file 'cslrend)
  87. (setq !*argnochk t)
  88. (setq !*int nil) % Prevents input buffer being saved.
  89. (setq !*msg nil)
  90. (global '(!$reduce))
  91. (setq !$reduce "../../..")
  92. (window!-heading "bootstrap RLISP")
  93. (rdf "$reduce/packages/support/boot.sl")
  94. (begin2)
  95. rds(xxx := open("$reduce/packages/support/build.red",'input));
  96. (close xxx)
  97. (load!-package!-sources prolog_file 'support)
  98. (load!-package!-sources 'rlisp 'rlisp)
  99. (load!-package!-sources rend_file 'support)
  100. (load!-package!-sources 'poly 'poly)
  101. (load!-package!-sources 'alg 'alg)
  102. (load!-package!-sources 'arith 'arith) % Needed by roots, specfn*, (psl).
  103. (load!-package!-sources 'entry 'support)
  104. (load!-package!-sources 'remake 'support)
  105. (setq !*comp nil)
  106. (begin)
  107. symbolic;
  108. !#if (not !*savedef)
  109. faslout 'user;
  110. %
  111. % The "user" module is only useful when building a full system, since
  112. % in the bootstrap the files u01.lsp to u12.lsp will probably not exist
  113. % and it is CERTAIN that they are not useful.
  114. %
  115. symbolic procedure c!:install(name, env, c!-version, !&optional, c1);
  116. begin
  117. scalar v, n;
  118. if c1 then return check!-c!-code(name, env, c!-version, c1);
  119. put(name, 'c!-version, c!-version);
  120. if null env then return name;
  121. v := mkvect sub1 length env;
  122. n := 0;
  123. while env do <<
  124. putv(v, n, car env);
  125. n := n + 1;
  126. env := cdr env >>;
  127. % I only instate the environment if there is nothing useful there at
  128. % present. Actually this is even stronger. When a built-in function is
  129. % set up it gets NIL in its environment cell by default. Things that are
  130. % not defined at all have themselves there.
  131. if symbol!-env name = nil then symbol!-set!-env(name, v);
  132. put(name, 'funarg, v);
  133. return name;
  134. end;
  135. rdf "../csl-c/u01.lsp"$
  136. rdf "../csl-c/u02.lsp"$
  137. rdf "../csl-c/u03.lsp"$
  138. rdf "../csl-c/u04.lsp"$
  139. rdf "../csl-c/u05.lsp"$
  140. rdf "../csl-c/u06.lsp"$
  141. rdf "../csl-c/u07.lsp"$
  142. rdf "../csl-c/u08.lsp"$
  143. rdf "../csl-c/u09.lsp"$
  144. rdf "../csl-c/u10.lsp"$
  145. rdf "../csl-c/u11.lsp"$
  146. rdf "../csl-c/u12.lsp"$
  147. faslend;
  148. !#endif
  149. faslout 'remake;
  150. !#if (not !*savedef)
  151. load!-module "user";
  152. !#endif
  153. in "$reduce/packages/support/remake.red"$
  154. % This next function recompiles the "patches" module from source
  155. % if the current compiled module for it seems out of date. It loads
  156. % that module into memory if that seems necessary, and then applies
  157. % patches to those packages that are already loaded.
  158. symbolic procedure ensure_patches_are_up_to_date();
  159. begin
  160. scalar sourcedate, fasldate, w;
  161. if not boundp '!$reduce or not stringp !$reduce then <<
  162. if boundp '!@reduce and stringp !@reduce then
  163. !$reduce := !@reduce
  164. else !$reduce := "../../.." >>;
  165. sourcedate := filedate "$reduce/packages/support/patches.red";
  166. fasldate := modulep 'patches;
  167. if sourcedate and
  168. (null fasldate or datelessp(fasldate, sourcedate)) then <<
  169. faslout 'patches;
  170. semic!* := '!$;
  171. in "$reduce/packages/support/patches.red"$
  172. printc "patches.red read";
  173. faslend >>;
  174. if modulep 'patches then <<
  175. load!-module 'patches;
  176. for each p in loaded!-packages!* do begin
  177. scalar !*usermode, !*redefmsg;
  178. if (w := get(p, 'patchfn)) then apply(w, nil) end;
  179. if patch!-date!* then
  180. w := append(explodec ", 15-Jan-99 patched to ",
  181. append(explodec patch!-date!*, explodec " ..."))
  182. else w := explodec ", 15-Jan-99 ...";
  183. startup!-banner list!-to!-string append(explodec version!*, w) >>
  184. end;
  185. global '(r37_base_modules r37_extra_modules r37_test_cases !$reduce);
  186. symbolic procedure get_configuration_data();
  187. % Read data from a configuration file that lists the modules that must
  188. % be processed. NOTE that this and the next few funtions will ONLY
  189. % work ppoperly if REDUCE had been started up with the correct
  190. % working directory. This is (just about) acceptable because these are
  191. % system maintainance functions rather than generally flexible things
  192. % for arbitrary use.
  193. begin
  194. scalar i;
  195. i := open("../util/config.lsp", 'input);
  196. i := rds i;
  197. r37_base_modules := read();
  198. r37_extra_modules := read();
  199. r37_test_cases := read();
  200. i := rds i;
  201. close i
  202. end;
  203. symbolic procedure build_reduce_modules names;
  204. <<
  205. !#if !*savedef
  206. !*savedef := t;
  207. !#else
  208. !*savedef := nil;
  209. !#endif
  210. load!-latest!-patches();
  211. !$reduce := "../../.."; % Indicates how "$reduce" expands in a filename
  212. in "$reduce/package.red"$
  213. window!-heading list!-to!-string explodec car names;
  214. package!-remake car names;
  215. if null (names := cdr names) then printc "Recompilation complete";
  216. !#if !*savedef
  217. if null names then restart!-csl 'begin
  218. !#else
  219. if null names then restart!-csl '(user begin)
  220. !#endif
  221. else restart!-csl('(remake build_reduce_modules), names) >>;
  222. symbolic procedure test_a_package names;
  223. begin
  224. scalar packge, logname, logtmp, logfile, start_time, start_gctime, gt;
  225. scalar oll;
  226. princ "TESTING: "; print car names;
  227. window!-heading list!-to!-string explodec car names;
  228. !*backtrace := nil;
  229. !*errcont := t;
  230. !*extraecho := t; % Ensure standard environment for the test...
  231. !*int := nil; % ... so that results are predictable.
  232. !$reduce := "../../..";
  233. packge := car names;
  234. verbos nil;
  235. load!-latest!-patches();
  236. semic!* := '!$;
  237. if boundp '!@log and stringp !@log then logname := !@log
  238. else logname := "log";
  239. logname := concat("$reduce/", concat(logname, "/"));
  240. logtmp := concat(logname, concat(car names, ".tmp"));
  241. logname := concat(logname, concat(car names,".rlg"));
  242. logfile := open(logtmp, 'output);
  243. in "$reduce/package.red"$
  244. begin
  245. scalar !*terminal!-io!*, !*standard!-output!*, !*error!-output!*,
  246. !*trace!-output!*, !*debug!-io!*, !*query!-io!*;
  247. !*terminal!-io!* := !*standard!-output!* := !*error!-output!* := logfile;
  248. !*trace!-output!* := !*debug!-io!* := !*query!-io!* := logfile;
  249. oll := linelength 80;
  250. princ date(); princ " run on "; printc cdr assoc('name, lispsystem!*);
  251. load!-package packge;
  252. if get(packge,'folder) then packge := get(packge,'folder);
  253. packge := concat("$reduce/packages/",
  254. concat(packge,
  255. concat("/",
  256. concat(car names,".tst"))));
  257. start_time := time();
  258. start_gctime := gctime();
  259. !*mode := 'algebraic;
  260. semic!* := '!;; % Specifically not a !$.
  261. !*extraecho := t; % Ensure standard environment for the test...
  262. !*int := nil; % ... so that results are predictable.
  263. in packge;
  264. terpri();
  265. terpri();
  266. prin2 "Time for test: ";
  267. prin2 (time() - start_time);
  268. prin2 " ms";
  269. if (gt := gctime() - start_gctime) > 0 then <<
  270. prin2 ", plus GC time: ";
  271. prin2 gt;
  272. prin2 " ms" >>;
  273. terpri();
  274. linelength oll
  275. end;
  276. close logfile;
  277. delete!-file logname;
  278. rename!-file(logtmp, logname);
  279. names := cdr names;
  280. if null names then restart!-csl t
  281. else restart!-csl('(remake test_a_package), names)
  282. end;
  283. symbolic procedure report_incomplete_tests names;
  284. begin
  285. % Displays information about what "complete_tests" would do
  286. scalar packge, tfile, logname;
  287. scalar date1, date2, date3;
  288. !$reduce := "../../..";
  289. semic!* := '!$;
  290. in "$reduce/package.red"$
  291. for each packge in names do <<
  292. tfile := packge;
  293. if get(packge,'folder) then tfile := get(packge,'folder);
  294. tfile := concat("$reduce/packages/",
  295. concat(tfile,
  296. concat("/",
  297. concat(packge,".tst"))));
  298. if boundp '!@log and stringp !@log then logname := !@log
  299. else logname := "log";
  300. logname := concat("$reduce/", concat(logname, "/"));
  301. logname := concat(logname, concat(packge,".rlg"));
  302. date1 := filedate "r37.img";
  303. date2 := filedate tfile;
  304. date3 := filedate logname;
  305. if null date1 then date1 := date();
  306. if null date2 then date2 := date();
  307. if null date3 or
  308. datelessp(date3, date1) or datelessp(date3, date2) then <<
  309. princ "NEED TO TEST: "; print packge >> >>
  310. end;
  311. symbolic procedure complete_tests names;
  312. begin
  313. % Just like the previous testing code except that logs that are already up
  314. % to date are not re-generated.
  315. scalar packge, tfile, logname, logfile, logtmp,
  316. start_time, start_gctime, gt;
  317. scalar date1, date2, date3, oll;
  318. !*backtrace := nil;
  319. !*errcont := t;
  320. !*extraecho := t; % Ensure standard environment for the test...
  321. !*int := nil; % ... so that results are predictable.
  322. verbos nil;
  323. load!-latest!-patches();
  324. !$reduce := "../../..";
  325. semic!* := '!$;
  326. in "$reduce/package.red"$
  327. top:
  328. tfile := packge := car names;
  329. if get(tfile,'folder) then tfile := get(tfile,'folder);
  330. tfile := concat("$reduce/packages/",
  331. concat(tfile,
  332. concat("/",
  333. concat(packge,".tst"))));
  334. if boundp '!@log and stringp !@log then logname := !@log
  335. else logname := "log";
  336. logname := concat("$reduce/", concat(logname, "/"));
  337. logtmp := concat(logname, concat(packge, ".tmp"));
  338. logname := concat(logname, concat(packge, ".rlg"));
  339. date1 := filedate "r37.img";
  340. date2 := filedate tfile;
  341. date3 := filedate logname;
  342. if null date1 then date1 := date();
  343. if null date2 then date2 := date();
  344. if null date3 or
  345. datelessp(date3, date1) or datelessp(date3, date2) then <<
  346. princ "TESTING: "; print packge;
  347. window!-heading list!-to!-string explodec packge;
  348. logfile := open(logtmp, 'output);
  349. start_time := time();
  350. start_gctime := gctime();
  351. begin
  352. scalar !*terminal!-io!*, !*standard!-output!*, !*error!-output!*,
  353. !*trace!-output!*, !*debug!-io!*, !*query!-io!*;
  354. !*terminal!-io!* := !*standard!-output!* := !*error!-output!* := logfile;
  355. !*trace!-output!* := !*debug!-io!* := !*query!-io!* := logfile;
  356. oll := linelength 80;
  357. princ date(); princ " run on ";
  358. printc cdr assoc('name, lispsystem!*);
  359. load!-package packge;
  360. !*mode := 'algebraic;
  361. semic!* := '!;; % Specifically not a !$.
  362. !*extraecho := t; % Ensure standard environment for the test...
  363. !*int := nil; % ... so that results are predictable.
  364. in tfile;
  365. terpri();
  366. terpri();
  367. prin2 "Time for test: ";
  368. prin2 (time() - start_time);
  369. prin2 " ms";
  370. if (gt := gctime() - start_gctime) > 0 then <<
  371. prin2 ", plus GC time: ";
  372. prin2 gt;
  373. prin2 " ms" >>;
  374. terpri();
  375. linelength oll
  376. end;
  377. close logfile;
  378. delete!-file logname;
  379. rename!-file(logtmp, logname) >>
  380. else if cdr names then <<
  381. names := cdr names;
  382. go to top >>;
  383. names := cdr names;
  384. if null names then restart!-csl t
  385. else restart!-csl('(remake complete_tests), names)
  386. end;
  387. symbolic procedure profile_compare_fn(p, q);
  388. (float caddr p/float cadr p) < (float caddr q/float cadr q);
  389. %
  390. % This function runs a test file and sorts out what the top 350
  391. % functions in it. It appends their names to "profile.dat".
  392. %
  393. % I need to talk a little about the interaction between profiling and
  394. % patching. Well firstly I arrange that whenever I run a profiling job
  395. % I rebuild REDUCE with the latest paches. This may involve re-compiling
  396. % the patches.red source. Thus when a test is run the current patches
  397. % will be in place. Patched functions are first defined with funny names
  398. % (including a hash based on their definition) and then copied into place
  399. % when a package is loaded. However MAPSTORE and the CSL instrumentation
  400. % attributes their cost to the hash-extended name even though the
  401. % functions may have been called via the simple one. Thus in the face
  402. % of patches one can expect the profile data to refer to some names that
  403. % are long and curious looking. Throughout all this I assume that there will
  404. % never be embarassing collisions in my hash functions.
  405. symbolic procedure profile_a_package names;
  406. begin
  407. scalar packge, oll, w, w1, w2;
  408. ensure_patches_are_up_to_date();
  409. princ "PROFILING: "; print car names;
  410. !*backtrace := nil;
  411. !*errcont := t;
  412. !*int := nil;
  413. !$reduce := "../../..";
  414. packge := car names;
  415. verbos nil;
  416. load!-latest!-patches();
  417. load!-package packge;
  418. semic!* := '!$;
  419. in "$reduce/package.red"$
  420. if get(packge,'folder) then packge := get(packge,'folder);
  421. packge := concat("$reduce/packages/",
  422. concat(packge,
  423. concat("/",
  424. concat(car names,".tst"))));
  425. oll := linelength 80;
  426. semic!* := '!;; % specifically not a !$.
  427. !*mode := 'algebraic;
  428. window!-heading list!-to!-string explodec car names;
  429. mapstore 4; % reset counts;
  430. in packge;
  431. terpri();
  432. w := sort(mapstore 2, function profile_compare_fn);
  433. w1 := nil;
  434. while w do <<
  435. w2 := get(caar w, '!*savedef);
  436. if eqcar(w2, 'lambda) then w1 := (caar w . md60 cdr w2 .
  437. cadar w . caddar w) . w1;
  438. w := cdr w >>;
  439. w := w1;
  440. % I collect the top 350 functions as used by each test, not because all
  441. % that many will be wanted but because I might as well record plenty
  442. % of information here and discard unwanted parts later on.
  443. for i := 1:349 do if w1 then w1 := cdr w1;
  444. if w1 then rplacd(w1, nil);
  445. % princ "MODULE "; prin car names; princ " suggests ";
  446. % print for each z in w collect car z;
  447. w1 := open("profile.dat", 'append);
  448. w1 := wrs w1;
  449. linelength 80;
  450. princ "("; prin car names; terpri();
  451. for each n in w do <<
  452. princ " ("; prin car n; princ " ";
  453. if posn() > 30 then << terpri(); ttab 30 >>;
  454. prin cadr n;
  455. % I also display the counts just to help me debug & for interest.
  456. princ " "; prin caddr n; princ " "; princ cdddr n;
  457. printc ")" >>;
  458. printc " )";
  459. terpri();
  460. close wrs w1;
  461. linelength oll;
  462. names := cdr names;
  463. if null names then restart!-csl t
  464. else restart!-csl('(remake profile_a_package), names)
  465. end;
  466. symbolic procedure trim_prefix(a, b);
  467. begin
  468. while a and b and car a = car b do <<
  469. a := cdr a;
  470. b := cdr b >>;
  471. if null a then return b
  472. else return nil
  473. end;
  474. fluid '(time_info);
  475. symbolic procedure read_file f1;
  476. begin
  477. % I take the view that I can afford to read the whole of a file into
  478. % memory at the start of processing. This makes life easier for me
  479. % and the REDUCE log files are small compared with current main memory sizes.
  480. scalar r, w, w1, n, x;
  481. scalar p1, p2, p3, p4, p5, p6, p7;
  482. % To make comparisons between my CSL logs and some of the Hearn "reference
  483. % logs", which are created using a different script, I will discard
  484. % lines that match certain patterns! Note that if the reference logs change
  485. % the particular tests I perform here could become out of date! Also if any
  486. % legitimate test output happened to match one of the following strings
  487. % I would lose out slightly.
  488. p1 := explodec "REDUCE 3.7,";
  489. p2 := explodec "1: 1:";
  490. p3 := explodec "2: 2: 2:";
  491. p4 := explodec "3: 3: "; % a prefix to first real line of output.
  492. p5 := explodec "4: 4: 4:";
  493. p6 := explodec "5: 5:";
  494. p7 := explodec "Quittin"; % nb left so that the "g" remains!
  495. % this is so that the match is detected.
  496. r := nil;
  497. n := 0;
  498. while not ((w := readline f1) = !$eof!$) do <<
  499. w1 := explodec w;
  500. if x := trim_prefix(p4, w1) then
  501. r := ((n := n + 1) . list!-to!-string x) . r
  502. else if trim_prefix(p1, w1) or
  503. trim_prefix(p2, w1) or
  504. trim_prefix(p3, w1) or
  505. trim_prefix(p5, w1) or
  506. trim_prefix(p6, w1) or
  507. trim_prefix(p7, w1) then nil
  508. else r := ((n := n + 1) . w) . r >>;
  509. w := r;
  510. % The text scanned for here is expected to match that generated by the
  511. % test script. I locate the last match in a file, extract the numbers
  512. % and eventually write them to log/times.log
  513. n := explodec "Time for test:";
  514. while w and null (x := trim_prefix(n, explodec cdar w)) do w := cdr w;
  515. if null w then <<
  516. time_info := nil;
  517. return reversip r >>;
  518. while eqcar(x, '! ) do x := cdr x;
  519. w := n := nil;
  520. while digit car x do << w := car x . w; x := cdr x >>;
  521. while eqcar(x, '! ) do x := cdr x;
  522. if x := trim_prefix(explodec "ms, plus GC time:", x) then <<
  523. while eqcar(x, '! ) do x := cdr x;
  524. while digit car x do << n := car x . n; x := cdr x >> >>;
  525. if null w then w := '(!0);
  526. if null n then n := '(!0);
  527. time_info := compress reverse w . compress reverse n;
  528. return reversip r;
  529. end;
  530. symbolic procedure in_sync(d1, n1, d2, n2);
  531. begin
  532. for i := 1:n1 do if d1 then <<
  533. d1 := cdr d1 >>;
  534. for i := 1:n2 do if d2 then <<
  535. d2 := cdr d2 >>;
  536. if null d1 then return null d2
  537. else if null d2 then return nil;
  538. % Here I insist on 3 lines that agree before I count a match as
  539. % having been re-established.
  540. if not (cdar d1 = cdar d2) then return nil;
  541. d1 := cdr d1; d2 := cdr d2;
  542. if null d1 then return null d2
  543. else if null d2 then return nil;
  544. if not (cdar d1 = cdar d2) then return nil;
  545. d1 := cdr d1; d2 := cdr d2;
  546. if null d1 then return null d2
  547. else if null d2 then return nil;
  548. if not (cdar d1 = cdar d2) then return nil;
  549. d1 := cdr d1; d2 := cdr d2;
  550. if null d1 then return null d2
  551. else if null d2 then return nil
  552. else return t
  553. end;
  554. fluid '(time_data time_ratio gc_time_ratio log_count);
  555. symbolic procedure file_compare(f1, f2, name);
  556. begin
  557. scalar i, j, d1, d2, t1, gt1, t2, gt2, time_info;
  558. d1 := read_file f1;
  559. if null time_info then t1 := gt1 := 0
  560. else << t1 := car time_info; gt1 := cdr time_info >>;
  561. d2 := read_file f2;
  562. if null time_info then t2 := gt2 := 0
  563. else << t2 := car time_info; gt2 := cdr time_info >>;
  564. i := wrs time_data;
  565. j := set!-print!-precision 3;
  566. prin name;
  567. ttab 20;
  568. if zerop t1 then princ "---"
  569. else << prin t1; ttab 30; prin gt1 >>;
  570. ttab 40;
  571. if zerop t2 then princ "---"
  572. else << prin t2; ttab 50; prin gt2 >>;
  573. ttab 60;
  574. if zerop t1 or zerop t2 then princ "*** ***"
  575. else begin
  576. scalar r1, gr1;
  577. r1 := float t1 / float t2;
  578. gr1 := float (t1+gt1)/float (t2+gt2);
  579. time_ratio := time_ratio * r1;
  580. gc_time_ratio := gc_time_ratio * gr1;
  581. log_count := log_count + 1;
  582. prin r1;
  583. ttab 70;
  584. prin gr1 end;
  585. terpri();
  586. set!-print!-precision j;
  587. wrs i;
  588. % I can not see a neat way to get a "structured" control structure
  589. % here easily. Ah well, drop back to GOTO statements!
  590. top:
  591. if null d1 then <<
  592. if d2 then terpri();
  593. i := 0;
  594. while d2 and i < 20 do <<
  595. princ "REF "; princ caar d2; princ ":"; ttab 10; printc cdar d2;
  596. d2 := cdr d2;
  597. i := i + 1 >>;
  598. if d2 then printc "...";
  599. return >>;
  600. if null d2 then <<
  601. i := 0;
  602. while d1 and i < 20 do <<
  603. princ "NEW "; princ caar d1; princ ":"; ttab 10; printc cdar d1;
  604. d1 := cdr d1;
  605. i := i + 1 >>;
  606. if d1 then printc "...";
  607. return >>;
  608. if cdar d1 = cdar d2 then <<
  609. d1 := cdr d1;
  610. d2 := cdr d2;
  611. go to top >>;
  612. % I will first see if there are just a few blank lines inserted into
  613. % one or other file. This special case is addressed here because it
  614. % appears more common a possibility than I had expected.
  615. if cdar d1 = "" and cdr d1 and cdadr d1 = cdar d2 then <<
  616. princ "NEW "; princ caar d1; princ ":"; ttab 10; printc cdar d1;
  617. d1 := cdr d1;
  618. go to top >>
  619. else if cdar d1 = "" and cdr d1 and cdadr d1 = "" and cddr d1 and
  620. cdaddr d1 = cdar d2 then <<
  621. princ "NEW "; princ caar d1; princ ":"; ttab 10; printc cdar d1;
  622. d1 := cdr d1;
  623. princ "NEW "; princ caar d1; princ ":"; ttab 10; printc cdar d1;
  624. d1 := cdr d1;
  625. go to top >>
  626. else if cdar d2 = "" and cdr d2 and cdadr d2 = cdar d1 then <<
  627. princ "REF "; princ caar d2; princ ":"; ttab 10; printc cdar d2;
  628. d2 := cdr d2;
  629. go to top >>
  630. else if cdar d2 = "" and cdr d2 and cdadr d2 = "" and cddr d2 and
  631. cdaddr d2 = cdar d1 then <<
  632. princ "REF "; princ caar d2; princ ":"; ttab 10; printc cdar d2;
  633. d2 := cdr d2;
  634. princ "REF "; princ caar d2; princ ":"; ttab 10; printc cdar d2;
  635. d2 := cdr d2;
  636. go to top >>;
  637. i := 1;
  638. seek_rematch:
  639. j := 0;
  640. inner:
  641. if in_sync(d1, i, d2, j) then <<
  642. terpri();
  643. for k := 1:i do <<
  644. princ "NEW "; princ caar d1; princ ":"; ttab 10; printc cdar d1;
  645. d1 := cdr d1 >>;
  646. for k := 1:j do <<
  647. princ "REF "; princ caar d2; princ ":"; ttab 10; printc cdar d2;
  648. d2 := cdr d2 >>;
  649. % Should be in step again here.
  650. if null d1 then return
  651. else go to top >>;
  652. j := j + 1;
  653. i := i - 1;
  654. if i >= 0 then go to inner;
  655. i := j;
  656. % I am prepared to seek 80 lines ahead on each side before I give up.
  657. if i < 80 then goto seek_rematch;
  658. terpri();
  659. i := 0;
  660. while d2 and i < 20 do <<
  661. princ "REF "; princ caar d2; princ ":"; ttab 10; printc cdar d2;
  662. d2 := cdr d2;
  663. i := i+1 >>;
  664. if d2 then printc "...";
  665. i := 0;
  666. while d1 and i < 20 do <<
  667. princ "NEW "; princ caar d1; princ ":"; ttab 10; printc cdar d1;
  668. d1 := cdr d1;
  669. i := i+1 >>;
  670. if d1 then printc "...";
  671. printc "Comparison failed."
  672. end;
  673. fluid '(which_module);
  674. symbolic procedure check_a_package;
  675. begin
  676. scalar oll, names, p1, mylogname, mylog, reflogname, reflog,
  677. time_data, time_ratio, gc_time_ratio, log_count;
  678. !$reduce := "../../..";
  679. get_configuration_data();
  680. if boundp 'which_module and which_module and
  681. not (which_module = "") then <<
  682. names := compress explodec which_module;
  683. if member(names, r37_test_cases) then names := list names
  684. else error(0, list("unknown module to check", which_module)) >>
  685. else names := r37_test_cases;
  686. semic!* := '!$;
  687. in "$reduce/package.red"$
  688. % I write a summary of timing information into log/times.log
  689. time_data := open("log/times.log", 'output);
  690. p1 := wrs time_data;
  691. princ "MODULE";
  692. ttab 20; princ "Local"; ttab 30; princ "(GC)";
  693. ttab 40; princ "Reference"; ttab 50; princ "(GC)";
  694. ttab 60; princ "Ratio"; ttab 70; printc "inc GC";
  695. wrs p1;
  696. terpri();
  697. oll := linelength 100;
  698. printc "=== Comparison results ===";
  699. time_ratio := gc_time_ratio := 1.0; log_count := 0;
  700. for each packge in names do <<
  701. terpri();
  702. princ "CHECKING: "; print packge;
  703. if boundp '!@log and stringp !@log then logname := !@log
  704. else logname := "log";
  705. logname := concat("$reduce/", concat(logname, "/"));
  706. mylogname := concat(logname, concat(packge, ".rlg"));
  707. if get(packge,'folder) then p1 := get(packge,'folder)
  708. else p1 := packge;
  709. reflogname := concat("$reduce/packages/",
  710. concat(p1,
  711. concat("/",
  712. concat(packge,".rlg"))));
  713. mylog := errorset(list('open, mkquote mylogname, ''input), nil, nil);
  714. reflog := errorset(list('open, mkquote reflogname, ''input), nil, nil);
  715. if errorp mylog then <<
  716. if not errorp reflog then close car reflog;
  717. princ "No current log in "; print mylogname >>
  718. else if errorp reflog then <<
  719. close car mylog;
  720. princ "No reference log in "; print reflogname >>
  721. else <<
  722. mylog := car mylog; reflog := car reflog;
  723. file_compare(mylog, reflog, packge);
  724. close mylog;
  725. close reflog >> >>;
  726. time_data := wrs time_data;
  727. if not zerop log_count then <<
  728. time_ratio := expt(time_ratio, 1.0/log_count);
  729. gc_time_ratio := expt(gc_time_ratio, 1.0/log_count);
  730. terpri();
  731. p1 := set!-print!-precision 3;
  732. princ "Over "; prin log_count; princ " tests the speed ratio was ";
  733. print time_ratio;
  734. princ " (or ";
  735. prin gc_time_ratio;
  736. printc " is garbage collection costs are included)";
  737. set!-print!-precision p1 >>;
  738. close wrs time_data;
  739. linelength oll;
  740. end;
  741. faslend;
  742. faslout 'cslhelp;
  743. module cslhelp;
  744. global '(!*force);
  745. flag('(force),'switch);
  746. flag('(on),'eval);
  747. on force;
  748. symbolic procedure formhelp(u,vars,mode);
  749. list('help, 'list . for each x in cdr u collect mkquote x);
  750. if member('help, lispsystem!*) then <<
  751. put('help, 'stat, 'rlis);
  752. flag('(help), 'go);
  753. put('help, 'formfn, 'formhelp) >>;
  754. off force;
  755. remflag('(on),'eval);
  756. endmodule;
  757. faslend;
  758. load!-module 'remake;
  759. ensure_patches_are_up_to_date();
  760. << initreduce();
  761. date!* := "Bootstrap version";
  762. checkpoint('begin, "REDUCE 3.7") >>;
  763. !#if (not !*savedef)
  764. load!-module 'user;
  765. !#endif
  766. in "$reduce/package.red"$
  767. package!-remake2(prolog_file,'support);
  768. package!-remake2(rend_file,'support);
  769. package!-remake2('entry,'support);
  770. package!-remake2('remake,'support);
  771. % The next lines hava LOTS of hidden depth! They restart CSL repeatedly
  772. % so that each of the modules that has to be processed gets dealt with in
  773. % a fresh uncluttered environment. The list of modules is fetched from
  774. % a configuration file which must have 3 s-expressions in it. The first
  775. % is a list of basic modules that must be built to get a core version of
  776. % REDUCE. The second list identifies modules that can be built one the core
  777. % is ready for use, while the last list indicates which modules have
  778. % associated test scripts.
  779. %
  780. % when the modules have been rebuild the system does a restart that
  781. % kicks it back into REDUCE by calling begin(). This then continues
  782. % reading from the stream that had been the standard input when this
  783. % job started. Thus this script MUST be invoked as
  784. % csl -oslowr37.img -z build37.lsp -l log/build37.log
  785. % with the file build37.lsp specified on the command line in the call. It
  786. % will not work if you start csl manually and then do a (rdf ..) [say]
  787. % on build37.lsp. I told you that it was a little delicate.
  788. get_configuration_data();
  789. build_reduce_modules r37_base_modules;
  790. % Now I want to do a cold-start so that I can create a sensible
  791. % image for use in the subsequent build steps. This image should not
  792. % contain ANYTHING extraneous.
  793. symbolic restart!-csl nil;
  794. (setq !*savedef (lessp (cdr (assoc 'c!-code lispsystem!*)) 20))
  795. (cond ((null !*savedef) (load!-module 'user)))
  796. (load!-module 'cslcompat)
  797. (setq !*comp nil)
  798. (load!-module 'module) % Definition of load_package, etc.
  799. (load!-module 'cslprolo) % CSL specific code.
  800. (setq loaded!-packages!* '(cslcompat user cslprolo))
  801. % NB I will re-load the "patches" module when REDUCE is started
  802. % if there is a version newer than the one I load up here. Note that
  803. % if there had not been a "patches.red" file I will not have a module to load
  804. % here.
  805. (cond
  806. ((modulep 'patches) (load!-module 'patches)))
  807. (load!-package 'rlisp)
  808. (load!-package 'cslrend)
  809. (load!-package 'poly)
  810. (load!-package 'arith)
  811. (load!-package 'alg)
  812. (load!-package 'mathpr)
  813. (load!-package 'entry)
  814. (write!-help!-module "../util/r37.inf" nil)
  815. (load!-module 'cslhelp)
  816. (setq version!* "REDUCE 3.7")
  817. (initreduce)
  818. (setq date!* "15-Jan-99")
  819. (setq no_init_file nil)
  820. (checkpoint 'begin (bldmsg "%w, %w ..." version!* date!*))
  821. (setq no_init_file t)
  822. (begin)
  823. %
  824. % See the fairly length comments given a bit earlier about the
  825. % delicacy of the next few lines!
  826. %
  827. symbolic;
  828. load!-module 'remake;
  829. get_configuration_data();
  830. build_reduce_modules r37_extra_modules;
  831. % At this stage I have a complete workable REDUCE. If built using a
  832. % basic CSL (I call it "slowr37" here) nothing has been compiled into C
  833. % (everything is bytecoded), and it is big because it has retained all
  834. % Lisp source code in the image file. If however I built using a version
  835. % of CSL ("r37") that did have things compiled into C then these will
  836. % be exploited and the original Lisp sourtce will be omitted from the
  837. % image, leaving a production version.
  838. bye;