fns2.c 113 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421
  1. /* fns2.c Copyright (C) 1989-2002 Codemist Ltd */
  2. /*
  3. * Basic functions part 2.
  4. */
  5. /*
  6. * This code may be used and modified, and redistributed in binary
  7. * or source form, subject to the "CCL Public License", which should
  8. * accompany it. This license is a variant on the BSD license, and thus
  9. * permits use of code derived from this in either open and commercial
  10. * projects: but it does require that updates to this code be made
  11. * available back to the originators of the package.
  12. * Before merging other code in with this or linking this code
  13. * with other packages or libraries please check that the license terms
  14. * of the other material are compatible with those of this.
  15. */
  16. /* Signature: 3fc8c70b 10-Oct-2002 */
  17. #include <stdarg.h>
  18. #include <string.h>
  19. #include <ctype.h>
  20. #include "machine.h"
  21. #include "tags.h"
  22. #include "cslerror.h"
  23. #include "externs.h"
  24. #include "read.h"
  25. #include "entries.h"
  26. #include "arith.h"
  27. #ifdef COMMON
  28. #include "clsyms.h"
  29. #endif
  30. #ifdef TIMEOUT
  31. #include "timeout.h"
  32. #endif
  33. #ifdef SOCKETS
  34. #include "sockhdr.h"
  35. #endif
  36. Lisp_Object getcodevector(int32 type, intxx size)
  37. {
  38. /*
  39. * type is the code (e.g. TYPE_BPS) that gets packed, together with
  40. * the size, into a header word.
  41. * size is measured in bytes and must allow space for the header word.
  42. * This obtains space in the BPS area
  43. */
  44. Lisp_Object nil = C_nil;
  45. #ifdef CHECK_FOR_CORRUPT_HEAP
  46. validate_all();
  47. #endif
  48. for (;;)
  49. { intxx alloc_size = (intxx)doubleword_align_up(size);
  50. char *cf = (char *)codefringe, *cl = (char *)codelimit;
  51. unsignedxx free = cf - cl;
  52. char *r;
  53. if (alloc_size > (intxx)free)
  54. { char msg[40];
  55. sprintf(msg, "codevector %ld", (long)size);
  56. reclaim(nil, msg, GC_BPS, alloc_size);
  57. errexit();
  58. continue;
  59. }
  60. r = cf - alloc_size;
  61. codefringe = (Lisp_Object)r;
  62. *((Header *)r) = type + (size << 10) + TAG_ODDS;
  63. /*
  64. * codelimit is always 8 bytes above the base of the code-page. The
  65. * address I need to return for a code-vector points (in a packed way)
  66. * to the first byte of actual byte data, ie CELL bytes above the start
  67. * of the data-structure. Oh joy!
  68. */
  69. return TAG_BPS +
  70. (((int32)((r + CELL) - (cl - 8)) & (PAGE_POWER_OF_TWO-4)) << 6) +
  71. (((int32)(bps_pages_count-1))<<(PAGE_BITS+6)); /* Wow! Obscure!! */
  72. }
  73. }
  74. Lisp_Object Lget_bps(Lisp_Object nil, Lisp_Object n)
  75. {
  76. int32 n1;
  77. if (!is_fixnum(n) || (int32)n<0) return aerror1("get-bps", n);
  78. n1 = int_of_fixnum(n);
  79. n = getcodevector(TYPE_BPS, n1+CELL);
  80. errexit();
  81. return onevalue(n);
  82. }
  83. Lisp_Object get_native_code_vector(intxx size)
  84. {
  85. /*
  86. * Create some space for native code and return a handle that identifies
  87. * its start point. size is measured in bytes.
  88. */
  89. Lisp_Object nil = C_nil;
  90. if (size <= 0) size = 8;
  91. for (;;)
  92. { intxx alloc_size = (intxx)doubleword_align_up(size);
  93. intxx cf = native_fringe;
  94. intxx free = CSL_PAGE_SIZE - cf - 0x100; /* 256 bytes to be safe */
  95. /*
  96. * When I start up a cold CSL I will have native_fringe set to zero and
  97. * native_pages_count also zero, indicating that there is none of this stuff
  98. * active.
  99. */
  100. if (native_fringe == 0 || alloc_size > free)
  101. { char msg[40];
  102. sprintf(msg, "native code %ld", (long)size);
  103. reclaim(nil, msg, GC_NATIVE, alloc_size);
  104. errexit();
  105. continue;
  106. }
  107. free = (intxx)native_pages[native_pages_count-1];
  108. free = doubleword_align_up(free);
  109. /*
  110. * I put the number of bytes in this block as the first word of the chunk
  111. * of memory, and arrange that there is a zero in what would be the first
  112. * word of unused space. Provided the user does not clobber bytes 0 to 4
  113. * or the block this is enough to allow restart code to scan through all
  114. * native code segments.
  115. */
  116. car32(free+native_fringe) = alloc_size;
  117. car32(free+native_fringe+alloc_size) = 0;
  118. native_fringe += alloc_size;
  119. native_pages_changed = 1;
  120. return Lcons(nil,
  121. fixnum_of_int(native_pages_count-1),
  122. fixnum_of_int(cf));
  123. }
  124. }
  125. Lisp_Object Lget_native(Lisp_Object nil, Lisp_Object n)
  126. {
  127. int32 n1;
  128. if (!is_fixnum(n) || (int32)n<0) return aerror1("get-native", n);
  129. n1 = int_of_fixnum(n);
  130. n = get_native_code_vector(n1);
  131. errexit();
  132. return onevalue(n);
  133. }
  134. int do_not_kill_native_code = 0;
  135. void set_fns(Lisp_Object a, one_args *f1, two_args *f2, n_args *fn)
  136. {
  137. Lisp_Object nil = C_nil;
  138. Lisp_Object w1, w2, w3 = nil;
  139. /*
  140. * If I redefine a function for any reason (except to set trace options
  141. * on a bytecoded definition) I will discard any native-coded definitions
  142. * by splicing them out of the record. I provide a global variable to
  143. * defeat this behaviour (ugh).
  144. */
  145. if (!do_not_kill_native_code)
  146. { for (w1 = native_code; w1!=nil; w1=qcdr(w1))
  147. { w2 = qcar(w1);
  148. if (qcar(w2) == a) break;
  149. w3 = w1;
  150. }
  151. if (w1 != nil)
  152. { w1 = qcdr(w1);
  153. if (w3 == nil) native_code = w1;
  154. else qcdr(w3) = w1;
  155. }
  156. }
  157. if ((qheader(a) & (SYM_C_DEF | SYM_CODEPTR)) ==
  158. (SYM_C_DEF | SYM_CODEPTR))
  159. { if (symbol_protect_flag)
  160. { if (warn_about_protected_symbols)
  161. { trace_printf("+++ WARNING: protected function ");
  162. prin_to_trace(a);
  163. trace_printf(" not redefined\n");
  164. }
  165. return;
  166. }
  167. else
  168. { if (warn_about_protected_symbols)
  169. { trace_printf("+++ WARNING: protected function ");
  170. prin_to_trace(a);
  171. trace_printf(" *has* been redefined\n");
  172. }
  173. Lsymbol_protect(C_nil, a, C_nil);
  174. }
  175. }
  176. ifn1(a) = (intxx)f1;
  177. ifn2(a) = (intxx)f2;
  178. ifnn(a) = (intxx)fn;
  179. }
  180. #ifdef HIDE_USELESS_SYMBOL_ENVIRONMENTS
  181. static CSLbool interpreter_entry(Lisp_Object a)
  182. /*
  183. * If a function will be handled by the interpreter, including the case
  184. * of it being undefined, then the fn1() cell will tell me so.
  185. */
  186. {
  187. return (
  188. qfn1(a) == interpreted1 ||
  189. qfn1(a) == traceinterpreted1 ||
  190. qfn1(a) == double_interpreted1 ||
  191. qfn1(a) == funarged1 ||
  192. qfn1(a) == tracefunarged1 ||
  193. qfn1(a) == double_funarged1 ||
  194. qfn1(a) == undefined1);
  195. }
  196. #endif
  197. static char *show_fn(void *p)
  198. {
  199. int i;
  200. for (i=0; i<entry_table_size; i++)
  201. if (entries_table[i].p == p) return 1+entries_table[i].s;
  202. trace_printf("+++ Unknown function pointer = %lx\n", (long)p);
  203. return "unknown";
  204. }
  205. Lisp_Object Lsymbol_fn_cell(Lisp_Object nil, Lisp_Object a)
  206. /*
  207. * For debugging...
  208. */
  209. {
  210. char *s1, *s2, *sn;
  211. if (!symbolp(a)) return onevalue(nil);
  212. s1 = show_fn((void *)qfn1(a));
  213. s2 = show_fn((void *)qfn2(a));
  214. sn = show_fn((void *)qfnn(a));
  215. trace_printf("%s %s %s\n", s1, s2, sn);
  216. return onevalue(nil);
  217. }
  218. Lisp_Object Lsymbol_argcount(Lisp_Object nil, Lisp_Object a)
  219. /*
  220. * For debugging and JIT compiler use. Only valid if the function involved
  221. * is byte-coded. For simple functions taking a fixed number of args the
  222. * result is an integer. Otherwise it is a list of 3 items
  223. * (fewest-legal-args most-args-before-&rest flags)
  224. * where the flags has a 1 bit if missing &optional args are to be left
  225. * for the bytecoded stuff to unpick, otherwise they should be mapped to nil
  226. * somewhere. The 2 bit is present if a &rest argument is present.
  227. */
  228. {
  229. one_args *f1;
  230. two_args *f2;
  231. n_args *fn;
  232. int low, high, hardrest;
  233. Lisp_Object r;
  234. unsigned char *b;
  235. if (!symbolp(a)) return onevalue(nil);
  236. f1 = qfn1(a);
  237. f2 = qfn2(a);
  238. fn = qfnn(a);
  239. r = qenv(a);
  240. if (!consp(r)) return onevalue(nil);
  241. r = qcar(r);
  242. if (!is_bps(r)) return onevalue(nil);
  243. b = (unsigned char *)data_of_bps(r);
  244. if (f1 == bytecoded1 ||
  245. f1 == tracebytecoded1 ||
  246. f1 == double_bytecoded1) return onevalue(fixnum_of_int(1));
  247. if (f2 == bytecoded2 ||
  248. f2 == tracebytecoded2 ||
  249. f2 == double_bytecoded2) return onevalue(fixnum_of_int(2));
  250. if (fn == bytecoded0 ||
  251. fn == tracebytecoded0 ||
  252. fn == double_bytecoded0) return onevalue(fixnum_of_int(0));
  253. if (fn == bytecoded3 ||
  254. fn == tracebytecoded3 ||
  255. fn == double_bytecoded3) return onevalue(fixnum_of_int(3));
  256. if (fn == bytecodedn ||
  257. fn == tracebytecodedn ||
  258. fn == double_bytecodedn) return onevalue(fixnum_of_int(b[0]));
  259. low = b[0]; /* smallest number of valid args */
  260. high = low + b[1]; /* largest number before &rest is accounted for */
  261. hardrest = 0;
  262. /*
  263. * byteopt - optional arguments, with default of NIL
  264. */
  265. if (f1 == byteopt1 ||
  266. f1 == tracebyteopt1) hardrest = 0;
  267. /*
  268. * hardopt - optional arguments but default is passed as a SPID so that
  269. * the user can follow up and apply cleverer default processing
  270. */
  271. else if (f1 == hardopt1 ||
  272. f1 == tracehardopt1) hardrest = 1;
  273. /*
  274. * byteoptrest - anything with a &rest argument on the end.
  275. */
  276. else if (f1 == byteoptrest1 ||
  277. f1 == tracebyteoptrest1) hardrest = 1;
  278. /*
  279. * hardoptrest - some &optional args with non-nil default value, plus &rest
  280. */
  281. else if (f1 == hardoptrest1 ||
  282. f1 == tracehardoptrest1) hardrest = 3;
  283. else return onevalue(nil);
  284. r = list3(fixnum_of_int(low),
  285. fixnum_of_int(high), fixnum_of_int(hardrest));
  286. errexit();
  287. return onevalue(r);
  288. }
  289. Lisp_Object Lsymbol_env(Lisp_Object nil, Lisp_Object a)
  290. /*
  291. * Not Common Lisp - read the 'environment' cell associated with a
  292. * symbol. This cell is deemed empty unless the symbol-function is
  293. * compiled code. For use mainly for debugging.
  294. */
  295. {
  296. if (!symbolp(a)) return onevalue(nil);
  297. #ifdef HIDE_USELESS_SYMBOL_ENVIRONMENTS
  298. else if ((qheader(a) & (SYM_SPECIAL_FORM | SYM_MACRO)) != 0 ||
  299. interpreter_entry(a)) return onevalue(nil);
  300. #endif
  301. return onevalue(qenv(a));
  302. }
  303. Lisp_Object Lsymbol_set_env(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  304. {
  305. CSL_IGNORE(nil);
  306. if (!is_symbol(a)) return aerror1("symbol-set-env", a);
  307. if ((qheader(a) & (SYM_C_DEF | SYM_CODEPTR)) ==
  308. (SYM_C_DEF | SYM_CODEPTR)) return onevalue(nil);
  309. qenv(a) = b;
  310. return onevalue(b);
  311. }
  312. Lisp_Object Lsymbol_fastgets(Lisp_Object nil, Lisp_Object a)
  313. {
  314. if (!symbolp(a)) return onevalue(nil);
  315. return onevalue(qfastgets(a));
  316. }
  317. /*
  318. * (protect 'name t) arranges that the function indicated (which is
  319. * expected to have been defined in the C kernel) can not be redefined.
  320. * (protect 'name nil) restores the usual state of affairs.
  321. */
  322. Lisp_Object Lsymbol_protect(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  323. {
  324. Header h;
  325. if (!is_symbol(a)) return onevalue(nil);
  326. h = qheader(a);
  327. if (b == nil) qheader(a) = h & ~(SYM_CODEPTR | SYM_C_DEF);
  328. else qheader(a) = h | SYM_CODEPTR | SYM_C_DEF;
  329. h &= (SYM_CODEPTR | SYM_C_DEF);
  330. return onevalue(Lispify_predicate(h == (SYM_CODEPTR | SYM_C_DEF)));
  331. }
  332. /*
  333. * (symbol-make-fastget 'xxx nil) returns current information, nil if no
  334. * fastget usage set.
  335. * (symbol-make-fastget 'xxx n) sets it to n (0 <= n < 63)
  336. * (symbol-make-fastget 'xxx -1) sets the option off
  337. * (symbol-make-fastget n) specify fast-get range (n <= 63)
  338. */
  339. Lisp_Object Lsymbol_make_fastget1(Lisp_Object nil, Lisp_Object a)
  340. {
  341. int32 n, n1 = fastget_size;
  342. CSL_IGNORE(nil);
  343. if (!is_fixnum(a) ||
  344. (n = int_of_fixnum(a)) < 0 ||
  345. (n > MAX_FASTGET_SIZE)) return aerror1("symbol-make-fastget", a);
  346. term_printf("+++ Fastget size was %d, now %d\n", n1, n);
  347. fastget_size = n;
  348. return onevalue(fixnum_of_int(n1));
  349. }
  350. Lisp_Object Lsymbol_make_fastget(Lisp_Object nil, Lisp_Object a, Lisp_Object n)
  351. {
  352. int32 n1, p, q;
  353. Header h;
  354. if (!symbolp(a)) return onevalue(nil);
  355. h = qheader(a);
  356. p = header_fastget(h);
  357. if (is_fixnum(n))
  358. { n1 = int_of_fixnum(n);
  359. if (n1 < -1 || n1 >= fastget_size)
  360. return aerror1("symbol-make-fastget", n);
  361. trace_printf("+++ Use fastget slot %d for ", n1);
  362. loop_print_trace(a);
  363. errexit();
  364. trace_printf("\n");
  365. if (p != 0) elt(fastget_names, p-1) = SPID_NOPROP;
  366. q = (n1 + 1) & 0x3f;
  367. h = (h & ~SYM_FASTGET_MASK) | (q << SYM_FASTGET_SHIFT);
  368. qheader(a) = h;
  369. if (q != 0) elt(fastget_names, q-1) = a;
  370. }
  371. if (p == 0) return onevalue(nil);
  372. else return onevalue(fixnum_of_int(p - 1));
  373. }
  374. static Lisp_Object deleqip(Lisp_Object a, Lisp_Object l)
  375. /*
  376. * This deletes the item a (tested for using EQ) from the list l,
  377. * assuming that the list is nil-terminated and that the item a
  378. * occurs at most once. It overwrites the list l in the process.
  379. */
  380. {
  381. Lisp_Object nil = C_nil, w, r;
  382. if (l == nil) return nil;
  383. if (qcar(l) == a) return qcdr(l);
  384. r = l;
  385. while (w = l, (l = qcdr(l)) != nil)
  386. { if (qcar(l) == a)
  387. { qcdr(w) = qcdr(l);
  388. return r;
  389. }
  390. }
  391. return r;
  392. }
  393. void lose_C_def(Lisp_Object a)
  394. {
  395. /*
  396. * None of the code here can cause garbage collection.
  397. */
  398. #ifdef COMMON
  399. Lisp_Object nil = C_nil;
  400. Lisp_Object b = get(a, unset_var, nil), c;
  401. #else
  402. nil_as_base
  403. Lisp_Object b = get(a, unset_var), c;
  404. #endif
  405. Lremprop(C_nil, a, unset_var);
  406. qheader(a) &= ~SYM_C_DEF;
  407. #ifdef COMMON
  408. c = get(b, work_symbol, nil);
  409. #else
  410. c = get(b, work_symbol);
  411. #endif
  412. c = deleqip(a, c);
  413. if (c == C_nil) Lremprop(C_nil, b, work_symbol);
  414. else putprop(b, work_symbol, c);
  415. }
  416. /*
  417. * (symbol-set-native fn args bpsbase offset env)
  418. * where bpsbase is as handed back by (make-native nnn) and offset is
  419. * the offset in this block to enter at.
  420. * If args has the actual arg count in its bottom byte. Usually the
  421. * rest of it will be zero, and then one function cell is set to point to the
  422. * given entrypoint and the other two are set to point at error handlers.
  423. * If any bits in args beyond that are set then this call only changes the
  424. * directly specified function cell, and the others are left in whatever state
  425. * they were. If several of the fuction cells are to be filled in (eg to cope
  426. * with &optional or &rest arguments) then a simple call with args<256 must
  427. * be made first, followed by the calls (args>=256) that fill in the other
  428. * two cells.
  429. * The first time that symbol-set-native is called on a function that
  430. * function MUST have a byte coded definition, and this definition is
  431. * picked up and stored away, so that if (preserve) is called the bytecoded
  432. * definition will be available for use on systems with different
  433. * architectures. To make things tolerably consistent with that any operation
  434. * that installs a new bytecoded (or for that matter other) definition
  435. * will clear away any native-compiled versions of the function.
  436. *
  437. * The native code that is installed will be expected to have relocation
  438. * records starting at the start of bpsbase, and these will be activated,
  439. * filling in references from the bps to other executable parts of Lisp.
  440. * Passing bad arguments to this function provide a quick and easy way to
  441. * cayse UTTER havoc. Therefore I disable its use in server applications.
  442. */
  443. Lisp_Object MS_CDECL Lsymbol_set_native(Lisp_Object nil, int nargs, ...)
  444. {
  445. va_list a;
  446. Lisp_Object fn, args, bpsbase, offset, env, w1, w2, w3;
  447. int32 pagenumber, t_p, arginfo;
  448. intxx address, page, bps;
  449. #ifdef SOCKETS
  450. /*
  451. * Security measure - deny symbol-set-native to remote users
  452. */
  453. if (socket_server != 0) return aerror("symbol-set-native");
  454. #endif
  455. argcheck(nargs, 5, "symbol-set-native");
  456. va_start(a, nargs);
  457. fn = va_arg(a, Lisp_Object);
  458. args = va_arg(a, Lisp_Object);
  459. bpsbase = va_arg(a, Lisp_Object);
  460. offset = va_arg(a, Lisp_Object);
  461. env = va_arg(a, Lisp_Object);
  462. va_end(a);
  463. if (!is_symbol(fn) ||
  464. (qheader(fn) & (SYM_SPECIAL_FORM | SYM_CODEPTR)) != 0)
  465. return aerror1("symbol-set-native", fn);
  466. if (!is_fixnum(args)) return aerror1("symbol-set-native", args);
  467. if (!consp(bpsbase) ||
  468. !is_fixnum(qcar(bpsbase)) ||
  469. !is_fixnum(qcdr(bpsbase)))
  470. return aerror1("symbol-set-native", bpsbase);
  471. if (!is_fixnum(offset)) return aerror1("symbol-set-native", offset);
  472. nargs = int_of_fixnum(args);
  473. pagenumber = int_of_fixnum(qcar(bpsbase));
  474. if (pagenumber<0 || pagenumber>=native_pages_count)
  475. return aerror1("symbol-set-native", bpsbase);
  476. bps = int_of_fixnum(qcdr(bpsbase));
  477. address = bps+int_of_fixnum(offset);
  478. if (address<8 || address>=CSL_PAGE_SIZE)
  479. return aerror1("symbol-set-native", offset);
  480. page = (intxx)native_pages[pagenumber];
  481. page = doubleword_align_up(page);
  482. bps = page + bps;
  483. relocate_native_function((unsigned char *)bps);
  484. /*
  485. * Here I need to push the info I have just collected onto
  486. * the native_code list since otherwise things will not be re-loaded in
  487. * from a checkpoint image. Also if the function is at present byte-coded
  488. * I need to record that info about it in native_code.
  489. */
  490. w1 = native_code;
  491. w2 = nil;
  492. while (w1!=nil)
  493. { w2 = qcar(w1);
  494. if (qcar(w2) == fn) break;
  495. w1 = qcdr(w1);
  496. }
  497. if (w1 == nil)
  498. {
  499. /*
  500. * Here the function has not been seen as native code ever before, so it has
  501. * not been entered into the list. Do something about that...
  502. */
  503. push2(env, fn);
  504. args = Lsymbol_argcount(nil, fn);
  505. errexitn(2);
  506. if (args == nil)
  507. return aerror1("No bytecode definition found for", fn);
  508. /*
  509. * Now I have to reverse the information that symbol_argcount gave me
  510. * to get the single numeric code as wanted by symbol_set_definition.
  511. * Oh what a mess.
  512. */
  513. if (is_fixnum(args)) arginfo = int_of_fixnum(args);
  514. else
  515. { arginfo = int_of_fixnum(qcar(args));
  516. args = qcdr(args);
  517. arginfo |= ((int_of_fixnum(qcar(args)) - arginfo) << 8);
  518. args = qcdr(args);
  519. arginfo |= int_of_fixnum(qcar(args)) << 16;
  520. }
  521. fn = stack[0];
  522. w2 = list2(fn, fixnum_of_int(arginfo));
  523. errexitn(2);
  524. w2 = cons(w2, native_code);
  525. errexitn(2);
  526. native_code = w2;
  527. w2 = qcar(w2);
  528. pop2(fn, env);
  529. }
  530. w2 = qcdr(w2); /* {nargs,(type . offset . env),...} */
  531. /*
  532. * If I was defining this function in the simple way I should clear any
  533. * previous version (for this machine architecture) from the record.
  534. * Just at present this does not release the memory, but at some stage
  535. * in the future I may arrange to compact away old code when I do a
  536. * preserve operation (say).
  537. */
  538. if (nargs <= 0xff)
  539. { w1 = w3 = w2;
  540. for (w1=qcdr(w2); w1!=nil; w1=qcdr(w1))
  541. { w3 = qcar(w1);
  542. if (qcar(w3) == fixnum_of_int(native_code_tag)) break;
  543. w3 = w1;
  544. }
  545. if (w1 != nil) qcdr(w3) = qcdr(w1);
  546. }
  547. /*
  548. * w2 is still the entry for this function in the native code list. It
  549. * needs to have an entry of type 0 (ie for bytecoded) and so the next
  550. * thing to do is to check that such an entry exists and if not to create
  551. * it.
  552. */
  553. w1 = w2;
  554. while ((w1 = qcdr(w1)) != nil)
  555. { w3 = qcar(w1);
  556. if (qcar(w3) == fixnum_of_int(0)) break;
  557. w1 = qcdr(w1);
  558. }
  559. if (w1 == nil)
  560. {
  561. /*
  562. * This is where there was no bytecode entry on the native code list
  563. * for this function, so I had better create one for it. Note that only
  564. * one such entry will ever be stored so it does not matter much where on
  565. * the list it goes. I suspect that the list ought always to be empty
  566. * in this case anyway.
  567. */
  568. push3(fn, env, w2);
  569. w1 = list2star(fixnum_of_int(0), fixnum_of_int(0), qenv(fn));
  570. errexitn(3);
  571. w2 = stack[0];
  572. w1 = cons(w1, qcdr(w2));
  573. errexitn(3);
  574. pop3(w2, env, fn);
  575. qcdr(w2) = w1;
  576. }
  577. /*
  578. * Now the list of native code associated with this function certainly holds
  579. * a byte-coded definition (and for sanity that had better be consistent
  580. * with the native code I am installing now, but that is not something
  581. * that can be checked at this level). Put in an entry referring to the
  582. * current gubbins.
  583. */
  584. push3(w2, fn, env);
  585. /*
  586. * now I pack the code type, arg category and offset into the
  587. * single fixnum that that information has to end up in.
  588. */
  589. t_p = (native_code_tag << 20);
  590. if ((nargs & 0xffffff00) != 0)
  591. {
  592. switch (nargs & 0xff)
  593. {
  594. case 1: t_p |= (1<<18); break;
  595. case 2: t_p |= (2<<18); break;
  596. default:t_p |= (3<<18); break;
  597. }
  598. }
  599. t_p |= (pagenumber & 0x3ffff);
  600. w1 = list2star(fixnum_of_int(t_p), fixnum_of_int(address), env);
  601. errexitn(3);
  602. w1 = ncons(w1);
  603. pop3(env, fn, w2);
  604. errexit();
  605. while ((w3 = qcdr(w2)) != nil) w2 = w3; /* Tag onto the END */
  606. qcdr(w2) = w1;
  607. qheader(fn) &= ~SYM_TRACED;
  608. address = page + address;
  609. /*
  610. * The code here must do just about the equivalent to that in restart.c
  611. */
  612. switch (nargs & 0xff)
  613. {
  614. case 0: ifnn(fn) = address;
  615. if (nargs<=0xff)
  616. ifn1(fn) = (int32)wrong_no_0a, ifn2(fn) = (int32)wrong_no_0b;
  617. break;
  618. case 1: ifn1(fn) = address;
  619. if (nargs<=0xff)
  620. ifn2(fn) = (int32)too_many_1, ifnn(fn) = (int32)wrong_no_1;
  621. break;
  622. case 2: ifn2(fn) = address;
  623. if (nargs<=0xff)
  624. ifn1(fn) = (int32)too_few_2, ifnn(fn) = (int32)wrong_no_2;
  625. break;
  626. case 3: ifnn(fn) = address;
  627. if (nargs<=0xff)
  628. ifn1(fn) = (int32)wrong_no_3a, ifn2(fn) = (int32)wrong_no_3b;
  629. break;
  630. default: ifnn(fn) = address;
  631. if (nargs<=0xff)
  632. ifn1(fn) = (int32)wrong_no_na, ifn2(fn) = (int32)wrong_no_nb;
  633. break;
  634. }
  635. qenv(fn) = env;
  636. return onevalue(fn);
  637. }
  638. static CSLbool restore_fn_cell(Lisp_Object a, char *name,
  639. int32 len, setup_type const s[])
  640. {
  641. int i;
  642. for (i=0; s[i].name != NULL; i++)
  643. { if (strlen(s[i].name) == (size_t)len &&
  644. memcmp(name, s[i].name, len) == 0) break;
  645. }
  646. if (s[i].name == NULL) return NO;
  647. set_fns(a, s[i].one, s[i].two, s[i].n);
  648. return YES;
  649. }
  650. static Lisp_Object Lrestore_c_code(Lisp_Object nil, Lisp_Object a)
  651. {
  652. char *name;
  653. int32 len;
  654. Lisp_Object pn;
  655. if (!symbolp(a)) return aerror1("restore-c-code", a);
  656. push(a);
  657. pn = get_pname(a);
  658. pop(a);
  659. errexit();
  660. name = (char *)&celt(pn, 0);
  661. len = length_of_header(vechdr(pn)) - 4;
  662. if (restore_fn_cell(a, name, len, u01_setup) ||
  663. restore_fn_cell(a, name, len, u02_setup) ||
  664. restore_fn_cell(a, name, len, u03_setup) ||
  665. restore_fn_cell(a, name, len, u04_setup) ||
  666. restore_fn_cell(a, name, len, u05_setup) ||
  667. restore_fn_cell(a, name, len, u06_setup) ||
  668. restore_fn_cell(a, name, len, u07_setup) ||
  669. restore_fn_cell(a, name, len, u08_setup) ||
  670. restore_fn_cell(a, name, len, u09_setup) ||
  671. restore_fn_cell(a, name, len, u10_setup) ||
  672. restore_fn_cell(a, name, len, u11_setup) ||
  673. restore_fn_cell(a, name, len, u12_setup))
  674. { Lisp_Object env;
  675. push(a);
  676. #ifdef COMMON
  677. env = get(a, funarg, nil);
  678. #else
  679. env = get(a, funarg);
  680. #endif
  681. pop(a);
  682. errexit();
  683. qenv(a) = env;
  684. return onevalue(a);
  685. }
  686. else return onevalue(nil);
  687. }
  688. Lisp_Object Lsymbol_set_definition(Lisp_Object nil,
  689. Lisp_Object a, Lisp_Object b)
  690. /*
  691. * The odd case here is where the second argument represents a freshly
  692. * created bit of compiled code. In which case the structure is
  693. * (nargs . codevec . envvec)
  694. * where nargs is an integer indicating the number of arguments, codevec
  695. * is a vector of bytecodes, and envvec is something to go in the
  696. * environment cell of the symbol.
  697. * Here the low 8 bits of nargs indicate the number of required arguments.
  698. * The next 8 bits give the number of optional arguments, and the next
  699. * two bits are flags. Of these, the first is set if any of the optional
  700. * arguments has an initform or supplied-p associate, and the other
  701. * indicates that a "&rest" argument is required.
  702. * Bits beyond that (if non-zero) indicate that the function definition
  703. * is of the form (defun f1 (a b c) (f2 a b)) and the number coded is the
  704. * length of the function body.
  705. * Standard Lisp does not need &optional or &rest arguments, but it turned
  706. * out to be pretty easy to make the bytecode compiler support them.
  707. */
  708. {
  709. if (!is_symbol(a) ||
  710. /*
  711. * Something flagged with the CODEPTR bit is a gensym manufactured to
  712. * stand for a compiled-code object. It should NOT be reset!
  713. */
  714. (qheader(a) & (SYM_SPECIAL_FORM | SYM_CODEPTR)) != 0)
  715. { if (qheader(a) & SYM_C_DEF) return onevalue(nil);
  716. return aerror1("symbol-set-definition", a);
  717. }
  718. qheader(a) &= ~SYM_TRACED;
  719. set_fns(a, undefined1, undefined2, undefinedn); /* Tidy up first */
  720. qenv(a) = a;
  721. if ((qheader(a) & SYM_C_DEF) != 0) lose_C_def(a);
  722. if (b == nil) return onevalue(b); /* set defn to nil to undefine */
  723. else if (symbolp(b))
  724. {
  725. /*
  726. * One could imagine a view that the second arg to symbol-set-definition
  727. * had to be a codepointer object. I will be kind (?) and permit the NAME
  728. * of a function too. However for the second arg to be a macro or a
  729. * special form would still be a calamity.
  730. * if ((qheader(b) & SYM_CODEPTR) == 0)
  731. * return aerror1("symbol-set-definition", b);
  732. */
  733. if ((qheader(b) & (SYM_SPECIAL_FORM | SYM_MACRO)) != 0)
  734. return aerror1("symbol-set-definition", b);
  735. qheader(a) = qheader(a) & ~SYM_MACRO;
  736. { set_fns(a, qfn1(b), qfn2(b), qfnn(b));
  737. qenv(a) = qenv(b);
  738. /*
  739. * In order that checkpoint files can be made there is some very
  740. * ugly fooling around here for functions that are defined in the C coded
  741. * kernel. Sorry.
  742. */
  743. if ((qheader(b) & SYM_C_DEF) != 0)
  744. {
  745. #ifdef COMMON
  746. Lisp_Object c = get(b, unset_var, nil);
  747. #else
  748. Lisp_Object c = get(b, unset_var);
  749. #endif
  750. if (c == nil) c = b;
  751. push2(c, a);
  752. putprop(a, unset_var, c);
  753. errexitn(2);
  754. pop(a);
  755. #ifdef COMMON
  756. a = cons(a, get(stack[0], work_symbol, nil));
  757. #else
  758. a = cons(a, get(stack[0], work_symbol));
  759. #endif
  760. errexitn(1);
  761. putprop(stack[0], work_symbol, a);
  762. pop(b);
  763. errexit();
  764. }
  765. }
  766. }
  767. else if (!consp(b)) return aerror1("symbol-set-definition", b);
  768. else if (is_fixnum(qcar(b)))
  769. { int32 nargs = (int)int_of_fixnum(qcar(b)), nopts, flagbits, ntail;
  770. nopts = nargs >> 8;
  771. flagbits = nopts >> 8;
  772. ntail = flagbits >> 2;
  773. nargs &= 0xff;
  774. nopts &= 0xff;
  775. flagbits &= 3;
  776. if (ntail != 0)
  777. { switch (100*nargs + ntail-1)
  778. {
  779. case 300: set_fns(a, wrong_no_na, wrong_no_nb, f3_as_0); break;
  780. case 301: set_fns(a, wrong_no_na, wrong_no_nb, f3_as_1); break;
  781. case 302: set_fns(a, wrong_no_na, wrong_no_nb, f3_as_2); break;
  782. case 303: set_fns(a, wrong_no_na, wrong_no_nb, f3_as_3); break;
  783. case 200: set_fns(a, too_few_2, f2_as_0, wrong_no_2); break;
  784. case 201: set_fns(a, too_few_2, f2_as_1, wrong_no_2); break;
  785. case 202: set_fns(a, too_few_2, f2_as_2, wrong_no_2); break;
  786. case 100: set_fns(a, f1_as_0, too_many_1, wrong_no_1); break;
  787. case 101: set_fns(a, f1_as_1, too_many_1, wrong_no_1); break;
  788. case 000: set_fns(a, wrong_no_na, wrong_no_nb, f0_as_0); break;
  789. }
  790. b = qcdr(b);
  791. }
  792. else if (flagbits != 0 || nopts != 0)
  793. { if ((qheader(a) & SYM_TRACED) == 0) switch(flagbits)
  794. {
  795. default:
  796. case 0: /* easy case optional arguments */
  797. set_fns(a, byteopt1, byteopt2, byteoptn); break;
  798. case 1: /* optional args, but non-nil default, or supplied-p extra */
  799. set_fns(a, hardopt1, hardopt2, hardoptn); break;
  800. case 2: /* easy opt args, but also a &rest arg */
  801. set_fns(a, byteoptrest1, byteoptrest2, byteoptrestn); break;
  802. case 3: /* complicated &options and &rest */
  803. set_fns(a, hardoptrest1, hardoptrest2, hardoptrestn); break;
  804. }
  805. else switch (flagbits)
  806. {
  807. default:
  808. case 0: /* easy case optional arguments */
  809. set_fns(a, tracebyteopt1, tracebyteopt2, tracebyteoptn); break;
  810. case 1: /* optional args, but non-nil default, or supplied-p extra */
  811. set_fns(a, tracehardopt1, tracehardopt2, tracehardoptn); break;
  812. case 2: /* easy opt args, but also a &rest arg */
  813. set_fns(a, tracebyteoptrest1, tracebyteoptrest2, tracebyteoptrestn); break;
  814. case 3: /* complicated &options and &rest */
  815. set_fns(a, tracehardoptrest1, tracehardoptrest2, tracehardoptrestn); break;
  816. }
  817. }
  818. else
  819. { if (nargs > 4) nargs = 4;
  820. if ((qheader(a) & SYM_TRACED) != 0) nargs += 5;
  821. qheader(a) = qheader(a) & ~SYM_MACRO;
  822. switch (nargs)
  823. {
  824. case 0: set_fns(a, wrong_no_0a, wrong_no_0b, bytecoded0);
  825. break;
  826. case 1: set_fns(a, bytecoded1, too_many_1, wrong_no_1);
  827. break;
  828. case 2: set_fns(a, too_few_2, bytecoded2, wrong_no_2);
  829. break;
  830. case 3: set_fns(a, wrong_no_3a, wrong_no_3b, bytecoded3);
  831. break;
  832. default:
  833. case 4: set_fns(a, wrong_no_na, wrong_no_nb, bytecodedn);
  834. break;
  835. case 5+0: set_fns(a, wrong_no_0a, wrong_no_0b, tracebytecoded0);
  836. break;
  837. case 5+1: set_fns(a, tracebytecoded1, too_many_1, wrong_no_1);
  838. break;
  839. case 5+2: set_fns(a, too_few_2, tracebytecoded2, wrong_no_2);
  840. break;
  841. case 5+3: set_fns(a, wrong_no_3a, wrong_no_3b, tracebytecoded3);
  842. break;
  843. case 5+4: set_fns(a, wrong_no_na, wrong_no_nb, tracebytecodedn);
  844. break;
  845. }
  846. }
  847. qenv(a) = qcdr(b);
  848. }
  849. else if (qcar(b) == lambda)
  850. { Lisp_Object bvl = qcar(qcdr(b));
  851. int nargs = 0;
  852. while (consp(bvl)) nargs++, bvl = qcdr(bvl);
  853. qheader(a) = qheader(a) & ~SYM_MACRO;
  854. if ((qheader(a) & SYM_TRACED) != 0)
  855. set_fns(a, traceinterpreted1, traceinterpreted2, traceinterpretedn);
  856. else set_fns(a, interpreted1, interpreted2, interpretedn);
  857. qenv(a) = qcdr(b);
  858. if (qvalue(comp_symbol) != nil &&
  859. qfn1(compiler_symbol) != undefined1)
  860. { push(a);
  861. a = ncons(a);
  862. errexitn(1);
  863. (qfn1(compiler_symbol))(qenv(compiler_symbol), a);
  864. pop(a);
  865. errexit();
  866. }
  867. }
  868. else if (qcar(b) == funarg)
  869. { Lisp_Object bvl = qcar(qcdr(b));
  870. int nargs = 0;
  871. while (consp(bvl)) nargs++, bvl = qcdr(bvl);
  872. qheader(a) = qheader(a) & ~SYM_MACRO;
  873. if ((qheader(a) & SYM_TRACED) != 0)
  874. set_fns(a, tracefunarged1, tracefunarged2, tracefunargedn);
  875. else set_fns(a, funarged1, funarged2, funargedn);
  876. qenv(a) = qcdr(b);
  877. }
  878. else return aerror1("symbol-set-definition", b);
  879. return onevalue(b);
  880. }
  881. Lisp_Object Lgetd(Lisp_Object nil, Lisp_Object a)
  882. {
  883. Header h;
  884. Lisp_Object type;
  885. CSL_IGNORE(nil);
  886. if (a == nil) return onevalue(nil);
  887. else if (!is_symbol(a)) return onevalue(nil);
  888. h = qheader(a);
  889. if ((h & SYM_SPECIAL_FORM) != 0) type = fexpr_symbol;
  890. else if ((h & SYM_MACRO) != 0)
  891. { a = cons(lambda, qenv(a));
  892. errexit();
  893. type = macro_symbol;
  894. }
  895. else
  896. { a = Lsymbol_function(nil, a);
  897. errexit();
  898. if (a == nil) return onevalue(nil);
  899. type = expr_symbol;
  900. }
  901. a = cons(type, a);
  902. errexit();
  903. return onevalue(a);
  904. }
  905. Lisp_Object Lremd(Lisp_Object nil, Lisp_Object a)
  906. {
  907. Lisp_Object res;
  908. CSL_IGNORE(nil);
  909. if (!is_symbol(a) ||
  910. (qheader(a) & SYM_SPECIAL_FORM) != 0)
  911. return aerror1("remd", a);
  912. if ((qheader(a) & (SYM_C_DEF | SYM_CODEPTR)) ==
  913. (SYM_C_DEF | SYM_CODEPTR)) return onevalue(nil);
  914. res = Lgetd(nil, a);
  915. errexit();
  916. if (res == nil) return onevalue(nil); /* no definition to remove */
  917. /*
  918. * I treat an explicit use of remd as a redefinition, and ensure that
  919. * restarting a preserved image will not put the definition back.
  920. */
  921. qheader(a) = qheader(a) & ~SYM_MACRO;
  922. if ((qheader(a) & SYM_C_DEF) != 0) lose_C_def(a);
  923. set_fns(a, undefined1, undefined2, undefinedn);
  924. qenv(a) = a;
  925. return onevalue(res);
  926. }
  927. /*
  928. * For set-autoload the first argument must be a symbol that will name
  929. * a function, the second arg is either an atom or a list of atoms, each
  930. * of which specified a module to be loaded if the names function is
  931. * called. Loading the modules is expected to instate a definition for the
  932. * function involved. This function is arranged so it does NOT do anything
  933. * if the function being set for autoloading is already defined. This is
  934. * on the supposition that the existing definition is in fact the desired
  935. * one, say because the relevant module happens to have been loaded already.
  936. * An explicit use of remd first can be used to ensure that no previous
  937. * definition is present and thus that a real autoload stub will be instated,
  938. * if that is what you really want.
  939. */
  940. Lisp_Object Lset_autoload(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  941. {
  942. Lisp_Object res;
  943. CSL_IGNORE(nil);
  944. if (!is_symbol(a) ||
  945. (qheader(a) & SYM_SPECIAL_FORM) != 0)
  946. return aerror1("set-autoload", a);
  947. if (!(qfn1(a) == undefined1 && qfn2(a) == undefined2 &&
  948. qfnn(a) == undefinedn)) return onevalue(nil);
  949. if ((qheader(a) & (SYM_C_DEF | SYM_CODEPTR)) ==
  950. (SYM_C_DEF | SYM_CODEPTR)) return onevalue(nil);
  951. push2(a, b);
  952. if (consp(b)) res = cons(a, b);
  953. else res = list2(a, b);
  954. pop2(b, a);
  955. errexit();
  956. /*
  957. * I treat an explicit use of set-autoload as a redefinition, and ensure that
  958. * restarting a preserved image will not put the definition back. Note that
  959. * I will not allow autoloadable macros...
  960. */
  961. qheader(a) = qheader(a) & ~SYM_MACRO;
  962. if ((qheader(a) & SYM_C_DEF) != 0) lose_C_def(a);
  963. set_fns(a, autoload1, autoload2, autoloadn);
  964. qenv(a) = res;
  965. return onevalue(res);
  966. }
  967. #define pack_funtable(a, n) ((((int32)(a)) << 16) | (n))
  968. #define funtable_nargs(u) ((u) >> 16)
  969. #define funtable_index(u) ((u) & 0xffffU)
  970. static one_args *displaced1 = NULL;
  971. static two_args *displaced2;
  972. static n_args *displacedn;
  973. static unsigned32 table_entry;
  974. static Lisp_Object traced1_function(Lisp_Object env, Lisp_Object a)
  975. {
  976. Lisp_Object name, nil = C_nil;
  977. Lisp_Object r = nil;
  978. /*
  979. * Worry about errors & garbage collection in following calls to print fns
  980. * This MUST be fixed sometime fairly soon... but then it could only bite
  981. * people using the trace facility, and their code is already dead!
  982. */
  983. freshline_trace();
  984. loop_print_trace(tracedfn);
  985. push(tracedfn);
  986. trace_printf(" called (1 arg)\narg1: ");
  987. loop_print_trace(a);
  988. trace_printf("\n");
  989. r = (*displaced1)(env, a);
  990. pop(name);
  991. errexit();
  992. push(r);
  993. freshline_trace();
  994. loop_print_trace(name);
  995. trace_printf(" = ");
  996. loop_print_trace(r);
  997. trace_printf("\n");
  998. pop(r);
  999. return onevalue(r);
  1000. }
  1001. static Lisp_Object traced2_function(Lisp_Object env,
  1002. Lisp_Object a, Lisp_Object b)
  1003. {
  1004. Lisp_Object name, nil = C_nil;
  1005. Lisp_Object r = nil;
  1006. freshline_trace();
  1007. loop_print_trace(tracedfn);
  1008. push(tracedfn);
  1009. trace_printf(" called (2 args)\narg1:");
  1010. loop_print_trace(a);
  1011. trace_printf("\narg2: ");
  1012. loop_print_trace(b);
  1013. trace_printf("\n");
  1014. r = (*displaced2)(env, a, b);
  1015. pop(name);
  1016. errexit();
  1017. push(r);
  1018. freshline_trace();
  1019. loop_print_trace(name);
  1020. trace_printf(" = ");
  1021. loop_print_trace(r);
  1022. trace_printf("\n");
  1023. pop(r);
  1024. return onevalue(r);
  1025. }
  1026. static Lisp_Object MS_CDECL tracedn_function(Lisp_Object env, int nargs, ...)
  1027. {
  1028. Lisp_Object name, nil = C_nil;
  1029. Lisp_Object r = nil;
  1030. int i;
  1031. va_list a;
  1032. push(tracedfn);
  1033. va_start(a, nargs);
  1034. push_args(a, nargs);
  1035. freshline_trace();
  1036. loop_print_trace(tracedfn);
  1037. trace_printf(" called (%d args)\n", nargs);
  1038. for (i=1; i<=nargs; i++)
  1039. { trace_printf("arg%d: ", i);
  1040. loop_print_trace(stack[i-nargs]);
  1041. trace_printf("\n");
  1042. }
  1043. if (nargs <= 15) switch (nargs)
  1044. {
  1045. default:
  1046. /*
  1047. * Calls with 1 or 2 args can never arise, since those cases have been
  1048. * split off for separate treatment.
  1049. */
  1050. popv(nargs+1);
  1051. return aerror("system error in trace mechanism");
  1052. case 0:
  1053. r = (*displacedn)(env, 0);
  1054. break;
  1055. case 3:
  1056. r = (*displacedn)(env, 3, stack[-2], stack[-1], stack[0]);
  1057. break;
  1058. case 4:
  1059. r = (*displacedn)(env, 4, stack[-3], stack[-2], stack[-1],
  1060. stack[0]);
  1061. break;
  1062. case 5:
  1063. r = (*displacedn)(env, 5, stack[-4], stack[-3], stack[-2],
  1064. stack[-1], stack[0]);
  1065. break;
  1066. case 6:
  1067. r = (*displacedn)(env, 6, stack[-5], stack[-4], stack[-3],
  1068. stack[-2], stack[-1], stack[0]);
  1069. break;
  1070. case 7:
  1071. r = (*displacedn)(env, 7, stack[-6], stack[-5], stack[-4],
  1072. stack[-3], stack[-2], stack[-1], stack[0]);
  1073. break;
  1074. case 8:
  1075. r = (*displacedn)(env, 8, stack[-7], stack[-6], stack[-5],
  1076. stack[-4], stack[-3], stack[-2], stack[-1],
  1077. stack[0]);
  1078. break;
  1079. case 9:
  1080. r = (*displacedn)(env, 9, stack[-8], stack[-7], stack[-6],
  1081. stack[-5], stack[-4], stack[-3], stack[-2],
  1082. stack[-1], stack[0]);
  1083. break;
  1084. case 10:
  1085. r = (*displacedn)(env, 10, stack[-9], stack[-8], stack[-7],
  1086. stack[-6], stack[-5], stack[-4], stack[-3],
  1087. stack[-2], stack[-1], stack[0]);
  1088. break;
  1089. case 11:
  1090. r = (*displacedn)(env, 11, stack[-10], stack[-9],
  1091. stack[-8], stack[-7], stack[-6], stack[-5],
  1092. stack[-4], stack[-3], stack[-2], stack[-1],
  1093. stack[0]);
  1094. break;
  1095. case 12:
  1096. r = (*displacedn)(env, 12, stack[-11], stack[-10],
  1097. stack[-9], stack[-8], stack[-7], stack[-6],
  1098. stack[-5], stack[-4], stack[-3], stack[-2],
  1099. stack[-1], stack[0]);
  1100. break;
  1101. case 13:
  1102. r = (*displacedn)(env, 13, stack[-12], stack[-11],
  1103. stack[-10], stack[-9], stack[-8], stack[-7],
  1104. stack[-6], stack[-5], stack[-4], stack[-3],
  1105. stack[-2], stack[-1], stack[0]);
  1106. break;
  1107. case 14:
  1108. r = (*displacedn)(env, 14, stack[-13], stack[-12],
  1109. stack[-11], stack[-10], stack[-9], stack[-8],
  1110. stack[-7], stack[-6], stack[-5], stack[-4],
  1111. stack[-3], stack[-2], stack[-1], stack[0]);
  1112. break;
  1113. case 15:
  1114. r = (*displacedn)(env, 15, stack[-14], stack[-13],
  1115. stack[-12], stack[-11], stack[-10], stack[-9],
  1116. stack[-8], stack[-7], stack[-6], stack[-5],
  1117. stack[-4], stack[-3], stack[-2], stack[-1],
  1118. stack[0]);
  1119. break;
  1120. }
  1121. else
  1122. { trace_printf("Too many arguments to trace a function\n");
  1123. /*
  1124. * Because the above is a horrid mess I will only support traced
  1125. * calls with at most 15 args (more than I expect most people to
  1126. * try). And this only applies to thigs that are NOT bytecoded -
  1127. * I can trace bytecoded things with more args I believe, so users are not
  1128. * utterly lost I hope.
  1129. */
  1130. return aerror("traced function with > 15 args: not supported");
  1131. }
  1132. popv(nargs);
  1133. pop(name);
  1134. errexit();
  1135. push(r);
  1136. freshline_trace();
  1137. loop_print_trace(name);
  1138. trace_printf(" = ");
  1139. loop_print_trace(r);
  1140. trace_printf("\n");
  1141. pop(r);
  1142. return onevalue(r);
  1143. }
  1144. #define NOT_FOUND 100
  1145. static unsigned32 find_built_in_function(one_args *f1,
  1146. two_args *f2,
  1147. n_args *fn)
  1148. /*
  1149. * This take the entrypoint of a function and tries to identify it
  1150. * by scanning the tables used by the bytecode interpreter. If the
  1151. * function is found a record is returned indicating how many args
  1152. * it takes, and what its index is in the relevant table. The code
  1153. * <NOT_FOUND,NOT_FOUND> is returned to indicate failure if the function
  1154. * is not found.
  1155. */
  1156. {
  1157. int32 index;
  1158. for (index=0; zero_arg_functions[index]!=NULL; index++)
  1159. if (fn == zero_arg_functions[index]) return pack_funtable(0, index);
  1160. for (index=0; one_arg_functions[index]!=NULL; index++)
  1161. if (f1 == one_arg_functions[index]) return pack_funtable(1, index);
  1162. for (index=0; two_arg_functions[index]!=NULL; index++)
  1163. if (f2 == two_arg_functions[index]) return pack_funtable(2, index);
  1164. for (index=0; three_arg_functions[index]!=NULL; index++)
  1165. if (fn == three_arg_functions[index]) return pack_funtable(3, index);
  1166. return pack_funtable(NOT_FOUND, NOT_FOUND);
  1167. }
  1168. Lisp_Object Ltrace_all(Lisp_Object nil, Lisp_Object a)
  1169. {
  1170. #ifdef DEBUG
  1171. if (a == nil) trace_all = 0;
  1172. else trace_all = 1;
  1173. return onevalue(nil);
  1174. #else
  1175. CSL_IGNORE(nil);
  1176. CSL_IGNORE(a);
  1177. return aerror("trace-all only supported in DEBUG version");
  1178. #endif
  1179. }
  1180. Lisp_Object Ltrace(Lisp_Object nil, Lisp_Object a)
  1181. {
  1182. Lisp_Object w = a;
  1183. if (symbolp(a))
  1184. { a = ncons(a);
  1185. errexit();
  1186. w = a;
  1187. }
  1188. while (consp(w))
  1189. { Lisp_Object s = qcar(w);
  1190. w = qcdr(w);
  1191. if (symbolp(s))
  1192. { one_args *f1 = qfn1(s);
  1193. two_args *f2 = qfn2(s);
  1194. n_args *fn = qfnn(s);
  1195. int fixenv = 0, done = 0;
  1196. if (f1 == undefined1)
  1197. { freshline_debug();
  1198. debug_printf("+++ ");
  1199. loop_print_debug(s);
  1200. debug_printf(" not yet defined\n");
  1201. continue;
  1202. }
  1203. qheader(s) |= SYM_TRACED;
  1204. if (f1 == interpreted1)
  1205. { set_fns(s, traceinterpreted1, traceinterpreted2, traceinterpretedn);
  1206. fixenv = done = 1;
  1207. }
  1208. if (f1 == funarged1)
  1209. { set_fns(s, tracefunarged1, tracefunarged2, tracefunargedn);
  1210. fixenv = done = 1;
  1211. }
  1212. if (fn == bytecoded0) ifnn(s) = (intxx)tracebytecoded0, done = 1;
  1213. if (f1 == bytecoded1) ifn1(s) = (intxx)tracebytecoded1, done = 1;
  1214. if (f2 == bytecoded2) ifn2(s) = (intxx)tracebytecoded2, done = 1;
  1215. if (fn == bytecoded3) ifnn(s) = (intxx)tracebytecoded3, done = 1;
  1216. if (fn == bytecodedn) ifnn(s) = (intxx)tracebytecodedn, done = 1;
  1217. if (f1 == byteopt1) ifn1(s) = (intxx)tracebyteopt1, done = 1;
  1218. if (f2 == byteopt2) ifn2(s) = (intxx)tracebyteopt2, done = 1;
  1219. if (fn == byteoptn) ifnn(s) = (intxx)tracebyteoptn, done = 1;
  1220. if (f1 == hardopt1) ifn1(s) = (intxx)tracehardopt1, done = 1;
  1221. if (f2 == hardopt2) ifn2(s) = (intxx)tracehardopt2, done = 1;
  1222. if (fn == hardoptn) ifnn(s) = (intxx)tracehardoptn, done = 1;
  1223. if (f1 == byteoptrest1) ifn1(s) = (intxx)tracebyteoptrest1, done = 1;
  1224. if (f2 == byteoptrest2) ifn2(s) = (intxx)tracebyteoptrest2, done = 1;
  1225. if (fn == byteoptrestn) ifnn(s) = (intxx)tracebyteoptrestn, done = 1;
  1226. if (f1 == hardoptrest1) ifn1(s) = (intxx)tracehardoptrest1, done = 1;
  1227. if (f2 == hardoptrest2) ifn2(s) = (intxx)tracehardoptrest2, done = 1;
  1228. if (fn == hardoptrestn) ifnn(s) = (intxx)tracehardoptrestn, done = 1;
  1229. if (fixenv)
  1230. { push2(a, s);
  1231. a = cons(s, qenv(s));
  1232. errexitn(2);
  1233. pop(s);
  1234. qenv(s) = a;
  1235. pop(a);
  1236. }
  1237. if (done) continue;
  1238. /*
  1239. * I permit the tracing of just one function from the kernel, and achieve
  1240. * this by installing a wrapper function in place of the real definition.
  1241. * Indeed this is just like Lisp-level embedding, except that I can get at the
  1242. * entrypoint table used by the bytecode interpreter and so trap calls made
  1243. * via there, and I can use that table to tell me how many arguments the
  1244. * traced function needed.
  1245. */
  1246. if (displaced1 == NULL)
  1247. { int nargs = funtable_nargs(table_entry);
  1248. /*
  1249. * Remember what function was being traced, so that it can eventually be
  1250. * invoked, and its name printed.
  1251. */
  1252. displaced1 = f1;
  1253. displaced2 = f2;
  1254. displacedn = fn;
  1255. tracedfn = s;
  1256. /*
  1257. * This makes calls via the regular interpreter see the traced version...
  1258. */
  1259. set_fns(s, traced1_function, traced2_function,
  1260. tracedn_function);
  1261. table_entry = find_built_in_function(f1, f2, fn);
  1262. nargs = funtable_nargs(table_entry);
  1263. table_entry = funtable_index(table_entry);
  1264. if (nargs != NOT_FOUND)
  1265. {
  1266. /*
  1267. * .. and now I make calls via short-form bytecodes do likewise.
  1268. */
  1269. switch (nargs)
  1270. {
  1271. default:
  1272. case 0: zero_arg_functions[funtable_index(table_entry)] =
  1273. tracedn_function;
  1274. break;
  1275. case 1: one_arg_functions[funtable_index(table_entry)] =
  1276. traced1_function;
  1277. break;
  1278. case 2: two_arg_functions[funtable_index(table_entry)] =
  1279. traced2_function;
  1280. break;
  1281. case 3: three_arg_functions[funtable_index(table_entry)] =
  1282. tracedn_function;
  1283. break;
  1284. }
  1285. }
  1286. }
  1287. continue;
  1288. }
  1289. }
  1290. return onevalue(a);
  1291. }
  1292. Lisp_Object Luntrace(Lisp_Object nil, Lisp_Object a)
  1293. {
  1294. Lisp_Object w = a;
  1295. CSL_IGNORE(nil);
  1296. if (symbolp(a))
  1297. { a = ncons(a);
  1298. errexit();
  1299. w = a;
  1300. }
  1301. while (consp(w))
  1302. { Lisp_Object s = qcar(w);
  1303. w = qcdr(w);
  1304. if (symbolp(s))
  1305. { one_args *f1 = qfn1(s);
  1306. two_args *f2 = qfn2(s);
  1307. n_args *fn = qfnn(s);
  1308. if (f1 == traceinterpreted1)
  1309. { set_fns(a, interpreted1, interpreted2, interpretedn);
  1310. qenv(s) = qcdr(qenv(s));
  1311. }
  1312. else if (f1 == tracefunarged1)
  1313. { set_fns(s, funarged1, funarged2, funargedn);
  1314. qenv(s) = qcdr(qenv(s));
  1315. }
  1316. if (f1 == tracebytecoded1) ifn1(s) = (intxx)bytecoded1;
  1317. if (f2 == tracebytecoded2) ifn2(s) = (intxx)bytecoded2;
  1318. if (fn == tracebytecoded0) ifnn(s) = (intxx)bytecoded0;
  1319. if (fn == tracebytecoded3) ifnn(s) = (intxx)bytecoded3;
  1320. if (fn == tracebytecodedn) ifnn(s) = (intxx)bytecodedn;
  1321. if (f1 == tracebyteopt1) ifn1(s) = (intxx)byteopt1;
  1322. if (f2 == tracebyteopt2) ifn2(s) = (intxx)byteopt2;
  1323. if (fn == tracebyteoptn) ifnn(s) = (intxx)byteoptn;
  1324. if (f1 == tracebyteoptrest1) ifn1(s) = (intxx)byteoptrest1;
  1325. if (f2 == tracebyteoptrest2) ifn2(s) = (intxx)byteoptrest2;
  1326. if (fn == tracebyteoptrestn) ifnn(s) = (intxx)byteoptrestn;
  1327. if (f1 == tracehardopt1) ifn1(s) = (intxx)hardopt1;
  1328. if (f2 == tracehardopt2) ifn2(s) = (intxx)hardopt2;
  1329. if (fn == tracehardoptn) ifnn(s) = (intxx)hardoptn;
  1330. if (f1 == tracehardoptrest1) ifn1(s) = (intxx)hardoptrest1;
  1331. if (f2 == tracehardoptrest2) ifn2(s) = (intxx)hardoptrest2;
  1332. if (fn == tracehardoptrestn) ifnn(s) = (intxx)hardoptrestn;
  1333. if (f1 == traced1_function)
  1334. { int nargs = funtable_nargs(table_entry);
  1335. set_fns(s, displaced1, displaced2, displacedn);
  1336. if (nargs != NOT_FOUND)
  1337. switch (nargs)
  1338. {
  1339. default:
  1340. case 0: zero_arg_functions[funtable_index(table_entry)] =
  1341. displacedn;
  1342. break;
  1343. case 1: one_arg_functions[funtable_index(table_entry)] =
  1344. displaced1;
  1345. break;
  1346. case 2: two_arg_functions[funtable_index(table_entry)] =
  1347. displaced2;
  1348. break;
  1349. case 3: three_arg_functions[funtable_index(table_entry)] =
  1350. displacedn;
  1351. break;
  1352. }
  1353. displaced1 = NULL;
  1354. displaced2 = NULL;
  1355. displacedn = NULL;
  1356. }
  1357. qheader(s) &= ~SYM_TRACED;
  1358. }
  1359. }
  1360. return onevalue(a);
  1361. }
  1362. Lisp_Object Ldouble(Lisp_Object nil, Lisp_Object a)
  1363. {
  1364. Lisp_Object w = a;
  1365. if (symbolp(a))
  1366. { a = ncons(a);
  1367. errexit();
  1368. w = a;
  1369. }
  1370. while (consp(w))
  1371. { Lisp_Object s = qcar(w);
  1372. w = qcdr(w);
  1373. if (symbolp(s))
  1374. { one_args *f1 = qfn1(s);
  1375. two_args *f2 = qfn2(s);
  1376. n_args *fn = qfnn(s);
  1377. int fixenv = 0, done = 0;
  1378. if (f1 == undefined1) continue;
  1379. if (f1 == interpreted1)
  1380. { set_fns(s, double_interpreted1, double_interpreted2, double_interpretedn);
  1381. fixenv = done = 1;
  1382. }
  1383. if (f1 == funarged1)
  1384. { set_fns(s, double_funarged1, double_funarged2, double_funargedn);
  1385. fixenv = done = 1;
  1386. }
  1387. if (fn == bytecoded0) ifnn(s) = (intxx)double_bytecoded0, done = 1;
  1388. if (f1 == bytecoded1) ifn1(s) = (intxx)double_bytecoded1, done = 1;
  1389. if (f2 == bytecoded2) ifn2(s) = (intxx)double_bytecoded2, done = 1;
  1390. if (fn == bytecoded3) ifnn(s) = (intxx)double_bytecoded3, done = 1;
  1391. if (fn == bytecodedn) ifnn(s) = (intxx)double_bytecodedn, done = 1;
  1392. if (f1 == byteopt1) ifn1(s) = (intxx)double_byteopt1, done = 1;
  1393. if (f2 == byteopt2) ifn2(s) = (intxx)double_byteopt2, done = 1;
  1394. if (fn == byteoptn) ifnn(s) = (intxx)double_byteoptn, done = 1;
  1395. if (f1 == hardopt1) ifn1(s) = (intxx)double_hardopt1, done = 1;
  1396. if (f2 == hardopt2) ifn2(s) = (intxx)double_hardopt2, done = 1;
  1397. if (fn == hardoptn) ifnn(s) = (intxx)double_hardoptn, done = 1;
  1398. if (f1 == byteoptrest1) ifn1(s) = (intxx)double_byteoptrest1, done = 1;
  1399. if (f2 == byteoptrest2) ifn2(s) = (intxx)double_byteoptrest2, done = 1;
  1400. if (fn == byteoptrestn) ifnn(s) = (intxx)double_byteoptrestn, done = 1;
  1401. if (f1 == hardoptrest1) ifn1(s) = (intxx)double_hardoptrest1, done = 1;
  1402. if (f2 == hardoptrest2) ifn2(s) = (intxx)double_hardoptrest2, done = 1;
  1403. if (fn == hardoptrestn) ifnn(s) = (intxx)double_hardoptrestn, done = 1;
  1404. if (fixenv)
  1405. { push2(a, s);
  1406. a = cons(s, qenv(s));
  1407. errexitn(2);
  1408. pop(s);
  1409. qenv(s) = a;
  1410. pop(a);
  1411. }
  1412. if (done) continue;
  1413. debug_printf("Unable to execution-double: "); loop_print_debug(s);
  1414. trace_printf("\n");
  1415. continue;
  1416. }
  1417. }
  1418. return onevalue(a);
  1419. }
  1420. Lisp_Object Lundouble(Lisp_Object nil, Lisp_Object a)
  1421. {
  1422. Lisp_Object w = a;
  1423. CSL_IGNORE(nil);
  1424. if (symbolp(a))
  1425. { a = ncons(a);
  1426. errexit();
  1427. w = a;
  1428. }
  1429. while (consp(w))
  1430. { Lisp_Object s = qcar(w);
  1431. w = qcdr(w);
  1432. if (symbolp(s))
  1433. { one_args *f1 = qfn1(s);
  1434. two_args *f2 = qfn2(s);
  1435. n_args *fn = qfnn(s);
  1436. if (f1 == double_interpreted1)
  1437. { set_fns(a, interpreted1, interpreted2, interpretedn);
  1438. qenv(s) = qcdr(qenv(s));
  1439. }
  1440. else if (f1 == double_funarged1)
  1441. { set_fns(s, funarged1, funarged2, funargedn);
  1442. qenv(s) = qcdr(qenv(s));
  1443. }
  1444. else if (f1 == double_bytecoded1) ifn1(s) = (intxx)bytecoded1;
  1445. else if (f2 == double_bytecoded2) ifn2(s) = (intxx)bytecoded2;
  1446. else if (fn == double_bytecoded0) ifnn(s) = (intxx)bytecoded0;
  1447. else if (fn == double_bytecoded3) ifnn(s) = (intxx)bytecoded3;
  1448. else if (fn == double_bytecodedn) ifnn(s) = (intxx)bytecodedn;
  1449. else if (f1 == double_byteopt1) ifn1(s) = (intxx)byteopt1;
  1450. else if (f2 == double_byteopt2) ifn2(s) = (intxx)byteopt2;
  1451. else if (fn == double_byteoptn) ifnn(s) = (intxx)byteoptn;
  1452. else if (f1 == double_byteoptrest1) ifn1(s) = (intxx)byteoptrest1;
  1453. else if (f2 == double_byteoptrest2) ifn2(s) = (intxx)byteoptrest2;
  1454. else if (fn == double_byteoptrestn) ifnn(s) = (intxx)byteoptrestn;
  1455. else if (f1 == double_hardopt1) ifn1(s) = (intxx)hardopt1;
  1456. else if (f2 == double_hardopt2) ifn2(s) = (intxx)hardopt2;
  1457. else if (fn == double_hardoptn) ifnn(s) = (intxx)hardoptn;
  1458. else if (f1 == double_hardoptrest1) ifn1(s) = (intxx)hardoptrest1;
  1459. else if (f2 == double_hardoptrest2) ifn2(s) = (intxx)hardoptrest2;
  1460. else if (fn == double_hardoptrestn) ifnn(s) = (intxx)hardoptrestn;
  1461. }
  1462. }
  1463. return onevalue(a);
  1464. }
  1465. Lisp_Object Lmacro_function(Lisp_Object nil, Lisp_Object a)
  1466. {
  1467. if (!symbolp(a)) return onevalue(nil);
  1468. else if ((qheader(a) & SYM_MACRO) == 0) return onevalue(nil);
  1469. /* If the MACRO bit is set in the header I know there is a definition */
  1470. else return onevalue(cons(lambda, qenv(a)));
  1471. }
  1472. Lisp_Object get_pname(Lisp_Object a)
  1473. {
  1474. Lisp_Object name = qpname(a);
  1475. #ifndef COMMON
  1476. /*
  1477. * When a gensym is first created its pname field points at a string that
  1478. * will form the base of its name, and a magic bit is set in its header.
  1479. * If at some stage it is necessary to inspect the print name (mainly in
  1480. * order to print the symbol) it becomes necessary to create a new string
  1481. * and insert a serial number. Doing things this way means that the serial
  1482. * numbers that users see will tend to be smaller, and space for per-gensym
  1483. * strings does not get allocated unless really needed. The down side is
  1484. * that every time I want to grab the pname of anything I have to check for
  1485. * this case and admit the possibility of garbage collection or even
  1486. * failure.
  1487. */
  1488. if (qheader(a) & SYM_UNPRINTED_GENSYM)
  1489. { unsignedxx len;
  1490. Lisp_Object nil = C_nil;
  1491. char genname[64];
  1492. len = length_of_header(vechdr(name)) - CELL;
  1493. if (len > 60) len = 60; /* Unpublished truncation of the string */
  1494. sprintf(genname, "%.*s%lu", (int)len,
  1495. (char *)name + (CELL - TAG_VECTOR), (long)gensym_ser++);
  1496. push(a);
  1497. name = make_string(genname);
  1498. pop(a);
  1499. errexit();
  1500. qpname(a) = name;
  1501. qheader(a) &= ~SYM_UNPRINTED_GENSYM;
  1502. }
  1503. #endif
  1504. return name;
  1505. }
  1506. Lisp_Object Lsymbol_name(Lisp_Object nil, Lisp_Object a)
  1507. {
  1508. if (!symbolp(a)) return aerror1("symbol-name", a);
  1509. a = get_pname(a);
  1510. errexit();
  1511. return onevalue(a);
  1512. }
  1513. #ifdef COMMON
  1514. Lisp_Object Lsymbol_package(Lisp_Object nil, Lisp_Object a)
  1515. {
  1516. if (!symbolp(a)) return aerror1("symbol-package", a);
  1517. a = qpackage(a);
  1518. return onevalue(a);
  1519. }
  1520. #endif
  1521. static Lisp_Object Lrestart_csl2(Lisp_Object nil,
  1522. Lisp_Object a, Lisp_Object b)
  1523. /*
  1524. * If the argument is given as nil then this is a cold-start, and when
  1525. * I begin again it would be a VERY good idea to do a (load!-module 'compat)
  1526. * rather promptly (otherwise some Lisp functions will not work at all).
  1527. * I do not automate that because this function is intended for use in
  1528. * delicate system rebuilding contexts and I want the user to have ultimate
  1529. * control. (restart!-csl t) reloads a heap-image in the normal way.
  1530. * (restart!-csl 'xx) where xx is neither nil nor t starts by reloading a
  1531. * heap image, but then it looks for a function with the same name as xx
  1532. * (since a heap image is reloaded it is NOT easy (possible?) to keep the
  1533. * symbol) and calls it as a function. Finally the case
  1534. * (restart!-csl '(module fn)) restart the system, then calls load-module
  1535. * on the named module and finally calls the given restart function.
  1536. * This last option can be useful since otherwise the function to be called
  1537. * in (restart!-csl 'xx) would need to be in the base image as re-loaded.
  1538. */
  1539. {
  1540. int n;
  1541. char *v;
  1542. #ifdef SOCKETS
  1543. /*
  1544. * Security measure - deny restart-csl to remote users
  1545. */
  1546. if (socket_server != 0) return aerror("restart-csl");
  1547. #endif
  1548. n = 0;
  1549. v = NULL;
  1550. /*
  1551. * A comment seems in order here. The case b==SPID_NOARG should only
  1552. * arise if I came from Lrestart_csl: it indicates that there was
  1553. * no second argument provided.
  1554. */
  1555. if (b != SPID_NOARG)
  1556. { Lisp_Object b1;
  1557. push(a);
  1558. b1 = b = Lexploden(nil, b);
  1559. pop(a);
  1560. errexit();
  1561. while (b1 != nil)
  1562. { n++; /* number of chars of arg */
  1563. b1 = qcdr(b1);
  1564. }
  1565. v = (char *)malloc(n+1);
  1566. if (v == NULL) return aerror("space exhausted in restart-csl");
  1567. n = 0;
  1568. while (b != nil)
  1569. { v[n++] = (char)int_of_fixnum(qcar(b));
  1570. b = qcdr(b);
  1571. }
  1572. v[n] = 0;
  1573. }
  1574. term_printf("\nThe system is about to do a restart...\n");
  1575. /* Almost all unpicking of the argument is done back in csl.c */
  1576. exit_value = a;
  1577. exit_tag = fixnum_of_int(2); /* Flag to say "restart" */
  1578. exit_reason = UNWIND_RESTART;
  1579. exit_charvec = v;
  1580. flip_exception();
  1581. return nil;
  1582. }
  1583. static Lisp_Object Lrestart_csl(Lisp_Object nil, Lisp_Object a)
  1584. {
  1585. return Lrestart_csl2(nil, a, SPID_NOARG);
  1586. }
  1587. static Lisp_Object Lpreserve(Lisp_Object nil,
  1588. Lisp_Object startup, Lisp_Object banner)
  1589. /*
  1590. * (preserve <startup-fn>) saves a Lisp image in a standard place
  1591. * and arranges that when restarted the saved image will call the specified
  1592. * startup function. In the process of doing all this it unwinds down to
  1593. * the top level of Lisp. If a startup function is not given then the
  1594. * previously active one is used. If nil is specified then the previously
  1595. * active startup function is retained. If banner is non-nil (well really
  1596. * I want a string) is is a message of up to 40 characters to display
  1597. * when the system restart.
  1598. */
  1599. {
  1600. char filename[LONGEST_LEGAL_FILENAME];
  1601. CSLbool failed;
  1602. #ifdef SOCKETS
  1603. /*
  1604. * Security measure - deny preserve to remote users
  1605. */
  1606. if (socket_server != 0) return aerror("preserve");
  1607. #endif
  1608. if (startup != nil) supervisor = startup;
  1609. failed = Iwriterootp(filename); /* Can I open image file for writing? */
  1610. term_printf("\nThe system will be preserved on file \"%s\"\n", filename);
  1611. if (failed) return aerror("preserve");
  1612. exit_count = 0;
  1613. nil = C_nil;
  1614. exit_value = banner;
  1615. exit_tag = fixnum_of_int(1); /* Flag to say "preserve" */
  1616. exit_reason = UNWIND_RESTART;
  1617. flip_exception();
  1618. return nil;
  1619. }
  1620. static Lisp_Object MS_CDECL Lpreserve_0(Lisp_Object nil, int nargs, ...)
  1621. {
  1622. argcheck(nargs, 0, "preserve");
  1623. return Lpreserve(nil, nil, nil);
  1624. }
  1625. static Lisp_Object Lpreserve_1(Lisp_Object nil, Lisp_Object startup)
  1626. {
  1627. return Lpreserve(nil, startup, nil);
  1628. }
  1629. /*
  1630. * This is an experimental addition - a version of PRESERVE that allows
  1631. * CSL to continue executing after it has written out an image file.
  1632. */
  1633. static Lisp_Object Lcheckpoint(Lisp_Object nil,
  1634. Lisp_Object startup, Lisp_Object banner)
  1635. {
  1636. char filename[LONGEST_LEGAL_FILENAME];
  1637. CSLbool failed = 0;
  1638. char *msg = "";
  1639. #ifdef SOCKETS
  1640. /*
  1641. * Security measure - deny checkpoint to remote users
  1642. */
  1643. if (socket_server != 0) return aerror("checkpoint");
  1644. #endif
  1645. if (startup != nil) supervisor = startup;
  1646. failed = Iwriterootp(filename); /* Can I open image file for writing? */
  1647. term_printf("\nThe system will be preserved on file \"%s\"\n", filename);
  1648. if (failed) return aerror("checkpoint");
  1649. if (is_vector(banner) &&
  1650. type_of_header(vechdr(banner)) == TYPE_STRING)
  1651. msg = &celt(banner, 0);
  1652. /*
  1653. * Note, with some degree of nervousness, that things on the C stack will
  1654. * be updated by the garbage collection that happens during the processing
  1655. * of the call to preserve(), but they will be neither adjusted into
  1656. * relative addresses nor unadjusted (and hence restored) by in the
  1657. * image-writing. But the image writing will not actually move any data
  1658. * around so all is still OK, I hope!
  1659. */
  1660. push5(codevec, litvec, catch_tags, faslvec, faslgensyms);
  1661. preserve(msg);
  1662. nil = C_nil;
  1663. if (exception_pending()) failed = 1, flip_exception();
  1664. adjust_all();
  1665. pop5(faslgensyms, faslvec, catch_tags, litvec, codevec);
  1666. eq_hash_tables = eq_hash_table_list;
  1667. equal_hash_tables = equal_hash_table_list;
  1668. eq_hash_table_list = equal_hash_table_list = nil;
  1669. { Lisp_Object qq;
  1670. for (qq = eq_hash_tables; qq!=nil; qq=qcdr(qq))
  1671. rehash_this_table(qcar(qq));
  1672. for (qq = equal_hash_tables; qq!=nil; qq=qcdr(qq))
  1673. rehash_this_table(qcar(qq));
  1674. }
  1675. set_up_functions(YES);
  1676. if (failed) return aerror("checkpoint");
  1677. return onevalue(nil);
  1678. }
  1679. static Lisp_Object MS_CDECL Lcheckpoint_0(Lisp_Object nil, int nargs, ...)
  1680. {
  1681. argcheck(nargs, 0, "checkpoint");
  1682. return Lcheckpoint(nil, nil, nil);
  1683. }
  1684. static Lisp_Object Lcheckpoint_1(Lisp_Object nil, Lisp_Object startup)
  1685. {
  1686. return Lcheckpoint(nil, startup, nil);
  1687. }
  1688. #ifdef COMMON
  1689. static CSLbool eql_numbers(Lisp_Object a, Lisp_Object b)
  1690. /*
  1691. * This is only called from eql, and then only when a and b are both tagged
  1692. * as ratios or complex numbers.
  1693. */
  1694. {
  1695. Lisp_Object p, q;
  1696. p = *(Lisp_Object *)(a + (CELL - TAG_NUMBERS));
  1697. q = *(Lisp_Object *)(b + (CELL - TAG_NUMBERS));
  1698. if (!eql(p, q)) return NO;
  1699. p = *(Lisp_Object *)(a + (2*CELL - TAG_NUMBERS));
  1700. q = *(Lisp_Object *)(b + (2*CELL - TAG_NUMBERS));
  1701. return eql(p, q);
  1702. }
  1703. #endif
  1704. CSLbool eql_fn(Lisp_Object a, Lisp_Object b)
  1705. /*
  1706. * This seems incredible - all the messing about that is needed to
  1707. * check that numeric values compare properly. Ugh.
  1708. */
  1709. {
  1710. /*
  1711. * (these tests done before eql_fn is called).
  1712. * if (a == b) return YES;
  1713. * if ((((int32)a ^ (int32)b) & TAG_BITS) != 0) return NO;
  1714. *
  1715. * Actually in Common Lisp mode where I have short floats as immediate data
  1716. * I have further pain here with (eql 0.0 -0.0).
  1717. */
  1718. #ifdef COMMON
  1719. if ((a == TAG_SFLOAT && b == (TAG_SFLOAT|0x80000000)) ||
  1720. (a == (TAG_SFLOAT|0x80000000) && b == TAG_SFLOAT)) return YES;
  1721. #endif
  1722. if (!is_number(a) || is_immed_or_cons(a)) return NO;
  1723. if (is_bfloat(a))
  1724. { Header h = flthdr(a);
  1725. if (h != flthdr(b)) return NO;
  1726. #ifdef COMMON
  1727. if (type_of_header(h) == TYPE_SINGLE_FLOAT)
  1728. return (single_float_val(a) == single_float_val(b));
  1729. else
  1730. #endif
  1731. /*
  1732. * For the moment I view all non-single floats as double floats. Extra
  1733. * stuff will be needed here if I ever implement long floats as 3-word
  1734. * objects.
  1735. */
  1736. return (double_float_val(a) == double_float_val(b));
  1737. }
  1738. else /* ratio, complex or bignum */
  1739. { Header h = numhdr(a);
  1740. if (h != numhdr(b)) return NO;
  1741. if (type_of_header(h) == TYPE_BIGNUM)
  1742. { intxx hh = (intxx)length_of_header(h) - TAG_NUMBERS;
  1743. while (hh > (intxx)(CELL - TAG_NUMBERS))
  1744. { hh -= 4;
  1745. if (*(unsigned32 *)((char *)a + hh) !=
  1746. *(unsigned32 *)((char *)b + hh))
  1747. return NO;
  1748. }
  1749. return YES;
  1750. }
  1751. #ifdef COMMON
  1752. else return eql_numbers(a, b);
  1753. #else
  1754. else return NO;
  1755. #endif
  1756. }
  1757. }
  1758. static CSLbool cl_vec_equal(Lisp_Object a, Lisp_Object b)
  1759. /*
  1760. * here a and b are known to be vectors or arrays. This should compare
  1761. * them following the Common Lisp recipe, where strings or bitvectors
  1762. * (simple or complex) have their contents compared, while all other types of
  1763. * vector or array are tested using EQ.
  1764. */
  1765. {
  1766. Header ha = vechdr(a), hb = vechdr(b);
  1767. intxx offa = 0, offb = 0;
  1768. int ta = type_of_header(ha), tb = type_of_header(hb);
  1769. intxx la = length_of_header(ha), lb = length_of_header(hb);
  1770. #ifdef COMMON
  1771. if (header_of_bitvector(ha)) ta = TYPE_BITVEC1;
  1772. if (header_of_bitvector(hb)) tb = TYPE_BITVEC1;
  1773. #endif
  1774. switch (ta)
  1775. {
  1776. /*
  1777. case TYPE_ARRAY:
  1778. /* My moan here is that, as noted above, I ought to process even
  1779. * non-simple strings and bit-vectors by comparing contents, but as a
  1780. * matter of idleness I have not yet got around to that. In fact if I get
  1781. * arrays to compare here I will pretend that they are not strings or
  1782. * bit-vectors and compare using EQ...
  1783. */
  1784. case TYPE_STRING:
  1785. switch (tb)
  1786. {
  1787. /* /*
  1788. case TYPE_ARRAY:
  1789. */
  1790. case TYPE_STRING:
  1791. goto compare_strings;
  1792. default:return NO;
  1793. }
  1794. #ifdef COMMON
  1795. case TYPE_BITVEC1:
  1796. switch (tb)
  1797. {
  1798. /* /*
  1799. case TYPE_ARRAY:
  1800. */
  1801. case TYPE_BITVEC1:
  1802. goto compare_bits;
  1803. default:return NO;
  1804. }
  1805. #endif
  1806. default: return (a == b);
  1807. }
  1808. compare_strings:
  1809. if (la != lb) return NO;
  1810. while (la > 0)
  1811. { la--;
  1812. if (*((char *)a + la + offa - TAG_VECTOR) !=
  1813. *((char *)b + la + offb - TAG_VECTOR)) return NO;
  1814. }
  1815. return YES;
  1816. #ifdef COMMON
  1817. compare_bits:
  1818. if (la != lb) return NO;
  1819. while (la > 0)
  1820. { la--;
  1821. if (*((char *)a + la + offa - TAG_VECTOR) !=
  1822. *((char *)b + la + offb - TAG_VECTOR)) return NO;
  1823. }
  1824. return YES;
  1825. #endif
  1826. }
  1827. CSLbool cl_equal_fn(Lisp_Object a, Lisp_Object b)
  1828. /*
  1829. * a and b are not EQ at this stage.. I guarantee to have checked that
  1830. * before entering this general purpose code.
  1831. */
  1832. {
  1833. Lisp_Object nil = C_nil;
  1834. CSL_IGNORE(nil);
  1835. /*
  1836. * The for loop at the top here is so that cl_equal can iterate along the
  1837. * length of linear lists.
  1838. */
  1839. #ifdef CHECK_STACK
  1840. if (check_stack(__FILE__,__LINE__))
  1841. { err_printf("Stack too deep in cl_equal\n");
  1842. my_exit(EXIT_FAILURE);
  1843. }
  1844. #endif
  1845. for (;;)
  1846. {
  1847. int32 ta = (int32)a & TAG_BITS;
  1848. if (ta == TAG_CONS
  1849. #ifdef COMMON
  1850. && a != nil
  1851. #endif
  1852. )
  1853. { if (!consp(b)
  1854. #ifdef COMMON
  1855. || b == nil
  1856. #endif
  1857. ) return NO;
  1858. else
  1859. { Lisp_Object ca = qcar(a), cb = qcar(b);
  1860. if (ca == cb)
  1861. { a = qcdr(a);
  1862. b = qcdr(b);
  1863. if (a == b) return YES;
  1864. continue;
  1865. }
  1866. /*
  1867. * And here, because cl_equal() seems to be a very important low-level
  1868. * primitive, I unwind one level of the recursion that would arise
  1869. * with nested lists.
  1870. */
  1871. for (;;)
  1872. {
  1873. int32 tca = (int32)ca & TAG_BITS;
  1874. if (tca == TAG_CONS
  1875. #ifdef COMMON
  1876. && ca != nil
  1877. #endif
  1878. )
  1879. { if (!consp(cb)
  1880. #ifdef COMMON
  1881. || cb == nil
  1882. #endif
  1883. ) return NO;
  1884. else
  1885. { Lisp_Object cca = qcar(ca), ccb = qcar(cb);
  1886. if (cca == ccb)
  1887. { ca = qcdr(ca);
  1888. cb = qcdr(cb);
  1889. if (ca == cb) break;
  1890. continue;
  1891. }
  1892. /*
  1893. * Do a real recursion when I get down to args like
  1894. * ((x ...) ...) ((y ...) ...)
  1895. */
  1896. if (!cl_equal(cca, ccb)) return NO;
  1897. ca = qcdr(ca);
  1898. cb = qcdr(cb);
  1899. if (ca == cb) break;
  1900. continue;
  1901. }
  1902. }
  1903. else if (tca <= TAG_SYMBOL ||
  1904. ((int32)cb & TAG_BITS) != tca) return NO;
  1905. else switch (tca)
  1906. {
  1907. case TAG_NUMBERS:
  1908. { Header h = numhdr(ca);
  1909. if (h != numhdr(cb)) return NO;
  1910. if (type_of_header(h) == TYPE_BIGNUM)
  1911. { intxx hh = (intxx)length_of_header(h) - TAG_NUMBERS;
  1912. while (hh > (intxx)(CELL - TAG_NUMBERS))
  1913. { hh -= 4;
  1914. if (*(unsigned32 *)((char *)ca + hh) !=
  1915. *(unsigned32 *)((char *)cb + hh))
  1916. return NO;
  1917. }
  1918. break;
  1919. }
  1920. #ifdef COMMON
  1921. else if (!eql_numbers(ca, cb)) return NO;
  1922. else break;
  1923. #else
  1924. else return NO;
  1925. #endif
  1926. }
  1927. case TAG_VECTOR:
  1928. if (!cl_vec_equal(ca, cb)) return NO;
  1929. break;
  1930. default:
  1931. case TAG_BOXFLOAT:
  1932. { Header h = flthdr(ca);
  1933. if (h != flthdr(cb)) return NO;
  1934. #ifdef COMMON
  1935. if (type_of_header(h) == TYPE_SINGLE_FLOAT)
  1936. {
  1937. if (single_float_val(ca) !=
  1938. single_float_val(cb)) return NO;
  1939. else break;
  1940. }
  1941. else
  1942. #endif
  1943. {
  1944. if (double_float_val(ca) !=
  1945. double_float_val(cb)) return NO;
  1946. else break;
  1947. }
  1948. }
  1949. }
  1950. break; /* out of the for (;;) loop */
  1951. }
  1952. a = qcdr(a);
  1953. b = qcdr(b);
  1954. if (a == b) return YES;
  1955. continue;
  1956. }
  1957. }
  1958. else if (ta <= TAG_SYMBOL ||
  1959. ((int32)b & TAG_BITS) != ta) return NO;
  1960. /*
  1961. * OK - now a and b both have the same type and neither are immediate data
  1962. * conses or symbols. That leaves vectors (including strings) and boxed
  1963. * numbers.
  1964. */
  1965. else switch (ta)
  1966. {
  1967. case TAG_NUMBERS:
  1968. { Header h = numhdr(a);
  1969. if (h != numhdr(b)) return NO;
  1970. if (type_of_header(h) == TYPE_BIGNUM)
  1971. { intxx hh = (intxx)length_of_header(h) - TAG_NUMBERS;
  1972. while (hh > (intxx)(CELL - TAG_NUMBERS))
  1973. { hh -= 4;
  1974. if (*(unsigned32 *)((char *)a + hh) !=
  1975. *(unsigned32 *)((char *)b + hh))
  1976. return NO;
  1977. }
  1978. return YES;
  1979. }
  1980. #ifdef COMMON
  1981. else return eql_numbers(a, b);
  1982. #else
  1983. else return NO;
  1984. #endif
  1985. }
  1986. case TAG_VECTOR:
  1987. return cl_vec_equal(a, b);
  1988. default:
  1989. case TAG_BOXFLOAT:
  1990. { Header h = flthdr(a);
  1991. if (h != flthdr(b)) return NO;
  1992. #ifdef COMMON
  1993. if (type_of_header(h) == TYPE_SINGLE_FLOAT)
  1994. {
  1995. if (single_float_val(a) != single_float_val(b))
  1996. return NO;
  1997. else return YES;
  1998. }
  1999. else
  2000. #endif
  2001. /*
  2002. * For the moment I view all non-single floats as double floats. Extra
  2003. * stuff will be needed here if I ever implement long floats as 3-word
  2004. * objects.
  2005. */
  2006. {
  2007. if (double_float_val(a) != double_float_val(b))
  2008. return NO;
  2009. else return YES;
  2010. }
  2011. }
  2012. }
  2013. }
  2014. }
  2015. static CSLbool vec_equal(Lisp_Object a, Lisp_Object b);
  2016. #ifdef TRACED_EQUAL
  2017. #define LOG_SIZE 10000
  2018. typedef struct equal_record
  2019. {
  2020. char file[24];
  2021. int line;
  2022. int depth;
  2023. int count;
  2024. } equal_record;
  2025. static equal_record equal_counts[LOG_SIZE];
  2026. static void record_equal(char *file, int line, int depth)
  2027. {
  2028. int hash = 169*line + depth;
  2029. char *p = file;
  2030. while (*p != 0) hash = 169*hash + (*p++ & 0xff);
  2031. hash = ((169*hash) & 0x7fffffff) % LOG_SIZE;
  2032. while (equal_counts[hash].count != 0)
  2033. { if (equal_counts[hash].line == line &&
  2034. equal_counts[hash].depth == depth &&
  2035. strncmp(equal_counts[hash].file, file, 24) == 0)
  2036. { equal_counts[hash].count++;
  2037. return;
  2038. }
  2039. hash = (hash + 1) % LOG_SIZE;
  2040. }
  2041. strncpy(equal_counts[hash].file, file, 24);
  2042. equal_counts[hash].line = line;
  2043. equal_counts[hash].depth = depth;
  2044. equal_counts[hash].count = 1;
  2045. return;
  2046. }
  2047. void dump_equals()
  2048. {
  2049. int i;
  2050. FILE *log = fopen("equal.log", "w");
  2051. if (log == NULL) log = stdout;
  2052. fprintf(log, "\nCalls to equal...\n");
  2053. for (i=0; i<LOG_SIZE; i++)
  2054. if (equal_counts[i].count != 0)
  2055. fprintf(log, "%24.24s %5d %5d %10d\n",
  2056. equal_counts[i].file, equal_counts[i].line,
  2057. equal_counts[i].depth, equal_counts[i].count);
  2058. fprintf(log, "end of counts\n");
  2059. if (log != stdout) fclose(log);
  2060. }
  2061. CSLbool traced_equal_fn(Lisp_Object a, Lisp_Object b,
  2062. char *file, int line, int depth)
  2063. /*
  2064. * a and b are not EQ at this stage.. I guarantee to have checked that
  2065. * before entering this general purpose code.
  2066. */
  2067. {
  2068. Lisp_Object nil = C_nil;
  2069. record_equal(file, line, depth);
  2070. #undef equal_fn
  2071. #define equal_fn(a, b) traced_equal_fn(a, b, file, line, depth+1)
  2072. #else
  2073. CSLbool equal_fn(Lisp_Object a, Lisp_Object b)
  2074. /*
  2075. * a and b are not EQ at this stage.. I guarantee to have checked that
  2076. * before entering this general purpose code. I will also have checked that
  2077. * the types of the two args agree, and that they are not both immediate
  2078. * date.
  2079. */
  2080. {
  2081. Lisp_Object nil = C_nil;
  2082. CSL_IGNORE(nil);
  2083. #endif
  2084. /*
  2085. * The for loop at the top here is so that equal can iterate along the
  2086. * length of linear lists.
  2087. */
  2088. #ifdef CHECK_STACK
  2089. if (check_stack(__FILE__,__LINE__))
  2090. { err_printf("Stack too deep in equal\n");
  2091. my_exit(EXIT_FAILURE);
  2092. }
  2093. #endif
  2094. for (;;)
  2095. {
  2096. int32 ta = (int32)a & TAG_BITS;
  2097. if (ta == TAG_CONS
  2098. #ifdef COMMON
  2099. && a != nil
  2100. #endif
  2101. )
  2102. { if (!consp(b)
  2103. #ifdef COMMON
  2104. || b == nil
  2105. #endif
  2106. ) return NO;
  2107. else
  2108. { Lisp_Object ca = qcar(a), cb = qcar(b);
  2109. if (ca == cb)
  2110. { a = qcdr(a);
  2111. b = qcdr(b);
  2112. if (a == b) return YES;
  2113. continue;
  2114. }
  2115. /*
  2116. * And here, because equal() seems to be a very important low-level
  2117. * primitive, I unwind one level of the recursion that would arise
  2118. * with nested lists.
  2119. */
  2120. for (;;)
  2121. {
  2122. int32 tca = (int32)ca & TAG_BITS;
  2123. if (tca == TAG_CONS
  2124. #ifdef COMMON
  2125. && ca != nil
  2126. #endif
  2127. )
  2128. { if (!consp(cb)
  2129. #ifdef COMMON
  2130. || cb == nil
  2131. #endif
  2132. ) return NO;
  2133. else
  2134. { Lisp_Object cca = qcar(ca), ccb = qcar(cb);
  2135. if (cca == ccb)
  2136. { ca = qcdr(ca);
  2137. cb = qcdr(cb);
  2138. if (ca == cb) break;
  2139. continue;
  2140. }
  2141. /*
  2142. * Do a real recursion when I get down to args like
  2143. * ((x ...) ...) ((y ...) ...)
  2144. */
  2145. if (!equal(cca, ccb)) return NO;
  2146. ca = qcdr(ca);
  2147. cb = qcdr(cb);
  2148. if (ca == cb) break;
  2149. continue;
  2150. }
  2151. }
  2152. else if (tca <= TAG_SYMBOL ||
  2153. ((int32)cb & TAG_BITS) != tca) return NO;
  2154. else switch (tca)
  2155. {
  2156. case TAG_NUMBERS:
  2157. { Header h = numhdr(ca);
  2158. if (h != numhdr(cb)) return NO;
  2159. if (type_of_header(h) == TYPE_BIGNUM)
  2160. { intxx hh = (intxx)length_of_header(h) - TAG_NUMBERS;
  2161. while (hh > (intxx)(CELL - TAG_NUMBERS))
  2162. { hh -= 4;
  2163. if (*(unsigned32 *)((char *)ca + hh) !=
  2164. *(unsigned32 *)((char *)cb + hh))
  2165. return NO;
  2166. }
  2167. break;
  2168. }
  2169. #ifdef COMMON
  2170. else if (!eql_numbers(ca, cb)) return NO;
  2171. else break;
  2172. #else
  2173. else return NO;
  2174. #endif
  2175. }
  2176. case TAG_VECTOR:
  2177. if (!vec_equal(ca, cb)) return NO;
  2178. break;
  2179. default:
  2180. case TAG_BOXFLOAT:
  2181. { Header h = flthdr(ca);
  2182. if (h != flthdr(cb)) return NO;
  2183. #ifdef COMMON
  2184. if (type_of_header(h) == TYPE_SINGLE_FLOAT)
  2185. {
  2186. if (single_float_val(ca) !=
  2187. single_float_val(cb)) return NO;
  2188. else break;
  2189. }
  2190. else
  2191. #endif
  2192. {
  2193. if (double_float_val(ca) !=
  2194. double_float_val(cb)) return NO;
  2195. else break;
  2196. }
  2197. }
  2198. }
  2199. break; /* out of the for (;;) loop */
  2200. }
  2201. a = qcdr(a);
  2202. b = qcdr(b);
  2203. if (a == b) return YES;
  2204. continue;
  2205. }
  2206. }
  2207. else if (ta <= TAG_SYMBOL ||
  2208. ((int32)b & TAG_BITS) != ta) return NO;
  2209. else switch (ta)
  2210. {
  2211. case TAG_NUMBERS:
  2212. { Header h = numhdr(a);
  2213. if (h != numhdr(b)) return NO;
  2214. if (type_of_header(h) == TYPE_BIGNUM)
  2215. { intxx hh = (intxx)length_of_header(h) - TAG_NUMBERS;
  2216. while (hh > (intxx)(CELL - TAG_NUMBERS))
  2217. { hh -= 4;
  2218. if (*(unsigned32 *)((char *)a + hh) !=
  2219. *(unsigned32 *)((char *)b + hh))
  2220. return NO;
  2221. }
  2222. return YES;
  2223. }
  2224. #ifdef COMMON
  2225. else return eql_numbers(a, b);
  2226. #else
  2227. else return NO;
  2228. #endif
  2229. }
  2230. case TAG_VECTOR:
  2231. return vec_equal(a, b);
  2232. default:
  2233. case TAG_BOXFLOAT:
  2234. { Header h = flthdr(a);
  2235. if (h != flthdr(b)) return NO;
  2236. #ifdef COMMON
  2237. if (type_of_header(h) == TYPE_SINGLE_FLOAT)
  2238. {
  2239. if (single_float_val(a) != single_float_val(b))
  2240. return NO;
  2241. else return YES;
  2242. }
  2243. else
  2244. #endif
  2245. /*
  2246. * For the moment I view all non-single floats as double floats. Extra
  2247. * stuff will be needed here if I ever implement long floats as 3-word
  2248. * objects.
  2249. */
  2250. {
  2251. if (double_float_val(a) != double_float_val(b))
  2252. return NO;
  2253. else return YES;
  2254. }
  2255. }
  2256. }
  2257. }
  2258. }
  2259. #ifdef TRACED_EQUAL
  2260. #undef equal_fn
  2261. #define equal_fn(a, b) traced_equal(a, b, __FILE__, __LINE__, 0)
  2262. #endif
  2263. static CSLbool vec_equal(Lisp_Object a, Lisp_Object b)
  2264. /*
  2265. * Here a and b are known to be vectors. Compare using recursive calls to
  2266. * EQUAL on all components.
  2267. */
  2268. {
  2269. Header ha = vechdr(a), hb = vechdr(b);
  2270. int32 l;
  2271. if (ha != hb) return NO;
  2272. l = (int32)doubleword_align_up(length_of_header(ha));
  2273. if (vector_holds_binary(ha))
  2274. { while ((l -= 4) != 0)
  2275. if (*((unsigned32 *)((char *)a + l - TAG_VECTOR)) !=
  2276. *((unsigned32 *)((char *)b + l - TAG_VECTOR))) return NO;
  2277. return YES;
  2278. }
  2279. else
  2280. { if (is_mixed_header(ha))
  2281. { while (l > 16)
  2282. { unsigned32 ea = *((unsigned32 *)((char *)a + l - TAG_VECTOR - 4)),
  2283. eb = *((unsigned32 *)((char *)b + l - TAG_VECTOR - 4));
  2284. if (ea != eb) return NO;
  2285. l -= 4;
  2286. }
  2287. }
  2288. while ((l -= CELL) != 0)
  2289. { Lisp_Object ea = *((Lisp_Object *)((char *)a + l - TAG_VECTOR)),
  2290. eb = *((Lisp_Object *)((char *)b + l - TAG_VECTOR));
  2291. if (ea == eb) continue;
  2292. if (!equal(ea, eb)) return NO;
  2293. }
  2294. return YES;
  2295. }
  2296. }
  2297. CSLbool equalp(Lisp_Object a, Lisp_Object b)
  2298. /*
  2299. * a and b are not EQ at this stage.. I guarantee to have checked that
  2300. * before entering this general purpose code.
  2301. */
  2302. {
  2303. Lisp_Object nil = C_nil;
  2304. CSL_IGNORE(nil);
  2305. /*
  2306. * The for loop at the top here is so that equalp can iterate along the
  2307. * length of linear lists.
  2308. */
  2309. #ifdef CHECK_STACK
  2310. if (check_stack(__FILE__,__LINE__))
  2311. { err_printf("Stack too deep in equalp\n");
  2312. my_exit(EXIT_FAILURE);
  2313. }
  2314. #endif
  2315. for (;;)
  2316. {
  2317. int32 ta = (int32)a & TAG_BITS;
  2318. if (ta == TAG_CONS
  2319. #ifdef COMMON
  2320. && a != nil
  2321. #endif
  2322. )
  2323. { if (!consp(b)
  2324. #ifdef COMMON
  2325. || b == nil
  2326. #endif
  2327. ) return NO;
  2328. else
  2329. { Lisp_Object ca = qcar(a), cb = qcar(b);
  2330. if (ca == cb)
  2331. { a = qcdr(a);
  2332. b = qcdr(b);
  2333. if (a == b) return YES;
  2334. continue;
  2335. }
  2336. /*
  2337. * And here, because equalp() seems to be a very important low-level
  2338. * primitive, I unwind one level of the recursion that would arise
  2339. * with nested lists.
  2340. */
  2341. for (;;)
  2342. {
  2343. int32 tca = (int32)ca & TAG_BITS;
  2344. if (tca == TAG_CONS
  2345. #ifdef COMMON
  2346. && ca != nil
  2347. #endif
  2348. )
  2349. { if (!consp(cb)
  2350. #ifdef COMMON
  2351. || cb == nil
  2352. #endif
  2353. ) return NO;
  2354. else
  2355. { Lisp_Object cca = qcar(ca), ccb = qcar(cb);
  2356. if (cca == ccb)
  2357. { ca = qcdr(ca);
  2358. cb = qcdr(cb);
  2359. if (ca == cb) break;
  2360. continue;
  2361. }
  2362. /*
  2363. * Do a real recursion when I get down to args like
  2364. * ((x ...) ...) ((y ...) ...)
  2365. */
  2366. if (!equalp(cca, ccb)) return NO;
  2367. ca = qcdr(ca);
  2368. cb = qcdr(cb);
  2369. if (ca == cb) break;
  2370. continue;
  2371. }
  2372. }
  2373. else if (tca <= TAG_SYMBOL ||
  2374. ((int32)cb & TAG_BITS) != tca) return NO;
  2375. else switch (tca)
  2376. {
  2377. case TAG_NUMBERS:
  2378. { Header h = numhdr(ca);
  2379. if (h != numhdr(cb)) return NO;
  2380. if (type_of_header(h) == TYPE_BIGNUM)
  2381. { intxx hh = (intxx)length_of_header(h) - TAG_NUMBERS;
  2382. while (hh > (intxx)(CELL - TAG_NUMBERS))
  2383. { hh -= 4;
  2384. if (*(unsigned32 *)((char *)ca + hh) !=
  2385. *(unsigned32 *)((char *)cb + hh))
  2386. return NO;
  2387. }
  2388. break;
  2389. }
  2390. #ifdef COMMON
  2391. else if (!eql_numbers(ca, cb)) return NO;
  2392. else break;
  2393. #else
  2394. else return NO;
  2395. #endif
  2396. }
  2397. case TAG_VECTOR:
  2398. /* /* At present vec_equal() is not right here */
  2399. if (!vec_equal(ca, cb)) return NO;
  2400. break;
  2401. default:
  2402. case TAG_BOXFLOAT:
  2403. { Header h = flthdr(ca);
  2404. if (h != flthdr(cb)) return NO;
  2405. #ifdef COMMON
  2406. if (type_of_header(h) == TYPE_SINGLE_FLOAT)
  2407. {
  2408. if (single_float_val(ca) !=
  2409. single_float_val(cb)) return NO;
  2410. else break;
  2411. }
  2412. else
  2413. #endif
  2414. {
  2415. if (double_float_val(ca) !=
  2416. double_float_val(cb)) return NO;
  2417. else break;
  2418. }
  2419. }
  2420. }
  2421. break; /* out of the for (;;) loop */
  2422. }
  2423. a = qcdr(a);
  2424. b = qcdr(b);
  2425. if (a == b) return YES;
  2426. continue;
  2427. }
  2428. }
  2429. else if (ta <= TAG_SYMBOL ||
  2430. ((int32)b & TAG_BITS) != ta) return NO;
  2431. /* What is left is vectors, strings and boxed numbers */
  2432. else switch (ta)
  2433. {
  2434. case TAG_NUMBERS:
  2435. { Header h = numhdr(a);
  2436. if (h != numhdr(b)) return NO;
  2437. if (type_of_header(h) == TYPE_BIGNUM)
  2438. { intxx hh = (intxx)length_of_header(h) - TAG_NUMBERS;
  2439. while (hh > (intxx)(CELL - TAG_NUMBERS))
  2440. { hh -= 4;
  2441. if (*(unsigned32 *)((char *)a + hh) !=
  2442. *(unsigned32 *)((char *)b + hh))
  2443. return NO;
  2444. }
  2445. return YES;
  2446. }
  2447. #ifdef COMMON
  2448. else return eql_numbers(a, b);
  2449. #else
  2450. else return NO;
  2451. #endif
  2452. }
  2453. case TAG_VECTOR:
  2454. /* /* wrong for Common Lisp */
  2455. return vec_equal(a, b);
  2456. default:
  2457. case TAG_BOXFLOAT:
  2458. { Header h = flthdr(a);
  2459. if (h != flthdr(b)) return NO;
  2460. #ifdef COMMON
  2461. if (type_of_header(h) == TYPE_SINGLE_FLOAT)
  2462. {
  2463. if (single_float_val(a) != single_float_val(b))
  2464. return NO;
  2465. else return YES;
  2466. }
  2467. else
  2468. #endif
  2469. /*
  2470. * For the moment I view all non-single floats as double floats. Extra
  2471. * stuff will be needed here if I ever implement long floats as 3-word
  2472. * objects.
  2473. */
  2474. {
  2475. if (double_float_val(a) != double_float_val(b))
  2476. return NO;
  2477. else return YES;
  2478. }
  2479. }
  2480. }
  2481. }
  2482. }
  2483. Lisp_Object Leq(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  2484. {
  2485. return onevalue(Lispify_predicate(a == b));
  2486. }
  2487. Lisp_Object Leql(Lisp_Object nil,
  2488. Lisp_Object a, Lisp_Object b)
  2489. {
  2490. return onevalue(Lispify_predicate(eql(a, b)));
  2491. }
  2492. Lisp_Object Leqcar(Lisp_Object nil,
  2493. Lisp_Object a, Lisp_Object b)
  2494. {
  2495. if (!consp(a)) return onevalue(nil);
  2496. a = qcar(a);
  2497. #ifdef COMMON
  2498. return onevalue(Lispify_predicate(eql(a, b)));
  2499. #else
  2500. return onevalue(Lispify_predicate(a == b));
  2501. #endif
  2502. }
  2503. Lisp_Object Lequalcar(Lisp_Object nil,
  2504. Lisp_Object a, Lisp_Object b)
  2505. {
  2506. if (!consp(a)) return onevalue(nil);
  2507. a = qcar(a);
  2508. if (a == b) return lisp_true;
  2509. else return onevalue(Lispify_predicate(equal(a, b)));
  2510. }
  2511. Lisp_Object Lcl_equal(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  2512. {
  2513. if (a == b) return onevalue(lisp_true);
  2514. else return onevalue(Lispify_predicate(cl_equal(a, b)));
  2515. }
  2516. Lisp_Object Lequal(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  2517. {
  2518. if (a == b) return onevalue(lisp_true);
  2519. else return onevalue(Lispify_predicate(equal(a, b)));
  2520. }
  2521. Lisp_Object Lequalp(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  2522. {
  2523. if (a == b) return onevalue(lisp_true);
  2524. else return onevalue(Lispify_predicate(equalp(a, b)));
  2525. }
  2526. Lisp_Object Lneq(Lisp_Object nil,
  2527. Lisp_Object a, Lisp_Object b)
  2528. {
  2529. CSLbool r;
  2530. #ifdef COMMON
  2531. r = cl_equal(a, b);
  2532. #else
  2533. r = equal(a, b);
  2534. #endif
  2535. return onevalue(Lispify_predicate(!r));
  2536. }
  2537. Lisp_Object Lnull(Lisp_Object nil, Lisp_Object a)
  2538. {
  2539. return onevalue(Lispify_predicate(a == nil));
  2540. }
  2541. Lisp_Object Lendp(Lisp_Object nil, Lisp_Object a)
  2542. {
  2543. if (a == nil) return onevalue(lisp_true);
  2544. else if (is_cons(a)) return onevalue(nil);
  2545. else return error(1, err_bad_endp, a);
  2546. }
  2547. Lisp_Object Lnreverse(Lisp_Object nil, Lisp_Object a)
  2548. {
  2549. Lisp_Object b = nil;
  2550. #ifdef COMMON
  2551. if (is_vector(a))
  2552. { int32 n = Llength(nil, a) - 0x10;
  2553. int32 i = TAG_FIXNUM;
  2554. while (n > i)
  2555. { Lisp_Object w = Laref2(nil, a, i);
  2556. Laset(nil, 3, a, i, Laref2(nil, a, n));
  2557. Laset(nil, 3, a, n, w);
  2558. i += 0x10;
  2559. n -= 0x10;
  2560. }
  2561. return onevalue(a);
  2562. }
  2563. #endif
  2564. while (consp(a))
  2565. { Lisp_Object c = a;
  2566. a = qcdr(a);
  2567. qcdr(c) = b;
  2568. b = c;
  2569. }
  2570. return onevalue(b);
  2571. }
  2572. Lisp_Object Lnreverse2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  2573. {
  2574. CSL_IGNORE(nil);
  2575. while (consp(a))
  2576. { Lisp_Object c = a;
  2577. a = qcdr(a);
  2578. qcdr(c) = b;
  2579. b = c;
  2580. }
  2581. return onevalue(b);
  2582. }
  2583. #ifdef COMMON
  2584. /*
  2585. * nreverse0 is like nreverse except that if its input is atomic it gets
  2586. * returned intact rather than being converted to nil.
  2587. */
  2588. Lisp_Object Lnreverse0(Lisp_Object nil, Lisp_Object a)
  2589. {
  2590. Lisp_Object b = nil;
  2591. if (!consp(a)) return onevalue(a);
  2592. b = a;
  2593. a = qcdr(a);
  2594. qcdr(b) = nil;
  2595. while (consp(a))
  2596. { Lisp_Object c = a;
  2597. a = qcdr(a);
  2598. qcdr(c) = b;
  2599. b = c;
  2600. }
  2601. return onevalue(b);
  2602. }
  2603. #endif
  2604. Lisp_Object Lreverse(Lisp_Object nil, Lisp_Object a)
  2605. {
  2606. Lisp_Object r;
  2607. stackcheck1(0, a);
  2608. nil = C_nil;
  2609. r = nil;
  2610. while (consp(a))
  2611. { push(a);
  2612. r = cons(qcar(a), r);
  2613. pop(a);
  2614. errexit();
  2615. a = qcdr(a);
  2616. }
  2617. return onevalue(r);
  2618. }
  2619. Lisp_Object Lassoc(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  2620. {
  2621. #ifdef TRACED_EQUAL
  2622. Lisp_Object save_b = b;
  2623. int pos = 0;
  2624. #endif
  2625. if (is_symbol(a) || is_fixnum(a))
  2626. { while (consp(b))
  2627. { Lisp_Object c = qcar(b);
  2628. if (consp(c) && a == qcar(c)) return onevalue(c);
  2629. b = qcdr(b);
  2630. }
  2631. return onevalue(nil);
  2632. }
  2633. while (consp(b))
  2634. { Lisp_Object c = qcar(b);
  2635. if (consp(c))
  2636. { Lisp_Object cc = qcar(c);
  2637. #ifdef COMMON
  2638. if (cl_equal(a, cc)) return onevalue(c);
  2639. #else
  2640. if (equal(a, cc))
  2641. {
  2642. #ifdef TRACED_EQUAL
  2643. trace_printf("Assoc YES %3d %3d ", pos, int_of_fixnum(Llength(nil,save_b)));
  2644. prin_to_stdout(a); trace_printf("\n");
  2645. #endif
  2646. return onevalue(c);
  2647. }
  2648. #endif
  2649. }
  2650. b = qcdr(b);
  2651. #ifdef TRACED_EQUAL
  2652. pos++;
  2653. #endif
  2654. }
  2655. #ifdef TRACED_EQUAL
  2656. trace_printf("Assoc NO %3d %3d ", pos, int_of_fixnum(Llength(nil,save_b)));
  2657. prin_to_stdout(a); trace_printf("\n");
  2658. #endif
  2659. return onevalue(nil);
  2660. }
  2661. Lisp_Object Latsoc(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  2662. {
  2663. #ifdef COMMON
  2664. if (is_symbol(a) || is_fixnum(a))
  2665. { while (consp(b))
  2666. { Lisp_Object c = qcar(b);
  2667. if (consp(c) && a == qcar(c)) return onevalue(c);
  2668. b = qcdr(b);
  2669. }
  2670. return onevalue(nil);
  2671. }
  2672. #endif
  2673. while (consp(b))
  2674. { Lisp_Object c = qcar(b);
  2675. /*
  2676. * eql() can neither fail nor call the garbage collector, so I do
  2677. * not need to stack things here.
  2678. */
  2679. #ifdef COMMON
  2680. if (consp(c) && eql(a, qcar(c))) return onevalue(c);
  2681. #else
  2682. if (consp(c) && a == qcar(c)) return onevalue(c);
  2683. #endif
  2684. b = qcdr(b);
  2685. }
  2686. return onevalue(nil);
  2687. }
  2688. Lisp_Object Lmember(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  2689. {
  2690. if (is_symbol(a) || is_fixnum(a))
  2691. { while (consp(b))
  2692. { if (a == qcar(b)) return onevalue(b);
  2693. b = qcdr(b);
  2694. }
  2695. return onevalue(nil);
  2696. }
  2697. while (consp(b))
  2698. { Lisp_Object cb = qcar(b);
  2699. #ifdef COMMON
  2700. if (cl_equal(a, cb)) return onevalue(b);
  2701. #else
  2702. if (equal(a, cb)) return onevalue(b);
  2703. #endif
  2704. b = qcdr(b);
  2705. }
  2706. return onevalue(nil);
  2707. }
  2708. Lisp_Object Lmemq(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  2709. {
  2710. #ifdef COMMON
  2711. if (is_symbol(a) || is_fixnum(a))
  2712. { while (consp(b))
  2713. { if (a == qcar(b)) return onevalue(b);
  2714. b = qcdr(b);
  2715. }
  2716. return onevalue(nil);
  2717. }
  2718. #endif
  2719. while (consp(b))
  2720. /*
  2721. * Note that eql() can never fail, and so checking for errors
  2722. * and stacking a and b across the call to it is not necessary.
  2723. */
  2724. {
  2725. #ifdef COMMON
  2726. if (eql(a, qcar(b))) return onevalue(b);
  2727. #else
  2728. if (a == qcar(b)) return onevalue(b);
  2729. #endif
  2730. b = qcdr(b);
  2731. }
  2732. return onevalue(nil);
  2733. }
  2734. static CSLbool smemq(Lisp_Object a, Lisp_Object b)
  2735. {
  2736. /*
  2737. * /* This is a bit worrying - it can use C recursion to arbitrary
  2738. * depth without any checking for overflow, and hence it can ESCAPE
  2739. * if (e.g.) given cyclic structures. Some alteration is needed. As
  2740. * things stand the code can never give wrong answers via GC rearrangement -
  2741. * the problem is closer to being that it can never call the GC.
  2742. */
  2743. #ifdef COMMON
  2744. Lisp_Object nil = C_nil;
  2745. #else
  2746. nil_as_base
  2747. #endif
  2748. while (consp(b))
  2749. { Lisp_Object w = qcar(b);
  2750. if (w == quote_symbol) return NO;
  2751. else if (smemq(a, w)) return YES;
  2752. else b = qcdr(b);
  2753. }
  2754. return (a == b);
  2755. }
  2756. Lisp_Object Lsmemq(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  2757. {
  2758. CSLbool r;
  2759. r = smemq(a, b);
  2760. errexit();
  2761. return onevalue(Lispify_predicate(r));
  2762. }
  2763. /*
  2764. * (defun contained (x y)
  2765. * (cond ((atom y) (equal x y))
  2766. * ((equal x y) 't)
  2767. * ('t (or (contained x (car y)) (contained x (cdr y))))))
  2768. */
  2769. static CSLbool containedeq(Lisp_Object nil, Lisp_Object x, Lisp_Object y)
  2770. {
  2771. while (consp(y))
  2772. { if (containedeq(nil, x, qcar(y))) return YES;
  2773. y = qcdr(y);
  2774. }
  2775. return (x == y);
  2776. }
  2777. static CSLbool containedequal(Lisp_Object nil, Lisp_Object x, Lisp_Object y)
  2778. {
  2779. while (consp(y))
  2780. { if (equal(x, y)) return YES;
  2781. if (containedequal(nil, x, qcar(y))) return YES;
  2782. y = qcdr(y);
  2783. }
  2784. return equal(x, y);
  2785. }
  2786. static Lisp_Object Lcontained(Lisp_Object nil, Lisp_Object x, Lisp_Object y)
  2787. {
  2788. CSLbool r;
  2789. if (is_symbol(x) || is_fixnum(x)) r = containedeq(nil, x, y);
  2790. else r = containedequal(nil, x, y);
  2791. errexit();
  2792. return onevalue(Lispify_predicate(r));
  2793. }
  2794. Lisp_Object Llast(Lisp_Object nil, Lisp_Object a)
  2795. {
  2796. Lisp_Object b;
  2797. CSL_IGNORE(nil);
  2798. if (!consp(a)) return aerror1("last", a);
  2799. while (b = qcdr(a), consp(b)) a = b;
  2800. return onevalue(qcar(a));
  2801. }
  2802. Lisp_Object Llastpair(Lisp_Object nil, Lisp_Object a)
  2803. {
  2804. Lisp_Object b;
  2805. CSL_IGNORE(nil);
  2806. if (!consp(a)) return onevalue(a); /* aerror1("lastpair", a); */
  2807. while (b = qcdr(a), consp(b)) a = b;
  2808. return onevalue(a);
  2809. }
  2810. Lisp_Object Llength(Lisp_Object nil, Lisp_Object a)
  2811. {
  2812. if (a == nil) return onevalue(fixnum_of_int(0));
  2813. if (is_cons(a))
  2814. { Lisp_Object n;
  2815. /*
  2816. * Possibly I should do something to trap cyclic lists.. ?
  2817. */
  2818. n = fixnum_of_int(1);
  2819. /*
  2820. * I have unrolled the loop here 4 times since I expect length to be
  2821. * tolerably heavily used. Look at the assembly code generated for
  2822. * this to see if it was useful or counterproductive!
  2823. */
  2824. for (;;)
  2825. { a = qcdr(a);
  2826. if (!consp(a)) return onevalue(n);
  2827. a = qcdr(a);
  2828. if (!consp(a)) return onevalue((Lisp_Object)((int32)n + (1 << 4)));
  2829. a = qcdr(a);
  2830. if (!consp(a)) return onevalue((Lisp_Object)((int32)n + (2 << 4)));
  2831. a = qcdr(a);
  2832. if (!consp(a)) return onevalue((Lisp_Object)((int32)n + (3 << 4)));
  2833. n = (Lisp_Object)((int32)n + (4 << 4));
  2834. }
  2835. }
  2836. #ifndef COMMON
  2837. return onevalue(fixnum_of_int(0)); /* aerror("length");??? */
  2838. #else
  2839. /*
  2840. * Common Lisp expects length to find the length of vectors
  2841. * as well as lists.
  2842. */
  2843. else if (!is_vector(a)) return aerror1("length", a);
  2844. else
  2845. { Header h = vechdr(a);
  2846. int32 n = length_of_header(h) - CELL;
  2847. if (type_of_header(h) == TYPE_ARRAY)
  2848. { Lisp_Object dims = elt(a, 1);
  2849. Lisp_Object fillp = elt(a, 5);
  2850. if (consp(dims) && !consp(qcdr(dims))) dims = qcar(dims);
  2851. else return aerror1("length", a); /* Not one-dimensional */
  2852. if (is_fixnum(fillp)) dims = fillp;
  2853. return onevalue(dims);
  2854. }
  2855. if (header_of_bitvector(h))
  2856. { n = (n - 1)*8;
  2857. /* Dodgy constant on next line - critically dependent on tag codes used! */
  2858. n += ((h & 0x380) >> 7) + 1;
  2859. }
  2860. else if (type_of_header(h) != TYPE_STRING) n = n/CELL;
  2861. return onevalue(fixnum_of_int(n));
  2862. }
  2863. #endif
  2864. }
  2865. #ifdef COMMON
  2866. Lisp_Object MS_CDECL Lappend_n(Lisp_Object nil, int nargs, ...)
  2867. {
  2868. va_list a;
  2869. int i;
  2870. Lisp_Object r;
  2871. if (nargs == 0) return onevalue(nil);
  2872. va_start(a, nargs);
  2873. push_args(a, nargs);
  2874. /*
  2875. * The actual args have been passed a C args - I can not afford to
  2876. * risk garbage collection until they have all been moved somewhere safe,
  2877. * and here that safe place is the Lisp stack. I have to delay checking for
  2878. * overflow on same until all args have been pushed.
  2879. */
  2880. stackcheck0(nargs);
  2881. nil = C_nil;
  2882. r = nil;
  2883. /*
  2884. * rearrange order of items on the stack...
  2885. * The idea is that I will then reverse-copy the args in the order a1,
  2886. * a2 , ... to make a result list. But I want to pop the stack as soon as
  2887. * I can, so I need arg1 on the TOP of the stack.
  2888. */
  2889. for (i = 0; 2*i+1<nargs; i++)
  2890. { Lisp_Object temp = stack[-i];
  2891. stack[-i] = stack[i+1-nargs];
  2892. stack[i+1-nargs] = temp;
  2893. }
  2894. for (i = 0; i<nargs; i++)
  2895. { Lisp_Object w;
  2896. pop(w);
  2897. while (consp(w))
  2898. { push(w);
  2899. nil = C_nil;
  2900. if (!exception_pending()) r = cons(qcar(w), r);
  2901. pop(w);
  2902. w = qcdr(w);
  2903. }
  2904. }
  2905. nil = C_nil;
  2906. if (exception_pending()) return C_nil;
  2907. return onevalue(nreverse(r));
  2908. }
  2909. Lisp_Object Lappend_1(Lisp_Object nil, Lisp_Object a)
  2910. {
  2911. CSL_IGNORE(nil);
  2912. return onevalue(a);
  2913. }
  2914. #endif /* COMMON */
  2915. Lisp_Object Lappend(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  2916. {
  2917. Lisp_Object r = nil;
  2918. push(b);
  2919. stackcheck2(1, a, r);
  2920. while (consp(a))
  2921. { push(a);
  2922. r = cons(qcar(a), r);
  2923. pop(a);
  2924. errexitn(1);
  2925. a = qcdr(a);
  2926. }
  2927. pop(b);
  2928. while (r != nil)
  2929. { a = qcdr(r);
  2930. qcdr(r) = b;
  2931. b = r;
  2932. r = a;
  2933. }
  2934. return onevalue(b);
  2935. }
  2936. Lisp_Object Ldelete(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  2937. {
  2938. Lisp_Object r;
  2939. push2(a, b);
  2940. r = nil;
  2941. if (is_symbol(a) || is_fixnum(a))
  2942. { while (consp(b))
  2943. { Lisp_Object q = qcar(b);
  2944. if (q == stack[-1])
  2945. { b = qcdr(b);
  2946. break;
  2947. }
  2948. stack[0] = qcdr(b);
  2949. r = cons(qcar(b), r);
  2950. errexitn(2);
  2951. b = stack[0];
  2952. }
  2953. }
  2954. else
  2955. { while (consp(b))
  2956. { Lisp_Object q = qcar(b);
  2957. #ifdef COMMON
  2958. if (cl_equal(q, a))
  2959. #else
  2960. if (equal(q, a))
  2961. #endif
  2962. { b = qcdr(b);
  2963. break;
  2964. }
  2965. stack[0] = qcdr(b);
  2966. r = cons(qcar(b), r);
  2967. errexitn(2);
  2968. b = stack[0];
  2969. a = stack[-1];
  2970. }
  2971. }
  2972. popv(2);
  2973. while (r != nil)
  2974. { Lisp_Object w = qcdr(r);
  2975. qcdr(r) = b;
  2976. b = r;
  2977. r = w;
  2978. }
  2979. return onevalue(b);
  2980. }
  2981. Lisp_Object Ldeleq(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  2982. {
  2983. Lisp_Object r;
  2984. push2(a, b);
  2985. r = nil;
  2986. while (consp(b))
  2987. { Lisp_Object q = qcar(b);
  2988. if (q == stack[-1])
  2989. { b = qcdr(b);
  2990. break;
  2991. }
  2992. stack[0] = qcdr(b);
  2993. r = cons(qcar(b), r);
  2994. errexitn(2);
  2995. b = stack[0];
  2996. }
  2997. popv(2);
  2998. while (r != nil)
  2999. { Lisp_Object w = qcdr(r);
  3000. qcdr(r) = b;
  3001. b = r;
  3002. r = w;
  3003. }
  3004. return onevalue(b);
  3005. }
  3006. Lisp_Object Lnconc(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  3007. {
  3008. Lisp_Object c;
  3009. CSL_IGNORE(nil);
  3010. if (!consp(a)) return onevalue(b);
  3011. c = a;
  3012. for (;;)
  3013. { Lisp_Object next = qcdr(c);
  3014. if (!consp(next))
  3015. { qcdr(c) = b;
  3016. return onevalue(a);
  3017. }
  3018. else c = next;
  3019. }
  3020. }
  3021. /* #ifndef COMMON */
  3022. static Lisp_Object Lsubstq(Lisp_Object a, Lisp_Object b, Lisp_Object c)
  3023. {
  3024. Lisp_Object w, nil = C_nil;
  3025. if (c == b) return onevalue(a);
  3026. #ifdef CHECK_STACK
  3027. if (check_stack(__FILE__,__LINE__)) return aerror("substq");
  3028. #endif
  3029. stackcheck3(0, a, b, c);
  3030. push3(a, b, c);
  3031. if (c == b)
  3032. { popv(2);
  3033. pop(a);
  3034. errexit();
  3035. return onevalue(a);
  3036. }
  3037. if (!consp(stack[0])) { pop(c); popv(2); return c; }
  3038. w = Lsubstq(stack[-2], stack[-1], qcar(stack[0]));
  3039. errexitn(3);
  3040. pop2(c, b);
  3041. a = stack[0];
  3042. stack[0] = w;
  3043. w = Lsubstq(a, b, qcdr(c));
  3044. pop(a);
  3045. errexit();
  3046. a = cons(a, w);
  3047. errexit();
  3048. return onevalue(a);
  3049. }
  3050. Lisp_Object MS_CDECL Lsubst(Lisp_Object nil, int nargs, ...)
  3051. {
  3052. Lisp_Object w, a, b, c;
  3053. va_list aa;
  3054. argcheck(nargs, 3, "subst");
  3055. #ifdef CHECK_STACK
  3056. if (check_stack(__FILE__,__LINE__)) return aerror("subst");
  3057. #endif
  3058. va_start(aa, nargs);
  3059. a = va_arg(aa, Lisp_Object);
  3060. b = va_arg(aa, Lisp_Object);
  3061. c = va_arg(aa, Lisp_Object);
  3062. va_end(aa);
  3063. if (c == b) return onevalue(a);
  3064. if (is_symbol(b) || is_fixnum(b)) return Lsubstq(a, b, c);
  3065. stackcheck3(0, a, b, c);
  3066. push3(a, b, c);
  3067. #ifdef COMMON
  3068. if (cl_equal(c, b))
  3069. #else
  3070. if (equal(c, b))
  3071. #endif
  3072. { popv(2);
  3073. pop(a);
  3074. errexit();
  3075. return onevalue(a);
  3076. }
  3077. if (!consp(stack[0])) { pop(c); popv(2); return c; }
  3078. w = Lsubst(nil, 3, stack[-2], stack[-1], qcar(stack[0]));
  3079. errexitn(3);
  3080. pop2(c, b);
  3081. a = stack[0];
  3082. stack[0] = w;
  3083. w = Lsubst(nil, 3, a, b, qcdr(c));
  3084. pop(a);
  3085. errexit();
  3086. a = cons(a, w);
  3087. errexit();
  3088. return onevalue(a);
  3089. }
  3090. /* #endif */
  3091. Lisp_Object Lsublis(Lisp_Object nil, Lisp_Object al, Lisp_Object x)
  3092. {
  3093. stackcheck2(0, al, x);
  3094. errexit();
  3095. #ifdef CHECK_STACK
  3096. if (check_stack(__FILE__,__LINE__)) return aerror("sublis");
  3097. #endif
  3098. push5(al, x, al, nil, nil);
  3099. #define carx stack[0]
  3100. #define cdrx stack[-1]
  3101. #define w stack[-2]
  3102. #define x stack[-3]
  3103. #define al stack[-4]
  3104. for (;;)
  3105. { if (!consp(w))
  3106. { if (!consp(x))
  3107. { Lisp_Object temp = x;
  3108. popv(5);
  3109. return temp;
  3110. }
  3111. carx = Lsublis(nil, al, qcar(x));
  3112. errexitn(5);
  3113. cdrx = Lsublis(nil, al, qcdr(x));
  3114. errexitn(5);
  3115. if (carx == qcar(x) && cdrx == qcdr(x))
  3116. { Lisp_Object temp = x;
  3117. popv(5);
  3118. return temp;
  3119. }
  3120. else
  3121. { Lisp_Object a1 = carx, a2 = cdrx;
  3122. popv(5);
  3123. return cons(a1, a2);
  3124. }
  3125. }
  3126. { Lisp_Object temp = qcar(w);
  3127. if (consp(temp))
  3128. { Lisp_Object v = qcar(temp);
  3129. #ifdef COMMON
  3130. if (cl_equal(v, x))
  3131. #else
  3132. if (equal(v, x))
  3133. #endif
  3134. { temp = qcdr(temp);
  3135. popv(5);
  3136. return temp;
  3137. }
  3138. }
  3139. }
  3140. w = qcdr(w);
  3141. }
  3142. }
  3143. #undef carx
  3144. #undef cdrx
  3145. #undef w
  3146. #undef x
  3147. #undef al
  3148. Lisp_Object Lsubla(Lisp_Object nil, Lisp_Object al, Lisp_Object x)
  3149. /*
  3150. * as sublis, but uses eq test rather than equal
  3151. */
  3152. {
  3153. stackcheck2(0, al, x);
  3154. errexit();
  3155. #ifdef CHECK_STACK
  3156. if (check_stack(__FILE__,__LINE__)) return aerror("subla");
  3157. #endif
  3158. push5(al, x, al, nil, nil);
  3159. #define carx stack[0]
  3160. #define cdrx stack[-1]
  3161. #define w stack[-2]
  3162. #define x stack[-3]
  3163. #define al stack[-4]
  3164. for (;;)
  3165. { if (!consp(w))
  3166. { if (!consp(x))
  3167. { Lisp_Object temp = x;
  3168. popv(5);
  3169. return temp;
  3170. }
  3171. carx = Lsubla(nil, al, qcar(x));
  3172. errexitn(5);
  3173. cdrx = Lsubla(nil, al, qcdr(x));
  3174. errexitn(5);
  3175. if (carx == qcar(x) && cdrx == qcdr(x))
  3176. { Lisp_Object temp = x;
  3177. popv(5);
  3178. return temp;
  3179. }
  3180. else
  3181. { Lisp_Object a1 = carx, a2 = cdrx;
  3182. popv(5);
  3183. return cons(a1, a2);
  3184. }
  3185. }
  3186. { Lisp_Object temp = qcar(w);
  3187. if (consp(temp))
  3188. { Lisp_Object v = qcar(temp);
  3189. if (v == x) { temp = qcdr(temp); popv(5); return temp; }
  3190. }
  3191. }
  3192. w = qcdr(w);
  3193. }
  3194. }
  3195. #undef carx
  3196. #undef cdrx
  3197. #undef w
  3198. #undef x
  3199. #undef al
  3200. setup_type const funcs2_setup[] =
  3201. {
  3202. {"assoc", too_few_2, Lassoc, wrong_no_2},
  3203. /*
  3204. * assoc** is expected to remain as the Standard Lisp version even if in
  3205. * a Common Lisp world I redefine assoc to be someting messier. xassoc was
  3206. * an earlier name I used for the same purpose, and is being withdrawn.
  3207. */
  3208. {"assoc**", too_few_2, Lassoc, wrong_no_2},
  3209. {"xassoc", too_few_2, Lassoc, wrong_no_2},
  3210. {"atsoc", too_few_2, Latsoc, wrong_no_2},
  3211. {"member", too_few_2, Lmember, wrong_no_2},
  3212. {"member**", too_few_2, Lmember, wrong_no_2},
  3213. {"memq", too_few_2, Lmemq, wrong_no_2},
  3214. {"contained", too_few_2, Lcontained, wrong_no_2},
  3215. {"restart-csl", Lrestart_csl, Lrestart_csl2, wrong_no_1},
  3216. {"eq", too_few_2, Leq, wrong_no_2},
  3217. {"iequal", too_few_2, Leq, wrong_no_2},
  3218. {"eqcar", too_few_2, Leqcar, wrong_no_2},
  3219. {"equalcar", too_few_2, Lequalcar, wrong_no_2},
  3220. {"eql", too_few_2, Leql, wrong_no_2},
  3221. {"equalp", too_few_2, Lequalp, wrong_no_2},
  3222. {"endp", Lendp, too_many_1, wrong_no_1},
  3223. {"getd", Lgetd, too_many_1, wrong_no_1},
  3224. {"last", Llast, too_many_1, wrong_no_1},
  3225. {"lastpair", Llastpair, too_many_1, wrong_no_1},
  3226. {"length", Llength, too_many_1, wrong_no_1},
  3227. {"make-bps", Lget_bps, too_many_1, wrong_no_1},
  3228. {"make-native", Lget_native, too_many_1, wrong_no_1},
  3229. {"symbol-env", Lsymbol_env, too_many_1, wrong_no_1},
  3230. {"symbol-make-fastget", Lsymbol_make_fastget1, Lsymbol_make_fastget, wrong_no_2},
  3231. {"symbol-fastgets", Lsymbol_fastgets, too_many_1, wrong_no_1},
  3232. {"symbol-fn-cell", Lsymbol_fn_cell, too_many_1, wrong_no_1},
  3233. {"symbol-argcount", Lsymbol_argcount, too_many_1, wrong_no_1},
  3234. {"symbol-set-env", too_few_2, Lsymbol_set_env, wrong_no_2},
  3235. {"symbol-set-native", wrong_no_na, wrong_no_nb, Lsymbol_set_native},
  3236. {"symbol-set-definition", too_few_2, Lsymbol_set_definition, wrong_no_2},
  3237. {"restore-c-code", Lrestore_c_code, too_many_1, wrong_no_1},
  3238. {"set-autoload", too_few_2, Lset_autoload, wrong_no_2},
  3239. {"remd", Lremd, too_many_1, wrong_no_1},
  3240. {"trace", Ltrace, too_many_1, wrong_no_1},
  3241. {"untrace", Luntrace, too_many_1, wrong_no_1},
  3242. {"trace-all", Ltrace_all, too_many_1, wrong_no_1},
  3243. {"double-execute", Ldouble, too_many_1, wrong_no_1},
  3244. {"undouble-execute", Lundouble, too_many_1, wrong_no_1},
  3245. {"macro-function", Lmacro_function, too_many_1, wrong_no_1},
  3246. {"symbol-name", Lsymbol_name, too_many_1, wrong_no_1},
  3247. {"plist", Lplist, too_many_1, wrong_no_1},
  3248. {"delete", too_few_2, Ldelete, wrong_no_2},
  3249. {"deleq", too_few_2, Ldeleq, wrong_no_2},
  3250. {"preserve", Lpreserve_1, Lpreserve, Lpreserve_0},
  3251. {"checkpoint", Lcheckpoint_1, Lcheckpoint, Lcheckpoint_0},
  3252. {"mkvect", Lmkvect, too_many_1, wrong_no_1},
  3253. {"nconc", too_few_2, Lnconc, wrong_no_2},
  3254. {"neq", too_few_2, Lneq, wrong_no_2},
  3255. {"not", Lnull, too_many_1, wrong_no_1},
  3256. {"null", Lnull, too_many_1, wrong_no_1},
  3257. {"reverse", Lreverse, too_many_1, wrong_no_1},
  3258. {"reversip", Lnreverse, Lnreverse2, wrong_no_1},
  3259. /* I make the name nreverse generally available as well as reversip */
  3260. {"nreverse", Lnreverse, Lnreverse2, wrong_no_1},
  3261. {"smemq", too_few_2, Lsmemq, wrong_no_2},
  3262. {"subla", too_few_2, Lsubla, wrong_no_2},
  3263. {"sublis", too_few_2, Lsublis, wrong_no_2},
  3264. {"subst", wrong_no_3a, wrong_no_3b, Lsubst},
  3265. {"symbol-protect", too_few_2, Lsymbol_protect, wrong_no_2},
  3266. #ifdef COMMON
  3267. {"symbol-package", Lsymbol_package, too_many_1, wrong_no_1},
  3268. {"symbol-plist", Lplist, too_many_1, wrong_no_1},
  3269. {"append", Lappend_1, Lappend, Lappend_n},
  3270. /*
  3271. * In Common Lisp mode I make EQUAL do what Common Lisp says it should, but
  3272. * also have EQUALS that is much the same but which also descends vectors.
  3273. */
  3274. {"equal", too_few_2, Lcl_equal, wrong_no_2},
  3275. {"equals", too_few_2, Lequal, wrong_no_2},
  3276. {"nreverse0", Lnreverse0, too_many_1, wrong_no_1},
  3277. #else
  3278. {"append", too_few_2, Lappend, wrong_no_2},
  3279. /* In Standard Lisp mode EQUAL descends vectors (but does not case fold) */
  3280. /* I provide cl-equal to do what Common Lisp does. */
  3281. {"cl-equal", too_few_2, Lcl_equal, wrong_no_2},
  3282. {"equal", too_few_2, Lequal, wrong_no_2},
  3283. {"member", too_few_2, Lmember, wrong_no_2},
  3284. {"member", too_few_2, Lmember, wrong_no_2},
  3285. #endif
  3286. {NULL, 0, 0, 0}
  3287. };
  3288. /* end of fns2.c */