1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421 |
- /* fns2.c Copyright (C) 1989-2002 Codemist Ltd */
- /*
- * Basic functions part 2.
- */
- /*
- * This code may be used and modified, and redistributed in binary
- * or source form, subject to the "CCL Public License", which should
- * accompany it. This license is a variant on the BSD license, and thus
- * permits use of code derived from this in either open and commercial
- * projects: but it does require that updates to this code be made
- * available back to the originators of the package.
- * Before merging other code in with this or linking this code
- * with other packages or libraries please check that the license terms
- * of the other material are compatible with those of this.
- */
- /* Signature: 3fc8c70b 10-Oct-2002 */
- #include <stdarg.h>
- #include <string.h>
- #include <ctype.h>
- #include "machine.h"
- #include "tags.h"
- #include "cslerror.h"
- #include "externs.h"
- #include "read.h"
- #include "entries.h"
- #include "arith.h"
- #ifdef COMMON
- #include "clsyms.h"
- #endif
- #ifdef TIMEOUT
- #include "timeout.h"
- #endif
- #ifdef SOCKETS
- #include "sockhdr.h"
- #endif
- Lisp_Object getcodevector(int32 type, intxx size)
- {
- /*
- * type is the code (e.g. TYPE_BPS) that gets packed, together with
- * the size, into a header word.
- * size is measured in bytes and must allow space for the header word.
- * This obtains space in the BPS area
- */
- Lisp_Object nil = C_nil;
- #ifdef CHECK_FOR_CORRUPT_HEAP
- validate_all();
- #endif
- for (;;)
- { intxx alloc_size = (intxx)doubleword_align_up(size);
- char *cf = (char *)codefringe, *cl = (char *)codelimit;
- unsignedxx free = cf - cl;
- char *r;
- if (alloc_size > (intxx)free)
- { char msg[40];
- sprintf(msg, "codevector %ld", (long)size);
- reclaim(nil, msg, GC_BPS, alloc_size);
- errexit();
- continue;
- }
- r = cf - alloc_size;
- codefringe = (Lisp_Object)r;
- *((Header *)r) = type + (size << 10) + TAG_ODDS;
- /*
- * codelimit is always 8 bytes above the base of the code-page. The
- * address I need to return for a code-vector points (in a packed way)
- * to the first byte of actual byte data, ie CELL bytes above the start
- * of the data-structure. Oh joy!
- */
- return TAG_BPS +
- (((int32)((r + CELL) - (cl - 8)) & (PAGE_POWER_OF_TWO-4)) << 6) +
- (((int32)(bps_pages_count-1))<<(PAGE_BITS+6)); /* Wow! Obscure!! */
- }
- }
- Lisp_Object Lget_bps(Lisp_Object nil, Lisp_Object n)
- {
- int32 n1;
- if (!is_fixnum(n) || (int32)n<0) return aerror1("get-bps", n);
- n1 = int_of_fixnum(n);
- n = getcodevector(TYPE_BPS, n1+CELL);
- errexit();
- return onevalue(n);
- }
- Lisp_Object get_native_code_vector(intxx size)
- {
- /*
- * Create some space for native code and return a handle that identifies
- * its start point. size is measured in bytes.
- */
- Lisp_Object nil = C_nil;
- if (size <= 0) size = 8;
- for (;;)
- { intxx alloc_size = (intxx)doubleword_align_up(size);
- intxx cf = native_fringe;
- intxx free = CSL_PAGE_SIZE - cf - 0x100; /* 256 bytes to be safe */
- /*
- * When I start up a cold CSL I will have native_fringe set to zero and
- * native_pages_count also zero, indicating that there is none of this stuff
- * active.
- */
- if (native_fringe == 0 || alloc_size > free)
- { char msg[40];
- sprintf(msg, "native code %ld", (long)size);
- reclaim(nil, msg, GC_NATIVE, alloc_size);
- errexit();
- continue;
- }
- free = (intxx)native_pages[native_pages_count-1];
- free = doubleword_align_up(free);
- /*
- * I put the number of bytes in this block as the first word of the chunk
- * of memory, and arrange that there is a zero in what would be the first
- * word of unused space. Provided the user does not clobber bytes 0 to 4
- * or the block this is enough to allow restart code to scan through all
- * native code segments.
- */
- car32(free+native_fringe) = alloc_size;
- car32(free+native_fringe+alloc_size) = 0;
- native_fringe += alloc_size;
- native_pages_changed = 1;
- return Lcons(nil,
- fixnum_of_int(native_pages_count-1),
- fixnum_of_int(cf));
- }
- }
- Lisp_Object Lget_native(Lisp_Object nil, Lisp_Object n)
- {
- int32 n1;
- if (!is_fixnum(n) || (int32)n<0) return aerror1("get-native", n);
- n1 = int_of_fixnum(n);
- n = get_native_code_vector(n1);
- errexit();
- return onevalue(n);
- }
- int do_not_kill_native_code = 0;
- void set_fns(Lisp_Object a, one_args *f1, two_args *f2, n_args *fn)
- {
- Lisp_Object nil = C_nil;
- Lisp_Object w1, w2, w3 = nil;
- /*
- * If I redefine a function for any reason (except to set trace options
- * on a bytecoded definition) I will discard any native-coded definitions
- * by splicing them out of the record. I provide a global variable to
- * defeat this behaviour (ugh).
- */
- if (!do_not_kill_native_code)
- { for (w1 = native_code; w1!=nil; w1=qcdr(w1))
- { w2 = qcar(w1);
- if (qcar(w2) == a) break;
- w3 = w1;
- }
- if (w1 != nil)
- { w1 = qcdr(w1);
- if (w3 == nil) native_code = w1;
- else qcdr(w3) = w1;
- }
- }
- if ((qheader(a) & (SYM_C_DEF | SYM_CODEPTR)) ==
- (SYM_C_DEF | SYM_CODEPTR))
- { if (symbol_protect_flag)
- { if (warn_about_protected_symbols)
- { trace_printf("+++ WARNING: protected function ");
- prin_to_trace(a);
- trace_printf(" not redefined\n");
- }
- return;
- }
- else
- { if (warn_about_protected_symbols)
- { trace_printf("+++ WARNING: protected function ");
- prin_to_trace(a);
- trace_printf(" *has* been redefined\n");
- }
- Lsymbol_protect(C_nil, a, C_nil);
- }
- }
- ifn1(a) = (intxx)f1;
- ifn2(a) = (intxx)f2;
- ifnn(a) = (intxx)fn;
- }
- #ifdef HIDE_USELESS_SYMBOL_ENVIRONMENTS
- static CSLbool interpreter_entry(Lisp_Object a)
- /*
- * If a function will be handled by the interpreter, including the case
- * of it being undefined, then the fn1() cell will tell me so.
- */
- {
- return (
- qfn1(a) == interpreted1 ||
- qfn1(a) == traceinterpreted1 ||
- qfn1(a) == double_interpreted1 ||
- qfn1(a) == funarged1 ||
- qfn1(a) == tracefunarged1 ||
- qfn1(a) == double_funarged1 ||
- qfn1(a) == undefined1);
- }
- #endif
- static char *show_fn(void *p)
- {
- int i;
- for (i=0; i<entry_table_size; i++)
- if (entries_table[i].p == p) return 1+entries_table[i].s;
- trace_printf("+++ Unknown function pointer = %lx\n", (long)p);
- return "unknown";
- }
- Lisp_Object Lsymbol_fn_cell(Lisp_Object nil, Lisp_Object a)
- /*
- * For debugging...
- */
- {
- char *s1, *s2, *sn;
- if (!symbolp(a)) return onevalue(nil);
- s1 = show_fn((void *)qfn1(a));
- s2 = show_fn((void *)qfn2(a));
- sn = show_fn((void *)qfnn(a));
- trace_printf("%s %s %s\n", s1, s2, sn);
- return onevalue(nil);
- }
- Lisp_Object Lsymbol_argcount(Lisp_Object nil, Lisp_Object a)
- /*
- * For debugging and JIT compiler use. Only valid if the function involved
- * is byte-coded. For simple functions taking a fixed number of args the
- * result is an integer. Otherwise it is a list of 3 items
- * (fewest-legal-args most-args-before-&rest flags)
- * where the flags has a 1 bit if missing &optional args are to be left
- * for the bytecoded stuff to unpick, otherwise they should be mapped to nil
- * somewhere. The 2 bit is present if a &rest argument is present.
- */
- {
- one_args *f1;
- two_args *f2;
- n_args *fn;
- int low, high, hardrest;
- Lisp_Object r;
- unsigned char *b;
- if (!symbolp(a)) return onevalue(nil);
- f1 = qfn1(a);
- f2 = qfn2(a);
- fn = qfnn(a);
- r = qenv(a);
- if (!consp(r)) return onevalue(nil);
- r = qcar(r);
- if (!is_bps(r)) return onevalue(nil);
- b = (unsigned char *)data_of_bps(r);
- if (f1 == bytecoded1 ||
- f1 == tracebytecoded1 ||
- f1 == double_bytecoded1) return onevalue(fixnum_of_int(1));
- if (f2 == bytecoded2 ||
- f2 == tracebytecoded2 ||
- f2 == double_bytecoded2) return onevalue(fixnum_of_int(2));
- if (fn == bytecoded0 ||
- fn == tracebytecoded0 ||
- fn == double_bytecoded0) return onevalue(fixnum_of_int(0));
- if (fn == bytecoded3 ||
- fn == tracebytecoded3 ||
- fn == double_bytecoded3) return onevalue(fixnum_of_int(3));
- if (fn == bytecodedn ||
- fn == tracebytecodedn ||
- fn == double_bytecodedn) return onevalue(fixnum_of_int(b[0]));
- low = b[0]; /* smallest number of valid args */
- high = low + b[1]; /* largest number before &rest is accounted for */
- hardrest = 0;
- /*
- * byteopt - optional arguments, with default of NIL
- */
- if (f1 == byteopt1 ||
- f1 == tracebyteopt1) hardrest = 0;
- /*
- * hardopt - optional arguments but default is passed as a SPID so that
- * the user can follow up and apply cleverer default processing
- */
- else if (f1 == hardopt1 ||
- f1 == tracehardopt1) hardrest = 1;
- /*
- * byteoptrest - anything with a &rest argument on the end.
- */
- else if (f1 == byteoptrest1 ||
- f1 == tracebyteoptrest1) hardrest = 1;
- /*
- * hardoptrest - some &optional args with non-nil default value, plus &rest
- */
- else if (f1 == hardoptrest1 ||
- f1 == tracehardoptrest1) hardrest = 3;
- else return onevalue(nil);
- r = list3(fixnum_of_int(low),
- fixnum_of_int(high), fixnum_of_int(hardrest));
- errexit();
- return onevalue(r);
- }
-
- Lisp_Object Lsymbol_env(Lisp_Object nil, Lisp_Object a)
- /*
- * Not Common Lisp - read the 'environment' cell associated with a
- * symbol. This cell is deemed empty unless the symbol-function is
- * compiled code. For use mainly for debugging.
- */
- {
- if (!symbolp(a)) return onevalue(nil);
- #ifdef HIDE_USELESS_SYMBOL_ENVIRONMENTS
- else if ((qheader(a) & (SYM_SPECIAL_FORM | SYM_MACRO)) != 0 ||
- interpreter_entry(a)) return onevalue(nil);
- #endif
- return onevalue(qenv(a));
- }
- Lisp_Object Lsymbol_set_env(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- CSL_IGNORE(nil);
- if (!is_symbol(a)) return aerror1("symbol-set-env", a);
- if ((qheader(a) & (SYM_C_DEF | SYM_CODEPTR)) ==
- (SYM_C_DEF | SYM_CODEPTR)) return onevalue(nil);
- qenv(a) = b;
- return onevalue(b);
- }
- Lisp_Object Lsymbol_fastgets(Lisp_Object nil, Lisp_Object a)
- {
- if (!symbolp(a)) return onevalue(nil);
- return onevalue(qfastgets(a));
- }
- /*
- * (protect 'name t) arranges that the function indicated (which is
- * expected to have been defined in the C kernel) can not be redefined.
- * (protect 'name nil) restores the usual state of affairs.
- */
- Lisp_Object Lsymbol_protect(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- Header h;
- if (!is_symbol(a)) return onevalue(nil);
- h = qheader(a);
- if (b == nil) qheader(a) = h & ~(SYM_CODEPTR | SYM_C_DEF);
- else qheader(a) = h | SYM_CODEPTR | SYM_C_DEF;
- h &= (SYM_CODEPTR | SYM_C_DEF);
- return onevalue(Lispify_predicate(h == (SYM_CODEPTR | SYM_C_DEF)));
- }
- /*
- * (symbol-make-fastget 'xxx nil) returns current information, nil if no
- * fastget usage set.
- * (symbol-make-fastget 'xxx n) sets it to n (0 <= n < 63)
- * (symbol-make-fastget 'xxx -1) sets the option off
- * (symbol-make-fastget n) specify fast-get range (n <= 63)
- */
- Lisp_Object Lsymbol_make_fastget1(Lisp_Object nil, Lisp_Object a)
- {
- int32 n, n1 = fastget_size;
- CSL_IGNORE(nil);
- if (!is_fixnum(a) ||
- (n = int_of_fixnum(a)) < 0 ||
- (n > MAX_FASTGET_SIZE)) return aerror1("symbol-make-fastget", a);
- term_printf("+++ Fastget size was %d, now %d\n", n1, n);
- fastget_size = n;
- return onevalue(fixnum_of_int(n1));
- }
- Lisp_Object Lsymbol_make_fastget(Lisp_Object nil, Lisp_Object a, Lisp_Object n)
- {
- int32 n1, p, q;
- Header h;
- if (!symbolp(a)) return onevalue(nil);
- h = qheader(a);
- p = header_fastget(h);
- if (is_fixnum(n))
- { n1 = int_of_fixnum(n);
- if (n1 < -1 || n1 >= fastget_size)
- return aerror1("symbol-make-fastget", n);
- trace_printf("+++ Use fastget slot %d for ", n1);
- loop_print_trace(a);
- errexit();
- trace_printf("\n");
- if (p != 0) elt(fastget_names, p-1) = SPID_NOPROP;
- q = (n1 + 1) & 0x3f;
- h = (h & ~SYM_FASTGET_MASK) | (q << SYM_FASTGET_SHIFT);
- qheader(a) = h;
- if (q != 0) elt(fastget_names, q-1) = a;
- }
- if (p == 0) return onevalue(nil);
- else return onevalue(fixnum_of_int(p - 1));
- }
- static Lisp_Object deleqip(Lisp_Object a, Lisp_Object l)
- /*
- * This deletes the item a (tested for using EQ) from the list l,
- * assuming that the list is nil-terminated and that the item a
- * occurs at most once. It overwrites the list l in the process.
- */
- {
- Lisp_Object nil = C_nil, w, r;
- if (l == nil) return nil;
- if (qcar(l) == a) return qcdr(l);
- r = l;
- while (w = l, (l = qcdr(l)) != nil)
- { if (qcar(l) == a)
- { qcdr(w) = qcdr(l);
- return r;
- }
- }
- return r;
- }
- void lose_C_def(Lisp_Object a)
- {
- /*
- * None of the code here can cause garbage collection.
- */
- #ifdef COMMON
- Lisp_Object nil = C_nil;
- Lisp_Object b = get(a, unset_var, nil), c;
- #else
- nil_as_base
- Lisp_Object b = get(a, unset_var), c;
- #endif
- Lremprop(C_nil, a, unset_var);
- qheader(a) &= ~SYM_C_DEF;
- #ifdef COMMON
- c = get(b, work_symbol, nil);
- #else
- c = get(b, work_symbol);
- #endif
- c = deleqip(a, c);
- if (c == C_nil) Lremprop(C_nil, b, work_symbol);
- else putprop(b, work_symbol, c);
- }
- /*
- * (symbol-set-native fn args bpsbase offset env)
- * where bpsbase is as handed back by (make-native nnn) and offset is
- * the offset in this block to enter at.
- * If args has the actual arg count in its bottom byte. Usually the
- * rest of it will be zero, and then one function cell is set to point to the
- * given entrypoint and the other two are set to point at error handlers.
- * If any bits in args beyond that are set then this call only changes the
- * directly specified function cell, and the others are left in whatever state
- * they were. If several of the fuction cells are to be filled in (eg to cope
- * with &optional or &rest arguments) then a simple call with args<256 must
- * be made first, followed by the calls (args>=256) that fill in the other
- * two cells.
- * The first time that symbol-set-native is called on a function that
- * function MUST have a byte coded definition, and this definition is
- * picked up and stored away, so that if (preserve) is called the bytecoded
- * definition will be available for use on systems with different
- * architectures. To make things tolerably consistent with that any operation
- * that installs a new bytecoded (or for that matter other) definition
- * will clear away any native-compiled versions of the function.
- *
- * The native code that is installed will be expected to have relocation
- * records starting at the start of bpsbase, and these will be activated,
- * filling in references from the bps to other executable parts of Lisp.
- * Passing bad arguments to this function provide a quick and easy way to
- * cayse UTTER havoc. Therefore I disable its use in server applications.
- */
- Lisp_Object MS_CDECL Lsymbol_set_native(Lisp_Object nil, int nargs, ...)
- {
- va_list a;
- Lisp_Object fn, args, bpsbase, offset, env, w1, w2, w3;
- int32 pagenumber, t_p, arginfo;
- intxx address, page, bps;
- #ifdef SOCKETS
- /*
- * Security measure - deny symbol-set-native to remote users
- */
- if (socket_server != 0) return aerror("symbol-set-native");
- #endif
- argcheck(nargs, 5, "symbol-set-native");
- va_start(a, nargs);
- fn = va_arg(a, Lisp_Object);
- args = va_arg(a, Lisp_Object);
- bpsbase = va_arg(a, Lisp_Object);
- offset = va_arg(a, Lisp_Object);
- env = va_arg(a, Lisp_Object);
- va_end(a);
- if (!is_symbol(fn) ||
- (qheader(fn) & (SYM_SPECIAL_FORM | SYM_CODEPTR)) != 0)
- return aerror1("symbol-set-native", fn);
- if (!is_fixnum(args)) return aerror1("symbol-set-native", args);
- if (!consp(bpsbase) ||
- !is_fixnum(qcar(bpsbase)) ||
- !is_fixnum(qcdr(bpsbase)))
- return aerror1("symbol-set-native", bpsbase);
- if (!is_fixnum(offset)) return aerror1("symbol-set-native", offset);
- nargs = int_of_fixnum(args);
- pagenumber = int_of_fixnum(qcar(bpsbase));
- if (pagenumber<0 || pagenumber>=native_pages_count)
- return aerror1("symbol-set-native", bpsbase);
- bps = int_of_fixnum(qcdr(bpsbase));
- address = bps+int_of_fixnum(offset);
- if (address<8 || address>=CSL_PAGE_SIZE)
- return aerror1("symbol-set-native", offset);
- page = (intxx)native_pages[pagenumber];
- page = doubleword_align_up(page);
- bps = page + bps;
- relocate_native_function((unsigned char *)bps);
- /*
- * Here I need to push the info I have just collected onto
- * the native_code list since otherwise things will not be re-loaded in
- * from a checkpoint image. Also if the function is at present byte-coded
- * I need to record that info about it in native_code.
- */
- w1 = native_code;
- w2 = nil;
- while (w1!=nil)
- { w2 = qcar(w1);
- if (qcar(w2) == fn) break;
- w1 = qcdr(w1);
- }
- if (w1 == nil)
- {
- /*
- * Here the function has not been seen as native code ever before, so it has
- * not been entered into the list. Do something about that...
- */
- push2(env, fn);
- args = Lsymbol_argcount(nil, fn);
- errexitn(2);
- if (args == nil)
- return aerror1("No bytecode definition found for", fn);
- /*
- * Now I have to reverse the information that symbol_argcount gave me
- * to get the single numeric code as wanted by symbol_set_definition.
- * Oh what a mess.
- */
- if (is_fixnum(args)) arginfo = int_of_fixnum(args);
- else
- { arginfo = int_of_fixnum(qcar(args));
- args = qcdr(args);
- arginfo |= ((int_of_fixnum(qcar(args)) - arginfo) << 8);
- args = qcdr(args);
- arginfo |= int_of_fixnum(qcar(args)) << 16;
- }
- fn = stack[0];
- w2 = list2(fn, fixnum_of_int(arginfo));
- errexitn(2);
- w2 = cons(w2, native_code);
- errexitn(2);
- native_code = w2;
- w2 = qcar(w2);
- pop2(fn, env);
- }
- w2 = qcdr(w2); /* {nargs,(type . offset . env),...} */
- /*
- * If I was defining this function in the simple way I should clear any
- * previous version (for this machine architecture) from the record.
- * Just at present this does not release the memory, but at some stage
- * in the future I may arrange to compact away old code when I do a
- * preserve operation (say).
- */
- if (nargs <= 0xff)
- { w1 = w3 = w2;
- for (w1=qcdr(w2); w1!=nil; w1=qcdr(w1))
- { w3 = qcar(w1);
- if (qcar(w3) == fixnum_of_int(native_code_tag)) break;
- w3 = w1;
- }
- if (w1 != nil) qcdr(w3) = qcdr(w1);
- }
- /*
- * w2 is still the entry for this function in the native code list. It
- * needs to have an entry of type 0 (ie for bytecoded) and so the next
- * thing to do is to check that such an entry exists and if not to create
- * it.
- */
- w1 = w2;
- while ((w1 = qcdr(w1)) != nil)
- { w3 = qcar(w1);
- if (qcar(w3) == fixnum_of_int(0)) break;
- w1 = qcdr(w1);
- }
- if (w1 == nil)
- {
- /*
- * This is where there was no bytecode entry on the native code list
- * for this function, so I had better create one for it. Note that only
- * one such entry will ever be stored so it does not matter much where on
- * the list it goes. I suspect that the list ought always to be empty
- * in this case anyway.
- */
- push3(fn, env, w2);
- w1 = list2star(fixnum_of_int(0), fixnum_of_int(0), qenv(fn));
- errexitn(3);
- w2 = stack[0];
- w1 = cons(w1, qcdr(w2));
- errexitn(3);
- pop3(w2, env, fn);
- qcdr(w2) = w1;
- }
- /*
- * Now the list of native code associated with this function certainly holds
- * a byte-coded definition (and for sanity that had better be consistent
- * with the native code I am installing now, but that is not something
- * that can be checked at this level). Put in an entry referring to the
- * current gubbins.
- */
- push3(w2, fn, env);
- /*
- * now I pack the code type, arg category and offset into the
- * single fixnum that that information has to end up in.
- */
- t_p = (native_code_tag << 20);
- if ((nargs & 0xffffff00) != 0)
- {
- switch (nargs & 0xff)
- {
- case 1: t_p |= (1<<18); break;
- case 2: t_p |= (2<<18); break;
- default:t_p |= (3<<18); break;
- }
- }
- t_p |= (pagenumber & 0x3ffff);
- w1 = list2star(fixnum_of_int(t_p), fixnum_of_int(address), env);
- errexitn(3);
- w1 = ncons(w1);
- pop3(env, fn, w2);
- errexit();
- while ((w3 = qcdr(w2)) != nil) w2 = w3; /* Tag onto the END */
- qcdr(w2) = w1;
- qheader(fn) &= ~SYM_TRACED;
- address = page + address;
- /*
- * The code here must do just about the equivalent to that in restart.c
- */
- switch (nargs & 0xff)
- {
- case 0: ifnn(fn) = address;
- if (nargs<=0xff)
- ifn1(fn) = (int32)wrong_no_0a, ifn2(fn) = (int32)wrong_no_0b;
- break;
- case 1: ifn1(fn) = address;
- if (nargs<=0xff)
- ifn2(fn) = (int32)too_many_1, ifnn(fn) = (int32)wrong_no_1;
- break;
- case 2: ifn2(fn) = address;
- if (nargs<=0xff)
- ifn1(fn) = (int32)too_few_2, ifnn(fn) = (int32)wrong_no_2;
- break;
- case 3: ifnn(fn) = address;
- if (nargs<=0xff)
- ifn1(fn) = (int32)wrong_no_3a, ifn2(fn) = (int32)wrong_no_3b;
- break;
- default: ifnn(fn) = address;
- if (nargs<=0xff)
- ifn1(fn) = (int32)wrong_no_na, ifn2(fn) = (int32)wrong_no_nb;
- break;
- }
- qenv(fn) = env;
- return onevalue(fn);
- }
- static CSLbool restore_fn_cell(Lisp_Object a, char *name,
- int32 len, setup_type const s[])
- {
- int i;
- for (i=0; s[i].name != NULL; i++)
- { if (strlen(s[i].name) == (size_t)len &&
- memcmp(name, s[i].name, len) == 0) break;
- }
- if (s[i].name == NULL) return NO;
- set_fns(a, s[i].one, s[i].two, s[i].n);
- return YES;
- }
- static Lisp_Object Lrestore_c_code(Lisp_Object nil, Lisp_Object a)
- {
- char *name;
- int32 len;
- Lisp_Object pn;
- if (!symbolp(a)) return aerror1("restore-c-code", a);
- push(a);
- pn = get_pname(a);
- pop(a);
- errexit();
- name = (char *)&celt(pn, 0);
- len = length_of_header(vechdr(pn)) - 4;
- if (restore_fn_cell(a, name, len, u01_setup) ||
- restore_fn_cell(a, name, len, u02_setup) ||
- restore_fn_cell(a, name, len, u03_setup) ||
- restore_fn_cell(a, name, len, u04_setup) ||
- restore_fn_cell(a, name, len, u05_setup) ||
- restore_fn_cell(a, name, len, u06_setup) ||
- restore_fn_cell(a, name, len, u07_setup) ||
- restore_fn_cell(a, name, len, u08_setup) ||
- restore_fn_cell(a, name, len, u09_setup) ||
- restore_fn_cell(a, name, len, u10_setup) ||
- restore_fn_cell(a, name, len, u11_setup) ||
- restore_fn_cell(a, name, len, u12_setup))
- { Lisp_Object env;
- push(a);
- #ifdef COMMON
- env = get(a, funarg, nil);
- #else
- env = get(a, funarg);
- #endif
- pop(a);
- errexit();
- qenv(a) = env;
- return onevalue(a);
- }
- else return onevalue(nil);
- }
- Lisp_Object Lsymbol_set_definition(Lisp_Object nil,
- Lisp_Object a, Lisp_Object b)
- /*
- * The odd case here is where the second argument represents a freshly
- * created bit of compiled code. In which case the structure is
- * (nargs . codevec . envvec)
- * where nargs is an integer indicating the number of arguments, codevec
- * is a vector of bytecodes, and envvec is something to go in the
- * environment cell of the symbol.
- * Here the low 8 bits of nargs indicate the number of required arguments.
- * The next 8 bits give the number of optional arguments, and the next
- * two bits are flags. Of these, the first is set if any of the optional
- * arguments has an initform or supplied-p associate, and the other
- * indicates that a "&rest" argument is required.
- * Bits beyond that (if non-zero) indicate that the function definition
- * is of the form (defun f1 (a b c) (f2 a b)) and the number coded is the
- * length of the function body.
- * Standard Lisp does not need &optional or &rest arguments, but it turned
- * out to be pretty easy to make the bytecode compiler support them.
- */
- {
- if (!is_symbol(a) ||
- /*
- * Something flagged with the CODEPTR bit is a gensym manufactured to
- * stand for a compiled-code object. It should NOT be reset!
- */
- (qheader(a) & (SYM_SPECIAL_FORM | SYM_CODEPTR)) != 0)
- { if (qheader(a) & SYM_C_DEF) return onevalue(nil);
- return aerror1("symbol-set-definition", a);
- }
- qheader(a) &= ~SYM_TRACED;
- set_fns(a, undefined1, undefined2, undefinedn); /* Tidy up first */
- qenv(a) = a;
- if ((qheader(a) & SYM_C_DEF) != 0) lose_C_def(a);
- if (b == nil) return onevalue(b); /* set defn to nil to undefine */
- else if (symbolp(b))
- {
- /*
- * One could imagine a view that the second arg to symbol-set-definition
- * had to be a codepointer object. I will be kind (?) and permit the NAME
- * of a function too. However for the second arg to be a macro or a
- * special form would still be a calamity.
- * if ((qheader(b) & SYM_CODEPTR) == 0)
- * return aerror1("symbol-set-definition", b);
- */
- if ((qheader(b) & (SYM_SPECIAL_FORM | SYM_MACRO)) != 0)
- return aerror1("symbol-set-definition", b);
- qheader(a) = qheader(a) & ~SYM_MACRO;
- { set_fns(a, qfn1(b), qfn2(b), qfnn(b));
- qenv(a) = qenv(b);
- /*
- * In order that checkpoint files can be made there is some very
- * ugly fooling around here for functions that are defined in the C coded
- * kernel. Sorry.
- */
- if ((qheader(b) & SYM_C_DEF) != 0)
- {
- #ifdef COMMON
- Lisp_Object c = get(b, unset_var, nil);
- #else
- Lisp_Object c = get(b, unset_var);
- #endif
- if (c == nil) c = b;
- push2(c, a);
- putprop(a, unset_var, c);
- errexitn(2);
- pop(a);
- #ifdef COMMON
- a = cons(a, get(stack[0], work_symbol, nil));
- #else
- a = cons(a, get(stack[0], work_symbol));
- #endif
- errexitn(1);
- putprop(stack[0], work_symbol, a);
- pop(b);
- errexit();
- }
- }
- }
- else if (!consp(b)) return aerror1("symbol-set-definition", b);
- else if (is_fixnum(qcar(b)))
- { int32 nargs = (int)int_of_fixnum(qcar(b)), nopts, flagbits, ntail;
- nopts = nargs >> 8;
- flagbits = nopts >> 8;
- ntail = flagbits >> 2;
- nargs &= 0xff;
- nopts &= 0xff;
- flagbits &= 3;
- if (ntail != 0)
- { switch (100*nargs + ntail-1)
- {
- case 300: set_fns(a, wrong_no_na, wrong_no_nb, f3_as_0); break;
- case 301: set_fns(a, wrong_no_na, wrong_no_nb, f3_as_1); break;
- case 302: set_fns(a, wrong_no_na, wrong_no_nb, f3_as_2); break;
- case 303: set_fns(a, wrong_no_na, wrong_no_nb, f3_as_3); break;
- case 200: set_fns(a, too_few_2, f2_as_0, wrong_no_2); break;
- case 201: set_fns(a, too_few_2, f2_as_1, wrong_no_2); break;
- case 202: set_fns(a, too_few_2, f2_as_2, wrong_no_2); break;
- case 100: set_fns(a, f1_as_0, too_many_1, wrong_no_1); break;
- case 101: set_fns(a, f1_as_1, too_many_1, wrong_no_1); break;
- case 000: set_fns(a, wrong_no_na, wrong_no_nb, f0_as_0); break;
- }
- b = qcdr(b);
- }
- else if (flagbits != 0 || nopts != 0)
- { if ((qheader(a) & SYM_TRACED) == 0) switch(flagbits)
- {
- default:
- case 0: /* easy case optional arguments */
- set_fns(a, byteopt1, byteopt2, byteoptn); break;
- case 1: /* optional args, but non-nil default, or supplied-p extra */
- set_fns(a, hardopt1, hardopt2, hardoptn); break;
- case 2: /* easy opt args, but also a &rest arg */
- set_fns(a, byteoptrest1, byteoptrest2, byteoptrestn); break;
- case 3: /* complicated &options and &rest */
- set_fns(a, hardoptrest1, hardoptrest2, hardoptrestn); break;
- }
- else switch (flagbits)
- {
- default:
- case 0: /* easy case optional arguments */
- set_fns(a, tracebyteopt1, tracebyteopt2, tracebyteoptn); break;
- case 1: /* optional args, but non-nil default, or supplied-p extra */
- set_fns(a, tracehardopt1, tracehardopt2, tracehardoptn); break;
- case 2: /* easy opt args, but also a &rest arg */
- set_fns(a, tracebyteoptrest1, tracebyteoptrest2, tracebyteoptrestn); break;
- case 3: /* complicated &options and &rest */
- set_fns(a, tracehardoptrest1, tracehardoptrest2, tracehardoptrestn); break;
- }
- }
- else
- { if (nargs > 4) nargs = 4;
- if ((qheader(a) & SYM_TRACED) != 0) nargs += 5;
- qheader(a) = qheader(a) & ~SYM_MACRO;
- switch (nargs)
- {
- case 0: set_fns(a, wrong_no_0a, wrong_no_0b, bytecoded0);
- break;
- case 1: set_fns(a, bytecoded1, too_many_1, wrong_no_1);
- break;
- case 2: set_fns(a, too_few_2, bytecoded2, wrong_no_2);
- break;
- case 3: set_fns(a, wrong_no_3a, wrong_no_3b, bytecoded3);
- break;
- default:
- case 4: set_fns(a, wrong_no_na, wrong_no_nb, bytecodedn);
- break;
- case 5+0: set_fns(a, wrong_no_0a, wrong_no_0b, tracebytecoded0);
- break;
- case 5+1: set_fns(a, tracebytecoded1, too_many_1, wrong_no_1);
- break;
- case 5+2: set_fns(a, too_few_2, tracebytecoded2, wrong_no_2);
- break;
- case 5+3: set_fns(a, wrong_no_3a, wrong_no_3b, tracebytecoded3);
- break;
- case 5+4: set_fns(a, wrong_no_na, wrong_no_nb, tracebytecodedn);
- break;
- }
- }
- qenv(a) = qcdr(b);
- }
- else if (qcar(b) == lambda)
- { Lisp_Object bvl = qcar(qcdr(b));
- int nargs = 0;
- while (consp(bvl)) nargs++, bvl = qcdr(bvl);
- qheader(a) = qheader(a) & ~SYM_MACRO;
- if ((qheader(a) & SYM_TRACED) != 0)
- set_fns(a, traceinterpreted1, traceinterpreted2, traceinterpretedn);
- else set_fns(a, interpreted1, interpreted2, interpretedn);
- qenv(a) = qcdr(b);
- if (qvalue(comp_symbol) != nil &&
- qfn1(compiler_symbol) != undefined1)
- { push(a);
- a = ncons(a);
- errexitn(1);
- (qfn1(compiler_symbol))(qenv(compiler_symbol), a);
- pop(a);
- errexit();
- }
- }
- else if (qcar(b) == funarg)
- { Lisp_Object bvl = qcar(qcdr(b));
- int nargs = 0;
- while (consp(bvl)) nargs++, bvl = qcdr(bvl);
- qheader(a) = qheader(a) & ~SYM_MACRO;
- if ((qheader(a) & SYM_TRACED) != 0)
- set_fns(a, tracefunarged1, tracefunarged2, tracefunargedn);
- else set_fns(a, funarged1, funarged2, funargedn);
- qenv(a) = qcdr(b);
- }
- else return aerror1("symbol-set-definition", b);
- return onevalue(b);
- }
- Lisp_Object Lgetd(Lisp_Object nil, Lisp_Object a)
- {
- Header h;
- Lisp_Object type;
- CSL_IGNORE(nil);
- if (a == nil) return onevalue(nil);
- else if (!is_symbol(a)) return onevalue(nil);
- h = qheader(a);
- if ((h & SYM_SPECIAL_FORM) != 0) type = fexpr_symbol;
- else if ((h & SYM_MACRO) != 0)
- { a = cons(lambda, qenv(a));
- errexit();
- type = macro_symbol;
- }
- else
- { a = Lsymbol_function(nil, a);
- errexit();
- if (a == nil) return onevalue(nil);
- type = expr_symbol;
- }
- a = cons(type, a);
- errexit();
- return onevalue(a);
- }
- Lisp_Object Lremd(Lisp_Object nil, Lisp_Object a)
- {
- Lisp_Object res;
- CSL_IGNORE(nil);
- if (!is_symbol(a) ||
- (qheader(a) & SYM_SPECIAL_FORM) != 0)
- return aerror1("remd", a);
- if ((qheader(a) & (SYM_C_DEF | SYM_CODEPTR)) ==
- (SYM_C_DEF | SYM_CODEPTR)) return onevalue(nil);
- res = Lgetd(nil, a);
- errexit();
- if (res == nil) return onevalue(nil); /* no definition to remove */
- /*
- * I treat an explicit use of remd as a redefinition, and ensure that
- * restarting a preserved image will not put the definition back.
- */
- qheader(a) = qheader(a) & ~SYM_MACRO;
- if ((qheader(a) & SYM_C_DEF) != 0) lose_C_def(a);
- set_fns(a, undefined1, undefined2, undefinedn);
- qenv(a) = a;
- return onevalue(res);
- }
- /*
- * For set-autoload the first argument must be a symbol that will name
- * a function, the second arg is either an atom or a list of atoms, each
- * of which specified a module to be loaded if the names function is
- * called. Loading the modules is expected to instate a definition for the
- * function involved. This function is arranged so it does NOT do anything
- * if the function being set for autoloading is already defined. This is
- * on the supposition that the existing definition is in fact the desired
- * one, say because the relevant module happens to have been loaded already.
- * An explicit use of remd first can be used to ensure that no previous
- * definition is present and thus that a real autoload stub will be instated,
- * if that is what you really want.
- */
- Lisp_Object Lset_autoload(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- Lisp_Object res;
- CSL_IGNORE(nil);
- if (!is_symbol(a) ||
- (qheader(a) & SYM_SPECIAL_FORM) != 0)
- return aerror1("set-autoload", a);
- if (!(qfn1(a) == undefined1 && qfn2(a) == undefined2 &&
- qfnn(a) == undefinedn)) return onevalue(nil);
- if ((qheader(a) & (SYM_C_DEF | SYM_CODEPTR)) ==
- (SYM_C_DEF | SYM_CODEPTR)) return onevalue(nil);
- push2(a, b);
- if (consp(b)) res = cons(a, b);
- else res = list2(a, b);
- pop2(b, a);
- errexit();
- /*
- * I treat an explicit use of set-autoload as a redefinition, and ensure that
- * restarting a preserved image will not put the definition back. Note that
- * I will not allow autoloadable macros...
- */
- qheader(a) = qheader(a) & ~SYM_MACRO;
- if ((qheader(a) & SYM_C_DEF) != 0) lose_C_def(a);
- set_fns(a, autoload1, autoload2, autoloadn);
- qenv(a) = res;
- return onevalue(res);
- }
- #define pack_funtable(a, n) ((((int32)(a)) << 16) | (n))
- #define funtable_nargs(u) ((u) >> 16)
- #define funtable_index(u) ((u) & 0xffffU)
- static one_args *displaced1 = NULL;
- static two_args *displaced2;
- static n_args *displacedn;
- static unsigned32 table_entry;
- static Lisp_Object traced1_function(Lisp_Object env, Lisp_Object a)
- {
- Lisp_Object name, nil = C_nil;
- Lisp_Object r = nil;
- /*
- * Worry about errors & garbage collection in following calls to print fns
- * This MUST be fixed sometime fairly soon... but then it could only bite
- * people using the trace facility, and their code is already dead!
- */
- freshline_trace();
- loop_print_trace(tracedfn);
- push(tracedfn);
- trace_printf(" called (1 arg)\narg1: ");
- loop_print_trace(a);
- trace_printf("\n");
- r = (*displaced1)(env, a);
- pop(name);
- errexit();
- push(r);
- freshline_trace();
- loop_print_trace(name);
- trace_printf(" = ");
- loop_print_trace(r);
- trace_printf("\n");
- pop(r);
- return onevalue(r);
- }
- static Lisp_Object traced2_function(Lisp_Object env,
- Lisp_Object a, Lisp_Object b)
- {
- Lisp_Object name, nil = C_nil;
- Lisp_Object r = nil;
- freshline_trace();
- loop_print_trace(tracedfn);
- push(tracedfn);
- trace_printf(" called (2 args)\narg1:");
- loop_print_trace(a);
- trace_printf("\narg2: ");
- loop_print_trace(b);
- trace_printf("\n");
- r = (*displaced2)(env, a, b);
- pop(name);
- errexit();
- push(r);
- freshline_trace();
- loop_print_trace(name);
- trace_printf(" = ");
- loop_print_trace(r);
- trace_printf("\n");
- pop(r);
- return onevalue(r);
- }
- static Lisp_Object MS_CDECL tracedn_function(Lisp_Object env, int nargs, ...)
- {
- Lisp_Object name, nil = C_nil;
- Lisp_Object r = nil;
- int i;
- va_list a;
- push(tracedfn);
- va_start(a, nargs);
- push_args(a, nargs);
- freshline_trace();
- loop_print_trace(tracedfn);
- trace_printf(" called (%d args)\n", nargs);
- for (i=1; i<=nargs; i++)
- { trace_printf("arg%d: ", i);
- loop_print_trace(stack[i-nargs]);
- trace_printf("\n");
- }
- if (nargs <= 15) switch (nargs)
- {
- default:
- /*
- * Calls with 1 or 2 args can never arise, since those cases have been
- * split off for separate treatment.
- */
- popv(nargs+1);
- return aerror("system error in trace mechanism");
- case 0:
- r = (*displacedn)(env, 0);
- break;
- case 3:
- r = (*displacedn)(env, 3, stack[-2], stack[-1], stack[0]);
- break;
- case 4:
- r = (*displacedn)(env, 4, stack[-3], stack[-2], stack[-1],
- stack[0]);
- break;
- case 5:
- r = (*displacedn)(env, 5, stack[-4], stack[-3], stack[-2],
- stack[-1], stack[0]);
- break;
- case 6:
- r = (*displacedn)(env, 6, stack[-5], stack[-4], stack[-3],
- stack[-2], stack[-1], stack[0]);
- break;
- case 7:
- r = (*displacedn)(env, 7, stack[-6], stack[-5], stack[-4],
- stack[-3], stack[-2], stack[-1], stack[0]);
- break;
- case 8:
- r = (*displacedn)(env, 8, stack[-7], stack[-6], stack[-5],
- stack[-4], stack[-3], stack[-2], stack[-1],
- stack[0]);
- break;
- case 9:
- r = (*displacedn)(env, 9, stack[-8], stack[-7], stack[-6],
- stack[-5], stack[-4], stack[-3], stack[-2],
- stack[-1], stack[0]);
- break;
- case 10:
- r = (*displacedn)(env, 10, stack[-9], stack[-8], stack[-7],
- stack[-6], stack[-5], stack[-4], stack[-3],
- stack[-2], stack[-1], stack[0]);
- break;
- case 11:
- r = (*displacedn)(env, 11, stack[-10], stack[-9],
- stack[-8], stack[-7], stack[-6], stack[-5],
- stack[-4], stack[-3], stack[-2], stack[-1],
- stack[0]);
- break;
- case 12:
- r = (*displacedn)(env, 12, stack[-11], stack[-10],
- stack[-9], stack[-8], stack[-7], stack[-6],
- stack[-5], stack[-4], stack[-3], stack[-2],
- stack[-1], stack[0]);
- break;
- case 13:
- r = (*displacedn)(env, 13, stack[-12], stack[-11],
- stack[-10], stack[-9], stack[-8], stack[-7],
- stack[-6], stack[-5], stack[-4], stack[-3],
- stack[-2], stack[-1], stack[0]);
- break;
- case 14:
- r = (*displacedn)(env, 14, stack[-13], stack[-12],
- stack[-11], stack[-10], stack[-9], stack[-8],
- stack[-7], stack[-6], stack[-5], stack[-4],
- stack[-3], stack[-2], stack[-1], stack[0]);
- break;
- case 15:
- r = (*displacedn)(env, 15, stack[-14], stack[-13],
- stack[-12], stack[-11], stack[-10], stack[-9],
- stack[-8], stack[-7], stack[-6], stack[-5],
- stack[-4], stack[-3], stack[-2], stack[-1],
- stack[0]);
- break;
- }
- else
- { trace_printf("Too many arguments to trace a function\n");
- /*
- * Because the above is a horrid mess I will only support traced
- * calls with at most 15 args (more than I expect most people to
- * try). And this only applies to thigs that are NOT bytecoded -
- * I can trace bytecoded things with more args I believe, so users are not
- * utterly lost I hope.
- */
- return aerror("traced function with > 15 args: not supported");
- }
- popv(nargs);
- pop(name);
- errexit();
- push(r);
- freshline_trace();
- loop_print_trace(name);
- trace_printf(" = ");
- loop_print_trace(r);
- trace_printf("\n");
- pop(r);
- return onevalue(r);
- }
- #define NOT_FOUND 100
- static unsigned32 find_built_in_function(one_args *f1,
- two_args *f2,
- n_args *fn)
- /*
- * This take the entrypoint of a function and tries to identify it
- * by scanning the tables used by the bytecode interpreter. If the
- * function is found a record is returned indicating how many args
- * it takes, and what its index is in the relevant table. The code
- * <NOT_FOUND,NOT_FOUND> is returned to indicate failure if the function
- * is not found.
- */
- {
- int32 index;
- for (index=0; zero_arg_functions[index]!=NULL; index++)
- if (fn == zero_arg_functions[index]) return pack_funtable(0, index);
- for (index=0; one_arg_functions[index]!=NULL; index++)
- if (f1 == one_arg_functions[index]) return pack_funtable(1, index);
- for (index=0; two_arg_functions[index]!=NULL; index++)
- if (f2 == two_arg_functions[index]) return pack_funtable(2, index);
- for (index=0; three_arg_functions[index]!=NULL; index++)
- if (fn == three_arg_functions[index]) return pack_funtable(3, index);
- return pack_funtable(NOT_FOUND, NOT_FOUND);
- }
- Lisp_Object Ltrace_all(Lisp_Object nil, Lisp_Object a)
- {
- #ifdef DEBUG
- if (a == nil) trace_all = 0;
- else trace_all = 1;
- return onevalue(nil);
- #else
- CSL_IGNORE(nil);
- CSL_IGNORE(a);
- return aerror("trace-all only supported in DEBUG version");
- #endif
- }
- Lisp_Object Ltrace(Lisp_Object nil, Lisp_Object a)
- {
- Lisp_Object w = a;
- if (symbolp(a))
- { a = ncons(a);
- errexit();
- w = a;
- }
- while (consp(w))
- { Lisp_Object s = qcar(w);
- w = qcdr(w);
- if (symbolp(s))
- { one_args *f1 = qfn1(s);
- two_args *f2 = qfn2(s);
- n_args *fn = qfnn(s);
- int fixenv = 0, done = 0;
- if (f1 == undefined1)
- { freshline_debug();
- debug_printf("+++ ");
- loop_print_debug(s);
- debug_printf(" not yet defined\n");
- continue;
- }
- qheader(s) |= SYM_TRACED;
- if (f1 == interpreted1)
- { set_fns(s, traceinterpreted1, traceinterpreted2, traceinterpretedn);
- fixenv = done = 1;
- }
- if (f1 == funarged1)
- { set_fns(s, tracefunarged1, tracefunarged2, tracefunargedn);
- fixenv = done = 1;
- }
- if (fn == bytecoded0) ifnn(s) = (intxx)tracebytecoded0, done = 1;
- if (f1 == bytecoded1) ifn1(s) = (intxx)tracebytecoded1, done = 1;
- if (f2 == bytecoded2) ifn2(s) = (intxx)tracebytecoded2, done = 1;
- if (fn == bytecoded3) ifnn(s) = (intxx)tracebytecoded3, done = 1;
- if (fn == bytecodedn) ifnn(s) = (intxx)tracebytecodedn, done = 1;
- if (f1 == byteopt1) ifn1(s) = (intxx)tracebyteopt1, done = 1;
- if (f2 == byteopt2) ifn2(s) = (intxx)tracebyteopt2, done = 1;
- if (fn == byteoptn) ifnn(s) = (intxx)tracebyteoptn, done = 1;
- if (f1 == hardopt1) ifn1(s) = (intxx)tracehardopt1, done = 1;
- if (f2 == hardopt2) ifn2(s) = (intxx)tracehardopt2, done = 1;
- if (fn == hardoptn) ifnn(s) = (intxx)tracehardoptn, done = 1;
- if (f1 == byteoptrest1) ifn1(s) = (intxx)tracebyteoptrest1, done = 1;
- if (f2 == byteoptrest2) ifn2(s) = (intxx)tracebyteoptrest2, done = 1;
- if (fn == byteoptrestn) ifnn(s) = (intxx)tracebyteoptrestn, done = 1;
- if (f1 == hardoptrest1) ifn1(s) = (intxx)tracehardoptrest1, done = 1;
- if (f2 == hardoptrest2) ifn2(s) = (intxx)tracehardoptrest2, done = 1;
- if (fn == hardoptrestn) ifnn(s) = (intxx)tracehardoptrestn, done = 1;
- if (fixenv)
- { push2(a, s);
- a = cons(s, qenv(s));
- errexitn(2);
- pop(s);
- qenv(s) = a;
- pop(a);
- }
- if (done) continue;
- /*
- * I permit the tracing of just one function from the kernel, and achieve
- * this by installing a wrapper function in place of the real definition.
- * Indeed this is just like Lisp-level embedding, except that I can get at the
- * entrypoint table used by the bytecode interpreter and so trap calls made
- * via there, and I can use that table to tell me how many arguments the
- * traced function needed.
- */
- if (displaced1 == NULL)
- { int nargs = funtable_nargs(table_entry);
- /*
- * Remember what function was being traced, so that it can eventually be
- * invoked, and its name printed.
- */
- displaced1 = f1;
- displaced2 = f2;
- displacedn = fn;
- tracedfn = s;
- /*
- * This makes calls via the regular interpreter see the traced version...
- */
- set_fns(s, traced1_function, traced2_function,
- tracedn_function);
- table_entry = find_built_in_function(f1, f2, fn);
- nargs = funtable_nargs(table_entry);
- table_entry = funtable_index(table_entry);
- if (nargs != NOT_FOUND)
- {
- /*
- * .. and now I make calls via short-form bytecodes do likewise.
- */
- switch (nargs)
- {
- default:
- case 0: zero_arg_functions[funtable_index(table_entry)] =
- tracedn_function;
- break;
- case 1: one_arg_functions[funtable_index(table_entry)] =
- traced1_function;
- break;
- case 2: two_arg_functions[funtable_index(table_entry)] =
- traced2_function;
- break;
- case 3: three_arg_functions[funtable_index(table_entry)] =
- tracedn_function;
- break;
- }
- }
- }
- continue;
- }
- }
- return onevalue(a);
- }
- Lisp_Object Luntrace(Lisp_Object nil, Lisp_Object a)
- {
- Lisp_Object w = a;
- CSL_IGNORE(nil);
- if (symbolp(a))
- { a = ncons(a);
- errexit();
- w = a;
- }
- while (consp(w))
- { Lisp_Object s = qcar(w);
- w = qcdr(w);
- if (symbolp(s))
- { one_args *f1 = qfn1(s);
- two_args *f2 = qfn2(s);
- n_args *fn = qfnn(s);
- if (f1 == traceinterpreted1)
- { set_fns(a, interpreted1, interpreted2, interpretedn);
- qenv(s) = qcdr(qenv(s));
- }
- else if (f1 == tracefunarged1)
- { set_fns(s, funarged1, funarged2, funargedn);
- qenv(s) = qcdr(qenv(s));
- }
- if (f1 == tracebytecoded1) ifn1(s) = (intxx)bytecoded1;
- if (f2 == tracebytecoded2) ifn2(s) = (intxx)bytecoded2;
- if (fn == tracebytecoded0) ifnn(s) = (intxx)bytecoded0;
- if (fn == tracebytecoded3) ifnn(s) = (intxx)bytecoded3;
- if (fn == tracebytecodedn) ifnn(s) = (intxx)bytecodedn;
- if (f1 == tracebyteopt1) ifn1(s) = (intxx)byteopt1;
- if (f2 == tracebyteopt2) ifn2(s) = (intxx)byteopt2;
- if (fn == tracebyteoptn) ifnn(s) = (intxx)byteoptn;
- if (f1 == tracebyteoptrest1) ifn1(s) = (intxx)byteoptrest1;
- if (f2 == tracebyteoptrest2) ifn2(s) = (intxx)byteoptrest2;
- if (fn == tracebyteoptrestn) ifnn(s) = (intxx)byteoptrestn;
- if (f1 == tracehardopt1) ifn1(s) = (intxx)hardopt1;
- if (f2 == tracehardopt2) ifn2(s) = (intxx)hardopt2;
- if (fn == tracehardoptn) ifnn(s) = (intxx)hardoptn;
- if (f1 == tracehardoptrest1) ifn1(s) = (intxx)hardoptrest1;
- if (f2 == tracehardoptrest2) ifn2(s) = (intxx)hardoptrest2;
- if (fn == tracehardoptrestn) ifnn(s) = (intxx)hardoptrestn;
- if (f1 == traced1_function)
- { int nargs = funtable_nargs(table_entry);
- set_fns(s, displaced1, displaced2, displacedn);
- if (nargs != NOT_FOUND)
- switch (nargs)
- {
- default:
- case 0: zero_arg_functions[funtable_index(table_entry)] =
- displacedn;
- break;
- case 1: one_arg_functions[funtable_index(table_entry)] =
- displaced1;
- break;
- case 2: two_arg_functions[funtable_index(table_entry)] =
- displaced2;
- break;
- case 3: three_arg_functions[funtable_index(table_entry)] =
- displacedn;
- break;
- }
- displaced1 = NULL;
- displaced2 = NULL;
- displacedn = NULL;
- }
- qheader(s) &= ~SYM_TRACED;
- }
- }
- return onevalue(a);
- }
- Lisp_Object Ldouble(Lisp_Object nil, Lisp_Object a)
- {
- Lisp_Object w = a;
- if (symbolp(a))
- { a = ncons(a);
- errexit();
- w = a;
- }
- while (consp(w))
- { Lisp_Object s = qcar(w);
- w = qcdr(w);
- if (symbolp(s))
- { one_args *f1 = qfn1(s);
- two_args *f2 = qfn2(s);
- n_args *fn = qfnn(s);
- int fixenv = 0, done = 0;
- if (f1 == undefined1) continue;
- if (f1 == interpreted1)
- { set_fns(s, double_interpreted1, double_interpreted2, double_interpretedn);
- fixenv = done = 1;
- }
- if (f1 == funarged1)
- { set_fns(s, double_funarged1, double_funarged2, double_funargedn);
- fixenv = done = 1;
- }
- if (fn == bytecoded0) ifnn(s) = (intxx)double_bytecoded0, done = 1;
- if (f1 == bytecoded1) ifn1(s) = (intxx)double_bytecoded1, done = 1;
- if (f2 == bytecoded2) ifn2(s) = (intxx)double_bytecoded2, done = 1;
- if (fn == bytecoded3) ifnn(s) = (intxx)double_bytecoded3, done = 1;
- if (fn == bytecodedn) ifnn(s) = (intxx)double_bytecodedn, done = 1;
- if (f1 == byteopt1) ifn1(s) = (intxx)double_byteopt1, done = 1;
- if (f2 == byteopt2) ifn2(s) = (intxx)double_byteopt2, done = 1;
- if (fn == byteoptn) ifnn(s) = (intxx)double_byteoptn, done = 1;
- if (f1 == hardopt1) ifn1(s) = (intxx)double_hardopt1, done = 1;
- if (f2 == hardopt2) ifn2(s) = (intxx)double_hardopt2, done = 1;
- if (fn == hardoptn) ifnn(s) = (intxx)double_hardoptn, done = 1;
- if (f1 == byteoptrest1) ifn1(s) = (intxx)double_byteoptrest1, done = 1;
- if (f2 == byteoptrest2) ifn2(s) = (intxx)double_byteoptrest2, done = 1;
- if (fn == byteoptrestn) ifnn(s) = (intxx)double_byteoptrestn, done = 1;
- if (f1 == hardoptrest1) ifn1(s) = (intxx)double_hardoptrest1, done = 1;
- if (f2 == hardoptrest2) ifn2(s) = (intxx)double_hardoptrest2, done = 1;
- if (fn == hardoptrestn) ifnn(s) = (intxx)double_hardoptrestn, done = 1;
- if (fixenv)
- { push2(a, s);
- a = cons(s, qenv(s));
- errexitn(2);
- pop(s);
- qenv(s) = a;
- pop(a);
- }
- if (done) continue;
- debug_printf("Unable to execution-double: "); loop_print_debug(s);
- trace_printf("\n");
- continue;
- }
- }
- return onevalue(a);
- }
- Lisp_Object Lundouble(Lisp_Object nil, Lisp_Object a)
- {
- Lisp_Object w = a;
- CSL_IGNORE(nil);
- if (symbolp(a))
- { a = ncons(a);
- errexit();
- w = a;
- }
- while (consp(w))
- { Lisp_Object s = qcar(w);
- w = qcdr(w);
- if (symbolp(s))
- { one_args *f1 = qfn1(s);
- two_args *f2 = qfn2(s);
- n_args *fn = qfnn(s);
- if (f1 == double_interpreted1)
- { set_fns(a, interpreted1, interpreted2, interpretedn);
- qenv(s) = qcdr(qenv(s));
- }
- else if (f1 == double_funarged1)
- { set_fns(s, funarged1, funarged2, funargedn);
- qenv(s) = qcdr(qenv(s));
- }
- else if (f1 == double_bytecoded1) ifn1(s) = (intxx)bytecoded1;
- else if (f2 == double_bytecoded2) ifn2(s) = (intxx)bytecoded2;
- else if (fn == double_bytecoded0) ifnn(s) = (intxx)bytecoded0;
- else if (fn == double_bytecoded3) ifnn(s) = (intxx)bytecoded3;
- else if (fn == double_bytecodedn) ifnn(s) = (intxx)bytecodedn;
- else if (f1 == double_byteopt1) ifn1(s) = (intxx)byteopt1;
- else if (f2 == double_byteopt2) ifn2(s) = (intxx)byteopt2;
- else if (fn == double_byteoptn) ifnn(s) = (intxx)byteoptn;
- else if (f1 == double_byteoptrest1) ifn1(s) = (intxx)byteoptrest1;
- else if (f2 == double_byteoptrest2) ifn2(s) = (intxx)byteoptrest2;
- else if (fn == double_byteoptrestn) ifnn(s) = (intxx)byteoptrestn;
- else if (f1 == double_hardopt1) ifn1(s) = (intxx)hardopt1;
- else if (f2 == double_hardopt2) ifn2(s) = (intxx)hardopt2;
- else if (fn == double_hardoptn) ifnn(s) = (intxx)hardoptn;
- else if (f1 == double_hardoptrest1) ifn1(s) = (intxx)hardoptrest1;
- else if (f2 == double_hardoptrest2) ifn2(s) = (intxx)hardoptrest2;
- else if (fn == double_hardoptrestn) ifnn(s) = (intxx)hardoptrestn;
- }
- }
- return onevalue(a);
- }
- Lisp_Object Lmacro_function(Lisp_Object nil, Lisp_Object a)
- {
- if (!symbolp(a)) return onevalue(nil);
- else if ((qheader(a) & SYM_MACRO) == 0) return onevalue(nil);
- /* If the MACRO bit is set in the header I know there is a definition */
- else return onevalue(cons(lambda, qenv(a)));
- }
- Lisp_Object get_pname(Lisp_Object a)
- {
- Lisp_Object name = qpname(a);
- #ifndef COMMON
- /*
- * When a gensym is first created its pname field points at a string that
- * will form the base of its name, and a magic bit is set in its header.
- * If at some stage it is necessary to inspect the print name (mainly in
- * order to print the symbol) it becomes necessary to create a new string
- * and insert a serial number. Doing things this way means that the serial
- * numbers that users see will tend to be smaller, and space for per-gensym
- * strings does not get allocated unless really needed. The down side is
- * that every time I want to grab the pname of anything I have to check for
- * this case and admit the possibility of garbage collection or even
- * failure.
- */
- if (qheader(a) & SYM_UNPRINTED_GENSYM)
- { unsignedxx len;
- Lisp_Object nil = C_nil;
- char genname[64];
- len = length_of_header(vechdr(name)) - CELL;
- if (len > 60) len = 60; /* Unpublished truncation of the string */
- sprintf(genname, "%.*s%lu", (int)len,
- (char *)name + (CELL - TAG_VECTOR), (long)gensym_ser++);
- push(a);
- name = make_string(genname);
- pop(a);
- errexit();
- qpname(a) = name;
- qheader(a) &= ~SYM_UNPRINTED_GENSYM;
- }
- #endif
- return name;
- }
- Lisp_Object Lsymbol_name(Lisp_Object nil, Lisp_Object a)
- {
- if (!symbolp(a)) return aerror1("symbol-name", a);
- a = get_pname(a);
- errexit();
- return onevalue(a);
- }
- #ifdef COMMON
- Lisp_Object Lsymbol_package(Lisp_Object nil, Lisp_Object a)
- {
- if (!symbolp(a)) return aerror1("symbol-package", a);
- a = qpackage(a);
- return onevalue(a);
- }
- #endif
- static Lisp_Object Lrestart_csl2(Lisp_Object nil,
- Lisp_Object a, Lisp_Object b)
- /*
- * If the argument is given as nil then this is a cold-start, and when
- * I begin again it would be a VERY good idea to do a (load!-module 'compat)
- * rather promptly (otherwise some Lisp functions will not work at all).
- * I do not automate that because this function is intended for use in
- * delicate system rebuilding contexts and I want the user to have ultimate
- * control. (restart!-csl t) reloads a heap-image in the normal way.
- * (restart!-csl 'xx) where xx is neither nil nor t starts by reloading a
- * heap image, but then it looks for a function with the same name as xx
- * (since a heap image is reloaded it is NOT easy (possible?) to keep the
- * symbol) and calls it as a function. Finally the case
- * (restart!-csl '(module fn)) restart the system, then calls load-module
- * on the named module and finally calls the given restart function.
- * This last option can be useful since otherwise the function to be called
- * in (restart!-csl 'xx) would need to be in the base image as re-loaded.
- */
- {
- int n;
- char *v;
- #ifdef SOCKETS
- /*
- * Security measure - deny restart-csl to remote users
- */
- if (socket_server != 0) return aerror("restart-csl");
- #endif
- n = 0;
- v = NULL;
- /*
- * A comment seems in order here. The case b==SPID_NOARG should only
- * arise if I came from Lrestart_csl: it indicates that there was
- * no second argument provided.
- */
- if (b != SPID_NOARG)
- { Lisp_Object b1;
- push(a);
- b1 = b = Lexploden(nil, b);
- pop(a);
- errexit();
- while (b1 != nil)
- { n++; /* number of chars of arg */
- b1 = qcdr(b1);
- }
- v = (char *)malloc(n+1);
- if (v == NULL) return aerror("space exhausted in restart-csl");
- n = 0;
- while (b != nil)
- { v[n++] = (char)int_of_fixnum(qcar(b));
- b = qcdr(b);
- }
- v[n] = 0;
- }
- term_printf("\nThe system is about to do a restart...\n");
- /* Almost all unpicking of the argument is done back in csl.c */
- exit_value = a;
- exit_tag = fixnum_of_int(2); /* Flag to say "restart" */
- exit_reason = UNWIND_RESTART;
- exit_charvec = v;
- flip_exception();
- return nil;
- }
- static Lisp_Object Lrestart_csl(Lisp_Object nil, Lisp_Object a)
- {
- return Lrestart_csl2(nil, a, SPID_NOARG);
- }
- static Lisp_Object Lpreserve(Lisp_Object nil,
- Lisp_Object startup, Lisp_Object banner)
- /*
- * (preserve <startup-fn>) saves a Lisp image in a standard place
- * and arranges that when restarted the saved image will call the specified
- * startup function. In the process of doing all this it unwinds down to
- * the top level of Lisp. If a startup function is not given then the
- * previously active one is used. If nil is specified then the previously
- * active startup function is retained. If banner is non-nil (well really
- * I want a string) is is a message of up to 40 characters to display
- * when the system restart.
- */
- {
- char filename[LONGEST_LEGAL_FILENAME];
- CSLbool failed;
- #ifdef SOCKETS
- /*
- * Security measure - deny preserve to remote users
- */
- if (socket_server != 0) return aerror("preserve");
- #endif
- if (startup != nil) supervisor = startup;
- failed = Iwriterootp(filename); /* Can I open image file for writing? */
- term_printf("\nThe system will be preserved on file \"%s\"\n", filename);
- if (failed) return aerror("preserve");
- exit_count = 0;
- nil = C_nil;
- exit_value = banner;
- exit_tag = fixnum_of_int(1); /* Flag to say "preserve" */
- exit_reason = UNWIND_RESTART;
- flip_exception();
- return nil;
- }
- static Lisp_Object MS_CDECL Lpreserve_0(Lisp_Object nil, int nargs, ...)
- {
- argcheck(nargs, 0, "preserve");
- return Lpreserve(nil, nil, nil);
- }
- static Lisp_Object Lpreserve_1(Lisp_Object nil, Lisp_Object startup)
- {
- return Lpreserve(nil, startup, nil);
- }
- /*
- * This is an experimental addition - a version of PRESERVE that allows
- * CSL to continue executing after it has written out an image file.
- */
- static Lisp_Object Lcheckpoint(Lisp_Object nil,
- Lisp_Object startup, Lisp_Object banner)
- {
- char filename[LONGEST_LEGAL_FILENAME];
- CSLbool failed = 0;
- char *msg = "";
- #ifdef SOCKETS
- /*
- * Security measure - deny checkpoint to remote users
- */
- if (socket_server != 0) return aerror("checkpoint");
- #endif
- if (startup != nil) supervisor = startup;
- failed = Iwriterootp(filename); /* Can I open image file for writing? */
- term_printf("\nThe system will be preserved on file \"%s\"\n", filename);
- if (failed) return aerror("checkpoint");
- if (is_vector(banner) &&
- type_of_header(vechdr(banner)) == TYPE_STRING)
- msg = &celt(banner, 0);
- /*
- * Note, with some degree of nervousness, that things on the C stack will
- * be updated by the garbage collection that happens during the processing
- * of the call to preserve(), but they will be neither adjusted into
- * relative addresses nor unadjusted (and hence restored) by in the
- * image-writing. But the image writing will not actually move any data
- * around so all is still OK, I hope!
- */
- push5(codevec, litvec, catch_tags, faslvec, faslgensyms);
- preserve(msg);
- nil = C_nil;
- if (exception_pending()) failed = 1, flip_exception();
- adjust_all();
- pop5(faslgensyms, faslvec, catch_tags, litvec, codevec);
- eq_hash_tables = eq_hash_table_list;
- equal_hash_tables = equal_hash_table_list;
- eq_hash_table_list = equal_hash_table_list = nil;
- { Lisp_Object qq;
- for (qq = eq_hash_tables; qq!=nil; qq=qcdr(qq))
- rehash_this_table(qcar(qq));
- for (qq = equal_hash_tables; qq!=nil; qq=qcdr(qq))
- rehash_this_table(qcar(qq));
- }
- set_up_functions(YES);
- if (failed) return aerror("checkpoint");
- return onevalue(nil);
- }
- static Lisp_Object MS_CDECL Lcheckpoint_0(Lisp_Object nil, int nargs, ...)
- {
- argcheck(nargs, 0, "checkpoint");
- return Lcheckpoint(nil, nil, nil);
- }
- static Lisp_Object Lcheckpoint_1(Lisp_Object nil, Lisp_Object startup)
- {
- return Lcheckpoint(nil, startup, nil);
- }
- #ifdef COMMON
- static CSLbool eql_numbers(Lisp_Object a, Lisp_Object b)
- /*
- * This is only called from eql, and then only when a and b are both tagged
- * as ratios or complex numbers.
- */
- {
- Lisp_Object p, q;
- p = *(Lisp_Object *)(a + (CELL - TAG_NUMBERS));
- q = *(Lisp_Object *)(b + (CELL - TAG_NUMBERS));
- if (!eql(p, q)) return NO;
- p = *(Lisp_Object *)(a + (2*CELL - TAG_NUMBERS));
- q = *(Lisp_Object *)(b + (2*CELL - TAG_NUMBERS));
- return eql(p, q);
- }
- #endif
- CSLbool eql_fn(Lisp_Object a, Lisp_Object b)
- /*
- * This seems incredible - all the messing about that is needed to
- * check that numeric values compare properly. Ugh.
- */
- {
- /*
- * (these tests done before eql_fn is called).
- * if (a == b) return YES;
- * if ((((int32)a ^ (int32)b) & TAG_BITS) != 0) return NO;
- *
- * Actually in Common Lisp mode where I have short floats as immediate data
- * I have further pain here with (eql 0.0 -0.0).
- */
- #ifdef COMMON
- if ((a == TAG_SFLOAT && b == (TAG_SFLOAT|0x80000000)) ||
- (a == (TAG_SFLOAT|0x80000000) && b == TAG_SFLOAT)) return YES;
- #endif
- if (!is_number(a) || is_immed_or_cons(a)) return NO;
- if (is_bfloat(a))
- { Header h = flthdr(a);
- if (h != flthdr(b)) return NO;
- #ifdef COMMON
- if (type_of_header(h) == TYPE_SINGLE_FLOAT)
- return (single_float_val(a) == single_float_val(b));
- else
- #endif
- /*
- * For the moment I view all non-single floats as double floats. Extra
- * stuff will be needed here if I ever implement long floats as 3-word
- * objects.
- */
- return (double_float_val(a) == double_float_val(b));
- }
- else /* ratio, complex or bignum */
- { Header h = numhdr(a);
- if (h != numhdr(b)) return NO;
- if (type_of_header(h) == TYPE_BIGNUM)
- { intxx hh = (intxx)length_of_header(h) - TAG_NUMBERS;
- while (hh > (intxx)(CELL - TAG_NUMBERS))
- { hh -= 4;
- if (*(unsigned32 *)((char *)a + hh) !=
- *(unsigned32 *)((char *)b + hh))
- return NO;
- }
- return YES;
- }
- #ifdef COMMON
- else return eql_numbers(a, b);
- #else
- else return NO;
- #endif
- }
- }
- static CSLbool cl_vec_equal(Lisp_Object a, Lisp_Object b)
- /*
- * here a and b are known to be vectors or arrays. This should compare
- * them following the Common Lisp recipe, where strings or bitvectors
- * (simple or complex) have their contents compared, while all other types of
- * vector or array are tested using EQ.
- */
- {
- Header ha = vechdr(a), hb = vechdr(b);
- intxx offa = 0, offb = 0;
- int ta = type_of_header(ha), tb = type_of_header(hb);
- intxx la = length_of_header(ha), lb = length_of_header(hb);
- #ifdef COMMON
- if (header_of_bitvector(ha)) ta = TYPE_BITVEC1;
- if (header_of_bitvector(hb)) tb = TYPE_BITVEC1;
- #endif
- switch (ta)
- {
- /*
- case TYPE_ARRAY:
- /* My moan here is that, as noted above, I ought to process even
- * non-simple strings and bit-vectors by comparing contents, but as a
- * matter of idleness I have not yet got around to that. In fact if I get
- * arrays to compare here I will pretend that they are not strings or
- * bit-vectors and compare using EQ...
- */
- case TYPE_STRING:
- switch (tb)
- {
- /* /*
- case TYPE_ARRAY:
- */
- case TYPE_STRING:
- goto compare_strings;
- default:return NO;
- }
- #ifdef COMMON
- case TYPE_BITVEC1:
- switch (tb)
- {
- /* /*
- case TYPE_ARRAY:
- */
- case TYPE_BITVEC1:
- goto compare_bits;
- default:return NO;
- }
- #endif
- default: return (a == b);
- }
- compare_strings:
- if (la != lb) return NO;
- while (la > 0)
- { la--;
- if (*((char *)a + la + offa - TAG_VECTOR) !=
- *((char *)b + la + offb - TAG_VECTOR)) return NO;
- }
- return YES;
- #ifdef COMMON
- compare_bits:
- if (la != lb) return NO;
- while (la > 0)
- { la--;
- if (*((char *)a + la + offa - TAG_VECTOR) !=
- *((char *)b + la + offb - TAG_VECTOR)) return NO;
- }
- return YES;
- #endif
- }
- CSLbool cl_equal_fn(Lisp_Object a, Lisp_Object b)
- /*
- * a and b are not EQ at this stage.. I guarantee to have checked that
- * before entering this general purpose code.
- */
- {
- Lisp_Object nil = C_nil;
- CSL_IGNORE(nil);
- /*
- * The for loop at the top here is so that cl_equal can iterate along the
- * length of linear lists.
- */
- #ifdef CHECK_STACK
- if (check_stack(__FILE__,__LINE__))
- { err_printf("Stack too deep in cl_equal\n");
- my_exit(EXIT_FAILURE);
- }
- #endif
- for (;;)
- {
- int32 ta = (int32)a & TAG_BITS;
- if (ta == TAG_CONS
- #ifdef COMMON
- && a != nil
- #endif
- )
- { if (!consp(b)
- #ifdef COMMON
- || b == nil
- #endif
- ) return NO;
- else
- { Lisp_Object ca = qcar(a), cb = qcar(b);
- if (ca == cb)
- { a = qcdr(a);
- b = qcdr(b);
- if (a == b) return YES;
- continue;
- }
- /*
- * And here, because cl_equal() seems to be a very important low-level
- * primitive, I unwind one level of the recursion that would arise
- * with nested lists.
- */
- for (;;)
- {
- int32 tca = (int32)ca & TAG_BITS;
- if (tca == TAG_CONS
- #ifdef COMMON
- && ca != nil
- #endif
- )
- { if (!consp(cb)
- #ifdef COMMON
- || cb == nil
- #endif
- ) return NO;
- else
- { Lisp_Object cca = qcar(ca), ccb = qcar(cb);
- if (cca == ccb)
- { ca = qcdr(ca);
- cb = qcdr(cb);
- if (ca == cb) break;
- continue;
- }
- /*
- * Do a real recursion when I get down to args like
- * ((x ...) ...) ((y ...) ...)
- */
- if (!cl_equal(cca, ccb)) return NO;
- ca = qcdr(ca);
- cb = qcdr(cb);
- if (ca == cb) break;
- continue;
- }
- }
- else if (tca <= TAG_SYMBOL ||
- ((int32)cb & TAG_BITS) != tca) return NO;
- else switch (tca)
- {
- case TAG_NUMBERS:
- { Header h = numhdr(ca);
- if (h != numhdr(cb)) return NO;
- if (type_of_header(h) == TYPE_BIGNUM)
- { intxx hh = (intxx)length_of_header(h) - TAG_NUMBERS;
- while (hh > (intxx)(CELL - TAG_NUMBERS))
- { hh -= 4;
- if (*(unsigned32 *)((char *)ca + hh) !=
- *(unsigned32 *)((char *)cb + hh))
- return NO;
- }
- break;
- }
- #ifdef COMMON
- else if (!eql_numbers(ca, cb)) return NO;
- else break;
- #else
- else return NO;
- #endif
- }
- case TAG_VECTOR:
- if (!cl_vec_equal(ca, cb)) return NO;
- break;
- default:
- case TAG_BOXFLOAT:
- { Header h = flthdr(ca);
- if (h != flthdr(cb)) return NO;
- #ifdef COMMON
- if (type_of_header(h) == TYPE_SINGLE_FLOAT)
- {
- if (single_float_val(ca) !=
- single_float_val(cb)) return NO;
- else break;
- }
- else
- #endif
- {
- if (double_float_val(ca) !=
- double_float_val(cb)) return NO;
- else break;
- }
- }
- }
- break; /* out of the for (;;) loop */
- }
- a = qcdr(a);
- b = qcdr(b);
- if (a == b) return YES;
- continue;
- }
- }
- else if (ta <= TAG_SYMBOL ||
- ((int32)b & TAG_BITS) != ta) return NO;
- /*
- * OK - now a and b both have the same type and neither are immediate data
- * conses or symbols. That leaves vectors (including strings) and boxed
- * numbers.
- */
- else switch (ta)
- {
- case TAG_NUMBERS:
- { Header h = numhdr(a);
- if (h != numhdr(b)) return NO;
- if (type_of_header(h) == TYPE_BIGNUM)
- { intxx hh = (intxx)length_of_header(h) - TAG_NUMBERS;
- while (hh > (intxx)(CELL - TAG_NUMBERS))
- { hh -= 4;
- if (*(unsigned32 *)((char *)a + hh) !=
- *(unsigned32 *)((char *)b + hh))
- return NO;
- }
- return YES;
- }
- #ifdef COMMON
- else return eql_numbers(a, b);
- #else
- else return NO;
- #endif
- }
- case TAG_VECTOR:
- return cl_vec_equal(a, b);
- default:
- case TAG_BOXFLOAT:
- { Header h = flthdr(a);
- if (h != flthdr(b)) return NO;
- #ifdef COMMON
- if (type_of_header(h) == TYPE_SINGLE_FLOAT)
- {
- if (single_float_val(a) != single_float_val(b))
- return NO;
- else return YES;
- }
- else
- #endif
- /*
- * For the moment I view all non-single floats as double floats. Extra
- * stuff will be needed here if I ever implement long floats as 3-word
- * objects.
- */
- {
- if (double_float_val(a) != double_float_val(b))
- return NO;
- else return YES;
- }
- }
- }
- }
- }
- static CSLbool vec_equal(Lisp_Object a, Lisp_Object b);
- #ifdef TRACED_EQUAL
- #define LOG_SIZE 10000
- typedef struct equal_record
- {
- char file[24];
- int line;
- int depth;
- int count;
- } equal_record;
- static equal_record equal_counts[LOG_SIZE];
- static void record_equal(char *file, int line, int depth)
- {
- int hash = 169*line + depth;
- char *p = file;
- while (*p != 0) hash = 169*hash + (*p++ & 0xff);
- hash = ((169*hash) & 0x7fffffff) % LOG_SIZE;
- while (equal_counts[hash].count != 0)
- { if (equal_counts[hash].line == line &&
- equal_counts[hash].depth == depth &&
- strncmp(equal_counts[hash].file, file, 24) == 0)
- { equal_counts[hash].count++;
- return;
- }
- hash = (hash + 1) % LOG_SIZE;
- }
- strncpy(equal_counts[hash].file, file, 24);
- equal_counts[hash].line = line;
- equal_counts[hash].depth = depth;
- equal_counts[hash].count = 1;
- return;
- }
- void dump_equals()
- {
- int i;
- FILE *log = fopen("equal.log", "w");
- if (log == NULL) log = stdout;
- fprintf(log, "\nCalls to equal...\n");
- for (i=0; i<LOG_SIZE; i++)
- if (equal_counts[i].count != 0)
- fprintf(log, "%24.24s %5d %5d %10d\n",
- equal_counts[i].file, equal_counts[i].line,
- equal_counts[i].depth, equal_counts[i].count);
- fprintf(log, "end of counts\n");
- if (log != stdout) fclose(log);
- }
- CSLbool traced_equal_fn(Lisp_Object a, Lisp_Object b,
- char *file, int line, int depth)
- /*
- * a and b are not EQ at this stage.. I guarantee to have checked that
- * before entering this general purpose code.
- */
- {
- Lisp_Object nil = C_nil;
- record_equal(file, line, depth);
- #undef equal_fn
- #define equal_fn(a, b) traced_equal_fn(a, b, file, line, depth+1)
- #else
- CSLbool equal_fn(Lisp_Object a, Lisp_Object b)
- /*
- * a and b are not EQ at this stage.. I guarantee to have checked that
- * before entering this general purpose code. I will also have checked that
- * the types of the two args agree, and that they are not both immediate
- * date.
- */
- {
- Lisp_Object nil = C_nil;
- CSL_IGNORE(nil);
- #endif
- /*
- * The for loop at the top here is so that equal can iterate along the
- * length of linear lists.
- */
- #ifdef CHECK_STACK
- if (check_stack(__FILE__,__LINE__))
- { err_printf("Stack too deep in equal\n");
- my_exit(EXIT_FAILURE);
- }
- #endif
- for (;;)
- {
- int32 ta = (int32)a & TAG_BITS;
- if (ta == TAG_CONS
- #ifdef COMMON
- && a != nil
- #endif
- )
- { if (!consp(b)
- #ifdef COMMON
- || b == nil
- #endif
- ) return NO;
- else
- { Lisp_Object ca = qcar(a), cb = qcar(b);
- if (ca == cb)
- { a = qcdr(a);
- b = qcdr(b);
- if (a == b) return YES;
- continue;
- }
- /*
- * And here, because equal() seems to be a very important low-level
- * primitive, I unwind one level of the recursion that would arise
- * with nested lists.
- */
- for (;;)
- {
- int32 tca = (int32)ca & TAG_BITS;
- if (tca == TAG_CONS
- #ifdef COMMON
- && ca != nil
- #endif
- )
- { if (!consp(cb)
- #ifdef COMMON
- || cb == nil
- #endif
- ) return NO;
- else
- { Lisp_Object cca = qcar(ca), ccb = qcar(cb);
- if (cca == ccb)
- { ca = qcdr(ca);
- cb = qcdr(cb);
- if (ca == cb) break;
- continue;
- }
- /*
- * Do a real recursion when I get down to args like
- * ((x ...) ...) ((y ...) ...)
- */
- if (!equal(cca, ccb)) return NO;
- ca = qcdr(ca);
- cb = qcdr(cb);
- if (ca == cb) break;
- continue;
- }
- }
- else if (tca <= TAG_SYMBOL ||
- ((int32)cb & TAG_BITS) != tca) return NO;
- else switch (tca)
- {
- case TAG_NUMBERS:
- { Header h = numhdr(ca);
- if (h != numhdr(cb)) return NO;
- if (type_of_header(h) == TYPE_BIGNUM)
- { intxx hh = (intxx)length_of_header(h) - TAG_NUMBERS;
- while (hh > (intxx)(CELL - TAG_NUMBERS))
- { hh -= 4;
- if (*(unsigned32 *)((char *)ca + hh) !=
- *(unsigned32 *)((char *)cb + hh))
- return NO;
- }
- break;
- }
- #ifdef COMMON
- else if (!eql_numbers(ca, cb)) return NO;
- else break;
- #else
- else return NO;
- #endif
- }
- case TAG_VECTOR:
- if (!vec_equal(ca, cb)) return NO;
- break;
- default:
- case TAG_BOXFLOAT:
- { Header h = flthdr(ca);
- if (h != flthdr(cb)) return NO;
- #ifdef COMMON
- if (type_of_header(h) == TYPE_SINGLE_FLOAT)
- {
- if (single_float_val(ca) !=
- single_float_val(cb)) return NO;
- else break;
- }
- else
- #endif
- {
- if (double_float_val(ca) !=
- double_float_val(cb)) return NO;
- else break;
- }
- }
- }
- break; /* out of the for (;;) loop */
- }
- a = qcdr(a);
- b = qcdr(b);
- if (a == b) return YES;
- continue;
- }
- }
- else if (ta <= TAG_SYMBOL ||
- ((int32)b & TAG_BITS) != ta) return NO;
- else switch (ta)
- {
- case TAG_NUMBERS:
- { Header h = numhdr(a);
- if (h != numhdr(b)) return NO;
- if (type_of_header(h) == TYPE_BIGNUM)
- { intxx hh = (intxx)length_of_header(h) - TAG_NUMBERS;
- while (hh > (intxx)(CELL - TAG_NUMBERS))
- { hh -= 4;
- if (*(unsigned32 *)((char *)a + hh) !=
- *(unsigned32 *)((char *)b + hh))
- return NO;
- }
- return YES;
- }
- #ifdef COMMON
- else return eql_numbers(a, b);
- #else
- else return NO;
- #endif
- }
- case TAG_VECTOR:
- return vec_equal(a, b);
- default:
- case TAG_BOXFLOAT:
- { Header h = flthdr(a);
- if (h != flthdr(b)) return NO;
- #ifdef COMMON
- if (type_of_header(h) == TYPE_SINGLE_FLOAT)
- {
- if (single_float_val(a) != single_float_val(b))
- return NO;
- else return YES;
- }
- else
- #endif
- /*
- * For the moment I view all non-single floats as double floats. Extra
- * stuff will be needed here if I ever implement long floats as 3-word
- * objects.
- */
- {
- if (double_float_val(a) != double_float_val(b))
- return NO;
- else return YES;
- }
- }
- }
- }
- }
- #ifdef TRACED_EQUAL
- #undef equal_fn
- #define equal_fn(a, b) traced_equal(a, b, __FILE__, __LINE__, 0)
- #endif
- static CSLbool vec_equal(Lisp_Object a, Lisp_Object b)
- /*
- * Here a and b are known to be vectors. Compare using recursive calls to
- * EQUAL on all components.
- */
- {
- Header ha = vechdr(a), hb = vechdr(b);
- int32 l;
- if (ha != hb) return NO;
- l = (int32)doubleword_align_up(length_of_header(ha));
- if (vector_holds_binary(ha))
- { while ((l -= 4) != 0)
- if (*((unsigned32 *)((char *)a + l - TAG_VECTOR)) !=
- *((unsigned32 *)((char *)b + l - TAG_VECTOR))) return NO;
- return YES;
- }
- else
- { if (is_mixed_header(ha))
- { while (l > 16)
- { unsigned32 ea = *((unsigned32 *)((char *)a + l - TAG_VECTOR - 4)),
- eb = *((unsigned32 *)((char *)b + l - TAG_VECTOR - 4));
- if (ea != eb) return NO;
- l -= 4;
- }
- }
- while ((l -= CELL) != 0)
- { Lisp_Object ea = *((Lisp_Object *)((char *)a + l - TAG_VECTOR)),
- eb = *((Lisp_Object *)((char *)b + l - TAG_VECTOR));
- if (ea == eb) continue;
- if (!equal(ea, eb)) return NO;
- }
- return YES;
- }
- }
- CSLbool equalp(Lisp_Object a, Lisp_Object b)
- /*
- * a and b are not EQ at this stage.. I guarantee to have checked that
- * before entering this general purpose code.
- */
- {
- Lisp_Object nil = C_nil;
- CSL_IGNORE(nil);
- /*
- * The for loop at the top here is so that equalp can iterate along the
- * length of linear lists.
- */
- #ifdef CHECK_STACK
- if (check_stack(__FILE__,__LINE__))
- { err_printf("Stack too deep in equalp\n");
- my_exit(EXIT_FAILURE);
- }
- #endif
- for (;;)
- {
- int32 ta = (int32)a & TAG_BITS;
- if (ta == TAG_CONS
- #ifdef COMMON
- && a != nil
- #endif
- )
- { if (!consp(b)
- #ifdef COMMON
- || b == nil
- #endif
- ) return NO;
- else
- { Lisp_Object ca = qcar(a), cb = qcar(b);
- if (ca == cb)
- { a = qcdr(a);
- b = qcdr(b);
- if (a == b) return YES;
- continue;
- }
- /*
- * And here, because equalp() seems to be a very important low-level
- * primitive, I unwind one level of the recursion that would arise
- * with nested lists.
- */
- for (;;)
- {
- int32 tca = (int32)ca & TAG_BITS;
- if (tca == TAG_CONS
- #ifdef COMMON
- && ca != nil
- #endif
- )
- { if (!consp(cb)
- #ifdef COMMON
- || cb == nil
- #endif
- ) return NO;
- else
- { Lisp_Object cca = qcar(ca), ccb = qcar(cb);
- if (cca == ccb)
- { ca = qcdr(ca);
- cb = qcdr(cb);
- if (ca == cb) break;
- continue;
- }
- /*
- * Do a real recursion when I get down to args like
- * ((x ...) ...) ((y ...) ...)
- */
- if (!equalp(cca, ccb)) return NO;
- ca = qcdr(ca);
- cb = qcdr(cb);
- if (ca == cb) break;
- continue;
- }
- }
- else if (tca <= TAG_SYMBOL ||
- ((int32)cb & TAG_BITS) != tca) return NO;
- else switch (tca)
- {
- case TAG_NUMBERS:
- { Header h = numhdr(ca);
- if (h != numhdr(cb)) return NO;
- if (type_of_header(h) == TYPE_BIGNUM)
- { intxx hh = (intxx)length_of_header(h) - TAG_NUMBERS;
- while (hh > (intxx)(CELL - TAG_NUMBERS))
- { hh -= 4;
- if (*(unsigned32 *)((char *)ca + hh) !=
- *(unsigned32 *)((char *)cb + hh))
- return NO;
- }
- break;
- }
- #ifdef COMMON
- else if (!eql_numbers(ca, cb)) return NO;
- else break;
- #else
- else return NO;
- #endif
- }
- case TAG_VECTOR:
- /* /* At present vec_equal() is not right here */
- if (!vec_equal(ca, cb)) return NO;
- break;
- default:
- case TAG_BOXFLOAT:
- { Header h = flthdr(ca);
- if (h != flthdr(cb)) return NO;
- #ifdef COMMON
- if (type_of_header(h) == TYPE_SINGLE_FLOAT)
- {
- if (single_float_val(ca) !=
- single_float_val(cb)) return NO;
- else break;
- }
- else
- #endif
- {
- if (double_float_val(ca) !=
- double_float_val(cb)) return NO;
- else break;
- }
- }
- }
- break; /* out of the for (;;) loop */
- }
- a = qcdr(a);
- b = qcdr(b);
- if (a == b) return YES;
- continue;
- }
- }
- else if (ta <= TAG_SYMBOL ||
- ((int32)b & TAG_BITS) != ta) return NO;
- /* What is left is vectors, strings and boxed numbers */
- else switch (ta)
- {
- case TAG_NUMBERS:
- { Header h = numhdr(a);
- if (h != numhdr(b)) return NO;
- if (type_of_header(h) == TYPE_BIGNUM)
- { intxx hh = (intxx)length_of_header(h) - TAG_NUMBERS;
- while (hh > (intxx)(CELL - TAG_NUMBERS))
- { hh -= 4;
- if (*(unsigned32 *)((char *)a + hh) !=
- *(unsigned32 *)((char *)b + hh))
- return NO;
- }
- return YES;
- }
- #ifdef COMMON
- else return eql_numbers(a, b);
- #else
- else return NO;
- #endif
- }
- case TAG_VECTOR:
- /* /* wrong for Common Lisp */
- return vec_equal(a, b);
- default:
- case TAG_BOXFLOAT:
- { Header h = flthdr(a);
- if (h != flthdr(b)) return NO;
- #ifdef COMMON
- if (type_of_header(h) == TYPE_SINGLE_FLOAT)
- {
- if (single_float_val(a) != single_float_val(b))
- return NO;
- else return YES;
- }
- else
- #endif
- /*
- * For the moment I view all non-single floats as double floats. Extra
- * stuff will be needed here if I ever implement long floats as 3-word
- * objects.
- */
- {
- if (double_float_val(a) != double_float_val(b))
- return NO;
- else return YES;
- }
- }
- }
- }
- }
- Lisp_Object Leq(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- return onevalue(Lispify_predicate(a == b));
- }
- Lisp_Object Leql(Lisp_Object nil,
- Lisp_Object a, Lisp_Object b)
- {
- return onevalue(Lispify_predicate(eql(a, b)));
- }
- Lisp_Object Leqcar(Lisp_Object nil,
- Lisp_Object a, Lisp_Object b)
- {
- if (!consp(a)) return onevalue(nil);
- a = qcar(a);
- #ifdef COMMON
- return onevalue(Lispify_predicate(eql(a, b)));
- #else
- return onevalue(Lispify_predicate(a == b));
- #endif
- }
- Lisp_Object Lequalcar(Lisp_Object nil,
- Lisp_Object a, Lisp_Object b)
- {
- if (!consp(a)) return onevalue(nil);
- a = qcar(a);
- if (a == b) return lisp_true;
- else return onevalue(Lispify_predicate(equal(a, b)));
- }
- Lisp_Object Lcl_equal(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- if (a == b) return onevalue(lisp_true);
- else return onevalue(Lispify_predicate(cl_equal(a, b)));
- }
- Lisp_Object Lequal(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- if (a == b) return onevalue(lisp_true);
- else return onevalue(Lispify_predicate(equal(a, b)));
- }
- Lisp_Object Lequalp(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- if (a == b) return onevalue(lisp_true);
- else return onevalue(Lispify_predicate(equalp(a, b)));
- }
- Lisp_Object Lneq(Lisp_Object nil,
- Lisp_Object a, Lisp_Object b)
- {
- CSLbool r;
- #ifdef COMMON
- r = cl_equal(a, b);
- #else
- r = equal(a, b);
- #endif
- return onevalue(Lispify_predicate(!r));
- }
- Lisp_Object Lnull(Lisp_Object nil, Lisp_Object a)
- {
- return onevalue(Lispify_predicate(a == nil));
- }
- Lisp_Object Lendp(Lisp_Object nil, Lisp_Object a)
- {
- if (a == nil) return onevalue(lisp_true);
- else if (is_cons(a)) return onevalue(nil);
- else return error(1, err_bad_endp, a);
- }
- Lisp_Object Lnreverse(Lisp_Object nil, Lisp_Object a)
- {
- Lisp_Object b = nil;
- #ifdef COMMON
- if (is_vector(a))
- { int32 n = Llength(nil, a) - 0x10;
- int32 i = TAG_FIXNUM;
- while (n > i)
- { Lisp_Object w = Laref2(nil, a, i);
- Laset(nil, 3, a, i, Laref2(nil, a, n));
- Laset(nil, 3, a, n, w);
- i += 0x10;
- n -= 0x10;
- }
- return onevalue(a);
- }
- #endif
- while (consp(a))
- { Lisp_Object c = a;
- a = qcdr(a);
- qcdr(c) = b;
- b = c;
- }
- return onevalue(b);
- }
- Lisp_Object Lnreverse2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- CSL_IGNORE(nil);
- while (consp(a))
- { Lisp_Object c = a;
- a = qcdr(a);
- qcdr(c) = b;
- b = c;
- }
- return onevalue(b);
- }
- #ifdef COMMON
- /*
- * nreverse0 is like nreverse except that if its input is atomic it gets
- * returned intact rather than being converted to nil.
- */
- Lisp_Object Lnreverse0(Lisp_Object nil, Lisp_Object a)
- {
- Lisp_Object b = nil;
- if (!consp(a)) return onevalue(a);
- b = a;
- a = qcdr(a);
- qcdr(b) = nil;
- while (consp(a))
- { Lisp_Object c = a;
- a = qcdr(a);
- qcdr(c) = b;
- b = c;
- }
- return onevalue(b);
- }
- #endif
- Lisp_Object Lreverse(Lisp_Object nil, Lisp_Object a)
- {
- Lisp_Object r;
- stackcheck1(0, a);
- nil = C_nil;
- r = nil;
- while (consp(a))
- { push(a);
- r = cons(qcar(a), r);
- pop(a);
- errexit();
- a = qcdr(a);
- }
- return onevalue(r);
- }
- Lisp_Object Lassoc(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- #ifdef TRACED_EQUAL
- Lisp_Object save_b = b;
- int pos = 0;
- #endif
- if (is_symbol(a) || is_fixnum(a))
- { while (consp(b))
- { Lisp_Object c = qcar(b);
- if (consp(c) && a == qcar(c)) return onevalue(c);
- b = qcdr(b);
- }
- return onevalue(nil);
- }
- while (consp(b))
- { Lisp_Object c = qcar(b);
- if (consp(c))
- { Lisp_Object cc = qcar(c);
- #ifdef COMMON
- if (cl_equal(a, cc)) return onevalue(c);
- #else
- if (equal(a, cc))
- {
- #ifdef TRACED_EQUAL
- trace_printf("Assoc YES %3d %3d ", pos, int_of_fixnum(Llength(nil,save_b)));
- prin_to_stdout(a); trace_printf("\n");
- #endif
- return onevalue(c);
- }
- #endif
- }
- b = qcdr(b);
- #ifdef TRACED_EQUAL
- pos++;
- #endif
- }
- #ifdef TRACED_EQUAL
- trace_printf("Assoc NO %3d %3d ", pos, int_of_fixnum(Llength(nil,save_b)));
- prin_to_stdout(a); trace_printf("\n");
- #endif
- return onevalue(nil);
- }
- Lisp_Object Latsoc(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- #ifdef COMMON
- if (is_symbol(a) || is_fixnum(a))
- { while (consp(b))
- { Lisp_Object c = qcar(b);
- if (consp(c) && a == qcar(c)) return onevalue(c);
- b = qcdr(b);
- }
- return onevalue(nil);
- }
- #endif
- while (consp(b))
- { Lisp_Object c = qcar(b);
- /*
- * eql() can neither fail nor call the garbage collector, so I do
- * not need to stack things here.
- */
- #ifdef COMMON
- if (consp(c) && eql(a, qcar(c))) return onevalue(c);
- #else
- if (consp(c) && a == qcar(c)) return onevalue(c);
- #endif
- b = qcdr(b);
- }
- return onevalue(nil);
- }
- Lisp_Object Lmember(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- if (is_symbol(a) || is_fixnum(a))
- { while (consp(b))
- { if (a == qcar(b)) return onevalue(b);
- b = qcdr(b);
- }
- return onevalue(nil);
- }
- while (consp(b))
- { Lisp_Object cb = qcar(b);
- #ifdef COMMON
- if (cl_equal(a, cb)) return onevalue(b);
- #else
- if (equal(a, cb)) return onevalue(b);
- #endif
- b = qcdr(b);
- }
- return onevalue(nil);
- }
- Lisp_Object Lmemq(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- #ifdef COMMON
- if (is_symbol(a) || is_fixnum(a))
- { while (consp(b))
- { if (a == qcar(b)) return onevalue(b);
- b = qcdr(b);
- }
- return onevalue(nil);
- }
- #endif
- while (consp(b))
- /*
- * Note that eql() can never fail, and so checking for errors
- * and stacking a and b across the call to it is not necessary.
- */
- {
- #ifdef COMMON
- if (eql(a, qcar(b))) return onevalue(b);
- #else
- if (a == qcar(b)) return onevalue(b);
- #endif
- b = qcdr(b);
- }
- return onevalue(nil);
- }
- static CSLbool smemq(Lisp_Object a, Lisp_Object b)
- {
- /*
- * /* This is a bit worrying - it can use C recursion to arbitrary
- * depth without any checking for overflow, and hence it can ESCAPE
- * if (e.g.) given cyclic structures. Some alteration is needed. As
- * things stand the code can never give wrong answers via GC rearrangement -
- * the problem is closer to being that it can never call the GC.
- */
- #ifdef COMMON
- Lisp_Object nil = C_nil;
- #else
- nil_as_base
- #endif
- while (consp(b))
- { Lisp_Object w = qcar(b);
- if (w == quote_symbol) return NO;
- else if (smemq(a, w)) return YES;
- else b = qcdr(b);
- }
- return (a == b);
- }
- Lisp_Object Lsmemq(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- CSLbool r;
- r = smemq(a, b);
- errexit();
- return onevalue(Lispify_predicate(r));
- }
- /*
- * (defun contained (x y)
- * (cond ((atom y) (equal x y))
- * ((equal x y) 't)
- * ('t (or (contained x (car y)) (contained x (cdr y))))))
- */
- static CSLbool containedeq(Lisp_Object nil, Lisp_Object x, Lisp_Object y)
- {
- while (consp(y))
- { if (containedeq(nil, x, qcar(y))) return YES;
- y = qcdr(y);
- }
- return (x == y);
- }
- static CSLbool containedequal(Lisp_Object nil, Lisp_Object x, Lisp_Object y)
- {
- while (consp(y))
- { if (equal(x, y)) return YES;
- if (containedequal(nil, x, qcar(y))) return YES;
- y = qcdr(y);
- }
- return equal(x, y);
- }
- static Lisp_Object Lcontained(Lisp_Object nil, Lisp_Object x, Lisp_Object y)
- {
- CSLbool r;
- if (is_symbol(x) || is_fixnum(x)) r = containedeq(nil, x, y);
- else r = containedequal(nil, x, y);
- errexit();
- return onevalue(Lispify_predicate(r));
- }
- Lisp_Object Llast(Lisp_Object nil, Lisp_Object a)
- {
- Lisp_Object b;
- CSL_IGNORE(nil);
- if (!consp(a)) return aerror1("last", a);
- while (b = qcdr(a), consp(b)) a = b;
- return onevalue(qcar(a));
- }
- Lisp_Object Llastpair(Lisp_Object nil, Lisp_Object a)
- {
- Lisp_Object b;
- CSL_IGNORE(nil);
- if (!consp(a)) return onevalue(a); /* aerror1("lastpair", a); */
- while (b = qcdr(a), consp(b)) a = b;
- return onevalue(a);
- }
- Lisp_Object Llength(Lisp_Object nil, Lisp_Object a)
- {
- if (a == nil) return onevalue(fixnum_of_int(0));
- if (is_cons(a))
- { Lisp_Object n;
- /*
- * Possibly I should do something to trap cyclic lists.. ?
- */
- n = fixnum_of_int(1);
- /*
- * I have unrolled the loop here 4 times since I expect length to be
- * tolerably heavily used. Look at the assembly code generated for
- * this to see if it was useful or counterproductive!
- */
- for (;;)
- { a = qcdr(a);
- if (!consp(a)) return onevalue(n);
- a = qcdr(a);
- if (!consp(a)) return onevalue((Lisp_Object)((int32)n + (1 << 4)));
- a = qcdr(a);
- if (!consp(a)) return onevalue((Lisp_Object)((int32)n + (2 << 4)));
- a = qcdr(a);
- if (!consp(a)) return onevalue((Lisp_Object)((int32)n + (3 << 4)));
- n = (Lisp_Object)((int32)n + (4 << 4));
- }
- }
- #ifndef COMMON
- return onevalue(fixnum_of_int(0)); /* aerror("length");??? */
- #else
- /*
- * Common Lisp expects length to find the length of vectors
- * as well as lists.
- */
- else if (!is_vector(a)) return aerror1("length", a);
- else
- { Header h = vechdr(a);
- int32 n = length_of_header(h) - CELL;
- if (type_of_header(h) == TYPE_ARRAY)
- { Lisp_Object dims = elt(a, 1);
- Lisp_Object fillp = elt(a, 5);
- if (consp(dims) && !consp(qcdr(dims))) dims = qcar(dims);
- else return aerror1("length", a); /* Not one-dimensional */
- if (is_fixnum(fillp)) dims = fillp;
- return onevalue(dims);
- }
- if (header_of_bitvector(h))
- { n = (n - 1)*8;
- /* Dodgy constant on next line - critically dependent on tag codes used! */
- n += ((h & 0x380) >> 7) + 1;
- }
- else if (type_of_header(h) != TYPE_STRING) n = n/CELL;
- return onevalue(fixnum_of_int(n));
- }
- #endif
- }
- #ifdef COMMON
- Lisp_Object MS_CDECL Lappend_n(Lisp_Object nil, int nargs, ...)
- {
- va_list a;
- int i;
- Lisp_Object r;
- if (nargs == 0) return onevalue(nil);
- va_start(a, nargs);
- push_args(a, nargs);
- /*
- * The actual args have been passed a C args - I can not afford to
- * risk garbage collection until they have all been moved somewhere safe,
- * and here that safe place is the Lisp stack. I have to delay checking for
- * overflow on same until all args have been pushed.
- */
- stackcheck0(nargs);
- nil = C_nil;
- r = nil;
- /*
- * rearrange order of items on the stack...
- * The idea is that I will then reverse-copy the args in the order a1,
- * a2 , ... to make a result list. But I want to pop the stack as soon as
- * I can, so I need arg1 on the TOP of the stack.
- */
- for (i = 0; 2*i+1<nargs; i++)
- { Lisp_Object temp = stack[-i];
- stack[-i] = stack[i+1-nargs];
- stack[i+1-nargs] = temp;
- }
- for (i = 0; i<nargs; i++)
- { Lisp_Object w;
- pop(w);
- while (consp(w))
- { push(w);
- nil = C_nil;
- if (!exception_pending()) r = cons(qcar(w), r);
- pop(w);
- w = qcdr(w);
- }
- }
- nil = C_nil;
- if (exception_pending()) return C_nil;
- return onevalue(nreverse(r));
- }
- Lisp_Object Lappend_1(Lisp_Object nil, Lisp_Object a)
- {
- CSL_IGNORE(nil);
- return onevalue(a);
- }
- #endif /* COMMON */
- Lisp_Object Lappend(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- Lisp_Object r = nil;
- push(b);
- stackcheck2(1, a, r);
- while (consp(a))
- { push(a);
- r = cons(qcar(a), r);
- pop(a);
- errexitn(1);
- a = qcdr(a);
- }
- pop(b);
- while (r != nil)
- { a = qcdr(r);
- qcdr(r) = b;
- b = r;
- r = a;
- }
- return onevalue(b);
- }
- Lisp_Object Ldelete(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- Lisp_Object r;
- push2(a, b);
- r = nil;
- if (is_symbol(a) || is_fixnum(a))
- { while (consp(b))
- { Lisp_Object q = qcar(b);
- if (q == stack[-1])
- { b = qcdr(b);
- break;
- }
- stack[0] = qcdr(b);
- r = cons(qcar(b), r);
- errexitn(2);
- b = stack[0];
- }
- }
- else
- { while (consp(b))
- { Lisp_Object q = qcar(b);
- #ifdef COMMON
- if (cl_equal(q, a))
- #else
- if (equal(q, a))
- #endif
- { b = qcdr(b);
- break;
- }
- stack[0] = qcdr(b);
- r = cons(qcar(b), r);
- errexitn(2);
- b = stack[0];
- a = stack[-1];
- }
- }
- popv(2);
- while (r != nil)
- { Lisp_Object w = qcdr(r);
- qcdr(r) = b;
- b = r;
- r = w;
- }
- return onevalue(b);
- }
- Lisp_Object Ldeleq(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- Lisp_Object r;
- push2(a, b);
- r = nil;
- while (consp(b))
- { Lisp_Object q = qcar(b);
- if (q == stack[-1])
- { b = qcdr(b);
- break;
- }
- stack[0] = qcdr(b);
- r = cons(qcar(b), r);
- errexitn(2);
- b = stack[0];
- }
- popv(2);
- while (r != nil)
- { Lisp_Object w = qcdr(r);
- qcdr(r) = b;
- b = r;
- r = w;
- }
- return onevalue(b);
- }
- Lisp_Object Lnconc(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
- {
- Lisp_Object c;
- CSL_IGNORE(nil);
- if (!consp(a)) return onevalue(b);
- c = a;
- for (;;)
- { Lisp_Object next = qcdr(c);
- if (!consp(next))
- { qcdr(c) = b;
- return onevalue(a);
- }
- else c = next;
- }
- }
- /* #ifndef COMMON */
- static Lisp_Object Lsubstq(Lisp_Object a, Lisp_Object b, Lisp_Object c)
- {
- Lisp_Object w, nil = C_nil;
- if (c == b) return onevalue(a);
- #ifdef CHECK_STACK
- if (check_stack(__FILE__,__LINE__)) return aerror("substq");
- #endif
- stackcheck3(0, a, b, c);
- push3(a, b, c);
- if (c == b)
- { popv(2);
- pop(a);
- errexit();
- return onevalue(a);
- }
- if (!consp(stack[0])) { pop(c); popv(2); return c; }
- w = Lsubstq(stack[-2], stack[-1], qcar(stack[0]));
- errexitn(3);
- pop2(c, b);
- a = stack[0];
- stack[0] = w;
- w = Lsubstq(a, b, qcdr(c));
- pop(a);
- errexit();
- a = cons(a, w);
- errexit();
- return onevalue(a);
- }
- Lisp_Object MS_CDECL Lsubst(Lisp_Object nil, int nargs, ...)
- {
- Lisp_Object w, a, b, c;
- va_list aa;
- argcheck(nargs, 3, "subst");
- #ifdef CHECK_STACK
- if (check_stack(__FILE__,__LINE__)) return aerror("subst");
- #endif
- va_start(aa, nargs);
- a = va_arg(aa, Lisp_Object);
- b = va_arg(aa, Lisp_Object);
- c = va_arg(aa, Lisp_Object);
- va_end(aa);
- if (c == b) return onevalue(a);
- if (is_symbol(b) || is_fixnum(b)) return Lsubstq(a, b, c);
- stackcheck3(0, a, b, c);
- push3(a, b, c);
- #ifdef COMMON
- if (cl_equal(c, b))
- #else
- if (equal(c, b))
- #endif
- { popv(2);
- pop(a);
- errexit();
- return onevalue(a);
- }
- if (!consp(stack[0])) { pop(c); popv(2); return c; }
- w = Lsubst(nil, 3, stack[-2], stack[-1], qcar(stack[0]));
- errexitn(3);
- pop2(c, b);
- a = stack[0];
- stack[0] = w;
- w = Lsubst(nil, 3, a, b, qcdr(c));
- pop(a);
- errexit();
- a = cons(a, w);
- errexit();
- return onevalue(a);
- }
- /* #endif */
- Lisp_Object Lsublis(Lisp_Object nil, Lisp_Object al, Lisp_Object x)
- {
- stackcheck2(0, al, x);
- errexit();
- #ifdef CHECK_STACK
- if (check_stack(__FILE__,__LINE__)) return aerror("sublis");
- #endif
- push5(al, x, al, nil, nil);
- #define carx stack[0]
- #define cdrx stack[-1]
- #define w stack[-2]
- #define x stack[-3]
- #define al stack[-4]
- for (;;)
- { if (!consp(w))
- { if (!consp(x))
- { Lisp_Object temp = x;
- popv(5);
- return temp;
- }
- carx = Lsublis(nil, al, qcar(x));
- errexitn(5);
- cdrx = Lsublis(nil, al, qcdr(x));
- errexitn(5);
- if (carx == qcar(x) && cdrx == qcdr(x))
- { Lisp_Object temp = x;
- popv(5);
- return temp;
- }
- else
- { Lisp_Object a1 = carx, a2 = cdrx;
- popv(5);
- return cons(a1, a2);
- }
- }
- { Lisp_Object temp = qcar(w);
- if (consp(temp))
- { Lisp_Object v = qcar(temp);
- #ifdef COMMON
- if (cl_equal(v, x))
- #else
- if (equal(v, x))
- #endif
- { temp = qcdr(temp);
- popv(5);
- return temp;
- }
- }
- }
- w = qcdr(w);
- }
- }
- #undef carx
- #undef cdrx
- #undef w
- #undef x
- #undef al
- Lisp_Object Lsubla(Lisp_Object nil, Lisp_Object al, Lisp_Object x)
- /*
- * as sublis, but uses eq test rather than equal
- */
- {
- stackcheck2(0, al, x);
- errexit();
- #ifdef CHECK_STACK
- if (check_stack(__FILE__,__LINE__)) return aerror("subla");
- #endif
- push5(al, x, al, nil, nil);
- #define carx stack[0]
- #define cdrx stack[-1]
- #define w stack[-2]
- #define x stack[-3]
- #define al stack[-4]
- for (;;)
- { if (!consp(w))
- { if (!consp(x))
- { Lisp_Object temp = x;
- popv(5);
- return temp;
- }
- carx = Lsubla(nil, al, qcar(x));
- errexitn(5);
- cdrx = Lsubla(nil, al, qcdr(x));
- errexitn(5);
- if (carx == qcar(x) && cdrx == qcdr(x))
- { Lisp_Object temp = x;
- popv(5);
- return temp;
- }
- else
- { Lisp_Object a1 = carx, a2 = cdrx;
- popv(5);
- return cons(a1, a2);
- }
- }
- { Lisp_Object temp = qcar(w);
- if (consp(temp))
- { Lisp_Object v = qcar(temp);
- if (v == x) { temp = qcdr(temp); popv(5); return temp; }
- }
- }
- w = qcdr(w);
- }
- }
- #undef carx
- #undef cdrx
- #undef w
- #undef x
- #undef al
- setup_type const funcs2_setup[] =
- {
- {"assoc", too_few_2, Lassoc, wrong_no_2},
- /*
- * assoc** is expected to remain as the Standard Lisp version even if in
- * a Common Lisp world I redefine assoc to be someting messier. xassoc was
- * an earlier name I used for the same purpose, and is being withdrawn.
- */
- {"assoc**", too_few_2, Lassoc, wrong_no_2},
- {"xassoc", too_few_2, Lassoc, wrong_no_2},
- {"atsoc", too_few_2, Latsoc, wrong_no_2},
- {"member", too_few_2, Lmember, wrong_no_2},
- {"member**", too_few_2, Lmember, wrong_no_2},
- {"memq", too_few_2, Lmemq, wrong_no_2},
- {"contained", too_few_2, Lcontained, wrong_no_2},
- {"restart-csl", Lrestart_csl, Lrestart_csl2, wrong_no_1},
- {"eq", too_few_2, Leq, wrong_no_2},
- {"iequal", too_few_2, Leq, wrong_no_2},
- {"eqcar", too_few_2, Leqcar, wrong_no_2},
- {"equalcar", too_few_2, Lequalcar, wrong_no_2},
- {"eql", too_few_2, Leql, wrong_no_2},
- {"equalp", too_few_2, Lequalp, wrong_no_2},
- {"endp", Lendp, too_many_1, wrong_no_1},
- {"getd", Lgetd, too_many_1, wrong_no_1},
- {"last", Llast, too_many_1, wrong_no_1},
- {"lastpair", Llastpair, too_many_1, wrong_no_1},
- {"length", Llength, too_many_1, wrong_no_1},
- {"make-bps", Lget_bps, too_many_1, wrong_no_1},
- {"make-native", Lget_native, too_many_1, wrong_no_1},
- {"symbol-env", Lsymbol_env, too_many_1, wrong_no_1},
- {"symbol-make-fastget", Lsymbol_make_fastget1, Lsymbol_make_fastget, wrong_no_2},
- {"symbol-fastgets", Lsymbol_fastgets, too_many_1, wrong_no_1},
- {"symbol-fn-cell", Lsymbol_fn_cell, too_many_1, wrong_no_1},
- {"symbol-argcount", Lsymbol_argcount, too_many_1, wrong_no_1},
- {"symbol-set-env", too_few_2, Lsymbol_set_env, wrong_no_2},
- {"symbol-set-native", wrong_no_na, wrong_no_nb, Lsymbol_set_native},
- {"symbol-set-definition", too_few_2, Lsymbol_set_definition, wrong_no_2},
- {"restore-c-code", Lrestore_c_code, too_many_1, wrong_no_1},
- {"set-autoload", too_few_2, Lset_autoload, wrong_no_2},
- {"remd", Lremd, too_many_1, wrong_no_1},
- {"trace", Ltrace, too_many_1, wrong_no_1},
- {"untrace", Luntrace, too_many_1, wrong_no_1},
- {"trace-all", Ltrace_all, too_many_1, wrong_no_1},
- {"double-execute", Ldouble, too_many_1, wrong_no_1},
- {"undouble-execute", Lundouble, too_many_1, wrong_no_1},
- {"macro-function", Lmacro_function, too_many_1, wrong_no_1},
- {"symbol-name", Lsymbol_name, too_many_1, wrong_no_1},
- {"plist", Lplist, too_many_1, wrong_no_1},
- {"delete", too_few_2, Ldelete, wrong_no_2},
- {"deleq", too_few_2, Ldeleq, wrong_no_2},
- {"preserve", Lpreserve_1, Lpreserve, Lpreserve_0},
- {"checkpoint", Lcheckpoint_1, Lcheckpoint, Lcheckpoint_0},
- {"mkvect", Lmkvect, too_many_1, wrong_no_1},
- {"nconc", too_few_2, Lnconc, wrong_no_2},
- {"neq", too_few_2, Lneq, wrong_no_2},
- {"not", Lnull, too_many_1, wrong_no_1},
- {"null", Lnull, too_many_1, wrong_no_1},
- {"reverse", Lreverse, too_many_1, wrong_no_1},
- {"reversip", Lnreverse, Lnreverse2, wrong_no_1},
- /* I make the name nreverse generally available as well as reversip */
- {"nreverse", Lnreverse, Lnreverse2, wrong_no_1},
- {"smemq", too_few_2, Lsmemq, wrong_no_2},
- {"subla", too_few_2, Lsubla, wrong_no_2},
- {"sublis", too_few_2, Lsublis, wrong_no_2},
- {"subst", wrong_no_3a, wrong_no_3b, Lsubst},
- {"symbol-protect", too_few_2, Lsymbol_protect, wrong_no_2},
- #ifdef COMMON
- {"symbol-package", Lsymbol_package, too_many_1, wrong_no_1},
- {"symbol-plist", Lplist, too_many_1, wrong_no_1},
- {"append", Lappend_1, Lappend, Lappend_n},
- /*
- * In Common Lisp mode I make EQUAL do what Common Lisp says it should, but
- * also have EQUALS that is much the same but which also descends vectors.
- */
- {"equal", too_few_2, Lcl_equal, wrong_no_2},
- {"equals", too_few_2, Lequal, wrong_no_2},
- {"nreverse0", Lnreverse0, too_many_1, wrong_no_1},
- #else
- {"append", too_few_2, Lappend, wrong_no_2},
- /* In Standard Lisp mode EQUAL descends vectors (but does not case fold) */
- /* I provide cl-equal to do what Common Lisp does. */
- {"cl-equal", too_few_2, Lcl_equal, wrong_no_2},
- {"equal", too_few_2, Lequal, wrong_no_2},
- {"member", too_few_2, Lmember, wrong_no_2},
- {"member", too_few_2, Lmember, wrong_no_2},
- #endif
- {NULL, 0, 0, 0}
- };
- /* end of fns2.c */
|