fns3.c 120 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645
  1. /* fns3.c Copyright (C) 1989-95 Codemist Ltd */
  2. /*
  3. * Basic functions part 3.
  4. * A concentration on hashtable, vector and array access code here.
  5. */
  6. /* Signature: 0aca95f3 07-Mar-2000 */
  7. #include <stdarg.h>
  8. #include <string.h>
  9. #include <ctype.h>
  10. #include "machine.h"
  11. #include "tags.h"
  12. #include "cslerror.h"
  13. #include "externs.h"
  14. #include "read.h"
  15. #include "entries.h"
  16. #include "arith.h"
  17. #ifdef COMMON
  18. #include "clsyms.h"
  19. #endif
  20. #ifdef TIMEOUT
  21. #include "timeout.h"
  22. #endif
  23. /*
  24. * Common Lisp and Standard Lisp disagree about vector sizes. Common
  25. * Lisp counts the number of elements in a vector (with make-simple-vector
  26. * and vector-bound) while Standard Lisp uses the value n, where the
  27. * vector concerned will accept index values from 0 to n (inclusive)
  28. * (mkvect and upbv). I provide the Standard Lisp versions always, so I
  29. * can use them even in Common Lisp mode. The vectors are exactly the
  30. * same - it is just a different way of talking about them.
  31. */
  32. Lisp_Object Lmkvect(Lisp_Object nil, Lisp_Object n)
  33. {
  34. int32 n1;
  35. if (!is_fixnum(n)) return aerror1("mkvect", n);
  36. n1 = int_of_fixnum(n) << 2;
  37. n1 += 4; /* Oh! What an abomination! Standard Lisp allocated 0::n, */
  38. /* Common allocates n items */
  39. if (n1 < 0) return aerror1("mkvect", n);
  40. return onevalue(getvector_init(n1+4, nil));
  41. }
  42. #ifdef COMMON
  43. Lisp_Object Lmksimplevec(Lisp_Object nil, Lisp_Object n)
  44. {
  45. int32 n1;
  46. if (!is_fixnum(n)) return aerror1("make-simple-vector", n);
  47. n1 = int_of_fixnum(n) << 2;
  48. if (n1 < 0) return aerror1("make-simple-vector", n);
  49. return onevalue(getvector_init(n1+4, nil));
  50. }
  51. #endif
  52. /*
  53. * This one creates a "structure" tagged vector.
  54. */
  55. Lisp_Object Lmkevect(Lisp_Object nil, Lisp_Object n)
  56. {
  57. int32 n1;
  58. if (!is_fixnum(n)) return aerror1("mkevect", n);
  59. n1 = int_of_fixnum(n) << 2;
  60. #ifndef COMMON
  61. n1 += 4; /* Oh! What an abomination! Standard Lisp allocated 0::n, */
  62. /* Common allocates n items */
  63. #endif
  64. if (n1 < 0) return aerror1("mkevect", n);
  65. n = getvector_init(n1+4, nil);
  66. errexit();
  67. vechdr(n) ^= (TYPE_SIMPLE_VEC ^ TYPE_STRUCTURE);
  68. return onevalue(n);
  69. }
  70. /*
  71. * The following creates a sort of vector where the first 3 items are
  72. * lisp pointers, and the remainder may be filled with binary stuff (which
  73. * is not byte-flipped or anything on garbage collection, and so is possibly
  74. * fairly unsafe). It is intended for internal or experimental use only.
  75. */
  76. Lisp_Object Lmkxvect(Lisp_Object nil, Lisp_Object n)
  77. {
  78. int32 n1;
  79. if (!is_fixnum(n)) return aerror1("mkxvect", n);
  80. n1 = int_of_fixnum(n) << 2;
  81. #ifndef COMMON
  82. n1 += 4; /* Oh! What an abomination! Standard Lisp allocated 0::n, */
  83. /* Common allocates n items */
  84. #endif
  85. if (n1 < 12) return aerror1("mkxvect", n);
  86. n = getvector_init(n1+4, nil);
  87. errexit();
  88. vechdr(n) ^= (TYPE_SIMPLE_VEC ^ TYPE_MIXED1);
  89. return onevalue(n);
  90. }
  91. static int primep(int32 n)
  92. /*
  93. * Used to ensure that the body of a hash-table has a size that is prime.
  94. * Assumes odd number provided on entry, and that the value to be checked
  95. * is not especially large. Since it will have been handed in as a
  96. * fixnum it is at worst 2^28 or so, so brute-force should be OK.
  97. */
  98. {
  99. int32 i;
  100. for (i=3; i*i<=n; i+=2)
  101. if (n%i == 0) return 0;
  102. return 1;
  103. }
  104. #define HASH_CHUNK_SIZE (((unsigned32)1) << (PAGE_BITS-3))
  105. #define HASH_CHUNK_WORDS (HASH_CHUNK_SIZE/4)
  106. static Lisp_Object get_hash_vector(int32 n)
  107. {
  108. Lisp_Object v, nil = C_nil;
  109. /*
  110. * A major ugliness here is that I need to support hash tables that are
  111. * larger than the largest simple vector I can use (as limited by
  112. * CSL_PAGE_SIZE). To achieve this I will handle such huge tables using
  113. * a vector of vectors, with the higher level vector tagged as a STRUCT,
  114. * and the lower level vectors each sized at around 1/8 of a CSL page. The
  115. * modest chunk size is intended to limit the packing lossage I will see at
  116. * page boundaries. HASH_CHUNK_SIZE is the size (in bytes) used for data in
  117. * each such hash chunk.
  118. */
  119. if (n > CSL_PAGE_SIZE/2) /* A fairly arbitrary cut-off */
  120. { int32 chunks = (n + HASH_CHUNK_SIZE - 1)/HASH_CHUNK_SIZE;
  121. int32 i;
  122. v = getvector_init(12+4*chunks, nil);
  123. errexit();
  124. /* The next line tags the top level vector as a struct */
  125. vechdr(v) ^= (TYPE_SIMPLE_VEC ^ TYPE_STRUCTURE);
  126. elt(v, 1) = fixnum_of_int(n);
  127. for (i=0; i<chunks; i++)
  128. { Lisp_Object v1;
  129. push(v);
  130. /*
  131. * In general the last of these chunks will be larger that it really needs
  132. * to be, but keeping all chunks the same standard size seems a useful
  133. * simplification right at present!
  134. */
  135. v1 = getvector_init(HASH_CHUNK_SIZE+4, SPID_HASH0);
  136. pop(v);
  137. errexit();
  138. elt(v, i+2) = v1;
  139. }
  140. }
  141. else v = getvector_init(n, SPID_HASH0);
  142. return v;
  143. }
  144. Lisp_Object MS_CDECL Lmkhash(Lisp_Object nil, int nargs, ...)
  145. /*
  146. * size suggests how many items can be inserted before re-hashing
  147. * occurs. flavour is 0, 1, 2, 3 or 4 corresponding to hash tables
  148. * that use EQ, EQL, EQUAL, EQUALS or EQUALP. growth is a floating point
  149. * value suggesting how much to grow by when rehashing is needed.
  150. *
  151. * NB. Hash tables of type 0 or 1 (using EQ or EQL) will need special
  152. * treatment by the garbage collector - in particular since the garbage
  153. * collector can relocate values the entire contents of the tables will
  154. * need rearrangement. Tables of types 2, 3 and 4 use hash-codes that are
  155. * more expensive to compute, but which are insensitive to memory addresses
  156. * and the like, and so so NOT need special treatment. Tables that need
  157. * re-hashing on GC are kept on a special list, known to the GC. Even type
  158. * 2, 3 and 4 hash tables are rehashed when a core image is re-loaded, since
  159. * the hash function may be byte-order sensitive.
  160. *
  161. * If flavour is not a number it might be a dotted pair (hashfn . eqfn)
  162. * where hashfn is a user-provided function to compute hash values (which
  163. * will actually be permitted to be anything at all, since I will then
  164. * hash the output again as if hashing under EQL - but I expect that really
  165. * I expect numeric hash values), and eqfn is a function used to compare
  166. * items. [this facility may not be implemented at first]
  167. */
  168. {
  169. va_list a;
  170. int32 size1, size2;
  171. Lisp_Object v, v1, size, flavour, growth;
  172. argcheck(nargs, 3, "mkhash");
  173. va_start(a, nargs);
  174. size = va_arg(a, Lisp_Object);
  175. flavour = va_arg(a, Lisp_Object);
  176. growth = va_arg(a, Lisp_Object);
  177. va_end(a);
  178. if (!is_fixnum(size)) return aerror1("mkhash", size);
  179. size1 = int_of_fixnum(size);
  180. if (size1 <= 0) return aerror1("mkhash", size);
  181. if (!is_fixnum(flavour) && !consp(flavour))
  182. return aerror1("mkhash", flavour);
  183. /*
  184. * I will start with a table with around 1.5 times as many slots as
  185. * were requested, and will ensure that the size is a prime. I also add
  186. * in a little more so that people who ask for VERY small tables get
  187. * given ones that are not mindlessly tiny.
  188. */
  189. size2 = (size1 + (size1/2) + 4) | 1;
  190. while (!primep(size2)) size2 += 2;
  191. size2 = size2<<2;
  192. push(growth);
  193. /*
  194. * Huge hash tables will be stored (internally) in chunks.
  195. */
  196. v = get_hash_vector(2*size2+8);
  197. errexitn(1);
  198. push(v);
  199. v1 = getvector_init(24, nil);
  200. pop2(v, growth);
  201. errexit();
  202. push3(v, v1, growth);
  203. v = ncons(v);
  204. errexitn(3);
  205. /*
  206. * I keep a list of all hash tables in a weak list-head. The use of ncons
  207. * followed by a RPLACD is because I want xx_hash_tables to be the ONLY
  208. * possible pointer to that bit of list. Even if I garbage collect while
  209. * updating it. Note that I also re-hash every garbage collection if the
  210. * hash function is a user-provided one. This is a matter of security
  211. * since it will often not really be necessary, since it will be a bit hard
  212. * for user hash functions to depend on absolute memory addresses. But all
  213. * rehashing costs is some time, I hope.
  214. */
  215. if (flavour == fixnum_of_int(0) ||
  216. flavour == fixnum_of_int(1) || !is_fixnum(flavour))
  217. { qcdr(v) = eq_hash_tables;
  218. eq_hash_tables = v;
  219. }
  220. else
  221. { qcdr(v) = equal_hash_tables;
  222. equal_hash_tables = v;
  223. }
  224. pop3(growth, v1, v);
  225. elt(v, 0) = elt(v1, 0) = flavour;
  226. elt(v1, 1) = fixnum_of_int(0);
  227. elt(v1, 2) = size;
  228. elt(v1, 3) = growth;
  229. elt(v1, 4) = v;
  230. vechdr(v1) ^= (TYPE_SIMPLE_VEC ^ TYPE_HASH);
  231. return onevalue(v1);
  232. }
  233. /*
  234. * I use the following while combining parts of a structure to compute a
  235. * hash value. It may not be totally wonderful (I would need to soak my mind
  236. * in pseudo-random numbers to do a really good job) but it will probably
  237. * serve for now.
  238. */
  239. static unsigned32 update_hash(unsigned32 prev, unsigned32 data)
  240. {
  241. prev = prev ^ data;
  242. prev = prev ^ (prev >> 11);
  243. prev = prev ^ ((prev & 0xffffff) * 169);
  244. return prev & 0x7fffffff;
  245. }
  246. static unsigned32 hash_eql(Lisp_Object key)
  247. /*
  248. * Must return same code for two eql numbers. This is remarkably
  249. * painfull! I would like the value to be insensitive to fine details
  250. * of the machine I am running on.
  251. */
  252. {
  253. if (is_bfloat(key))
  254. { int32 h = type_of_header(flthdr(key));
  255. /*
  256. * For floating point values I look at the binary representation of
  257. * the number.
  258. */
  259. union nasty
  260. { double fp;
  261. unsigned32 i[2];
  262. } nasty_union;
  263. nasty_union.i[0] = nasty_union.i[1] = 0;
  264. switch (h)
  265. {
  266. #ifdef COMMON
  267. case TYPE_SINGLE_FLOAT:
  268. nasty_union.fp = (double)single_float_val(key);
  269. break;
  270. #endif
  271. case TYPE_DOUBLE_FLOAT:
  272. nasty_union.fp = double_float_val(key);
  273. break;
  274. #ifdef COMMON
  275. case TYPE_LONG_FLOAT:
  276. nasty_union.fp = (double)long_float_val(key);
  277. break;
  278. #endif
  279. default:
  280. nasty_union.fp = 0.0;
  281. }
  282. /*
  283. * The following line is OK on any one computer, but will generate values
  284. * that are not portable across machines with different floating point
  285. * representation. This is not too important when the hash value is only
  286. * used with my built-in implementation of hash tables, since I arrange
  287. * to re-hash everything when an image file is re-loaded (as well as on
  288. * any garbage collection), so non-portable calculation here is corrected
  289. * for automatically.
  290. */
  291. return update_hash(nasty_union.i[0], nasty_union.i[1]);
  292. }
  293. else if (is_numbers(key))
  294. { Header h = numhdr(key);
  295. unsigned32 r;
  296. int n;
  297. switch (type_of_header(h))
  298. {
  299. case TYPE_BIGNUM:
  300. n = length_of_header(h);
  301. n = (n>>2) - 2; /* last index into the data */
  302. r = update_hash(1, (unsigned32)h);
  303. /*
  304. * This mat be overkill - for very long bignums it is possibly a waste to
  305. * walk over ALL the digits when computing a hash value - I could do well
  306. * enough just looking at a few. But I still feel safer using all of them.
  307. */
  308. while (n >= 0)
  309. { r = update_hash(r, bignum_digits(key)[n]);
  310. n--;
  311. }
  312. return r;
  313. #ifdef COMMON
  314. case TYPE_RATNUM:
  315. case TYPE_COMPLEX_NUM:
  316. return update_hash(hash_eql(numerator(key)),
  317. hash_eql(denominator(key)));
  318. #endif
  319. default:
  320. return 0x12345678; /* unknown type of number? */
  321. }
  322. }
  323. /*
  324. * For all things OTHER than messy numbers I just hand back the
  325. * representation of the object as a C pointer. Well, I scramble it a bit
  326. * because otherwise too often Lisp objects only differ in their low order
  327. * bits.
  328. */
  329. else return update_hash(1, (unsigned32)key);
  330. }
  331. static unsigned32 hash_cl_equal(Lisp_Object key, CSLbool descend)
  332. /*
  333. * This function is the one used hashing things under EQUAL, and note
  334. * that Common Lisp expects that EQUAL will NOT descend vectors or
  335. * structures, so this code had better not. But it is supposed to
  336. * descend path-names and it must treat non-simple strings and bitvectors
  337. * as if they were like ordinary strings and bitvectors. If descend is
  338. * false this will not descend through lists.
  339. */
  340. {
  341. unsigned32 r = 1, c;
  342. Lisp_Object nil, w;
  343. int32 len;
  344. #ifdef COMMON
  345. int32 bitoff;
  346. #endif
  347. unsigned char *data;
  348. Header ha;
  349. #ifdef CHECK_STACK
  350. if (check_stack(__FILE__,__LINE__))
  351. { err_printf("Stack too deep in hash calculation\n");
  352. my_exit(EXIT_FAILURE);
  353. }
  354. #endif
  355. for (;;)
  356. { switch (TAG_BITS & (int32)key)
  357. {
  358. case TAG_CONS:
  359. if (key == C_nil || !descend) return r;
  360. r = update_hash(r, hash_cl_equal(qcar(key), YES));
  361. nil = C_nil;
  362. if (exception_pending()) return 0;
  363. key = qcdr(key);
  364. continue;
  365. case TAG_SYMBOL:
  366. if (key == C_nil) return r;
  367. key = get_pname(key);
  368. nil = C_nil;
  369. if (exception_pending()) return 0;
  370. r = update_hash(r, 1); /* makes name & string hash differently */
  371. /* Drop through, because the pname is a string */
  372. case TAG_VECTOR:
  373. { ha = vechdr(key);
  374. len = type_of_header(ha);
  375. /*
  376. * I need to treat strings and bitvectors here specially since in those
  377. * cases (and for pathnames) I must inspect the vector contents, while
  378. * in other cases I must not.
  379. */
  380. if (len == TYPE_STRING)
  381. { len = length_of_header(ha) - 4;
  382. data = &ucelt(key, 0);
  383. goto hash_as_string;
  384. }
  385. #ifdef COMMON
  386. else if (header_of_bitvector(ha))
  387. { len = length_of_header(ha);
  388. len = (len - 5)*8 + ((ha & 0x380) >> 7) + 1;
  389. bitoff = 0;
  390. data = &ucelt(key, 0);
  391. goto hash_as_bitvector;
  392. }
  393. #endif
  394. else if (len == TYPE_ARRAY)
  395. {
  396. /*
  397. * Arrays are fun here! I need to pick up the special case of character
  398. * vectors and bit vectors and make them compute the same hash value as the
  399. * simple case of the same thing.
  400. */
  401. w = elt(key, 0);
  402. if (w == string_char_sym) ha = 0;
  403. #ifdef COMMON
  404. else if (w == bit_symbol) ha = 1;
  405. #endif
  406. else return update_hash(r, (unsigned32)key);
  407. w = elt(key, 1); /* List of dimensions */
  408. if (!consp(w) || consp(qcdr(w))) /* 1 dim or more? */
  409. return update_hash(r, (unsigned32)key);
  410. len = int_of_fixnum(qcar(w)); /* This is the length */
  411. w = elt(key, 5); /* Fill pointer */
  412. if (is_fixnum(w)) len = int_of_fixnum(w);
  413. w = elt(key, 3); /* displace adjustment */
  414. key = elt(key, 2); /* vector holding the actual data */
  415. data = &ucelt(key, 0);
  416. #ifdef COMMON
  417. if (ha)
  418. { bitoff = int_of_fixnum(w);
  419. goto hash_as_bitvector;
  420. }
  421. #endif
  422. data += int_of_fixnum(w);
  423. goto hash_as_string;
  424. }
  425. #ifdef COMMON
  426. /*
  427. * Common Lisp demands that pathname structures be compared and hashed in
  428. * a way that is expected to look at their contents. Here I just descend
  429. * all components of the pathname.
  430. */
  431. else if (len == TYPE_STRUCTURE &&
  432. elt(key, 0) == pathname_symbol &&
  433. descend)
  434. { len = doubleword_align_up(length_of_header(ha));
  435. while ((len -= 4) != 0)
  436. { Lisp_Object ea =
  437. *((Lisp_Object *)((char *)key + len - TAG_VECTOR));
  438. r = update_hash(r, hash_cl_equal(ea, YES));
  439. nil = C_nil;
  440. if (exception_pending()) return 0;
  441. }
  442. return r;
  443. }
  444. #endif
  445. else return update_hash(r, (unsigned32)key);
  446. }
  447. case TAG_ODDS:
  448. if (is_bps(key))
  449. { data = (unsigned char *)data_of_bps(key);
  450. /* I treat bytecode things as strings here */
  451. len = length_of_header(*(Header *)(data - 4));
  452. goto hash_as_string;
  453. }
  454. else return update_hash(r, (unsigned32)key);
  455. case TAG_BOXFLOAT:
  456. /*
  457. * The "case TAG_BOXFLOAT:" above is not logically necessary, but at least
  458. * one release of a Silicon Graphics C compiler seems to miscompile this
  459. * function without it (when optimised). It is as if it seems the masking
  460. * with TAG_BITS in the switch() and therefore knows that there is just a
  461. * limited range of possibilities, so it omits the normal range-check one
  462. * would use before a table-branch. But it then leaves the branch table
  463. * that it generates NOT padded with the final case (TAG_BOXFLOAT) that is
  464. * needed, so when a floating point values does arise the code goes into the
  465. * yonder and usually crashes.
  466. */
  467. default:
  468. return hash_eql(key);
  469. }
  470. hash_as_string:
  471. /* Here len is the length of the string data structure, excluding header */
  472. while (len > 0)
  473. { c = data[--len];
  474. r = update_hash(r, c);
  475. }
  476. return r;
  477. #ifdef COMMON
  478. hash_as_bitvector:
  479. /* here len is the number of bits to scan, and bitoff is a BIT offset */
  480. len += bitoff;
  481. while (len > bitoff)
  482. { len--;
  483. c = data[len >> 3] & (1 << (len & 7));
  484. if (c != 0) c = 1;
  485. r = update_hash(r, c);
  486. }
  487. return r;
  488. #endif
  489. }
  490. }
  491. static unsigned32 hash_equal(Lisp_Object key)
  492. /*
  493. * This function is the one used hashing things under the Standard Lisp
  494. * version of EQUAL, which descends vectors but is still sensitive to
  495. * case and which views different types of numbers as different. I will
  496. * make it view displaced or fill-pointered vectors as equivalent to the
  497. * corresponding simple vectors: I am pretty well obliged to do that for
  498. * strings and bitvectors so it seems polite to do the same for general
  499. * vectors (which are the only other ones I support!).
  500. */
  501. {
  502. unsigned32 r = 1, c;
  503. Lisp_Object nil, w;
  504. int32 type, len, offset = 0;
  505. unsigned char *data;
  506. Header ha;
  507. #ifdef CHECK_STACK
  508. if (check_stack(__FILE__,__LINE__))
  509. { err_printf("Stack too deep in hash calculation\n");
  510. my_exit(EXIT_FAILURE);
  511. }
  512. #endif
  513. for (;;)
  514. { switch (TAG_BITS & (int32)key)
  515. {
  516. case TAG_CONS:
  517. if (key == C_nil) return r;
  518. r = update_hash(r, hash_equal(qcar(key)));
  519. nil = C_nil;
  520. if (exception_pending()) return 0;
  521. key = qcdr(key);
  522. continue;
  523. case TAG_SYMBOL:
  524. if (key == C_nil) return r;
  525. key = get_pname(key);
  526. nil = C_nil;
  527. if (exception_pending()) return 0;
  528. r = update_hash(r, 1);
  529. /* Drop through, because the pname is a string */
  530. case TAG_VECTOR:
  531. { ha = vechdr(key);
  532. type = type_of_header(ha);
  533. len = length_of_header(ha) - 4; /* counts in bytes here */
  534. /*
  535. * First I will separate off the two important cases of strings and bitvectors
  536. */
  537. if (type == TYPE_STRING)
  538. { data = &ucelt(key, 0);
  539. goto hash_as_string;
  540. }
  541. #ifdef COMMON
  542. else if (header_of_bitvector(ha))
  543. { len = (len - 1)*8 + ((ha & 0x380) >> 7) + 1;
  544. offset = 0;
  545. data = &ucelt(key, 0);
  546. goto hash_as_bitvector;
  547. }
  548. #endif
  549. #ifdef COMMON
  550. /*
  551. * Common Lisp demands that pathname structures be compared and hashed in
  552. * a way that is expected to look at their contents. Here I just descend
  553. * all components of the pathname.
  554. */
  555. if (len == TYPE_STRUCTURE &&
  556. elt(key, 0) != pathname_symbol)
  557. return update_hash(r, (unsigned32)key);
  558. #endif
  559. /*
  560. * Now I will look for an array that is in fact just a vector.
  561. */
  562. if (type == TYPE_ARRAY)
  563. { w = elt(key, 0);
  564. if (w == string_char_sym) ha = 0;
  565. #ifdef COMMON
  566. else if (w == bit_symbol) ha = 1;
  567. #endif
  568. else ha = 2;
  569. w = elt(key, 1); /* List of dimensions */
  570. if (consp(w) && !consp(qcdr(w))) /* 1 dim or not? */
  571. { len = int_of_fixnum(qcar(w)); /* This is the length */
  572. w = elt(key, 5); /* Fill pointer */
  573. if (is_fixnum(w)) len = int_of_fixnum(w);
  574. w = elt(key, 3); /* displace adjustment */
  575. key = elt(key, 2); /* vector holding the data */
  576. switch (ha)
  577. {
  578. case 0: data = &ucelt(key, int_of_fixnum(w));
  579. goto hash_as_string;
  580. #ifdef COMMON
  581. case 1:
  582. data = &ucelt(key, 0);
  583. offset = int_of_fixnum(w);
  584. goto hash_as_bitvector;
  585. #endif
  586. default:
  587. /* /* The code here can CRASH if asked to hash a general array that
  588. * has been represented in chunks because it has over 32K elements.
  589. */
  590. ha = vechdr(key);
  591. offset = int_of_fixnum(w);
  592. break;
  593. }
  594. }
  595. }
  596. /*
  597. * Now in the case that I had a non-simple vector I have reset key to point
  598. * to the vector containing the true data, ha to the header of same and
  599. * len is the length that I want to use. offset is an offset into the vector.
  600. * For simple vectors all the same variables are set up (and offset will be
  601. * zero). All cases of strings and bitvectors should have been dealt with
  602. * so the only vectors containing binary are things like "file" structures,
  603. * and I do not expect them to hash portably.
  604. */
  605. if (vector_holds_binary(ha))
  606. return update_hash(r, (unsigned32)key);
  607. offset = 4*offset;
  608. if (is_mixed_header(ha))
  609. { while (len > 16)
  610. { unsigned32 ea = *(unsigned32 *)((char *)key +
  611. offset + len - TAG_VECTOR - 4);
  612. len -= 4;
  613. r = update_hash(r, ea);
  614. }
  615. }
  616. while ((len -= 4) != 0)
  617. { Lisp_Object ea =
  618. *((Lisp_Object *)((char *)key +
  619. offset + len - TAG_VECTOR));
  620. r = update_hash(r, hash_equal(ea));
  621. nil = C_nil;
  622. if (exception_pending()) return 0;
  623. }
  624. return r;
  625. }
  626. case TAG_ODDS:
  627. if (is_bps(key))
  628. { data = (unsigned char *)data_of_bps(key);
  629. /* I treat bytecode things as strings here */
  630. len = length_of_header(*(Header *)(data - 4));
  631. goto hash_as_string;
  632. }
  633. else return update_hash(r, (unsigned32)key);
  634. case TAG_BOXFLOAT:
  635. default:/* The default case here mainly covers numbers */
  636. return hash_eql(key);
  637. }
  638. hash_as_string:
  639. /* Here len is the length of the string data structure, excluding header */
  640. while (len > 0)
  641. { c = data[--len];
  642. r = update_hash(r, c);
  643. }
  644. return r;
  645. #ifdef COMMON
  646. hash_as_bitvector:
  647. /* here len is the number of bits to scan, and offset is a BIT offset */
  648. len += offset;
  649. while (len > offset)
  650. { len--;
  651. c = data[len >> 3] & (1 << (len & 7));
  652. if (c != 0) c = 1;
  653. r = update_hash(r, c);
  654. }
  655. return r;
  656. #endif
  657. }
  658. }
  659. static unsigned32 hash_equalp(Lisp_Object key)
  660. /*
  661. * This function is the one used hashing things under the Common Lisp
  662. * version of EQUALP, which descends vectors but not structs (except
  663. * pathnames), which is case-insensitive and which views numbers of
  664. * different types but similar values (eg 1 and 1.0) as EQUALP).
  665. */
  666. {
  667. unsigned32 r = 1, c;
  668. Lisp_Object nil, w;
  669. int32 type, len, offset = 0;
  670. unsigned char *data;
  671. Header ha;
  672. #ifdef CHECK_STACK
  673. if (check_stack(__FILE__,__LINE__))
  674. { err_printf("Stack too deep in hash calculation\n");
  675. my_exit(EXIT_FAILURE);
  676. }
  677. #endif
  678. for (;;)
  679. { switch (TAG_BITS & (int32)key)
  680. {
  681. case TAG_CONS:
  682. if (key == C_nil) return r;
  683. r = update_hash(r, hash_equalp(qcar(key)));
  684. nil = C_nil;
  685. if (exception_pending()) return 0;
  686. key = qcdr(key);
  687. continue;
  688. case TAG_SYMBOL:
  689. if (key == C_nil) return r;
  690. key = get_pname(key);
  691. nil = C_nil;
  692. if (exception_pending()) return 0;
  693. r = update_hash(r, 1);
  694. /* Drop through, because the pname is a string */
  695. case TAG_VECTOR:
  696. { ha = vechdr(key);
  697. type = type_of_header(ha);
  698. len = length_of_header(ha) - 4; /* counts in bytes here */
  699. /*
  700. * First I will separate off the two important cases of strings and bitvectors
  701. */
  702. if (type == TYPE_STRING)
  703. { data = &ucelt(key, 0);
  704. goto hash_as_string;
  705. }
  706. #ifdef COMMON
  707. else if (header_of_bitvector(ha))
  708. { len = (len - 1)*8 + ((ha & 0x380) >> 7) + 1;
  709. offset = 0;
  710. data = &ucelt(key, 0);
  711. goto hash_as_bitvector;
  712. }
  713. #endif
  714. #ifdef COMMON
  715. /*
  716. * Common Lisp demands that pathname structures be compared and hashed in
  717. * a way that is expected to look at their contents. Here I just descend
  718. * all components of the pathname. Other structs are not descended.
  719. */
  720. if (len == TYPE_STRUCTURE &&
  721. elt(key, 0) != pathname_symbol)
  722. return update_hash(r, (unsigned32)key);
  723. #endif
  724. /*
  725. * Now I will look for an array that is in fact just a vector.
  726. */
  727. if (type == TYPE_ARRAY)
  728. { w = elt(key, 0);
  729. if (w == string_char_sym) ha = 0;
  730. #ifdef COMMON
  731. else if (w == bit_symbol) ha = 1;
  732. #endif
  733. else ha = 2;
  734. w = elt(key, 1); /* List of dimensions */
  735. if (consp(w) && !consp(qcdr(w))) /* 1 dim or not? */
  736. { len = int_of_fixnum(qcar(w)); /* This is the length */
  737. w = elt(key, 5); /* Fill pointer */
  738. if (is_fixnum(w)) len = int_of_fixnum(w);
  739. w = elt(key, 3); /* displace adjustment */
  740. key = elt(key, 2); /* vector holding the data */
  741. switch (ha)
  742. {
  743. case 0: data = &ucelt(key, int_of_fixnum(w));
  744. goto hash_as_string;
  745. #ifdef COMMON
  746. case 1:
  747. data = &ucelt(key, 0);
  748. offset = int_of_fixnum(w);
  749. goto hash_as_bitvector;
  750. #endif
  751. default:
  752. /* /* Trouble if a general array with over 32K elements gets to here */
  753. ha = vechdr(key);
  754. offset = int_of_fixnum(w);
  755. break;
  756. }
  757. }
  758. }
  759. /*
  760. * Now in the case that I had a non-simple vector I have reset key to point
  761. * to the vector containing the true data, ha to the header of same and
  762. * len is the length that I want to use. offset is an offset into the vector.
  763. * For simple vectors all the same variables are set up (and offset will be
  764. * zero). All cases of strings and bitvectors should have been dealt with
  765. * so the only vectors containing binary are things like "file" structures,
  766. * and I do not expect them to hash portably.
  767. */
  768. if (vector_holds_binary(ha))
  769. return update_hash(r, (unsigned32)key);
  770. offset = 4*offset;
  771. if (is_mixed_header(ha))
  772. { while (len > 16)
  773. { unsigned32 ea = *(unsigned32 *)((char *)key +
  774. offset + len - TAG_VECTOR - 4);
  775. len -= 4;
  776. r = update_hash(r, ea);
  777. }
  778. }
  779. while ((len -= 4) != 0)
  780. { Lisp_Object ea =
  781. *((Lisp_Object *)((char *)key +
  782. offset + len - TAG_VECTOR));
  783. r = update_hash(r, hash_equalp(ea));
  784. nil = C_nil;
  785. if (exception_pending()) return 0;
  786. }
  787. return r;
  788. }
  789. case TAG_ODDS:
  790. if (is_bps(key))
  791. { data = (unsigned char *)data_of_bps(key);
  792. /* I treat bytecode things as strings here */
  793. len = length_of_header(*(Header *)(data - 4));
  794. goto hash_as_string;
  795. }
  796. else if (is_char(key))
  797. key = pack_char(0, 0, tolower(code_of_char(key)));
  798. return update_hash(r, (unsigned32)key);
  799. case TAG_BOXFLOAT:
  800. default:/* The default case here mainly covers numbers */
  801. if (is_float(key))
  802. { key = rational(key); /* painful expense */
  803. nil = C_nil;
  804. if (exception_pending()) return 0;
  805. }
  806. #ifdef COMMON
  807. if (is_numbers(key))
  808. { switch (type_of_header(numhdr(key)))
  809. {
  810. case TYPE_RATNUM:
  811. case TYPE_COMPLEX_NUM:
  812. return update_hash(hash_equalp(numerator(key)),
  813. hash_equalp(denominator(key)));
  814. default:
  815. break;
  816. }
  817. }
  818. #endif
  819. return hash_eql(key);
  820. }
  821. /*
  822. * Note that I scan the elements of a string or bitvector in the same order
  823. * that I would process a general vector of the same length, and I adjust the
  824. * vector contents to its generic representation before updating the hash
  825. * value. For strings I fold to lower case.
  826. */
  827. hash_as_string:
  828. /* Here len is the length of the string data structure, excluding header */
  829. while (len > 0)
  830. { c = tolower(data[--len]);
  831. r = update_hash(r, update_hash(1, pack_char(0, 0, c)));
  832. }
  833. return r;
  834. #ifdef COMMON
  835. hash_as_bitvector:
  836. /* here len is the number of bits to scan, and offset is a BIT offset */
  837. len += offset;
  838. while (len > offset)
  839. { len--;
  840. c = data[len >> 3] & (1 << (len & 7));
  841. if (c != 0) c = 1;
  842. r = update_hash(r, update_hash(1, fixnum_of_int(c)));
  843. }
  844. return r;
  845. #endif
  846. }
  847. }
  848. static unsigned32 hashcode;
  849. static int hashsize, hashoffset, hashgap;
  850. static CSLbool large_hash_table;
  851. #define words_in_hash_table(v) \
  852. (((large_hash_table ? int_of_fixnum(elt(v, 1)) : \
  853. length_of_header(vechdr(v))) - 8) >> 2)
  854. #define ht_elt(v, n) \
  855. (*(large_hash_table ? \
  856. &elt(elt((v), 2+(n)/HASH_CHUNK_WORDS), (n)%HASH_CHUNK_WORDS) : \
  857. &elt((v), (n))))
  858. Lisp_Object MS_CDECL Lget_hash(Lisp_Object nil, int nargs, ...)
  859. {
  860. int32 size, p, flavour = -1, hashstride, nprobes;
  861. va_list a;
  862. Lisp_Object v, key, tab, dflt;
  863. argcheck(nargs, 3, "gethash");
  864. va_start(a, nargs);
  865. key = va_arg(a, Lisp_Object);
  866. tab = va_arg(a, Lisp_Object);
  867. dflt = va_arg(a, Lisp_Object);
  868. va_end(a);
  869. if (!is_vector(tab) || type_of_header(vechdr(tab)) != TYPE_HASH)
  870. return aerror1("gethash", tab);
  871. v = elt(tab, 0);
  872. /* /* The code here needs to allow for user-specified hash functions */
  873. if (is_fixnum(v)) flavour = int_of_fixnum(v);
  874. switch (flavour)
  875. {
  876. default:
  877. return aerror1("gethash", cons(v, tab));
  878. case 0:
  879. hashcode = update_hash(1, (unsigned32)key);
  880. break;
  881. case 1:
  882. hashcode = hash_eql(key); /* can never fail */
  883. break;
  884. case 2:
  885. push3(key, tab, dflt);
  886. hashcode = hash_cl_equal(key, YES);
  887. pop3(dflt, tab, key);
  888. errexit();
  889. break;
  890. case 3:
  891. push3(key, tab, dflt);
  892. hashcode = hash_equal(key);
  893. pop3(dflt, tab, key);
  894. errexit();
  895. break;
  896. case 4:
  897. push3(key, tab, dflt);
  898. hashcode = hash_equalp(key);
  899. pop3(dflt, tab, key);
  900. errexit();
  901. break;
  902. }
  903. v = elt(tab, 4);
  904. large_hash_table = type_of_header(vechdr(v)) == TYPE_STRUCTURE;
  905. hashsize = size = words_in_hash_table(v);
  906. p = (hashcode % (unsigned32)(size >> 1)) << 1;
  907. /*
  908. * I want to take my single 32-bit hash value and produce a secondary
  909. * hash value that is a stride for the search. I can just take the
  910. * remainder by 1 less than the hash table size (and add 1 so I get
  911. * a non-zero stride).
  912. */
  913. hashstride = (1 + (hashcode % (unsigned32)((size >> 1)-1))) << 1;
  914. hashgap = -1;
  915. for (nprobes=0;nprobes<size;nprobes++)
  916. { Lisp_Object q = ht_elt(v, p+1);
  917. CSLbool cf;
  918. if (q == SPID_HASH0)
  919. { mv_2 = nil;
  920. work_0 = v;
  921. hashoffset = p;
  922. return nvalues(dflt, 2);
  923. }
  924. if (q == SPID_HASH1)
  925. { hashgap = p;
  926. cf = NO; /* vacated slot */
  927. }
  928. /* /* again user-specified hash functions need insertion here */
  929. else switch (flavour)
  930. {
  931. case 0: cf = (q == key);
  932. break;
  933. case 1: cf = eql(q, key);
  934. break;
  935. case 2: push4(key, tab, dflt, v);
  936. if (q == key) cf = YES;
  937. else cf = cl_equal(q, key);
  938. pop4(v, dflt, tab, key);
  939. errexit();
  940. break;
  941. case 3: push4(key, tab, dflt, v);
  942. if (q == key) cf = YES;
  943. else cf = equal(q, key);
  944. pop4(v, dflt, tab, key);
  945. errexit();
  946. break;
  947. case 4: push4(key, tab, dflt, v);
  948. if (q == key) cf = YES;
  949. else cf = equalp(q, key);
  950. pop4(v, dflt, tab, key);
  951. errexit();
  952. break;
  953. }
  954. if (cf)
  955. { mv_2 = lisp_true;
  956. work_0 = v;
  957. hashoffset = p;
  958. return nvalues(ht_elt(v, p+2), 2);
  959. }
  960. p = p + hashstride;
  961. if (p >= size) p = p - size;
  962. }
  963. return aerror("too many probes in hash look-up");
  964. }
  965. static void reinsert_hash(Lisp_Object v, int32 size, int32 flavour,
  966. Lisp_Object key, Lisp_Object val)
  967. {
  968. int32 p;
  969. unsigned32 hcode, hstride;
  970. Lisp_Object nil = C_nil;
  971. switch (flavour)
  972. {
  973. case 0:
  974. hcode = update_hash(1, (unsigned32)key);
  975. break;
  976. case 1:
  977. hcode = hash_eql(key); /* can never fail */
  978. break;
  979. case 2:
  980. push3(key, v, val);
  981. hcode = hash_cl_equal(key, YES);
  982. pop3(val, v, key);
  983. errexitv();
  984. break;
  985. case 3:
  986. push3(key, v, val);
  987. hcode = hash_equal(key);
  988. pop3(val, v, key);
  989. errexitv();
  990. break;
  991. case 4:
  992. push3(key, v, val);
  993. hcode = hash_equalp(key);
  994. pop3(val, v, key);
  995. errexitv();
  996. break;
  997. }
  998. p = (hcode % (unsigned32)(size >> 1)) << 1;
  999. hstride = (1 + (hcode % (unsigned32)((size >> 1)-1))) << 1;
  1000. /*
  1001. * When I re-insert the item into the table life is especially easy -
  1002. * I know it is not there already and I know I will be able to find a
  1003. * gap to put it in! So I just have to look for a gap - no comparisons
  1004. * are needed.
  1005. */
  1006. large_hash_table = type_of_header(vechdr(v)) == TYPE_STRUCTURE;
  1007. for (;;)
  1008. { Lisp_Object q = ht_elt(v, p+1);
  1009. if (q == SPID_HASH0 || q == SPID_HASH1)
  1010. { ht_elt(v, p+1) = key;
  1011. ht_elt(v, p+2) = val;
  1012. return;
  1013. }
  1014. p = p + hstride;
  1015. if (p >= size) p = p - size;
  1016. }
  1017. }
  1018. #define REHASH_CYCLES 2
  1019. #define REHASH_AT_ONE_GO 64
  1020. void rehash_this_table(Lisp_Object v)
  1021. /*
  1022. * Hash tables where the hash function depends on absolute memory addresses
  1023. * will sometimes need rehashing - I do this by removing items from the
  1024. * table one at a time and re-inserting them. This does not guarantee that
  1025. * the table is left in a perfect state, but for modest loading will be
  1026. * adequate. I reason that if I extract 64 (say) items at a time and
  1027. * then re-insert them then (especially for smallish tables) I have a
  1028. * better chance of things ending up in the ideal place. The problem is that
  1029. * items that have not yet been moved may be sitting in places where a
  1030. * re-hashed item ought to go. The effect will be that the newly re-inserted
  1031. * item sees a clash and moves to a second-choice position. When the other
  1032. * item is (later on) processed it will then vacate the place I would have
  1033. * liked to use, leaving a "tombstone" marker behind. If at the end of all
  1034. * re-hashing there are too many tombstones left around lookup performance
  1035. * in the table will degrade. I attempt to counter this effect by performing
  1036. * the whole re-hashing procedure several times. But I have neither analysed
  1037. * nore measured what happens! I will do so if practical applications show
  1038. * up serious trouble here.
  1039. */
  1040. {
  1041. int32 size, i, j, flavour, many;
  1042. CSLbool old_large = large_hash_table;
  1043. Lisp_Object pendkey[REHASH_AT_ONE_GO], pendval[REHASH_AT_ONE_GO];
  1044. flavour = int_of_fixnum(elt(v, 0)); /* Done this way always */
  1045. large_hash_table = type_of_header(vechdr(v)) == TYPE_STRUCTURE;
  1046. size = words_in_hash_table(v);
  1047. /*
  1048. * The cycle count here is something I may want to experiment with.
  1049. */
  1050. for (i=0; i<REHASH_CYCLES; i++)
  1051. {
  1052. /*
  1053. * Change all slots in the table that are empty just because something has
  1054. * been deleted to indicate that they are truly not in use. This makes some
  1055. * items inaccessible by normal hash searches (because a void will be placed
  1056. * earlier than them on a search trajectory) but this does not matter because
  1057. * everything is about to be taken out of the table and reinserted properly.
  1058. */
  1059. for (j=0; j<size; j+=2)
  1060. if (ht_elt(v, j+1) == SPID_HASH1) ht_elt(v, j+1) = SPID_HASH0;
  1061. many = 0;
  1062. for (j=0; j<size; j+=2)
  1063. { Lisp_Object key = ht_elt(v, j+1), val = ht_elt(v, j+2);
  1064. if (key == SPID_HASH0 || key == SPID_HASH1) continue;
  1065. pendkey[many] = key; pendval[many++] = val;
  1066. ht_elt(v, j+1) = SPID_HASH1; ht_elt(v, j+2) = SPID_HASH0;
  1067. if (many >= REHASH_AT_ONE_GO)
  1068. { while (many > 0)
  1069. { many--;
  1070. reinsert_hash(v, size, flavour,
  1071. pendkey[many], pendval[many]);
  1072. }
  1073. }
  1074. }
  1075. while (--many >= 0)
  1076. reinsert_hash(v, size, flavour, pendkey[many], pendval[many]);
  1077. }
  1078. large_hash_table = old_large;
  1079. }
  1080. Lisp_Object Lmaphash(Lisp_Object nil, Lisp_Object fn, Lisp_Object tab)
  1081. /*
  1082. * There is a big worry here if the table is re-hashed because of
  1083. * a garbage collection while I am in the middle of things. To
  1084. * avoid utter shambles I will make a copy of the vector early
  1085. * on and work from that.
  1086. */
  1087. { int32 size, i;
  1088. Lisp_Object v, v1;
  1089. if (!is_vector(tab) || type_of_header(vechdr(tab)) != TYPE_HASH)
  1090. return aerror1("maphash", tab);
  1091. v = elt(tab, 4);
  1092. large_hash_table = type_of_header(vechdr(v)) == TYPE_STRUCTURE;
  1093. size = words_in_hash_table(v)*4+8;
  1094. push2(fn, tab);
  1095. v1 = get_hash_vector(size);
  1096. pop2(tab, fn);
  1097. v = elt(tab, 4);
  1098. size = (size - 4) >> 2;
  1099. for (i=0; i<size; i++) ht_elt(v1, i) = ht_elt(v, i);
  1100. for (i=1; i<size; i+=2)
  1101. { Lisp_Object key = ht_elt(v1, i), val = ht_elt(v1, i+1);
  1102. if (key == SPID_HASH0 || key == SPID_HASH1) continue;
  1103. push2(v1, fn);
  1104. Lapply2(nil, 3, fn, key, val);
  1105. pop2(fn, v1);
  1106. errexit();
  1107. }
  1108. return onevalue(nil);
  1109. }
  1110. Lisp_Object Lhashcontents(Lisp_Object nil, Lisp_Object tab)
  1111. /*
  1112. * There is a big worry here if the table is re-hashed because of
  1113. * a garbage collection while I am in the middle of things. To
  1114. * avoid utter shambles I will restart if a GC happens while I
  1115. * am unfolding the hash table. And fail if that happens twice
  1116. * in a row.
  1117. */
  1118. {
  1119. int32 size, i, ogcnum;
  1120. int n_gc = 0;
  1121. Lisp_Object v, r;
  1122. if (!is_vector(tab) || type_of_header(vechdr(tab)) != TYPE_HASH)
  1123. return aerror1("hashcontents", tab);
  1124. v = elt(tab, 4);
  1125. large_hash_table = type_of_header(vechdr(v)) == TYPE_STRUCTURE;
  1126. size = words_in_hash_table(v)*4+8;
  1127. size = (size - 4) >> 2;
  1128. restart:
  1129. r = nil;
  1130. if (++n_gc > 2) return aerror("hashcontents");
  1131. ogcnum = gc_number;
  1132. for (i=1; i<size; i+=2)
  1133. { Lisp_Object k1 = ht_elt(v, i), v1 = ht_elt(v, i+1);
  1134. if (k1 == SPID_HASH0 || k1 == SPID_HASH1) continue;
  1135. push(v);
  1136. r = acons(k1, v1, r);
  1137. pop(v);
  1138. errexit();
  1139. if (gc_number != ogcnum) goto restart;
  1140. }
  1141. return onevalue(r);
  1142. }
  1143. Lisp_Object Lget_hash_1(Lisp_Object nil, Lisp_Object key)
  1144. {
  1145. #ifdef COMMON
  1146. return Lget_hash(nil, 3, key, sys_hash_table, nil);
  1147. #else
  1148. /*
  1149. * The definition implemented here is as required by Reduce in
  1150. * the file matrix.red... In the long term this is unsatisfactory.
  1151. */
  1152. Lisp_Object r;
  1153. push(key);
  1154. r = Lget_hash(nil, 3, key, sys_hash_table, nil);
  1155. pop(key);
  1156. errexit();
  1157. if (mv_2 != nil)
  1158. { r = cons(key, r);
  1159. errexit();
  1160. }
  1161. return onevalue(r);
  1162. #endif
  1163. }
  1164. Lisp_Object Lget_hash_2(Lisp_Object nil, Lisp_Object key, Lisp_Object tab)
  1165. {
  1166. return Lget_hash(nil, 3, key, tab, nil);
  1167. }
  1168. Lisp_Object MS_CDECL Lput_hash(Lisp_Object nil, int nargs, ...)
  1169. {
  1170. va_list a;
  1171. Lisp_Object key, tab, val;
  1172. va_start(a, nargs);
  1173. key = va_arg(a, Lisp_Object);
  1174. tab = va_arg(a, Lisp_Object);
  1175. val = va_arg(a, Lisp_Object);
  1176. va_end(a);
  1177. argcheck(nargs, 3, "puthash");
  1178. push3(key, tab, val);
  1179. Lget_hash(nil, 3, key, tab, nil);
  1180. pop3(val, tab, key);
  1181. errexit();
  1182. if (mv_2 == nil) /* Not found, thus I point at an empty slot */
  1183. { if (hashgap >= 0) hashoffset = hashgap;
  1184. ht_elt(work_0, hashoffset+1) = key;
  1185. ht_elt(work_0, hashoffset+2) = val;
  1186. elt(tab, 1) += 0x10; /* increment count of used entries */
  1187. if (elt(tab, 1) > elt(tab, 2))
  1188. { Lisp_Object size = elt(tab, 2),
  1189. growth = elt(tab, 3),
  1190. newhash, v;
  1191. int32 isize = int_of_fixnum(size), i;
  1192. push2(tab, val);
  1193. if (is_fixnum(growth))
  1194. { int32 w1 = int_of_fixnum(growth);
  1195. if (w1 > 0) isize = isize + w1;
  1196. else isize = isize + (isize/2);
  1197. }
  1198. else if (is_float(growth))
  1199. { double w2 = float_of_number(growth);
  1200. int32 newsize = isize;
  1201. if (1.0 < w2 && w2 < 10.0) newsize = (int32)(w2 * (double)isize);
  1202. if (newsize > isize) isize = newsize;
  1203. else isize = isize + (isize/2);
  1204. }
  1205. else isize = isize + (isize/2);
  1206. /*
  1207. * NB - Lmkhash() does not disturb large_hash_table, so I can still
  1208. * access the old table happily even after this call...
  1209. */
  1210. newhash = Lmkhash(nil, 3, fixnum_of_int(isize),
  1211. elt(tab, 0), growth);
  1212. pop2(val, tab);
  1213. errexit();
  1214. v = elt(tab, 4);
  1215. for (i=0; i<=4; i++) elt(tab, i) = elt(newhash, i);
  1216. large_hash_table = type_of_header(vechdr(v)) == TYPE_STRUCTURE;
  1217. isize = words_in_hash_table(v);
  1218. for (i=0; i<isize; i+=2)
  1219. { Lisp_Object key1 = ht_elt(v, i+1), val1 = ht_elt(v, i+2);
  1220. CSLbool large = large_hash_table;
  1221. if (key1 == SPID_HASH0 || key1 == SPID_HASH1) continue;
  1222. /*
  1223. * NB the new hash table is big enough to hold all the data that was in the
  1224. * old one, so inserting stuff into it can not cause a (recursive)
  1225. * enlargement here....
  1226. */
  1227. push3(v, tab, val);
  1228. Lput_hash(nil, 3, key1, tab, val1);
  1229. pop3(val, tab, v);
  1230. large_hash_table = large; /* Maybe scrabled by put_hash */
  1231. }
  1232. }
  1233. return onevalue(val);
  1234. }
  1235. else
  1236. { ht_elt(work_0, hashoffset+2) = val;
  1237. return onevalue(val);
  1238. }
  1239. }
  1240. Lisp_Object Lput_hash_2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  1241. {
  1242. return Lput_hash(nil, 3, a, sys_hash_table, b);
  1243. }
  1244. Lisp_Object Lrem_hash(Lisp_Object nil, Lisp_Object key, Lisp_Object tab)
  1245. {
  1246. push2(key, tab);
  1247. Lget_hash(nil, 3, key, tab, nil);
  1248. pop2(tab, key);
  1249. errexit();
  1250. if (mv_2 == nil) return onevalue(nil);
  1251. else
  1252. { ht_elt(work_0, hashoffset+1) = SPID_HASH1;
  1253. ht_elt(work_0, hashoffset+2) = SPID_HASH0;
  1254. elt(tab, 1) -= 0x10;
  1255. /*
  1256. * Some folk would believe that if the table shrank too much I should
  1257. * shrink it, or at the very least re-hash it.
  1258. */
  1259. return onevalue(lisp_true);
  1260. }
  1261. }
  1262. Lisp_Object Lrem_hash_1(Lisp_Object nil, Lisp_Object a)
  1263. {
  1264. return Lrem_hash(nil, a, sys_hash_table);
  1265. }
  1266. Lisp_Object Lclr_hash(Lisp_Object nil, Lisp_Object tab)
  1267. {
  1268. Lisp_Object v;
  1269. int32 size, i;
  1270. CSL_IGNORE(nil);
  1271. if (!is_vector(tab) ||
  1272. type_of_header(vechdr(tab)) != TYPE_HASH)
  1273. return aerror1("clrhash", tab);
  1274. elt(tab, 1) = fixnum_of_int(0);
  1275. v = elt(tab, 4);
  1276. large_hash_table = type_of_header(vechdr(v)) == TYPE_STRUCTURE;
  1277. size = words_in_hash_table(v);
  1278. for (i=1; i<size; i++) ht_elt(v, i) = SPID_HASH0;
  1279. return tab;
  1280. }
  1281. Lisp_Object MS_CDECL Lclr_hash_0(Lisp_Object nil, int nargs, ...)
  1282. {
  1283. argcheck(nargs, 0, "clrhash");
  1284. return Lclr_hash(nil, sys_hash_table);
  1285. }
  1286. Lisp_Object Lsxhash(Lisp_Object nil, Lisp_Object key)
  1287. {
  1288. unsigned32 h = hash_cl_equal(key, YES);
  1289. errexit();
  1290. h = (h ^ (h >> 16)) & 0x03ffffff; /* ensure it will be a positive fixnum */
  1291. return onevalue(fixnum_of_int(h));
  1292. }
  1293. Lisp_Object Leqlhash(Lisp_Object nil, Lisp_Object key)
  1294. {
  1295. unsigned32 h = hash_cl_equal(key, NO);
  1296. errexit();
  1297. h = (h ^ (h >> 16)) & 0x03ffffff; /* ensure it will be a positive fixnum */
  1298. return onevalue(fixnum_of_int(h));
  1299. }
  1300. #ifdef COMMON
  1301. Lisp_Object Lhash_flavour(Lisp_Object nil, Lisp_Object tab)
  1302. {
  1303. Lisp_Object v,flavour = fixnum_of_int(-1);
  1304. if (!is_vector(tab) || type_of_header(vechdr(tab)) != TYPE_HASH)
  1305. return aerror1("hash_flavour", tab);
  1306. v = elt(tab, 0);
  1307. /* The code here needs to allow for user-specified hash functions */
  1308. if (is_fixnum(v)) flavour = v;
  1309. return onevalue(flavour);
  1310. }
  1311. #endif
  1312. Lisp_Object MS_CDECL Lputv(Lisp_Object nil, int nargs, ...)
  1313. {
  1314. Header h;
  1315. va_list a;
  1316. int32 n1, hl;
  1317. Lisp_Object v, n, x;
  1318. argcheck(nargs, 3, "putv");
  1319. va_start(a, nargs);
  1320. v = va_arg(a, Lisp_Object);
  1321. n = va_arg(a, Lisp_Object);
  1322. x = va_arg(a, Lisp_Object);
  1323. va_end(a);
  1324. CSL_IGNORE(nil);
  1325. if (!is_vector(v) || vector_holds_binary(h = vechdr(v)))
  1326. return aerror1("putv", v);
  1327. else if (!is_fixnum(n)) return aerror1("putv offset not fixnum", n);
  1328. hl = (length_of_header(h) - 4) >> 2;
  1329. n1 = int_of_fixnum(n);
  1330. if (n1 < 0 || n1 >= hl) return aerror1("putv index range", n);
  1331. elt(v, n1) = x;
  1332. return onevalue(x);
  1333. }
  1334. Lisp_Object Lgetv(Lisp_Object nil, Lisp_Object v, Lisp_Object n)
  1335. {
  1336. Header h;
  1337. int32 n1, hl;
  1338. CSL_IGNORE(nil);
  1339. if (!is_vector(v) || vector_holds_binary(h = vechdr(v)))
  1340. return aerror1("getv", v);
  1341. else if (!is_fixnum(n)) return aerror1("getv offset not fixnum", n);
  1342. hl = (length_of_header(h) - 4) >> 2;
  1343. n1 = int_of_fixnum(n);
  1344. if (n1 < 0 || n1 >= hl) return aerror1("getv index range", n);
  1345. else return onevalue(elt(v, n1));
  1346. }
  1347. /*
  1348. * Here I make a (simple) string.
  1349. */
  1350. Lisp_Object Lsmkvect(Lisp_Object nil, Lisp_Object n)
  1351. {
  1352. Lisp_Object w;
  1353. int32 nn;
  1354. if (!is_fixnum(n) || (int32)n<0) return aerror1("make-simple-string", n);
  1355. nn = int_of_fixnum(n);
  1356. w = getvector(TAG_VECTOR, TYPE_STRING, nn+4);
  1357. errexit();
  1358. nn = (int32)doubleword_align_up(nn+4);
  1359. while (nn > 4)
  1360. { nn -= 4;
  1361. *(int32 *)((char *)w - TAG_VECTOR + nn) = 0;
  1362. }
  1363. return onevalue(w);
  1364. }
  1365. /*
  1366. * Here I make a vector capable of holding 8-bit binary integers.
  1367. */
  1368. Lisp_Object Lmkvect8(Lisp_Object nil, Lisp_Object n)
  1369. {
  1370. Lisp_Object w;
  1371. int32 nn;
  1372. if (!is_fixnum(n) || (int32)n<0) return aerror1("mkvect8", n);
  1373. nn = int_of_fixnum(n);
  1374. w = getvector(TAG_VECTOR, TYPE_VEC8, nn+4);
  1375. errexit();
  1376. nn = (int32)doubleword_align_up(nn+4);
  1377. while (nn > 4)
  1378. { nn -= 4;
  1379. *(int32 *)((char *)w - TAG_VECTOR + nn) = 0;
  1380. }
  1381. return onevalue(w);
  1382. }
  1383. /*
  1384. * Here I make a vector capable of holding 16-bit binary integers.
  1385. */
  1386. Lisp_Object Lmkvect16(Lisp_Object nil, Lisp_Object n)
  1387. {
  1388. Lisp_Object w;
  1389. int32 nn;
  1390. if (!is_fixnum(n) || (int32)n<0) return aerror1("mkvect16", n);
  1391. nn = 2*int_of_fixnum(n);
  1392. w = getvector(TAG_VECTOR, TYPE_VEC16, nn+4);
  1393. errexit();
  1394. nn = (int32)doubleword_align_up(nn+4);
  1395. while (nn > 4)
  1396. { nn -= 4;
  1397. *(int32 *)((char *)w - TAG_VECTOR + nn) = 0;
  1398. }
  1399. return onevalue(w);
  1400. }
  1401. /*
  1402. * Here I make a vector capable of holding 32-bit binary integers.
  1403. */
  1404. Lisp_Object Lmkvect32(Lisp_Object nil, Lisp_Object n)
  1405. {
  1406. Lisp_Object w;
  1407. int32 nn;
  1408. if (!is_fixnum(n) || (int32)n<0) return aerror1("mkvect32", n);
  1409. nn = 4*int_of_fixnum(n);
  1410. w = getvector(TAG_VECTOR, TYPE_VEC32, nn+4);
  1411. errexit();
  1412. nn = (int32)doubleword_align_up(nn+4);
  1413. while (nn > 4)
  1414. { nn -= 4;
  1415. *(int32 *)((char *)w - TAG_VECTOR + nn) = 0;
  1416. }
  1417. return onevalue(w);
  1418. }
  1419. /*
  1420. * Here I make a vector capable of holding 32-bit floats.
  1421. */
  1422. Lisp_Object Lmkfvect32(Lisp_Object nil, Lisp_Object n)
  1423. {
  1424. Lisp_Object w;
  1425. int32 nn;
  1426. if (!is_fixnum(n) || (int32)n<0) return aerror1("mkfvect32", n);
  1427. nn = 4*int_of_fixnum(n);
  1428. w = getvector(TAG_VECTOR, TYPE_FLOAT32, nn+4);
  1429. errexit();
  1430. nn = (int32)doubleword_align_up(nn+4);
  1431. while (nn > 4)
  1432. { nn -= 4;
  1433. *(float *)((char *)w - TAG_VECTOR + nn) = (float)0.0;
  1434. }
  1435. return onevalue(w);
  1436. }
  1437. /*
  1438. * Here I make a vector capable of holding 64-bit floats.
  1439. */
  1440. Lisp_Object Lmkfvect64(Lisp_Object nil, Lisp_Object n)
  1441. {
  1442. Lisp_Object w;
  1443. int32 nn;
  1444. if (!is_fixnum(n) || (int32)n<0) return aerror1("mkfvect64", n);
  1445. nn = 4 + 8*int_of_fixnum(n);
  1446. w = getvector(TAG_VECTOR, TYPE_FLOAT64, nn+4);
  1447. errexit();
  1448. nn = (int32)doubleword_align_up(nn+4);
  1449. while (nn > 8)
  1450. { nn -= 8;
  1451. *(double *)((char *)w - TAG_VECTOR + nn) = 0.0;
  1452. }
  1453. return onevalue(w);
  1454. }
  1455. Lisp_Object simplify_string(Lisp_Object s)
  1456. /*
  1457. * s is supposed to be a string of some sort - return a simple string
  1458. * with the same contents. This is horrid and messy, and relies on
  1459. * a load of stuff coded elsewhere in Lisp: is is coded here in C
  1460. * despite that because despite the breaches of modularity that are involved
  1461. * doing so seems to make bootstrapping easier.
  1462. */
  1463. {
  1464. Header h;
  1465. Lisp_Object w, nil = C_nil, h1;
  1466. int32 i, n = 0;
  1467. if (!is_vector(s)) return aerror("simplify-string");
  1468. h = vechdr(s);
  1469. if (type_of_header(h) == TYPE_STRING)
  1470. return onevalue(s); /* Already simple */
  1471. if (type_of_header(h) != TYPE_ARRAY) return aerror("simplify-string");
  1472. h1 = elt(s, 0);
  1473. if (h1 != string_char_sym) return aerror("simplify-string");
  1474. h1 = elt(s, 1); /* Dimension list */
  1475. if (!consp(h1)) return aerror("simplify-string");
  1476. n = int_of_fixnum(qcar(h1)); /* Look at size involved */
  1477. h1 = elt(s, 5); /* Fill pointer */
  1478. if (is_fixnum(h1)) n = int_of_fixnum(h1);
  1479. stackcheck1(0, s);
  1480. nil = C_nil;
  1481. push(s);
  1482. w = getvector(TAG_VECTOR, TYPE_STRING, n+4);
  1483. pop(s);
  1484. errexit();
  1485. i = (int32)doubleword_align_up(n+4);
  1486. while (i > 4) /* pre-fill target vector with zero */
  1487. { i -= 4;
  1488. *(int32 *)((char *)w - TAG_VECTOR + i) = 0;
  1489. }
  1490. h1 = elt(s, 3);
  1491. h = int_of_fixnum(h1); /* Displace adjustment */
  1492. s = elt(s, 2);
  1493. for (i=0; i<n; i++) celt(w, i) = celt(s, i+h);
  1494. return onevalue(w);
  1495. }
  1496. Lisp_Object MS_CDECL Lsputv(Lisp_Object nil, int nargs, ...)
  1497. {
  1498. Header h;
  1499. va_list a;
  1500. int32 vx, n1, hl;
  1501. Lisp_Object v, n, x;
  1502. argcheck(nargs, 3, "sputv");
  1503. va_start(a, nargs);
  1504. v = va_arg(a, Lisp_Object);
  1505. n = va_arg(a, Lisp_Object);
  1506. x = va_arg(a, Lisp_Object);
  1507. va_end(a);
  1508. CSL_IGNORE(nil);
  1509. if (!is_vector(v) || type_of_header(h = vechdr(v)) != TYPE_STRING)
  1510. return aerror1("putv-char", v);
  1511. else if (!is_fixnum(n)) return aerror1("putv-char", n);
  1512. else if (is_fixnum(x)) vx = int_of_fixnum(x);
  1513. else if (is_char(x)) vx = code_of_char(x);
  1514. else return aerror1("putv-char contents", x);
  1515. hl = length_of_header(h) - 4;
  1516. n1 = int_of_fixnum(n);
  1517. if (n1 < 0 || n1 >= hl) return aerror1("putv-char", n);
  1518. #ifdef Kanji
  1519. if (iswchar((int)vx)
  1520. { if (n1 == hl-1) return aerror1("putv-char", n);
  1521. celt(v, n1) = vx >> 8;
  1522. celt(v, n1+1) = vx;
  1523. }
  1524. else celt(v, n1) = vx;
  1525. #else
  1526. celt(v, n1) = vx;
  1527. #endif
  1528. return onevalue(x);
  1529. }
  1530. Lisp_Object Lbpsupbv(Lisp_Object nil, Lisp_Object v)
  1531. {
  1532. Header h;
  1533. int32 n;
  1534. CSL_IGNORE(nil);
  1535. if (!(is_bps(v))) return aerror1("bps-upbv", v);
  1536. h = *(Header *)((char *)data_of_bps(v) - 4);
  1537. n = length_of_header(h) - 4;
  1538. return onevalue(fixnum_of_int(n-1));
  1539. }
  1540. Lisp_Object MS_CDECL Lbpsputv(Lisp_Object nil, int nargs, ...)
  1541. {
  1542. Header h;
  1543. va_list a;
  1544. int32 n1, hl;
  1545. Lisp_Object v, n, x;
  1546. argcheck(nargs, 3, "bpsputv");
  1547. va_start(a, nargs);
  1548. v = va_arg(a, Lisp_Object);
  1549. n = va_arg(a, Lisp_Object);
  1550. x = va_arg(a, Lisp_Object);
  1551. va_end(a);
  1552. CSL_IGNORE(nil);
  1553. if (!is_bps(v)) return aerror1("bpsputv", v);
  1554. else if (!is_fixnum(n)) return aerror1("bps-putv", n);
  1555. else if (!is_fixnum(x)) return aerror1("bps-putv contents", x);
  1556. h = *(Header *)((char *)data_of_bps(v) - 4);
  1557. hl = length_of_header(h) - 4;
  1558. n1 = int_of_fixnum(n);
  1559. if (n1 < 0 || n1 >= hl) return aerror1("bps-putv", n);
  1560. *((char *)data_of_bps(v) + n1) = (int)int_of_fixnum(x);
  1561. return onevalue(x);
  1562. }
  1563. /*
  1564. * To make this function Standard Lisp Friendly it will return as its
  1565. * value a SYMBOL. This is because unadorned character objects are not
  1566. * really part of Standard Lisp. For cases where you want to character
  1567. * code I have introduced a function scharn which is almost exactly the
  1568. * same except that it returns an integer character code not a symbol.
  1569. */
  1570. Lisp_Object Lsgetv(Lisp_Object nil, Lisp_Object v, Lisp_Object n)
  1571. {
  1572. Header h;
  1573. int w;
  1574. int32 n1, hl;
  1575. CSL_IGNORE(nil);
  1576. if (!is_vector(v) || type_of_header(h = vechdr(v)) != TYPE_STRING)
  1577. return aerror1("schar", v);
  1578. else if (!is_fixnum(n)) return aerror1("schar", n);
  1579. hl = length_of_header(h) - 4;
  1580. n1 = int_of_fixnum(n);
  1581. if (n1 < 0 || n1 >= hl) return aerror1("schar", n);
  1582. w = celt(v, n1);
  1583. #ifdef Kanji
  1584. if (n1 < hl-1 && is2byte(w)) w = (w << 8) + celt(v, n+1);
  1585. #endif
  1586. #ifdef COMMON
  1587. return onevalue(pack_char(0, 0, w)); /* NB 16-bite chars OK here */
  1588. #else
  1589. #ifdef Kanji
  1590. if (w & 0xff00)
  1591. { celt(boffo, 0) = w >> 8;
  1592. celt(boffo, 1) = w;
  1593. /*
  1594. * If it is an extended character I will look up a symbol for it each time.
  1595. * this will make processing extended characters distinctly more expensive
  1596. * than working with the basic ASCII ones, but I hope it will still be
  1597. * acceptable.
  1598. */
  1599. n = iintern(boffo, 2, lisp_package, 0);
  1600. errexit();
  1601. return onevalue(n);
  1602. }
  1603. #endif
  1604. /*
  1605. * For 8-bit characters I keep a table of ready-interned Lisp symbols.
  1606. */
  1607. n = elt(charvec, w & 0xff);
  1608. if (n == nil)
  1609. { celt(boffo, 0) = w;
  1610. n = iintern(boffo, 1, lisp_package, 0);
  1611. errexit();
  1612. elt(charvec, w & 0xff) = n;
  1613. }
  1614. return onevalue(n);
  1615. #endif
  1616. }
  1617. Lisp_Object Lsgetvn(Lisp_Object nil, Lisp_Object v, Lisp_Object n)
  1618. {
  1619. Header h;
  1620. int w;
  1621. int32 n1, hl;
  1622. CSL_IGNORE(nil);
  1623. if (!is_vector(v) || type_of_header(h = vechdr(v)) != TYPE_STRING)
  1624. return aerror1("scharn", v);
  1625. else if (!is_fixnum(n)) return aerror1("scharn", n);
  1626. hl = length_of_header(h) - 4;
  1627. n1 = int_of_fixnum(n);
  1628. if (n1 < 0 || n1 >= hl) return aerror1("scharn", n);
  1629. w = celt(v, n1);
  1630. #ifdef Kanji
  1631. if (n1 < hl-1 && is2byte(w)) w = (w << 8) + celt(v, n+1);
  1632. #endif
  1633. return onevalue(fixnum_of_int(w));
  1634. }
  1635. Lisp_Object Lbytegetv(Lisp_Object nil, Lisp_Object v, Lisp_Object n)
  1636. {
  1637. Header h;
  1638. int w;
  1639. int32 n1, hl;
  1640. CSL_IGNORE(nil);
  1641. if (!is_vector(v) || type_of_header(h = vechdr(v)) != TYPE_STRING)
  1642. return aerror1("byte-getv", v);
  1643. else if (!is_fixnum(n)) return aerror1("byte-getv", n);
  1644. hl = length_of_header(h) - 4;
  1645. n1 = int_of_fixnum(n);
  1646. if (n1 < 0 || n1 >= hl) return aerror1("byte-getv", n);
  1647. w = ucelt(v, n1);
  1648. return onevalue(fixnum_of_int(w));
  1649. }
  1650. Lisp_Object Lbpsgetv(Lisp_Object nil, Lisp_Object v, Lisp_Object n)
  1651. {
  1652. Header h;
  1653. int32 n1, hl;
  1654. CSL_IGNORE(nil);
  1655. if (!is_bps(v)) return aerror1("bps-getv", v);
  1656. else if (!is_fixnum(n)) return aerror1("bps-getv", n);
  1657. h = *(Header *)((char *)data_of_bps(v) - 4);
  1658. hl = length_of_header(h) - 4;
  1659. n1 = int_of_fixnum(n);
  1660. if (n1 < 0 || n1 >= hl) return aerror1("bps-getv", n);
  1661. n1 = *((char *)data_of_bps(v) + n1);
  1662. return onevalue(fixnum_of_int(n1 & 0xff));
  1663. }
  1664. /*
  1665. * native-putv and native-getv have an optional trailing argument that
  1666. * should have the value 1, 2 or 4 to indicate the number of bytes to be
  1667. * transferred.
  1668. */
  1669. Lisp_Object MS_CDECL Lnativeputv(Lisp_Object nil, int nargs, ...)
  1670. {
  1671. va_list a;
  1672. int32 p, o, v32, width;
  1673. Lisp_Object v, n, x, w;
  1674. if (nargs != 4)
  1675. { argcheck(nargs, 3, "native-putv");
  1676. }
  1677. va_start(a, nargs);
  1678. v = va_arg(a, Lisp_Object);
  1679. n = va_arg(a, Lisp_Object);
  1680. x = va_arg(a, Lisp_Object);
  1681. if (nargs == 4) w = va_arg(a, Lisp_Object);
  1682. else w = fixnum_of_int(1);
  1683. va_end(a);
  1684. CSL_IGNORE(nil);
  1685. if (!consp(v) ||
  1686. !is_fixnum(qcar(v)) ||
  1687. !is_fixnum(qcdr(v)) ||
  1688. (p = int_of_fixnum(qcar(v))) < 0 ||
  1689. p > native_pages_count) return aerror1("native-putv", v);
  1690. else if (!is_fixnum(n)) return aerror1("native-putv", n);
  1691. else if (!is_fixnum(x) &&
  1692. (!is_numbers(x) || !is_bignum(x)))
  1693. return aerror1("native-putv contents", x);
  1694. else if (!is_fixnum(w)) return aerror1("native-putv width", w);
  1695. width = int_of_fixnum(w);
  1696. o = int_of_fixnum(qcdr(v)) + int_of_fixnum(n);
  1697. if (o < 0 || o >= CSL_PAGE_SIZE) return aerror1("native-putv", n);
  1698. p = (int32)native_pages[p];
  1699. p = doubleword_align_up(p);
  1700. v32 = thirty_two_bits(x);
  1701. switch (width)
  1702. {
  1703. default:
  1704. return aerror1("native-putv width", w);
  1705. case 1:
  1706. *((char *)p + o) = (int)int_of_fixnum(x);
  1707. break;
  1708. #ifdef ADDRESS_64
  1709. case 2:
  1710. /*
  1711. * NOTE that I access the memory here as an array of 16-bit or 32-bit
  1712. * values and I do not do anything to adjust for the order of bytes in
  1713. * the word. Thus the effect of mixtures of 1, 2 and 4 byte operations on
  1714. * native code space will be system dependent. But my intent at present is
  1715. * that native code is always to be generated on ths machine on which it
  1716. * will run and that it will never be touched on other machines so this
  1717. * lack of portability is not really an issue!
  1718. */
  1719. /*
  1720. * This seems to be one of a very small number of places where I use int16.
  1721. * In the case of a machine with try 64-bit addresses I will disble it.
  1722. */
  1723. *(int16 *)((char *)p + o) = (int)int_of_fixnum(x);
  1724. break;
  1725. #endif
  1726. case 4:
  1727. *(int32 *)((char *)p + o) = (int)int_of_fixnum(x);
  1728. break;
  1729. }
  1730. native_pages_changed = 1;
  1731. return onevalue(x);
  1732. }
  1733. Lisp_Object Lnativegetv(Lisp_Object nil, Lisp_Object v, Lisp_Object n)
  1734. {
  1735. int32 p, o;
  1736. CSL_IGNORE(nil);
  1737. if (!consp(v) ||
  1738. !is_fixnum(qcar(v)) ||
  1739. !is_fixnum(qcdr(v)) ||
  1740. (p = int_of_fixnum(qcar(v))) < 0 ||
  1741. p > native_pages_count) return aerror1("native-getv", v);
  1742. else if (!is_fixnum(n)) return aerror1("native-getv", n);
  1743. o = int_of_fixnum(qcdr(v)) + int_of_fixnum(n);
  1744. if (o < 0 || o >= CSL_PAGE_SIZE) return aerror1("native-getv", o);
  1745. p = (int32)native_pages[p];
  1746. p = doubleword_align_up(p);
  1747. o = *((char *)p + o);
  1748. return onevalue(fixnum_of_int(o & 0xff));
  1749. }
  1750. Lisp_Object MS_CDECL Lnativegetvn(Lisp_Object nil, int nargs, ...)
  1751. {
  1752. Lisp_Object v, n, w;
  1753. int32 p, o;
  1754. va_list a;
  1755. argcheck(nargs, 3, "native-getv");
  1756. va_start(a, nargs);
  1757. v = va_arg(a, Lisp_Object);
  1758. n = va_arg(a, Lisp_Object);
  1759. w = va_arg(a, Lisp_Object);
  1760. va_end(a);
  1761. CSL_IGNORE(nil);
  1762. if (!consp(v) ||
  1763. !is_fixnum(qcar(v)) ||
  1764. !is_fixnum(qcdr(v)) ||
  1765. (p = int_of_fixnum(qcar(v))) < 0 ||
  1766. p > native_pages_count) return aerror1("native-getv", v);
  1767. else if (!is_fixnum(n)) return aerror1("native-getv", n);
  1768. else if (!is_fixnum(w)) return aerror1("native-getv width", w);
  1769. o = int_of_fixnum(qcdr(v)) + int_of_fixnum(n);
  1770. if (o < 0 || o >= CSL_PAGE_SIZE) return aerror1("native-getv", o);
  1771. p = (int32)native_pages[p];
  1772. p = doubleword_align_up(p);
  1773. switch (int_of_fixnum(w))
  1774. {
  1775. default:
  1776. return aerror1("native-getv width", w);
  1777. case 1:
  1778. o = *((char *)p + o);
  1779. return onevalue(fixnum_of_int(o & 0xff));
  1780. #ifndef ADDRESS_64
  1781. case 2:
  1782. o = *(int16 *)((char *)p + o);
  1783. return onevalue(fixnum_of_int(o & 0xffff));
  1784. #endif
  1785. case 4:
  1786. o = *(int32 *)((char *)p + o);
  1787. p = o & fix_mask;
  1788. if (p==0 || p==fix_mask) return onevalue(fixnum_of_int(o & 0xff));
  1789. else if ((o & 0x80000000) == 0)
  1790. { w = make_one_word_bignum(o);
  1791. errexit();
  1792. return onevalue(w);
  1793. }
  1794. else
  1795. { w = make_two_word_bignum(1, o & 0x7fffffff);
  1796. errexit();
  1797. return onevalue(w);
  1798. }
  1799. }
  1800. }
  1801. Lisp_Object MS_CDECL Lnative_type(Lisp_Object nil, int nargs, ...)
  1802. {
  1803. return onevalue(fixnum_of_int(NATIVE_CODE_TAG));
  1804. }
  1805. /*
  1806. * (native-address fn nargs) fetches the value from the relevent function cell
  1807. * of the function and returns it represented as an integer. This gives
  1808. * the current real absolute address of the code involved and is intended
  1809. * to be useful while testing a native-mode compiler.
  1810. */
  1811. Lisp_Object Lnative_address(Lisp_Object nil, Lisp_Object fn, Lisp_Object nargs)
  1812. {
  1813. int32 n, n1;
  1814. CSL_IGNORE(nil);
  1815. if (!symbolp(fn)) return aerror1("native-address", fn);
  1816. if (!is_fixnum(nargs)) return aerror1("native-address", nargs);
  1817. n = int_of_fixnum(nargs);
  1818. switch (n)
  1819. {
  1820. case 1: n = ifn1(fn);
  1821. break;
  1822. case 2: n = ifn2(fn);
  1823. break;
  1824. default:n = ifnn(fn);
  1825. break;
  1826. }
  1827. n1 = n & fix_mask;
  1828. if (n1 == 0 || n1 == fix_mask) return onevalue(fixnum_of_int(n));
  1829. fn = make_one_word_bignum(n);
  1830. errexit();
  1831. return onevalue(fn);
  1832. }
  1833. /*
  1834. * (native-address n) with one integer argument will return an integer that
  1835. * is the current memory address of a CSL/CCL internal variable identified
  1836. * by that integer. The association between integers and variables is as
  1837. * per the file "externs.h" and the switch statement here. The case 0 gives
  1838. * the address of NIL, while 1 gives the address of "stack".
  1839. * An invalid or unrecognised integer leads to a result
  1840. * of zero. This is intended solely for the use of a native-code compiler.
  1841. * It may not then be necessary to provide access to ALL of these variables,
  1842. * but at least to start with it seems easiest to be comprehensive.
  1843. * Negative integers use values in the following table, which are functions
  1844. * in CSL that might usefully be called directly. If the one argument is a
  1845. * cons then it is expected to be a native code handle and the associated
  1846. * real address is returned.
  1847. */
  1848. void *useful_functions[] =
  1849. {
  1850. (void *)cons, /* -1, 0 */
  1851. (void *)ncons, /* -2, 1 */
  1852. (void *)list2, /* -3, 2 */
  1853. (void *)list2star, /* -4, 3 */
  1854. (void *)acons, /* -5, 4 */
  1855. (void *)list3, /* -6, 5 */
  1856. (void *)plus2, /* -7, 6 */
  1857. (void *)difference2, /* -8, 7 */
  1858. (void *)add1, /* -9, 8 */
  1859. (void *)sub1, /* -10, 9 */
  1860. (void *)get, /* -11, 10 */
  1861. (void *)lognot, /* -12, 11 */
  1862. (void *)ash, /* -13, 12 */
  1863. (void *)quot2, /* -14, 13 */
  1864. (void *)Cremainder, /* -15, 14 */
  1865. (void *)times2, /* -16, 15 */
  1866. (void *)negate, /* -17, 16 */
  1867. (void *)rational, /* -18, 17 */
  1868. (void *)lessp2, /* -19, 18 */
  1869. (void *)lesseq2, /* -20, 19 */
  1870. (void *)greaterp2, /* -21, 20 */
  1871. (void *)geq2, /* -22, 21 */
  1872. (void *)zerop, /* -23, 22 */
  1873. (void *)reclaim, /* -24, 23 */
  1874. (void *)error, /* -25, 24 */
  1875. (void *)equal_fn, /* -26, 25 */
  1876. (void *)cl_equal_fn, /* -27, 26 */
  1877. (void *)aerror, /* -28, 27 */
  1878. (void *)integerp, /* -29, 28 */
  1879. (void *)apply /* -30, 29 */
  1880. };
  1881. char *address_of_var(int n)
  1882. {
  1883. char *p = NULL;
  1884. Lisp_Object nil = C_nil;
  1885. if (n == 0) p = (char *)nil;
  1886. else if (n == 1) p = (char *)&stack;
  1887. else
  1888. #ifdef NILSEG_EXTERNS
  1889. switch (n)
  1890. {
  1891. default: p = 0; break;
  1892. case 12: p = (char *)&byteflip; break;
  1893. case 13: p = (char *)&codefringe; break;
  1894. case 14: p = (char *)&codelimit; break;
  1895. #ifdef COMMON
  1896. case 16: p = (char *)&stacklimit; break;
  1897. #else
  1898. case 15: p = (char *)&stacklimit; break;
  1899. #endif
  1900. case 18: p = (char *)&fringe; break;
  1901. case 19: p = (char *)&heaplimit; break;
  1902. case 20: p = (char *)&vheaplimit; break;
  1903. case 21: p = (char *)&vfringe; break;
  1904. case 22: p = (char *)&miscflags; break;
  1905. case 24: p = (char *)&nwork; break;
  1906. case 25: p = (char *)&exit_reason; break;
  1907. case 26: p = (char *)&exit_count; break;
  1908. case 27: p = (char *)&gensym_ser; break;
  1909. case 28: p = (char *)&print_precision; break;
  1910. case 29: p = (char *)&current_modulus; break;
  1911. case 30: p = (char *)&fastget_size; break;
  1912. case 31: p = (char *)&package_bits; break;
  1913. case 52: p = (char *)&current_package; break;
  1914. case 53: p = (char *)&B_reg; break;
  1915. case 54: p = (char *)&codevec; break;
  1916. case 55: p = (char *)&litvec; break;
  1917. case 56: p = (char *)&exit_tag; break;
  1918. case 57: p = (char *)&exit_value; break;
  1919. case 58: p = (char *)&catch_tags; break;
  1920. case 59: p = (char *)&lisp_package; break;
  1921. case 60: p = (char *)&boffo; break;
  1922. case 61: p = (char *)&charvec; break;
  1923. case 62: p = (char *)&sys_hash_table; break;
  1924. case 63: p = (char *)&help_index; break;
  1925. case 64: p = (char *)&gensym_base; break;
  1926. case 65: p = (char *)&err_table; break;
  1927. case 66: p = (char *)&supervisor; break;
  1928. case 67: p = (char *)&startfn; break;
  1929. case 68: p = (char *)&faslvec; break;
  1930. case 69: p = (char *)&tracedfn; break;
  1931. case 70: p = (char *)&prompt_thing; break;
  1932. case 71: p = (char *)&faslgensyms; break;
  1933. case 72: p = (char *)&cl_symbols; break;
  1934. case 73: p = (char *)&active_stream; break;
  1935. case 80: p = (char *)&append_symbol; break;
  1936. case 81: p = (char *)&applyhook; break;
  1937. case 82: p = (char *)&cfunarg; break;
  1938. case 83: p = (char *)&comma_at_symbol; break;
  1939. case 84: p = (char *)&comma_symbol; break;
  1940. case 85: p = (char *)&compiler_symbol; break;
  1941. case 86: p = (char *)&comp_symbol; break;
  1942. case 87: p = (char *)&cons_symbol; break;
  1943. case 88: p = (char *)&echo_symbol; break;
  1944. case 89: p = (char *)&emsg_star; break;
  1945. case 90: p = (char *)&evalhook; break;
  1946. case 91: p = (char *)&eval_symbol; break;
  1947. case 92: p = (char *)&expr_symbol; break;
  1948. case 93: p = (char *)&features_symbol; break;
  1949. case 94: p = (char *)&fexpr_symbol; break;
  1950. case 95: p = (char *)&funarg; break;
  1951. case 96: p = (char *)&function_symbol; break;
  1952. case 97: p = (char *)&lambda; break;
  1953. case 98: p = (char *)&lisp_true; break;
  1954. case 99: p = (char *)&lower_symbol; break;
  1955. case 100: p = (char *)&macroexpand_hook; break;
  1956. case 101: p = (char *)&macro_symbol; break;
  1957. case 102: p = (char *)&opt_key; break;
  1958. case 103: p = (char *)&prinl_symbol; break;
  1959. case 104: p = (char *)&progn_symbol; break;
  1960. case 105: p = (char *)&quote_symbol; break;
  1961. case 106: p = (char *)&raise_symbol; break;
  1962. case 107: p = (char *)&redef_msg; break;
  1963. case 108: p = (char *)&rest_key; break;
  1964. case 109: p = (char *)&savedef; break;
  1965. case 110: p = (char *)&string_char_sym; break;
  1966. case 111: p = (char *)&unset_var; break;
  1967. case 112: p = (char *)&work_symbol; break;
  1968. case 113: p = (char *)&lex_words; break;
  1969. case 114: p = (char *)&get_counts; break;
  1970. case 115: p = (char *)&fastget_names; break;
  1971. case 116: p = (char *)&input_libraries; break;
  1972. case 117: p = (char *)&output_library; break;
  1973. case 118: p = (char *)&current_file; break;
  1974. case 119: p = (char *)&break_function; break;
  1975. case 120: p = (char *)&lisp_work_stream; break;
  1976. case 121: p = (char *)&lisp_standard_output; break;
  1977. case 122: p = (char *)&lisp_standard_input; break;
  1978. case 123: p = (char *)&lisp_debug_io; break;
  1979. case 124: p = (char *)&lisp_error_output; break;
  1980. case 125: p = (char *)&lisp_query_io; break;
  1981. case 126: p = (char *)&lisp_terminal_io; break;
  1982. case 127: p = (char *)&lisp_trace_output; break;
  1983. case 128: p = (char *)&standard_output; break;
  1984. case 129: p = (char *)&standard_input; break;
  1985. case 130: p = (char *)&debug_io; break;
  1986. case 131: p = (char *)&error_output; break;
  1987. case 132: p = (char *)&query_io; break;
  1988. case 133: p = (char *)&terminal_io; break;
  1989. case 134: p = (char *)&trace_output; break;
  1990. case 135: p = (char *)&fasl_stream; break;
  1991. case 136: p = (char *)&native_code; break;
  1992. #ifdef COMMON
  1993. case 140: p = (char *)&keyword_package; break;
  1994. case 141: p = (char *)&all_packages; break;
  1995. case 142: p = (char *)&package_symbol; break;
  1996. case 143: p = (char *)&internal_symbol; break;
  1997. case 144: p = (char *)&external_symbol; break;
  1998. case 145: p = (char *)&inherited_symbol; break;
  1999. case 146: p = (char *)&key_key; break;
  2000. case 147: p = (char *)&allow_other_keys; break;
  2001. case 148: p = (char *)&aux_key; break;
  2002. case 149: p = (char *)&format_symbol; break;
  2003. case 150: p = (char *)&expand_def_symbol; break;
  2004. case 151: p = (char *)&allow_key_key; break;
  2005. case 152: p = (char *)&declare_symbol; break;
  2006. case 153: p = (char *)&special_symbol; break;
  2007. #endif
  2008. }
  2009. #else /* NILSEG_EXTERNS */
  2010. if (n >= 160) switch (n)
  2011. {
  2012. default: p = 0; break;
  2013. case 160: p = (char *)&user_base_0; break;
  2014. case 161: p = (char *)&user_base_1; break;
  2015. case 162: p = (char *)&user_base_2; break;
  2016. case 163: p = (char *)&user_base_3; break;
  2017. case 164: p = (char *)&user_base_4; break;
  2018. case 165: p = (char *)&user_base_5; break;
  2019. case 166: p = (char *)&user_base_6; break;
  2020. case 167: p = (char *)&user_base_7; break;
  2021. case 168: p = (char *)&user_base_8; break;
  2022. case 169: p = (char *)&user_base_9; break;
  2023. }
  2024. else p = (char *)&(((int32 *)nil)[n]);
  2025. #endif /* NILSEG_EXTERNS */
  2026. return p;
  2027. }
  2028. Lisp_Object Lnative_address1(Lisp_Object nil, Lisp_Object x)
  2029. {
  2030. int32 n, n1, p;
  2031. if (consp(x))
  2032. { if (!is_fixnum(qcar(x)) ||
  2033. !is_fixnum(qcdr(x)) ||
  2034. (p = int_of_fixnum(qcar(x))) < 0 ||
  2035. p > native_pages_count) return aerror1("native-address", x);
  2036. n = int_of_fixnum(qcdr(x));
  2037. if (n < 0 || n >= CSL_PAGE_SIZE) return aerror1("native-address", x);
  2038. p = (int32)native_pages[p];
  2039. p = doubleword_align_up(p);
  2040. p = (int32)((char *)p + n);
  2041. }
  2042. else
  2043. { if (!is_fixnum(x)) return aerror1("native-address", x);
  2044. n = int_of_fixnum(x);
  2045. if (n < 0)
  2046. { n = (-n) - 1;
  2047. if (n >= sizeof(useful_functions)/sizeof(void *))
  2048. return aerror1("native-address", x);
  2049. else p = (int32)useful_functions[n];
  2050. }
  2051. else p = (int32)address_of_var(n);
  2052. }
  2053. n1 = p & fix_mask;
  2054. if (n1 == 0 || n1 == fix_mask) return onevalue(fixnum_of_int(p));
  2055. x = make_one_word_bignum(p);
  2056. errexit();
  2057. return onevalue(x);
  2058. }
  2059. /*
  2060. * Access functions for specialised (binary-contents) vectors. NOT integrated
  2061. * in with the greater generality of vector structures.
  2062. */
  2063. Lisp_Object MS_CDECL Lputv8(Lisp_Object nil, int nargs, ...)
  2064. {
  2065. Header h;
  2066. va_list a;
  2067. int32 n1, hl;
  2068. Lisp_Object v, n, x;
  2069. argcheck(nargs, 3, "putv8");
  2070. va_start(a, nargs);
  2071. v = va_arg(a, Lisp_Object);
  2072. n = va_arg(a, Lisp_Object);
  2073. x = va_arg(a, Lisp_Object);
  2074. va_end(a);
  2075. CSL_IGNORE(nil);
  2076. if (!is_vector(v) || type_of_header(h = vechdr(v)) != TYPE_VEC8)
  2077. return aerror1("putv8", v);
  2078. else if (!is_fixnum(n)) return aerror1("putv8 offset not fixnum", n);
  2079. hl = length_of_header(h) - 4;
  2080. n1 = int_of_fixnum(n);
  2081. if (n1 < 0 || n1 >= hl) return aerror1("putv8 index range", n);
  2082. scelt(v, n1) = int_of_fixnum(x);
  2083. return onevalue(x);
  2084. }
  2085. Lisp_Object Lgetv8(Lisp_Object nil, Lisp_Object v, Lisp_Object n)
  2086. {
  2087. Header h;
  2088. int32 n1, hl;
  2089. CSL_IGNORE(nil);
  2090. if (!is_vector(v) || type_of_header(h = vechdr(v)) != TYPE_VEC8)
  2091. return aerror1("getv8", v);
  2092. else if (!is_fixnum(n)) return aerror1("getv8 offset not fixnum", n);
  2093. hl = length_of_header(h) - 4;
  2094. n1 = int_of_fixnum(n);
  2095. if (n1 < 0 || n1 >= hl) return aerror1("getv8 index range", n);
  2096. else return onevalue(fixnum_of_int(scelt(v, n1)));
  2097. }
  2098. Lisp_Object MS_CDECL Lputv16(Lisp_Object nil, int nargs, ...)
  2099. {
  2100. Header h;
  2101. va_list a;
  2102. int32 n1, hl;
  2103. Lisp_Object v, n, x;
  2104. argcheck(nargs, 3, "putv16");
  2105. va_start(a, nargs);
  2106. v = va_arg(a, Lisp_Object);
  2107. n = va_arg(a, Lisp_Object);
  2108. x = va_arg(a, Lisp_Object);
  2109. va_end(a);
  2110. CSL_IGNORE(nil);
  2111. if (!is_vector(v) || type_of_header(h = vechdr(v)) != TYPE_VEC16)
  2112. return aerror1("putv16", v);
  2113. else if (!is_fixnum(n)) return aerror1("putv16 offset not fixnum", n);
  2114. hl = (length_of_header(h) - 4) >> 1;
  2115. n1 = int_of_fixnum(n);
  2116. if (n1 < 0 || n1 >= hl) return aerror1("putv16 index range", n);
  2117. sethelt(v, n1, int_of_fixnum(x));
  2118. return onevalue(x);
  2119. }
  2120. Lisp_Object Lgetv16(Lisp_Object nil, Lisp_Object v, Lisp_Object n)
  2121. {
  2122. Header h;
  2123. int32 n1, hl;
  2124. CSL_IGNORE(nil);
  2125. if (!is_vector(v) || type_of_header(h = vechdr(v)) != TYPE_VEC16)
  2126. return aerror1("getv16", v);
  2127. else if (!is_fixnum(n)) return aerror1("getv16 offset not fixnum", n);
  2128. hl = (length_of_header(h) - 4) >> 1;
  2129. n1 = int_of_fixnum(n);
  2130. if (n1 < 0 || n1 >= hl) return aerror1("getv16 index range", n);
  2131. n1 = helt(v, n1);
  2132. return onevalue(fixnum_of_int(n1));
  2133. }
  2134. Lisp_Object MS_CDECL Lputv32(Lisp_Object nil, int nargs, ...)
  2135. {
  2136. Header h;
  2137. va_list a;
  2138. int32 n1, hl;
  2139. Lisp_Object v, n, x;
  2140. argcheck(nargs, 3, "putv32");
  2141. va_start(a, nargs);
  2142. v = va_arg(a, Lisp_Object);
  2143. n = va_arg(a, Lisp_Object);
  2144. x = va_arg(a, Lisp_Object);
  2145. va_end(a);
  2146. CSL_IGNORE(nil);
  2147. if (!is_vector(v) || type_of_header(h = vechdr(v)) != TYPE_VEC32)
  2148. return aerror1("putv32", v);
  2149. else if (!is_fixnum(n)) return aerror1("putv32 offset not fixnum", n);
  2150. hl = (length_of_header(h) - 4) >> 2;
  2151. n1 = int_of_fixnum(n);
  2152. if (n1 < 0 || n1 >= hl) return aerror1("putv32 index range", n);
  2153. ielt(v, n1) = thirty_two_bits(x);
  2154. return onevalue(x);
  2155. }
  2156. Lisp_Object Lgetv32(Lisp_Object nil, Lisp_Object v, Lisp_Object n)
  2157. {
  2158. Header h;
  2159. int32 n1, hl;
  2160. CSL_IGNORE(nil);
  2161. if (!is_vector(v) || type_of_header(h = vechdr(v)) != TYPE_VEC32)
  2162. return aerror1("getv32", v);
  2163. else if (!is_fixnum(n)) return aerror1("getv32 offset not fixnum", n);
  2164. hl = (length_of_header(h) - 4) >> 2;
  2165. n1 = int_of_fixnum(n);
  2166. if (n1 < 0 || n1 >= hl) return aerror1("getv32 index range", n);
  2167. n1 = ielt(v, n1);
  2168. hl = n1 & fix_mask;
  2169. if (hl == 0 || hl == fix_mask) return fixnum_of_int(n1);
  2170. n = make_one_word_bignum(n1);
  2171. errexit();
  2172. return onevalue(n);
  2173. }
  2174. Lisp_Object MS_CDECL Lfputv32(Lisp_Object nil, int nargs, ...)
  2175. {
  2176. Header h;
  2177. va_list a;
  2178. int32 n1, hl;
  2179. Lisp_Object v, n, x;
  2180. double d;
  2181. argcheck(nargs, 3, "fputv32");
  2182. va_start(a, nargs);
  2183. v = va_arg(a, Lisp_Object);
  2184. n = va_arg(a, Lisp_Object);
  2185. x = va_arg(a, Lisp_Object);
  2186. d = float_of_number(x);
  2187. va_end(a);
  2188. CSL_IGNORE(nil);
  2189. if (!is_vector(v) || type_of_header(h = vechdr(v)) != TYPE_FLOAT32)
  2190. return aerror1("fputv32", v);
  2191. else if (!is_fixnum(n)) return aerror1("fputv32 offset not fixnum", n);
  2192. hl = (length_of_header(h) - 4) >> 2;
  2193. n1 = int_of_fixnum(n);
  2194. if (n1 < 0 || n1 >= hl) return aerror1("fputv32 index range", n);
  2195. felt(v, n1) = (float)d;
  2196. return onevalue(x);
  2197. }
  2198. Lisp_Object Lfgetv32(Lisp_Object nil, Lisp_Object v, Lisp_Object n)
  2199. {
  2200. Header h;
  2201. int32 n1, hl;
  2202. CSL_IGNORE(nil);
  2203. if (!is_vector(v) || type_of_header(h = vechdr(v)) != TYPE_FLOAT32)
  2204. return aerror1("fgetv32", v);
  2205. else if (!is_fixnum(n)) return aerror1("fgetv32 offset not fixnum", n);
  2206. hl = (length_of_header(h) - 4) >> 2;
  2207. n1 = int_of_fixnum(n);
  2208. if (n1 < 0 || n1 >= hl) return aerror1("fgetv32 index range", n);
  2209. #ifdef COMMON
  2210. v = make_boxfloat((double)felt(v, n1), TYPE_SINGLE_FLOAT);
  2211. #else
  2212. v = make_boxfloat((double)felt(v, n1), TYPE_DOUBLE_FLOAT);
  2213. #endif
  2214. errexit();
  2215. return onevalue(v);
  2216. }
  2217. Lisp_Object MS_CDECL Lfputv64(Lisp_Object nil, int nargs, ...)
  2218. {
  2219. Header h;
  2220. va_list a;
  2221. int32 n1, hl;
  2222. Lisp_Object v, n, x;
  2223. double d;
  2224. argcheck(nargs, 3, "fputv64");
  2225. va_start(a, nargs);
  2226. v = va_arg(a, Lisp_Object);
  2227. n = va_arg(a, Lisp_Object);
  2228. x = va_arg(a, Lisp_Object);
  2229. d = float_of_number(x);
  2230. va_end(a);
  2231. CSL_IGNORE(nil);
  2232. if (!is_vector(v) || type_of_header(h = vechdr(v)) != TYPE_FLOAT64)
  2233. return aerror1("fputv64", v);
  2234. else if (!is_fixnum(n)) return aerror1("fputv64 offset not fixnum", n);
  2235. hl = (length_of_header(h) - 8) >> 3;
  2236. n1 = int_of_fixnum(n);
  2237. if (n1 < 0 || n1 >= hl) return aerror1("fputv64 index range", n);
  2238. delt(v, n1) = d;
  2239. return onevalue(x);
  2240. }
  2241. Lisp_Object Lfgetv64(Lisp_Object nil, Lisp_Object v, Lisp_Object n)
  2242. {
  2243. Header h;
  2244. int32 n1, hl;
  2245. CSL_IGNORE(nil);
  2246. if (!is_vector(v) || type_of_header(h = vechdr(v)) != TYPE_FLOAT64)
  2247. return aerror1("fgetv64", v);
  2248. else if (!is_fixnum(n)) return aerror1("fgetv64 offset not fixnum", n);
  2249. hl = (length_of_header(h) - 8) >> 3;
  2250. n1 = int_of_fixnum(n);
  2251. if (n1 < 0 || n1 >= hl) return aerror1("fgetv64 index range", n);
  2252. v = make_boxfloat(delt(v, n1), TYPE_DOUBLE_FLOAT);
  2253. errexit();
  2254. return onevalue(v);
  2255. }
  2256. #ifdef COMMON
  2257. /*
  2258. * (defun putvec (v n x)
  2259. * (cond
  2260. * ((simple-string-p v) (putv-char v n x))
  2261. * ((simple-bit-vector-p v) (putv-bit v n x))
  2262. * (t (putv v n x))))
  2263. */
  2264. static Lisp_Object MS_CDECL Lputvec(Lisp_Object nil, int nargs, ...)
  2265. {
  2266. Header h;
  2267. va_list a;
  2268. int32 vx, n1, hl;
  2269. Lisp_Object v, n, x;
  2270. CSL_IGNORE(nil);
  2271. argcheck(nargs, 3, "putvec");
  2272. va_start(a, nargs);
  2273. v = va_arg(a, Lisp_Object);
  2274. n = va_arg(a, Lisp_Object);
  2275. x = va_arg(a, Lisp_Object);
  2276. va_end(a);
  2277. /*
  2278. * Oh joy - here I have to dispatch based on what sort of vector I have.
  2279. */
  2280. if (!is_vector(v)) return aerror1("putvec", v);
  2281. else if (!is_fixnum(n)) return aerror1("putvec", n);
  2282. h = vechdr(v);
  2283. if (type_of_header(h) == TYPE_STRING)
  2284. { if (is_fixnum(x)) vx = int_of_fixnum(x);
  2285. else if (is_char(x)) vx = code_of_char(x);
  2286. else return aerror1("putvec on string, contents", x);
  2287. hl = length_of_header(h) - 4;
  2288. n1 = int_of_fixnum(n);
  2289. if (n1 < 0 || n1 >= hl) return aerror1("putvec", n);
  2290. celt(v, n1) = (int)vx;
  2291. return onevalue(x);
  2292. }
  2293. if (header_of_bitvector(h))
  2294. { int b;
  2295. if (!is_fixnum(x)) return aerror1("putvec on bitvec, contents", x);
  2296. x = int_of_fixnum(x) & 1;
  2297. h = length_of_header(h) - 4;
  2298. n1 = int_of_fixnum(n);
  2299. b = 1 << (n1 & 7); /* Bit selector */
  2300. n1 = n1 >> 3; /* Byte selector */
  2301. /*
  2302. * I am just a bit shoddy here - I only complain if an attempt is made to
  2303. * access beyond the last active byte of a bitvector - I do not
  2304. * do bound checking accurate to bit positions.
  2305. */
  2306. if (n1 < 0 || n1 >= (int32)h) return aerror1("putv-bit", n);
  2307. if (x == 0) celt(v, n1) &= ~b;
  2308. else celt(v, n1) |= b;
  2309. return onevalue(fixnum_of_int(x));
  2310. }
  2311. if (vector_holds_binary(h)) return aerror1("putvec", v);
  2312. hl = (length_of_header(h) - 4) >> 2;
  2313. n1 = int_of_fixnum(n);
  2314. if (n1 < 0 || n1 >= hl) return aerror1("putvec index range", n);
  2315. elt(v, n1) = x;
  2316. return onevalue(x);
  2317. }
  2318. /*
  2319. * (defun aref (v n1 &rest r)
  2320. * (if (null r)
  2321. * (cond
  2322. * ((simple-vector-p v) (getv v n1))
  2323. * ((simple-string-p v) (schar v n1))
  2324. * ((simple-bit-vector-p v) (getv-bit v n1))
  2325. * ((structp v) (getv v n1))
  2326. * (t (general-aref v n1 r)))
  2327. * (general-aref v n1 r)))
  2328. *
  2329. * (defun general-aref (v n1 r)
  2330. * (when (not (arrayp v)) (error "aref ~s ~s" v (cons n1 r)))
  2331. * (do ((dd (cdr (getv v 1)) (cdr dd)))
  2332. * ((null r))
  2333. * (setq n1 (+ (* n1 (car dd)) (pop r))))
  2334. ***** plus special magic to deal with segmented representations...
  2335. * (aref (getv v 2) (+ (getv v 3) n1)))
  2336. */
  2337. Lisp_Object MS_CDECL Laref(Lisp_Object nil, int nargs, ...)
  2338. {
  2339. Header h;
  2340. Lisp_Object v, n, w;
  2341. int32 hl, n1, b;
  2342. va_list a;
  2343. if (nargs == 0) return aerror("aref");
  2344. va_start(a, nargs);
  2345. v = va_arg(a, Lisp_Object);
  2346. if (!is_vector(v))
  2347. { va_end(a);
  2348. return aerror1("aref", v);
  2349. }
  2350. h = vechdr(v);
  2351. if (nargs == 1) n = 0; /* Funny case (aref v) legal if no dimensions! */
  2352. else
  2353. { n = va_arg(a, Lisp_Object); /* First subscript */
  2354. if (!is_fixnum(n))
  2355. { va_end(a);
  2356. return aerror1("aref", n);
  2357. }
  2358. if (nargs == 2)
  2359. { if (type_of_header(h) == TYPE_SIMPLE_VEC ||
  2360. type_of_header(h) == TYPE_STRUCTURE)
  2361. { va_end(a);
  2362. hl = (length_of_header(h) - 4) >> 2;
  2363. n1 = int_of_fixnum(n);
  2364. if (n1 < 0 || n1 >= hl) return aerror1("aref index range", n);
  2365. else return onevalue(elt(v, n1));
  2366. }
  2367. else if (type_of_header(h) == TYPE_STRING)
  2368. { va_end(a);
  2369. hl = length_of_header(h) - 4;
  2370. n1 = int_of_fixnum(n);
  2371. if (n1 < 0 || n1 >= hl) return aerror1("aref index range", n);
  2372. return onevalue(pack_char(0, 0, celt(v, n1)));
  2373. }
  2374. else if (header_of_bitvector(h))
  2375. { va_end(a);
  2376. h = length_of_header(h) - 4;
  2377. n1 = int_of_fixnum(n);
  2378. b = 1 << (n1 & 7); /* Bit selector */
  2379. n1 = n1 >> 3; /* Byte selector */
  2380. if (n1 < 0 || n1 >= (int32)h)
  2381. return aerror1("aref index range", n);
  2382. if ((celt(v, n1) & b) == 0) return onevalue(fixnum_of_int(0));
  2383. else return onevalue(fixnum_of_int(1));
  2384. }
  2385. }
  2386. }
  2387. if (type_of_header(h) != TYPE_ARRAY)
  2388. { va_end(a);
  2389. return aerror1("aref", v);
  2390. }
  2391. /*
  2392. * Here I had better have a general array, and I will need to calculate the
  2393. * real index location within it.
  2394. */
  2395. w = elt(v, 1); /* The list of dimensions */
  2396. if (w == nil && nargs == 1)
  2397. { va_end(a);
  2398. return onevalue(elt(v, 2));
  2399. }
  2400. n1 = int_of_fixnum(n);
  2401. w = qcdr(w);
  2402. while (nargs > 2 && w != nil)
  2403. { n = va_arg(a, Lisp_Object);
  2404. if (!is_fixnum(n))
  2405. { va_end(a);
  2406. return aerror1("aref", n);
  2407. }
  2408. n1 = n1*int_of_fixnum(qcar(w)) + int_of_fixnum(n);
  2409. nargs--;
  2410. w = qcdr(w);
  2411. }
  2412. va_end(a);
  2413. if (nargs > 2 || w != nil)
  2414. return aerror("aref, wrong number of subscripts");
  2415. n1 += int_of_fixnum(elt(v, 3)); /* displaced-index-offset */
  2416. v = elt(v, 2);
  2417. /*
  2418. * Now I have got the vector that this array is displaced to or
  2419. * represented by. If it is in fact a structure (not a simple vector)
  2420. * then it is a row of 8K sub-vectors, and at element zero it has the
  2421. * nominal size of the big vector (as a Lisp integer)
  2422. */
  2423. h = vechdr(v);
  2424. if (type_of_header(h) == TYPE_SIMPLE_VEC)
  2425. { hl = (length_of_header(h) - 4) >> 2;
  2426. if (n1 < 0 || n1 >= hl) return aerror("aref index range");
  2427. else return onevalue(elt(v, n1));
  2428. }
  2429. else if (type_of_header(h) == TYPE_STRUCTURE)
  2430. { int32 n2;
  2431. hl = int_of_fixnum(elt(v, 0));
  2432. if (n1 < 0 || n1 >= hl) return aerror("aref index range");
  2433. n2 = n1 % 8192;
  2434. n1 = n1 / 8192;
  2435. return onevalue(elt(elt(v, n1+1), n2));
  2436. }
  2437. else if (type_of_header(h) == TYPE_STRING)
  2438. { hl = length_of_header(h) - 4;
  2439. if (n1 < 0 || n1 >= hl) return aerror("aref index range");
  2440. return onevalue(pack_char(0, 0, celt(v, n1)));
  2441. }
  2442. else if (header_of_bitvector(h))
  2443. { h = length_of_header(h) - 4;
  2444. b = 1 << (n1 & 7); /* Bit selector */
  2445. n1 = n1 >> 3; /* Byte selector */
  2446. if (n1 < 0 || n1 >= (int32)h) return aerror("aref index range");
  2447. if ((celt(v, n1) & b) == 0) return onevalue(fixnum_of_int(0));
  2448. else return onevalue(fixnum_of_int(1));
  2449. }
  2450. return aerror("aref unknown type for vector representation");
  2451. }
  2452. static Lisp_Object Laref1(Lisp_Object nil, Lisp_Object a)
  2453. {
  2454. return Laref(nil, 1, a);
  2455. }
  2456. Lisp_Object Laref2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  2457. {
  2458. return Laref(nil, 2, a, b);
  2459. }
  2460. Lisp_Object Lelt(Lisp_Object nil, Lisp_Object v, Lisp_Object n)
  2461. {
  2462. Header h;
  2463. Lisp_Object w;
  2464. int32 hl, n1, b;
  2465. if (!is_fixnum(n) || ((int32)n) < 0) return aerror1("elt", n);
  2466. n1 = int_of_fixnum(n);
  2467. if (!is_vector(v))
  2468. { w = v;
  2469. while (consp(w) && n1>0)
  2470. { n1--;
  2471. w = qcdr(w);
  2472. }
  2473. if (!consp(w)) return aerror1("elt", v);
  2474. return onevalue(qcar(w));
  2475. }
  2476. h = vechdr(v);
  2477. if (type_of_header(h) == TYPE_SIMPLE_VEC ||
  2478. type_of_header(h) == TYPE_STRUCTURE)
  2479. { hl = (length_of_header(h) - 4) >> 2;
  2480. if (n1 >= hl) return aerror1("elt index range", n);
  2481. else return onevalue(elt(v, n1));
  2482. }
  2483. else if (type_of_header(h) == TYPE_STRING)
  2484. { hl = length_of_header(h) - 4;
  2485. if (n1 >= hl) return aerror1("elt index range", n);
  2486. return onevalue(pack_char(0, 0, celt(v, n1)));
  2487. }
  2488. else if (header_of_bitvector(h))
  2489. { h = length_of_header(h) - 4;
  2490. b = 1 << (n1 & 7); /* Bit selector */
  2491. n1 = n1 >> 3; /* Byte selector */
  2492. if (n1 < 0 || n1 >= (int32)h)
  2493. return aerror1("elt index range", n);
  2494. if ((celt(v, n1) & b) == 0) return onevalue(fixnum_of_int(0));
  2495. else return onevalue(fixnum_of_int(1));
  2496. }
  2497. if (type_of_header(h) != TYPE_ARRAY) return aerror1("elt", v);
  2498. w = elt(v, 1); /* The list of dimensions - must be 1 dim here */
  2499. w = qcdr(w);
  2500. if (w != nil) return aerror1("elt", v);
  2501. n1 += int_of_fixnum(elt(v, 3)); /* displaced-index-offset */
  2502. v = elt(v, 2);
  2503. h = vechdr(v);
  2504. if (type_of_header(h) == TYPE_SIMPLE_VEC)
  2505. { hl = (length_of_header(h) - 4) >> 2;
  2506. if (n1 >= hl) return aerror("elt index range");
  2507. else return onevalue(elt(v, n1));
  2508. }
  2509. else if (type_of_header(h) == TYPE_STRUCTURE)
  2510. { int32 n2;
  2511. hl = int_of_fixnum(elt(v, 0));
  2512. if (n1 >= hl) return aerror("elt index range");
  2513. n2 = n1 % 8192;
  2514. n1 = n1 / 8192;
  2515. return onevalue(elt(elt(v, n1+1), n2));
  2516. }
  2517. else if (type_of_header(h) == TYPE_STRING)
  2518. { hl = length_of_header(h) - 4;
  2519. if (n1 >= hl) return aerror("elt index range");
  2520. return onevalue(pack_char(0, 0, celt(v, n1)));
  2521. }
  2522. else if (header_of_bitvector(h))
  2523. { h = length_of_header(h) - 4;
  2524. b = 1 << (n1 & 7); /* Bit selector */
  2525. n1 = n1 >> 3; /* Byte selector */
  2526. if (n1 >= (int32)h) return aerror("elt index range");
  2527. if ((celt(v, n1) & b) == 0) return onevalue(fixnum_of_int(0));
  2528. else return onevalue(fixnum_of_int(1));
  2529. }
  2530. return aerror("elt unknown type for vector representation");
  2531. }
  2532. /*
  2533. * (defun aset (v n1 x &rest r)
  2534. * (if (null r)
  2535. * (cond
  2536. * ((simple-vector-p v) (putv v n1 x))
  2537. * ((simple-string-p v) (putv-char v n1 x))
  2538. * ((simple-bit-vector-p v) (putv-bit v n1 x))
  2539. * ((structp v) (putv v n1 x))
  2540. * (t (general-aset v n1 x r)))
  2541. * (general-aset v n1 x r)))
  2542. *
  2543. * (defun general-aset (v n1 x r)
  2544. * (when (not (arrayp v)) (error "aref ~s ~s" v
  2545. * (reverse (cdr (reverse (cons n1 (cons x r)))))))
  2546. * (setq r (cons x r))
  2547. * (do ((dd (cdr (getv v 1)) (cdr dd)))
  2548. * ((null (cdr r)))
  2549. * (setq n1 (+ (* n1 (car dd)) (pop r))))
  2550. ***** plus special magic to deal with segmented representations...
  2551. * (aset (getv v 2) (+ (getv v 3) n1) (car r)))
  2552. */
  2553. /*
  2554. * Note that the code for ASET is really a mildly modified copy of that
  2555. * for AREF.
  2556. */
  2557. Lisp_Object MS_CDECL Laset(Lisp_Object nil, int nargs, ...)
  2558. {
  2559. Header h;
  2560. Lisp_Object v, n, w, x;
  2561. int32 hl, n1, b;
  2562. va_list a;
  2563. if (nargs < 2) return aerror("aset");
  2564. va_start(a, nargs);
  2565. v = va_arg(a, Lisp_Object);
  2566. if (!is_vector(v))
  2567. { va_end(a);
  2568. return aerror1("aset", v);
  2569. }
  2570. h = vechdr(v);
  2571. if (nargs == 2) n = 0; /* Funny case (aset v w) legal if no dimensions! */
  2572. else
  2573. { n = va_arg(a, Lisp_Object); /* First subscript */
  2574. if (!is_fixnum(n))
  2575. { va_end(a);
  2576. return aerror1("aset", n);
  2577. }
  2578. if (nargs == 3)
  2579. { if (type_of_header(h) == TYPE_SIMPLE_VEC ||
  2580. type_of_header(h) == TYPE_STRUCTURE)
  2581. { x = va_arg(a, Lisp_Object);
  2582. va_end(a);
  2583. hl = (length_of_header(h) - 4) >> 2;
  2584. n1 = int_of_fixnum(n);
  2585. if (n1 < 0 || n1 >= hl) return aerror1("aset index range", n);
  2586. elt(v, n1) = x;
  2587. return onevalue(x);
  2588. }
  2589. else if (type_of_header(h) == TYPE_STRING)
  2590. { x = va_arg(a, Lisp_Object);
  2591. va_end(a);
  2592. hl = length_of_header(h) - 4;
  2593. n1 = int_of_fixnum(n);
  2594. if (n1 < 0 || n1 >= hl) return aerror1("aset index range", n);
  2595. if (is_fixnum(x)) b = int_of_fixnum(x);
  2596. else if (is_char(x)) b = code_of_char(x);
  2597. else return aerror1("aset needs char", x);
  2598. celt(v, n1) = b;
  2599. return onevalue(x);
  2600. }
  2601. else if (header_of_bitvector(h))
  2602. { x = va_arg(a, Lisp_Object);
  2603. va_end(a);
  2604. h = length_of_header(h) - 4;
  2605. n1 = int_of_fixnum(n);
  2606. b = 1 << (n1 & 7); /* Bit selector */
  2607. n1 = n1 >> 3; /* Byte selector */
  2608. if (n1 < 0 || n1 >= (int32)h)
  2609. return aerror1("aset index range", n);
  2610. if (!is_fixnum(x)) return aerror1("aset needs bit", x);
  2611. if (int_of_fixnum(x) & 1) ucelt(v, n1) |= b;
  2612. else ucelt(v, n1) &= ~b;
  2613. return onevalue(x);
  2614. }
  2615. }
  2616. }
  2617. if (type_of_header(h) != TYPE_ARRAY)
  2618. { va_end(a);
  2619. return aerror1("aset", v);
  2620. }
  2621. /*
  2622. * Here I had better have a general array, and I will need to calculate the
  2623. * real index location within it.
  2624. */
  2625. w = elt(v, 1); /* The list of dimensions */
  2626. if (w == nil && nargs == 2)
  2627. { x = va_arg(a, Lisp_Object);
  2628. va_end(a);
  2629. elt(v, 2) = x;
  2630. return onevalue(x);
  2631. }
  2632. n1 = int_of_fixnum(n);
  2633. w = qcdr(w);
  2634. while (nargs > 3 && w != nil)
  2635. { n = va_arg(a, Lisp_Object);
  2636. if (!is_fixnum(n))
  2637. { va_end(a);
  2638. return aerror1("aset", n);
  2639. }
  2640. n1 = n1*int_of_fixnum(qcar(w)) + int_of_fixnum(n);
  2641. nargs--;
  2642. w = qcdr(w);
  2643. }
  2644. x = va_arg(a, Lisp_Object);
  2645. va_end(a);
  2646. if (nargs > 3 || w != nil)
  2647. return aerror("aset, wrong number of subscripts");
  2648. n1 += int_of_fixnum(elt(v, 3)); /* displaced-index-offset */
  2649. v = elt(v, 2);
  2650. h = vechdr(v);
  2651. if (type_of_header(h) == TYPE_SIMPLE_VEC)
  2652. { hl = (length_of_header(h) - 4) >> 2;
  2653. if (n1 < 0 || n1 >= hl) return aerror("aset index range");
  2654. elt(v, n1) = x;
  2655. return onevalue(x);
  2656. }
  2657. if (type_of_header(h) == TYPE_STRUCTURE)
  2658. { int32 n2;
  2659. hl = int_of_fixnum(elt(v, 0));
  2660. if (n1 < 0 || n1 >= hl) return aerror("aset index range");
  2661. n2 = n1 % 8192;
  2662. n1 = n1 / 8192;
  2663. elt(elt(v, n1+1), n2) = x;
  2664. return onevalue(x);
  2665. }
  2666. else if (type_of_header(h) == TYPE_STRING)
  2667. { hl = length_of_header(h) - 4;
  2668. if (n1 < 0 || n1 >= hl) return aerror("aset index range");
  2669. if (is_fixnum(x)) b = int_of_fixnum(x);
  2670. else if (is_char(x)) b = code_of_char(x);
  2671. else return aerror1("aset needs char", x);
  2672. celt(v, n1) = b;
  2673. return onevalue(x);
  2674. }
  2675. else if (header_of_bitvector(h))
  2676. { h = length_of_header(h) - 4;
  2677. b = 1 << (n1 & 7); /* Bit selector */
  2678. n1 = n1 >> 3; /* Byte selector */
  2679. if (n1 < 0 || n1 >= (int32)h) return aerror("aset index range");
  2680. if (!is_fixnum(x)) return aerror1("aset needs bit", x);
  2681. if (int_of_fixnum(x) & 1) ucelt(v, n1) |= b;
  2682. else ucelt(v, n1) &= ~b;
  2683. return onevalue(x);
  2684. }
  2685. return aerror("aset unknown type for vector representation");
  2686. }
  2687. static Lisp_Object Laset1(Lisp_Object nil, Lisp_Object a)
  2688. {
  2689. return aerror("aset");
  2690. }
  2691. static Lisp_Object Laset2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  2692. {
  2693. return Laset(nil, 2, a, b);
  2694. }
  2695. static Lisp_Object MS_CDECL Lsetelt(Lisp_Object nil, int nargs, ...)
  2696. {
  2697. Lisp_Object v, n, x;
  2698. Header h;
  2699. Lisp_Object w;
  2700. int32 hl, n1, b;
  2701. va_list a;
  2702. argcheck(nargs, 3, "setelt");
  2703. va_start(a, nargs);
  2704. v = va_arg(a, Lisp_Object);
  2705. n = va_arg(a, Lisp_Object);
  2706. x = va_arg(a, Lisp_Object);
  2707. va_end(a);
  2708. if (!is_fixnum(n) || ((int32)n) < 0) return aerror1("setelt", n);
  2709. n1 = int_of_fixnum(n);
  2710. if (!is_vector(v))
  2711. { w = v;
  2712. while (consp(w) && n1>0)
  2713. { n1--;
  2714. w = qcdr(w);
  2715. }
  2716. if (!consp(w)) return aerror1("setelt", v);
  2717. qcar(w) = x;
  2718. return onevalue(x);
  2719. }
  2720. h = vechdr(v);
  2721. if (type_of_header(h) == TYPE_SIMPLE_VEC ||
  2722. type_of_header(h) == TYPE_STRUCTURE)
  2723. { hl = (length_of_header(h) - 4) >> 2;
  2724. if (n1 >= hl) return aerror1("setelt index range", n);
  2725. elt(v, n1) = x;
  2726. return onevalue(x);
  2727. }
  2728. else if (type_of_header(h) == TYPE_STRING)
  2729. { int vx;
  2730. hl = length_of_header(h) - 4;
  2731. if (n1 >= hl) return aerror1("setelt index range", n);
  2732. if (is_fixnum(x)) vx = int_of_fixnum(x);
  2733. else if (is_char(x)) vx = code_of_char(x);
  2734. else return aerror1("setelt contents", x);
  2735. celt(v, n1) = vx;
  2736. return onevalue(x);
  2737. }
  2738. else if (header_of_bitvector(h))
  2739. { if (!is_fixnum(x)) return aerror1("setelt contents", x);
  2740. x = int_of_fixnum(x) & 1;
  2741. h = length_of_header(h) - 4;
  2742. b = 1 << (n1 & 7); /* Bit selector */
  2743. n1 = n1 >> 3; /* Byte selector */
  2744. if (n1 >= (int32)h)
  2745. return aerror1("setelt index range", n);
  2746. if (x == 0) celt(v, n1) &= ~b;
  2747. else celt(v, n1) |= b;
  2748. return onevalue(fixnum_of_int(x));
  2749. }
  2750. if (type_of_header(h) != TYPE_ARRAY) return aerror1("setelt", v);
  2751. w = elt(v, 1); /* The list of dimensions - must be 1 dim here */
  2752. w = qcdr(w);
  2753. if (w != nil) return aerror1("setelt", v);
  2754. n1 += int_of_fixnum(elt(v, 3)); /* displaced-index-offset */
  2755. v = elt(v, 2);
  2756. h = vechdr(v);
  2757. if (type_of_header(h) == TYPE_SIMPLE_VEC)
  2758. { hl = (length_of_header(h) - 4) >> 2;
  2759. if (n1 >= hl) return aerror("setelt index range");
  2760. elt(v, n1) = x;
  2761. return onevalue(x);
  2762. }
  2763. else if (type_of_header(h) == TYPE_STRUCTURE)
  2764. { int32 n2;
  2765. hl = int_of_fixnum(elt(v, 0));
  2766. if (n1 >= hl) return aerror("setelt index range");
  2767. n2 = n1 % 8192;
  2768. n1 = n1 / 8192;
  2769. elt(elt(v, n1+1), n2) = x;
  2770. return onevalue(x);
  2771. }
  2772. else if (type_of_header(h) == TYPE_STRING)
  2773. { int vx;
  2774. hl = length_of_header(h) - 4;
  2775. if (is_fixnum(x)) vx = int_of_fixnum(x);
  2776. else if (is_char(x)) vx = code_of_char(x);
  2777. else return aerror1("setelt contents", x);
  2778. if (n1 >= hl) return aerror("setelt index range");
  2779. celt(v, n1) = vx;
  2780. return onevalue(x);
  2781. }
  2782. else if (header_of_bitvector(h))
  2783. { if (!is_fixnum(x)) return aerror1("setelt contents", x);
  2784. x = int_of_fixnum(x) & 1;
  2785. h = length_of_header(h) - 4;
  2786. b = 1 << (n1 & 7); /* Bit selector */
  2787. n1 = n1 >> 3; /* Byte selector */
  2788. if (n1 >= (int32)h) return aerror("setelt index range");
  2789. if (x == 0) celt(v, n1) &= ~b;
  2790. else celt(v, n1) |= b;
  2791. return onevalue(fixnum_of_int(x));
  2792. }
  2793. return aerror("setelt unknown type for vector representation");
  2794. }
  2795. /*
  2796. * (defun vectorp (x)
  2797. * (or (simple-vector-p x)
  2798. * (simple-string-p x)
  2799. * (simple-bit-vector-p x)
  2800. * (and (arrayp x) (length-one-p (svref x 1)))))
  2801. */
  2802. Lisp_Object Lvectorp(Lisp_Object nil, Lisp_Object a)
  2803. {
  2804. Header h;
  2805. int32 tt;
  2806. if (!is_vector(a)) return onevalue(nil);
  2807. h = vechdr(a);
  2808. tt = type_of_header(h);
  2809. if (tt == TYPE_SIMPLE_VEC ||
  2810. tt == TYPE_STRING ||
  2811. header_of_bitvector(h)) return onevalue(lisp_true);
  2812. if (tt == TYPE_ARRAY)
  2813. { a = elt(a, 1); /* List of dimensions */
  2814. if (consp(a) && !consp(qcdr(a))) return onevalue(lisp_true);
  2815. }
  2816. return onevalue(nil);
  2817. }
  2818. /*
  2819. * (defun char (s n)
  2820. * (cond
  2821. * ((simple-string-p s) (schar s n))
  2822. * (t (aref s n))))
  2823. */
  2824. static Lisp_Object Lchar(Lisp_Object nil, Lisp_Object v, Lisp_Object n)
  2825. {
  2826. Header h;
  2827. if (!is_vector(v)) return aerror("char");
  2828. h = vechdr(v);
  2829. if (type_of_header(h) == TYPE_STRING)
  2830. { int32 hl, n1;
  2831. if (!is_fixnum(n)) return aerror1("char", n);
  2832. hl = length_of_header(h) - 4;
  2833. n1 = int_of_fixnum(n);
  2834. if (n1 < 0 || n1 >= hl) return aerror1("schar", n);
  2835. return onevalue(pack_char(0, 0, celt(v, n1)));
  2836. }
  2837. return Laref(nil, 2, v, n);
  2838. }
  2839. /*
  2840. * (defun charset (s n c)
  2841. * (cond
  2842. * ((simple-string-p s) (putv-char s n c))
  2843. * (t (aset s n c))))
  2844. */
  2845. static Lisp_Object MS_CDECL Lcharset(Lisp_Object nil, int nargs, ...)
  2846. {
  2847. Lisp_Object v, n, c;
  2848. Header h;
  2849. va_list a;
  2850. argcheck(nargs, 3, "charset");
  2851. va_start(a, nargs);
  2852. v = va_arg(a, Lisp_Object);
  2853. n = va_arg(a, Lisp_Object);
  2854. c = va_arg(a, Lisp_Object);
  2855. va_end(a);
  2856. if (!is_vector(v)) return aerror1("charset", v);
  2857. h = vechdr(v);
  2858. if (!is_fixnum(n)) return aerror1("charset", n);
  2859. if (type_of_header(h) == TYPE_STRING)
  2860. { int32 hl, n1, vx;
  2861. if (!is_fixnum(n)) return aerror1("charset", n);
  2862. hl = length_of_header(h) - 4;
  2863. if (is_fixnum(c)) vx = int_of_fixnum(c);
  2864. else if (is_char(c)) vx = code_of_char(c);
  2865. else return aerror1("charset contents", c);
  2866. n1 = int_of_fixnum(n);
  2867. if (n1 < 0 || n1 >= hl) return aerror1("charset", n);
  2868. celt(v, n1) = (int)vx;
  2869. return onevalue(c);
  2870. }
  2871. return Laset(nil, 3, v, n, c);
  2872. }
  2873. /*
  2874. * (defun make-string (len &key (initial-element #\ ))
  2875. * (let ((s (make-simple-string len)))
  2876. * (dotimes (i len) (charset s i initial-element))
  2877. * s))
  2878. */
  2879. static Lisp_Object MS_CDECL Lmake_string(Lisp_Object nil, int nargs, ...)
  2880. {
  2881. va_list a;
  2882. Lisp_Object w, n, key, init;
  2883. int32 nn, z, blanks;
  2884. argcheck(nargs, 3, "make-string");
  2885. va_start(a, nargs);
  2886. n = va_arg(a, Lisp_Object);
  2887. key = va_arg(a, Lisp_Object);
  2888. init = va_arg(a, Lisp_Object);
  2889. va_end(a);
  2890. if (!is_fixnum(n) || (int32)n<0) return aerror1("make-string", n);
  2891. if (!is_char(init) && !is_fixnum(init))
  2892. return aerror1("make-string", init);
  2893. if (key != initial_element) return aerror1("make-string", key);
  2894. nn = int_of_fixnum(n);
  2895. w = getvector(TAG_VECTOR, TYPE_STRING, nn+4);
  2896. errexit();
  2897. z = (int32)doubleword_align_up(nn+4);
  2898. if (is_char(init)) blanks = code_of_char(init);
  2899. else blanks = int_of_fixnum(init);
  2900. blanks = (blanks << 8) | blanks;
  2901. blanks = (blanks << 16) | blanks;
  2902. while (z > 4)
  2903. { z -= 4;
  2904. *(int32 *)((char *)w - TAG_VECTOR + z) = blanks;
  2905. }
  2906. nn = nn + 4;
  2907. while ((nn & 7) != 0)
  2908. { *((char *)w - TAG_VECTOR + nn) = 0;
  2909. nn++;
  2910. }
  2911. return onevalue(w);
  2912. }
  2913. static Lisp_Object Lmake_string1(Lisp_Object nil, Lisp_Object n)
  2914. {
  2915. Lisp_Object w;
  2916. int32 nn, z, blanks;
  2917. if (!is_fixnum(n) || (int32)n<0) return aerror1("make-string", n);
  2918. nn = int_of_fixnum(n);
  2919. w = getvector(TAG_VECTOR, TYPE_STRING, nn+4);
  2920. errexit();
  2921. z = (int32)doubleword_align_up(nn+4);
  2922. blanks = (' ' << 24) | (' ' << 16) | (' ' << 8) | ' ';
  2923. while (z > 4)
  2924. { z -= 4;
  2925. *(int32 *)((char *)w - TAG_VECTOR + z) = blanks;
  2926. }
  2927. nn = nn + 4;
  2928. while ((nn & 7) != 0)
  2929. { *((char *)w - TAG_VECTOR + nn) = 0;
  2930. nn++;
  2931. }
  2932. return onevalue(w);
  2933. }
  2934. static Lisp_Object Lmake_string2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  2935. {
  2936. return Lmake_string(nil, 2, a, b);
  2937. }
  2938. /*
  2939. * (defun string (x)
  2940. * (cond
  2941. * ((stringp x) x)
  2942. * ((symbolp x) (symbol-name x))
  2943. * ((string-char-p x) (make-string 1 :initial-element x))
  2944. * (t (error "String expected, but found ~S" x))))
  2945. */
  2946. static Lisp_Object Lstring(Lisp_Object nil, Lisp_Object a)
  2947. {
  2948. Header h;
  2949. Lisp_Object w;
  2950. if (!is_vector(a))
  2951. { char dd[4];
  2952. if (symbolp(a)) return onevalue(qpname(a));
  2953. if (!is_char(a)) return aerror1("string", a);
  2954. dd[0] = 'x'; /* Done this way in case character arg has code 0 */
  2955. dd[1] = 0;
  2956. w = make_string(dd);
  2957. errexit();
  2958. celt(w, 0) = code_of_char(a);
  2959. return onevalue(w);
  2960. }
  2961. h = vechdr(a);
  2962. if (type_of_header(h) == TYPE_STRING) return onevalue(a);
  2963. else if (type_of_header(h) != TYPE_ARRAY) return aerror1("string", a);
  2964. /*
  2965. * Beware abolition of 'string-char
  2966. */
  2967. else if (elt(a, 0) != string_char_sym) return aerror1("string", a);
  2968. w = elt(a, 1);
  2969. if (!consp(w) || consp(qcdr(w))) return aerror1("string", a);
  2970. else return onevalue(a);
  2971. }
  2972. /*
  2973. * (defun list-to-vector (old)
  2974. * (let* ((len (length old))
  2975. * (new (make-simple-vector len)))
  2976. * (dotimes (i len new) (putv new i (car old)) (setq old (cdr old)))))
  2977. */
  2978. static Lisp_Object Llist_to_vector(Lisp_Object nil, Lisp_Object a)
  2979. {
  2980. Lisp_Object v;
  2981. int32 n = 4;
  2982. /*
  2983. * The general LENGTH function deals with vectors as well as lists, and
  2984. * returns a Lisp integer result. So here I just write out a simple in-line
  2985. * version.
  2986. */
  2987. for (v=a; consp(v); v = qcdr(v)) n += 4;
  2988. push(a);
  2989. v = getvector(TAG_VECTOR, TYPE_SIMPLE_VEC, n);
  2990. pop(a);
  2991. errexit();
  2992. for(n=0; consp(a); a = qcdr(a), n++) elt(v, n) = qcar(a);
  2993. if ((n & 1) == 0) elt(v, n) = nil; /* Padder word */
  2994. return onevalue(v);
  2995. }
  2996. /*
  2997. * (defun copy-vector (old)
  2998. * ;; At present this only copies general vectors...
  2999. * (let* ((len (vector-bound old))
  3000. * (new (make-simple-vector len)))
  3001. * (dotimes (i len new) (putv new i (svref old i)))))
  3002. */
  3003. static Lisp_Object Lcopy_vector(Lisp_Object nil, Lisp_Object a)
  3004. {
  3005. return onevalue(nil);
  3006. }
  3007. /*
  3008. * (defun vector (&rest args)
  3009. * ;; Note that a vector made this way can have at most 50 elements...
  3010. * (let* ((l (length args))
  3011. * (g (make-simple-vector l)))
  3012. * (dotimes (i l g)
  3013. * (putv g i (car args))
  3014. * (setq args (cdr args)))))
  3015. */
  3016. static Lisp_Object MS_CDECL Lvector(Lisp_Object nil, int nargs, ...)
  3017. {
  3018. Lisp_Object r = nil, w;
  3019. va_list a;
  3020. va_start(a, nargs);
  3021. push_args(a, nargs);
  3022. r = getvector(TAG_VECTOR, TYPE_SIMPLE_VEC, 4*nargs+4);
  3023. errexitn(nargs);
  3024. /*
  3025. * The next line allows for the fact that vectors MUST pad to an even
  3026. * number of words.
  3027. */
  3028. if ((nargs & 1) == 0) elt(r, nargs) = nil;
  3029. while (nargs > 0)
  3030. { pop(w);
  3031. elt(r, --nargs) = w;
  3032. }
  3033. return onevalue(r);
  3034. }
  3035. static Lisp_Object Lvector1(Lisp_Object nil, Lisp_Object a)
  3036. {
  3037. return Lvector(nil, 1, a);
  3038. }
  3039. static Lisp_Object Lvector2(Lisp_Object nil, Lisp_Object a, Lisp_Object b)
  3040. {
  3041. return Lvector(nil, 2, a, b);
  3042. }
  3043. static Lisp_Object Lshrink_vector(Lisp_Object nil,
  3044. Lisp_Object v, Lisp_Object n)
  3045. {
  3046. int32 n1, n2;
  3047. if (!is_vector(v)) return aerror1("shrink-vector", v);
  3048. if (!is_fixnum(n)) return aerror1("shrink-vector", n);
  3049. n1 = length_of_header(vechdr(v));
  3050. n2 = 4*int_of_fixnum(n)+4;
  3051. if (n2 >= n1) return onevalue(v); /* Not shrunk at all */
  3052. if (n1==n2+4 && (n2&4)==0) /* No space to free */
  3053. *(Lisp_Object *)((char *)v-TAG_VECTOR+n2) = nil;
  3054. else
  3055. { int32 n2a = doubleword_align_up(n2);
  3056. n1 = doubleword_align_up(n1);
  3057. *(Lisp_Object *)((char *)v-TAG_VECTOR+n1) =
  3058. TAG_ODDS+TYPE_STRING+((n1-n2a)<<10);
  3059. }
  3060. vechdr(v) = TAG_ODDS+type_of_header(vechdr(v))+(n2<<10);
  3061. return onevalue(v);
  3062. }
  3063. static Lisp_Object Lmake_simple_bitvector(Lisp_Object nil, Lisp_Object n)
  3064. {
  3065. int32 bytes;
  3066. Lisp_Object w;
  3067. int32 n1;
  3068. if (!is_fixnum(n) || (int32)n<0)
  3069. return aerror1("make-simple-bitvector", n);
  3070. n1 = int_of_fixnum(n);
  3071. bytes = 4+(n1+7)/8;
  3072. #define bitvechdr_(n) (TYPE_BITVEC1 + ((((n)+7)&7)<<7))
  3073. w = getvector(TAG_VECTOR, bitvechdr_(n1), bytes);
  3074. errexit();
  3075. n1 = doubleword_align_up(bytes);
  3076. while (n1 > 4)
  3077. { n1 -= 4;
  3078. *(int32 *)((char *)w - TAG_VECTOR + n1) = 0;
  3079. }
  3080. return onevalue(w);
  3081. }
  3082. static Lisp_Object MS_CDECL Lbputv(Lisp_Object nil, int nargs, ...)
  3083. {
  3084. Header h;
  3085. va_list a;
  3086. int b;
  3087. int32 n1;
  3088. Lisp_Object v, n, x;
  3089. argcheck(nargs, 3, "bputv");
  3090. va_start(a, nargs);
  3091. v = va_arg(a, Lisp_Object);
  3092. n = va_arg(a, Lisp_Object);
  3093. x = va_arg(a, Lisp_Object);
  3094. va_end(a);
  3095. CSL_IGNORE(nil);
  3096. /*
  3097. * This code is WRONG at present in that unexpectedly it is supposed to
  3098. * support bit-arrays of arbitrary rank, and not just simple vectors.
  3099. */
  3100. if (!(is_vector(v)) || !header_of_bitvector(h = vechdr(v)))
  3101. return aerror1("putv-bit", v);
  3102. if (!is_fixnum(n)) return aerror1("putv-bit", n);
  3103. if (!is_fixnum(x)) return aerror1("putv-bit contents", x);
  3104. x = int_of_fixnum(x) & 1;
  3105. h = length_of_header(h) - 4;
  3106. n1 = int_of_fixnum(n);
  3107. b = 1 << (n1 & 7); /* Bit selector */
  3108. n1 = n1 >> 3; /* Byte selector */
  3109. /*
  3110. * I am just a bit shoddy here - I only complain if an attempt is made to
  3111. * access beyond the last active byte of a bitvector - I do not
  3112. * do bound checking accurate to bit positions.
  3113. */
  3114. if (n1 < 0 || n1 >= (int32)h) return aerror1("putv-bit", n);
  3115. if (x == 0) ucelt(v, n1) &= ~b;
  3116. else ucelt(v, n1) |= b;
  3117. return onevalue(fixnum_of_int(x));
  3118. }
  3119. static Lisp_Object Lbgetv(Lisp_Object nil, Lisp_Object v, Lisp_Object n)
  3120. {
  3121. Header h;
  3122. int b;
  3123. int32 n1;
  3124. CSL_IGNORE(nil);
  3125. /*
  3126. * This code is WRONG at present in that unexpectedly it is supposed to
  3127. * support bit-arrays of arbitrary rank, and not just simple vectors.
  3128. */
  3129. if (!(is_vector(v)) || !header_of_bitvector(h = vechdr(v)))
  3130. return aerror1("getv-bit", v);
  3131. if (!is_fixnum(n)) return aerror1("getv-bit", n);
  3132. h = length_of_header(h) - 4;
  3133. n1 = int_of_fixnum(n);
  3134. b = 1 << (n1 & 7); /* Bit selector */
  3135. n1 = n1 >> 3; /* Byte selector */
  3136. if (n1 < 0 || n1 >= (int32)h) return aerror1("getv-bit", n);
  3137. if ((ucelt(v, n1) & b) == 0)
  3138. return onevalue(fixnum_of_int(0));
  3139. else return onevalue(fixnum_of_int(1));
  3140. }
  3141. #endif /* COMMON */
  3142. Lisp_Object Lupbv(Lisp_Object nil, Lisp_Object v)
  3143. {
  3144. Header h;
  3145. int32 n;
  3146. CSL_IGNORE(nil);
  3147. /*
  3148. * in non segmented mode this will support BPS, but really
  3149. * you ought not to rely on that.
  3150. */
  3151. if (!(is_vector(v))) return onevalue(nil); /* Standard Lisp demands.. */
  3152. h = vechdr(v);
  3153. n = length_of_header(h) - 4;
  3154. #ifdef COMMON
  3155. if (header_of_bitvector(h))
  3156. { n = (n - 1)*8;
  3157. n += ((h & 0x380) >> 7) + 1;
  3158. }
  3159. else
  3160. #endif
  3161. switch (type_of_header(h))
  3162. {
  3163. case TYPE_STRING:
  3164. case TYPE_VEC8:
  3165. break;
  3166. case TYPE_VEC16:
  3167. n = n >> 1;
  3168. break;
  3169. case TYPE_FLOAT64:
  3170. n = (n - 4) >> 3;
  3171. break;
  3172. default:
  3173. n = n >> 2;
  3174. break;
  3175. }
  3176. n--; /* c.f. mkvect */
  3177. return onevalue(fixnum_of_int(n));
  3178. }
  3179. #ifdef COMMON
  3180. Lisp_Object Lvecbnd(Lisp_Object nil, Lisp_Object v)
  3181. {
  3182. Header h;
  3183. int32 n;
  3184. CSL_IGNORE(nil);
  3185. /*
  3186. * in non segmented mode this will support BPS, but really
  3187. * you ought not to rely on that.
  3188. */
  3189. if (!(is_vector(v))) return aerror1("vector-bound", v);
  3190. h = vechdr(v);
  3191. n = length_of_header(h) - 4;
  3192. if (header_of_bitvector(h))
  3193. { n = (n - 1)*8;
  3194. n += ((h & 0x380) >> 7) + 1;
  3195. }
  3196. else switch (type_of_header(h))
  3197. {
  3198. case TYPE_STRING:
  3199. case TYPE_VEC8:
  3200. break;
  3201. case TYPE_VEC16:
  3202. n = n >> 1;
  3203. break;
  3204. case TYPE_FLOAT64:
  3205. n = (n - 4) >> 3;
  3206. break;
  3207. default:
  3208. n = n >> 2;
  3209. break;
  3210. }
  3211. return onevalue(fixnum_of_int(n));
  3212. }
  3213. #endif
  3214. #ifdef COMMON
  3215. /*
  3216. * The following were added for efficiency reasons, MCD 14/8/96
  3217. */
  3218. Lisp_Object list_subseq(Lisp_Object sequence, int32 start, int32 end)
  3219. {
  3220. Lisp_Object nil=C_nil, copy, last, new, seq=sequence;
  3221. int32 i, seq_length, pntr = start;
  3222. seq_length = end - start;
  3223. /* Find start of subsequence */
  3224. while (consp(seq) && pntr > 0) {
  3225. pntr--;
  3226. seq = qcdr(seq);
  3227. }
  3228. if (!consp(seq)) return aerror1("subseq",sequence);
  3229. copy = nil;
  3230. /* Store the values */
  3231. push(sequence);
  3232. while (consp(seq) && pntr < seq_length) {
  3233. push3(seq,copy,last);
  3234. new = Lcons(nil,qcar(seq),nil);
  3235. pop3(last,copy,seq);
  3236. if (pntr == 0)
  3237. copy = new;
  3238. else
  3239. qcdr(last) = new;
  3240. last = new;
  3241. seq = qcdr(seq);
  3242. pntr++;
  3243. }
  3244. pop(sequence);
  3245. errexit();
  3246. if (pntr != seq_length) return aerror1("subseq",sequence);
  3247. return onevalue(copy);
  3248. }
  3249. Lisp_Object vector_subseq(Lisp_Object sequence, int32 start, int32 end)
  3250. {
  3251. Lisp_Object nil=C_nil, copy;
  3252. Header h;
  3253. int32 hl, seq_length, i;
  3254. if (is_cons(sequence))
  3255. return list_subseq(sequence,start,end);
  3256. else if (!is_vector(sequence))
  3257. return aerror1("vector-subseq*",sequence);
  3258. seq_length = end - start;
  3259. h = vechdr(sequence);
  3260. if (type_of_header(h) == TYPE_SIMPLE_VEC ) {
  3261. hl = (length_of_header(h) - 4) >> 2;
  3262. if (hl < end) return aerror0("vector-subseq* out of range");
  3263. /*
  3264. * Since we are dealing with a simple vector the following shift is
  3265. * guarenteed to work. The extra 4 bytes are for the header.
  3266. */
  3267. copy = getvector_init(4+(seq_length << 2),nil);
  3268. for (i=start; i < end; ++i) elt(copy,i-start) = elt(sequence,i);
  3269. return onevalue(copy);
  3270. }
  3271. else if (type_of_header(h) == TYPE_STRING) {
  3272. char *s;
  3273. int32 k;
  3274. hl = length_of_header(h) - 4;
  3275. if (hl < end) return aerror0("vector-subseq* out of range");
  3276. /* Get a new string of the right size */
  3277. push(sequence);
  3278. copy = getvector(TAG_VECTOR, TYPE_STRING, 4+seq_length);
  3279. pop(sequence);
  3280. /* This code plagiarised from copy_string ... */
  3281. s = (char *)copy - TAG_VECTOR;
  3282. k = (seq_length + 3) & ~(int32)7;
  3283. errexit();
  3284. *(int32 *)(s + k + 4) = 0;
  3285. if (k != 0) *(int32 *)(s + k) = 0;
  3286. memcpy(s + 4, (char *)sequence+(4L-TAG_VECTOR)+start, (size_t)seq_length);
  3287. return onevalue(copy);
  3288. }
  3289. else if (header_of_bitvector(h)) {
  3290. hl = length_of_header(h) - 4;
  3291. if (hl < (end >> 3)) return aerror0("vector-subseq* out of range");
  3292. /* Grab a bit-vector of the right size */
  3293. push(sequence);
  3294. copy = Lmake_simple_bitvector(nil,fixnum_of_int(seq_length));
  3295. pop(sequence);
  3296. errexit();
  3297. /*
  3298. * This is not terribly efficient since the calls to Lbputv and Lbgetv
  3299. * ought to be coded inline, but on the other hand its no worse than the
  3300. * original Lisp-coded version.
  3301. */
  3302. for (i=start; i<end; ++i) {
  3303. push2(sequence,copy);
  3304. Lbputv(nil,3,copy,fixnum_of_int(i-start),
  3305. Lbgetv(nil,sequence,fixnum_of_int(i)));
  3306. pop2(copy,sequence);
  3307. errexit();
  3308. }
  3309. return onevalue(copy);
  3310. }
  3311. else if (type_of_header(h) == TYPE_ARRAY) {
  3312. /* elt(sequence, 1) is the list of dimensions - only handle 1-d case */
  3313. if (qcdr(elt(sequence, 1)) != nil)
  3314. return aerror1("vector-subseq*",sequence);
  3315. i = int_of_fixnum(elt(sequence, 3)); /* displaced-index-offset */
  3316. return vector_subseq(elt(sequence,2),start+i,end+i);
  3317. }
  3318. else
  3319. return aerror1("vector-subseq*",sequence);
  3320. }
  3321. Lisp_Object Llist_subseq1(Lisp_Object nil, Lisp_Object seq, Lisp_Object start)
  3322. {
  3323. Lisp_Object len;
  3324. int32 first, last;
  3325. first = int_of_fixnum(start);
  3326. push(seq);
  3327. len = Llength(nil,seq);
  3328. pop(seq);
  3329. errexit();
  3330. last = int_of_fixnum(len);
  3331. if (first > last) return aerror1("list-subseq* out of range",seq);
  3332. return list_subseq(seq, first, last);
  3333. }
  3334. Lisp_Object MS_CDECL Llist_subseq2(Lisp_Object nil, int32 nargs, ...)
  3335. {
  3336. va_list args;
  3337. int32 first, last;
  3338. Lisp_Object seq, start, end;
  3339. argcheck(nargs, 3, "list-subseq*");
  3340. va_start(args, nargs);
  3341. seq = va_arg(args, Lisp_Object);
  3342. start = va_arg(args, Lisp_Object);
  3343. end = va_arg(args, Lisp_Object);
  3344. va_end(args);
  3345. first = int_of_fixnum(start);
  3346. last = int_of_fixnum(end);
  3347. if (first > last) return aerror1("list-subseq* out of range",seq);
  3348. return list_subseq(seq, first, last);
  3349. }
  3350. Lisp_Object Lvector_subseq1(Lisp_Object nil, Lisp_Object seq, Lisp_Object start)
  3351. {
  3352. Lisp_Object len;
  3353. int32 first, last;
  3354. first = int_of_fixnum(start);
  3355. push(seq);
  3356. len = Llength(nil,seq);
  3357. pop(seq);
  3358. errexit();
  3359. last = int_of_fixnum(len);
  3360. if (first > last) return aerror1("vector-subseq* out of range",seq);
  3361. return vector_subseq(seq, first, last);
  3362. }
  3363. Lisp_Object MS_CDECL Lvector_subseq2(Lisp_Object nil, int32 nargs, ...)
  3364. {
  3365. va_list args;
  3366. int32 first, last;
  3367. Lisp_Object seq, start, end;
  3368. argcheck(nargs, 3, "vector-subseq*");
  3369. va_start(args, nargs);
  3370. seq = va_arg(args, Lisp_Object);
  3371. start = va_arg(args, Lisp_Object);
  3372. end = va_arg(args, Lisp_Object);
  3373. va_end(args);
  3374. first = int_of_fixnum(start);
  3375. last = int_of_fixnum(end);
  3376. if (first > last) return aerror1("vector-subseq* out of range",seq);
  3377. return vector_subseq(seq, first, last);
  3378. }
  3379. #endif
  3380. setup_type const funcs3_setup[] =
  3381. {
  3382. {"getv", too_few_2, Lgetv, wrong_no_2},
  3383. {"putv", wrong_no_3a, wrong_no_3b, Lputv},
  3384. {"getv8", too_few_2, Lgetv8, wrong_no_2},
  3385. {"putv8", wrong_no_3a, wrong_no_3b, Lputv8},
  3386. {"getv16", too_few_2, Lgetv16, wrong_no_2},
  3387. {"putv16", wrong_no_3a, wrong_no_3b, Lputv16},
  3388. {"getv32", too_few_2, Lgetv32, wrong_no_2},
  3389. {"putv32", wrong_no_3a, wrong_no_3b, Lputv32},
  3390. {"fgetv32", too_few_2, Lfgetv32, wrong_no_2},
  3391. {"fputv32", wrong_no_3a, wrong_no_3b, Lfputv32},
  3392. {"fgetv64", too_few_2, Lfgetv64, wrong_no_2},
  3393. {"fputv64", wrong_no_3a, wrong_no_3b, Lfputv64},
  3394. {"qgetv", too_few_2, Lgetv, wrong_no_2},
  3395. {"egetv", too_few_2, Lgetv, wrong_no_2},
  3396. {"qputv", wrong_no_3a, wrong_no_3b, Lputv},
  3397. {"eputv", wrong_no_3a, wrong_no_3b, Lputv},
  3398. {"make-simple-string", Lsmkvect, too_many_1, wrong_no_1},
  3399. {"putv-char", wrong_no_3a, wrong_no_3b, Lsputv},
  3400. {"bps-putv", wrong_no_3a, wrong_no_3b, Lbpsputv},
  3401. {"bps-getv", too_few_2, Lbpsgetv, wrong_no_2},
  3402. {"bps-upbv", Lbpsupbv, too_many_1, wrong_no_1},
  3403. {"native-type", wrong_no_na, wrong_no_nb, Lnative_type},
  3404. {"native-putv", wrong_no_3a, wrong_no_3b, Lnativeputv},
  3405. {"native-getv", too_few_2, Lnativegetv, Lnativegetvn},
  3406. {"native-address", Lnative_address1, Lnative_address, wrong_no_2},
  3407. {"eupbv", Lupbv, too_many_1, wrong_no_1},
  3408. {"schar", too_few_2, Lsgetv, wrong_no_2},
  3409. {"scharn", too_few_2, Lsgetvn, wrong_no_2},
  3410. {"byte-getv", too_few_2, Lbytegetv, wrong_no_2},
  3411. {"mkvect", Lmkvect, too_many_1, wrong_no_1},
  3412. {"mkevect", Lmkevect, too_many_1, wrong_no_1},
  3413. {"mkxvect", Lmkxvect, too_many_1, wrong_no_1},
  3414. {"mkvect8", Lmkvect8, too_many_1, wrong_no_1},
  3415. {"mkvect16", Lmkvect16, too_many_1, wrong_no_1},
  3416. {"mkvect32", Lmkvect32, too_many_1, wrong_no_1},
  3417. {"mkfvect32", Lmkfvect32, too_many_1, wrong_no_1},
  3418. {"mkfvect64", Lmkfvect64, too_many_1, wrong_no_1},
  3419. {"mkhash", wrong_no_3a, wrong_no_3b, Lmkhash},
  3420. {"gethash", Lget_hash_1, Lget_hash_2, Lget_hash},
  3421. {"puthash", wrong_no_3a, Lput_hash_2, Lput_hash},
  3422. {"remhash", Lrem_hash_1, Lrem_hash, wrong_no_2},
  3423. {"clrhash", Lclr_hash, too_many_1, Lclr_hash_0},
  3424. {"sxhash", Lsxhash, too_many_1, wrong_no_1},
  3425. {"eqlhash", Leqlhash, too_many_1, wrong_no_1},
  3426. {"maphash", too_few_2, Lmaphash, wrong_no_2},
  3427. {"hashcontents", Lhashcontents, too_many_1, wrong_no_1},
  3428. {"upbv", Lupbv, too_many_1, wrong_no_1},
  3429. #ifdef COMMON
  3430. {"hashtable-flavour", Lhash_flavour, too_many_1, wrong_no_1},
  3431. {"getv-bit", too_few_2, Lbgetv, wrong_no_2},
  3432. {"sbit", too_few_2, Lbgetv, wrong_no_2},
  3433. {"make-simple-bitvector", Lmake_simple_bitvector, too_many_1, wrong_no_1},
  3434. {"make-simple-vector", Lmksimplevec, too_many_1, wrong_no_1},
  3435. {"putv-bit", wrong_no_3a, wrong_no_3b, Lbputv},
  3436. {"sbitset", wrong_no_3a, wrong_no_3b, Lbputv},
  3437. {"svref", too_few_2, Lgetv, wrong_no_2},
  3438. {"vector-bound", Lvecbnd, too_many_1, wrong_no_1},
  3439. {"putvec", wrong_no_3a, wrong_no_3b, Lputvec},
  3440. {"aref", Laref1, Laref2, Laref},
  3441. {"aset", Laset1, Laset2, Laset},
  3442. {"elt", too_few_2, Lelt, wrong_no_2},
  3443. {"setelt", wrong_no_3a, wrong_no_3b, Lsetelt},
  3444. {"vectorp", Lvectorp, too_many_1, wrong_no_1},
  3445. {"char", too_few_2, Lchar, wrong_no_2},
  3446. {"charset", wrong_no_3a, wrong_no_3b, Lcharset},
  3447. {"make-string", Lmake_string1, Lmake_string2, Lmake_string},
  3448. {"list-to-vector", Llist_to_vector, too_many_1, wrong_no_1},
  3449. {"vector", Lvector1, Lvector2, Lvector},
  3450. {"shrink-vector", too_few_2, Lshrink_vector, wrong_no_2},
  3451. {"string", Lstring, too_many_1, wrong_no_1},
  3452. #ifdef COMMON
  3453. {"vector-subseq*", wrong_no_3a, Lvector_subseq1, Lvector_subseq2},
  3454. {"list-subseq*", wrong_no_3a, Llist_subseq1, Llist_subseq2},
  3455. {"subseq", wrong_no_3a, Lvector_subseq1, Lvector_subseq2},
  3456. #endif
  3457. /* The "x" is temporary while I debug */
  3458. {"xcopy-vector", Lcopy_vector, too_many_1, wrong_no_1},
  3459. #endif
  3460. {NULL, 0, 0, 0}
  3461. };
  3462. /* end of fns3.c */