veneer.c 85 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394
  1. /* ------------------------------------------------------------------------- */
  2. /* "veneer" : Compiling the run-time "veneer" of any routines invoked */
  3. /* by the compiler (e.g. DefArt) which the program doesn't */
  4. /* provide */
  5. /* */
  6. /* Part of Inform 6.33 */
  7. /* copyright (c) Graham Nelson 1993 - 2014 */
  8. /* */
  9. /* ------------------------------------------------------------------------- */
  10. #include "header.h"
  11. int veneer_mode; /* Is the code currently being
  12. compiled from the veneer? */
  13. static debug_locations null_debug_locations =
  14. { { 0, 0, 0, 0, 0, 0, 0 }, NULL, 0 };
  15. extern void compile_initial_routine(void)
  16. {
  17. /* The first routine present in memory in any Inform game, beginning
  18. at the code area start position, always has 0 local variables
  19. (since the interpreter begins execution with an empty stack frame):
  20. and it must "quit" rather than "return".
  21. In order not to impose these restrictions on "Main", we compile a
  22. trivial routine consisting of a call to "Main" followed by "quit". */
  23. int32 j;
  24. assembly_operand AO;
  25. j = symbol_index("Main__", -1);
  26. assign_symbol(j,
  27. assemble_routine_header(0, FALSE, "Main__", FALSE, j),
  28. ROUTINE_T);
  29. sflags[j] |= SYSTEM_SFLAG + USED_SFLAG;
  30. if (trace_fns_setting==3) sflags[j] |= STAR_SFLAG;
  31. if (!glulx_mode) {
  32. AO.value = 0; AO.type = LONG_CONSTANT_OT; AO.marker = MAIN_MV;
  33. sequence_point_follows = FALSE;
  34. if (version_number > 3)
  35. assemblez_1_to(call_vs_zc, AO, temp_var1);
  36. else
  37. assemblez_1_to(call_zc, AO, temp_var1);
  38. assemblez_0(quit_zc);
  39. }
  40. else {
  41. AO.value = 0; AO.type = CONSTANT_OT; AO.marker = MAIN_MV;
  42. sequence_point_follows = FALSE;
  43. assembleg_3(call_gc, AO, zero_operand, zero_operand);
  44. assembleg_1(return_gc, zero_operand);
  45. }
  46. assemble_routine_end(FALSE, null_debug_locations);
  47. }
  48. /* ------------------------------------------------------------------------- */
  49. /* The rest of the veneer is applied at the end of the pass, as required. */
  50. /* ------------------------------------------------------------------------- */
  51. static int veneer_routine_needs_compilation[VENEER_ROUTINES];
  52. int32 veneer_routine_address[VENEER_ROUTINES];
  53. static int veneer_symbols_base;
  54. #define VR_UNUSED 0
  55. #define VR_CALLED 1
  56. #define VR_COMPILED 2
  57. typedef struct VeneerRoutine_s
  58. { char *name;
  59. char *source1;
  60. char *source2;
  61. char *source3;
  62. char *source4;
  63. char *source5;
  64. char *source6;
  65. } VeneerRoutine;
  66. static char *veneer_source_area;
  67. static VeneerRoutine VRs_z[VENEER_ROUTINES] =
  68. {
  69. /* Box__Routine: the only veneer routine used in the implementation of
  70. an actual statement ("box", of course), written in a
  71. hybrid of Inform and assembly language. Note the
  72. transcription of the box text to the transcript
  73. output stream (-1, or $ffff). */
  74. { "Box__Routine",
  75. "maxw table n w w2 line lc t;\
  76. n = table --> 0;\
  77. @add n 6 -> sp;\
  78. @split_window sp;\
  79. @set_window 1;\
  80. w = 0 -> 33;\
  81. if (w == 0) w=80;\
  82. w2 = (w - maxw)/2;\
  83. style reverse;\
  84. @sub w2 2 -> w;\
  85. line = 5;\
  86. lc = 1;\
  87. @set_cursor 4 w;\
  88. spaces maxw + 4;",
  89. "do\
  90. { @set_cursor line w;\
  91. spaces maxw + 4;\
  92. @set_cursor line w2;\
  93. t = table --> lc;\
  94. if (t~=0) print (string) t;\
  95. line++; lc++;\
  96. } until (lc > n);\
  97. @set_cursor line w;\
  98. spaces maxw + 4;\
  99. @buffer_mode 1;\
  100. style roman;\
  101. @set_window 0;\
  102. @split_window 1;\
  103. @output_stream $ffff;\
  104. print \"[ \";\
  105. lc = 1;",
  106. "do\
  107. { w = table --> lc;\
  108. if (w ~= 0) print (string) w;\
  109. lc++;\
  110. if (lc > n)\
  111. { print \"]^^\";\
  112. break;\
  113. }\
  114. print \"^ \";\
  115. } until (false);\
  116. @output_stream 1;\
  117. ]", "", "", ""
  118. },
  119. /* This batch of routines is expected to be defined (rather better) by
  120. the Inform library: these minimal forms here are provided to prevent
  121. tiny non-library-using programs from failing to compile when certain
  122. legal syntaxes (such as <<Action a b>>;) are used. */
  123. { "R_Process",
  124. "a b c d; print \"Action <\", a, \" \", b, \" \", c;\
  125. if (d) print \", \", d; print \">^\";\
  126. ]", "", "", "", "", ""
  127. },
  128. { "DefArt",
  129. "obj; print \"the \", obj; ]", "", "", "", "", ""
  130. },
  131. { "InDefArt",
  132. "obj; print \"a \", obj; ]", "", "", "", "", ""
  133. },
  134. { "CDefArt",
  135. "obj; print \"The \", obj; ]", "", "", "", "", ""
  136. },
  137. { "CInDefArt",
  138. "obj; print \"A \", obj; ]", "", "", "", "", ""
  139. },
  140. { "PrintShortName",
  141. "obj; switch(metaclass(obj))\
  142. { 0: print \"nothing\";\
  143. Object: @print_obj obj;\
  144. Class: print \"class \"; @print_obj obj;\
  145. Routine: print \"(routine at \", obj, \")\";\
  146. String: print \"(string at \", obj, \")\";\
  147. } ]", "", "", "", "", ""
  148. },
  149. { "EnglishNumber",
  150. "obj; print obj; ]", "", "", "", "", ""
  151. },
  152. { "Print__PName",
  153. "prop p size cla i;\
  154. if (prop & $c000)\
  155. { cla = #classes_table-->(prop & $ff);\
  156. print (name) cla, \"::\";\
  157. if ((prop & $8000) == 0) prop = (prop & $3f00)/$100;\
  158. else\
  159. { prop = (prop & $7f00)/$100;\
  160. i = cla.3;\
  161. while ((i-->0 ~= 0) && (prop>0))\
  162. { i = i + i->2 + 3;\
  163. prop--;\
  164. }\
  165. prop = (i-->0) & $7fff;\
  166. }\
  167. }",
  168. "p = #identifiers_table;\
  169. size = p-->0;\
  170. if (prop<=0 || prop>=size || p-->prop==0)\
  171. print \"<number \", prop, \">\";\
  172. else print (string) p-->prop;\
  173. ]", "", "", "", ""
  174. },
  175. /* The remaining routines make up the run-time half of the object
  176. orientation system, and need never be present for Inform 5 programs. */
  177. {
  178. /* WV__Pr: write a value to the property for the given
  179. object having the given identifier */
  180. "WV__Pr",
  181. "obj identifier value x;\
  182. x = obj..&identifier;\
  183. if (x==0) { RT__Err(\"write to\", obj, identifier); return; }\
  184. #ifdef INFIX;\
  185. if (obj has infix__watching || (debug_flag & 15)) RT__TrPS(obj,identifier,value);\
  186. #ifnot; #ifdef DEBUG;\
  187. if (debug_flag & 15) RT__TrPS(obj,identifier,value);\
  188. #endif; #endif;\
  189. x-->0 = value;\
  190. ]", "", "", "", "", ""
  191. },
  192. {
  193. /* RV__Pr: read a value from the property for the given
  194. object having the given identifier */
  195. "RV__Pr",
  196. "obj identifier x;\
  197. x = obj..&identifier;\
  198. if (x==0)\
  199. { if (identifier >= 1 && identifier < 64 && obj.#identifier <= 2)\
  200. return obj.identifier;\
  201. RT__Err(\"read\", obj, identifier); return; }\
  202. if (obj..#identifier > 2) RT__Err(\"read\", obj, identifier, 2);\
  203. return x-->0;\
  204. ]", "", "", "", "", ""
  205. },
  206. { /* CA__Pr: call, that is, print-or-run-or-read, a property:
  207. this exactly implements obj..prop(...). Note that
  208. classes (members of Class) have 5 built-in properties
  209. inherited from Class: create, recreate, destroy,
  210. remaining and copy. Implementing these here prevents
  211. the need for a full metaclass inheritance scheme. */
  212. "CA__Pr",
  213. "obj id a b c d e f x y z s s2 n m;\
  214. if (obj < 1 || obj > #largest_object-255)\
  215. { switch(Z__Region(obj))\
  216. { 2: if (id == call)\
  217. { s = sender; sender = self; self = obj;\
  218. #ifdef action;sw__var=action;#endif;\
  219. x = indirect(obj, a, b, c, d, e, f);\
  220. self = sender; sender = s; return x; }\
  221. jump Call__Error;",
  222. "3: if (id == print) { @print_paddr obj; rtrue; }\
  223. if (id == print_to_array)\
  224. { @output_stream 3 a; @print_paddr obj; @output_stream -3;\
  225. return a-->0; }\
  226. jump Call__Error;\
  227. }\
  228. jump Call__Error;\
  229. }\
  230. @check_arg_count 3 ?~A__x;y++;@check_arg_count 4 ?~A__x;y++;\
  231. @check_arg_count 5 ?~A__x;y++;@check_arg_count 6 ?~A__x;y++;\
  232. @check_arg_count 7 ?~A__x;y++;@check_arg_count 8 ?~A__x;y++;.A__x;",
  233. "#ifdef INFIX;if (obj has infix__watching) n=1;#endif;\
  234. #ifdef DEBUG;if (debug_flag & 1 ~= 0) n=1;#endif;\
  235. if (n==1) {\
  236. #ifdef DEBUG;n=debug_flag & 1; debug_flag=debug_flag-n;#endif;\
  237. print \"[ ~\", (name) obj, \"~.\", (property) id, \"(\";\
  238. switch(y) { 1: print a; 2: print a,\",\",b; 3: print a,\",\",b,\",\",c;\
  239. 4: print a,\",\",b,\",\",c,\",\",d;\
  240. 5: print a,\",\",b,\",\",c,\",\",d,\",\",e;\
  241. 6: print a,\",\",b,\",\",c,\",\",d,\",\",e,\",\",f; }\
  242. print \") ]^\";\
  243. #ifdef DEBUG;debug_flag = debug_flag + n;#endif;\
  244. }",
  245. "if (id > 0 && id < 64)\
  246. { x = obj.&id; if (x==0) { x=$000a-->0 + 2*(id-1); n=2; }\
  247. else n = obj.#id; }\
  248. else\
  249. { if (id>=64 && id<69 && obj in Class)\
  250. return Cl__Ms(obj,id,y,a,b,c,d);\
  251. x = obj..&id;\
  252. if (x == 0) { .Call__Error;\
  253. RT__Err(\"send message\", obj, id); return; }\
  254. n = 0->(x-1);\
  255. if (id&$C000==$4000)\
  256. switch (n&$C0) { 0: n=1; $40: n=2; $80: n=n&$3F; }\
  257. }",
  258. "for (:2*m<n:m++)\
  259. { if (x-->m==$ffff) rfalse;\
  260. switch(Z__Region(x-->m))\
  261. { 2: s = sender; sender = self; self = obj; s2 = sw__var;\
  262. #ifdef LibSerial;\
  263. if (id==life) sw__var=reason_code; else sw__var=action;\
  264. #endif;\
  265. switch(y) { 0: z = indirect(x-->m); 1: z = indirect(x-->m, a);\
  266. 2: z = indirect(x-->m, a, b); 3: z = indirect(x-->m, a, b, c);",
  267. "4: z = indirect(x-->m, a, b, c, d); 5:z = indirect(x-->m, a, b, c, d, e);\
  268. 6: z = indirect(x-->m, a, b, c, d, e, f); }\
  269. self = sender; sender = s; sw__var = s2;\
  270. if (z ~= 0) return z;\
  271. 3: print_ret (string) x-->m;\
  272. default: return x-->m;\
  273. }\
  274. }\
  275. rfalse;\
  276. ]"
  277. },
  278. {
  279. /* IB__Pr: ++(individual property) */
  280. "IB__Pr",
  281. "obj identifier x;\
  282. x = obj..&identifier;\
  283. if (x==0) { RT__Err(\"increment\", obj, identifier); return; }\
  284. #ifdef INFIX;\
  285. if (obj has infix__watching || (debug_flag & 15)) RT__TrPS(obj,identifier,(x-->0)+1);\
  286. #ifnot; #ifdef DEBUG;\
  287. if (debug_flag & 15) RT__TrPS(obj,identifier,(x-->0)+1);\
  288. #endif; #endif;\
  289. return ++(x-->0);\
  290. ]", "", "", "", "", ""
  291. },
  292. {
  293. /* IA__Pr: (individual property)++ */
  294. "IA__Pr",
  295. "obj identifier x;\
  296. x = obj..&identifier;\
  297. if (x==0) { RT__Err(\"increment\", obj, identifier); return; }\
  298. #ifdef INFIX;\
  299. if (obj has infix__watching || (debug_flag & 15))\
  300. RT__TrPS(obj,identifier,(x-->0)+1);\
  301. #ifnot; #ifdef DEBUG;\
  302. if (debug_flag & 15) RT__TrPS(obj,identifier,(x-->0)+1);\
  303. #endif; #endif;\
  304. return (x-->0)++;\
  305. ]", "", "", "", "", ""
  306. },
  307. {
  308. /* DB__Pr: --(individual property) */
  309. "DB__Pr",
  310. "obj identifier x;\
  311. x = obj..&identifier;\
  312. if (x==0) { RT__Err(\"decrement\", obj, identifier); return; }\
  313. #ifdef INFIX;\
  314. if (obj has infix__watching || (debug_flag & 15)) RT__TrPS(obj,identifier,(x-->0)-1);\
  315. #ifnot; #ifdef DEBUG;\
  316. if (debug_flag & 15) RT__TrPS(obj,identifier,(x-->0)-1);\
  317. #endif; #endif;\
  318. return --(x-->0);\
  319. ]", "", "", "", "", ""
  320. },
  321. {
  322. /* DA__Pr: (individual property)-- */
  323. "DA__Pr",
  324. "obj identifier x;\
  325. x = obj..&identifier;\
  326. if (x==0) { RT__Err(\"decrement\", obj, identifier); return; }\
  327. #ifdef INFIX;\
  328. if (obj has infix__watching || (debug_flag & 15)) RT__TrPS(obj,identifier,(x-->0)-1);\
  329. #ifnot; #ifdef DEBUG;\
  330. if (debug_flag & 15) RT__TrPS(obj,identifier,(x-->0)-1);\
  331. #endif; #endif;\
  332. return (x-->0)--;\
  333. ]", "", "", "", "", ""
  334. },
  335. {
  336. /* RA__Pr: read the address of a property value for a given object,
  337. returning 0 if it doesn't provide this individual
  338. property */
  339. "RA__Pr",
  340. "obj identifier i otherid cla;\
  341. if (obj==0) rfalse;\
  342. if (identifier<64 && identifier>0) return obj.&identifier;\
  343. if (identifier & $8000 ~= 0)\
  344. { cla = #classes_table-->(identifier & $ff);\
  345. if (cla.&3 == 0) rfalse;\
  346. if (~~(obj ofclass cla)) rfalse;\
  347. identifier = (identifier & $7f00) / $100;\
  348. i = cla.3;\
  349. while (identifier>0)\
  350. { identifier--;\
  351. i = i + i->2 + 3;\
  352. }\
  353. return i+3;\
  354. }",
  355. "if (identifier & $4000 ~= 0)\
  356. { cla = #classes_table-->(identifier & $ff);\
  357. identifier = (identifier & $3f00) / $100;\
  358. if (~~(obj ofclass cla)) rfalse; i=0-->5;\
  359. if (cla == 2) return i+2*identifier-2;\
  360. i = 0-->((i+124+cla*14)/2);\
  361. i = CP__Tab(i + 2*(0->i) + 1, -1)+6;\
  362. return CP__Tab(i, identifier);\
  363. }\
  364. if (obj.&3 == 0) rfalse;\
  365. if (obj in 1)\
  366. { if (identifier<64 || identifier>=72) rfalse;\
  367. }",
  368. "if (self == obj)\
  369. otherid = identifier | $8000;\
  370. i = obj.3;\
  371. while (i-->0 ~= 0)\
  372. { if (i-->0 == identifier or otherid)\
  373. return i+3;\
  374. i = i + i->2 + 3;\
  375. }\
  376. rfalse;\
  377. ]", "", "", ""
  378. },
  379. {
  380. /* RL__Pr: read the property length of an individual property value,
  381. returning 0 if it isn't provided by the given object */
  382. "RL__Pr",
  383. "obj identifier x;\
  384. if (identifier<64 && identifier>0) return obj.#identifier;\
  385. x = obj..&identifier;\
  386. if (x==0) rfalse;\
  387. if (identifier&$C000==$4000)\
  388. switch (((x-1)->0)&$C0)\
  389. { 0: return 1; $40: return 2; $80: return ((x-1)->0)&$3F; }\
  390. return (x-1)->0;\
  391. ]", "", "", "", "", ""
  392. },
  393. {
  394. /* RA__Sc: implement the "superclass" (::) operator,
  395. returning an identifier */
  396. "RA__Sc",
  397. "cla identifier otherid i j k;\
  398. if (cla notin 1 && cla > 4)\
  399. { RT__Err(\"be a '::' superclass\", cla, -1); rfalse; }\
  400. if (self ofclass cla) otherid = identifier | $8000;\
  401. for (j=0: #classes_table-->j ~= 0: j++)\
  402. { if (cla==#classes_table-->j)\
  403. { if (identifier < 64) return $4000 + identifier*$100 + j;\
  404. if (cla.&3 == 0) break;\
  405. i = cla.3;",
  406. "while (i-->0 ~= 0)\
  407. { if (i-->0 == identifier or otherid)\
  408. return $8000 + k*$100 + j;\
  409. i = i + i->2 + 3;\
  410. k++;\
  411. }\
  412. break;\
  413. }\
  414. }\
  415. RT__Err(\"make use of\", cla, identifier);\
  416. rfalse;\
  417. ]", "", "", "", ""
  418. },
  419. {
  420. /* OP__Pr: test whether or not given object provides individual
  421. property with the given identifier code */
  422. "OP__Pr",
  423. "obj identifier;\
  424. if (obj<1 || obj > (#largest_object-255))\
  425. { if (identifier ~= print or print_to_array or call) rfalse;\
  426. switch(Z__Region(obj))\
  427. { 2: if (identifier == call) rtrue;\
  428. 3: if (identifier == print or print_to_array) rtrue;\
  429. }\
  430. rfalse;\
  431. }",
  432. "if (identifier<64)\
  433. { if (obj.&identifier ~= 0) rtrue;\
  434. rfalse;\
  435. }\
  436. if (obj..&identifier ~= 0) rtrue;\
  437. if (identifier<72 && obj in 1) rtrue;\
  438. rfalse;\
  439. ]", "", "", "", ""
  440. },
  441. {
  442. /* OC__Cl: test whether or not given object is of the given class */
  443. "OC__Cl",
  444. "obj cla j a n;\
  445. if (obj<1 || obj > (#largest_object-255))\
  446. { if (cla ~= 3 or 4) rfalse;\
  447. if (Z__Region(obj) == cla-1) rtrue;\
  448. rfalse;\
  449. }\
  450. if (cla == 1) {\
  451. if (obj<=4) rtrue;\
  452. if (obj in 1) rtrue;\
  453. rfalse;\
  454. } else if (cla == 2) {\
  455. if (obj<=4) rfalse;\
  456. if (obj in 1) rfalse;\
  457. rtrue;\
  458. } else if (cla == 3 or 4) {\
  459. rfalse;\
  460. }",
  461. "if (cla notin 1) { RT__Err(\"apply 'ofclass' for\", cla, -1);rfalse;}\
  462. @get_prop_addr obj 2 -> a;\
  463. if (a==0) rfalse;\
  464. @get_prop_len a -> n;\
  465. for (j=0: j<n/2: j++)\
  466. { if (a-->j == cla) rtrue;\
  467. }\
  468. rfalse;\
  469. ]", "", "", "", ""
  470. },
  471. { /* Copy__Primitive: routine to "deep copy" objects */
  472. "Copy__Primitive",
  473. "o1 o2 a1 a2 n m l size identifier;\
  474. for (n=0:n<48:n++)\
  475. { if (o2 has n) give o1 n;\
  476. else give o1 ~n;\
  477. }\
  478. for (n=1:n<64:n++) if (n~=2 or 3)\
  479. { a1 = o1.&n; a2 = o2.&n; size = o1.#n;\
  480. if (a1~=0 && a2~=0 && size==o2.#n)\
  481. { for (m=0:m<size:m++) a1->m=a2->m;\
  482. }\
  483. }",
  484. "if (o1.&3 == 0 || o2.&3 == 0) return;\
  485. for (n=o2.3: n-->0 ~= 0: n = n + size + 3)\
  486. { identifier = n-->0;\
  487. size = n->2;\
  488. for (m=o1.3: m-->0 ~= 0: m = m + m->2 + 3)\
  489. if ((identifier & $7fff == (m-->0) & $7fff) && size==m->2)\
  490. for (l=3: l<size+3: l++) m->l = n->l;\
  491. }\
  492. ]", "", "", "", ""
  493. },
  494. { /* RT__Err: for run-time errors occurring in the above: e.g.,
  495. an attempt to write to a non-existent individual
  496. property */
  497. "RT__Err",
  498. "crime obj id size p q;\
  499. print \"^[** Programming error: \";\
  500. if (crime<0) jump RErr;\
  501. if (crime==1) { print \"class \"; @print_obj obj;\
  502. \": 'create' can have 0 to 3 parameters only **]\";}\
  503. if (crime == 32) \"objectloop broken because the object \",\
  504. (name) obj, \" was moved while the loop passed through it **]\";\
  505. if (crime == 33) \"tried to print (char) \", obj,\
  506. \", which is not a valid ZSCII character code for output **]\";\
  507. if (crime == 34) \"tried to print (address) on something not the \",\
  508. \"byte address of a string **]\";\
  509. if (crime == 35) \"tried to print (string) on something not a \",\
  510. \"string **]\";\
  511. if (crime == 36) \"tried to print (object) on something not an \",\
  512. \"object or class **]\";",
  513. "if (crime < 32) { print \"tried to \";\
  514. if (crime >= 28) { if (crime==28 or 29) print \"read from \";\
  515. else print \"write to \";\
  516. if (crime==29 or 31) print \"-\"; print \"->\", obj,\
  517. \" in the\"; switch(size&7){0,1:q=0; 2:print \" string\";\
  518. q=1; 3:print \" table\";q=1; 4:print \" buffer\";q=WORDSIZE;} \
  519. if(size&16) print\" (->)\"; if(size&8) print\" (-->)\";\
  520. \" array ~\", (string) #array_names_offset-->p,\
  521. \"~, which has entries \", q, \" up to \",id,\" **]\"; }\
  522. if (crime >= 24 && crime <=27) { if (crime<=25) print \"read\";\
  523. else print \"write\"; print \" outside memory using \";\
  524. switch(crime) { 24,26:\"-> **]\"; 25,27:\"--> **]\"; } }\
  525. if (crime < 4) print \"test \"; else\
  526. if (crime < 12 || crime > 20) print \"find the \"; else\
  527. if (crime < 14) print \"use \";\
  528. if (crime==20) \"divide by zero **]\"; print \"~\";\
  529. switch(crime) {\
  530. 2: print \"in~ or ~notin\"; 3: print \"has~ or ~hasnt\";\
  531. 4: print \"parent\"; 5: print \"eldest\"; 6: print \"child\";\
  532. 7: print \"younger\"; 8: print \"sibling\"; 9: print \"children\";\
  533. 10: print \"youngest\"; 11: print \"elder\";\
  534. 12: print \"objectloop\"; 13: print \"}~ at end of ~objectloop\";\
  535. 14: \"give~ an attribute to \", (name) obj, \" **]\";\
  536. 15: \"remove~ \", (name) obj, \" **]\";",
  537. "16,17,18: print \"move~ \", (name) obj, \" to \", (name) id;\
  538. if (crime==18) { print \", which would make a loop: \",(name) obj;\
  539. p=id; if (p==obj) p=obj;\
  540. else do { print \" in \", (name) p; p=parent(p);} until (p==obj);\
  541. \" in \", (name) p, \" **]\"; }\
  542. \" **]\"; 19: \"give~ or test ~has~ or ~hasnt~ with a non-attribute"\
  543. " on the object \",(name) obj,\" **]\";\
  544. 21: print \".&\"; 22: print \".#\"; 23: print \".\"; }\
  545. \"~ of \", (name) obj, \" **]\"; }",
  546. ".RErr; if (obj>=0 && obj<=(#largest_object-255)) {\
  547. if (obj && obj in Class) print \"class \";\
  548. if (obj) @print_obj obj;else print \"nothing\";print\" \";}\
  549. print \"(object number \", obj, \") \";\
  550. if (id<0) print \"is not of class \", (name) -id;",
  551. "else if (size) print \"has a property \", (property) id,\
  552. \", but it is longer than 2 bytes so you cannot use ~.~\";\
  553. else\
  554. { print \" has no property \", (property) id;\
  555. p = #identifiers_table;\
  556. size = p-->0;\
  557. if (id<0 || id>=size)\
  558. print \" (and nor has any other object)\";\
  559. }\
  560. print \" to \", (string) crime, \" **]^\";\
  561. ]", ""
  562. },
  563. { /* Z__Region: Determines whether a value is:
  564. 1 an object number
  565. 2 a code address
  566. 3 a string address
  567. 0 none of the above */
  568. "Z__Region",
  569. "addr top;\
  570. if (addr==0 or -1) rfalse;\
  571. top = addr;\
  572. #IfV5; #iftrue (#version_number == 6) || (#version_number == 7);\
  573. @log_shift addr $FFFF -> top; #Endif; #Endif;\
  574. if (Unsigned__Compare(top, $001A-->0) >= 0) rfalse;\
  575. if (addr>=1 && addr<=(#largest_object-255)) rtrue;\
  576. #iftrue #oddeven_packing;\
  577. @test addr 1 ?~NotString;\
  578. if (Unsigned__Compare(addr, #strings_offset)<0) rfalse;\
  579. return 3;\
  580. .NotString;\
  581. if (Unsigned__Compare(addr, #code_offset)<0) rfalse;\
  582. return 2;\
  583. #ifnot;\
  584. if (Unsigned__Compare(addr, #strings_offset)>=0) return 3;\
  585. if (Unsigned__Compare(addr, #code_offset)>=0) return 2;\
  586. rfalse;\
  587. #endif;\
  588. ]", "", "", "", "", ""
  589. },
  590. { /* Unsigned__Compare: returns 1 if x>y, 0 if x=y, -1 if x<y */
  591. "Unsigned__Compare",
  592. "x y u v;\
  593. if (x==y) return 0;\
  594. if (x<0 && y>=0) return 1;\
  595. if (x>=0 && y<0) return -1;\
  596. u = x&$7fff; v= y&$7fff;\
  597. if (u>v) return 1;\
  598. return -1;\
  599. ]", "", "", "", "", ""
  600. },
  601. { /* Meta__class: returns the metaclass of an object */
  602. "Meta__class",
  603. "obj;\
  604. switch(Z__Region(obj))\
  605. { 2: return Routine;\
  606. 3: return String;\
  607. 1: if (obj in 1 || obj <= 4) return Class;\
  608. return Object;\
  609. }\
  610. rfalse;\
  611. ]", "", "", "", "", ""
  612. },
  613. { /* CP__Tab: searches a common property table for the given
  614. identifier, thus imitating the get_prop_addr opcode.
  615. Returns 0 if not provided, except:
  616. if the identifier supplied is -1, then returns
  617. the address of the first byte after the table. */
  618. "CP__Tab",
  619. "x id n l;\
  620. while ((n=0->x) ~= 0)\
  621. { if (n & $80) { x++; l = (0->x) & $3f; }\
  622. else { if (n & $40) l=2; else l=1; }\
  623. x++;\
  624. if ((n & $3f) == id) return x;\
  625. x = x + l;\
  626. }\
  627. if (id<0) return x+1; rfalse; ]", "", "", "", "", ""
  628. },
  629. { /* Cl__Ms: the five message-receiving properties of Classes */
  630. "Cl__Ms",
  631. "obj id y a b c d x;\
  632. switch(id)\
  633. { create:\
  634. if (children(obj)<=1) rfalse; x=child(obj);\
  635. remove x; if (x provides create) { if (y==0) x..create();\
  636. if (y==1) x..create(a); if (y==2) x..create(a,b);\
  637. if (y>3) RT__Err(1,obj); if (y>=3) x..create(a,b,c);}\
  638. return x;\
  639. recreate:\
  640. if (~~(a ofclass obj))\
  641. { RT__Err(\"recreate\", a, -obj); rfalse; }\
  642. Copy__Primitive(a, child(obj));\
  643. if (a provides create) { if (y==1) a..create();\
  644. if (y==2) a..create(b); if (y==3) a..create(b,c);\
  645. if (y>4) RT__Err(1,obj); if (y>=4) a..create(b,c,d);\
  646. } rfalse;",
  647. "destroy:\
  648. if (~~(a ofclass obj))\
  649. { RT__Err(\"destroy\", a, -obj); rfalse; }\
  650. if (a provides destroy) a..destroy();\
  651. Copy__Primitive(a, child(obj));\
  652. move a to obj; rfalse;\
  653. remaining:\
  654. return children(obj)-1;",
  655. "copy:\
  656. if (~~(a ofclass obj))\
  657. { RT__Err(\"copy\", a, -obj); rfalse; }\
  658. if (~~(b ofclass obj))\
  659. { RT__Err(\"copy\", b, -obj); rfalse; }\
  660. Copy__Primitive(a, b); rfalse;\
  661. }\
  662. ]", "", "", ""
  663. },
  664. { /* RT__ChT: check at run-time that a proposed object move is legal
  665. cause error and do nothing if not; otherwise move */
  666. "RT__ChT",
  667. "obj1 obj2 x;\
  668. if (obj1<5 || obj1>(#largest_object-255) || obj1 in 1)\
  669. return RT__Err(16,obj1,obj2);\
  670. if (obj2<5 || obj2>(#largest_object-255) || obj2 in 1)\
  671. return RT__Err(17,obj1,obj2);",
  672. "x=obj2; while (x~=0) { if (x==obj1) return RT__Err(18,obj1,obj2); \
  673. x=parent(x); }\
  674. #ifdef INFIX;\
  675. if (obj1 has infix__watching\
  676. || obj2 has infix__watching || (debug_flag & 15))\
  677. print \"[Moving \", (name) obj1, \" to \", (name) obj2, \"]^\";\
  678. #ifnot; #ifdef DEBUG;\
  679. if (debug_flag & 15)\
  680. print \"[Moving \", (name) obj1, \" to \", (name) obj2, \"]^\";\
  681. #endif; #endif;\
  682. @insert_obj obj1 obj2; ]", "", "", "", ""
  683. },
  684. { /* RT__ChR: check at run-time that a proposed object remove is legal
  685. cause error and do nothing if not; otherwise remove */
  686. "RT__ChR",
  687. "obj1;\
  688. if (obj1<5 || obj1>(#largest_object-255) || obj1 in 1)\
  689. return RT__Err(15,obj1);",
  690. "#ifdef INFIX;\
  691. if (obj1 has infix__watching || (debug_flag & 15))\
  692. print \"[Removing \", (name) obj1, \"]^\";\
  693. #ifnot; #ifdef DEBUG;\
  694. if (debug_flag & 15)\
  695. print \"[Removing \", (name) obj1, \"]^\";\
  696. #endif; #endif;\
  697. @remove_obj obj1; ]", "", "", "", ""
  698. },
  699. { /* RT__ChG: check at run-time that a proposed attr give is legal
  700. cause error and do nothing if not; otherwise give */
  701. "RT__ChG",
  702. "obj1 a;\
  703. if (obj1<5 || obj1>(#largest_object-255) || obj1 in 1)\
  704. return RT__Err(14,obj1); if (a<0 || a>=48) return RT__Err(19,obj1);\
  705. if (obj1 has a) return;",
  706. "#ifdef INFIX;\
  707. if (a ~= workflag && (obj1 has infix__watching || (debug_flag & 15)))\
  708. print \"[Giving \", (name) obj1, \" \", (DebugAttribute) a, \"]^\";\
  709. #ifnot; #ifdef DEBUG;\
  710. if (a ~= workflag && debug_flag & 15)\
  711. print \"[Giving \", (name) obj1, \" \", (DebugAttribute) a, \"]^\";\
  712. #endif; #endif;\
  713. @set_attr obj1 a; ]", "", "", "", ""
  714. },
  715. { /* RT__ChGt: check at run-time that a proposed attr give ~ is legal
  716. cause error and do nothing if not; otherwise give */
  717. "RT__ChGt",
  718. "obj1 a;\
  719. if (obj1<5 || obj1>(#largest_object-255) || obj1 in 1)\
  720. return RT__Err(14,obj1); if (a<0 || a>=48) return RT__Err(19,obj1);\
  721. if (obj1 hasnt a) return;",
  722. "#ifdef INFIX;\
  723. if (a ~= workflag && (obj1 has infix__watching || (debug_flag & 15)))\
  724. print \"[Giving \",(name) obj1,\" @@126\", (DebugAttribute) a, \"]^\";\
  725. #ifnot; #ifdef DEBUG;\
  726. if (a ~= workflag && debug_flag & 15)\
  727. print \"[Giving \",(name) obj1,\" @@126\", (DebugAttribute) a, \"]^\";\
  728. #endif; #endif;\
  729. @clear_attr obj1 a; ]", "", "", "", ""
  730. },
  731. { /* RT__ChPS: check at run-time that a proposed property set is legal
  732. cause error and do nothing if not; otherwise make it */
  733. "RT__ChPS",
  734. "obj prop val size;\
  735. if (obj<5 || obj>(#largest_object-255) || obj in 1 || obj.&prop==0 || (size=obj.#prop)>2 )\
  736. return RT__Err(\"set\", obj, prop, size);\
  737. @put_prop obj prop val;",
  738. "#ifdef INFIX;\
  739. if (obj has infix__watching || (debug_flag & 15)) RT__TrPS(obj,prop,val);\
  740. #ifnot; #ifdef DEBUG;\
  741. if (debug_flag & 15) RT__TrPS(obj,prop,val);\
  742. #endif; #endif;\
  743. return val; ]", "", "", "", ""
  744. },
  745. { /* RT__ChPR: check at run-time that a proposed property read is legal
  746. cause error and return 0 if not; otherwise read it */
  747. "RT__ChPR",
  748. "obj prop val size;\
  749. if (obj<5 || obj>(#largest_object-255) || (size=obj.#prop)>2)\
  750. {RT__Err(\"read\", obj, prop, size); obj=2;}\
  751. @get_prop obj prop -> val;",
  752. "return val; ]", "", "", "", ""
  753. },
  754. { /* RT__TrPS: trace property settings */
  755. "RT__TrPS",
  756. "obj prop val;\
  757. print \"[Setting \",(name) obj,\".\",(property) prop,\
  758. \" to \",val,\"]^\"; ]",
  759. "", "", "", "", ""
  760. },
  761. { /* RT__ChLDB: check at run-time that it's safe to load a byte
  762. and return the byte */
  763. "RT__ChLDB",
  764. "base offset a val;\
  765. a=base+offset;if (Unsigned__Compare(a,#readable_memory_offset)>=0)\
  766. return RT__Err(24);",
  767. "@loadb base offset -> val;return val; ]", "", "", "", ""
  768. },
  769. { /* RT__ChLDW: check at run-time that it's safe to load a word
  770. and return the word */
  771. "RT__ChLDW",
  772. "base offset a val;\
  773. a=base+2*offset;if (Unsigned__Compare(a,#readable_memory_offset)>=0)\
  774. return RT__Err(25);",
  775. "@loadw base offset -> val;return val; ]", "", "", "", ""
  776. },
  777. { /* RT__ChSTB: check at run-time that it's safe to store a byte
  778. and store it */
  779. "RT__ChSTB",
  780. "base offset val a f;\
  781. a=base+offset;\
  782. if (Unsigned__Compare(a,#array__start)>=0\
  783. && Unsigned__Compare(a,#array__end)<0) f=1; else\
  784. if (Unsigned__Compare(a,#cpv__start)>=0\
  785. && Unsigned__Compare(a,#cpv__end)<0) f=1; else\
  786. if (Unsigned__Compare(a,#ipv__start)>=0\
  787. && Unsigned__Compare(a,#ipv__end)<0) f=1; else\
  788. if (a==$0011) f=1;\
  789. if (f==0) return RT__Err(26);",
  790. "@storeb base offset val; ]", "", "", "", ""
  791. },
  792. { /* RT__ChSTW: check at run-time that it's safe to store a word
  793. and store it */
  794. "RT__ChSTW",
  795. "base offset val a f;\
  796. a=base+2*offset;\
  797. if (Unsigned__Compare(a,#array__start)>=0\
  798. && Unsigned__Compare(a,#array__end)<0) f=1; else\
  799. if (Unsigned__Compare(a,#cpv__start)>=0\
  800. && Unsigned__Compare(a,#cpv__end)<0) f=1; else\
  801. if (Unsigned__Compare(a,#ipv__start)>=0\
  802. && Unsigned__Compare(a,#ipv__end)<0) f=1; else\
  803. if (a==$0010) f=1;\
  804. if (f==0) return RT__Err(27);",
  805. "@storew base offset val; ]", "", "", "", ""
  806. },
  807. { /* RT__ChPrintC: check at run-time that it's safe to print (char)
  808. and do so */
  809. "RT__ChPrintC",
  810. "c fl;\
  811. if (c==0 or 9 or 11 or 13) fl=1;\
  812. if (c>=32 && c<=126) fl=1; if (c>=155 && c<=251) fl=1;\
  813. if (fl==0) return RT__Err(33,c);",
  814. "@print_char c; ]", "", "", "", ""
  815. },
  816. { /* RT__ChPrintA: check at run-time that it's safe to print (address)
  817. and do so */
  818. "RT__ChPrintA",
  819. "a;\
  820. if (Unsigned__Compare(a, #readable_memory_offset)>=0)\
  821. return RT__Err(34);",
  822. "@print_addr a; ]", "", "", "", ""
  823. },
  824. { /* RT__ChPrintS: check at run-time that it's safe to print (string)
  825. and do so */
  826. "RT__ChPrintS",
  827. "a;\
  828. if (Z__Region(a)~=3) return RT__Err(35);",
  829. "@print_paddr a; ]", "", "", "", ""
  830. },
  831. { /* RT__ChPrintO: check at run-time that it's safe to print (object)
  832. and do so */
  833. "RT__ChPrintO",
  834. "a;\
  835. if (Z__Region(a)~=1) return RT__Err(36);",
  836. "@print_obj a; ]", "", "", "", ""
  837. }
  838. };
  839. static VeneerRoutine VRs_g[VENEER_ROUTINES] =
  840. {
  841. {
  842. /* Box__Routine: Display the given array of text as a box quote.
  843. This is a very simple implementation; the library should provide
  844. a fancier version.
  845. */
  846. "Box__Routine",
  847. "maxwid arr ix;\
  848. maxwid = 0;\
  849. glk($0086, 7);\
  850. for (ix=0 : ix<arr-->0 : ix++) {\
  851. print (string) arr-->(ix+1);\
  852. new_line;\
  853. }\
  854. glk($0086, 0);\
  855. ]", "", "", "", "", ""
  856. },
  857. /* This batch of routines is expected to be defined (rather better) by
  858. the Inform library: these minimal forms here are provided to prevent
  859. tiny non-library-using programs from failing to compile when certain
  860. legal syntaxes (such as <<Action a b>>;) are used. */
  861. { "R_Process",
  862. "a b c d; print \"Action <\", a, \" \", b, \" \", c;\
  863. if (d) print \", \", d; print \">^\";\
  864. ]", "", "", "", "", ""
  865. },
  866. { "DefArt",
  867. "obj; print \"the \", obj; ]", "", "", "", "", ""
  868. },
  869. { "InDefArt",
  870. "obj; print \"a \", obj; ]", "", "", "", "", ""
  871. },
  872. { "CDefArt",
  873. "obj; print \"The \", obj; ]", "", "", "", "", ""
  874. },
  875. { "CInDefArt",
  876. "obj; print \"A \", obj; ]", "", "", "", "", ""
  877. },
  878. { "PrintShortName",
  879. "obj q; switch(metaclass(obj))\
  880. { 0: print \"nothing\";\
  881. Object: q = obj-->GOBJFIELD_NAME; @streamstr q;\
  882. Class: print \"class \"; q = obj-->GOBJFIELD_NAME; @streamstr q;\
  883. Routine: print \"(routine at \", obj, \")\";\
  884. String: print \"(string at \", obj, \")\";\
  885. } ]", "", "", "", "", ""
  886. },
  887. { "EnglishNumber",
  888. "obj; print obj; ]", "", "", "", "", ""
  889. },
  890. {
  891. /* Print__PName: Print the name of a property.
  892. */
  893. "Print__PName",
  894. "prop ptab cla maxcom minind maxind str;\
  895. if (prop & $FFFF0000) {\
  896. cla = #classes_table-->(prop & $FFFF);\
  897. print (name) cla, \"::\";\
  898. @ushiftr prop 16 prop;\
  899. }\
  900. ptab = #identifiers_table;\
  901. maxcom = ptab-->1;\
  902. minind = INDIV_PROP_START;\
  903. maxind = minind + ptab-->3;\
  904. str = 0;\
  905. if (prop >= 0 && prop < maxcom) {\
  906. str = (ptab-->0)-->prop;\
  907. }\
  908. else if (prop >= minind && prop < maxind) {\
  909. str = (ptab-->2)-->(prop-minind);\
  910. }\
  911. if (str)\
  912. print (string) str;\
  913. else\
  914. print \"<number \", prop, \">\";\
  915. ]", "", "", "", "", ""
  916. },
  917. /* The remaining routines make up the run-time half of the object
  918. orientation system, and need never be present for Inform 5 programs. */
  919. {
  920. /* WV__Pr: Write a value to the property for the given object.
  921. */
  922. "WV__Pr",
  923. "obj id val addr;\
  924. addr = obj.&id;\
  925. if (addr == 0) {\
  926. RT__Err(\"write\", obj, id);\
  927. return 0;\
  928. }\
  929. addr-->0 = val;\
  930. return 0;\
  931. ]", "", "", "", "", ""
  932. },
  933. {
  934. /* RV__Pr: Read a value to the property for the given object.
  935. */
  936. "RV__Pr",
  937. "obj id addr;\
  938. addr = obj.&id;\
  939. if (addr == 0) {\
  940. if (id > 0 && id < INDIV_PROP_START) {\
  941. return #cpv__start-->id;\
  942. }\
  943. RT__Err(\"read\", obj, id);\
  944. return 0;\
  945. }\
  946. return addr-->0;\
  947. ]", "", "", "", "", ""
  948. },
  949. {
  950. /* CA__Pr: Call, that is, print-or-run-or-read, a property:
  951. this exactly implements obj..prop(...). Note that
  952. classes (members of Class) have 5 built-in properties
  953. inherited from Class: create, recreate, destroy,
  954. remaining and copy. Implementing these here prevents
  955. the need for a full metaclass inheritance scheme.
  956. */
  957. "CA__Pr",
  958. "_vararg_count obj id zr s s2 z addr len m val;\
  959. @copy sp obj;\
  960. @copy sp id;\
  961. _vararg_count = _vararg_count - 2;\
  962. zr = Z__Region(obj);\
  963. if (zr == 2) {\
  964. if (id == call) {\
  965. s = sender; sender = self; self = obj;\
  966. #ifdef action; sw__var=action; #endif;\
  967. @call obj _vararg_count z;\
  968. self = sender; sender = s;\
  969. return z;\
  970. }\
  971. jump Call__Error;\
  972. }",
  973. " if (zr == 3) {\
  974. if (id == print) {\
  975. @streamstr obj; rtrue;\
  976. }\
  977. if (id == print_to_array) {\
  978. if (_vararg_count >= 2) {\
  979. @copy sp m;\
  980. @copy sp len;\
  981. }\
  982. else {\
  983. RT__Err(37); rfalse;\
  984. }\
  985. s2 = glk($0048);\
  986. s = glk($0043, m+4, len-4, 1, 0);",
  987. " if (s) {\
  988. glk($0047, s);\
  989. @streamstr obj;\
  990. glk($0047, s2);\
  991. @copy $ffffffff sp;\
  992. @copy s sp;\
  993. @glk $0044 2 0;\
  994. @copy sp len;\
  995. @copy sp 0;\
  996. m-->0 = len;\
  997. return len;\
  998. }\
  999. rfalse;\
  1000. }\
  1001. jump Call__Error;\
  1002. }",
  1003. " if (zr ~= 1)\
  1004. jump Call__Error;\
  1005. #ifdef DEBUG;#ifdef InformLibrary;\
  1006. if (debug_flag & 1 ~= 0) {\
  1007. debug_flag--;\
  1008. print \"[ ~\", (name) obj, \"~.\", (property) id, \"(\";\
  1009. @stkcopy _vararg_count;\
  1010. for (val=0 : val < _vararg_count : val++) {\
  1011. if (val) print \", \";\
  1012. @streamnum sp;\
  1013. }\
  1014. print \") ]^\";\
  1015. debug_flag++;\
  1016. }\
  1017. #endif;#endif;\
  1018. if (obj in Class) {\
  1019. switch (id) {\
  1020. remaining:\
  1021. return Cl__Ms(obj, id);\
  1022. copy:\
  1023. @copy sp m;\
  1024. @copy sp val;\
  1025. return Cl__Ms(obj, id, m, val);\
  1026. create, destroy, recreate:\
  1027. m = _vararg_count+2;\
  1028. @copy id sp;\
  1029. @copy obj sp;\
  1030. @call Cl__Ms m val;\
  1031. return val;\
  1032. }\
  1033. }",
  1034. " addr = obj.&id;\
  1035. if (addr == 0) {\
  1036. if (id > 0 && id < INDIV_PROP_START) {\
  1037. addr = #cpv__start + 4*id;\
  1038. len = 4;\
  1039. }\
  1040. else {\
  1041. jump Call__Error;\
  1042. }\
  1043. }\
  1044. else {\
  1045. len = obj.#id;\
  1046. }\
  1047. for (m=0 : 4*m<len : m++) {\
  1048. val = addr-->m;\
  1049. if (val == -1) rfalse;\
  1050. switch (Z__Region(val)) {\
  1051. 2:\
  1052. s = sender; sender = self; self = obj; s2 = sw__var;\
  1053. #ifdef LibSerial;\
  1054. if (id==life) sw__var=reason_code; else sw__var=action;\
  1055. #endif;",
  1056. " @stkcopy _vararg_count;\
  1057. @call val _vararg_count z;\
  1058. self = sender; sender = s; sw__var = s2;\
  1059. if (z ~= 0) return z;\
  1060. 3:\
  1061. @streamstr val;\
  1062. new_line;\
  1063. rtrue;\
  1064. default:\
  1065. return val;\
  1066. }\
  1067. }\
  1068. rfalse;\
  1069. .Call__Error;\
  1070. RT__Err(\"send message\", obj, id);\
  1071. rfalse;\
  1072. ]"
  1073. },
  1074. {
  1075. /* IB__Pr: ++(individual property) */
  1076. "IB__Pr",
  1077. "obj identifier x;\
  1078. x = obj.&identifier;\
  1079. if (x==0) { RT__Err(\"increment\", obj, identifier); return; }\
  1080. #ifdef INFIX;\
  1081. if (obj has infix__watching || (debug_flag & 15)) RT__TrPS(obj,identifier,(x-->0)+1);\
  1082. #ifnot; #ifdef DEBUG;\
  1083. if (debug_flag & 15) RT__TrPS(obj,identifier,(x-->0)+1);\
  1084. #endif; #endif;\
  1085. return ++(x-->0);\
  1086. ]", "", "", "", "", ""
  1087. },
  1088. {
  1089. /* IA__Pr: (individual property)++ */
  1090. "IA__Pr",
  1091. "obj identifier x;\
  1092. x = obj.&identifier;\
  1093. if (x==0) { RT__Err(\"increment\", obj, identifier); return; }\
  1094. #ifdef INFIX;\
  1095. if (obj has infix__watching || (debug_flag & 15))\
  1096. RT__TrPS(obj,identifier,(x-->0)+1);\
  1097. #ifnot; #ifdef DEBUG;\
  1098. if (debug_flag & 15) RT__TrPS(obj,identifier,(x-->0)+1);\
  1099. #endif; #endif;\
  1100. return (x-->0)++;\
  1101. ]", "", "", "", "", ""
  1102. },
  1103. {
  1104. /* DB__Pr: --(individual property) */
  1105. "DB__Pr",
  1106. "obj identifier x;\
  1107. x = obj.&identifier;\
  1108. if (x==0) { RT__Err(\"decrement\", obj, identifier); return; }\
  1109. #ifdef INFIX;\
  1110. if (obj has infix__watching || (debug_flag & 15)) RT__TrPS(obj,identifier,(x-->0)-1);\
  1111. #ifnot; #ifdef DEBUG;\
  1112. if (debug_flag & 15) RT__TrPS(obj,identifier,(x-->0)-1);\
  1113. #endif; #endif;\
  1114. return --(x-->0);\
  1115. ]", "", "", "", "", ""
  1116. },
  1117. {
  1118. /* DA__Pr: (individual property)-- */
  1119. "DA__Pr",
  1120. "obj identifier x;\
  1121. x = obj.&identifier;\
  1122. if (x==0) { RT__Err(\"decrement\", obj, identifier); return; }\
  1123. #ifdef INFIX;\
  1124. if (obj has infix__watching || (debug_flag & 15)) RT__TrPS(obj,identifier,(x-->0)-1);\
  1125. #ifnot; #ifdef DEBUG;\
  1126. if (debug_flag & 15) RT__TrPS(obj,identifier,(x-->0)-1);\
  1127. #endif; #endif;\
  1128. return (x-->0)--;\
  1129. ]", "", "", "", "", ""
  1130. },
  1131. {
  1132. /* RA__Pr: Read the property address of a given property value.
  1133. Returns zero if it isn't provided by the object. This
  1134. understands all the same concerns as RL__Pr().
  1135. */
  1136. "RA__Pr",
  1137. "obj id cla prop ix;\
  1138. if (id & $FFFF0000) {\
  1139. cla = #classes_table-->(id & $FFFF);\
  1140. if (~~(obj ofclass cla)) return 0;\
  1141. @ushiftr id 16 id;\
  1142. obj = cla;\
  1143. }\
  1144. prop = CP__Tab(obj, id);\
  1145. if (prop==0) return 0;\
  1146. if (obj in Class && cla == 0) {\
  1147. if (id < INDIV_PROP_START || id >= INDIV_PROP_START+8)\
  1148. return 0;\
  1149. }\
  1150. if (self ~= obj) {\
  1151. @aloadbit prop 72 ix;\
  1152. if (ix) return 0;\
  1153. }\
  1154. return prop-->1;\
  1155. ]", "", "", "", "", ""
  1156. },
  1157. {
  1158. /* RL__Pr: Read the property length of a given property value.
  1159. Returns zero if it isn't provided by the object. This understands
  1160. inherited values (of the form class::prop) as well as simple
  1161. property ids and the special metaclass methods. It also knows
  1162. that private properties can only be read if (self == obj).
  1163. */
  1164. "RL__Pr",
  1165. "obj id cla prop ix;\
  1166. if (id & $FFFF0000) {\
  1167. cla = #classes_table-->(id & $FFFF);\
  1168. if (~~(obj ofclass cla)) return 0;\
  1169. @ushiftr id 16 id;\
  1170. obj = cla;\
  1171. }\
  1172. prop = CP__Tab(obj, id);\
  1173. if (prop==0) return 0;\
  1174. if (obj in Class && cla == 0) {\
  1175. if (id < INDIV_PROP_START || id >= INDIV_PROP_START+8)\
  1176. return 0;\
  1177. }\
  1178. if (self ~= obj) {\
  1179. @aloadbit prop 72 ix;\
  1180. if (ix) return 0;\
  1181. }\
  1182. @aloads prop 1 ix;\
  1183. return WORDSIZE * ix;\
  1184. ]", "", "", "", "", ""
  1185. },
  1186. {
  1187. /* RA__Sc: Implement the \"superclass\" (::) operator. This
  1188. returns an compound property identifier, which is a
  1189. 32-bit value.
  1190. */
  1191. "RA__Sc",
  1192. "cla id j;\
  1193. if ((cla notin Class) && (cla ~= Class or String or Routine or Object)) {\
  1194. RT__Err(\"be a '::' superclass\", cla, -1);\
  1195. rfalse;\
  1196. }\
  1197. for (j=0 : #classes_table-->j ~= 0 : j++) {\
  1198. if (cla == #classes_table-->j) {\
  1199. return (id * $10000 + j);\
  1200. }\
  1201. }\
  1202. RT__Err(\"make use of\", cla, id);\
  1203. rfalse;\
  1204. ]", "", "", "", "", ""
  1205. },
  1206. {
  1207. /* OP__Pr: Test whether the given object provides the given property.
  1208. This winds up calling RA__Pr().
  1209. */
  1210. "OP__Pr",
  1211. "obj id zr;\
  1212. zr = Z__Region(obj);\
  1213. if (zr == 3) {\
  1214. if (id == print or print_to_array) rtrue;\
  1215. rfalse;\
  1216. }\
  1217. if (zr == 2) {\
  1218. if (id == call) rtrue;\
  1219. rfalse;\
  1220. }\
  1221. if (zr ~= 1) rfalse;\
  1222. if (id >= INDIV_PROP_START && id < INDIV_PROP_START+8) {\
  1223. if (obj in Class) rtrue;\
  1224. }\
  1225. if (obj.&id ~= 0)\
  1226. rtrue;\
  1227. rfalse;\
  1228. ]", "", "", "", "", ""
  1229. },
  1230. {
  1231. /* OC__Cl: Test whether the given object is of the given class.
  1232. (implements the OfClass operator.)
  1233. */
  1234. "OC__Cl",
  1235. "obj cla zr jx inlist inlistlen;\
  1236. zr = Z__Region(obj);\
  1237. if (zr == 3) {\
  1238. if (cla == String) rtrue;\
  1239. rfalse;\
  1240. }\
  1241. if (zr == 2) {\
  1242. if (cla == Routine) rtrue;\
  1243. rfalse;\
  1244. }\
  1245. if (zr ~= 1) rfalse;\
  1246. if (cla == Class) {\
  1247. if (obj in Class\
  1248. || obj == Class or String or Routine or Object)\
  1249. rtrue;\
  1250. rfalse;\
  1251. }\
  1252. if (cla == Object) {\
  1253. if (obj in Class\
  1254. || obj == Class or String or Routine or Object)\
  1255. rfalse;\
  1256. rtrue;\
  1257. }\
  1258. if (cla == String or Routine) rfalse;\
  1259. if (cla notin Class) {\
  1260. RT__Err(\"apply 'ofclass' for\", cla, -1);\
  1261. rfalse;\
  1262. }\
  1263. inlist = obj.&2;\
  1264. if (inlist == 0) rfalse;\
  1265. inlistlen = (obj.#2) / WORDSIZE;\
  1266. for (jx=0 : jx<inlistlen : jx++) {\
  1267. if (inlist-->jx == cla) rtrue;\
  1268. }\
  1269. rfalse;\
  1270. ]", "", "", "", "", ""
  1271. },
  1272. {
  1273. /* Copy__Primitive: Routine to \"deep copy\" objects.
  1274. */
  1275. "Copy__Primitive",
  1276. "o1 o2 p1 p2 pcount i j propid proplen val pa1 pa2;\
  1277. for (i=1 : i<=NUM_ATTR_BYTES : i++) {\
  1278. o1->i = o2->i;\
  1279. }\
  1280. p2 = o2-->GOBJFIELD_PROPTAB;\
  1281. pcount = p2-->0;\
  1282. p2 = p2+4;\
  1283. for (i=0 : i<pcount : i++) {\
  1284. @aloads p2 0 propid;\
  1285. @aloads p2 1 proplen;\
  1286. p1 = CP__Tab(o1, propid);\
  1287. if (p1) {\
  1288. @aloads p1 1 val;\
  1289. if (proplen == val) {\
  1290. @aloads p2 4 val;\
  1291. @astores p1 4 val;\
  1292. pa1 = p1-->1;\
  1293. pa2 = p2-->1;\
  1294. for (j=0 : j<proplen : j++)\
  1295. pa1-->j = pa2-->j;\
  1296. }\
  1297. }\
  1298. p2 = p2+10;\
  1299. }\
  1300. ]", "", "", "", "", ""
  1301. },
  1302. { /* RT__Err: for run-time errors occurring in the above: e.g.,
  1303. an attempt to write to a non-existent individual
  1304. property */
  1305. "RT__Err",
  1306. "crime obj id size p q;\
  1307. print \"^[** Programming error: \";\
  1308. if (crime<0) jump RErr;\
  1309. if (crime==1) { print \"class \"; q = obj-->GOBJFIELD_NAME; @streamstr q;\
  1310. \": 'create' can have 0 to 3 parameters only **]\";}\
  1311. if (crime == 40) \"tried to change printing variable \",\
  1312. obj, \"; must be 0 to \", #dynam_string_table-->0-1, \" **]\";\
  1313. if (crime == 32) \"objectloop broken because the object \",\
  1314. (name) obj, \" was moved while the loop passed through it **]\";\
  1315. if (crime == 33) \"tried to print (char) \", obj,\
  1316. \", which is not a valid Glk character code for output **]\";\
  1317. if (crime == 34) \"tried to print (address) on something not the \",\
  1318. \"address of a dict word **]\";\
  1319. if (crime == 35) \"tried to print (string) on something not a \",\
  1320. \"string **]\";\
  1321. if (crime == 36) \"tried to print (object) on something not an \",\
  1322. \"object or class **]\";\
  1323. if (crime == 37) \"tried to call Glulx print_to_array with only \",\
  1324. \"one argument **]\";",
  1325. "if (crime < 32) { print \"tried to \";\
  1326. if (crime >= 28) { if (crime==28 or 29) print \"read from \";\
  1327. else print \"write to \";\
  1328. if (crime==29 or 31) print \"-\"; print \"->\", obj,\
  1329. \" in the\"; switch(size&7){0,1:q=0; 2:print \" string\";\
  1330. q=1; 3:print \" table\";q=1; 4:print \" buffer\";q=WORDSIZE;} \
  1331. if(size&16) print\" (->)\"; if(size&8) print\" (-->)\";\
  1332. \" array ~\", (string) #array_names_offset-->(p+1),\
  1333. \"~, which has entries \", q, \" up to \",id,\" **]\"; }\
  1334. if (crime >= 24 && crime <=27) { if (crime<=25) print \"read\";\
  1335. else print \"write\"; print \" outside memory using \";\
  1336. switch(crime) { 24,26:\"-> **]\"; 25,27:\"--> **]\"; } }\
  1337. if (crime < 4) print \"test \"; else\
  1338. if (crime < 12 || crime > 20) print \"find the \"; else\
  1339. if (crime < 14) print \"use \";\
  1340. if (crime==20) \"divide by zero **]\"; print \"~\";\
  1341. switch(crime) {\
  1342. 2: print \"in~ or ~notin\"; 3: print \"has~ or ~hasnt\";\
  1343. 4: print \"parent\"; 5: print \"eldest\"; 6: print \"child\";\
  1344. 7: print \"younger\"; 8: print \"sibling\"; 9: print \"children\";\
  1345. 10: print \"youngest\"; 11: print \"elder\";\
  1346. 12: print \"objectloop\"; 13: print \"}~ at end of ~objectloop\";\
  1347. 14: \"give~ an attribute to \", (name) obj, \" **]\";\
  1348. 15: \"remove~ \", (name) obj, \" **]\";",
  1349. "16,17,18: print \"move~ \", (name) obj, \" to \", (name) id;\
  1350. if (crime==18) { print \", which would make a loop: \",(name) obj;\
  1351. p=id; if (p==obj) p=obj;\
  1352. else do { print \" in \", (name) p; p=parent(p);} until (p==obj);\
  1353. \" in \", (name) p, \" **]\"; }\
  1354. \" **]\"; 19: \"give~ or test ~has~ or ~hasnt~ with a non-attribute"\
  1355. " on the object \",(name) obj,\" **]\";\
  1356. 21: print \".&\"; 22: print \".#\"; 23: print \".\"; }\
  1357. \"~ of \", (name) obj, \" **]\"; }",
  1358. ".RErr; if (obj==0 || obj->0>=$70 && obj->0<=$7F) {\
  1359. if (obj && obj in Class) print \"class \";\
  1360. if (obj) print (object) obj;else print \"nothing\";print\" \";}\
  1361. print \"(object number \", obj, \") \";\
  1362. if (id<0) print \"is not of class \", (name) -id;",
  1363. "else\
  1364. { print \" has no property \", (property) id;\
  1365. p = #identifiers_table;\
  1366. size = INDIV_PROP_START + p-->3;\
  1367. if (id<0 || id>=size)\
  1368. print \" (and nor has any other object)\";\
  1369. }\
  1370. print \" to \", (string) crime, \" **]^\";\
  1371. ]", ""
  1372. },
  1373. {
  1374. /* Z__Region: Determines whether a value is:
  1375. 1 an object number
  1376. 2 a code address
  1377. 3 a string address
  1378. 0 none of the above
  1379. */
  1380. "Z__Region",
  1381. "addr tb endmem;\
  1382. if (addr<36) rfalse;\
  1383. @getmemsize endmem;\
  1384. @jgeu addr endmem?outrange;\
  1385. tb=addr->0;\
  1386. if (tb >= $E0) return 3;\
  1387. if (tb >= $C0) return 2;\
  1388. if (tb >= $70 && tb <= $7F && addr >= (0-->2)) return 1;\
  1389. .outrange;\
  1390. rfalse;\
  1391. ]", "", "", "", "", ""
  1392. },
  1393. { /* Unsigned__Compare: returns 1 if x>y, 0 if x=y, -1 if x<y */
  1394. "Unsigned__Compare",
  1395. "x y;\
  1396. @jleu x y ?lesseq;\
  1397. return 1;\
  1398. .lesseq;\
  1399. @jeq x y ?equal;\
  1400. return -1;\
  1401. .equal;\
  1402. return 0;\
  1403. ]", "", "", "", "", ""
  1404. },
  1405. { /* Meta__class: returns the metaclass of an object */
  1406. "Meta__class",
  1407. "obj;\
  1408. switch(Z__Region(obj))\
  1409. { 2: return Routine;\
  1410. 3: return String;\
  1411. 1: if (obj in Class\
  1412. || obj == Class or String or Routine or Object)\
  1413. return Class;\
  1414. return Object;\
  1415. }\
  1416. rfalse;\
  1417. ]", "", "", "", "", ""
  1418. },
  1419. {
  1420. /* CP__Tab: Search a property table for the given identifier.
  1421. The definition here is a bit different from the Z-code veneer.
  1422. This just searches the property table of obj for an entry with
  1423. the given identifier. It return the address of the property
  1424. entry, or 0 if nothing found. (Remember that the value returned
  1425. is not the address of the property *data*; it's the structure
  1426. which contains the address/length/flags.)
  1427. */
  1428. "CP__Tab",
  1429. "obj id otab max res;\
  1430. if (Z__Region(obj)~=1) {RT__Err(23, obj); rfalse;}\
  1431. otab = obj-->GOBJFIELD_PROPTAB;\
  1432. if (otab == 0) return 0;\
  1433. max = otab-->0;\
  1434. otab = otab+4;\
  1435. @binarysearch id 2 otab 10 max 0 0 res;\
  1436. return res;\
  1437. ]", "", "", "", "", ""
  1438. },
  1439. {
  1440. /* Cl__Ms: Implements the five message-receiving properties of
  1441. Classes.
  1442. */
  1443. "Cl__Ms",
  1444. "_vararg_count obj id a b x y;\
  1445. @copy sp obj;\
  1446. @copy sp id;\
  1447. _vararg_count = _vararg_count - 2;\
  1448. switch (id) {\
  1449. create:\
  1450. if (children(obj) <= 1) rfalse;\
  1451. x = child(obj);\
  1452. remove x;\
  1453. if (x provides create) {\
  1454. @copy create sp;\
  1455. @copy x sp;\
  1456. y = _vararg_count + 2;\
  1457. @call CA__Pr y 0;\
  1458. }\
  1459. return x;\
  1460. recreate:\
  1461. @copy sp a;\
  1462. _vararg_count--;\
  1463. if (~~(a ofclass obj)) {\
  1464. RT__Err(\"recreate\", a, -obj);\
  1465. rfalse;\
  1466. }\
  1467. if (a provides destroy)\
  1468. a.destroy();\
  1469. Copy__Primitive(a, child(obj));\
  1470. if (a provides create) {\
  1471. @copy create sp;\
  1472. @copy a sp;\
  1473. y = _vararg_count + 2;\
  1474. @call CA__Pr y 0;\
  1475. }\
  1476. rfalse;\
  1477. destroy:\
  1478. @copy sp a;\
  1479. _vararg_count--;\
  1480. if (~~(a ofclass obj)) {\
  1481. RT__Err(\"destroy\", a, -obj);\
  1482. rfalse;\
  1483. }\
  1484. if (a provides destroy)\
  1485. a.destroy();\
  1486. Copy__Primitive(a, child(obj));\
  1487. move a to obj;\
  1488. rfalse;\
  1489. remaining:\
  1490. return children(obj)-1;\
  1491. copy:\
  1492. @copy sp a;\
  1493. @copy sp b;\
  1494. _vararg_count = _vararg_count - 2;\
  1495. if (~~(a ofclass obj)) {\
  1496. RT__Err(\"copy\", a, -obj);\
  1497. rfalse;\
  1498. }\
  1499. if (~~(b ofclass obj)) {\
  1500. RT__Err(\"copy\", b, -obj);\
  1501. rfalse;\
  1502. }\
  1503. Copy__Primitive(a, b);\
  1504. rfalse;\
  1505. }\
  1506. ]", "", "", "", "", ""
  1507. },
  1508. {
  1509. /* RT__ChT: Check at run-time that a proposed object move is legal.
  1510. Cause error and do nothing if not; otherwise move
  1511. */
  1512. "RT__ChT",
  1513. "obj1 obj2 ix;\
  1514. if (obj1==0 || Z__Region(obj1)~=1\
  1515. || (obj1 == Class or String or Routine or Object) || obj1 in Class)\
  1516. return RT__Err(16, obj1, obj2);\
  1517. if (obj2==0 || Z__Region(obj2)~=1\
  1518. || (obj2 == Class or String or Routine or Object) || obj2 in Class)\
  1519. return RT__Err(17, obj1, obj2);\
  1520. ix = obj2;\
  1521. while (ix ~= 0) {\
  1522. if (ix==obj1) return RT__Err(18, obj1, obj2);\
  1523. ix = parent(ix);\
  1524. }\
  1525. #ifdef INFIX;\
  1526. if (obj1 has infix__watching\
  1527. || obj2 has infix__watching || (debug_flag & 15))\
  1528. print \"[Moving \", (name) obj1, \" to \", (name) obj2, \"]^\";\
  1529. #ifnot; #ifdef DEBUG;\
  1530. if (debug_flag & 15)\
  1531. print \"[Moving \", (name) obj1, \" to \", (name) obj2, \"]^\";\
  1532. #endif; #endif;\
  1533. OB__Move(obj1, obj2);\
  1534. ]", "", "", "", "", ""
  1535. },
  1536. {
  1537. /* RT__ChR: Check at run-time that a proposed object remove is legal.
  1538. Cause error and do nothing if not; otherwise remove
  1539. */
  1540. "RT__ChR",
  1541. "obj1;\
  1542. if (obj1==0 || Z__Region(obj1)~=1\
  1543. || (obj1 == Class or String or Routine or Object) || obj1 in Class)\
  1544. return RT__Err(15, obj1);\
  1545. #ifdef INFIX;\
  1546. if (obj1 has infix__watching || (debug_flag & 15))\
  1547. print \"[Removing \", (name) obj1, \"]^\";\
  1548. #ifnot; #ifdef DEBUG;\
  1549. if (debug_flag & 15)\
  1550. print \"[Removing \", (name) obj1, \"]^\";\
  1551. #endif; #endif;\
  1552. OB__Remove(obj1);\
  1553. ]", "", "", "", "", ""
  1554. },
  1555. { /* RT__ChG: check at run-time that a proposed attr give is legal
  1556. cause error and do nothing if not; otherwise give */
  1557. "RT__ChG",
  1558. "obj1 a;\
  1559. if (Z__Region(obj1) ~= 1) return RT__Err(14,obj1);\
  1560. if (obj1 in Class || obj1 == Class or String or Routine or Object)\
  1561. return RT__Err(14,obj1);\
  1562. if (a<0 || a>=NUM_ATTR_BYTES*8) return RT__Err(19,obj1);\
  1563. if (obj1 has a) return;",
  1564. "#ifdef INFIX;\
  1565. if (a ~= workflag && (obj1 has infix__watching || (debug_flag & 15)))\
  1566. print \"[Giving \", (name) obj1, \" \", (DebugAttribute) a, \"]^\";\
  1567. #ifnot; #ifdef DEBUG;\
  1568. if (a ~= workflag && debug_flag & 15)\
  1569. print \"[Giving \", (name) obj1, \" \", (DebugAttribute) a, \"]^\";\
  1570. #endif; #endif;\
  1571. give obj1 a; ]", "", "", "", ""
  1572. },
  1573. { /* RT__ChGt: check at run-time that a proposed attr give ~ is legal
  1574. cause error and do nothing if not; otherwise give */
  1575. "RT__ChGt",
  1576. "obj1 a;\
  1577. if (Z__Region(obj1) ~= 1) return RT__Err(14,obj1);\
  1578. if (obj1 in Class || obj1 == Class or String or Routine or Object)\
  1579. return RT__Err(14,obj1);\
  1580. if (a<0 || a>=NUM_ATTR_BYTES*8) return RT__Err(19,obj1);\
  1581. if (obj1 hasnt a) return;",
  1582. "#ifdef INFIX;\
  1583. if (a ~= workflag && (obj1 has infix__watching || (debug_flag & 15)))\
  1584. print \"[Giving \",(name) obj1,\" @@126\", (DebugAttribute) a, \"]^\";\
  1585. #ifnot; #ifdef DEBUG;\
  1586. if (a ~= workflag && debug_flag & 15)\
  1587. print \"[Giving \",(name) obj1,\" @@126\", (DebugAttribute) a, \"]^\";\
  1588. #endif; #endif;\
  1589. give obj1 ~a; ]", "", "", "", ""
  1590. },
  1591. {
  1592. /* RT__ChPS: Check at run-time that a proposed property set is legal.
  1593. Cause error and do nothing if not; otherwise make it.
  1594. */
  1595. "RT__ChPS",
  1596. "obj prop val res;\
  1597. if (obj==0 || Z__Region(obj)~=1\
  1598. || (obj == Class or String or Routine or Object) || obj in Class)\
  1599. return RT__Err(\"set\", obj, prop);\
  1600. res = WV__Pr(obj, prop, val);\
  1601. #ifdef INFIX;\
  1602. if (obj has infix__watching || (debug_flag & 15)) RT__TrPS(obj,prop,val);\
  1603. #ifnot; #ifdef DEBUG;\
  1604. if (debug_flag & 15) RT__TrPS(obj,prop,val);\
  1605. #endif; #endif;\
  1606. return res;\
  1607. ]", "", "", "", "", ""
  1608. },
  1609. { /* RT__ChPR: check at run-time that a proposed property read is legal.
  1610. cause error and return 0 if not; otherwise read it */
  1611. "RT__ChPR",
  1612. "obj prop val;\
  1613. if (obj==0 or Class or String or Routine or Object || Z_Region(obj)~=1 )\
  1614. {RT__Err(\"read\", obj, prop); obj=2;}\
  1615. val = RV__Pr(obj, prop);",
  1616. "return val; ]", "", "", "", ""
  1617. },
  1618. { /* RT__TrPS: trace property settings */
  1619. "RT__TrPS",
  1620. "obj prop val;\
  1621. print \"[Setting \",(name) obj,\".\",(property) prop,\
  1622. \" to \",val,\"]^\"; ]",
  1623. "", "", "", "", ""
  1624. },
  1625. {
  1626. /* RT__ChLDB: Check at run-time that it's safe to load a byte
  1627. and return the byte.
  1628. */
  1629. "RT__ChLDB",
  1630. "base offset a b val;\
  1631. a=base+offset;\
  1632. @getmemsize b;\
  1633. if (Unsigned__Compare(a, b) >= 0)\
  1634. return RT__Err(24);\
  1635. @aloadb base offset val;\
  1636. return val;\
  1637. ]", "", "", "", "", ""
  1638. },
  1639. {
  1640. /* RT__ChLDW: Check at run-time that it's safe to load a word
  1641. and return the word
  1642. */
  1643. "RT__ChLDW",
  1644. "base offset a b val;\
  1645. a=base+WORDSIZE*offset;\
  1646. @getmemsize b;\
  1647. if (Unsigned__Compare(a, b) >= 0)\
  1648. return RT__Err(25);\
  1649. @aload base offset val;\
  1650. return val;\
  1651. ]", "", "", "", "", ""
  1652. },
  1653. {
  1654. /* RT__ChSTB: Check at run-time that it's safe to store a byte
  1655. and store it
  1656. */
  1657. "RT__ChSTB",
  1658. "base offset val a b;\
  1659. a=base+offset;\
  1660. @getmemsize b;\
  1661. if (Unsigned__Compare(a, b) >= 0) jump ChSTB_Fail;\
  1662. @aload 0 2 b;\
  1663. if (Unsigned__Compare(a, b) < 0) jump ChSTB_Fail;\
  1664. @astoreb base offset val;\
  1665. return;\
  1666. .ChSTB_Fail;\
  1667. return RT__Err(26);\
  1668. ]", "", "", "", "", ""
  1669. },
  1670. {
  1671. /* RT__ChSTW: Check at run-time that it's safe to store a word
  1672. and store it
  1673. */
  1674. "RT__ChSTW",
  1675. "base offset val a b;\
  1676. a=base+WORDSIZE*offset;\
  1677. @getmemsize b;\
  1678. if (Unsigned__Compare(a, b) >= 0) jump ChSTW_Fail;\
  1679. @aload 0 2 b;\
  1680. if (Unsigned__Compare(a, b) < 0) jump ChSTW_Fail;\
  1681. @astore base offset val;\
  1682. return;\
  1683. .ChSTW_Fail;\
  1684. return RT__Err(27);\
  1685. ]", "", "", "", "", ""
  1686. },
  1687. {
  1688. /* RT__ChPrintC: Check at run-time that it's safe to print (char)
  1689. and do so.
  1690. */
  1691. "RT__ChPrintC",
  1692. "c;\
  1693. if (c<10 || (c>10 && c<32) || (c>126 && c<160))\
  1694. return RT__Err(33,c);\
  1695. if (c>=0 && c<256)\
  1696. @streamchar c;\
  1697. else\
  1698. @streamunichar c;\
  1699. ]", "", "", "", "", ""
  1700. },
  1701. {
  1702. /* RT__ChPrintA: Check at run-time that it's safe to print (address)
  1703. and do so.
  1704. */
  1705. "RT__ChPrintA",
  1706. "addr endmem;\
  1707. if (addr<36)\
  1708. return RT__Err(34);\
  1709. @getmemsize endmem;\
  1710. if (Unsigned__Compare(addr, endmem) >= 0)\
  1711. return RT__Err(34);\
  1712. if (addr->0 ~= $60)\
  1713. return RT__Err(34);\
  1714. Print__Addr(addr);\
  1715. ]", "", "", "", "", ""
  1716. },
  1717. {
  1718. /* Check at run-time that it's safe to print (string) and do so.
  1719. */
  1720. "RT__ChPrintS",
  1721. "str;\
  1722. if (Z__Region(str) ~= 3)\
  1723. return RT__Err(35);\
  1724. @streamstr str;\
  1725. ]", "", "", "", "", ""
  1726. },
  1727. {
  1728. /* Check at run-time that it's safe to print (object) and do so.
  1729. */
  1730. "RT__ChPrintO",
  1731. "obj;\
  1732. if (Z__Region(obj) ~= 1)\
  1733. return RT__Err(36);\
  1734. @aload obj GOBJFIELD_NAME sp; @streamstr sp;\
  1735. ]", "", "", "", "", ""
  1736. },
  1737. {
  1738. /* OB__Move: Move an object within the object tree. This does no
  1739. more error checking than the Z-code \"move\" opcode.
  1740. */
  1741. "OB__Move",
  1742. "obj dest par chi sib;\
  1743. par = obj-->GOBJFIELD_PARENT;\
  1744. if (par ~= 0) {\
  1745. chi = par-->GOBJFIELD_CHILD;\
  1746. if (chi == obj) {\
  1747. par-->GOBJFIELD_CHILD = obj-->GOBJFIELD_SIBLING;\
  1748. }\
  1749. else {\
  1750. while (1) {\
  1751. sib = chi-->GOBJFIELD_SIBLING;\
  1752. if (sib == obj)\
  1753. break;\
  1754. chi = sib;\
  1755. }\
  1756. chi-->GOBJFIELD_SIBLING = obj-->GOBJFIELD_SIBLING;\
  1757. }\
  1758. }\
  1759. obj-->GOBJFIELD_SIBLING = dest-->GOBJFIELD_CHILD;\
  1760. obj-->GOBJFIELD_PARENT = dest;\
  1761. dest-->GOBJFIELD_CHILD = obj;\
  1762. rfalse;\
  1763. ]", "", "", "", "", ""
  1764. },
  1765. {
  1766. /* OB__Remove: Remove an object from the tree. This does no
  1767. more error checking than the Z-code \"remove\" opcode.
  1768. */
  1769. "OB__Remove",
  1770. "obj par chi sib;\
  1771. par = obj-->GOBJFIELD_PARENT;\
  1772. if (par == 0)\
  1773. rfalse;\
  1774. chi = par-->GOBJFIELD_CHILD;\
  1775. if (chi == obj) {\
  1776. par-->GOBJFIELD_CHILD = obj-->GOBJFIELD_SIBLING;\
  1777. }\
  1778. else {\
  1779. while (1) {\
  1780. sib = chi-->GOBJFIELD_SIBLING;\
  1781. if (sib == obj)\
  1782. break;\
  1783. chi = sib;\
  1784. }\
  1785. chi-->GOBJFIELD_SIBLING = obj-->GOBJFIELD_SIBLING;\
  1786. }\
  1787. obj-->GOBJFIELD_SIBLING = 0;\
  1788. obj-->GOBJFIELD_PARENT = 0;\
  1789. rfalse;\
  1790. ]", "", "", "", "", ""
  1791. },
  1792. {
  1793. /* Print__Addr: Handle the print (address) statement. In Glulx,
  1794. this behaves differently than on the Z-machine; it can *only*
  1795. print dictionary words.
  1796. */
  1797. "Print__Addr",
  1798. "addr ix ch;\
  1799. if (addr->0 ~= $60) {\
  1800. print \"(\", addr, \": not dict word)\";\
  1801. return;\
  1802. }\
  1803. for (ix=1 : ix <= DICT_WORD_SIZE : ix++) {\
  1804. #ifndef DICT_IS_UNICODE;\
  1805. ch = addr->ix;\
  1806. #ifnot;\
  1807. ch = addr-->ix;\
  1808. #endif;\
  1809. if (ch == 0) return;\
  1810. print (char) ch;\
  1811. }\
  1812. ]", "", "", "", "", ""
  1813. },
  1814. {
  1815. /* Glk__Wrap: This is a wrapper for the @glk opcode. It just passes
  1816. all its arguments into the Glk dispatcher, and returns the Glk
  1817. call result.
  1818. */
  1819. "Glk__Wrap",
  1820. "_vararg_count callid retval;\
  1821. @copy sp callid;\
  1822. _vararg_count = _vararg_count - 1;\
  1823. @glk callid _vararg_count retval;\
  1824. return retval;\
  1825. ]", "", "", "", "", ""
  1826. },
  1827. {
  1828. /* Dynam__String: Set dynamic string (printing variable) num to the
  1829. given val, which can be any string or function.
  1830. */
  1831. "Dynam__String",
  1832. "num val;\
  1833. if (num < 0 || num >= #dynam_string_table-->0)\
  1834. return RT__Err(40, num);\
  1835. (#dynam_string_table)-->(num+1) = val;\
  1836. ]", "", "", "", "", ""
  1837. }
  1838. };
  1839. static void mark_as_needed_z(int code)
  1840. {
  1841. ASSERT_ZCODE();
  1842. if (veneer_routine_needs_compilation[code] == VR_UNUSED)
  1843. { veneer_routine_needs_compilation[code] = VR_CALLED;
  1844. /* Here each routine must mark every veneer routine it explicitly
  1845. calls as needed */
  1846. switch(code)
  1847. { case WV__Pr_VR:
  1848. mark_as_needed_z(RT__TrPS_VR);
  1849. mark_as_needed_z(RT__Err_VR);
  1850. return;
  1851. case RV__Pr_VR:
  1852. mark_as_needed_z(RT__Err_VR);
  1853. return;
  1854. case CA__Pr_VR:
  1855. mark_as_needed_z(Z__Region_VR);
  1856. mark_as_needed_z(Cl__Ms_VR);
  1857. mark_as_needed_z(RT__Err_VR);
  1858. return;
  1859. case IB__Pr_VR:
  1860. case IA__Pr_VR:
  1861. case DB__Pr_VR:
  1862. case DA__Pr_VR:
  1863. mark_as_needed_z(RT__Err_VR);
  1864. mark_as_needed_z(RT__TrPS_VR);
  1865. return;
  1866. case RA__Pr_VR:
  1867. mark_as_needed_z(CP__Tab_VR);
  1868. return;
  1869. case RA__Sc_VR:
  1870. mark_as_needed_z(RT__Err_VR);
  1871. return;
  1872. case OP__Pr_VR:
  1873. mark_as_needed_z(Z__Region_VR);
  1874. return;
  1875. case OC__Cl_VR:
  1876. mark_as_needed_z(Z__Region_VR);
  1877. mark_as_needed_z(RT__Err_VR);
  1878. return;
  1879. case Z__Region_VR:
  1880. mark_as_needed_z(Unsigned__Compare_VR);
  1881. return;
  1882. case Metaclass_VR:
  1883. mark_as_needed_z(Z__Region_VR);
  1884. return;
  1885. case Cl__Ms_VR:
  1886. mark_as_needed_z(RT__Err_VR);
  1887. mark_as_needed_z(Copy__Primitive_VR);
  1888. return;
  1889. case RT__ChR_VR:
  1890. case RT__ChT_VR:
  1891. case RT__ChG_VR:
  1892. case RT__ChGt_VR:
  1893. case RT__ChPR_VR:
  1894. mark_as_needed_z(RT__Err_VR);
  1895. return;
  1896. case RT__ChPS_VR:
  1897. mark_as_needed_z(RT__Err_VR);
  1898. mark_as_needed_z(RT__TrPS_VR);
  1899. return;
  1900. case RT__ChLDB_VR:
  1901. case RT__ChLDW_VR:
  1902. case RT__ChSTB_VR:
  1903. case RT__ChSTW_VR:
  1904. mark_as_needed_z(Unsigned__Compare_VR);
  1905. mark_as_needed_z(RT__Err_VR);
  1906. return;
  1907. case RT__ChPrintC_VR:
  1908. mark_as_needed_z(RT__Err_VR);
  1909. return;
  1910. case RT__ChPrintA_VR:
  1911. mark_as_needed_z(Unsigned__Compare_VR);
  1912. mark_as_needed_z(RT__Err_VR);
  1913. return;
  1914. case RT__ChPrintS_VR:
  1915. case RT__ChPrintO_VR:
  1916. mark_as_needed_z(RT__Err_VR);
  1917. mark_as_needed_z(Z__Region_VR);
  1918. return;
  1919. }
  1920. }
  1921. }
  1922. static void mark_as_needed_g(int code)
  1923. {
  1924. ASSERT_GLULX();
  1925. if (veneer_routine_needs_compilation[code] == VR_UNUSED)
  1926. { veneer_routine_needs_compilation[code] = VR_CALLED;
  1927. /* Here each routine must mark every veneer routine it explicitly
  1928. calls as needed */
  1929. switch(code)
  1930. {
  1931. case PrintShortName_VR:
  1932. mark_as_needed_g(Metaclass_VR);
  1933. return;
  1934. case Print__Pname_VR:
  1935. mark_as_needed_g(PrintShortName_VR);
  1936. return;
  1937. case WV__Pr_VR:
  1938. mark_as_needed_g(RA__Pr_VR);
  1939. mark_as_needed_g(RT__TrPS_VR);
  1940. mark_as_needed_g(RT__Err_VR);
  1941. return;
  1942. case RV__Pr_VR:
  1943. mark_as_needed_g(RA__Pr_VR);
  1944. mark_as_needed_g(RT__Err_VR);
  1945. return;
  1946. case CA__Pr_VR:
  1947. mark_as_needed_g(RA__Pr_VR);
  1948. mark_as_needed_g(RL__Pr_VR);
  1949. mark_as_needed_g(PrintShortName_VR);
  1950. mark_as_needed_g(Print__Pname_VR);
  1951. mark_as_needed_g(Z__Region_VR);
  1952. mark_as_needed_g(Cl__Ms_VR);
  1953. mark_as_needed_g(Glk__Wrap_VR);
  1954. mark_as_needed_g(RT__Err_VR);
  1955. return;
  1956. case IB__Pr_VR:
  1957. case IA__Pr_VR:
  1958. case DB__Pr_VR:
  1959. case DA__Pr_VR:
  1960. mark_as_needed_g(RT__Err_VR);
  1961. mark_as_needed_g(RT__TrPS_VR);
  1962. return;
  1963. case RA__Pr_VR:
  1964. mark_as_needed_g(OC__Cl_VR);
  1965. mark_as_needed_g(CP__Tab_VR);
  1966. return;
  1967. case RL__Pr_VR:
  1968. mark_as_needed_g(OC__Cl_VR);
  1969. mark_as_needed_g(CP__Tab_VR);
  1970. return;
  1971. case RA__Sc_VR:
  1972. mark_as_needed_g(OC__Cl_VR);
  1973. mark_as_needed_g(RT__Err_VR);
  1974. return;
  1975. case OP__Pr_VR:
  1976. mark_as_needed_g(RA__Pr_VR);
  1977. mark_as_needed_g(Z__Region_VR);
  1978. return;
  1979. case OC__Cl_VR:
  1980. mark_as_needed_g(RA__Pr_VR);
  1981. mark_as_needed_g(RL__Pr_VR);
  1982. mark_as_needed_g(Z__Region_VR);
  1983. mark_as_needed_g(RT__Err_VR);
  1984. return;
  1985. case Copy__Primitive_VR:
  1986. mark_as_needed_g(CP__Tab_VR);
  1987. return;
  1988. case Z__Region_VR:
  1989. mark_as_needed_g(Unsigned__Compare_VR);
  1990. return;
  1991. case CP__Tab_VR:
  1992. case Metaclass_VR:
  1993. mark_as_needed_g(Z__Region_VR);
  1994. return;
  1995. case Cl__Ms_VR:
  1996. mark_as_needed_g(OC__Cl_VR);
  1997. mark_as_needed_g(OP__Pr_VR);
  1998. mark_as_needed_g(RT__Err_VR);
  1999. mark_as_needed_g(Copy__Primitive_VR);
  2000. mark_as_needed_g(OB__Remove_VR);
  2001. mark_as_needed_g(OB__Move_VR);
  2002. return;
  2003. case RT__ChG_VR:
  2004. case RT__ChGt_VR:
  2005. mark_as_needed_g(RT__Err_VR);
  2006. return;
  2007. case RT__ChR_VR:
  2008. mark_as_needed_g(RT__Err_VR);
  2009. mark_as_needed_g(Z__Region_VR);
  2010. mark_as_needed_g(OB__Remove_VR);
  2011. return;
  2012. case RT__ChT_VR:
  2013. mark_as_needed_g(RT__Err_VR);
  2014. mark_as_needed_g(Z__Region_VR);
  2015. mark_as_needed_g(OB__Move_VR);
  2016. return;
  2017. case RT__ChPS_VR:
  2018. mark_as_needed_g(RT__Err_VR);
  2019. mark_as_needed_g(RT__TrPS_VR);
  2020. mark_as_needed_g(WV__Pr_VR);
  2021. return;
  2022. case RT__ChPR_VR:
  2023. mark_as_needed_g(RT__Err_VR);
  2024. mark_as_needed_g(RV__Pr_VR); return;
  2025. case RT__ChLDB_VR:
  2026. case RT__ChLDW_VR:
  2027. case RT__ChSTB_VR:
  2028. case RT__ChSTW_VR:
  2029. mark_as_needed_g(Unsigned__Compare_VR);
  2030. mark_as_needed_g(RT__Err_VR);
  2031. return;
  2032. case RT__ChPrintC_VR:
  2033. mark_as_needed_g(RT__Err_VR);
  2034. return;
  2035. case RT__ChPrintA_VR:
  2036. mark_as_needed_g(Unsigned__Compare_VR);
  2037. mark_as_needed_g(RT__Err_VR);
  2038. mark_as_needed_g(Print__Addr_VR);
  2039. return;
  2040. case RT__ChPrintS_VR:
  2041. case RT__ChPrintO_VR:
  2042. mark_as_needed_g(RT__Err_VR);
  2043. mark_as_needed_g(Z__Region_VR);
  2044. return;
  2045. case Print__Addr_VR:
  2046. mark_as_needed_g(RT__Err_VR);
  2047. return;
  2048. case Dynam__String_VR:
  2049. mark_as_needed_g(RT__Err_VR);
  2050. return;
  2051. }
  2052. }
  2053. }
  2054. extern assembly_operand veneer_routine(int code)
  2055. { assembly_operand AO;
  2056. if (!glulx_mode) {
  2057. AO.type = LONG_CONSTANT_OT;
  2058. AO.marker = VROUTINE_MV;
  2059. AO.value = code;
  2060. mark_as_needed_z(code);
  2061. }
  2062. else {
  2063. AO.type = CONSTANT_OT;
  2064. AO.marker = VROUTINE_MV;
  2065. AO.value = code;
  2066. mark_as_needed_g(code);
  2067. }
  2068. return(AO);
  2069. }
  2070. static void compile_symbol_table_routine(void)
  2071. { int32 j, nl, arrays_l, routines_l, constants_l;
  2072. assembly_operand AO, AO2, AO3;
  2073. /* Assign local var names for the benefit of the debugging information
  2074. file. */
  2075. local_variable_texts[0] = "dummy1";
  2076. local_variable_texts[1] = "dummy2";
  2077. veneer_mode = TRUE; j = symbol_index("Symb__Tab", -1);
  2078. assign_symbol(j,
  2079. assemble_routine_header(2, FALSE, "Symb__Tab", FALSE, j),
  2080. ROUTINE_T);
  2081. sflags[j] |= SYSTEM_SFLAG + USED_SFLAG;
  2082. if (trace_fns_setting==3) sflags[j] |= STAR_SFLAG;
  2083. if (!glulx_mode) {
  2084. if (define_INFIX_switch == FALSE)
  2085. { assemblez_0(rfalse_zc);
  2086. variable_usage[1] = TRUE;
  2087. variable_usage[2] = TRUE;
  2088. assemble_routine_end(FALSE, null_debug_locations);
  2089. veneer_mode = FALSE;
  2090. return;
  2091. }
  2092. AO.value = 1; AO.type = VARIABLE_OT; AO.marker = 0;
  2093. AO2.type = SHORT_CONSTANT_OT; AO2.marker = 0;
  2094. AO3.type = LONG_CONSTANT_OT; AO3.marker = 0;
  2095. arrays_l = next_label++;
  2096. routines_l = next_label++;
  2097. constants_l = next_label++;
  2098. sequence_point_follows = FALSE;
  2099. AO2.value = 1;
  2100. assemblez_2_branch(je_zc, AO, AO2, arrays_l, TRUE);
  2101. sequence_point_follows = FALSE;
  2102. AO2.value = 2;
  2103. assemblez_2_branch(je_zc, AO, AO2, routines_l, TRUE);
  2104. sequence_point_follows = FALSE;
  2105. AO2.value = 3;
  2106. assemblez_2_branch(je_zc, AO, AO2, constants_l, TRUE);
  2107. sequence_point_follows = FALSE;
  2108. assemblez_0(rtrue_zc);
  2109. assemble_label_no(arrays_l);
  2110. AO.value = 2;
  2111. for (j=0; j<no_arrays; j++)
  2112. { { AO2.value = j;
  2113. if (AO2.value<256) AO2.type = SHORT_CONSTANT_OT;
  2114. else AO2.type = LONG_CONSTANT_OT;
  2115. nl = next_label++;
  2116. sequence_point_follows = FALSE;
  2117. assemblez_2_branch(je_zc, AO, AO2, nl, FALSE);
  2118. AO3.value = array_sizes[j];
  2119. AO3.marker = 0;
  2120. assemblez_store(temp_var2, AO3);
  2121. AO3.value = array_types[j];
  2122. if (sflags[array_symbols[j]] & (INSF_SFLAG+SYSTEM_SFLAG))
  2123. AO3.value = AO3.value + 16;
  2124. AO3.marker = 0;
  2125. assemblez_store(temp_var3, AO3);
  2126. AO3.value = svals[array_symbols[j]];
  2127. AO3.marker = ARRAY_MV;
  2128. assemblez_1(ret_zc, AO3);
  2129. assemble_label_no(nl);
  2130. }
  2131. }
  2132. sequence_point_follows = FALSE;
  2133. assemblez_0(rtrue_zc);
  2134. assemble_label_no(routines_l);
  2135. for (j=0; j<no_named_routines; j++)
  2136. { AO2.value = j;
  2137. if (AO2.value<256) AO2.type = SHORT_CONSTANT_OT;
  2138. else AO2.type = LONG_CONSTANT_OT;
  2139. nl = next_label++;
  2140. sequence_point_follows = FALSE;
  2141. assemblez_2_branch(je_zc, AO, AO2, nl, FALSE);
  2142. AO3.value = 0;
  2143. if (sflags[named_routine_symbols[j]]
  2144. & (INSF_SFLAG+SYSTEM_SFLAG)) AO3.value = 16;
  2145. AO3.marker = 0;
  2146. assemblez_store(temp_var3, AO3);
  2147. AO3.value = svals[named_routine_symbols[j]];
  2148. AO3.marker = IROUTINE_MV;
  2149. assemblez_1(ret_zc, AO3);
  2150. assemble_label_no(nl);
  2151. }
  2152. sequence_point_follows = FALSE;
  2153. assemblez_0(rtrue_zc);
  2154. assemble_label_no(constants_l);
  2155. for (j=0, no_named_constants=0; j<no_symbols; j++)
  2156. { if (((stypes[j] == OBJECT_T) || (stypes[j] == CLASS_T)
  2157. || (stypes[j] == CONSTANT_T))
  2158. && ((sflags[j] & (UNKNOWN_SFLAG+ACTION_SFLAG))==0))
  2159. { AO2.value = no_named_constants++;
  2160. if (AO2.value<256) AO2.type = SHORT_CONSTANT_OT;
  2161. else AO2.type = LONG_CONSTANT_OT;
  2162. nl = next_label++;
  2163. sequence_point_follows = FALSE;
  2164. assemblez_2_branch(je_zc, AO, AO2, nl, FALSE);
  2165. AO3.value = 0;
  2166. if (stypes[j] == OBJECT_T) AO3.value = 2;
  2167. if (stypes[j] == CLASS_T) AO3.value = 1;
  2168. if (sflags[j] & (INSF_SFLAG+SYSTEM_SFLAG))
  2169. AO3.value = AO3.value + 16;
  2170. AO3.marker = 0;
  2171. assemblez_store(temp_var3, AO3);
  2172. AO3.value = j;
  2173. AO3.marker = SYMBOL_MV;
  2174. assemblez_1(ret_zc, AO3);
  2175. assemble_label_no(nl);
  2176. }
  2177. }
  2178. no_named_constants = 0; AO3.marker = 0;
  2179. sequence_point_follows = FALSE;
  2180. assemblez_0(rfalse_zc);
  2181. variable_usage[1] = TRUE;
  2182. variable_usage[2] = TRUE;
  2183. assemble_routine_end(FALSE, null_debug_locations);
  2184. veneer_mode = FALSE;
  2185. }
  2186. else {
  2187. if (define_INFIX_switch == FALSE)
  2188. { assembleg_1(return_gc, zero_operand);
  2189. variable_usage[1] = TRUE;
  2190. variable_usage[2] = TRUE;
  2191. assemble_routine_end(FALSE, null_debug_locations);
  2192. veneer_mode = FALSE;
  2193. return;
  2194. }
  2195. error("*** Infix symbol-table routine is not yet implemented. ***");
  2196. }
  2197. }
  2198. extern void compile_veneer(void)
  2199. { int i, j, try_veneer_again;
  2200. VeneerRoutine *VRs;
  2201. if (module_switch) return;
  2202. VRs = (!glulx_mode) ? VRs_z : VRs_g;
  2203. /* Called at the end of the pass to insert as much of the veneer as is
  2204. needed and not elsewhere compiled. */
  2205. veneer_symbols_base = no_symbols;
  2206. /* for (i=0; i<VENEER_ROUTINES; i++)
  2207. printf("%s %d %d %d %d %d %d\n", VRs[i].name,
  2208. strlen(VRs[i].source1), strlen(VRs[i].source2),
  2209. strlen(VRs[i].source3), strlen(VRs[i].source4),
  2210. strlen(VRs[i].source5), strlen(VRs[i].source6)); */
  2211. try_veneer_again = TRUE;
  2212. while (try_veneer_again)
  2213. { try_veneer_again = FALSE;
  2214. for (i=0; i<VENEER_ROUTINES; i++)
  2215. { if (veneer_routine_needs_compilation[i] == VR_CALLED)
  2216. { j = symbol_index(VRs[i].name, -1);
  2217. if (sflags[j] & UNKNOWN_SFLAG)
  2218. { veneer_mode = TRUE;
  2219. strcpy(veneer_source_area, VRs[i].source1);
  2220. strcat(veneer_source_area, VRs[i].source2);
  2221. strcat(veneer_source_area, VRs[i].source3);
  2222. strcat(veneer_source_area, VRs[i].source4);
  2223. strcat(veneer_source_area, VRs[i].source5);
  2224. strcat(veneer_source_area, VRs[i].source6);
  2225. assign_symbol(j,
  2226. parse_routine(veneer_source_area, FALSE,
  2227. VRs[i].name, TRUE, j),
  2228. ROUTINE_T);
  2229. veneer_mode = FALSE;
  2230. if (trace_fns_setting==3) sflags[j] |= STAR_SFLAG;
  2231. }
  2232. else
  2233. { if (stypes[j] != ROUTINE_T)
  2234. error_named("The following name is reserved by Inform for its \
  2235. own use as a routine name; you can use it as a routine name yourself (to \
  2236. override the standard definition) but cannot use it for anything else:",
  2237. VRs[i].name);
  2238. else
  2239. sflags[j] |= USED_SFLAG;
  2240. }
  2241. veneer_routine_address[i] = svals[j];
  2242. veneer_routine_needs_compilation[i] = VR_COMPILED;
  2243. try_veneer_again = TRUE;
  2244. }
  2245. }
  2246. }
  2247. compile_symbol_table_routine();
  2248. }
  2249. /* ========================================================================= */
  2250. /* Data structure management routines */
  2251. /* ------------------------------------------------------------------------- */
  2252. extern void init_veneer_vars(void)
  2253. {
  2254. }
  2255. extern void veneer_begin_pass(void)
  2256. { int i;
  2257. veneer_mode = FALSE;
  2258. for (i=0; i<VENEER_ROUTINES; i++)
  2259. { veneer_routine_needs_compilation[i] = VR_UNUSED;
  2260. veneer_routine_address[i] = 0;
  2261. }
  2262. }
  2263. extern void veneer_allocate_arrays(void)
  2264. { veneer_source_area = my_malloc(16384, "veneer source code area");
  2265. }
  2266. extern void veneer_free_arrays(void)
  2267. { my_free(&veneer_source_area, "veneer source code area");
  2268. }
  2269. /* ========================================================================= */