fns3.c 130 KB

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