external.c 69 KB

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