X-Git-Url: https://git.stderr.nl/gitweb?a=blobdiff_plain;f=interpreters%2Fglulxe%2Fglkop.c;h=090632abdcbfabf5cb6ba83e6662b094723b34ac;hb=2ab029c7428eb3e4894e7d165815c90fbc39a8b2;hp=e9c519128b29d15d6ca3699433d4b814b4519c4b;hpb=5f927b0d7c728e389f3295ac39acb85ecb3a6ef0;p=projects%2Fchimara%2Fchimara.git diff --git a/interpreters/glulxe/glkop.c b/interpreters/glulxe/glkop.c index e9c5191..090632a 100644 --- a/interpreters/glulxe/glkop.c +++ b/interpreters/glulxe/glkop.c @@ -120,6 +120,8 @@ typedef struct classtable_struct { static int num_classes = 0; classtable_t **classes = NULL; +static glui32 find_id_for_stream(strid_t str); + static classtable_t *new_classtable(glui32 firstid); static void *classes_get(int classid, glui32 objid); static classref_t *classes_put(int classid, void *obj); @@ -185,6 +187,16 @@ glui32 perform_glk(glui32 funcnum, glui32 numargs, glui32 *arglist) directly -- instead of bothering with the whole prototype mess. */ + case 0x0047: /* stream_set_current */ + if (numargs != 1) + goto WrongArgNum; + glk_stream_set_current(find_stream_by_id(arglist[0])); + break; + case 0x0048: /* stream_get_current */ + if (numargs != 0) + goto WrongArgNum; + retval = find_id_for_stream(glk_stream_get_current()); + break; case 0x0080: /* put_char */ if (numargs != 1) goto WrongArgNum; @@ -205,6 +217,16 @@ glui32 perform_glk(glui32 funcnum, glui32 numargs, glui32 *arglist) goto WrongArgNum; retval = glk_char_to_upper(arglist[0] & 0xFF); break; + case 0x0128: /* put_char_uni */ + if (numargs != 1) + goto WrongArgNum; + glk_put_char_uni(arglist[0]); + break; + case 0x012B: /* put_char_stream_uni */ + if (numargs != 2) + goto WrongArgNum; + glk_put_char_stream_uni(find_stream_by_id(arglist[0]), arglist[1]); + break; WrongArgNum: fatal_error("Wrong number of arguments to Glk function."); @@ -214,7 +236,7 @@ glui32 perform_glk(glui32 funcnum, glui32 numargs, glui32 *arglist) /* Go through the full dispatcher prototype foo. */ char *proto, *cx; dispatch_splot_t splot; - int argnum; + int argnum, argnum2; /* Grab the string. */ proto = gidispatch_prototype(funcnum); @@ -243,9 +265,11 @@ glui32 perform_glk(glui32 funcnum, glui32 numargs, glui32 *arglist) gidispatch_call(funcnum, argnum, splot.garglist); /* Phase 3. */ - argnum = 0; + argnum2 = 0; cx = proto; - unparse_glk_args(&splot, &cx, 0, &argnum, 0, 0); + unparse_glk_args(&splot, &cx, 0, &argnum2, 0, 0); + if (argnum != argnum2) + fatal_error("Argument counts did not match."); break; } @@ -468,6 +492,17 @@ static void parse_glk_args(dispatch_splot_t *splot, char **proto, int depth, switch (typeclass) { case 'C': + /* This test checks for a giant array length, which is + deprecated. It displays a warning and cuts it down to + something reasonable. Future releases of this interpreter + may remove this test and go on to verify_array_addresses(), + which treats this case as a fatal error. */ + if (varglist[ix+1] > endmem + || varglist[ix]+varglist[ix+1] > endmem) { + nonfatal_warning_i("Memory access was much too long -- perhaps a print_to_array call with only one argument", varglist[ix+1]); + varglist[ix+1] = endmem - varglist[ix]; + } + verify_array_addresses(varglist[ix], varglist[ix+1], 1); garglist[gargnum].array = AddressOfArray(varglist[ix]); gargnum++; ix++; @@ -476,6 +511,13 @@ static void parse_glk_args(dispatch_splot_t *splot, char **proto, int depth, cx++; break; case 'I': + /* See comment above. */ + if (varglist[ix+1] > endmem/4 + || varglist[ix+1] > (endmem-varglist[ix])/4) { + nonfatal_warning_i("Memory access was much too long -- perhaps a print_to_array call with only one argument", varglist[ix+1]); + varglist[ix+1] = (endmem - varglist[ix]) / 4; + } + verify_array_addresses(varglist[ix], varglist[ix+1], 4); garglist[gargnum].array = CaptureIArray(varglist[ix], varglist[ix+1], passin); gargnum++; ix++; @@ -587,6 +629,8 @@ static void parse_glk_args(dispatch_splot_t *splot, char **proto, int depth, } else { cx++; + if (isarray) + ix++; } } } @@ -789,6 +833,8 @@ static void unparse_glk_args(dispatch_splot_t *splot, char **proto, int depth, } else { cx++; + if (isarray) + ix++; } } } @@ -820,6 +866,21 @@ strid_t find_stream_by_id(glui32 objid) return classes_get(1, objid); } +/* find_id_for_stream(): + The converse of find_stream_by_id(). + This is only needed in this file, so it's static. +*/ +static glui32 find_id_for_stream(strid_t str) +{ + gidispatch_rock_t objrock; + + if (!str) + return 0; + + objrock = gidispatch_get_objrock(str, 1); + return ((classref_t *)objrock.ptr)->id; +} + /* Build a hash table to hold a set of Glk objects. */ static classtable_t *new_classtable(glui32 firstid) {