int main(void) { if (!xpost_init()) { fprintf(stderr, "Fail to initialize xpost dict test\n"); return -1; } init(); printf("\n^test gc.c\n"); ctx = &itpdata->ctab[0]; mem = ctx->lo; stac = ctx->os; xpost_stack_push(mem, stac, xpost_int_cons(5)); xpost_stack_push(mem, stac, xpost_int_cons(6)); xpost_stack_push(mem, stac, xpost_real_cons(7.0)); Xpost_Object ar; ar = xpost_array_cons_memory(mem, 3); int i; for (i=0; i < 3; i++) xpost_array_put_memory(mem, ar, i, xpost_stack_pop(mem, stac)); xpost_stack_push(mem, stac, ar); /* array on stack */ xpost_stack_push(mem, stac, xpost_int_cons(1)); xpost_stack_push(mem, stac, xpost_int_cons(2)); xpost_stack_push(mem, stac, xpost_int_cons(3)); ar = xpost_array_cons_memory(mem, 3); for (i=0; i < 3; i++) xpost_array_put_memory(mem, ar, i, xpost_stack_pop(mem, stac)); xpost_object_dump(ar); /* array not on stack */ #define CNT_STR(x) sizeof(x), x xpost_stack_push(mem, stac, xpost_string_cons_memory(mem, CNT_STR("string on stack"))); xpost_object_dump(xpost_string_cons_memory(mem, CNT_STR("string not on stack"))); collect(mem); xpost_stack_push(mem, stac, xpost_string_cons_memory(mem, CNT_STR("string on stack"))); xpost_object_dump(xpost_string_cons_memory(mem, CNT_STR("string not on stack"))); collect(mem); xpost_memory_file_dump(mem); printf("stackaedr: %04x\n", stac); dumpmtab(mem, 0); /* ^ent 8 (8): adr 3404 0x0d4c, sz [24], mark _ */ /* ^ 06 00 00 00 6en 67g 20 6en 6fo 74t 20 */ printf("gc: look at the mark field . . . . . . . .^\n"); printf("also, see that the first 4 bytes of strings not on stack\n" "have been obliterated to link-up the free list.\n"); xpost_quit(); }
/* - vmstatus level used max return size information for (local) vm */ static int Zvmstatus (Xpost_Context *ctx) { unsigned int vs; xpost_memory_table_get_addr(ctx->lo, XPOST_MEMORY_TABLE_SPECIAL_SAVE_STACK, &vs); xpost_stack_push(ctx->lo, ctx->os, xpost_int_cons(xpost_stack_count(ctx->lo, vs))); xpost_stack_push(ctx->lo, ctx->os, xpost_int_cons(ctx->lo->used)); xpost_stack_push(ctx->lo, ctx->os, xpost_int_cons(ctx->lo->max)); return 0; }
/* |- any1..anyN count |- any1..anyN N count elements on stack */ static int Zcount (Xpost_Context *ctx) { if (!xpost_stack_push(ctx->lo, ctx->os, xpost_int_cons(xpost_stack_count(ctx->lo, ctx->os)))) return stackoverflow; return 0; }
/* string cvi int convert initial portion of string to integer */ static int Scvi(Xpost_Context *ctx, Xpost_Object s) { double dbl; long num; char *t = alloca(s.comp_.sz+1); memcpy(t, xpost_string_get_pointer(ctx, s), s.comp_.sz); t[s.comp_.sz] = '\0'; dbl = strtod(t, NULL); if ((dbl == HUGE_VAL || dbl -HUGE_VAL) && errno==ERANGE) return limitcheck; if (dbl >= LONG_MAX || dbl <= LONG_MIN) return limitcheck; num = (long)dbl; /* num = strtol(t, NULL, 10); if ((num == LONG_MAX || num == LONG_MIN) && errno==ERANGE) return limitcheck; */ xpost_stack_push(ctx->lo, ctx->os, xpost_int_cons(num)); return 0; }
/* number cvi int convert number to integer */ static int Ncvi(Xpost_Context *ctx, Xpost_Object n) { if (xpost_object_get_type(n) == realtype) n = xpost_int_cons((integer)n.real_.val); xpost_stack_push(ctx->lo, ctx->os, n); return 0; }
/* file fileposition int return position of read/write head for file */ static int xpost_op_fileposition (Xpost_Context *ctx, Xpost_Object F) { long pos; pos = xpost_file_tell(xpost_file_get_file_pointer(ctx->lo, F)); if (pos == -1) return ioerror; else xpost_stack_push(ctx->lo, ctx->os, xpost_int_cons(pos)); return 0; }
/* file bytesavailable int return number of bytes available to read or -1 if not known */ static int xpost_op_file_bytesavailable (Xpost_Context *ctx, Xpost_Object F) { int bytes; int ret; ret = xpost_file_get_bytes_available(ctx->lo, F, &bytes); if (ret) return ret; xpost_stack_push(ctx->lo, ctx->os, xpost_int_cons(bytes)); return 0; }
/* mark obj1..objN counttomark N count elements down to mark */ int xpost_op_counttomark (Xpost_Context *ctx) { unsigned i; unsigned z; z = xpost_stack_count(ctx->lo, ctx->os); for (i = 0; i < z; i++) { if (xpost_stack_topdown_fetch(ctx->lo, ctx->os, i).tag == marktype) { xpost_stack_push(ctx->lo, ctx->os, xpost_int_cons(i)); return 0; } } return unmatchedmark; }
/* number radix string cvrs string convert number to a radix representation in string */ static int NRScvrs (Xpost_Context *ctx, Xpost_Object num, Xpost_Object rad, Xpost_Object str) { int r, n; if (xpost_object_get_type(num) == realtype) num = xpost_int_cons((integer)num.real_.val); r = rad.int_.val; if (r < 2 || r > 36) return rangecheck; n = conv_rad(num.int_.val, r, xpost_string_get_pointer(ctx, str), str.comp_.sz); if (n == -1) return rangecheck; if (n < str.comp_.sz) str.comp_.sz = n; xpost_stack_push(ctx->lo, ctx->os, str); return 0; }
/* FIXME remove duplication of effort here and in bin/xpost_main.c (ie. there should be 1 table, not 2) Generates postscript code to initialize the selected device currentglobal false setglobal % allocate in local memory device_requires_loading? { loadXXXdevice } if % load if necessary userdict /DEVICE 612 792 newXXXdevice put % instantiate the device setglobal % reset previous allocation mode initialization of the device is deferred until the start procedure has initialized graphics (importantly, the ppmimage base class). the loadXXXdevice operators all specialize the ppmimage base class and so must wait until it is available. also creates the definitions PACKAGE_DATA_DIR PACKAGE_INSTALL_DIR and EXE_DIR */ static void setlocalconfig(Xpost_Context *ctx, Xpost_Object sd, const char *device, const char *outfile, const char *bufferin, char **bufferout, Xpost_Showpage_Semantics semantics, Xpost_Set_Size set_size, int width, int height) { const char *device_strings[][3] = { { "pgm", "", "newPGMIMAGEdevice" }, { "ppm", "", "newPPMIMAGEdevice" }, { "null", "", "newnulldevice" }, { "xcb", "loadxcbdevice", "newxcbdevice" }, { "gdi", "loadwin32device", "newwin32device" }, { "gl", "loadwin32device", "newwin32device" }, { "bgr", "loadbgrdevice", "newbgrdevice" }, { "raster", "loadrasterdevice", "newrasterdevice" }, { "png", "loadpngdevice", "newpngdevice" }, { "jpeg", "loadjpegdevice", "newjpegdevice" }, { NULL, NULL, NULL } }; const char *strtemplate = "currentglobal false setglobal " "%s userdict /DEVICE %s %s put " "setglobal"; Xpost_Object namenewdev; Xpost_Object newdevstr; int i; char *devstr; char *subdevice; char *dimensions; ctx->vmmode = GLOBAL; #ifdef _WIN32 xpost_dict_put(ctx, sd, xpost_name_cons(ctx, "WIN32"), xpost_bool_cons(1)); #endif devstr = strdup(device); /* Parse device string for mode selector "dev:mode" */ if ((subdevice=strchr(devstr, ':'))) { *subdevice++ = '\0'; xpost_dict_put(ctx, sd, xpost_name_cons(ctx, "SUBDEVICE"), xpost_object_cvlit(xpost_string_cons(ctx, strlen(subdevice), subdevice))); } /* define the /newdefaultdevice name called by /start */ for (i = 0; device_strings[i][0]; i++) { if (strcmp(devstr, device_strings[i][0]) == 0) { break; } } if (set_size == XPOST_USE_SIZE){ dimensions = malloc(2 + (int)ceil(log10(width)) + (int)ceil(log10(height))); sprintf(dimensions, "%d %d", width, height); } else { static char x[] = "612 792"; dimensions = x; } newdevstr = xpost_string_cons(ctx, strlen(strtemplate) - 6 + strlen(device_strings[i][1]) + strlen(dimensions) + strlen(device_strings[i][2]) + 1, NULL); sprintf(xpost_string_get_pointer(ctx, newdevstr), strtemplate, device_strings[i][1], dimensions, device_strings[i][2]); --newdevstr.comp_.sz; /* trim the '\0' */ namenewdev = xpost_name_cons(ctx, "newdefaultdevice"); xpost_dict_put(ctx, sd, namenewdev, xpost_object_cvx(newdevstr)); xpost_dict_put(ctx, sd, xpost_name_cons(ctx, "ShowpageSemantics"), xpost_int_cons(semantics)); if (outfile) { xpost_dict_put(ctx, sd, xpost_name_cons(ctx, "OutputFileName"), xpost_object_cvlit(xpost_string_cons(ctx, strlen(outfile), outfile))); } if (bufferin) { Xpost_Object s = xpost_object_cvlit(xpost_string_cons(ctx, sizeof(bufferin), NULL)); xpost_object_set_access(ctx, s, XPOST_OBJECT_TAG_ACCESS_NONE); memcpy(xpost_string_get_pointer(ctx, s), &bufferin, sizeof(bufferin)); xpost_dict_put(ctx, sd, xpost_name_cons(ctx, "OutputBufferIn"), s); } if (bufferout) { Xpost_Object s = xpost_object_cvlit(xpost_string_cons(ctx, sizeof(bufferout), NULL)); xpost_object_set_access(ctx, s, XPOST_OBJECT_TAG_ACCESS_NONE); memcpy(xpost_string_get_pointer(ctx, s), &bufferout, sizeof(bufferout)); xpost_dict_put(ctx, sd, xpost_name_cons(ctx, "OutputBufferOut"), s); } ctx->vmmode = LOCAL; free(devstr); }
int test_garbage_collect(int (*xpost_interpreter_cid_init)(unsigned int *cid), Xpost_Context *(*xpost_interpreter_cid_get_context)(unsigned int cid), int (*xpost_interpreter_get_initializing)(void), void (*xpost_interpreter_set_initializing)(int), Xpost_Memory_File *(*xpost_interpreter_alloc_local_memory)(void), Xpost_Memory_File *(*xpost_interpreter_alloc_global_memory)(void)) { if (!init_test_garbage(xpost_interpreter_cid_init, xpost_interpreter_cid_get_context, xpost_interpreter_get_initializing, xpost_interpreter_set_initializing, xpost_interpreter_alloc_local_memory, xpost_interpreter_alloc_global_memory)) return 0; { Xpost_Object str; unsigned int pre, post, sz, ret; pre = ctx->lo->used; str = xpost_string_cons(ctx, 7, "0123456"); post = ctx->lo->used; sz = post-pre; /* printf("str sz=%u\n", sz); */ xpost_stack_push(ctx->lo, ctx->os, str); _clear_hold(ctx); ret = collect(ctx->lo, 1, 0); //assert(ret == 0); if (ret != 0) { XPOST_LOG_ERR("Warning: collect returned %d, expected %d", ret, 0); } xpost_stack_pop(ctx->lo, ctx->os); _clear_hold(ctx); ret = collect(ctx->lo, 1, 0); /* printf("collect returned %u\n", ret); */ //assert(ret >= sz); if (! (ret >= sz) ) { XPOST_LOG_ERR("Warning: collect returned %d, expected >= %d", ret, sz); } } { Xpost_Object arr; unsigned int pre, post, sz, ret; pre = ctx->lo->used; arr = xpost_array_cons(ctx, 5); xpost_array_put(ctx, arr, 0, xpost_int_cons(12)); xpost_array_put(ctx, arr, 1, xpost_int_cons(13)); xpost_array_put(ctx, arr, 2, xpost_int_cons(14)); xpost_array_put(ctx, arr, 3, xpost_string_cons(ctx, 5, "fubar")); xpost_array_put(ctx, arr, 4, xpost_string_cons(ctx, 4, "buzz")); post = ctx->lo->used; sz = post-pre; xpost_stack_push(ctx->lo, ctx->os, arr); _clear_hold(ctx); ret = collect(ctx->lo, 1, 0); //assert(ret == 0); if (ret != 0) { XPOST_LOG_ERR("Warning: collect returned %d, expected %d", ret, 0); } xpost_stack_pop(ctx->lo, ctx->os); _clear_hold(ctx); ret = collect(ctx->lo, 1, 0); //assert(ret >= sz); if (! (ret >= sz) ) { XPOST_LOG_ERR("Warning: collect returned %d, expected >= %d", ret, sz); } } exit_test_garbage(); return 1; }