Пример #1
0
void Glulxe::classes_remove(int classid, void *obj) {
	classtable_t *ctab;
	classref_t *cref;
	classref_t **crefp;
	gidispatch_rock_t objrock;
	if (classid < 0 || classid >= num_classes)
		return;
	ctab = classes[classid];
	objrock = gidispatch_get_objrock(obj, classid);
	cref = (classref_t *)objrock.ptr;
	if (!cref)
		return;
	crefp = &(ctab->bucket[cref->bucknum]);
	for (; *crefp; crefp = &((*crefp)->next)) {
		if ((*crefp) == cref) {
			*crefp = cref->next;
			if (!cref->obj) {
				nonfatal_warning("attempt to free nullptr object!");
			}
			cref->obj = nullptr;
			cref->id = 0;
			cref->next = nullptr;
			glulx_free(cref);
			return;
		}
	}
	return;
}
Пример #2
0
/* Delete a Glk object from the appropriate hash table. */
static void classes_remove(int classid, void *obj)
{
  classtable_t *ctab;
  classref_t *cref;
  classref_t **crefp;
  gidispatch_rock_t objrock;
  if (classid < 0 || classid >= num_classes)
    return;
  ctab = git_classes[classid];
  objrock = gidispatch_get_objrock(obj, classid);
  cref = objrock.ptr;
  if (!cref)
    return;
  crefp = &(ctab->bucket[cref->bucknum]);
  for (; *crefp; crefp = &((*crefp)->next)) {
    if ((*crefp) == cref) {
      *crefp = cref->next;
      cref->obj = NULL;
      cref->id = 0;
      cref->next = NULL;
      glulx_free(cref);
      return;
    }
  }
  return;
}
Пример #3
0
/* git_find_id_for_schannel():
   Return the ID of a given Glk schannel.
*/
glui32 git_find_id_for_schannel(schanid_t schan)
{
  gidispatch_rock_t objrock;

  if (!schan)
    return 0;

  objrock = gidispatch_get_objrock(schan, gidisp_Class_Schannel);
  return ((classref_t *)objrock.ptr)->id;
}
Пример #4
0
/* git_find_id_for_fileref():
   Return the ID of a given Glk fileref.
*/
glui32 git_find_id_for_fileref(frefid_t fref)
{
  gidispatch_rock_t objrock;

  if (!fref)
    return 0;

  objrock = gidispatch_get_objrock(fref, gidisp_Class_Fileref);
  return ((classref_t *)objrock.ptr)->id;
}
Пример #5
0
/* git_find_id_for_stream():
   Return the ID of a given Glk stream.
*/
glui32 git_find_id_for_stream(strid_t str)
{
  gidispatch_rock_t objrock;

  if (!str)
    return 0;

  objrock = gidispatch_get_objrock(str, gidisp_Class_Stream);
  return ((classref_t *)objrock.ptr)->id;
}
Пример #6
0
/* git_find_id_for_window():
   Return the ID of a given Glk window.
*/
glui32 git_find_id_for_window(winid_t win)
{
  gidispatch_rock_t objrock;

  if (!win)
    return 0;

  objrock = gidispatch_get_objrock(win, gidisp_Class_Window);
  return ((classref_t *)objrock.ptr)->id;
}
Пример #7
0
static void release_temp_ptr_array(void **arr, glui32 addr, glui32 len, int objclass, int passout)
{
  arrayref_t *arref = NULL;
  arrayref_t **aptr;
  glui32 ix, val, addr2;

  if (arr) {
    for (aptr=(&arrays); (*aptr); aptr=(&((*aptr)->next))) {
      if ((*aptr)->array == arr)
        break;
    }
    arref = *aptr;
    if (!arref)
      fatalError("Unable to re-find array argument in Glk call.");
    if (arref->addr != addr || arref->len != len)
      fatalError("Mismatched array argument in Glk call.");

    if (arref->retained) {
      return;
    }

    *aptr = arref->next;
    arref->next = NULL;

    if (passout) {
      for (ix=0, addr2=addr; ix<len; ix++, addr2+=4) {
        void *opref = arr[ix];
        if (opref) {
          gidispatch_rock_t objrock = 
            gidispatch_get_objrock(opref, objclass);
          val = ((classref_t *)objrock.ptr)->id;
        }
        else {
          val = 0;
        }
        memWrite32(addr2, val);
      }
    }
    glulx_free(arr);
    glulx_free(arref);
  }
}
Пример #8
0
void Glulxe::unparse_glk_args(dispatch_splot_t *splot, const char **proto, int depth,
                              int *argnumptr, uint subaddress, int subpassout) {
	const char *cx;
	int ix, argx;
	int gargnum, numwanted;
	void *opref;
	gluniversal_t *garglist;
	uint *varglist;

	garglist = splot->garglist;
	varglist = splot->varglist;
	gargnum = *argnumptr;
	cx = *proto;

	numwanted = 0;
	while (*cx >= '0' && *cx <= '9') {
		numwanted = 10 * numwanted + (*cx - '0');
		cx++;
	}

	for (argx = 0, ix = 0; argx < numwanted; argx++, ix++) {
		char typeclass;
		int skipval;
		int isref, passin, passout, nullok, isarray, isretained, isreturn;
		cx = read_prefix(cx, &isref, &isarray, &passin, &passout, &nullok,
		                 &isretained, &isreturn);

		typeclass = *cx;
		cx++;

		skipval = false;
		if (isref) {
			if (!isreturn && varglist[ix] == 0) {
				if (!nullok)
					error("Zero passed invalidly to Glk function.");
				garglist[gargnum]._ptrflag = false;
				gargnum++;
				skipval = true;
			} else {
				garglist[gargnum]._ptrflag = true;
				gargnum++;
			}
		}
		if (!skipval) {
			uint thisval = 0;

			if (typeclass == '[') {

				unparse_glk_args(splot, &cx, depth + 1, &gargnum, varglist[ix], passout);

			} else if (isarray) {
				/* definitely isref */

				switch (typeclass) {
				case 'C':
					ReleaseCArray((char *)garglist[gargnum]._array, varglist[ix], varglist[ix + 1], passout);
					gargnum++;
					ix++;
					gargnum++;
					cx++;
					break;
				case 'I':
					ReleaseIArray((uint *)garglist[gargnum]._array, varglist[ix], varglist[ix + 1], passout);
					gargnum++;
					ix++;
					gargnum++;
					cx++;
					break;
				case 'Q':
					ReleasePtrArray((void **)garglist[gargnum]._array, varglist[ix], varglist[ix + 1], (*cx - 'a'), passout);
					gargnum++;
					ix++;
					gargnum++;
					cx++;
					break;
				default:
					error("Illegal format string.");
					break;
				}
			} else {
				/* a plain value or a reference to one. */

				if (isreturn || (depth > 0 && subpassout) || (isref && passout)) {
					skipval = false;
				} else {
					skipval = true;
				}

				switch (typeclass) {
				case 'I':
					if (!skipval) {
						if (*cx == 'u')
							thisval = (uint)garglist[gargnum]._uint;
						else if (*cx == 's')
							thisval = (uint)garglist[gargnum]._sint;
						else
							error("Illegal format string.");
					}
					gargnum++;
					cx++;
					break;
				case 'Q':
					if (!skipval) {
						opref = garglist[gargnum]._opaqueref;
						if (opref) {
							gidispatch_rock_t objrock = gidispatch_get_objrock(opref, *cx - 'a');
							assert(objrock.ptr);
							thisval = ((classref_t *)objrock.ptr)->id;
						} else {
							thisval = 0;
						}
					}
					gargnum++;
					cx++;
					break;
				case 'C':
					if (!skipval) {
						if (*cx == 'u')
							thisval = (uint)garglist[gargnum]._uch;
						else if (*cx == 's')
							thisval = (uint)garglist[gargnum]._sch;
						else if (*cx == 'n')
							thisval = (uint)garglist[gargnum]._ch;
						else
							error("Illegal format string.");
					}
					gargnum++;
					cx++;
					break;
				case 'S':
					if (garglist[gargnum]._charstr)
						ReleaseVMString(garglist[gargnum]._charstr);
					gargnum++;
					break;
#ifdef GLK_MODULE_UNICODE
				case 'U':
					if (garglist[gargnum]._unicharstr)
						ReleaseVMUstring(garglist[gargnum]._unicharstr);
					gargnum++;
					break;
#endif /* GLK_MODULE_UNICODE */
				default:
					error("Illegal format string.");
					break;
				}

				if (isreturn) {
					*(splot->retval) = thisval;
				} else if (depth > 0) {
					/* Definitely not isref or isarray. */
					if (subpassout)
						WriteStructField(subaddress, ix, thisval);
				} else if (isref) {
					if (passout)
						WriteMemory(varglist[ix], thisval);
				}
			}
		} else {
			/* We got a null reference, so we have to skip the format element. */
			if (typeclass == '[') {
				int numsubwanted, refdepth;
				numsubwanted = 0;
				while (*cx >= '0' && *cx <= '9') {
					numsubwanted = 10 * numsubwanted + (*cx - '0');
					cx++;
				}
				refdepth = 1;
				while (refdepth > 0) {
					if (*cx == '[')
						refdepth++;
					else if (*cx == ']')
						refdepth--;
					cx++;
				}
			} else if (typeclass == 'S' || typeclass == 'U') {
				/* leave it */
			} else {
				cx++;
				if (isarray)
					ix++;
			}
		}
	}

	if (depth > 0) {
		if (*cx != ']')
			error("Illegal format string.");
		cx++;
	} else {
		if (*cx != ':' && *cx != '\0')
			error("Illegal format string.");
	}

	*proto = cx;
	*argnumptr = gargnum;
}