buildreduce.lsp 59 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771
  1. % "buildreduce.lsp" Copyright (C) Codemist 2016-2021
  2. %
  3. % Build a CSL REDUCE.
  4. %
  5. % Depending on how this file is used it will EITHER create a bootstrap
  6. % version of REDUCE or a full and optimised one.
  7. %
  8. % The behaviour is determined by whether the version of CSL used to
  9. % run it has a full complement of functions in the modules u01.c to u60.c.
  10. %
  11. %
  12. % bootstrapreduce -z buildreduce.lsp -D@srcdir=<DIR> -D@reduce=<DIR>
  13. %
  14. % Builds a system "bootstrapreduce.img" that does not depend on any
  15. % custom C code. The main use of this slow system is for profiling
  16. % REDUCE and then compiling the hot-spots into C. Once that has been
  17. % done this image is logically unnecessary.
  18. %
  19. %
  20. % reduce -z buildreduce.lsp -D@srcdir=<DIR> -D@reduce=<dir>
  21. %
  22. % Here the files u01.c to u60.c and u01.lsp to u60.lsp must already
  23. % have been created, and that the reduce executable has them compiled in.
  24. % The REDUCE source files that are compiled *MUST* be the same as those used
  25. % to create this C code.
  26. % Author: Anthony C. Hearn, Stanley L. Kameny and Arthur Norman
  27. % $Id: buildreduce.lsp 5439 2020-10-19 07:24:47Z arthurcnorman $
  28. (cond
  29. ((eq 'vsl (car lispsystem!*)) (rdf "$srcdir/vsl.lsp")))
  30. (verbos 3)
  31. (window!-heading "basic CSL")
  32. (make!-special '!*savedef)
  33. (make!-special '!*backtrace)
  34. % "-Dbootstrap" can force !*savedef even in an embedded world.
  35. (setq !*savedef (and (or (boundp 'bootstrap)
  36. (not (memq 'embedded lispsystem!*)))
  37. (zerop (cdr (assoc 'c!-code lispsystem!*)))))
  38. (make!-special '!*noinlines)
  39. (prog (w)
  40. (setq w (errorset 'noinlines nil nil))
  41. (setq !*noinlines (and (not (atom w)) (car w)))
  42. (print (list '!*noinlines 'set 'to !*noinlines)))
  43. % A command-line flag "-g" sets the variable !*backtrace and so can activate
  44. % this. But beware that otherwise !*backtrace may be an unset variable, and
  45. % so I use an errorset to protect myself.
  46. (prog (w)
  47. (setq w (errorset '!*backtrace nil nil))
  48. (cond
  49. ((or (atom w) (null (car w))) (setq !*backtrace nil))
  50. (t (enable!-errorset 3 3)
  51. (setq !*backtrace t))))
  52. (cond
  53. (!*backtrace (setq !*echo t)))
  54. (make!-special '!*native_code)
  55. (setq !*native_code nil)
  56. (cond ((and (null !*savedef)
  57. (null (memq 'jlisp lispsystem!*))
  58. (or (boundp 'force_c_code)
  59. (null (memq 'embedded lispsystem!*)))) (progn
  60. % This is all to do with getting stuff that was compiled into C++ hooked in
  61. (de c!:install (name env c!-version !&optional c1)
  62. (cond
  63. (c1 (check!-c!-code name env c!-version c1))
  64. (t (progn
  65. (put name 'c!-version c!-version)
  66. (cond (env (prog (v n)
  67. (setq v (mkvect (sub1 (length env))))
  68. (setq n 0)
  69. top (cond
  70. ((null env) (progn
  71. (put name 'funarg v)
  72. (return (symbol!-set!-env name v)))))
  73. (putv v n (car env))
  74. (setq n (add1 n))
  75. (setq env (cdr env))
  76. (go top))))
  77. name))))
  78. (prog (name names)
  79. (setq names '(
  80. "u01.lsp" "u02.lsp" "u03.lsp" "u04.lsp" "u05.lsp"
  81. "u06.lsp" "u07.lsp" "u08.lsp" "u09.lsp" "u10.lsp"
  82. "u11.lsp" "u12.lsp" "u13.lsp" "u14.lsp" "u15.lsp"
  83. "u16.lsp" "u17.lsp" "u18.lsp" "u19.lsp" "u20.lsp"
  84. "u21.lsp" "u22.lsp" "u23.lsp" "u24.lsp" "u25.lsp"
  85. "u26.lsp" "u27.lsp" "u28.lsp" "u29.lsp" "u30.lsp"
  86. "u31.lsp" "u32.lsp" "u33.lsp" "u34.lsp" "u35.lsp"
  87. "u36.lsp" "u37.lsp" "u38.lsp" "u39.lsp" "u40.lsp"
  88. "u41.lsp" "u42.lsp" "u43.lsp" "u44.lsp" "u45.lsp"
  89. "u46.lsp" "u47.lsp" "u48.lsp" "u49.lsp" "u50.lsp"
  90. "u51.lsp" "u52.lsp" "u53.lsp" "u54.lsp" "u55.lsp"
  91. "u56.lsp" "u57.lsp" "u58.lsp" "u59.lsp" "u60.lsp"))
  92. top(cond ((null names) (return nil)))
  93. (setq name (car names))
  94. (setq names (cdr names))
  95. % If I am "generic" I will find u01.lsp etc in the current directory...
  96. (cond
  97. ((or (memq 'embedded lispsystem!*)
  98. (not (memq 'generic lispsystem!*)))
  99. (setq name (compress (cons '!"
  100. (append (explodec "$reduce/cslbuild/generated-c/")
  101. (cdr (explode name))))))))
  102. (rdf name)
  103. (go top)) )))
  104. (fluid '(!*nocompile))
  105. (setq !*nocompile nil)
  106. (cond
  107. ((and (boundp 'interpreted) (eq (compress (explodec interpreted)) 'yes))
  108. (setq !*nocompile t)))
  109. (cond
  110. ((memq 'vsl lispsystem!*)
  111. (faslout 'cslcompat)
  112. (rdf "$srcdir/vsl.lsp")
  113. (faslend)
  114. )
  115. (t (rdf "$srcdir/fastgets.lsp")
  116. (rdf "$srcdir/compat.lsp")
  117. (rdf "$srcdir/extras.lsp")
  118. (rdf (cond
  119. ((memq 'jlisp lispsystem!*) "$srcdir/compiler-for-jlisp.lsp")
  120. (t "$srcdir/compiler.lsp")))
  121. (progn (terpri)
  122. (princ "### !*nocompile = ")
  123. (print !*nocompile)
  124. nil)
  125. (setq !*comp (null !*nocompile))
  126. % Compile some important things first to improve bootstrapping speed.
  127. (cond
  128. ((null !*nocompile)
  129. (compile '(
  130. s!:improve s!:literal_order s!:comval s!:outopcode0
  131. s!:plant_basic_block s!:remlose s!:islocal
  132. s!:is_lose_and_exit s!:comatom s!:destination_label
  133. s!:record_literal s!:resolve_labels s!:expand_jump
  134. s!:outopcode1lit stable!-sortip s!:iseasy s!:outjump
  135. s!:add_pending s!:comcall s!:resolve_literals))
  136. (compile!-all)))
  137. % Tidy up be deleting any modules that are left over in this image
  138. (dolist (a (library!-members)) (delete!-module a))
  139. % Build fasl files for the compatibility code and the two
  140. % versions of the compiler.
  141. (faslout 'cslcompat)
  142. (rdf "$srcdir/fastgets.lsp")
  143. (rdf "$srcdir/compat.lsp")
  144. (rdf "$srcdir/extras.lsp")
  145. (faslend)
  146. (faslout 'compiler)
  147. (rdf (cond
  148. ((memq 'jlisp lispsystem!*) "$srcdir/compiler-for-jlisp.lsp")
  149. (t "$srcdir/compiler.lsp")))
  150. (faslend)
  151. ))
  152. (setq !*comp (null !*nocompile))
  153. (de concat (u v)
  154. (compress (cons '!" (append (explode2 u)
  155. (nconc (explode2 v) (list '!"))))))
  156. (global '(oldchan!*))
  157. (setq prolog_file 'cslprolo)
  158. (setq rend_file 'cslrend)
  159. (setq !*argnochk t)
  160. (setq !*int nil) % Prevents input buffer being saved.
  161. (setq !*msg nil)
  162. (window!-heading "bootstrap RLISP")
  163. % This is dervived fron the Standard LISP BOOT File.
  164. % Author: Anthony C. Hearn.
  165. % Copyright (c) 1991 RAND. All Rights Reserved.
  166. (fluid '(fname!* !*blockp !*lower !*mode))
  167. (global '(oldchan!*))
  168. (fluid '(!*raise !*lower))
  169. (global '(crchar!* cursym!* nxtsym!* ttype!* !$eol!$))
  170. (put '!; 'switch!* '(nil !*semicol!*))
  171. (put '!( 'switch!* '(nil !*lpar!*))
  172. (put '!) 'switch!* '(nil !*rpar!*))
  173. (put '!, 'switch!* '(nil !*comma!*))
  174. (put '!. 'switch!* '(nil cons))
  175. (put '!= 'switch!* '(nil equal))
  176. (put '!: 'switch!* '(((!= nil setq)) !*colon!*))
  177. (put '!< 'switch!* '(((!= nil leq) (!< nil !*lsqbkt!*)) lessp))
  178. (put '!> 'switch!* '(((!= nil geq) (!> nil !*rsqbkt!*)) greaterp))
  179. % When the full parser is loaded the function mkprec() will reset all
  180. % these precedences. Until then please parenthesize expressions carefully.
  181. (put '!*comma!* 'infix 1)
  182. (put 'setq 'infix 2)
  183. (put 'cons 'infix 3)
  184. (put 'equal 'infix 4)
  185. (put 'eq 'infix 5)
  186. (flag '(!*comma!*) 'nary)
  187. (flag '(!*colon!* !*semicol!* end then else) 'delim)
  188. (put 'begin 'stat 'blockstat)
  189. (put 'if 'stat 'ifstat)
  190. (put 'symbolic 'stat 'procstat)
  191. (de begin2 nil
  192. (prog nil
  193. (setq cursym!* '!*semicol!*)
  194. a (cond
  195. ((eq cursym!* 'end) (progn (rds oldchan!*) (return nil)))
  196. (t (prin2 (errorset '(eval (form (xread nil))) t t)) ))
  197. (go a)))
  198. (de form (u) u)
  199. (de xread (u) (progn (scan) (xread1 u)))
  200. (de xread1 (u)
  201. (prog (v w x y z z2)
  202. a (setq z cursym!*)
  203. a1 (cond
  204. ((or (null (atom z)) (numberp z)) (setq y nil))
  205. ((flagp z 'delim) (go end1))
  206. ((eq z '!*lpar!*) (go lparen))
  207. ((eq z '!*rpar!*) (go end1))
  208. ((and w (setq y (get z 'infix))) (go infx))
  209. ((setq y (get z 'stat)) (go stat)))
  210. a3 (setq w (cons z w))
  211. next (setq z (scan))
  212. (go a1)
  213. lparen(setq y nil)
  214. (cond
  215. ((eq (scan) '!*rpar!*)
  216. (and w (setq w (cons (list (car w)) (cdr w)))) )
  217. ((eqcar (setq z (xread1 'paren)) '!*comma!*)
  218. (setq w (cons (cons (car w) (cdr z)) (cdr w))))
  219. (t (go a3)))
  220. (go next)
  221. infx (setq z2 (car w))
  222. un1 (setq w (cdr w))
  223. (cond
  224. ((null w) (go un2))
  225. (t (setq z2 (cons (car w) (list z2)))) )
  226. (go un1)
  227. un2 (setq v (cons z2 v))
  228. preced(cond ((null x) (go pr4)) ((lessp y (car (car x))) (go pr2)))
  229. pr1 (setq x (cons (cons y z) x))
  230. (go next)
  231. pr2 (setq v
  232. (cons
  233. (cond
  234. ((and (eqcar (car v) (cdar x)) (flagp (cdar x) 'nary))
  235. (cons (cdar x) (cons (cadr v) (cdar v))))
  236. (t (cons (cdar x) (list (cadr v) (car v)))) )
  237. (cdr (cdr v))))
  238. (setq x (cdr x))
  239. (go preced)
  240. stat (setq w (cons (eval (list y)) w))
  241. (setq y nil)
  242. (go a)
  243. end1 (cond
  244. ((and (and (null v) (null w)) (null x)) (return nil))
  245. (t (setq y 0)))
  246. (go infx)
  247. pr4 (cond ((null (equal y 0)) (go pr1)) (t (return (car v)))) ))
  248. (de eqcar (u v) (and (null (atom u)) (eq (car u) v)))
  249. (de mksetq (u v) (list 'setq u v))
  250. (de rread nil
  251. (prog (x)
  252. (setq x (token))
  253. (return
  254. (cond
  255. ((and (equal ttype!* 3) (eq x '!()) (rrdls))
  256. (t x)))) )
  257. (de rrdls nil
  258. (prog (x r)
  259. a (setq x (rread))
  260. (cond
  261. ((null (equal ttype!* 3)) (go b))
  262. ((eq x '!)) (return (reverse r))) % REVERSIP not yet defined.
  263. ((null (eq x '!.)) (go b)))
  264. (setq x (rread))
  265. (token)
  266. (return (nconc (reverse r) x))
  267. b (setq r (cons x r))
  268. (go a)))
  269. (de token nil
  270. (prog (x y z)
  271. (setq x crchar!*)
  272. a (cond
  273. ((seprp x) (go sepr))
  274. ((digit x) (go number))
  275. ((liter x) (go letter))
  276. ((eq x '!%) (go coment))
  277. ((eq x '!!) (go escape))
  278. ((eq x '!') (go quote))
  279. ((eq x '!") (go string)))
  280. (setq ttype!* 3)
  281. (cond ((delcp x) (go d)))
  282. (setq nxtsym!* x)
  283. a1 (setq crchar!* (readch))
  284. (go c)
  285. escape(setq y (cons x y))
  286. (setq z (cons !*raise !*lower))
  287. (setq !*raise (setq !*lower nil))
  288. (setq x (readch))
  289. (setq !*raise (car z))
  290. (setq !*lower (cdr z))
  291. letter(setq ttype!* 0)
  292. let1 (setq y (cons x y))
  293. (cond
  294. ((or (digit (setq x (readch))) (liter x)) (go let1))
  295. ((eq x '!!) (go escape)))
  296. (setq nxtsym!* (intern (compress (reverse y))))
  297. b (setq crchar!* x)
  298. c (return nxtsym!*)
  299. number(setq ttype!* 2)
  300. num1 (setq y (cons x y))
  301. (cond ((digit (setq x (readch))) (go num1)))
  302. (setq nxtsym!* (compress (reverse y)))
  303. (go b)
  304. quote (setq crchar!* (readch))
  305. (setq nxtsym!* (list 'quote (rread)))
  306. (setq ttype!* 4)
  307. (go c)
  308. string(prog (raise !*lower)
  309. (setq raise !*raise)
  310. (setq !*raise nil)
  311. strinx(setq y (cons x y))
  312. (cond ((null (eq (setq x (readch)) '!")) (go strinx)))
  313. (setq y (cons x y))
  314. (setq nxtsym!* (mkstrng (compress (reverse y))))
  315. (setq !*raise raise))
  316. (setq ttype!* 1)
  317. (go a1)
  318. coment(cond ((null (eq (readch) !$eol!$)) (go coment)))
  319. sepr (setq x (readch))
  320. (go a)
  321. d (setq nxtsym!* x)
  322. (setq crchar!* '! )
  323. (go c)))
  324. (setq crchar!* '! )
  325. (de delcp (u) (or (eq u '!;) (eq u '!$)))
  326. (de mkstrng (u) u)
  327. (de seprp (u) (or (eq u blank) (eq u tab) (eq u !$eol!$)))
  328. (de scan nil
  329. (prog (x y)
  330. (cond ((null (eq cursym!* '!*semicol!*)) (go b)))
  331. a (setq nxtsym!* (token))
  332. b (cond
  333. ((or (null (atom nxtsym!*)) (numberp nxtsym!*)) (go l))
  334. ((and (setq x (get nxtsym!* 'newnam)) (setq nxtsym!* x))
  335. (go b))
  336. ((eq nxtsym!* 'comment) (go comm))
  337. ((and
  338. (eq nxtsym!* '!')
  339. (setq cursym!* (list 'quote (rread))))
  340. (go l1))
  341. ((null (setq x (get nxtsym!* 'switch!*))) (go l))
  342. ((eq (cadr x) '!*semicol!*)
  343. (return (setq cursym!* (cadr x)))) )
  344. sw1 (setq nxtsym!* (token))
  345. (cond
  346. ((or
  347. (null (car x))
  348. (null (setq y (assoc nxtsym!* (car x)))) )
  349. (return (setq cursym!* (cadr x)))) )
  350. (setq x (cdr y))
  351. (go sw1)
  352. comm (cond ((eq (readch) '!;) (setq crchar!* '! )) (t (go comm)))
  353. (go a)
  354. l (setq cursym!*
  355. (cond
  356. ((null (eqcar nxtsym!* 'string)) nxtsym!*)
  357. (t (cons 'quote (cdr nxtsym!*)))) )
  358. l1 (setq nxtsym!* (token))
  359. (return cursym!*)))
  360. (de ifstat nil
  361. (prog (condx condit)
  362. a (setq condx (xread t))
  363. (setq condit (nconc condit (list (list condx (xread t)))) )
  364. (cond
  365. ((null (eq cursym!* 'else)) (go b))
  366. ((eq (scan) 'if) (go a))
  367. (t (setq condit
  368. (nconc condit (list (list t (xread1 t)))) )))
  369. b (return (cons 'cond condit))))
  370. (de procstat nil
  371. (prog (x y)
  372. (cond ((eq cursym!* 'symbolic) (scan)))
  373. (cond
  374. ((eq cursym!* '!*semicol!*)
  375. (return (null (setq !*mode 'symbolic)))) )
  376. (setq fname!* (scan))
  377. (cond ((atom (setq x (xread1 nil))) (setq x (list x))))
  378. (setq y (xread nil))
  379. (cond ((flagp (car x) 'lose) (return nil)))
  380. (putd (car x) 'expr (list 'lambda (cdr x) y))
  381. (setq fname!* nil)
  382. (return (list 'quote (car x)))) )
  383. (de blockstat nil
  384. (prog (x hold varlis !*blockp)
  385. a0 (setq !*blockp t)
  386. (scan)
  387. (cond
  388. ((null (or (eq cursym!* 'integer) (eq cursym!* 'scalar)))
  389. (go a)))
  390. (setq x (xread nil))
  391. (setq varlis
  392. (nconc
  393. (cond ((eqcar x '!*comma!*) (cdr x)) (t (list x)))
  394. varlis))
  395. (go a0)
  396. a (setq hold (nconc hold (list (xread1 nil))))
  397. (setq x cursym!*)
  398. (scan)
  399. (cond ((not (eq x 'end)) (go a)))
  400. (return (mkprog varlis hold))))
  401. (de mkprog (u v) (cons 'prog (cons u v)))
  402. (de gostat nil
  403. (prog (x) (scan) (setq x (scan)) (scan) (return (list 'go x))))
  404. (put 'go 'stat 'gostat)
  405. (de rlis nil
  406. (prog (x)
  407. (setq x cursym!*)
  408. (return (list x (list 'quote (list (xread t)))))))
  409. (de endstat nil (prog (x) (setq x cursym!*) (scan) (return (list x))))
  410. % It is only a rather small number of lines of code to support
  411. % both << >> blocks and WHILE statements here, and doing so makes
  412. % it possible to write the full implementation of RLISP in a much
  413. % more civilised way. What I put in here is a little more than is used
  414. % to start with, but matches the eventual implementation. Eg the 'go
  415. % and 'nodel flags are not relevant until the read parser has been loaded.
  416. (de readprogn nil
  417. (prog (lst)
  418. a (setq lst (cons (xread 'group) lst))
  419. (cond ((null (eq cursym!* '!*rsqbkt!*)) (go a)))
  420. (scan)
  421. (return (cons 'progn (reverse lst)))))
  422. (put '!*lsqbkt!* 'stat 'readprogn)
  423. (flag '(!*lsqbkt!*) 'go)
  424. (flag '(!*rsqbkt!*) 'delim)
  425. (flag '(!*rsqbkt!*) 'nodel)
  426. (de whilstat ()
  427. (prog (!*blockp bool bool2)
  428. (cond
  429. ((flagp 'do 'delim) (setq bool2 t))
  430. (t (flag '(do) 'delim)))
  431. (setq bool (xread t))
  432. (cond
  433. (bool2 (remflag '(do) 'delim)))
  434. (cond
  435. ((not (eq cursym!* 'do)) (symerr 'while t)))
  436. (return (list 'while bool (xread t)))))
  437. (dm while (u)
  438. (prog (body bool lab)
  439. (setq bool (cadr u))
  440. (setq body (caddr u))
  441. (setq lab 'whilelabel)
  442. (return (list
  443. 'prog nil
  444. lab (list 'cond
  445. (list (list 'not bool) '(return nil)))
  446. body
  447. (list 'go lab)))))
  448. (put 'while 'stat 'whilstat)
  449. (flag '(while) 'nochange)
  450. (de repeatstat ()
  451. (prog (!*blockp body bool)
  452. (cond
  453. ((flagp 'until 'delim) (setq bool t))
  454. (t (flag '(until) 'delim)))
  455. (setq body (xread t))
  456. (cond
  457. ((null bool) (remflag '(until) 'delim)))
  458. (cond
  459. ((not (eq cursym!* 'until)) (symerr 'repeat t)))
  460. (return (list 'repeat body (xread t)))))
  461. (dm repeat (u)
  462. (progn (terpri) (print (prog (body bool lab)
  463. (setq body (cadr u))
  464. (setq bool (caddr u))
  465. (setq lab 'repeatlabel)
  466. (return (list
  467. 'prog nil
  468. lab body
  469. (list 'cond
  470. (list (list 'not bool) (list 'go lab))))))))))
  471. (put 'repeat 'stat 'repeatstat)
  472. (flag '(repeat) 'nochange)
  473. % Now we have just enough to be able to start to express ourselves in
  474. % (a subset of) rlisp.
  475. (begin2)
  476. rds(xxx := open("$reduce/packages/support/build.red", 'input));
  477. (close xxx)
  478. (load!-package!-sources prolog_file 'support)
  479. (load!-package!-sources 'revision 'support)
  480. (cond (!*backtrace (setq !*echo t)))
  481. (load!-package!-sources 'rlisp 'rlisp)
  482. (load!-package!-sources 'smacros 'support)
  483. (load!-package!-sources rend_file 'support)
  484. (load!-package!-sources 'poly 'poly)
  485. (load!-package!-sources 'alg 'alg)
  486. (load!-package!-sources 'arith 'arith) % Needed by roots, specfn*, (psl).
  487. (load!-package!-sources 'entry 'support)
  488. (load!-package!-sources 'remake 'support)
  489. (setq !*comp nil)
  490. (begin)
  491. symbolic;
  492. !#if (and (or (boundp 'force_c_code) (not (memq 'embedded lispsystem!*)))
  493. (not !*savedef))
  494. faslout 'user;
  495. %
  496. % The "user" module is only useful when building a full system, since
  497. % in the bootstrap the files u01.lsp to u60.lsp will probably not exist
  498. % and it is CERTAIN that they are not useful.
  499. %
  500. if modulep 'cslcompat then load!-module 'cslcompat;
  501. !#if (not (memq 'jlisp lispsystem!*))
  502. % Note that Jlisp will use a different scheme to get the literal-vectors
  503. % of translated functions installed.
  504. symbolic procedure c!:install(name, env, c!-version, !&optional, c1);
  505. begin
  506. scalar v, n;
  507. if c1 then return check!-c!-code(name, env, c!-version, c1);
  508. put(name, 'c!-version, c!-version);
  509. if null env then return name;
  510. v := mkvect sub1 length env;
  511. n := 0;
  512. while env do <<
  513. putv(v, n, car env);
  514. n := n + 1;
  515. env := cdr env >>;
  516. % I only instate the environment if there is nothing useful there at
  517. % present. This is a rather dubious test!
  518. if symbol!-env name = nil or
  519. symbol!-env name = name then symbol!-set!-env(name, v);
  520. put(name, 'funarg, v);
  521. return name;
  522. end;
  523. for each name in '(
  524. "u01.lsp" "u02.lsp" "u03.lsp" "u04.lsp" "u05.lsp"
  525. "u06.lsp" "u07.lsp" "u08.lsp" "u09.lsp" "u10.lsp"
  526. "u11.lsp" "u12.lsp" "u13.lsp" "u14.lsp" "u15.lsp"
  527. "u16.lsp" "u17.lsp" "u18.lsp" "u19.lsp" "u20.lsp"
  528. "u21.lsp" "u22.lsp" "u23.lsp" "u24.lsp" "u25.lsp"
  529. "u26.lsp" "u27.lsp" "u28.lsp" "u29.lsp" "u30.lsp"
  530. "u31.lsp" "u32.lsp" "u33.lsp" "u34.lsp" "u35.lsp"
  531. "u36.lsp" "u37.lsp" "u38.lsp" "u39.lsp" "u40.lsp"
  532. "u41.lsp" "u42.lsp" "u43.lsp" "u44.lsp" "u45.lsp"
  533. "u46.lsp" "u47.lsp" "u48.lsp" "u49.lsp" "u50.lsp"
  534. "u51.lsp" "u52.lsp" "u53.lsp" "u54.lsp" "u55.lsp"
  535. "u56.lsp" "u57.lsp" "u58.lsp" "u59.lsp" "u60.lsp") do <<
  536. if memq('embedded, lispsystem!*) or
  537. not memq('generic, lispsystem!*) then
  538. name := compress('!" .
  539. append(explodec "$reduce/cslbuild/generated-c/",
  540. cdr explode name));
  541. rdf name >>;
  542. !#endif % jlisp
  543. if modulep 'smacros then load!-module 'smacros;
  544. faslend;
  545. !#endif % embedded
  546. faslout 'xremake;
  547. fluid '(!*nocompile);
  548. !*nocompile := nil;
  549. if boundp 'interpreted and eq(compress explodec interpreted, 'yes) then
  550. !*nocompile := t;
  551. !#if (and (or (boundp 'force_c_code) (not (memq 'embedded lispsystem!*)))
  552. (not !*savedef))
  553. load!-module "user";
  554. !#endif % embedded
  555. in "$reduce/packages/support/remake.red"$
  556. global '(reduce_base_modules reduce_extra_modules
  557. reduce_test_cases reduce_regression_tests
  558. !*reduce!-packages!*);
  559. symbolic procedure get_configuration_data();
  560. % Read data from a configuration file that lists the modules that must
  561. % be processed. NOTE that this and the next few funtions will ONLY
  562. % work properly if REDUCE had been started up with the correct
  563. % working directory. This is (just about) acceptable because these are
  564. % system maintainance functions rather than generally flexible things
  565. % for arbitrary use.
  566. begin
  567. scalar i, w, e, r, r1;
  568. % Configuration information is held in a file called something like
  569. % "package.map".
  570. if (boundp 'minireduce and symbol!-value 'minireduce) or
  571. memq('vsl, lispsystem!*) then i := "package.map"
  572. else i := "$reduce/packages/package.map";
  573. i := open(i, 'input);
  574. i := rds i;
  575. e := !*echo;
  576. !*echo := nil;
  577. w := read();
  578. !*echo := e;
  579. i := rds i;
  580. close i;
  581. reduce_base_modules :=
  582. for each x in w conc
  583. if member('core, cddr x) and
  584. member('csl, cddr x) then list car x else nil;
  585. reduce_extra_modules :=
  586. for each x in w conc
  587. if not member('core, cddr x) and
  588. member('csl, cddr x) then list car x else nil;
  589. reduce_test_cases :=
  590. for each x in w conc
  591. if member('test, cddr x) and
  592. member('csl, cddr x) then list car x else nil;
  593. % Any file with a name *.tst in the regressions directory will be
  594. % considered to be a test case in addition to ones explicitly shown
  595. % in package.map.
  596. reduce_regression_tests := nil;
  597. % The embedded build may not support the list!-directory function and so
  598. % I arrange that if it fails I just omit being aware of the regression
  599. % test scripts. Soon the embedded system (built ising C++17) will in fact
  600. % support this!
  601. if memq('embedded, lispsystem!*) then rdf("$srcdir/regressions.list")
  602. else <<
  603. r := errorset(list('list!-directory, "$reduce/packages/regressions"),
  604. nil, nil);
  605. if atom r then r :=nil else r := car r;
  606. for each f in r do <<
  607. r1 := reverse explodec f;
  608. if eqcar(r1, 't) and
  609. eqcar(cdr r1, 's) and
  610. eqcar(cddr r1, 't) and
  611. eqcar(cdddr r1, '!.) then <<
  612. r1 := intern list!-to!-string reverse cddddr r1;
  613. put(r1, 'folder, "regressions");
  614. reduce_regression_tests :=
  615. r1 . reduce_regression_tests >> >> >>;
  616. % I will run the "alg" test twice! This is for the benefit of Java where the
  617. % first time will be seriously slowed down by the need to JIT almost
  618. % everything.
  619. reduce_test_cases := 'alg . append(reduce_test_cases, reduce_regression_tests);
  620. for each x in w do
  621. if member('csl, cddr x) then put(car x, 'folder, cadr x);
  622. % princ "reduce_base_modules: "; print reduce_base_modules;
  623. % princ "reduce_extra_modules: "; print reduce_extra_modules;
  624. % princ "reduce_test_cases: "; print reduce_test_cases;
  625. % princ "reduce_regression_tests: "; print reduce_regression_tests;
  626. !*reduce!-packages!* := append(reduce_base_modules, reduce_extra_modules);
  627. return;
  628. end;
  629. symbolic procedure build_reduce_modules names;
  630. begin
  631. scalar w;
  632. if boundp 'interpreted and interpreted then !*nocompile := t;
  633. !*comp := null !*nocompile;
  634. !#if !*savedef
  635. !*savedef := t;
  636. !#else
  637. !*savedef := nil;
  638. !#endif
  639. !#if !*noinlines
  640. !*noinlines := t;
  641. !#else
  642. !*noinlines := nil;
  643. !#endif
  644. make!-special '!*native_code;
  645. !*native_code := nil;
  646. get_configuration_data();
  647. if !*backtrace then !*echo := t; % To help with debugging...
  648. w := explodec car names;
  649. if !*savedef then w := append(explodec "[Bootstrap] ", w);
  650. window!-heading list!-to!-string w;
  651. !#if !*savedef
  652. % When building the bootstrap version I want to record what switches
  653. % get declared...
  654. if not getd 'original!-switch then <<
  655. w := getd 'switch;
  656. putd('original!-switch, car w, cdr w);
  657. putd('switch, 'expr,
  658. '(lambda (x)
  659. (dolist (y x) (princ "+++ Declaring a switch: ") (print y))
  660. (original!-switch x))) >>;
  661. !#endif
  662. package!-remake car names;
  663. if null (names := cdr names) then <<
  664. printc "Recompilation complete";
  665. window!-heading "Recompilation complete" >>;
  666. !#if (or !*savedef
  667. (and (not (boundp 'force_c_code)) (memq 'embedded lispsystem!*)))
  668. if null names then restart!-csl 'begin
  669. else restart!-csl('(xremake build_reduce_modules), names)
  670. !#else
  671. if null names then restart!-csl '(user begin)
  672. else restart!-csl('(xremake build_reduce_modules), names)
  673. !#endif
  674. end;
  675. fluid '(cpulimit conslimit testdirectory);
  676. symbolic procedure test_a_package names;
  677. begin
  678. scalar packge, logname, logtmp, logfile;
  679. scalar quitfn, oll, rr, !*redefmsg, !*redeflg!*, walltime, w;
  680. if not boundp 'cpulimit or
  681. not fixp (cpulimit := compress explodec cpulimit) or
  682. cpulimit < 1 then
  683. cpulimit := if memq('jlisp, lispsystem!*) then 6000 else 360;
  684. if not boundp 'conslimit or
  685. not fixp (conslimit := compress explodec conslimit) or
  686. conslimit < 1 then
  687. conslimit := 2000;
  688. princ "TESTING: "; printc car names;
  689. window!-heading list!-to!-string append(explodec "[Testing] ",
  690. explodec car names);
  691. !*backtrace := nil;
  692. !*errcont := t;
  693. !*extraecho := t; % Ensure standard environment for the test...
  694. !*int := nil; % ... so that results are predictable.
  695. packge := car names;
  696. verbos nil;
  697. % Normally logs from testing go in testlogs/name.rlg, however you may
  698. % may sometimes want to put them somewhere else. If you do then launch reduce
  699. % along the lines
  700. % reduce -D@log="mylogs" ...
  701. % and ensure that <top>/mylogs exists.
  702. if boundp '!@log and stringp symbol!-value '!@log then
  703. logname := symbol!-value '!@log
  704. else logname := "testlogs";
  705. logname := concat(logname, "/");
  706. logtmp := concat(logname, concat(car names, ".tmp"));
  707. logname := concat(logname, concat(car names,".rlg"));
  708. logfile := open(logtmp, 'output);
  709. get_configuration_data();
  710. % Any messages generated while loading the package do NOT appear in the log
  711. if not memq(packge, reduce_regression_tests) then load!-package packge;
  712. begin
  713. scalar !*terminal!-io!*, !*standard!-output!*, !*error!-output!*,
  714. !*trace!-output!*, !*debug!-io!*, !*query!-io!*, !*errcont,
  715. outputhandler!*;
  716. !*terminal!-io!* := !*standard!-output!* := !*error!-output!* := logfile;
  717. !*trace!-output!* := !*debug!-io!* := !*query!-io!* := logfile;
  718. oll := linelength 80;
  719. % princ date(); princ " run on "; printc cdr assoc('name, lispsystem!*);
  720. if get(packge,'folder) then packge := get(packge,'folder);
  721. testdirectory := concat("$reduce/packages/", packge);
  722. packge := concat("$reduce/packages/",
  723. concat(packge,
  724. concat("/",
  725. concat(car names,".tst"))));
  726. quitfn := getd 'quit;
  727. % At least at one stage at least one test file ends in "quit;" rather than
  728. % "end;" and the normal effect would be that this leads it to cancel
  729. % all execution instantly. To avoid that I will undefine the function
  730. % "quit", but restore it after the test. I reset !*redefmsg to avoid getting
  731. % messages about this. I redefined quit to something (specifically "posn")
  732. % that does not need an argument and that is "harmless".
  733. remd 'quit;
  734. putd('quit, 'expr, 'posn);
  735. !*mode := 'algebraic;
  736. !*extraecho := t; % Ensure standard environment for the test...
  737. !*int := nil; % ... so that results are predictable.
  738. !*errcont := t;
  739. % resource!-limit is a special feature in CSL so that potentially wild
  740. % code can be run with it being stopped harshly if it gets stuck.
  741. % The first argument is an expression to evaluate. The next 4 are
  742. % a time limit, in seconds
  743. % a "cons" limit, in megaconses
  744. % a limit on the number of thousands of I/O bytes that can be
  745. % performed, with both reading and printing counted
  746. % a limit on the number of Lisp-level errors that can be raised.
  747. % note that that can be large if errorset is used to trap them.
  748. %
  749. % If a limit is specified as a negative value (typically -1) then that
  750. % resource is not applied.
  751. % The first 3 limits are applied in an APPROXIMATE way, and the first
  752. % is seriously sensitive the the speed of the computer you are running
  753. % on, so should be used with real care. At the end the return value
  754. % is atomic if a limit expired, otherwise ncons of the regular value.
  755. % A global variable *resources* should end up a list of 4 values
  756. % showing the usage in each category.
  757. % The settings here are intended to be fairly conservative...
  758. % Time: On an Intel Q6600 CPU the longest test runs in under 20 seconds,
  759. % so allowing 3 minutes gives almost a factor of 10 slack. If
  760. % many people are running slow(ish) machines still I can increase
  761. % the limit.
  762. % Space: The amount of space used ought to be pretty independent of
  763. % the computer used. Measuring on 32 and 64-bit systems will
  764. % give minor differences. But the limit given here seems to allow
  765. % all the current tests to run with a factor of 2 headroom
  766. % in case the test-scripts are updated.
  767. % IO: The "crack" package has code in it that checkpoints its state
  768. % to disc periodically, and tests that activate that use amazingly
  769. % more IO than the others. The limit at 10 Mbytes suits the
  770. % relevant current tests. If a broken package leads to a test
  771. % script looping this then means that the resulting log file is no
  772. % larger than (about) 10 Mbytes, which is ugly but managable.
  773. % Errors: Some REDUCE packages make extensive use of errorset and
  774. % predictable use of "error" (for lack of use of catch and throw,
  775. % usually). So I do not constrain errors here. But if things were
  776. % ever such that no errors were expected I could enforce that
  777. % condition here.
  778. walltime := timeofday();
  779. eval '(resettime1);
  780. rr := resource!-limit(list('in_list1, mkquote packge, t),
  781. cpulimit, % CPU time per test
  782. conslimit, % megaconses
  783. 10000,% allow ten megabytes of I/O
  784. -1); % Do not limit Lisp-level errors at all
  785. erfg!* := nil;
  786. terpri();
  787. princ "Tested on ";
  788. princ cdr assoc('platform, lispsystem!*);
  789. princ " CSL";
  790. eval '(showtime1 nil);
  791. w := timeofday();
  792. walltime := (car w - car walltime) . (cdr w - cdr walltime);
  793. w := cdr walltime;
  794. walltime := car walltime;
  795. if w < 0 then << walltime := walltime - 1; w := w + 1000000 >>;
  796. princ "real ";
  797. princ (walltime/60);
  798. princ "m";
  799. princ remainder(walltime, 60);
  800. princ ".";
  801. % This illustrates that I need a proper general formatted print mechanism!
  802. w := (w + 500)/1000;
  803. if w < 10 then princ "00"
  804. else if w < 100 then princ "0";
  805. princ w;
  806. printc "s";
  807. erfg!* := nil;
  808. putd('quit, car quitfn, cdr quitfn);
  809. if atom rr then printc "+++++ Error: Resource limit exceeded";
  810. linelength oll
  811. end;
  812. close logfile;
  813. delete!-file logname;
  814. rename!-file(logtmp, logname);
  815. names := cdr names;
  816. if null names then <<
  817. printc "Testing complete";
  818. window!-heading "Testing complete";
  819. restart!-csl t >>
  820. else restart!-csl('(xremake test_a_package), names)
  821. end;
  822. symbolic procedure profile_compare_fn(p, q);
  823. begin
  824. scalar a, b;
  825. a := (float caddr p/float cadr p);
  826. b := (float caddr q/float cadr q);
  827. if a < b then return t
  828. else if a > b then return nil
  829. else return ordp(p, q) % Use alpha ordering on function
  830. % if counts match exactly.
  831. end;
  832. %
  833. % This function runs a test file and sorts out what the top 350
  834. % functions in it. It appends their names to "profile.dat".
  835. %
  836. symbolic procedure profile_a_package names;
  837. begin
  838. scalar packge, oll, w, w1, w2, quitfn, !*errcont, rr;
  839. if not boundp 'cpulimit or
  840. not fixp (cpulimit := compress explodec cpulimit) or
  841. cpulimit < 1 then
  842. cpulimit := if memq('jlisp, lispsystem!*) then 5000 else 180;
  843. if not boundp 'conslimit or
  844. not fixp (conslimit := compress explodec conslimit) or
  845. conslimit < 1 then
  846. conslimit := 2000;
  847. princ "PROFILING: "; print car names;
  848. !*backtrace := nil;
  849. !*errcont := t;
  850. !*int := nil;
  851. packge := car names;
  852. verbos nil;
  853. get_configuration_data();
  854. if not memq(packge, reduce_regression_tests) then <<
  855. load!-package packge;
  856. if get(packge,'folder) then packge := get(packge,'folder);
  857. testdirectory := concat("$reduce/packages/", packge);
  858. packge := concat("$reduce/packages/",
  859. concat(packge,
  860. concat("/",
  861. concat(car names,".tst"))));
  862. oll := linelength 80;
  863. !*mode := 'algebraic;
  864. window!-heading list!-to!-string append(explodec "[Profile] ",
  865. explodec car names);
  866. quitfn := getd 'quit;
  867. remd 'quit;
  868. putd('quit, 'expr, 'posn);
  869. mapstore 4; % reset counts;
  870. !*errcont := t;
  871. % I try hard to arrange that even if the test fails I can continue and that
  872. % input & output file selection is not messed up for me.
  873. w := wrs nil; w1 := rds nil;
  874. wrs w; rds w1;
  875. rr := resource!-limit(list('errorset,
  876. mkquote list('in_list1, mkquote packge, t),
  877. nil, nil),
  878. cpulimit,
  879. conslimit,
  880. 10000,% allow ten megabytes of I/O
  881. -1); % Do not limit Lisp-level errors at all
  882. wrs w; rds w1;
  883. erfg!* := nil;
  884. terpri();
  885. putd('quit, car quitfn, cdr quitfn);
  886. w := sort(mapstore 2, function profile_compare_fn);
  887. begin
  888. scalar oo;
  889. oo := wrs open("buildlogs/flaguse.log", 'append);
  890. bytecounts t;
  891. close wrs oo;
  892. end;
  893. load!-source(); % Need source versions of all code here
  894. w1 := nil;
  895. while w do <<
  896. w2 := get(caar w, '!*savedef);
  897. if eqcar(w2, 'lambda) then w1 := (caar w . md60 (caar w . cdr w2) .
  898. cadar w . caddar w) . w1;
  899. w := cdr w >>;
  900. w := w1;
  901. % I collect the top 350 functions as used by each test, not because all
  902. % that many will be wanted but because I might as well record plenty
  903. % of information here and discard unwanted parts later on.
  904. for i := 1:349 do if w1 then w1 := cdr w1;
  905. if w1 then rplacd(w1, nil);
  906. % princ "MODULE "; prin car names; princ " suggests ";
  907. % print for each z in w collect car z;
  908. w1 := open("profile.dat", 'append);
  909. w1 := wrs w1;
  910. linelength 80;
  911. if atom rr then printc "% +++++ Error: Resource limit exceeded";
  912. princ "% @@@@@ Resources used: "; print !*resources!*;
  913. princ "("; prin car names; terpri();
  914. for each n in w do <<
  915. princ " ("; prin car n; princ " ";
  916. if posn() > 30 then << terpri(); ttab 30 >>;
  917. prin cadr n;
  918. % I also display the counts just to help me debug & for interest.
  919. princ " "; prin caddr n; princ " "; princ cdddr n;
  920. printc ")" >>;
  921. printc " )";
  922. terpri();
  923. close wrs w1;
  924. linelength oll >>;
  925. names := cdr names;
  926. if null names then <<
  927. w1 := open("buildlogs/flaguse.log", 'input);
  928. w1 := rds w1;
  929. w := nil;
  930. while (w2 := read()) neq !$eof!$ do
  931. w := sort(w2, 'orderp) . w;
  932. close rds w1;
  933. rr := '((symbol!-make!-fastget 'lose 1)
  934. (symbol!-make!-fastget 'noncom 0));
  935. flag('(lose noncom), 'processed);
  936. oll := 2;
  937. while w do <<
  938. w1 := nil;
  939. for each x in w do <<
  940. if x and
  941. not flagp(cadar x, 'processed) and
  942. oll < 63 then <<
  943. rr :=
  944. list('symbol!-make!-fastget, mkquote cadar x, oll) . rr;
  945. flag(list cadar x, 'processed);
  946. oll := oll + 1 >>;
  947. if cdr x then w1 := cdr x . w1 >>;
  948. w := reverse w1 >>;
  949. w := open("buildlogs/fastgets.lsp", 'output);
  950. w := wrs w;
  951. printc "% fastgets.lsp generated by profiling";
  952. terpri();
  953. prettyprint ('progn . reverse rr);
  954. terpri();
  955. printc "% end of fastgets.lsp";
  956. close wrs w;
  957. printc "Profiling complete";
  958. window!-heading "Profiling complete";
  959. restart!-csl t >>
  960. else restart!-csl('(xremake profile_a_package), names)
  961. end;
  962. symbolic procedure trim_prefix(a, b);
  963. begin
  964. while a and b and car a = car b do <<
  965. a := cdr a;
  966. b := cdr b >>;
  967. if null a then return b
  968. else return nil
  969. end;
  970. fluid '(time_info);
  971. symbolic procedure read_file f1;
  972. begin
  973. % I take the view that I can afford to read the whole of a file into
  974. % memory at the start of processing. This makes life easier for me
  975. % and the REDUCE log files are small compared with current main memory sizes.
  976. scalar r, w, w1, n, x;
  977. scalar p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13;
  978. % To make comparisons between my CSL logs and some of the "reference
  979. % logs", which are created using a different script, I will discard
  980. % lines that match certain patterns! Note that if the reference logs change
  981. % the particular tests I perform here could become out of date! Also if any
  982. % legitimate test output happened to match one of the following strings
  983. % I would lose out slightly.
  984. p1 := explodec "Time: ";
  985. p2 := explodec "user ";
  986. p3 := explodec "sys ";
  987. p4 := explodec "time to formulate conditions:";
  988. p5 := explodec "CRACK needed :";
  989. p6 := explodec "time for initializations:";
  990. p7 := explodec "Tested on ";
  991. p8 := explodec "Total time taken:";
  992. p9 := explodec "*** turned off switch";
  993. p10 := explodec "+++ levelt compiled";
  994. p11 := explodec "Request to set constant bitsperword";
  995. p12 := explodec "*** (levelt): base";
  996. p13 := explodec "max_gc_int :";
  997. r := nil;
  998. n := 0;
  999. while not ((w := readline f1) = !$eof!$) do <<
  1000. w1 := explodec w;
  1001. if trim_prefix(p1, w1)
  1002. or trim_prefix(p2, w1)
  1003. or trim_prefix(p3, w1)
  1004. or trim_prefix(p4, w1)
  1005. or trim_prefix(p5, w1)
  1006. or trim_prefix(p6, w1)
  1007. or trim_prefix(p7, w1)
  1008. or trim_prefix(p8, w1)
  1009. or trim_prefix(p9, w1)
  1010. or trim_prefix(p10, w1)
  1011. or trim_prefix(p11, w1)
  1012. or trim_prefix(p12, w1)
  1013. or trim_prefix(p13, w1)
  1014. then n := n + 1
  1015. else r := ((n := n + 1) . w) . r >>;
  1016. w := r;
  1017. % The text scanned for here is expected to match that generated by the
  1018. % test script. I locate the last match in a file, extract the numbers
  1019. % and eventually write them to testlogs/times.log
  1020. n := explodec "Time (counter 1):";
  1021. while w and null (x := trim_prefix(n, explodec cdar w)) do w := cdr w;
  1022. if null w then <<
  1023. time_info := nil;
  1024. return reversip r >>;
  1025. % Remove time info from lines
  1026. w := cdr w;
  1027. if (trim_prefix(explodec "Tested on ", explodec cdar w)) then w := cdr w;
  1028. r := w;
  1029. while eqcar(x, '! ) do x := cdr x;
  1030. w := n := nil;
  1031. while digit car x do << w := car x . w; x := cdr x >>;
  1032. while eqcar(x, '! ) do x := cdr x;
  1033. if x := trim_prefix(explodec "ms plus GC time:", x) then <<
  1034. while eqcar(x, '! ) do x := cdr x;
  1035. while digit car x do << n := car x . n; x := cdr x >> >>;
  1036. if null w then w := '(!0);
  1037. if null n then n := '(!0);
  1038. time_info := compress reverse w . compress reverse n;
  1039. return reversip r;
  1040. end;
  1041. fluid '(!*insist_on_exact_match);
  1042. !*insist_on_exact_match := t;
  1043. symbolic procedure roughly_equal(a, b);
  1044. begin
  1045. % a and b are strings repesenting lines of text. I want to test if they
  1046. % match subject to some floating point slop.
  1047. scalar wa, wb, adot, bdot;
  1048. if a = b then return t;
  1049. a := explodec a;
  1050. b := explodec b;
  1051. if !*insist_on_exact_match then return (a = b);
  1052. top:
  1053. % First deal with end of line matters.
  1054. if null a and null b then return t
  1055. else if null a or null b then return nil;
  1056. % next split off any bits of a and b up to a digit
  1057. wa := wb := nil;
  1058. while a and not digit car a do <<
  1059. wa := car a . wa;
  1060. a := cdr a >>;
  1061. while b and not digit car b do <<
  1062. wb := car b . wb;
  1063. b := cdr b >>;
  1064. if not (wa = wb) then return nil;
  1065. % now both a and b start with digits. I will seek a chunk of the
  1066. % form nnn.mmmE+xxx where E<sign>xxx is optional...
  1067. % Note that any leading sign on the float has been checked already!
  1068. wa := wb := nil;
  1069. adot := bdot := nil;
  1070. while a and digit car a do <<
  1071. wa := car a . wa;
  1072. a := cdr a >>;
  1073. if eqcar(a, '!.) then <<
  1074. adot := t;
  1075. wa := car a . wa;
  1076. a := cdr a >>;
  1077. while a and digit car a do <<
  1078. wa := car a . wa;
  1079. a := cdr a >>;
  1080. if eqcar(a, '!e) or eqcar(a, '!E) then <<
  1081. adot := t;
  1082. wa := car a . wa;
  1083. a := cdr a;
  1084. if eqcar(a, '!+) or eqcar(a, '!-) then <<
  1085. wa := car a . wa;
  1086. a := cdr a >>;
  1087. while a and digit car a do <<
  1088. wa := car a . wa;
  1089. a := cdr a >> >>;
  1090. % Now all the same to grab a float from b
  1091. while b and digit car b do <<
  1092. wb := car b . wb;
  1093. b := cdr b >>;
  1094. if eqcar(b, '!.) then <<
  1095. bdot := t;
  1096. wb := car b . wb;
  1097. b := cdr b >>;
  1098. while b and digit car b do <<
  1099. wb := car b . wb;
  1100. b := cdr b >>;
  1101. if eqcar(b, '!e) or eqcar(b, '!E) then <<
  1102. bdot := t;
  1103. wb := car b . wb;
  1104. b := cdr b;
  1105. if eqcar(b, '!+) or eqcar(b, '!-) then <<
  1106. wb := car b . wb;
  1107. b := cdr b >>;
  1108. while b and digit car b do <<
  1109. wb := car b . wb;
  1110. b := cdr b >> >>;
  1111. % Now one possibility is that I had an integer not a float,
  1112. % and in that case I want an exact match
  1113. if not adot or not bdot then <<
  1114. if wa = wb then goto top
  1115. else return nil >>;
  1116. if wa = wb then goto top; % textual match on floating point values
  1117. wa := compress reversip wa;
  1118. wb := compress reversip wb;
  1119. if fixp wa then wa := float wa;
  1120. if fixp wb then wb := float wb;
  1121. if not (floatp wa and floatp wb) then return nil; % messed up somehow!
  1122. if wa = wb then goto top;
  1123. % now the crucial approximate floating point test - note that both numbers
  1124. % are positive, but that they may be extreme in range.
  1125. % As a cop-out I am going to insist that if values are either very very big
  1126. % or very very small that they match as text.
  1127. if wa > 1.0e100 or wb > 1.0e100 then return nil;
  1128. if wa < 1.0e-100 or wb < 1.0e-100 then return nil;
  1129. wa := (wa - wb)/(wa + wb);
  1130. if wa < 0 then wa := -wa;
  1131. if wa > 0.0001 then return nil; % pretty crude!
  1132. goto top
  1133. end;
  1134. symbolic procedure in_sync(d1, n1, d2, n2);
  1135. begin
  1136. for i := 1:n1 do if d1 then << % skip n1 lines from d1
  1137. d1 := cdr d1 >>;
  1138. for i := 1:n2 do if d2 then << % skip n2 lines from d2
  1139. d2 := cdr d2 >>;
  1140. % If one is ended but the other is not then we do not have a match. If
  1141. % both are ended we do have one.
  1142. if null d1 then return null d2
  1143. else if null d2 then return nil;
  1144. % Here I insist on 3 lines that agree before I count a match as
  1145. % having been re-established.
  1146. if not roughly_equal(cdar d1, cdar d2) then return nil;
  1147. d1 := cdr d1; d2 := cdr d2;
  1148. if null d1 then return null d2
  1149. else if null d2 then return nil;
  1150. if not roughly_equal(cdar d1, cdar d2) then return nil;
  1151. d1 := cdr d1; d2 := cdr d2;
  1152. if null d1 then return null d2
  1153. else if null d2 then return nil;
  1154. if not roughly_equal(cdar d1, cdar d2) then return nil;
  1155. d1 := cdr d1; d2 := cdr d2;
  1156. if null d1 then return null d2
  1157. else if null d2 then return nil
  1158. else return t
  1159. end;
  1160. fluid '(time_data time_ratio gc_time_ratio log_count);
  1161. symbolic procedure prinright(x, w);
  1162. begin
  1163. scalar xx, xl;
  1164. xx := explodec x;
  1165. xl := length xx;
  1166. while w > xl do << princ " "; xl := xl + 1 >>;
  1167. princ x;
  1168. end;
  1169. fluid '(files_with_differences);
  1170. symbolic procedure file_compare(f1, f2, name);
  1171. begin
  1172. scalar i, j, d1, d2, t1, gt1, t2, gt2, time_info, fdiffer;
  1173. d1 := read_file f1;
  1174. if null time_info then t1 := gt1 := 0
  1175. else << t1 := car time_info; gt1 := cdr time_info >>;
  1176. d2 := read_file f2;
  1177. if null time_info then t2 := gt2 := 0
  1178. else << t2 := car time_info; gt2 := cdr time_info >>;
  1179. i := wrs time_data;
  1180. j := set!-print!-precision 3;
  1181. prin name;
  1182. ttab 17;
  1183. if zerop t1 then princ " ---"
  1184. else << prinright(t1, 8);
  1185. % Tag the time with an asterisk if it will not participate in the
  1186. % eventual overall timing report.
  1187. if t1<=200 then princ "*";
  1188. ttab 30; prinright(gt1, 8) >>;
  1189. ttab 40;
  1190. if zerop t2 then princ " ---"
  1191. else << prinright(t2, 9);
  1192. if t2<=200 then princ "*";
  1193. ttab 50; prinright(gt2, 8) >>;
  1194. ttab 60;
  1195. if zerop t1 or zerop t2 then princ " *** ***"
  1196. else begin
  1197. scalar r1, gr1, w;
  1198. r1 := float t1 / float t2;
  1199. gr1 := float (t1+gt1)/float (t2+gt2);
  1200. % I will only use tests where the time taken was over 200ms in my eventual
  1201. % composite summary of timings, since measurement accuracy can leave the
  1202. % really short tests pretty meaningless.
  1203. if t1 > 200 and t2 > 200 then <<
  1204. % But I will go further than that and give less weight to any test whose time
  1205. % is under 1 second, so that the cut-off is gradual rather than abrupt.
  1206. w := min(t1, t2);
  1207. % This means that if w (the smaller time) = 200 then then
  1208. % the test does not contribute to the average, while if w>=1000
  1209. % it contributes fully.
  1210. if w < 1000.0 then w := (w - 200.0)/800.0
  1211. else w := 1.0;
  1212. time_ratio := time_ratio * expt(r1, w);
  1213. gc_time_ratio := gc_time_ratio * expt(gr1, w);
  1214. log_count := log_count + w >>;
  1215. princ r1;
  1216. ttab 70;
  1217. princ gr1;
  1218. end;
  1219. terpri();
  1220. set!-print!-precision j;
  1221. wrs i;
  1222. % The next segment of code is a version of "diff" to report ways in which
  1223. % reference and recent log files match or diverge.
  1224. % I can not see a neat way to get a "structured" control structure
  1225. % here easily. Ah well, drop back to GOTO statements!
  1226. top:
  1227. if null d1 then << % end of one file
  1228. if d2 then terpri();
  1229. i := 0;
  1230. while d2 and i < 20 do <<
  1231. fdiffer := t;
  1232. princ "REF "; princ caar d2; princ ":"; ttab 10; printc cdar d2;
  1233. d2 := cdr d2;
  1234. i := i + 1 >>;
  1235. if d2 then printc "...";
  1236. if fdiffer then files_with_differences := name . files_with_differences;
  1237. return >>;
  1238. if null d2 then << % end of other file
  1239. i := 0;
  1240. while d1 and i < 20 do <<
  1241. fdiffer := t;
  1242. princ "NEW "; princ caar d1; princ ":"; ttab 10; printc cdar d1;
  1243. d1 := cdr d1;
  1244. i := i + 1 >>;
  1245. if d1 then printc "...";
  1246. if fdiffer then files_with_differences := name . files_with_differences;
  1247. return >>;
  1248. % The test "roughly_equal" compares allowing some tolerance on floating
  1249. % point values. This is because REDUCE uses platform libraries for
  1250. % floating point elementary functions and printing, so small differences
  1251. % are expected. This is perhaps uncomfortable, but is part of reality, and
  1252. % the test here makes comparison output much more useful in that the
  1253. % differences shown up are better limited towards "real" ones.
  1254. if roughly_equal(cdar d1, cdar d2) then <<
  1255. d1 := cdr d1;
  1256. d2 := cdr d2;
  1257. go to top >>;
  1258. % I will first see if there are just a few blank lines inserted into
  1259. % one or other file. This special case is addressed here because it
  1260. % appears more common a possibility than I had expected.
  1261. if cdar d1 = "" and cdr d1 and roughly_equal(cdadr d1, cdar d2) then <<
  1262. fdiffer := t;
  1263. princ "NEW "; princ caar d1; princ ":"; ttab 10; printc cdar d1;
  1264. d1 := cdr d1;
  1265. go to top >>
  1266. else if cdar d1 = "" and cdr d1 and cdadr d1 = "" and cddr d1 and
  1267. roughly_equal(cdaddr d1, cdar d2) then <<
  1268. fdiffer := t;
  1269. princ "NEW "; princ caar d1; princ ":"; ttab 10; printc cdar d1;
  1270. d1 := cdr d1;
  1271. princ "NEW "; princ caar d1; princ ":"; ttab 10; printc cdar d1;
  1272. d1 := cdr d1;
  1273. go to top >>
  1274. else if cdar d2 = "" and cdr d2 and
  1275. roughly_equal(cdadr d2, cdar d1) then <<
  1276. fdiffer := t;
  1277. princ "REF "; princ caar d2; princ ":"; ttab 10; printc cdar d2;
  1278. d2 := cdr d2;
  1279. go to top >>
  1280. else if cdar d2 = "" and cdr d2 and cdadr d2 = "" and cddr d2 and
  1281. roughly_equal(cdaddr d2, cdar d1) then <<
  1282. fdiffer := t;
  1283. princ "REF "; princ caar d2; princ ":"; ttab 10; printc cdar d2;
  1284. d2 := cdr d2;
  1285. princ "REF "; princ caar d2; princ ":"; ttab 10; printc cdar d2;
  1286. d2 := cdr d2;
  1287. go to top >>;
  1288. i := 1;
  1289. seek_rematch:
  1290. j := 0;
  1291. inner:
  1292. if in_sync(d1, i, d2, j) then <<
  1293. terpri();
  1294. for k := 1:i do <<
  1295. if not trim_prefix(explodec "Time (counter 1)", explodec cdar d1) and
  1296. not trim_prefix(explodec "real ", explodec cdar d1) then
  1297. fdiffer := t;
  1298. princ "NEW "; princ caar d1; princ ":"; ttab 10; printc cdar d1;
  1299. d1 := cdr d1 >>;
  1300. for k := 1:j do <<
  1301. if not trim_prefix(explodec "Time (counter 1)", explodec cdar d2) and
  1302. not trim_prefix(explodec "real ", explodec cdar d2) then
  1303. fdiffer := t;
  1304. princ "REF "; princ caar d2; princ ":"; ttab 10; printc cdar d2;
  1305. d2 := cdr d2 >>;
  1306. if null d1 then <<
  1307. if fdiffer then files_with_differences := name . files_with_differences;
  1308. return >>
  1309. else go to top >>;
  1310. j := j + 1;
  1311. i := i - 1;
  1312. if i >= 0 then go to inner;
  1313. i := j;
  1314. % I am prepared to seek 80 lines ahead on each side before I give up.
  1315. % The number 80 is pretty much arbitrary.
  1316. if i < 80 then goto seek_rematch;
  1317. terpri();
  1318. i := 0;
  1319. while d2 and i < 20 do <<
  1320. fdiffer := t;
  1321. princ "REF "; princ caar d2; princ ":"; ttab 10; printc cdar d2;
  1322. d2 := cdr d2;
  1323. i := i+1 >>;
  1324. if d2 then printc "...";
  1325. i := 0;
  1326. while d1 and i < 20 do <<
  1327. fdiffer := t;
  1328. princ "NEW "; princ caar d1; princ ":"; ttab 10; printc cdar d1;
  1329. d1 := cdr d1;
  1330. i := i+1 >>;
  1331. if d1 then printc "...";
  1332. printc "Comparison failed.";
  1333. if fdiffer then files_with_differences := name . files_with_differences;
  1334. end;
  1335. fluid '(which_module);
  1336. symbolic procedure check_a_package;
  1337. begin
  1338. scalar oll, names, p1, logname, mylogname, mylog, reflogname, reflog,
  1339. time_data, time_ratio, gc_time_ratio, log_count,
  1340. files_with_differences;
  1341. get_configuration_data();
  1342. if boundp 'which_module and symbol!-value 'which_module and
  1343. not (symbol!-value 'which_module = "") then <<
  1344. names := compress explodec symbol!-value 'which_module;
  1345. if member(names, reduce_test_cases) then names := list names
  1346. else error(0, list("unknown module to check", which_module)) >>
  1347. else names := reduce_test_cases;
  1348. % I write a summary of timing information into csllogs/times.log
  1349. time_data := open("testlogs/times.log", 'output);
  1350. p1 := wrs time_data;
  1351. princ "MODULE";
  1352. ttab 21; princ "Local"; ttab 32; princ "(GC)";
  1353. ttab 40; princ "Reference"; ttab 52; princ "(GC)";
  1354. ttab 55; princ "Ratio"; ttab 65; printc "inc GC";
  1355. wrs p1;
  1356. terpri();
  1357. oll := linelength 100;
  1358. printc "=== Comparison results ===";
  1359. time_ratio := gc_time_ratio := 1.0; log_count := 0.0;
  1360. for each packge in names do <<
  1361. terpri();
  1362. princ "CHECKING: "; print packge;
  1363. if boundp '!@log and stringp symbol!-value '!@log then
  1364. logname := symbol!-value '!@log
  1365. else logname := "testlogs";
  1366. mylogname := concat(logname, concat("/", concat(packge, ".rlg")));
  1367. if get(packge,'folder) then p1 := get(packge,'folder)
  1368. else p1 := packge;
  1369. reflogname := concat("$reduce/packages/",
  1370. concat(p1,
  1371. concat("/",
  1372. concat(packge,".rlg"))));
  1373. mylog := errorset(list('open, mkquote mylogname, ''input), nil, nil);
  1374. reflog := errorset(list('open, mkquote reflogname, ''input), nil, nil);
  1375. if errorp mylog then <<
  1376. if not errorp reflog then close car reflog;
  1377. princ "No current log in "; print mylogname >>
  1378. else if errorp reflog then <<
  1379. close car mylog;
  1380. princ "No reference log in "; print reflogname >>
  1381. else <<
  1382. princ "LOGS: "; princ mylogname; princ " "; printc reflogname;
  1383. mylog := car mylog; reflog := car reflog;
  1384. file_compare(mylog, reflog, packge);
  1385. close mylog;
  1386. close reflog >> >>;
  1387. time_data := wrs time_data;
  1388. if not zerop log_count then <<
  1389. time_ratio := expt(time_ratio, 1.0/log_count);
  1390. gc_time_ratio := expt(gc_time_ratio, 1.0/log_count);
  1391. terpri();
  1392. p1 := set!-print!-precision 3;
  1393. princ "Over "; prin log_count; princ " tests the speed ratio was ";
  1394. print time_ratio;
  1395. princ " (or ";
  1396. prin gc_time_ratio;
  1397. printc " is garbage collection costs are included)";
  1398. set!-print!-precision p1 >>;
  1399. close wrs time_data;
  1400. linelength oll;
  1401. if null files_with_differences then <<
  1402. terpri(); terpri();
  1403. printc "+++++++++++++++++++++++++++";
  1404. printc "+++ All log files match +++";
  1405. printc "+++++++++++++++++++++++++++";
  1406. terpri() >>
  1407. else <<
  1408. terpri(); terpri();
  1409. printc "+++++++++++++++++++++++++++++++";
  1410. printc "+++ The following logs differ:";
  1411. for each x in reverse files_with_differences do <<
  1412. ttab 4; print x >>;
  1413. printc "+++++++++++++++++++++++++++++++";
  1414. terpri() >>;
  1415. end;
  1416. faslend;
  1417. load!-module 'xremake;
  1418. << initreduce();
  1419. date!* := "Bootstrap version";
  1420. preserve('begin, "REDUCE", t) >>;
  1421. symbolic;
  1422. !#if (and (or (boundp 'force_c_code)
  1423. (not (memq 'embedded lispsystem!*)))
  1424. (not !*savedef))
  1425. load!-module 'user;
  1426. !#endif
  1427. get_configuration_data();
  1428. package!-remake2(prolog_file,'support);
  1429. package!-remake2('revision,'support);
  1430. package!-remake2(rend_file,'support);
  1431. package!-remake2('entry,'support);
  1432. package!-remake2('smacros,'support);
  1433. package!-remake2('remake,'support);
  1434. % The next lines have LOTS of hidden depth! They restart CSL repeatedly
  1435. % so that each of the modules that has to be processed gets dealt with in
  1436. % a fresh uncluttered environment. The list of modules is fetched from
  1437. % a configuration file which must have 3 s-expressions in it. The first
  1438. % is a list of basic modules that must be built to get a core version of
  1439. % REDUCE. The second list identifies modules that can be built one the core
  1440. % is ready for use, while the last list indicates which modules have
  1441. % associated test scripts.
  1442. %
  1443. % When the modules have been rebuilt the system does a restart that
  1444. % kicks it back into REDUCE by calling begin(). This then continues
  1445. % reading from the stream that had been the standard input when this
  1446. % job started. Thus this script MUST be invoked as
  1447. % ./csl -obootstrapreduce.img -z buildreduce.lsp
  1448. % with the file buildreduce.lsp specified on the command line in the call. It
  1449. % will not work if you start csl manually and then do a (rdf ..) [say]
  1450. % on buildreduce.lsp. I told you that it was a little delicate.
  1451. !#if !*savedef
  1452. % Some switches may be in the utter core and not introduced via the
  1453. % "switch" declaration...
  1454. for each y in oblist() do
  1455. if flagp(y, 'switch) then <<
  1456. princ "+++ Declaring a switch: ";
  1457. print y >>;
  1458. !#endif
  1459. get_configuration_data();
  1460. build_reduce_modules reduce_base_modules;
  1461. % Now I want to do a cold-start so that I can create a sensible
  1462. % image for use in the subsequent build steps. This image should not
  1463. % contain ANYTHING extraneous.
  1464. symbolic restart!-csl nil;
  1465. (cond
  1466. ((eq 'vsl (car lispsystem!*)) (rdf "$srcdir/vsl.lsp")))
  1467. (setq !*savedef (and (or (boundp 'bootstrap)
  1468. (null (memq 'embedded lispsystem!*)))
  1469. (zerop (cdr (assoc 'c!-code lispsystem!*)))))
  1470. (make!-special '!*noinlines)
  1471. (prog (w)
  1472. (setq w (errorset 'noinlines nil nil))
  1473. (setq !*noinlines (and (not (atom w)) (car w)))
  1474. (print (list '!*noinlines 'set 'to !*noinlines)))
  1475. (make!-special '!*native_code)
  1476. (setq !*native_code nil)
  1477. (setq !*backtrace t)
  1478. (cond ((and (null !*savedef)
  1479. (or (boundp 'force_c_code) (null (memq 'embedded lispsystem!*))))
  1480. (load!-module 'user)))
  1481. (load!-module 'cslcompat)
  1482. (setq !*comp nil)
  1483. (load!-module 'module) % Definition of load_package, etc.
  1484. (load!-module 'cslprolo) % CSL specific code.
  1485. (setq loaded!-packages!* '(cslcompat user cslprolo))
  1486. (load!-package 'revision)
  1487. (load!-package 'rlisp)
  1488. (load!-package 'cslrend)
  1489. (load!-package 'smacros)
  1490. (load!-package 'poly)
  1491. (load!-package 'arith)
  1492. (load!-package 'alg)
  1493. (load!-package 'mathpr)
  1494. (cond
  1495. ((modulep 'tmprint) (load!-package 'tmprint)))
  1496. (load!-package 'entry)
  1497. (setq version!* (compress (cons '!"
  1498. (append
  1499. (explodec "Reduce (Free CSL version, revision ")
  1500. (append (explodec revision!*) (explodec ")"""))))))
  1501. (setq date!* (date))
  1502. (setq !*backtrace nil)
  1503. (initreduce)
  1504. (setq no_init_file nil)
  1505. % restart-csl re-applied the -D@srcdir=<DIR> -D@reduce=<DIR> command-line
  1506. % options and as a consequence the variables !@srcdir and !@reduce will be
  1507. % set here. This is perhaps convenient for people who run Reduce with the
  1508. % binaries sitting exactly where they where originally built, or at least
  1509. % on a computer where the path to the source files used to build Reduce still
  1510. % being valid. It would however be a MESS to try to rely on these on (for
  1511. % instance) another machine. I had thus considered the line
  1512. % (setq !@csl (setq !@reduce (symbol!-value (gensym))))
  1513. % which is intende to unset those variables so leaving things clean. However
  1514. % some developers really like to be able to do incremental builds to Reduce
  1515. % and so to help them I will leave things as they are and also ensure
  1516. % that everything is ready for package!-remake. I am not 100% happy about this
  1517. % since I view it as supporting and hence encouraging practises that I count
  1518. % as delicate (especially as regards built vs installed Reduce and dependencies
  1519. % between modules) so I still HOPE that most people who are developing
  1520. % stuff will rebuild Reduce from scratch rather often.
  1521. (load!-package 'xremake)
  1522. (get_configuration_data)
  1523. % If the user compiles a new FASL module then I will let it
  1524. % generate native code by default. I build the bulk of REDUCE
  1525. % without that since I have statically-selected hot-spot compilation
  1526. % that gives me what I believe to be a better speed/space tradeoff.
  1527. % Oh well, let's change that and disable it by default since at least on
  1528. % windows there are problems with windows vs cygwin file-names.
  1529. (fluid '(!*native_code))
  1530. (setq !*native_code nil) % The native compilation option that I was
  1531. % considering at one stage is no longer available.
  1532. (preserve 'begin (bldmsg "%w, %w ..." version!* date!*) t)
  1533. % Note that (preserve) here arranges to reload the image that it
  1534. % creates, and it then runs (begin) the start-up function. This will
  1535. % leave us running Reduce in algebraic mode...
  1536. %
  1537. % See the fairly length comments given a bit earlier about the
  1538. % delicacy of the next few lines!
  1539. %
  1540. symbolic;
  1541. no_init_file := t;
  1542. load!-module 'xremake;
  1543. get_configuration_data();
  1544. build_reduce_modules reduce_extra_modules;
  1545. symbolic;
  1546. "**** **** REDUCE FULLY REBUILD **** ****";
  1547. % At this stage I have a complete workable REDUCE. If built using a
  1548. % basic CSL (I call it "bootstrapreduce" here) nothing has been compiled into
  1549. % C (everything is bytecoded), and it is big because it has retained all
  1550. % Lisp source code in the image file. If however I built using a version
  1551. % of CSL ("reduce") that did have things compiled into C then these will
  1552. % be exploited and the original Lisp source will be omitted from the
  1553. % image, leaving a production version.
  1554. lisp stop(0);
  1555. bye;