external.c 69 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447
  1. /* Copyright (c) 1993-2008 by Richard Kelsey and Jonathan Rees.
  2. See file COPYING. */
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include <string.h>
  6. #include <setjmp.h>
  7. #include <stdarg.h>
  8. #include "c-mods.h"
  9. #include "scheme48.h"
  10. #include "scheme48vm.h"
  11. #include "bignum.h"
  12. #include "ffi.h"
  13. /*
  14. * The Joy of C
  15. * I don't understand why we need this, but we do.
  16. */
  17. struct s_jmp_buf {
  18. jmp_buf buf;
  19. };
  20. /*
  21. * Longjump target set up by the most recent call into C.
  22. */
  23. static struct s_jmp_buf current_return_point;
  24. /*
  25. * The name of the procedure we are currently executing; used for error messages.
  26. */
  27. static s48_ref_t current_procedure = NULL;
  28. /*
  29. * Stack of Scheme stack-block records which represent portions of the process
  30. * stack.
  31. */
  32. static s48_ref_t current_stack_block = NULL;
  33. /*
  34. * These need to agree with the record definition in callback.scm.
  35. */
  36. #define STACK_BLOCK_FREE(stack_block) S48_UNSAFE_RECORD_REF(stack_block, 0)
  37. #define STACK_BLOCK_UNWIND(stack_block) S48_UNSAFE_RECORD_REF(stack_block, 1)
  38. #define STACK_BLOCK_PROC(stack_block) S48_UNSAFE_RECORD_REF(stack_block, 2)
  39. #define STACK_BLOCK_THREAD(stack_block) S48_UNSAFE_RECORD_REF(stack_block, 3)
  40. #define STACK_BLOCK_NEXT(stack_block) S48_UNSAFE_RECORD_REF(stack_block, 4)
  41. #define STACK_BLOCK_FREE_2(c, stack_block) \
  42. s48_unsafe_record_ref_2(c, stack_block, 0)
  43. #define STACK_BLOCK_UNWIND_2(c, stack_block) \
  44. s48_unsafe_record_ref_2(c, stack_block, 1)
  45. #define STACK_BLOCK_PROC_2(c, stack_block) \
  46. s48_unsafe_record_ref_2(c, stack_block, 2)
  47. #define STACK_BLOCK_THREAD_2(c, stack_block) \
  48. s48_unsafe_record_ref_2(c, stack_block, 3)
  49. #define STACK_BLOCK_NEXT_2(c, stack_block) \
  50. s48_unsafe_record_ref_2(c, stack_block, 4)
  51. #define s48_push_2(c, x) s48_push(s48_deref(x))
  52. #ifdef DEBUG_FFI
  53. /*
  54. * For debugging.
  55. */
  56. static int callback_depth()
  57. {
  58. int depth = 0;
  59. s48_value stack = s48_deref(current_stack_block);
  60. for(; stack != S48_FALSE; depth++, stack = STACK_BLOCK_NEXT(stack));
  61. return depth;
  62. }
  63. #endif
  64. /*
  65. * The value being returned from an external call. The returns may be preceded
  66. * by a longjmp(), so we stash the value here.
  67. */
  68. static s48_value external_return_value;
  69. /* Exports to Scheme */
  70. static s48_value s48_clear_stack_top(void);
  71. static s48_ref_t s48_clear_stack_top_2(s48_call_t call);
  72. static s48_ref_t s48_system_2(s48_call_t call, s48_ref_t string);
  73. /* Imports from Scheme */
  74. static s48_ref_t the_record_type_binding = NULL;
  75. static s48_ref_t stack_block_type_binding = NULL;
  76. static s48_ref_t callback_binding = NULL;
  77. static s48_ref_t delay_callback_return_binding = NULL;
  78. #ifdef DEBUG_FFI
  79. static s48_value s48_trampoline(s48_value proc, s48_value nargs);
  80. static s48_ref_t s48_trampoline_2(s48_call_t call, s48_ref_t proc, s48_ref_t nargs);
  81. #endif
  82. void
  83. s48_initialize_external()
  84. {
  85. the_record_type_binding =
  86. s48_get_imported_binding_2("s48-the-record-type");
  87. stack_block_type_binding =
  88. s48_get_imported_binding_2("s48-stack-block-type");
  89. callback_binding =
  90. s48_get_imported_binding_2("s48-callback");
  91. delay_callback_return_binding =
  92. s48_get_imported_binding_2("s48-delay-callback-return");
  93. current_stack_block = s48_make_global_ref(_s48_value_false);
  94. current_procedure = s48_make_global_ref(_s48_value_false);
  95. S48_EXPORT_FUNCTION(s48_clear_stack_top);
  96. S48_EXPORT_FUNCTION(s48_clear_stack_top_2);
  97. S48_EXPORT_FUNCTION(s48_system_2);
  98. #ifdef DEBUG_FFI
  99. S48_EXPORT_FUNCTION(s48_trampoline);
  100. S48_EXPORT_FUNCTION(s48_trampoline_2);
  101. init_debug_ffi ();
  102. #endif
  103. }
  104. /* The three reasons for an extern-call longjump. */
  105. #define NO_THROW 0
  106. #define EXCEPTION_THROW 1
  107. #define CLEANUP_THROW 2
  108. /*
  109. * Used to call `proc' from Scheme code. `nargs' the number of arguments in
  110. * vector `argv'. If `spread_p' is true the procedure is applied to the
  111. * arguments, otherwise `proc' is just called on `nargs' and `argv'.
  112. *
  113. * We do a setjmp() to get a return point for clearing off this portion of
  114. * the process stack. This is used when `proc' calls back to Scheme and
  115. * then a throw transfers control up past the call to `proc'.
  116. */
  117. typedef s48_value (*proc_0_t)(void);
  118. typedef s48_value (*proc_1_t)(s48_value);
  119. typedef s48_value (*proc_2_t)(s48_value, s48_value);
  120. typedef s48_value (*proc_3_t)(s48_value, s48_value, s48_value);
  121. typedef s48_value (*proc_4_t)(s48_value, s48_value, s48_value, s48_value);
  122. typedef s48_value (*proc_5_t)(s48_value, s48_value, s48_value, s48_value,
  123. s48_value);
  124. typedef s48_value (*proc_6_t)(s48_value, s48_value, s48_value, s48_value,
  125. s48_value, s48_value);
  126. typedef s48_value (*proc_7_t)(s48_value, s48_value, s48_value, s48_value,
  127. s48_value, s48_value, s48_value);
  128. typedef s48_value (*proc_8_t)(s48_value, s48_value, s48_value, s48_value,
  129. s48_value, s48_value, s48_value, s48_value);
  130. typedef s48_value (*proc_9_t)(s48_value, s48_value, s48_value, s48_value,
  131. s48_value, s48_value, s48_value, s48_value,
  132. s48_value);
  133. typedef s48_value (*proc_10_t)(s48_value, s48_value, s48_value, s48_value,
  134. s48_value, s48_value, s48_value, s48_value,
  135. s48_value, s48_value);
  136. typedef s48_value (*proc_11_t)(s48_value, s48_value, s48_value, s48_value,
  137. s48_value, s48_value, s48_value, s48_value,
  138. s48_value, s48_value, s48_value);
  139. typedef s48_value (*proc_12_t)(s48_value, s48_value, s48_value, s48_value,
  140. s48_value, s48_value, s48_value, s48_value,
  141. s48_value, s48_value, s48_value, s48_value);
  142. typedef s48_value (*proc_n_t)(int, s48_value []);
  143. s48_value
  144. s48_external_call(s48_value sch_proc, s48_value proc_name,
  145. long nargs, char *char_argv)
  146. {
  147. volatile char *gc_roots_marker; /* volatile to survive longjumps */
  148. volatile s48_value name = proc_name; /* volatile to survive longjumps */
  149. #ifdef DEBUG_FFI
  150. int depth; /* debugging */
  151. #endif
  152. long *argv = (long *) char_argv;
  153. proc_0_t proc = S48_EXTRACT_VALUE(sch_proc, proc_0_t);
  154. int throw_reason;
  155. s48_setref(current_procedure, name);
  156. S48_CHECK_VALUE(sch_proc);
  157. S48_CHECK_STRING(name);
  158. gc_roots_marker = s48_set_gc_roots_baseB();
  159. #ifdef DEBUG_FFI
  160. depth = callback_depth();
  161. fprintf(stderr, "[external_call at depth %d]\n", depth);
  162. #endif
  163. throw_reason = setjmp(current_return_point.buf);
  164. if (throw_reason == NO_THROW) { /* initial entry */
  165. switch (nargs) {
  166. case 0:
  167. external_return_value = proc();
  168. break;
  169. case 1:
  170. external_return_value = ((proc_1_t)proc)(argv[0]);
  171. break;
  172. case 2:
  173. external_return_value = ((proc_2_t)proc)(argv[1], argv[0]);
  174. break;
  175. case 3:
  176. external_return_value = ((proc_3_t)proc)(argv[2], argv[1], argv[0]);
  177. break;
  178. case 4:
  179. external_return_value = ((proc_4_t)proc)(argv[3], argv[2], argv[1], argv[0]);
  180. break;
  181. case 5:
  182. external_return_value = ((proc_5_t)proc)(argv[4],
  183. argv[3], argv[2], argv[1], argv[0]);
  184. break;
  185. case 6:
  186. external_return_value = ((proc_6_t)proc)(argv[5], argv[4],
  187. argv[3], argv[2], argv[1], argv[0]);
  188. break;
  189. case 7:
  190. external_return_value = ((proc_7_t)proc)(argv[6], argv[5], argv[4],
  191. argv[3], argv[2], argv[1], argv[0]);
  192. break;
  193. case 8:
  194. external_return_value = ((proc_8_t)proc)(argv[7], argv[6], argv[5], argv[4],
  195. argv[3], argv[2], argv[1], argv[0]);
  196. break;
  197. case 9:
  198. external_return_value = ((proc_9_t)proc)(argv[8],
  199. argv[7], argv[6], argv[5], argv[4],
  200. argv[3], argv[2], argv[1], argv[0]);
  201. break;
  202. case 10:
  203. external_return_value = ((proc_10_t)proc)(argv[9], argv[8],
  204. argv[7], argv[6], argv[5], argv[4],
  205. argv[3], argv[2], argv[1], argv[0]);
  206. break;
  207. case 11:
  208. external_return_value = ((proc_11_t)proc)(argv[10], argv[9], argv[8],
  209. argv[7], argv[6], argv[5], argv[4],
  210. argv[3], argv[2], argv[1], argv[0]);
  211. break;
  212. case 12:
  213. external_return_value = ((proc_12_t)proc)(argv[11], argv[10], argv[9], argv[8],
  214. argv[7], argv[6], argv[5], argv[4],
  215. argv[3], argv[2], argv[1], argv[0]);
  216. break;
  217. default:
  218. external_return_value = ((proc_n_t)proc)((int)nargs, (s48_value *)argv);
  219. }
  220. /* Raise an exception if the user neglected to pop off some gc roots. */
  221. if (! s48_release_gc_roots_baseB((char *)gc_roots_marker)) {
  222. s48_raise_scheme_exception(S48_EXCEPTION_GC_PROTECTION_MISMATCH, 0);
  223. }
  224. /* Clear any free stack-blocks off of the top of the stack-block stack and
  225. then longjmp past the corresponding portions of the process stack. */
  226. if (s48_deref(current_stack_block) != S48_FALSE &&
  227. STACK_BLOCK_FREE(s48_deref(current_stack_block)) == S48_TRUE) {
  228. s48_value bottom_free_block;
  229. do {
  230. bottom_free_block = s48_deref(current_stack_block);
  231. s48_setref(current_stack_block, STACK_BLOCK_NEXT(s48_deref(current_stack_block)));
  232. }
  233. while (s48_deref(current_stack_block) != S48_FALSE &&
  234. STACK_BLOCK_FREE(s48_deref(current_stack_block)) == S48_TRUE);
  235. #ifdef DEBUG_FFI
  236. fprintf(stderr, "[Freeing stack blocks from %d to %d]\n",
  237. depth,
  238. callback_depth());
  239. #endif
  240. longjmp(S48_EXTRACT_VALUE_POINTER(STACK_BLOCK_UNWIND(bottom_free_block),
  241. struct s_jmp_buf)->buf,
  242. CLEANUP_THROW);
  243. }
  244. }
  245. else { /* throwing an exception or unwinding the stack */
  246. #ifdef DEBUG_FFI
  247. fprintf(stderr, "[external_call throw; was %d and now %d]\n",
  248. depth,
  249. callback_depth());
  250. fprintf(stderr, "[throw unrolling to %ld]\n", gc_roots_marker);
  251. #endif
  252. s48_release_gc_roots_baseB((char *)gc_roots_marker);
  253. }
  254. /* Check to see if a thread is waiting to return to the next block down. */
  255. if (s48_deref(current_stack_block) != S48_FALSE &&
  256. STACK_BLOCK_THREAD(s48_deref(current_stack_block)) != S48_FALSE) {
  257. #ifdef DEBUG_FFI
  258. fprintf(stderr, "[releasing return at %d]\n", callback_depth());
  259. #endif
  260. if (throw_reason == EXCEPTION_THROW) {
  261. /* We are in the midst of raising an exception, so we need to piggyback
  262. our exception on that one. */
  263. s48_value old_exception
  264. = s48_resetup_external_exception(S48_EXCEPTION_CALLBACK_RETURN_UNCOVERED,
  265. 2);
  266. s48_push(old_exception);
  267. s48_push(s48_deref(current_stack_block));
  268. external_return_value = S48_UNSPECIFIC;
  269. }
  270. else {
  271. s48_setup_external_exception(S48_EXCEPTION_CALLBACK_RETURN_UNCOVERED, 2);
  272. s48_push(s48_deref(current_stack_block));
  273. s48_push(external_return_value);
  274. external_return_value = S48_UNSPECIFIC;
  275. }
  276. }
  277. return external_return_value;
  278. }
  279. /*
  280. * The value being returned from an external call. The returns may be preceded
  281. * by a longjmp(), so we stash the value here.
  282. */
  283. static s48_ref_t cexternal_return_value;
  284. typedef s48_ref_t (*cproc_0_t)(s48_call_t);
  285. typedef s48_ref_t (*cproc_1_t)(s48_call_t,
  286. s48_ref_t);
  287. typedef s48_ref_t (*cproc_2_t)(s48_call_t,
  288. s48_ref_t, s48_ref_t);
  289. typedef s48_ref_t (*cproc_3_t)(s48_call_t,
  290. s48_ref_t, s48_ref_t, s48_ref_t);
  291. typedef s48_ref_t (*cproc_4_t)(s48_call_t,
  292. s48_ref_t, s48_ref_t, s48_ref_t, s48_ref_t);
  293. typedef s48_ref_t (*cproc_5_t)(s48_call_t,
  294. s48_ref_t, s48_ref_t, s48_ref_t, s48_ref_t,
  295. s48_ref_t);
  296. typedef s48_ref_t (*cproc_6_t)(s48_call_t,
  297. s48_ref_t, s48_ref_t, s48_ref_t, s48_ref_t,
  298. s48_ref_t, s48_ref_t);
  299. typedef s48_ref_t (*cproc_7_t)(s48_call_t,
  300. s48_ref_t, s48_ref_t, s48_ref_t, s48_ref_t,
  301. s48_ref_t, s48_ref_t, s48_ref_t);
  302. typedef s48_ref_t (*cproc_8_t)(s48_call_t,
  303. s48_ref_t, s48_ref_t, s48_ref_t, s48_ref_t,
  304. s48_ref_t, s48_ref_t, s48_ref_t, s48_ref_t);
  305. typedef s48_ref_t (*cproc_9_t)(s48_call_t,
  306. s48_ref_t, s48_ref_t, s48_ref_t, s48_ref_t,
  307. s48_ref_t, s48_ref_t, s48_ref_t, s48_ref_t,
  308. s48_ref_t);
  309. typedef s48_ref_t (*cproc_10_t)(s48_call_t,
  310. s48_ref_t, s48_ref_t, s48_ref_t, s48_ref_t,
  311. s48_ref_t, s48_ref_t, s48_ref_t, s48_ref_t,
  312. s48_ref_t, s48_ref_t);
  313. typedef s48_ref_t (*cproc_11_t)(s48_call_t,
  314. s48_ref_t, s48_ref_t, s48_ref_t, s48_ref_t,
  315. s48_ref_t, s48_ref_t, s48_ref_t, s48_ref_t,
  316. s48_ref_t, s48_ref_t, s48_ref_t);
  317. typedef s48_ref_t (*cproc_12_t)(s48_call_t,
  318. s48_ref_t, s48_ref_t, s48_ref_t, s48_ref_t,
  319. s48_ref_t, s48_ref_t, s48_ref_t, s48_ref_t,
  320. s48_ref_t, s48_ref_t, s48_ref_t, s48_ref_t);
  321. typedef s48_ref_t (*cproc_n_t)(s48_call_t, int, s48_ref_t []);
  322. s48_value
  323. s48_external_ecall(s48_call_t call,
  324. s48_value sch_proc, s48_value proc_name,
  325. long nargs, char *char_argv)
  326. {
  327. volatile char *gc_roots_marker; /* volatile to survive longjumps */
  328. volatile s48_value name = proc_name; /* volatile to survive longjumps */
  329. s48_call_t new_call;
  330. s48_ref_t argv_ref[12];
  331. s48_ref_t sch_proc_ref, proc_name_ref;
  332. s48_value result;
  333. #ifdef DEBUG_FFI
  334. int depth = callback_depth(); /* debugging */
  335. #endif
  336. long *argv = (long *) char_argv;
  337. cproc_0_t cproc = S48_EXTRACT_VALUE(sch_proc, cproc_0_t);
  338. int throw_reason;
  339. s48_setref(current_procedure, name);
  340. S48_CHECK_VALUE(sch_proc);
  341. S48_CHECK_STRING(name);
  342. gc_roots_marker = s48_set_gc_roots_baseB();
  343. #ifdef DEBUG_FFI
  344. fprintf(stderr, "[external_call_2 at depth %d]\n", depth);
  345. #endif
  346. throw_reason = setjmp(current_return_point.buf);
  347. if (throw_reason == NO_THROW) { /* initial entry */
  348. long i;
  349. new_call = s48_push_call (call);
  350. for (i = 0; i < nargs; i++)
  351. argv_ref[i] = s48_make_local_ref (new_call, argv[i]);
  352. sch_proc_ref = s48_make_local_ref (new_call, sch_proc);
  353. proc_name_ref = s48_make_local_ref (new_call, proc_name);
  354. switch (nargs) {
  355. case 0:
  356. cexternal_return_value = ((cproc_0_t)cproc)(new_call);
  357. break;
  358. case 1:
  359. cexternal_return_value = ((cproc_1_t)cproc)(new_call, argv_ref[0]);
  360. break;
  361. case 2:
  362. cexternal_return_value = ((cproc_2_t)cproc)(new_call, argv_ref[1], argv_ref[0]);
  363. break;
  364. case 3:
  365. cexternal_return_value = ((cproc_3_t)cproc)(new_call, argv_ref[2], argv_ref[1], argv_ref[0]);
  366. break;
  367. case 4:
  368. cexternal_return_value = ((cproc_4_t)cproc)(new_call,
  369. argv_ref[3], argv_ref[2], argv_ref[1], argv_ref[0]);
  370. break;
  371. case 5:
  372. cexternal_return_value = ((cproc_5_t)cproc)(new_call, argv_ref[4],
  373. argv_ref[3], argv_ref[2], argv_ref[1], argv_ref[0]);
  374. break;
  375. case 6:
  376. cexternal_return_value = ((cproc_6_t)cproc)(new_call, argv_ref[5], argv_ref[4],
  377. argv_ref[3], argv_ref[2], argv_ref[1], argv_ref[0]);
  378. break;
  379. case 7:
  380. cexternal_return_value = ((cproc_7_t)cproc)(new_call, argv_ref[6], argv_ref[5], argv_ref[4],
  381. argv_ref[3], argv_ref[2], argv_ref[1], argv_ref[0]);
  382. break;
  383. case 8:
  384. cexternal_return_value = ((cproc_8_t)cproc)(new_call,
  385. argv_ref[7], argv_ref[6], argv_ref[5], argv_ref[4],
  386. argv_ref[3], argv_ref[2], argv_ref[1], argv_ref[0]);
  387. break;
  388. case 9:
  389. cexternal_return_value = ((cproc_9_t)cproc)(new_call, argv_ref[8],
  390. argv_ref[7], argv_ref[6], argv_ref[5], argv_ref[4],
  391. argv_ref[3], argv_ref[2], argv_ref[1], argv_ref[0]);
  392. break;
  393. case 10:
  394. cexternal_return_value = ((cproc_10_t)cproc)(new_call, argv_ref[9], argv_ref[8],
  395. argv_ref[7], argv_ref[6], argv_ref[5], argv_ref[4],
  396. argv_ref[3], argv_ref[2], argv_ref[1], argv_ref[0]);
  397. break;
  398. case 11:
  399. cexternal_return_value = ((cproc_11_t)cproc)(new_call, argv_ref[10], argv_ref[9], argv_ref[8],
  400. argv_ref[7], argv_ref[6], argv_ref[5], argv_ref[4],
  401. argv_ref[3], argv_ref[2], argv_ref[1], argv_ref[0]);
  402. break;
  403. case 12:
  404. cexternal_return_value = ((cproc_12_t)cproc)(new_call,
  405. argv_ref[11], argv_ref[10], argv_ref[9], argv_ref[8],
  406. argv_ref[7], argv_ref[6], argv_ref[5], argv_ref[4],
  407. argv_ref[3], argv_ref[2], argv_ref[1], argv_ref[0]);
  408. break;
  409. default:
  410. cexternal_return_value = ((cproc_n_t)cproc)(new_call, (int) nargs, argv_ref);
  411. }
  412. /* Raise an exception if the user neglected to pop off some gc roots. */
  413. if (! s48_release_gc_roots_baseB((char *)gc_roots_marker)) {
  414. s48_raise_scheme_exception(S48_EXCEPTION_GC_PROTECTION_MISMATCH, 0);
  415. }
  416. /* Clear any free stack-blocks off of the top of the stack-block stack and
  417. then longjmp past the corresponding portions of the process stack. */
  418. if (!s48_false_p_2(new_call, current_stack_block) &&
  419. s48_true_p_2(new_call, STACK_BLOCK_FREE_2(new_call, current_stack_block))) {
  420. s48_ref_t bottom_free_block;
  421. do {
  422. s48_setref(bottom_free_block, s48_deref(current_stack_block));
  423. s48_setref(current_stack_block, s48_deref(STACK_BLOCK_NEXT_2(new_call, current_stack_block)));
  424. }
  425. while (!s48_false_p_2(new_call, current_stack_block) &&
  426. s48_false_p_2(new_call, STACK_BLOCK_FREE_2(new_call, current_stack_block)));
  427. #ifdef DEBUG_FFI
  428. fprintf(stderr, "[Freeing stack blocks from %d to %d]\n",
  429. depth,
  430. callback_depth());
  431. #endif
  432. longjmp(s48_extract_value_pointer_2(new_call,
  433. STACK_BLOCK_UNWIND_2(new_call, bottom_free_block),
  434. struct s_jmp_buf)->buf,
  435. CLEANUP_THROW);
  436. }
  437. }
  438. else { /* throwing an exception or unwinding the stack */
  439. #ifdef DEBUG_FFI
  440. fprintf(stderr, "[external_call_2 throw; was %d and now %d]\n",
  441. depth,
  442. callback_depth());
  443. fprintf(stderr, "[throw unrolling to %ld]\n", gc_roots_marker);
  444. #endif
  445. s48_release_gc_roots_baseB((char *)gc_roots_marker);
  446. }
  447. /* otherwise the pop_to will kill us */
  448. if (cexternal_return_value)
  449. cexternal_return_value = s48_copy_local_ref(call, cexternal_return_value);
  450. s48_pop_to (call);
  451. if (cexternal_return_value)
  452. result = s48_deref(cexternal_return_value);
  453. else
  454. result = S48_UNSPECIFIC;
  455. /* Check to see if a thread is waiting to return to the next block down. */
  456. if (!s48_false_p_2(call, current_stack_block) &&
  457. !s48_false_p_2(call, STACK_BLOCK_THREAD_2(call, current_stack_block))) {
  458. #ifdef DEBUG_FFI
  459. fprintf(stderr, "[releasing return at %d]\n", callback_depth());
  460. #endif
  461. if (throw_reason == EXCEPTION_THROW) {
  462. /* We are in the midst of raising an exception, so we need to piggyback
  463. our exception on that one. */
  464. s48_value old_exception
  465. = s48_resetup_external_exception(S48_EXCEPTION_CALLBACK_RETURN_UNCOVERED,
  466. 2);
  467. s48_push(old_exception);
  468. s48_push_2(call, current_stack_block);
  469. if (cexternal_return_value)
  470. s48_free_local_ref(call, cexternal_return_value);
  471. result = S48_UNSPECIFIC;
  472. }
  473. else {
  474. s48_setup_external_exception(S48_EXCEPTION_CALLBACK_RETURN_UNCOVERED, 2);
  475. s48_push_2(call, current_stack_block);
  476. s48_push_2(call, cexternal_return_value);
  477. result = S48_UNSPECIFIC;
  478. }
  479. } else {
  480. if (cexternal_return_value)
  481. s48_free_local_ref(call, cexternal_return_value);
  482. }
  483. return result;
  484. }
  485. s48_value
  486. s48_external_call_2(s48_value sch_proc, s48_value proc_name,
  487. long nargs, char *char_argv)
  488. {
  489. return s48_external_ecall (s48_get_current_call(), sch_proc,
  490. proc_name, nargs, char_argv);
  491. }
  492. /*
  493. * Call Scheme function `proc' from C. We push the call-back depth, `proc',
  494. * and the arguments on the Scheme stack and then restart the VM. The restarted
  495. * VM calls the Scheme procedure `callback' which wraps the call to `proc' with
  496. * a dynamic-wind. This prevents downward throws back into the call to `proc',
  497. * which C can't handle, and allows the C stack to be cleaned up if an upward
  498. * throw occurs.
  499. *
  500. * The maximum number of arguments is determined by the amount of space reserved
  501. * on the Scheme stack for exceptions. See the definition of stack-slack in
  502. * scheme/vm/stack.scm.
  503. */
  504. s48_value
  505. s48_call_scheme(s48_value proc, long nargs, ...)
  506. {
  507. int i;
  508. va_list arguments;
  509. s48_value value;
  510. s48_value unwind, stack_block;
  511. S48_DECLARE_GC_PROTECT(2);
  512. S48_GC_PROTECT_2(unwind, proc);
  513. va_start(arguments, nargs);
  514. S48_SHARED_BINDING_CHECK(s48_deref(callback_binding));
  515. /* It would be nice to push a list of the arguments, but we have no way
  516. of preserving them across a cons. */
  517. if (nargs < 0 || 12 < nargs) { /* DO NOT INCREASE THIS NUMBER */
  518. s48_value sch_nargs = s48_enter_integer(nargs); /* `proc' is protected */
  519. s48_raise_scheme_exception(S48_EXCEPTION_TOO_MANY_ARGUMENTS_IN_CALLBACK,
  520. 2, proc, sch_nargs);
  521. }
  522. #ifdef DEBUG_FFI
  523. fprintf(stderr, "[s48_call_scheme, %ld args, depth %d]\n",
  524. nargs, callback_depth());
  525. #endif
  526. s48_push(S48_UNSPECIFIC); /* placeholder */
  527. s48_push(proc);
  528. for (i = 0; i < nargs; i++)
  529. s48_push(va_arg(arguments, s48_value));
  530. va_end(arguments);
  531. /* With everything safely on the stack we can do the necessary allocation. */
  532. unwind = S48_MAKE_VALUE(struct s_jmp_buf);
  533. S48_EXTRACT_VALUE(unwind, struct s_jmp_buf) = current_return_point;
  534. stack_block = s48_make_record(s48_deref(stack_block_type_binding));
  535. STACK_BLOCK_UNWIND(stack_block) = unwind;
  536. STACK_BLOCK_PROC(stack_block) = s48_deref(current_procedure);
  537. STACK_BLOCK_NEXT(stack_block) = s48_deref(current_stack_block);
  538. STACK_BLOCK_FREE(stack_block) = S48_FALSE;
  539. STACK_BLOCK_THREAD(stack_block) = S48_FALSE;
  540. S48_GC_UNPROTECT(); /* no more references to `unwind' or `proc'. */
  541. s48_setref(current_stack_block, stack_block);
  542. #ifdef DEBUG_FFI
  543. if(s48_stack_ref(nargs + 1) != S48_UNSPECIFIC)
  544. fprintf(stderr, "[stack_block set missed]\n");
  545. #endif
  546. s48_stack_setB(nargs + 1, stack_block);
  547. #ifdef DEBUG_FFI
  548. fprintf(stderr, "[s48_call_scheme, %ld args, depth %d, off we go]\n",
  549. nargs, callback_depth());
  550. #endif
  551. value = s48_restart(S48_UNSAFE_SHARED_BINDING_REF(s48_deref(callback_binding)),
  552. nargs + 2);
  553. for (;s48_Scallback_return_stack_blockS != s48_deref(current_stack_block);) {
  554. if (s48_Scallback_return_stack_blockS == S48_FALSE) {
  555. #ifdef DEBUG_FFI
  556. fprintf(stderr, "[s48_call_scheme returning from VM %ld]\n", callback_depth());
  557. #endif
  558. exit(value);
  559. }
  560. else {
  561. /* Someone has returned (because of threads) to the wrong section of the
  562. C stack. We call back to a Scheme procedure that will suspend until
  563. our block is at the top of the stack. */
  564. s48_push(s48_Scallback_return_stack_blockS);
  565. s48_push(S48_UNSAFE_SHARED_BINDING_REF(s48_deref(delay_callback_return_binding)));
  566. s48_push(s48_Scallback_return_stack_blockS);
  567. s48_push(value);
  568. #ifdef DEBUG_FFI
  569. fprintf(stderr, "[Premature return, %ld args, depth %d, back we go]\n",
  570. nargs, callback_depth());
  571. #endif
  572. s48_disable_interruptsB();
  573. value = s48_restart(S48_UNSAFE_SHARED_BINDING_REF(s48_deref(callback_binding)), 4);
  574. }
  575. }
  576. /* Restore the state of the current stack block. */
  577. unwind = STACK_BLOCK_UNWIND(s48_deref(current_stack_block));
  578. current_return_point = S48_EXTRACT_VALUE(unwind, struct s_jmp_buf);
  579. s48_setref(current_procedure, STACK_BLOCK_PROC(s48_deref(current_stack_block)));
  580. s48_setref(current_stack_block, STACK_BLOCK_NEXT(s48_deref(current_stack_block)));
  581. #ifdef DEBUG_FFI
  582. fprintf(stderr, "[s48_call_scheme returns from depth %d]\n", callback_depth());
  583. #endif
  584. return value;
  585. }
  586. s48_ref_t
  587. s48_call_scheme_2(s48_call_t call, s48_ref_t proc, long nargs, ...)
  588. {
  589. int i;
  590. va_list arguments;
  591. s48_value value;
  592. s48_ref_t unwind;
  593. s48_value stack_block;
  594. va_start(arguments, nargs);
  595. #ifdef DEBUG_FFI
  596. fprintf(stderr, "[s48_call_scheme_2, %ld args, depth %d]\n",
  597. nargs, callback_depth());
  598. #endif
  599. s48_copy_local_bvs_to_scheme (call);
  600. s48_shared_binding_check_2(call, callback_binding);
  601. /* It would be nice to push a list of the arguments, but we have no way
  602. of preserving them across a cons. */
  603. if (nargs < 0 || 12 < nargs) { /* DO NOT INCREASE THIS NUMBER */
  604. s48_value sch_nargs = s48_enter_integer(nargs); /* `proc' is protected */
  605. s48_raise_scheme_exception(S48_EXCEPTION_TOO_MANY_ARGUMENTS_IN_CALLBACK,
  606. 2, s48_deref(proc), sch_nargs);
  607. }
  608. #ifdef DEBUG_FFI
  609. fprintf(stderr, "[s48_call_scheme_2, %ld args, depth %d]\n",
  610. nargs, callback_depth());
  611. #endif
  612. s48_push(S48_UNSPECIFIC); /* placeholder */
  613. s48_push(s48_deref(proc));
  614. for (i = 0; i < nargs; i++) {
  615. s48_ref_t ref = va_arg(arguments, s48_ref_t);
  616. #ifdef DEBUG_FFI
  617. fprintf(stderr, "call_scheme_2: pushing arg %d ref %x\n", i, ref);
  618. #endif
  619. s48_push(s48_deref(ref));
  620. }
  621. va_end(arguments);
  622. /* With everything safely on the stack we can do the necessary allocation. */
  623. unwind = s48_make_value_2(call, struct s_jmp_buf);
  624. s48_extract_value_2(call, unwind, struct s_jmp_buf) = current_return_point;
  625. stack_block = s48_make_record(s48_deref(stack_block_type_binding));
  626. STACK_BLOCK_UNWIND(stack_block) = s48_deref(unwind);
  627. STACK_BLOCK_PROC(stack_block) = s48_deref(current_procedure);
  628. STACK_BLOCK_NEXT(stack_block) = s48_deref(current_stack_block);
  629. STACK_BLOCK_FREE(stack_block) = S48_FALSE;
  630. STACK_BLOCK_THREAD(stack_block) = S48_FALSE;
  631. s48_setref(current_stack_block, stack_block);
  632. #ifdef DEBUG_FFI
  633. if(s48_stack_ref(nargs + 1) != S48_UNSPECIFIC)
  634. fprintf(stderr, "[stack_block set missed]\n");
  635. #endif
  636. s48_stack_setB(nargs + 1, stack_block);
  637. #ifdef DEBUG_FFI
  638. fprintf(stderr, "[s48_call_scheme_2, %ld args, depth %d, off we go]\n",
  639. nargs, callback_depth());
  640. #endif
  641. value = s48_restart(s48_deref(s48_unsafe_shared_binding_ref_2(call, callback_binding)),
  642. nargs + 2);
  643. for (;s48_Scallback_return_stack_blockS != s48_deref(current_stack_block);) {
  644. if (s48_Scallback_return_stack_blockS == S48_FALSE) {
  645. #ifdef DEBUG_FFI
  646. fprintf(stderr, "[s48_call_scheme_2 returning from VM %ld]\n", callback_depth());
  647. #endif
  648. exit(value);
  649. }
  650. else {
  651. /* Someone has returned (because of threads) to the wrong section of the
  652. C stack. We call back to a Scheme procedure that will suspend until
  653. our block is at the top of the stack. */
  654. s48_push(s48_Scallback_return_stack_blockS);
  655. s48_push_2(call, s48_unsafe_shared_binding_ref_2(call, delay_callback_return_binding));
  656. s48_push(s48_Scallback_return_stack_blockS);
  657. s48_push(value);
  658. #ifdef DEBUG_FFI
  659. fprintf(stderr, "[Premature return, %ld args, depth %d, back we go]\n",
  660. nargs, callback_depth());
  661. #endif
  662. s48_disable_interruptsB();
  663. value = s48_restart(s48_deref(s48_unsafe_shared_binding_ref_2(call, callback_binding)), 4);
  664. }
  665. }
  666. /* Restore the state of the current stack block. */
  667. unwind = STACK_BLOCK_UNWIND_2(call, current_stack_block);
  668. current_return_point = s48_extract_value_2(call, unwind, struct s_jmp_buf);
  669. s48_setref(current_procedure, s48_deref(STACK_BLOCK_PROC_2(call, current_stack_block)));
  670. s48_setref(current_stack_block, s48_deref(STACK_BLOCK_NEXT_2(call, current_stack_block)));
  671. #ifdef DEBUG_FFI
  672. fprintf(stderr, "[s48_call_scheme_2 returns from depth %d]\n", callback_depth());
  673. #endif
  674. s48_copy_local_bvs_from_scheme (call);
  675. return s48_make_local_ref (call, value);
  676. }
  677. /*
  678. * Because the top of the stack is cleared on the return from every external
  679. * call, this doesn't have to do anything but exist.
  680. */
  681. static s48_value
  682. s48_clear_stack_top()
  683. {
  684. #ifdef DEBUG_FFI
  685. fprintf(stderr, "[Clearing stack top]\n");
  686. #endif
  687. return S48_UNSPECIFIC;
  688. }
  689. static s48_ref_t
  690. s48_clear_stack_top_2(s48_call_t call)
  691. {
  692. #ifdef DEBUG_FFI
  693. fprintf(stderr, "[Clearing stack top]\n");
  694. #endif
  695. return s48_unspecific_2(call);
  696. }
  697. #ifdef DEBUG_FFI
  698. /*
  699. * For testing callbacks. This just calls its argument on the specified number
  700. * of values.
  701. */
  702. static s48_value
  703. s48_trampoline(s48_value proc, s48_value nargs)
  704. {
  705. fprintf(stderr, "[C trampoline, %ld args]\n", S48_UNSAFE_EXTRACT_FIXNUM(nargs));
  706. switch (s48_extract_fixnum(nargs)) {
  707. case -2: { /* provoke exception: GC protection mismatch */
  708. S48_DECLARE_GC_PROTECT(1);
  709. S48_GC_PROTECT_1(proc);
  710. return S48_FALSE;
  711. }
  712. case -1: { /* this is broken, dunno what this should do, anyway --Marcus */
  713. long n = - s48_extract_integer(proc);
  714. fprintf(stderr, "[extract magnitude is %ld (%lx)]\n", n, n);
  715. return s48_enter_integer(n);
  716. }
  717. case 0: {
  718. s48_value value = s48_call_scheme(proc, 0);
  719. if (value == S48_FALSE)
  720. s48_assertion_violation("s48_trampoline", "trampoline bouncing", 0);
  721. return value;
  722. }
  723. case 1:
  724. return s48_call_scheme(proc, 1, s48_enter_fixnum(100));
  725. case 2:
  726. return s48_call_scheme(proc, 2, s48_enter_fixnum(100), s48_enter_fixnum(200));
  727. case 3:
  728. return s48_call_scheme(proc, 3, s48_enter_fixnum(100), s48_enter_fixnum(200),
  729. s48_enter_fixnum(300));
  730. default:
  731. s48_assertion_violation("s48_trampoline", "invalid number of arguments", 1, nargs);
  732. return S48_UNDEFINED; /* not that we ever get here */
  733. }
  734. }
  735. static s48_ref_t
  736. s48_trampoline_2(s48_call_t call, s48_ref_t proc, s48_ref_t nargs)
  737. {
  738. fprintf(stderr, "[C trampoline_2, %ld args]\n", s48_unsafe_extract_long_2(call, nargs));
  739. switch (s48_extract_fixnum(s48_deref(nargs))) {
  740. case -2: { /* provoke exception: GC protection mismatch */
  741. S48_DECLARE_GC_PROTECT(1);
  742. S48_GC_PROTECT_1(proc);
  743. return s48_false_2(call);
  744. }
  745. case 0: {
  746. s48_ref_t result = s48_call_scheme_2(call, proc, 1,
  747. s48_make_local_ref (call, s48_enter_fixnum(0)));
  748. if (s48_deref(result) == S48_FALSE)
  749. s48_assertion_violation("s48_trampoline_2", "trampoline bouncing", 0);
  750. return result;
  751. }
  752. case 1:
  753. return s48_call_scheme_2(call, proc, 1,
  754. s48_make_local_ref (call, s48_enter_fixnum(100)));
  755. case 2:
  756. return s48_call_scheme_2(call, proc, 2,
  757. s48_make_local_ref (call, s48_enter_fixnum(100)),
  758. s48_make_local_ref (call, s48_enter_fixnum(200)));
  759. case 3:
  760. return s48_call_scheme_2(call, proc, 3,
  761. s48_make_local_ref (call, s48_enter_fixnum(100)),
  762. s48_make_local_ref (call, s48_enter_fixnum(200)),
  763. s48_make_local_ref (call, s48_enter_fixnum(300)));
  764. default:
  765. s48_assertion_violation("s48_trampoline_2", "invalid number of arguments", 1, nargs);
  766. return s48_undefined_2(call); /* not that we ever get here */
  767. }
  768. }
  769. #endif
  770. static s48_ref_t
  771. s48_system_2(s48_call_t call, s48_ref_t string)
  772. {
  773. return s48_enter_long_2(call,
  774. system(s48_false_p_2(call, string)
  775. ? NULL
  776. : s48_extract_byte_vector_readonly_2(call, string)));
  777. }
  778. /********************************/
  779. /*
  780. * Raising exceptions. We push the arguments on the stack end then throw out
  781. * of the most recent call from Scheme.
  782. *
  783. * The maximum number of arguments is determined by the amount of space reserved
  784. * on the Scheme stack for exceptions. See the definition of stack-slack in
  785. * scheme/vm/interp/stack.scm.
  786. */
  787. static long
  788. raise_scheme_exception_prelude(long why, long nargs)
  789. {
  790. s48_setup_external_exception(why, nargs);
  791. if (11 < nargs) { /* DO NOT INCREASE THIS NUMBER */
  792. fprintf(stderr, "too many arguments to external exception, discarding surplus\n");
  793. nargs = 11;
  794. }
  795. return nargs;
  796. }
  797. static long
  798. raise_scheme_exception_prelude_2(s48_call_t call, long why, long nargs)
  799. {
  800. s48_copy_local_bvs_to_scheme(call);
  801. return raise_scheme_exception_prelude(why, nargs);
  802. }
  803. static void
  804. raise_scheme_exception_postlude(void)
  805. {
  806. external_return_value = S48_UNSPECIFIC;
  807. longjmp(current_return_point.buf, EXCEPTION_THROW);
  808. }
  809. void
  810. s48_raise_scheme_exception(long why, long nargs, ...)
  811. {
  812. int i;
  813. va_list irritants;
  814. nargs = raise_scheme_exception_prelude(why, nargs + 1) - 1;
  815. s48_push(s48_deref(current_procedure));
  816. va_start(irritants, nargs);
  817. for (i = 0; i < nargs; i++)
  818. s48_push(va_arg(irritants, s48_value));
  819. va_end(irritants);
  820. raise_scheme_exception_postlude();
  821. }
  822. void
  823. s48_raise_scheme_exception_2(s48_call_t call, long why, long nargs, ...)
  824. {
  825. int i;
  826. va_list irritants;
  827. nargs = raise_scheme_exception_prelude_2(call, why, nargs + 1) - 1;
  828. s48_push_2(call, current_procedure);
  829. va_start(irritants, nargs);
  830. for (i = 0; i < nargs; i++)
  831. s48_push_2(call, va_arg(irritants, s48_ref_t));
  832. va_end(irritants);
  833. raise_scheme_exception_postlude();
  834. }
  835. static void
  836. raise_scheme_standard_exception(long why, const char* who, const char* message,
  837. long irritant_count, va_list irritants)
  838. {
  839. int i;
  840. long nargs = irritant_count + 2; /* who and message */
  841. nargs = raise_scheme_exception_prelude(why, nargs);
  842. irritant_count = nargs - 2;
  843. for (i = 0; i < irritant_count; i++)
  844. s48_push(va_arg(irritants, s48_value));
  845. va_end(irritants);
  846. /* these must be last because of GC protection */
  847. if (who == NULL)
  848. s48_push(s48_deref(current_procedure));
  849. else
  850. s48_push(s48_enter_string_utf_8((char*)who));
  851. s48_push(s48_enter_byte_string((char*)message));
  852. raise_scheme_exception_postlude();
  853. }
  854. static void
  855. raise_scheme_standard_exception_2(s48_call_t call, long why, const char* who, const char* message,
  856. long irritant_count, va_list irritants)
  857. {
  858. int i;
  859. long nargs = irritant_count + 2; /* who and message */
  860. nargs = raise_scheme_exception_prelude_2(call, why, nargs);
  861. irritant_count = nargs - 2;
  862. for (i = 0; i < irritant_count; i++)
  863. s48_push_2(call, va_arg(irritants, s48_ref_t));
  864. va_end(irritants);
  865. /* these must be last because of GC protection */
  866. if (who == NULL)
  867. s48_push_2(call, current_procedure);
  868. else
  869. s48_push_2(call, s48_enter_string_utf_8_2(call, (char*) who));
  870. s48_push_2(call, s48_enter_byte_string_2(call, (char*) message));
  871. raise_scheme_exception_postlude();
  872. }
  873. /* Specific exceptions */
  874. void
  875. s48_error(const char* who, const char* message,
  876. long irritant_count, ...)
  877. {
  878. va_list irritants;
  879. va_start(irritants, irritant_count);
  880. raise_scheme_standard_exception(S48_EXCEPTION_EXTERNAL_ERROR,
  881. who, message, irritant_count, irritants);
  882. }
  883. void
  884. s48_error_2(s48_call_t call, const char* who, const char* message,
  885. long irritant_count, ...)
  886. {
  887. va_list irritants;
  888. va_start(irritants, irritant_count);
  889. raise_scheme_standard_exception_2(call, S48_EXCEPTION_EXTERNAL_ERROR,
  890. who, message, irritant_count, irritants);
  891. }
  892. void
  893. s48_assertion_violation(const char* who, const char* message,
  894. long irritant_count, ...)
  895. {
  896. va_list irritants;
  897. va_start(irritants, irritant_count);
  898. raise_scheme_standard_exception(S48_EXCEPTION_EXTERNAL_ASSERTION_VIOLATION,
  899. who, message, irritant_count, irritants);
  900. }
  901. void
  902. s48_assertion_violation_2(s48_call_t call, const char* who, const char* message,
  903. long irritant_count, ...)
  904. {
  905. va_list irritants;
  906. va_start(irritants, irritant_count);
  907. raise_scheme_standard_exception_2(call, S48_EXCEPTION_EXTERNAL_ASSERTION_VIOLATION,
  908. who, message, irritant_count, irritants);
  909. }
  910. void
  911. s48_os_error(const char* who, int the_errno,
  912. long irritant_count, ...)
  913. {
  914. int i;
  915. long nargs = irritant_count + 2; /* who and errno */
  916. va_list irritants;
  917. nargs = raise_scheme_exception_prelude(S48_EXCEPTION_EXTERNAL_OS_ERROR, nargs);
  918. irritant_count = nargs - 2;
  919. va_start(irritants, irritant_count);
  920. for (i = 0; i < irritant_count; i++)
  921. s48_push(va_arg(irritants, s48_value));
  922. va_end(irritants);
  923. /* last because of GC protection */
  924. if (who == NULL)
  925. s48_push(s48_deref(current_procedure));
  926. else
  927. s48_push(s48_enter_string_utf_8((char*)who));
  928. s48_push(s48_enter_fixnum(the_errno));
  929. raise_scheme_exception_postlude();
  930. }
  931. void
  932. s48_os_error_2(s48_call_t call, const char* who, int the_errno,
  933. long irritant_count, ...)
  934. {
  935. int i;
  936. long nargs = irritant_count + 2; /* who and errno */
  937. va_list irritants;
  938. nargs = raise_scheme_exception_prelude_2(call, S48_EXCEPTION_EXTERNAL_OS_ERROR, nargs);
  939. irritant_count = nargs - 2;
  940. va_start(irritants, irritant_count);
  941. for (i = 0; i < irritant_count; i++)
  942. s48_push_2(call, va_arg(irritants, s48_ref_t));
  943. va_end(irritants);
  944. /* last because of GC protection */
  945. if (who == NULL)
  946. s48_push_2(call, current_procedure);
  947. else
  948. s48_push_2(call, s48_enter_string_utf_8_2(call, who));
  949. s48_push_2(call, s48_enter_long_as_fixnum_2(call, the_errno));
  950. raise_scheme_exception_postlude();
  951. }
  952. void
  953. s48_out_of_memory_error()
  954. {
  955. s48_raise_scheme_exception(S48_EXCEPTION_OUT_OF_MEMORY, 0);
  956. }
  957. void
  958. s48_out_of_memory_error_2(s48_call_t call)
  959. {
  960. s48_raise_scheme_exception_2(call, S48_EXCEPTION_OUT_OF_MEMORY, 0);
  961. }
  962. /* For internal use by the VM: */
  963. void
  964. s48_argument_type_violation(s48_value value) {
  965. s48_assertion_violation(NULL, "argument-type violation", 1, value);
  966. }
  967. void
  968. s48_argument_type_violation_2(s48_call_t call, s48_ref_t value) {
  969. s48_assertion_violation_2(call, NULL, "argument-type violation", 1, value);
  970. }
  971. void
  972. s48_range_violation(s48_value value, s48_value min, s48_value max) {
  973. s48_assertion_violation(NULL, "argument out of range", 3, value, min, max);
  974. }
  975. void
  976. s48_range_violation_2(s48_call_t call, s48_ref_t value, s48_ref_t min, s48_ref_t max) {
  977. s48_assertion_violation_2(call, NULL, "argument out of range", 3, value, min, max);
  978. }
  979. /* The following are deprecated: */
  980. void
  981. s48_raise_argument_type_error(s48_value value) {
  982. s48_raise_scheme_exception(S48_EXCEPTION_WRONG_TYPE_ARGUMENT, 1, value);
  983. }
  984. void
  985. s48_raise_argument_number_error(s48_value value, s48_value min, s48_value max) {
  986. s48_raise_scheme_exception(S48_EXCEPTION_WRONG_NUMBER_OF_ARGUMENTS,
  987. 3, value, min, max);
  988. }
  989. void
  990. s48_raise_range_error(s48_value value, s48_value min, s48_value max) {
  991. s48_raise_scheme_exception(S48_EXCEPTION_INDEX_OUT_OF_RANGE,
  992. 3, value, min, max);
  993. }
  994. void
  995. s48_raise_closed_channel_error() {
  996. s48_raise_scheme_exception(S48_EXCEPTION_CLOSED_CHANNEL, 0);
  997. }
  998. void
  999. s48_raise_os_error(int the_errno) {
  1000. s48_os_error(NULL, the_errno, 0);
  1001. }
  1002. void
  1003. s48_raise_string_os_error(char *reason) {
  1004. s48_error(NULL, (const char*)s48_enter_string_latin_1(reason), 0);
  1005. }
  1006. void
  1007. s48_raise_out_of_memory_error() {
  1008. s48_raise_scheme_exception(S48_EXCEPTION_OUT_OF_MEMORY, 0);
  1009. }
  1010. /********************************/
  1011. /* Support routines for external code */
  1012. /*
  1013. * Type-safe procedures for checking types and dereferencing and setting slots.
  1014. */
  1015. int
  1016. s48_stob_has_type(s48_value thing, int type)
  1017. {
  1018. return S48_STOB_P(thing) && (S48_STOB_TYPE(thing) == type);
  1019. }
  1020. int
  1021. s48_stob_has_type_2(s48_call_t call, s48_ref_t thing, int type)
  1022. {
  1023. return s48_stob_p_2(call, thing) && (s48_stob_type_2(call, thing) == type);
  1024. }
  1025. long
  1026. s48_stob_length(s48_value thing, int type)
  1027. {
  1028. if (!(S48_STOB_P(thing) && (S48_STOB_TYPE(thing) == type)))
  1029. s48_assertion_violation("s48_stob_length", "not a stob", 1, thing);
  1030. return S48_STOB_DESCRIPTOR_LENGTH(thing);
  1031. }
  1032. long
  1033. s48_stob_length_2(s48_call_t call, s48_ref_t thing, int type)
  1034. {
  1035. if (!(s48_stob_p_2(call, thing) && (s48_stob_type_2(call, thing) == type)))
  1036. s48_assertion_violation_2(call, "s48_stob_length_2", "not a stob", 1, thing);
  1037. return s48_unsafe_stob_descriptor_length_2(call, thing);
  1038. }
  1039. long
  1040. s48_stob_byte_length(s48_value thing, int type)
  1041. {
  1042. if (!(S48_STOB_P(thing) && (S48_STOB_TYPE(thing) == type)))
  1043. s48_assertion_violation("s48_stob_byte_length", "not a stob", 1, thing);
  1044. if (type == S48_STOBTYPE_STRING)
  1045. return S48_STOB_BYTE_LENGTH(thing) - 1;
  1046. else
  1047. return S48_STOB_BYTE_LENGTH(thing);
  1048. }
  1049. long
  1050. s48_stob_byte_length_2(s48_call_t call, s48_ref_t thing, int type)
  1051. {
  1052. if (!(s48_stob_p_2(call, thing) && (s48_stob_type_2(call, thing) == type)))
  1053. s48_assertion_violation_2(call, "s48_stob_byte_length_2", "not a stob", 1, thing);
  1054. if (type == S48_STOBTYPE_STRING)
  1055. return s48_unsafe_stob_byte_length_2(call, thing) - 1;
  1056. else
  1057. return s48_unsafe_stob_byte_length_2(call, thing);
  1058. }
  1059. s48_value
  1060. s48_stob_ref(s48_value thing, int type, long offset)
  1061. {
  1062. long length;
  1063. if (!(S48_STOB_P(thing) && (S48_STOB_TYPE(thing) == type)))
  1064. s48_assertion_violation("s48_stob_ref", "not a stob", 1, thing);
  1065. length = S48_STOB_DESCRIPTOR_LENGTH(thing);
  1066. if (offset < 0 || length <= offset)
  1067. s48_assertion_violation("s48_stob_ref", "invalid stob index", 3,
  1068. s48_enter_integer(offset),
  1069. S48_UNSAFE_ENTER_FIXNUM(0),
  1070. S48_UNSAFE_ENTER_FIXNUM(length - 1));
  1071. return S48_STOB_REF(thing, offset);
  1072. }
  1073. s48_ref_t
  1074. s48_stob_ref_2(s48_call_t call, s48_ref_t thing, int type, long offset)
  1075. {
  1076. long length;
  1077. if (!(s48_stob_p_2(call, thing) && (s48_stob_type_2(call, thing) == type)))
  1078. s48_assertion_violation_2(call, "s48_stob_ref_2", "not a stob", 1, thing);
  1079. length = s48_unsafe_stob_descriptor_length_2(call, thing);
  1080. if (offset < 0 || length <= offset)
  1081. s48_assertion_violation_2(call, "s48_stob_ref_2", "invalid stob index", 3,
  1082. s48_enter_long_2(call, offset),
  1083. s48_unsafe_enter_long_as_fixnum_2(call, 0),
  1084. s48_unsafe_enter_long_as_fixnum_2(call, length - 1));
  1085. return s48_unsafe_stob_ref_2(call, thing, offset);
  1086. }
  1087. void
  1088. s48_stob_set(s48_value thing, int type, long offset, s48_value value)
  1089. {
  1090. long length;
  1091. if (!(S48_STOB_P(thing) &&
  1092. (S48_STOB_TYPE(thing) == type) &&
  1093. !S48_STOB_IMMUTABLEP(thing)))
  1094. s48_assertion_violation("s48_stob_set", "not a mutable stob", 1, thing);
  1095. length = S48_STOB_DESCRIPTOR_LENGTH(thing);
  1096. if (offset < 0 || length <= offset)
  1097. s48_assertion_violation("s48_stob_set", "invalid stob index", 3,
  1098. s48_enter_integer(offset),
  1099. S48_UNSAFE_ENTER_FIXNUM(0),
  1100. S48_UNSAFE_ENTER_FIXNUM(length - 1));
  1101. S48_STOB_SET(thing, offset, value);
  1102. }
  1103. void
  1104. s48_stob_set_2(s48_call_t call, s48_ref_t thing, int type, long offset, s48_ref_t value)
  1105. {
  1106. long length;
  1107. if (!(s48_stob_p_2(call, thing) &&
  1108. (s48_stob_type_2(call, thing) == type) &&
  1109. !s48_stob_immutablep_2(call, thing)))
  1110. s48_assertion_violation_2(call, "s48_stob_set_2",
  1111. "not a mutable stob", 1, thing);
  1112. length = s48_unsafe_stob_descriptor_length_2(call, thing);
  1113. if (offset < 0 || length <= offset)
  1114. s48_assertion_violation_2(call, "s48_stob_set_2", "invalid stob index", 3,
  1115. s48_enter_integer(offset),
  1116. s48_unsafe_enter_long_as_fixnum_2(call, 0),
  1117. s48_unsafe_enter_long_as_fixnum_2(call, length - 1));
  1118. s48_unsafe_stob_set_2(call, thing, offset, value);
  1119. }
  1120. char
  1121. s48_stob_byte_ref(s48_value thing, int type, long offset)
  1122. {
  1123. long length;
  1124. if (!(S48_STOB_P(thing) && (S48_STOB_TYPE(thing) == type)))
  1125. s48_assertion_violation("s48_stob_byte_ref", "not a stob", 1, thing);
  1126. length = (type == S48_STOBTYPE_STRING) ?
  1127. S48_STOB_BYTE_LENGTH(thing) - 1 :
  1128. S48_STOB_BYTE_LENGTH(thing);
  1129. if (offset < 0 || length <= offset)
  1130. s48_assertion_violation("s48_stob_byte_ref", "invalid stob index", 3,
  1131. s48_enter_integer(offset),
  1132. S48_UNSAFE_ENTER_FIXNUM(0),
  1133. S48_UNSAFE_ENTER_FIXNUM(length - 1));
  1134. return S48_STOB_BYTE_REF(thing, offset);
  1135. }
  1136. char
  1137. s48_stob_byte_ref_2(s48_call_t call, s48_ref_t thing, int type, long offset)
  1138. {
  1139. long length;
  1140. if (!(s48_stob_p_2(call, thing) && (s48_stob_type_2(call, thing) == type)))
  1141. s48_assertion_violation_2(call, "s48_stob_byte_ref_2", "not a stob", 1, thing);
  1142. length = (type == s48_stobtype_string) ?
  1143. s48_unsafe_stob_byte_length_2(call, thing) - 1 :
  1144. s48_unsafe_stob_byte_length_2(call, thing);
  1145. if (offset < 0 || length <= offset)
  1146. s48_assertion_violation_2(call, "s48_stob_byte_ref_2", "invalid stob index", 3,
  1147. s48_enter_integer(offset),
  1148. s48_unsafe_enter_long_as_fixnum_2(call, 0),
  1149. s48_unsafe_enter_long_as_fixnum_2(call, length - 1));
  1150. return s48_unsafe_stob_byte_ref_2(call, thing, offset);
  1151. }
  1152. void
  1153. s48_stob_byte_set(s48_value thing, int type, long offset, char value)
  1154. {
  1155. long length;
  1156. if (!(S48_STOB_P(thing) && (S48_STOB_TYPE(thing) == type)))
  1157. s48_assertion_violation("s48_stob_byte_set", "not a stob", 1, thing);
  1158. length = (type == S48_STOBTYPE_STRING) ?
  1159. S48_STOB_BYTE_LENGTH(thing) - 1 :
  1160. S48_STOB_BYTE_LENGTH(thing);
  1161. if (offset < 0 || length <= offset)
  1162. s48_assertion_violation("s48_stob_byte_set", "invalid stob index", 3,
  1163. s48_enter_integer(offset),
  1164. S48_UNSAFE_ENTER_FIXNUM(0),
  1165. S48_UNSAFE_ENTER_FIXNUM(length - 1));
  1166. S48_STOB_BYTE_SET(thing, offset, value);
  1167. }
  1168. void
  1169. s48_stob_byte_set_2(s48_call_t call, s48_ref_t thing, int type, long offset, char value)
  1170. {
  1171. long length;
  1172. if (!(s48_stob_p_2(call, thing) && (s48_stob_type_2(call, thing) == type)))
  1173. s48_assertion_violation_2(call, "s48_stob_byte_set_2", "not a stob", 1, thing);
  1174. length = (type == S48_STOBTYPE_STRING) ?
  1175. s48_unsafe_stob_byte_length_2(call, thing) - 1 :
  1176. s48_unsafe_stob_byte_length_2(call, thing);
  1177. if (offset < 0 || length <= offset)
  1178. s48_assertion_violation_2(call, "s48_stob_byte_set_2", "invalid stob index", 3,
  1179. s48_enter_integer(offset),
  1180. s48_unsafe_enter_long_as_fixnum_2(call, 0),
  1181. s48_unsafe_enter_long_as_fixnum_2(call, length - 1));
  1182. s48_unsafe_stob_byte_set_2(call, thing, offset, value);
  1183. }
  1184. void *
  1185. s48_value_pointer(s48_value value)
  1186. {
  1187. S48_CHECK_VALUE(value);
  1188. return S48_ADDRESS_AFTER_HEADER(value, void *);
  1189. }
  1190. void *
  1191. s48_value_pointer_2(s48_call_t call, s48_ref_t value)
  1192. {
  1193. s48_check_value_2(call, value);
  1194. return s48_address_after_header_2(call, value, void *);
  1195. }
  1196. /********************************/
  1197. /* Numbers, characters, and pointers. */
  1198. /*
  1199. * These two functions have the same range as the unsafe macros, but they signal
  1200. * an error if things go wrong, instead of silently producing garbage. Unlike
  1201. * the integer versions they cannot cause a GC.
  1202. */
  1203. s48_value
  1204. s48_enter_fixnum(long value)
  1205. {
  1206. if (value < S48_MIN_FIXNUM_VALUE || S48_MAX_FIXNUM_VALUE < value)
  1207. s48_assertion_violation("s48_enter_fixnum", "not a fixnum", 1, s48_enter_integer(value));
  1208. return S48_UNSAFE_ENTER_FIXNUM(value);
  1209. }
  1210. s48_ref_t
  1211. s48_enter_long_as_fixnum_2(s48_call_t call, long value)
  1212. {
  1213. if (value < S48_MIN_FIXNUM_VALUE || S48_MAX_FIXNUM_VALUE < value)
  1214. s48_assertion_violation_2(call, "s48_enter_long_as_fixnum_2", "not a fixnum",
  1215. 1, s48_enter_long_2(call, value));
  1216. return s48_unsafe_enter_long_as_fixnum_2(call, value);
  1217. }
  1218. long
  1219. s48_extract_fixnum(s48_value value)
  1220. {
  1221. if (! S48_FIXNUM_P(value))
  1222. s48_assertion_violation("s48_extract_fixnum", "not a fixnum", 1, value);
  1223. return S48_UNSAFE_EXTRACT_FIXNUM(value);
  1224. }
  1225. /* If we have a fixnum we just extract it. For bignums call the
  1226. * functions in bignum.c.
  1227. */
  1228. s48_ref_t
  1229. s48_enter_long_2(s48_call_t call, long value)
  1230. {
  1231. return s48_make_local_ref(call, s48_enter_integer(value));
  1232. }
  1233. long
  1234. s48_extract_integer(s48_value value)
  1235. {
  1236. if (S48_FIXNUM_P(value))
  1237. return S48_UNSAFE_EXTRACT_FIXNUM(value);
  1238. if (S48_BIGNUM_P(value)){
  1239. bignum_type bignum = S48_ADDRESS_AFTER_HEADER(value, long);
  1240. if (! s48_bignum_fits_in_word_p(bignum, 32, 1))
  1241. s48_assertion_violation("s48_extract_integer", "does not fit in word", 1, value);
  1242. else return s48_bignum_to_long(bignum);
  1243. }
  1244. else s48_assertion_violation("s48_extract_integer", "not an exact integer", 1, value);
  1245. }
  1246. long
  1247. s48_extract_long_2(s48_call_t call, s48_ref_t value)
  1248. {
  1249. if (s48_fixnum_p_2(call, value))
  1250. return s48_unsafe_extract_long_2(call, value);
  1251. if (s48_bignum_p_2(call, value)){
  1252. bignum_type bignum = s48_address_after_header_2(call, value, long);
  1253. if (! s48_bignum_fits_in_word_p(bignum, sizeof(long) * BITS_PER_BYTE, 1))
  1254. s48_assertion_violation_2(call, "s48_extract_long_2",
  1255. "does not fit in word", 1, value);
  1256. else return s48_bignum_to_long(bignum);
  1257. }
  1258. else s48_assertion_violation_2(call, "s48_extract_long_2",
  1259. "not an exact integer", 1, value);
  1260. }
  1261. s48_ref_t
  1262. s48_enter_unsigned_long_2(s48_call_t call, unsigned long value)
  1263. {
  1264. return s48_make_local_ref(call, s48_enter_unsigned_integer(value));
  1265. }
  1266. unsigned long
  1267. s48_extract_unsigned_integer(s48_value value)
  1268. {
  1269. if (S48_FIXNUM_P(value))
  1270. {
  1271. long fixnum = S48_UNSAFE_EXTRACT_FIXNUM(value);
  1272. if (fixnum < 0)
  1273. s48_assertion_violation("s48_extract_unsigned_integer", "negative argument", 1,
  1274. value);
  1275. return (unsigned long) fixnum;
  1276. }
  1277. if (S48_BIGNUM_P(value)){
  1278. bignum_type bignum = S48_ADDRESS_AFTER_HEADER(value, long);
  1279. if (! s48_bignum_fits_in_word_p(bignum, 32, 0))
  1280. s48_assertion_violation("s48_extract_unsigned_integer", "does not fit in word", 1,
  1281. value);
  1282. else return s48_bignum_to_ulong(bignum);
  1283. }
  1284. else s48_assertion_violation("s48_extract_unsigned_integer", "not an exact integer", 1,
  1285. value);
  1286. }
  1287. unsigned long
  1288. s48_extract_unsigned_long_2(s48_call_t call, s48_ref_t value)
  1289. {
  1290. if (s48_fixnum_p_2(call, value))
  1291. {
  1292. long fixnum = s48_unsafe_extract_long_2(call, value);
  1293. if (fixnum < 0)
  1294. s48_assertion_violation_2(call, "s48_extract_unsigned_long_2",
  1295. "negative argument", 1, value);
  1296. return (unsigned long) fixnum;
  1297. }
  1298. if (s48_bignum_p_2(call, value)){
  1299. bignum_type bignum = s48_address_after_header_2(call, value, long);
  1300. if (! s48_bignum_fits_in_word_p(bignum, sizeof(long) * BITS_PER_BYTE, 0))
  1301. s48_assertion_violation_2(call, "s48_extract_unsigned_long_2",
  1302. "does not fit in word", 1, value);
  1303. else return s48_bignum_to_ulong(bignum);
  1304. }
  1305. else s48_assertion_violation_2(call, "s48_extract_unsigned_long_2",
  1306. "not an exact integer", 1, value);
  1307. }
  1308. /*
  1309. * Strings from and to encodings
  1310. */
  1311. /*
  1312. * These are just wrappers to ensure the right types.
  1313. */
  1314. s48_ref_t
  1315. s48_enter_string_latin_1_2(s48_call_t call, const char *s)
  1316. {
  1317. return s48_make_local_ref(call, s48_enter_string_latin_1((char*) s));
  1318. }
  1319. s48_ref_t
  1320. s48_enter_string_latin_1_n_2(s48_call_t call, const char *s, long count)
  1321. {
  1322. return s48_make_local_ref(call, s48_enter_string_latin_1_n((char*) s, count));
  1323. }
  1324. void
  1325. s48_copy_string_to_latin_1_2(s48_call_t call, s48_ref_t sch_s, char *s)
  1326. {
  1327. s48_copy_string_to_latin_1(s48_deref(sch_s), s);
  1328. }
  1329. void
  1330. s48_copy_string_to_latin_1_n_2(s48_call_t call, s48_ref_t sch_s, long start, long count, char *s)
  1331. {
  1332. s48_copy_string_to_latin_1_n(s48_deref(sch_s), start, count, s);
  1333. }
  1334. void
  1335. s48_copy_latin_1_to_string_2(s48_call_t call, const char *s, s48_ref_t sch_s)
  1336. {
  1337. s48_copy_latin_1_to_string((char*) s, s48_deref(sch_s));
  1338. }
  1339. void
  1340. s48_copy_latin_1_to_string_n_2(s48_call_t call, const char *s, long len, s48_ref_t sch_s)
  1341. {
  1342. s48_copy_latin_1_to_string_n((char*) s, len, s48_deref(sch_s));
  1343. }
  1344. s48_ref_t
  1345. s48_enter_string_utf_8_2(s48_call_t call, const char *s)
  1346. {
  1347. return s48_make_local_ref(call, s48_enter_string_utf_8((char*) s));
  1348. }
  1349. s48_value
  1350. s48_enter_string_utf_16be(const uint16_t *s)
  1351. {
  1352. return s48_enter_string_utf_16beU((char*) s);
  1353. }
  1354. s48_ref_t
  1355. s48_enter_string_utf_16be_2(s48_call_t call, const uint16_t *s)
  1356. {
  1357. return s48_make_local_ref(call, s48_enter_string_utf_16beU((char*) s));
  1358. }
  1359. s48_value
  1360. s48_enter_string_utf_16be_n(const uint16_t * s, long l)
  1361. {
  1362. return s48_enter_string_utf_16be_nU((char*) s, l);
  1363. }
  1364. s48_ref_t
  1365. s48_enter_string_utf_16be_n_2(s48_call_t call, const uint16_t * s, long l)
  1366. {
  1367. return s48_make_local_ref(call, s48_enter_string_utf_16be_nU((char*) s, l));
  1368. }
  1369. long
  1370. s48_copy_string_to_utf_16be(s48_value sch_s, uint16_t * s)
  1371. {
  1372. return s48_copy_string_to_utf_16beU(sch_s, (char*) s);
  1373. }
  1374. long
  1375. s48_copy_string_to_utf_16be_2(s48_call_t call, s48_ref_t sch_s, uint16_t * s)
  1376. {
  1377. return s48_copy_string_to_utf_16beU(s48_deref(sch_s), (char*) s);
  1378. }
  1379. long
  1380. s48_copy_string_to_utf_16be_n(s48_value sch_s, long start, long count, uint16_t *s)
  1381. {
  1382. return s48_copy_string_to_utf_16be_nU(sch_s, start, count, (char*) s);
  1383. }
  1384. long
  1385. s48_copy_string_to_utf_16be_n_2(s48_call_t call, s48_ref_t sch_s, long start, long count, uint16_t *s)
  1386. {
  1387. return s48_copy_string_to_utf_16be_nU(s48_deref(sch_s), start, count, (char*) s);
  1388. }
  1389. s48_value
  1390. s48_enter_string_utf_16le(const uint16_t *s)
  1391. {
  1392. return s48_enter_string_utf_16leU((char *) s);
  1393. }
  1394. s48_ref_t
  1395. s48_enter_string_utf_16le_2(s48_call_t call, const uint16_t *s)
  1396. {
  1397. return s48_make_local_ref(call, s48_enter_string_utf_16leU((char *) s));
  1398. }
  1399. s48_value
  1400. s48_enter_string_utf_16le_n(const uint16_t *s, long l)
  1401. {
  1402. return s48_enter_string_utf_16le_nU((char *) s,l);
  1403. }
  1404. s48_ref_t
  1405. s48_enter_string_utf_16le_n_2(s48_call_t call, const uint16_t *s, long l)
  1406. {
  1407. return s48_make_local_ref(call, s48_enter_string_utf_16le_nU((char *) s,l));
  1408. }
  1409. long
  1410. s48_copy_string_to_utf_16le(s48_value sch_s, uint16_t *s)
  1411. {
  1412. return s48_copy_string_to_utf_16leU(sch_s, (char *) s);
  1413. }
  1414. long
  1415. s48_copy_string_to_utf_16le_2(s48_call_t call, s48_ref_t sch_s, uint16_t *s)
  1416. {
  1417. return s48_copy_string_to_utf_16leU(s48_deref(sch_s), (char *) s);
  1418. }
  1419. long
  1420. s48_copy_string_to_utf_16le_n(s48_value sch_s, long start, long count, uint16_t *s)
  1421. {
  1422. return s48_copy_string_to_utf_16le_nU(sch_s, start, count, (char *) s);
  1423. }
  1424. long
  1425. s48_copy_string_to_utf_16le_n_2(s48_call_t call, s48_ref_t sch_s, long start, long count, uint16_t *s)
  1426. {
  1427. return s48_copy_string_to_utf_16le_nU(s48_deref(sch_s), start, count, (char *) s);
  1428. }
  1429. s48_ref_t
  1430. s48_enter_string_utf_8_n_2(s48_call_t call, const char* s, long count)
  1431. {
  1432. return s48_make_local_ref(call, s48_enter_string_utf_8_n((char*) s, count));
  1433. }
  1434. long
  1435. s48_string_utf_8_length_2(s48_call_t call, s48_ref_t s)
  1436. {
  1437. return s48_string_utf_8_length(s48_deref(s));
  1438. }
  1439. long
  1440. s48_string_utf_8_length_n_2(s48_call_t call, s48_ref_t s, long start, long count)
  1441. {
  1442. return s48_string_utf_8_length_n(s48_deref(s), start, count);
  1443. }
  1444. long
  1445. s48_copy_string_to_utf_8_2(s48_call_t call, s48_ref_t sch_s, char* s)
  1446. {
  1447. return s48_copy_string_to_utf_8(s48_deref(sch_s), s);
  1448. }
  1449. long
  1450. s48_copy_string_to_utf_8_n_2(s48_call_t call, s48_ref_t sch_s, long start, long count, char* s)
  1451. {
  1452. return s48_copy_string_to_utf_8_n(s48_deref(sch_s), start, count, s);
  1453. }
  1454. long
  1455. s48_string_utf_16be_length_2(s48_call_t call, s48_ref_t sch_s)
  1456. {
  1457. return s48_string_utf_16be_length(s48_deref(sch_s));
  1458. }
  1459. long
  1460. s48_string_utf_16be_length_n_2(s48_call_t call, s48_ref_t sch_s, long start, long count)
  1461. {
  1462. return s48_string_utf_16be_length_n(s48_deref(sch_s), start, count);
  1463. }
  1464. long
  1465. s48_string_utf_16le_length_2(s48_call_t call, s48_ref_t sch_s)
  1466. {
  1467. return s48_string_utf_16le_length(s48_deref(sch_s));
  1468. }
  1469. long
  1470. s48_string_utf_16le_length_n_2(s48_call_t call, s48_ref_t sch_s, long start, long count)
  1471. {
  1472. return s48_string_utf_16le_length_n(s48_deref(sch_s), start, count);
  1473. }
  1474. long
  1475. s48_string_length_2(s48_call_t call, s48_ref_t string)
  1476. {
  1477. return s48_string_length(s48_deref(string));
  1478. }
  1479. long
  1480. s48_string_latin_1_length_2(s48_call_t call, s48_ref_t string)
  1481. {
  1482. return s48_string_length_2(call, string);
  1483. }
  1484. long
  1485. s48_string_latin_1_length_n_2(s48_call_t call, s48_ref_t string, long start, long count)
  1486. {
  1487. return count;
  1488. }
  1489. void
  1490. s48_string_set_2(s48_call_t call, s48_ref_t s, long i, long c)
  1491. {
  1492. s48_string_set(s48_deref(s), i, c);
  1493. }
  1494. long
  1495. s48_string_ref_2(s48_call_t call, s48_ref_t s, long i)
  1496. {
  1497. return s48_string_ref(s48_deref(s), i);
  1498. }
  1499. /*
  1500. * Extract strings to local buffer
  1501. */
  1502. #define MAKE_STRING_EXTRACT_FUNCTION(encoding) \
  1503. char *s48_extract_##encoding##_from_string_2(s48_call_t call, s48_ref_t sch_s) { \
  1504. char *buf = s48_make_local_buf(call, s48_string_##encoding##_length_2(call, sch_s)); \
  1505. s48_copy_string_to_##encoding##_2(call, sch_s, buf); \
  1506. return buf; \
  1507. }
  1508. char *
  1509. s48_extract_latin_1_from_string_2(s48_call_t call, s48_ref_t sch_s) {
  1510. long size = s48_string_latin_1_length_2(call, sch_s) + 1;
  1511. char *buf = s48_make_local_buf(call, size + 1);
  1512. s48_copy_string_to_latin_1_2(call, sch_s, buf);
  1513. buf[size] = '\0';
  1514. return buf;
  1515. }
  1516. char *
  1517. s48_extract_utf_8_from_string_2(s48_call_t call, s48_ref_t sch_s) {
  1518. long size = s48_string_utf_8_length_2(call, sch_s) + 1;
  1519. char *buf = s48_make_local_buf(call, size + 1);
  1520. s48_copy_string_to_utf_8_2(call, sch_s, buf);
  1521. buf[size] = '\0';
  1522. return buf;
  1523. }
  1524. uint16_t *
  1525. s48_extract_utf_16be_from_string_2(s48_call_t call, s48_ref_t sch_s) {
  1526. long size = s48_string_utf_16be_length_2(call, sch_s);
  1527. uint16_t *buf =
  1528. (uint16_t *) s48_make_local_buf(call, (size + 1) * sizeof(uint16_t));
  1529. s48_copy_string_to_utf_16be_2(call, sch_s, buf);
  1530. buf[size] = 0;
  1531. return buf;
  1532. }
  1533. uint16_t *
  1534. s48_extract_utf_16le_from_string_2(s48_call_t call, s48_ref_t sch_s) {
  1535. long size = s48_string_utf_16le_length_2(call, sch_s);
  1536. uint16_t *buf =
  1537. (uint16_t *) s48_make_local_buf(call, (size + 1) * sizeof(uint16_t));
  1538. s48_copy_string_to_utf_16le_2(call, sch_s, buf);
  1539. buf[size] = 0;
  1540. return buf;
  1541. }
  1542. /*
  1543. * Doubles and characters are straightforward.
  1544. */
  1545. s48_value
  1546. s48_enter_double(double value)
  1547. {
  1548. s48_value obj;
  1549. obj = s48_allocate_stob(S48_STOBTYPE_DOUBLE, sizeof(double));
  1550. S48_UNSAFE_EXTRACT_DOUBLE(obj) = value;
  1551. return obj;
  1552. }
  1553. s48_ref_t
  1554. s48_enter_double_2(s48_call_t call, double value)
  1555. {
  1556. s48_ref_t ref;
  1557. ref = s48_make_local_ref(call, s48_allocate_stob(S48_STOBTYPE_DOUBLE, sizeof(double)));
  1558. s48_unsafe_extract_double_2(call, ref) = value;
  1559. return ref;
  1560. }
  1561. double
  1562. s48_extract_double(s48_value s48_double)
  1563. {
  1564. if (! S48_DOUBLE_P(s48_double))
  1565. s48_assertion_violation("s48_extract_double", "not a double", 1, s48_double);
  1566. return S48_UNSAFE_EXTRACT_DOUBLE(s48_double);
  1567. }
  1568. double
  1569. s48_extract_double_2(s48_call_t call, s48_ref_t s48_double)
  1570. {
  1571. if (! s48_double_p_2(call, s48_double))
  1572. s48_assertion_violation_2(call, "s48_extract_double_2",
  1573. "not a double", 1, s48_double);
  1574. return s48_unsafe_extract_double_2(call, s48_double);
  1575. }
  1576. s48_value
  1577. s48_enter_char(long a_char)
  1578. {
  1579. if (! ((a_char >= 0)
  1580. && ((a_char <= 0xd7ff)
  1581. || ((a_char >= 0xe000) && (a_char <= 0x10ffff)))))
  1582. s48_assertion_violation("s48_enter_char", "not a scalar value", 1, s48_enter_fixnum(a_char));
  1583. return S48_UNSAFE_ENTER_CHAR(a_char);
  1584. }
  1585. s48_ref_t
  1586. s48_enter_char_2(s48_call_t call, long a_char)
  1587. {
  1588. if (! ((a_char >= 0)
  1589. && ((a_char <= 0xd7ff)
  1590. || ((a_char >= 0xe000) && (a_char <= 0x10ffff)))))
  1591. s48_assertion_violation_2(call, "s48_enter_char_2",
  1592. "not a scalar value", 1, s48_enter_long_as_fixnum_2(call, a_char));
  1593. return s48_unsafe_enter_char_2(call, a_char);
  1594. }
  1595. long
  1596. s48_extract_char(s48_value a_char)
  1597. {
  1598. if (! S48_CHAR_P(a_char))
  1599. s48_assertion_violation("s48_extract_char", "not a char", 1, a_char);
  1600. return S48_UNSAFE_EXTRACT_CHAR(a_char);
  1601. }
  1602. long
  1603. s48_extract_char_2(s48_call_t call, s48_ref_t a_char)
  1604. {
  1605. if (! s48_char_p_2(call, a_char))
  1606. s48_assertion_violation_2(call, "s48_extract_char_2", "not a char", 1, a_char);
  1607. return s48_unsafe_extract_char_2(call, a_char);
  1608. }
  1609. /********************************/
  1610. /* Allocation */
  1611. s48_value
  1612. s48_enter_pointer(void *pointer)
  1613. {
  1614. s48_value obj;
  1615. obj = s48_allocate_stob(S48_STOBTYPE_BYTE_VECTOR, sizeof(void *));
  1616. *(S48_ADDRESS_AFTER_HEADER(obj, void *)) = pointer;
  1617. return obj;
  1618. }
  1619. s48_ref_t
  1620. s48_enter_pointer_2(s48_call_t call, void *pointer)
  1621. {
  1622. s48_ref_t ref;
  1623. ref = s48_make_local_ref(call, s48_allocate_stob(S48_STOBTYPE_BYTE_VECTOR, sizeof(void *)));
  1624. *(s48_address_after_header_2(call, ref, void *)) = pointer;
  1625. return ref;
  1626. }
  1627. void*
  1628. s48_extract_pointer(s48_value sch_pointer)
  1629. {
  1630. S48_CHECK_VALUE(sch_pointer);
  1631. return *(S48_ADDRESS_AFTER_HEADER(sch_pointer, void *));
  1632. }
  1633. void*
  1634. s48_extract_pointer_2(s48_call_t call, s48_ref_t sch_pointer)
  1635. {
  1636. s48_check_value_2(call, sch_pointer);
  1637. return *(s48_address_after_header_2(call, sch_pointer, void *));
  1638. }
  1639. s48_ref_t
  1640. s48_get_imported_binding_2(char *name)
  1641. {
  1642. return s48_make_global_ref(s48_get_imported_binding(name));
  1643. }
  1644. s48_ref_t
  1645. s48_get_imported_binding_local_2(s48_call_t call, char *name)
  1646. {
  1647. return s48_make_local_ref(call, s48_get_imported_binding(name));
  1648. }
  1649. s48_ref_t
  1650. s48_define_exported_binding_2(s48_call_t call, char *name, s48_ref_t binding)
  1651. {
  1652. return s48_make_local_ref(call, s48_define_exported_binding(name, s48_deref(binding)));
  1653. }
  1654. s48_value
  1655. s48_cons(s48_value v1, s48_value v2)
  1656. {
  1657. s48_value obj;
  1658. S48_DECLARE_GC_PROTECT(2);
  1659. S48_GC_PROTECT_2(v1, v2);
  1660. obj = s48_allocate_stob(S48_STOBTYPE_PAIR, 2);
  1661. S48_UNSAFE_SET_CAR(obj, v1);
  1662. S48_UNSAFE_SET_CDR(obj, v2);
  1663. S48_GC_UNPROTECT();
  1664. return obj;
  1665. }
  1666. s48_ref_t
  1667. s48_cons_2(s48_call_t call, s48_ref_t v1, s48_ref_t v2)
  1668. {
  1669. s48_ref_t ref;
  1670. ref = s48_make_local_ref(call, s48_allocate_stob(S48_STOBTYPE_PAIR, 2));
  1671. s48_unsafe_set_car_2(call, ref, v1);
  1672. s48_unsafe_set_cdr_2(call, ref, v2);
  1673. return ref;
  1674. }
  1675. s48_value
  1676. s48_make_weak_pointer(s48_value value)
  1677. {
  1678. s48_value obj;
  1679. S48_DECLARE_GC_PROTECT(1);
  1680. S48_GC_PROTECT_1(value);
  1681. obj = s48_allocate_weak_stob(S48_STOBTYPE_WEAK_POINTER, 1);
  1682. S48_STOB_SET(obj, 0, value);
  1683. S48_GC_UNPROTECT();
  1684. return obj;
  1685. }
  1686. s48_ref_t
  1687. s48_make_weak_pointer_2(s48_call_t call, s48_ref_t value)
  1688. {
  1689. s48_ref_t ref = s48_make_local_ref(call, s48_allocate_weak_stob(S48_STOBTYPE_WEAK_POINTER, 1));
  1690. s48_unsafe_stob_set_2(call, ref, 0, value);
  1691. return ref;
  1692. }
  1693. /*
  1694. * Entering and extracting byte vectors.
  1695. */
  1696. s48_value
  1697. s48_enter_byte_vector(char *bytes, long length)
  1698. {
  1699. s48_value obj = s48_make_byte_vector(length);
  1700. memcpy(S48_UNSAFE_EXTRACT_BYTE_VECTOR(obj), bytes, length);
  1701. return obj;
  1702. }
  1703. s48_ref_t
  1704. s48_enter_byte_vector_2(s48_call_t call, const char *bytes, long length)
  1705. {
  1706. s48_ref_t ref = s48_make_byte_vector_2(call, length);
  1707. s48_enter_byte_vector_region_2(call, ref, 0, length, (char *) bytes);
  1708. return ref;
  1709. }
  1710. s48_value
  1711. s48_enter_unmovable_byte_vector(char *bytes, long length)
  1712. {
  1713. s48_value obj = s48_make_unmovable_byte_vector(length);
  1714. memcpy(S48_UNSAFE_EXTRACT_BYTE_VECTOR(obj), bytes, length);
  1715. return obj;
  1716. }
  1717. s48_ref_t
  1718. s48_enter_unmovable_byte_vector_2(s48_call_t call, const char *bytes, long length)
  1719. {
  1720. s48_ref_t ref = s48_make_unmovable_byte_vector_2(call, length);
  1721. s48_enter_byte_vector_region_2(call, ref, 0, length, (char *) bytes);
  1722. return ref;
  1723. }
  1724. char *
  1725. s48_extract_byte_vector(s48_value byte_vector)
  1726. {
  1727. S48_CHECK_VALUE(byte_vector);
  1728. return S48_UNSAFE_EXTRACT_BYTE_VECTOR(byte_vector);
  1729. }
  1730. char *
  1731. s48_extract_byte_vector_2(s48_call_t call, s48_ref_t byte_vector)
  1732. {
  1733. long s = s48_byte_vector_length_2(call, byte_vector);
  1734. char *buf = s48_make_local_bv(call, byte_vector, s);
  1735. return buf;
  1736. }
  1737. char *
  1738. s48_extract_byte_vector_readonly_2(s48_call_t call, s48_ref_t byte_vector)
  1739. {
  1740. long s = s48_byte_vector_length_2(call, byte_vector);
  1741. char *buf = s48_make_local_bv_readonly(call, byte_vector, s);
  1742. return buf;
  1743. }
  1744. void
  1745. s48_extract_byte_vector_region_2(s48_call_t call, s48_ref_t byte_vector,
  1746. long start, long length, char *buf)
  1747. {
  1748. char *scheme_buf;
  1749. s48_check_value_2(call, byte_vector);
  1750. scheme_buf = s48_unsafe_extract_byte_vector_2(call, byte_vector);
  1751. memcpy(buf, scheme_buf + start, length);
  1752. }
  1753. void
  1754. s48_enter_byte_vector_region_2(s48_call_t call, s48_ref_t byte_vector,
  1755. long start, long length, char *buf)
  1756. {
  1757. char *scheme_buf;
  1758. s48_check_value_2(call, byte_vector);
  1759. scheme_buf = s48_unsafe_extract_byte_vector_2(call, byte_vector);
  1760. memcpy(scheme_buf + start, buf, length);
  1761. }
  1762. void
  1763. s48_copy_from_byte_vector_2(s48_call_t call, s48_ref_t byte_vector, char *buf)
  1764. {
  1765. s48_extract_byte_vector_region_2(call, byte_vector, 0,
  1766. s48_byte_vector_length_2(call, byte_vector), buf);
  1767. }
  1768. void
  1769. s48_copy_to_byte_vector_2(s48_call_t call, s48_ref_t byte_vector, char *buf)
  1770. {
  1771. s48_enter_byte_vector_region_2(call, byte_vector, 0,
  1772. s48_byte_vector_length_2(call, byte_vector), buf);
  1773. }
  1774. psbool
  1775. s48_unmovable_p(s48_call_t call, s48_ref_t ref)
  1776. {
  1777. return s48_unmovableP(s48_deref(ref));
  1778. }
  1779. char *
  1780. s48_extract_unmovable_byte_vector_2(s48_call_t call, s48_ref_t byte_vector)
  1781. {
  1782. s48_check_value_2(call, byte_vector);
  1783. if (!s48_unmovable_p(call, byte_vector))
  1784. s48_assertion_violation("s48_extract_unmovable_byte_vector_2",
  1785. "not an unmovable byte vector", 1, byte_vector);
  1786. return s48_unsafe_extract_byte_vector_2(call, byte_vector);
  1787. }
  1788. /*
  1789. The returned byte vector by s48_extract_byte_vector_unmanaged_2 may
  1790. be a copy of the Scheme byte vector, changes made to the returned
  1791. byte vector will not necessarily be reflected in Scheme until
  1792. s48_release_byte_vector_2 is called.
  1793. */
  1794. char *
  1795. s48_extract_byte_vector_unmanaged_2(s48_call_t call, s48_ref_t byte_vector)
  1796. {
  1797. if (s48_unmovable_p(call, byte_vector))
  1798. {
  1799. return s48_extract_unmovable_byte_vector_2(call, byte_vector);
  1800. }
  1801. else
  1802. {
  1803. long len = s48_byte_vector_length_2(call, byte_vector);
  1804. char *buf = s48_make_local_buf(call, len);
  1805. s48_extract_byte_vector_region_2(call, byte_vector, 0, len, buf);
  1806. return buf;
  1807. }
  1808. }
  1809. void
  1810. s48_release_byte_vector_2(s48_call_t call, s48_ref_t byte_vector, char *buf)
  1811. {
  1812. if (!s48_unmovable_p(call, byte_vector))
  1813. s48_copy_to_byte_vector_2(call, byte_vector, buf);
  1814. }
  1815. /*
  1816. * Making various kinds of stored objects.
  1817. */
  1818. s48_value
  1819. s48_make_string(int length, long init)
  1820. {
  1821. int i;
  1822. s48_value obj = s48_allocate_string(length);
  1823. /* We should probably offer a VM function for this. */
  1824. for (i = 0; i < length; ++i)
  1825. s48_string_set(obj, i, init);
  1826. return obj;
  1827. }
  1828. s48_ref_t
  1829. s48_make_string_2(s48_call_t call, int length, long init)
  1830. {
  1831. int i;
  1832. s48_ref_t ref = s48_make_local_ref(call, s48_allocate_string(length));
  1833. /* We should probably offer a VM function for this. */
  1834. for (i = 0; i < length; ++i)
  1835. s48_string_set(s48_deref(ref), i, init);
  1836. return ref;
  1837. }
  1838. s48_value
  1839. s48_make_vector(long length, s48_value init)
  1840. {
  1841. long i;
  1842. s48_value obj;
  1843. S48_DECLARE_GC_PROTECT(1);
  1844. S48_GC_PROTECT_1(init);
  1845. obj = s48_allocate_stob(S48_STOBTYPE_VECTOR, length);
  1846. for (i = 0; i < length; ++i)
  1847. S48_UNSAFE_VECTOR_SET(obj, i, init);
  1848. S48_GC_UNPROTECT();
  1849. return obj;
  1850. }
  1851. s48_ref_t
  1852. s48_make_vector_2(s48_call_t call, long length, s48_ref_t init)
  1853. {
  1854. long i;
  1855. s48_ref_t ref = s48_make_local_ref(call, s48_allocate_stob(S48_STOBTYPE_VECTOR, length));
  1856. for (i = 0; i < length; ++i)
  1857. s48_unsafe_vector_set_2(call, ref, i, init);
  1858. return ref;
  1859. }
  1860. s48_value
  1861. s48_make_byte_vector(long length)
  1862. {
  1863. return s48_allocate_stob(S48_STOBTYPE_BYTE_VECTOR, length);
  1864. }
  1865. s48_ref_t
  1866. s48_make_byte_vector_2(s48_call_t call, long length)
  1867. {
  1868. return s48_make_local_ref(call, s48_allocate_stob(S48_STOBTYPE_BYTE_VECTOR, length));
  1869. }
  1870. s48_value
  1871. s48_make_unmovable_byte_vector(long length)
  1872. {
  1873. return s48_allocate_unmovable_stob(S48_STOBTYPE_BYTE_VECTOR, length);
  1874. }
  1875. s48_ref_t
  1876. s48_make_unmovable_byte_vector_2(s48_call_t call, long length)
  1877. {
  1878. return s48_make_local_ref(call, s48_allocate_unmovable_stob(S48_STOBTYPE_BYTE_VECTOR, length));
  1879. }
  1880. s48_value
  1881. s48_enter_byte_substring(char *str, long length)
  1882. {
  1883. s48_value obj = s48_allocate_stob(S48_STOBTYPE_BYTE_VECTOR, length + 1);
  1884. memcpy(S48_UNSAFE_EXTRACT_BYTE_VECTOR(obj), str, length);
  1885. *(S48_UNSAFE_EXTRACT_BYTE_VECTOR(obj) + length) = '\0';
  1886. return obj;
  1887. }
  1888. s48_ref_t
  1889. s48_enter_byte_substring_2(s48_call_t call, const char *str, long length)
  1890. {
  1891. s48_ref_t ref = s48_make_byte_vector_2(call, length + 1);
  1892. s48_enter_byte_vector_region_2(call, ref, 0, length, (char *) str);
  1893. s48_byte_vector_set_2(call, ref, length, '\0');
  1894. return ref;
  1895. }
  1896. s48_value
  1897. s48_enter_byte_string(char *str)
  1898. {
  1899. return s48_enter_byte_substring(str, strlen(str));
  1900. }
  1901. s48_ref_t
  1902. s48_enter_byte_string_2(s48_call_t call, const char *str)
  1903. {
  1904. return s48_enter_byte_substring_2(call, str, strlen(str));
  1905. }
  1906. s48_value
  1907. s48_make_record(s48_value type_shared_binding)
  1908. {
  1909. long i, number_of_fields;
  1910. s48_value record = S48_FALSE;
  1911. s48_value record_type = S48_FALSE;
  1912. S48_DECLARE_GC_PROTECT(1);
  1913. S48_GC_PROTECT_1(record_type);
  1914. S48_SHARED_BINDING_CHECK(type_shared_binding);
  1915. S48_SHARED_BINDING_CHECK(s48_deref(the_record_type_binding));
  1916. record_type = S48_SHARED_BINDING_REF(type_shared_binding);
  1917. s48_check_record_type(record_type, s48_deref(the_record_type_binding));
  1918. number_of_fields =
  1919. S48_UNSAFE_EXTRACT_FIXNUM(S48_RECORD_TYPE_NUMBER_OF_FIELDS(record_type));
  1920. record = s48_allocate_stob(S48_STOBTYPE_RECORD, number_of_fields + 1);
  1921. S48_UNSAFE_RECORD_SET(record, -1, record_type);
  1922. for (i = 0; i < number_of_fields; ++i)
  1923. S48_UNSAFE_RECORD_SET(record, i, S48_UNSPECIFIC);
  1924. S48_GC_UNPROTECT();
  1925. return record;
  1926. }
  1927. s48_ref_t
  1928. s48_make_record_2(s48_call_t call, s48_ref_t type_shared_binding)
  1929. {
  1930. long i, number_of_fields;
  1931. s48_ref_t record;
  1932. s48_ref_t record_type;
  1933. s48_shared_binding_check_2(call, type_shared_binding);
  1934. s48_shared_binding_check_2(call, the_record_type_binding);
  1935. record_type = s48_shared_binding_ref_2(call, type_shared_binding);
  1936. s48_check_record_type_2(call, record_type, the_record_type_binding);
  1937. number_of_fields =
  1938. s48_unsafe_extract_long_2(call,
  1939. s48_record_type_number_of_fields_2(call, record_type));
  1940. record = s48_make_local_ref(call, s48_allocate_stob(S48_STOBTYPE_RECORD, number_of_fields + 1));
  1941. s48_unsafe_record_set_2(call, record, -1, record_type);
  1942. for (i = 0; i < number_of_fields; ++i)
  1943. s48_unsafe_record_set_2(call, record, i, s48_unspecific_2(call));
  1944. return record;
  1945. }
  1946. /*
  1947. * Raise an exception if `record' is not a record whose type is the one
  1948. * found in `type_binding'.
  1949. */
  1950. void
  1951. s48_check_record_type(s48_value record, s48_value type_binding)
  1952. {
  1953. if (! S48_RECORD_P(S48_SHARED_BINDING_REF(type_binding)))
  1954. s48_raise_scheme_exception(S48_EXCEPTION_UNBOUND_EXTERNAL_NAME, 1,
  1955. S48_SHARED_BINDING_NAME(type_binding));
  1956. if ((! S48_RECORD_P(record)) ||
  1957. (S48_UNSAFE_SHARED_BINDING_REF(type_binding) !=
  1958. S48_UNSAFE_RECORD_REF(record, -1)))
  1959. s48_assertion_violation("s48_check_record_type", "not a record of the appropriate type", 2,
  1960. record, S48_SHARED_BINDING_REF(type_binding));
  1961. }
  1962. void
  1963. s48_check_record_type_2(s48_call_t call, s48_ref_t record, s48_ref_t type_binding)
  1964. {
  1965. if (! s48_record_p_2(call, s48_shared_binding_ref_2(call, type_binding)))
  1966. s48_raise_scheme_exception_2(call,S48_EXCEPTION_UNBOUND_EXTERNAL_NAME, 1,
  1967. s48_shared_binding_name_2(call, type_binding));
  1968. if ((! s48_record_p_2(call, record)) ||
  1969. (!s48_eq_p_2(call,
  1970. s48_unsafe_shared_binding_ref_2(call, type_binding),
  1971. s48_unsafe_record_ref_2(call, record, -1))))
  1972. s48_assertion_violation_2(call, "s48_check_record_type_2",
  1973. "not a record of the appropriate type", 2,
  1974. record, s48_shared_binding_ref_2(call, type_binding));
  1975. }
  1976. long
  1977. s48_length(s48_value list)
  1978. {
  1979. long i = 0;
  1980. while (!(S48_EQ(list, S48_NULL)))
  1981. {
  1982. list = S48_CDR(list);
  1983. ++i;
  1984. }
  1985. return S48_UNSAFE_ENTER_FIXNUM(i);
  1986. }
  1987. s48_ref_t
  1988. s48_length_2(s48_call_t call, s48_ref_t list)
  1989. {
  1990. s48_ref_t l = s48_copy_local_ref(call, list);
  1991. long i = 0;
  1992. while (!(s48_null_p_2(call, l)))
  1993. {
  1994. s48_ref_t temp = l;
  1995. l = s48_cdr_2(call, l);
  1996. s48_free_local_ref(call, temp);
  1997. ++i;
  1998. }
  1999. return s48_unsafe_enter_long_as_fixnum_2(call, i);
  2000. }