Ejemplo n.º 1
0
void do_write_block(caValue* blockName, caValue* contents, caValue* reply)
{
    Term* term = find_global(as_cstring(blockName));

    // Create the block if needed
    if (term == NULL)
        term = apply(global_root_block(), FUNCS.section_block, TermList(), blockName);

    // Import the new block contents
    Block* block = nested_contents(term);
    rewrite_block(block, contents, reply);
}
Ejemplo n.º 2
0
/**
 * add new symbol to global table
 * @param sname
 * @param identity
 * @param type
 * @param offset size in bytes
 * @param storage
 * @return new index
 */
int add_global (char *sname, int identity, int type, int offset, int storage) {
    SYMBOL *symbol;
    char *buffer_ptr;
    if ((current_symbol_table_idx = find_global(sname)) > -1) {
        return (current_symbol_table_idx);
    }
    if (global_table_index >= NUMBER_OF_GLOBALS) {
        error ("global symbol table overflow");
        return (0);
    }
    current_symbol_table_idx = global_table_index;
    symbol = &symbol_table[current_symbol_table_idx];
    buffer_ptr = symbol->name;
    /* FIXME: only copy so many bytes */
    while (alphanumeric(*buffer_ptr++ = *sname++));
    symbol->identity = identity;
    symbol->type = type;
    symbol->storage = storage;
    symbol->offset = offset;
    global_table_index++;
    return (current_symbol_table_idx);
}
Ejemplo n.º 3
0
void newfunc_typed(int storage, char *n, int type)
{
    int idx;
    SYMBOL *symbol;
    char an[NAMESIZE];

    fexitlab = getlabel();

    if ((idx = find_global(n)) > -1) {
        symbol = &symbol_table[idx];
        if (symbol->identity != FUNCTION)
            multidef(n);
    } else {
        /* extern implies global scope */
        idx = add_global(n, FUNCTION, CINT, 0, storage == EXTERN ? PUBLIC : storage);
        symbol = &symbol_table[idx];
    }
    local_table_index = NUMBER_OF_GLOBALS; //locptr = STARTLOC;
    argstk = 0;
    // ANSI style argument declaration
    if (doAnsiArguments()) {
        if (storage == EXTERN) {
            need_semicolon();
            return;
        }
        /* No body .. just a definition */
        if (match(";"))
            return;
    } else {
        // K&R style argument declaration
        while (!match(")")) {
            if (symname(an)) {
                if (find_locale(an) > -1)
                    multidef(an);
                else {
                    /* FIXME: struct */
                    add_local(an, 0, 0, argstk, AUTO);
                    argstk = argstk + INTSIZE;
                }
            } else {
                error("illegal argument name");
                junk();
            }
            blanks();
            if (!streq(line + lptr, ")")) {
                if (!match(","))
                    error("expected comma");
            }
            if (endst())
                break;
        }
        if (storage == EXTERN) {
            need_semicolon();
            return;
        }
        /* No body .. just a definition */
        if (match(";"))
            return;
        stkp = 0;
        argtop = argstk;
        while (argstk) {
            if ((type = get_type()) != -1) {
                notvoid(type);
                getarg(type);
                need_semicolon();
            } else {
                error("wrong number args");
                break;
            }
        }
    }
    if (symbol->offset == FUNCTION)
            multidef(n);
    symbol->offset = FUNCTION;
    output_string(n);
    output_label_terminator();
    newline();
    gen_prologue();
    statement(YES);
    print_label(fexitlab);
    output_label_terminator();
    newline();
    gen_epilogue();
    gen_modify_stack(0);
    gen_ret();
    stkp = 0;
    local_table_index = NUMBER_OF_GLOBALS; //locptr = STARTLOC;
}
Ejemplo n.º 4
0
/**
 * declare a static variable
 * @param type
 * @param storage
 * @param mtag tag of struct whose members are being declared, or zero
 * @param otag tag of struct object being declared. only matters if mtag is non-zero
 * @param is_struct struct or union or no meaning
 * @return 1 if a function was parsed
 */
int declare_global(int type, int storage, TAG_SYMBOL *mtag, int otag, int is_struct) {
    int     dim, identity;
    char    sname[NAMESIZE];

    FOREVER {
        FOREVER {
            if (endst ())
                return 0;
            dim = 1;
            if (match ("*")) {
                identity = POINTER;
            } else {
                identity = VARIABLE;
            }
            if (!symname (sname))
                illname ();
            if (match ("(")) {
                /* FIXME: We need to deal with pointer types properly here */
                if (identity == POINTER)
                    type = CINT;
                newfunc_typed(storage, sname, type);
                /* Can't int foo(x){blah),a=4; */
                return 1;
            }
            /* FIXME: we need to deal with extern properly here */
            if (find_global (sname) > -1)
                multidef (sname);
            if (identity == VARIABLE)
                notvoid(type);
            if (match ("[")) {
                dim = needsub ();
                //if (dim || storage == EXTERN) {
                    identity = ARRAY;
                //} else {
                //    identity = POINTER;
                //}
            }
            // add symbol
            if (mtag == 0) { // real variable, not a struct/union member
                identity = initials(sname, type, identity, dim, otag);
                add_global (sname, identity, type, (dim == 0 ? -1 : dim), storage);
                if (type == STRUCT) {
                    symbol_table[current_symbol_table_idx].tagidx = otag;
                }
                break;
            } else if (is_struct) {
                // structure member, mtag->size is offset
                add_member(sname, identity, type, mtag->size, storage);
                // store (correctly scaled) size of member in tag table entry
                if (identity == POINTER)
                    type = CINT;
                scale_const(type, otag, &dim);
                mtag->size += dim;
            }
            else {
                // union member, offset is always zero
                add_member(sname, identity, type, 0, storage);
                // store maximum member size in tag table entry
                if (identity == POINTER)
                    type = CINT;
                scale_const(type, otag, &dim);
                if (mtag->size < dim)
                    mtag->size = dim;
            }
        }
        if (!match (","))
            return 0;
    }
}
Ejemplo n.º 5
0
static PyObject *
marshal_Load_internal(PyObject *py_stream, PyObject *py_callback, int skipcrc)
{
	// Return value: New Reference

	char *stream;
	Py_ssize_t size;

	char *s;
	char *end;

	int type = -1;   // current object type
	int shared = -1; // indicates whether current object is shared
	int i;

	char *error = "NO ERROR SPECIFIED";
	char errortext[256];

	Py_ssize_t length = 0;  // generic length value.

	int shared_mapsize;
	int shared_count;  // shared object index counter
	int *shared_map;  // points to shared object mapping at end of stream
	PyObject **shared_obj = NULL;  // holds the shared objects

	PyObject *obj = NULL;  // currently decoded object
	PyObject *result = NULL;  // final result

	int ct_ix = 0;
	struct Container ct_stack[MAX_DEPTH];
	struct Container *container = &ct_stack[0];

	if(PyString_AsStringAndSize(py_stream, &stream, &size) == -1)
		return NULL;

	s = stream;

	container->obj = NULL;
	container->type = 0;
	container->free = -1;
	container->index = 0;

	if(size < 6 || *s++ != PROTOCOL_ID)
	{
		int offset = 0;
		result = unpickle(py_stream, &offset);
		if(!result)
			goto cleanup;

		return result;
	}

	// how many shared objects in this stream?
	shared_mapsize = *(int32_t *)s;
	s += 4;

	// Security Check: assert there is enough data for that many items.
	if((5 + shared_mapsize*4) > size) 
	{
		PyErr_Format(UnmarshalError, "Not enough room in stream for map. Wanted %d, but have only %d bytes remaining...", (shared_mapsize*4), ((int)size-5));
		goto cleanup;
	}

	// ok, we got the map data right here...
	shared_map = (int32_t *)&stream[size - shared_mapsize * 4];

	// Security Check #2: assert all map entries are between 1 and shared_mapsize
	for(i=0; i<shared_mapsize; i++)
	{
		if( (shared_map[i] > shared_mapsize) || (shared_map[i] < 1) )
		{
			PyErr_SetString(UnmarshalError, "Bogus map data in marshal stream");
			goto cleanup;
		}
	}

	// the start of which is incidentally also the end of the object data.
	end = (char *)shared_map;

	// create object table
	shared_obj = PyMem_MALLOC(shared_mapsize * sizeof(PyObject *));
	if(!shared_obj)
		goto cleanup;

	// zero out object table
	for(shared_count = 0; shared_count < shared_mapsize; shared_count++)
		shared_obj[shared_count] = NULL;
	shared_count = 0;


	// start decoding.

	while(s < end)
	{
		// This outer loop is responsible for reading and decoding the next
		// object from the stream. The object is then handed to the inner loop,
		// which adds it to the current container, or returns it to the caller.

		// get type of next object to decode and check shared flag
		type = *s++;
		shared = type & SHARED_FLAG;
		type &= ~SHARED_FLAG;

		// if token uses a normal length value, read it now.
		if(needlength[type])
		{
			READ_LENGTH;
		}
		else
			length = 0;


#if MARSHAL_DEBUG
//		if(shared)
		{
			char text[220];

			DEBUG_INDENT;
			sprintf(text, "pos:%4d type:%s(0x%02x) shared:%d len:%4d map:[", s-stream, tokenname[type], type, shared?1:0, length);
			printf(text);
			for(i=0; i<shared_mapsize; i++)
				printf("%d(%d),", shared_obj[i], shared_obj[i] ? ((PyObject *)(shared_obj[i]))->ob_refcnt : 0);
			printf("]\r\n");
		}
#endif // MARSHAL_DEBUG

		switch(type) {
		//
		// break statement:
		//   attempts to add the newly decoded object (in the obj variable) to
		//   the currently building container object.
		//
		// continue statement:
		//   indicates the decoded object or type marker was handled/consumed
		//   by the case and should _not_ be added to the currently building
		//   container object or used in any other way; immediately decode a
		//   new object
		//

		//---------------------------------------------------------------------
		// SCALAR TYPES
		//---------------------------------------------------------------------

		case TYPE_INT8:
			CHECK_SIZE(1);
			obj = PyInt_FromLong(*(int8_t *)s);
			s++;
			break;

		case TYPE_INT16:
			CHECK_SIZE(2);
			obj = PyInt_FromLong(*(int16_t *)s);
			s += 2;
			break;

		case TYPE_INT32:
			CHECK_SIZE(4);
			obj = PyInt_FromLong(*(int32_t *)s);
			s += 4;
			break;

		case TYPE_INT64:
			CHECK_SIZE(8);
			obj = PyLong_FromLongLong(*(int64_t *)s);
			s += 8;
			break;

		case TYPE_LONG:
			CHECK_SIZE(length);
			if(!length)
				obj = PyLong_FromLong(0);
			else
			{
				obj = _PyLong_FromByteArray((unsigned char *)s, length, 1, 1);
				Py_INCREF(obj);
			}

			CHECK_SHARED(obj);
			s += length;
			break;

		case TYPE_FLOAT:
			CHECK_SIZE(8);
			obj = PyFloat_FromDouble(*(double *)s);
			s += 8;
			break;


		case TYPE_CHECKSUM:
			CHECK_SIZE(4);
			if(!skipcrc && (*(uint32_t *)s != (uint32_t)adler32(1, s, (unsigned long)(end-s))))
			{
				error = "checksum error";
				goto fail;
			}
			s += 4;
			// because this type does not yield an object, go grab another
			// object right away!
			continue;


		//---------------------------------------------------------------------
		// STRING TYPES
		//---------------------------------------------------------------------

		case TYPE_STRINGR:
			if (length < 1 || length >= PyList_GET_SIZE(string_table))
			{
				if(PyList_GET_SIZE(string_table))
					PyErr_Format(UnmarshalError, "Invalid string table index %d", (int)length);
				else
					PyErr_SetString(PyExc_RuntimeError, "_stringtable not initialized");
				goto cleanup;
			}
			obj = PyList_GET_ITEM(string_table, length);
			Py_INCREF(obj);
			break;

		case TYPE_STRING:
			// appears to be deprecated since machoVersion 213
			CHECK_SIZE(1);
			length = *(unsigned char *)s++;
			CHECK_SIZE(length);
			obj = PyString_FromStringAndSize(s, length);
			s += length;
			break;

		case TYPE_STRING1:
			CHECK_SIZE(1);
			obj = PyString_FromStringAndSize(s, 1);
			s++;
			break;

		case TYPE_STREAM:
			// fallthrough, can be treated as string.
		case TYPE_STRINGL:
			// fallthrough, deprecated since machoVersion 213
		case TYPE_BUFFER:
			// Type identifier re-used by CCP. treat as string.
			CHECK_SIZE(length);
			obj = PyString_FromStringAndSize(s, length);
			s += length;
			CHECK_SHARED(obj);
			break;

		case TYPE_UNICODE1:
			CHECK_SIZE(2);
#ifdef Py_UNICODE_WIDE
			obj = _PyUnicodeUCS4_FromUCS2((void *)s, 1);
#else
			obj = PyUnicode_FromWideChar((wchar_t *)s, 1);
#endif
			s += 2;
			break;

		case TYPE_UNICODE:
			CHECK_SIZE(length*2);
#ifdef Py_UNICODE_WIDE
			obj = _PyUnicodeUCS4_FromUCS2((void *)s, (int)length);
#else
			obj = PyUnicode_FromWideChar((wchar_t *)s, length);
#endif
			s += length*2;
			break;

		case TYPE_UTF8:
			CHECK_SIZE(length);
			obj = PyUnicode_DecodeUTF8(s, length, NULL);
			s += length;
			break;

		//---------------------------------------------------------------------
		// SEQUENCE/MAPPING TYPES
		//---------------------------------------------------------------------

		case TYPE_TUPLE1:
			NEW_SEQUENCE(TYPE_TUPLE, 1);
			continue;

		case TYPE_TUPLE2:
			NEW_SEQUENCE(TYPE_TUPLE, 2);
			continue;

		case TYPE_TUPLE:
			NEW_SEQUENCE(TYPE_TUPLE, (int)length);
			continue;

		case TYPE_LIST0:
			obj = PyList_New(0);
			CHECK_SHARED(obj);
			break;

		case TYPE_LIST1:
			NEW_SEQUENCE(TYPE_LIST, 1);
			continue;

		case TYPE_LIST:
			NEW_SEQUENCE(TYPE_LIST, (int)length);
			continue;

		case TYPE_DICT:
			if(length)
			{
				CHECK_SIZE(length*2);
				PUSH_CONTAINER(TYPE_DICT, (int)length*2);
				container->obj = PyDict_New();
				container->obj2 = NULL;
				container->index = 0;
				CHECK_SHARED(container->obj);
				continue;
			}
			else
			{
				obj = PyDict_New();
				CHECK_SHARED(obj);
				break;
			}


		//---------------------------------------------------------------------
		// OBJECT TYPES
		//---------------------------------------------------------------------

		case TYPE_REF:
			// length value is index in sharedobj array!
			if((length < 1 || length > shared_mapsize))
			{
				error = "Shared reference index out of range";
				goto fail;
			}

			if(!(obj = shared_obj[length-1]))
			{
				error = "Shared reference points to invalid object";
				goto fail;
			}

			Py_INCREF(obj);
			//printf("Getting object %d from %d (refs:%d)\r\n", (int)obj, length-1, obj->ob_refcnt);
			break;

		case TYPE_GLOBAL:
		{
			PyObject *name;
			CHECK_SIZE(length);
 			name = PyString_FromStringAndSize(s, length);
			if(!name)
				goto cleanup;
			s += length;
			if(!(obj = find_global(name)))
			{
				// exception should be set by find_global
				goto cleanup;
			}

			Py_DECREF(name);

			CHECK_SHARED(obj);
			break;
		}

		case TYPE_DBROW:
		case TYPE_INSTANCE:
		case TYPE_NEWOBJ:
		case TYPE_REDUCE:
			PUSH_CONTAINER(type, -1);
			container->obj = NULL;
			RESERVE_SLOT(container->index);
			continue;

		case TYPE_MARK:
			// this is a marker, not a real object. list/dict iterators check
			// for this type, but it can't be instantiated.
			break;

		default:
			if((obj = constants[type]))
			{
				Py_INCREF(obj);
			}
			else
			{
				error = "Unsupported type";
				goto fail;
			}
		}


		// object decoding and construction done!

		if(!obj && type != TYPE_MARK)
		{
			// if obj is somehow NULL, whatever caused it is expected to have
			// set an exception at this point.
			goto cleanup;
		}

#if MARSHAL_DEBUG
/*
if(obj && obj->ob_refcnt < 0)
{
	char b[200];
	sprintf(b, "type: %d, refcount: %d", type, obj->ob_refcnt);
	DEBUG(b);
}
*/
if(obj) {
	DEBUG_INDENT;
	printf("`-- ");
	PyObject_Print(obj, stdout, 0);
	printf("\r\n");
	fflush(stdout);
}
else
{
	DEBUG_INDENT;
	printf("*** MARK\r\n");
}
#endif // MARSHAL_DEBUG

		while(1)
		{
			// This inner loop does one of two things:
			//
			// - return the finished object to the caller if we're at the root
			//   container.
			//
			// - add the object to the current container in a container-
			//   specific manner. note that ownership of the reference is to be
			//   given to the container object.

#if MARSHAL_DEBUG
		{ 
			//char text[220];
			DEBUG_INDENT;
			printf("container ix:%d (%08lx) type:%s[0x%02x] free:%d index:%d\r\n", ct_ix, container->obj, tokenname[container->type], container->type, container->free, container->index);
		}
#endif // MARSHAL_DEBUG

/*			if(!container->obj) {
				error = "Root container popped off stack";
				goto fail;
			}
*/
			switch(container->type) {
				case TYPE_TUPLE:
					// tuples steal references.
					PyTuple_SET_ITEM(container->obj, container->index++, obj);
					break;

				case TYPE_LIST:
					// lists steal references.
					PyList_SET_ITEM(container->obj, container->index++, obj);
					break;


				case TYPE_DBROW:
					if(container->obj)
					{
						// we have an initialized DBRow. current object is a
						// non-scalar object for the row. append it.
						if(!dbrow_append_internal((PyDBRowObject *)container->obj, obj))
						{
							// append call will have set an exception here.
							goto cleanup;
						}
					}
					else
					{
						// we now have a DBRowDescriptor, and the header data
						// should follow. Pull it and create the DBRow.
						READ_LENGTH;
						CHECK_SIZE(length);
						container->obj = PyDBRow_New((PyDBRowDescriptorObject *)obj, s, (int)length);
						container->free = 1+((PyDBRowDescriptorObject *)obj)->rd_num_objects;

						if(!container->obj)
							goto cleanup;
						Py_DECREF(obj);
						s += length;

						// add as shared object, if neccessary...
						UPDATE_SLOT(container->index, container->obj);

					}
					break;


				case TYPE_INSTANCE:
				{
					PyObject *cls;

					if(container->free == -1)
					{
						// create class instance
						if(!(cls = find_global(obj)))
							goto cleanup;
						container->obj = PyInstance_NewRaw(cls, 0);
						Py_DECREF(cls);
						if(!container->obj)
							goto cleanup;
						UPDATE_SLOT(container->index, container->obj);
						Py_DECREF(obj);
						break;
					}

					if(container->free == -2)
					{
						container->free = 1;
						// set state.
						if(!set_state(container->obj, obj))
							goto cleanup;

						Py_DECREF(obj);
						break;
					}

					error = "invalid container state";
					goto fail;
				}


				case TYPE_NEWOBJ:
				{
					PyObject *cls, *args, *__new__, *state;

					// instantiate the object...
					if(!(args = PyTuple_GetItem(obj, 0)))
						goto cleanup;
					if(!(cls = PyTuple_GetItem(args, 0)))
						goto cleanup;

					__new__ = PyObject_GetAttr(cls, py__new__);
					if(!__new__)
						goto cleanup;

					container->obj = PyObject_CallObject(__new__, args);
					Py_DECREF(__new__);
					if(!container->obj)
						goto cleanup;

					// add as shared object, if neccessary...
					UPDATE_SLOT(container->index, container->obj);

					// is there state data?
					if(PyTuple_GET_SIZE(obj) > 1)
					{
						state = PyTuple_GET_ITEM(obj, 1);
						if(!set_state(container->obj, state))
							goto cleanup;
					}

					Py_DECREF(obj);

					// switch to list iterator
					LIST_ITERATOR;
					break;
				}


				case TYPE_REDUCE:
				{
					PyObject *callable, *args, *state;

					if(!(args = PyTuple_GetItem(obj, 1)))
						goto cleanup;
					if(!(callable = PyTuple_GET_ITEM(obj, 0)))
						goto cleanup;

					if(!(container->obj = PyObject_CallObject(callable, args)))
						goto cleanup;

					UPDATE_SLOT(container->index, container->obj);

					if(PyTuple_GET_SIZE(obj) > 2)
					{
						state = PyTuple_GET_ITEM(obj, 2);
						if(!set_state(container->obj, state))
							goto cleanup;
					}

					Py_DECREF(obj);

					// switch to list iterator
					LIST_ITERATOR;
					break;
				}


				case TYPE_LIST_ITERATOR:
					if(type == TYPE_MARK)
					{
						// clear mark so nested iterator containers do not get terminated prematurely.
						type = -1;

						// decref the append method
						Py_XDECREF(container->obj2);
						container->obj2 = NULL;
						container->type = TYPE_DICT_ITERATOR;
						break;
					}

					if(!container->obj2)
					{
						// grab the append method from the container and keep
						// it around for speed.
						if(!(container->obj2 = PyObject_GetAttr(container->obj, pyappend)))
							goto cleanup;
					}

					if(!PyObject_CallFunctionObjArgs(container->obj2, obj, NULL))
						goto cleanup;

#if MARSHAL_DEBUG
					DEBUG_INDENT;
					printf("Appended %08lx to %08lx\r\n", obj, container->obj);
#endif // MARSHAL_DEBUG

					Py_DECREF(obj);
					break;


				case TYPE_DICT_ITERATOR:
					if(type == TYPE_MARK)
					{
						// clear mark so nested iterator containers do not get terminated prematurely.
						type = -1;

						// we're done with dict iter. container is finished.
						container->free = 1;
						break;
					}
					POPULATE_DICT(container->obj2, obj);
					break;


				case TYPE_DICT:
					POPULATE_DICT(obj, container->obj2);
					break;


				case 0:
					// we're at the root. return the object to caller.
					result = obj;

					// avoid decreffing this object.
					obj = NULL;
					goto cleanup;
			}

			container->free--;
			if(container->free)
				// still room in this container.
				// break out of container handling to get next object for it.
				break;

			// this container is done, it is the next object to put into the
			// container under it!
			obj = container->obj;

			// switch context to said older container
			POP_CONTAINER;
		}

		// we've processed the object. clear it for next one.
		obj = NULL;
	}

	// if we get here, we're out of data, but it's a "clean" eof; we ran out
	// of data while expecting a new object...
	error = "Not enough objects in stream";

fail:
	PyErr_Format(UnmarshalError, "%s - type:0x%02x ctype:0x%02x len:%d share:%d pos:%d size:%d", error, type, container->type, (int)length, shared, (int)(s-stream), (int)(size));

cleanup:
	// on any error the current object we were working on will be unassociated
	// with anything, decref it. if decode was succesful or an object failed to
	// be created, it will be NULL anyway.
	Py_XDECREF(obj);

	// same story for containers...
	while(container->type)
	{
		Py_XDECREF(container->obj);
		// possibly unassociated object for dict entry?
		if(container->type == TYPE_DICT || container->type == TYPE_DICT_ITERATOR)
		{
			Py_XDECREF(container->obj2);
		}

		POP_CONTAINER;
	}

	if(shared_obj)
	{
		/* shared object list held a safety ref to all objects, decref em */
		int i;
		for(i=0; i<shared_mapsize; i++)
			Py_XDECREF(shared_obj[i]);

		/* and free the list */
		PyMem_FREE(shared_obj);
	}
	return result;
}
Ejemplo n.º 6
0
int primary(LVALUE *lval) {
    char    sname[NAMESIZE];
    int     num[1], k, symbol_table_idx, offset, reg;
    SYMBOL *symbol;

    lval->ptr_type = 0;  // clear pointer/array type
    lval->tagsym = 0;
    if (match ("(")) {
        k = hier1 (lval);
        needbrack (")");
        return (k);
    }
    if (amatch("sizeof", 6)) {
        needbrack("(");
        gen_immediate();
        if (amatch("int", 3)) output_number(INTSIZE);
        else if (amatch("char", 4)) output_number(1);
        else if (symname(sname)) {
            if (((symbol_table_idx = find_locale(sname)) > -1) ||
                ((symbol_table_idx = find_global(sname)) > -1)) {
                symbol = &symbol_table[symbol_table_idx];
                if (symbol->storage == LSTATIC)
                    error("sizeof local static");
                offset = symbol->offset;
                if ((symbol->type & CINT) ||
                    (symbol->identity == POINTER))
                    offset *= INTSIZE;
                else if (symbol->type == STRUCT)
                    offset *= tag_table[symbol->tagidx].size;
                output_number(offset);
            } else {
                error("sizeof undeclared variable");
                output_number(0);
            }
        } else {
            error("sizeof only on type or variable");
        }
        needbrack(")");
        newline();
        lval->symbol = 0;
        lval->indirect = 0;
        return(0);
    }
    if (symname (sname)) {
        if ((symbol_table_idx = find_locale(sname)) > -1) {
            symbol = &symbol_table[symbol_table_idx];
            reg = gen_get_locale(symbol);
            lval->symbol = symbol;
            lval->indirect = symbol->type;
            if (symbol->type == STRUCT) {
                lval->tagsym = &tag_table[symbol->tagidx];
            }
            if (symbol->identity == ARRAY ||
                (symbol->identity == VARIABLE && symbol->type == STRUCT)) {
                lval->ptr_type = symbol->type;
                return reg;
            }
            if (symbol->identity == POINTER) {
                lval->indirect = CINT;
                lval->ptr_type = symbol->type;
            }
            return FETCH | reg;
        }
        if ((symbol_table_idx = find_global(sname)) > -1) {
            symbol = &symbol_table[symbol_table_idx];
            if (symbol->identity != FUNCTION) {
                lval->symbol = symbol;
                lval->indirect = 0;
                if (symbol->type == STRUCT) {
                    lval->tagsym = &tag_table[symbol->tagidx];
                }
                if (symbol->identity != ARRAY &&
                    (symbol->identity != VARIABLE || symbol->type != STRUCT)) {
                    if (symbol->identity == POINTER) {
                        lval->ptr_type = symbol->type;
                    }
                    return FETCH | HL_REG;
                }
                gen_immediate();
                output_string(symbol->name);
                newline();
                lval->indirect = symbol->type;
                lval->ptr_type = symbol->type;
                return 0;
            }
        }
        blanks();
        if (ch() != '(')
            error("undeclared variable");
        symbol_table_idx = add_global(sname, FUNCTION, CINT, 0, PUBLIC);
        symbol = &symbol_table[symbol_table_idx];
        lval->symbol = symbol;
        lval->indirect = 0;
        return 0;
    }
    lval->symbol = 0;
    lval->indirect = 0;
    if (constant(num))
        return 0;
    else {
        error("invalid expression");
        gen_immediate();
        output_number(0);
        newline();
        junk();
        return 0;
    }
}
Ejemplo n.º 7
0
int main(int argc, char *argv[]){
    unsigned i, addr;
    int SimsVersion = 0;
    int overwrite = 0;
    int ShowAddresses = 0;
    int length;
    char *basename;
    char *path[filecount] = {NULL};
    uint8_t *data[filecount-1] = {NULL};
    size_t filesize[filecount-1];
    FILE * hFile;
    const global_t * Globals;
    size_t GlobalCount;
    uint32_t SymbolTable = 0;
    uint32_t BaseSoundID = 0, BaseSoundIDSet = 0;

    /* collected data */
    addresslist_t AddressList;

    /****
    ** Parse the command-line arguments
    */

    if(argc == 1 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")){
        printf("Usage: hitdump [-ts1|-tso] [-f] [-a] [-o outfile.txt] [-hsm infile.hsm]\n"
            "       [-hot infile.hot] [-evt infile.evt] infile.hit\n"
            "Disassemble a HIT binary.\n"
            "\n"
            "The HSM, HOT, and EVT files are not strictly necessary but\n"
            "each help in their own way to provide labels for addresses.\n"
            "Use -f to force overwriting without confirmation.\n"
            "Use -a to show addresses (verbose).\n"
            "\n"
            "Report bugs to <*****@*****.**>.\n"
            "hitutils is maintained by the Niotso project.\n"
            "Home page: <http://www.niotso.org/>\n");
        return 0;
    }

    for(i=1; i<(unsigned)argc-1; i++){
        if(!strcmp(argv[i], "-ts1"))      SimsVersion = VERSION_TS1;
        else if(!strcmp(argv[i], "-tso")) SimsVersion = VERSION_TSO;
        else if(!strcmp(argv[i], "-f"))   overwrite = 1;
        else if(!strcmp(argv[i], "-a"))   ShowAddresses = 1;
        else if(i != (unsigned)argc-2){
            if(!strcmp(argv[i], "-out"))      path[out] = argv[++i];
            else if(!strcmp(argv[i], "-hsm")) path[hsm] = argv[++i];
            else if(!strcmp(argv[i], "-hot")) path[hot] = argv[++i];
            else if(!strcmp(argv[i], "-evt")) path[evt] = argv[++i];
            else break;
        }
        else break;
    }

    if(!SimsVersion){
        fprintf(stderr, "%sSims version not specified. (Use -ts1 or -tso.)\n", "hitdump: Error: ");
        return -1;
    }

    if(SimsVersion == VERSION_TS1){
        Globals = TS1Globals;
        GlobalCount = TS1GlobalCount;
    }else{
        Globals = TSOGlobals;
        GlobalCount = TSOGlobalCount;
    }

    path[hit] = argv[i];
    length = strlen(path[hit]);
    if(path[out] == NULL){
        path[out] = malloc(max(length+1, 5));
        strcpy(path[out], path[hit]);
        strcpy(path[out] + max(length-4, 0), ".txt");
    }
    length = max(length+1-4, 1);
    basename = malloc(length);
    memcpy(basename, path[hit], length-1);
    basename[length-1] = '\0';

    /****
    ** Read all of the requested files
    */

    for(i=0; i<filecount-1; i++){
        if(!path[i]) continue;

        hFile = fopen(path[i], "rb");
        if(hFile == NULL){
            if(i != hit){
                fprintf(stderr, "%sCould not open file: %s\n", "hitdump: Warning: ", path[i]);
                continue;
            }else{
                fprintf(stderr, "%sCould not open file: %s\n", "hitdump: Error: ", path[i]);
                return -1;
            }
        }

        fseek(hFile, 0, SEEK_END);
        filesize[i] = ftell(hFile);
        if(filesize[i] == 0){
            fclose(hFile);
            if(i != hit){
                fprintf(stderr, "%sFile is invalid: %s\n", "hitdump: Warning: ", path[i]);
                continue;
            }else{
                fprintf(stderr, "%sFile is invalid: %s\n", "hitdump: Error: ", path[i]);
                return -1;
            }
        }

        data[i] = malloc(filesize[i]);
        if(data[i] == NULL){
            fclose(hFile);
            if(i != hit){
                fprintf(stderr, "%sCould not allocate memory for file: %s\n", "hitdump: Warning: ", path[i]);
                continue;
            }else{
                fprintf(stderr, "%sCould not allocate memory for file: %s\n", "hitdump: Error: ", path[i]);
                return -1;
            }
        }

        fseek(hFile, 0, SEEK_SET);
        if(fread(data[i], 1, filesize[i], hFile) != filesize[i]){
            fclose(hFile);
            if(i != hit){
                fprintf(stderr, "%sCould not read file: %s\n", "hitdump: Warning: ", path[i]);
                continue;
            }else{
                fprintf(stderr, "%sCould not read file: %s\n", "hitdump: Error: ", path[i]);
                return -1;
            }
        }

        fclose(hFile);
    }

    /****
    ** Open the output file for writing
    */

    if(!overwrite){
        hFile = fopen(path[out], "rb");
        if(hFile != NULL){
            /* File exists */
            char c;
            fclose(hFile);
            fprintf(stderr, "hitdump: File \"%s\" exists.\nContinue anyway? (y/n) ", path[out]);
            c = getchar();
            if(c != 'y' && c != 'Y'){
                printf("\nAborted.\n");
                return -1;
            }
        }
    }
    hFile = fopen(path[out], "wb");
    if(hFile == NULL){
        fprintf(stderr, "%sCould not open file: %s\n", "hitdump: Error: ", path[out]);
        return -1;
    }

    /****
    ** Verify the header of the HIT file
    */

    if(filesize[hit] < 16 || memcmp(data[hit], HITHeader, 16)){
        fprintf(stderr, "%sFile is invalid: %s\n", "hitdump: Error: ", path[hit]);
        return -1;
    }

    /****
    ** Build up the address list
    */

    AddressList.Size = 32;
    AddressList.Count = 0;
    AddressList.Entries = malloc(32 * sizeof(address_t));

    read_hit_addresses(data[hit], filesize[hit], &AddressList, &SymbolTable);
    if(data[evt]) read_evt_addresses(data[evt], filesize[evt], &AddressList);
    if(data[hsm]) read_hsm_addresses(data[hsm], filesize[hsm], &AddressList);
    if(data[hot]) read_hot_addresses(data[hot], filesize[hot], &AddressList);
    /* scan_branch_destinations(data[hit], filesize[hit], &AddressList); */

    for(i=0; i<AddressList.Count; i++){
        if(AddressList.Entries[i].SoundID != 0 && (!BaseSoundIDSet || AddressList.Entries[i].SoundID < BaseSoundID)){
            BaseSoundID = AddressList.Entries[i].SoundID;
            BaseSoundIDSet = 1;
        }

        if(ShowAddresses){
            printf("Address %u:\n  Exported: %u\n  TrackID: %u\n  SoundID: %u\n  Name: %s\n  LogicalAddress: %u\n", i,
                AddressList.Entries[i].Exported,
                AddressList.Entries[i].TrackID,
                AddressList.Entries[i].SoundID,
                AddressList.Entries[i].Name,
                AddressList.Entries[i].LogicalAddress
            );
        }
    }

    /****
    ** Perform the disassembly
    */

    fprintf(hFile, "BASEID_TRACKDATA %u\r\n"
        "\r\n"
        ";\r\n"
        "; generated by hitdump.\r\n"
        ";\r\n"
        "\r\n"
        "; useful symbols:\r\n"
        "; kSndobPlay = 1\r\n"
        "; tkd_Generic 1\r\n"
        "; tkd_GenericLooped 2\r\n"
        "; tkd_GenericHitList 3\r\n"
        "\r\n"
        "INCLUDE defaultsyms.txt\r\n"
        "INCLUDE SimsGlobals.txt\r\n"
        "\r\n"
        "LIST [Options] Version=1\r\n"
        "LIST [Options] LoadPriority=2\r\n"
        "\r\n"
        ";LIST [EventMappingEquate] kSndobPlay=1\r\n"
        "; --- end of standard intro text ---\r\n"
        "\r\n"
        "SYMBOLFILE %s%s\r\n"
        "INIFILE %s.ini", BaseSoundID, path[hsm] ? path[hsm] : basename, path[hsm] ? "" : ".hsm", basename);

    fprintf(hFile, "\r\n\r\nBINARY\r\n[");

    for(addr=16; addr<filesize[hit];){
        unsigned i;
        uint8_t opcode;
        const instruction_t * instruction;
        uint32_t operands;
        const address_t * Address;
        int HadSymbolTable = 0;

        if(SymbolTable && addr == SymbolTable){
            if(addr != 16)
                fprintf(hFile, "\r\n]\r\n\r\nBINARY\r\n[");
            fprintf(hFile, "\r\n"
                "\t69\r\n"
                "\t78\r\n"
                "\t84\r\n"
                "\t80\r\n");

            for(addr+=4; memcmp(data[hit]+addr, "EENT", 4); addr+=8){
                uint32_t TrackID = read_uint32(data[hit]+addr), LogicalAddress = read_uint32(data[hit]+addr+4);

                Address = find_address_by_logical_address(&AddressList, LogicalAddress);
                fprintf(hFile, "\r\n\t#%u\t\t#", TrackID);
                if(Address && Address->Name) fprintf(hFile, "%s", Address->Name);
                else                         fprintf(hFile, "%u", LogicalAddress);
            }

            if(addr-4 != SymbolTable)
                fprintf(hFile, "\r\n");
            fprintf(hFile, "\r\n"
                "\t69\r\n"
                "\t69\r\n"
                "\t78\r\n"
                "\t84");

            if(addr+4 == filesize[hit])
                break;
            fprintf(hFile, "\r\n]\r\n\r\nBINARY\r\n[");

            addr += 4;
            SymbolTable = 0;
            HadSymbolTable++;
        }

        Address = find_address_by_logical_address(&AddressList, addr);
        if(Address){
            if(!HadSymbolTable && addr != 16 && Address->Exported)
                fprintf(hFile, "\r\n]\r\n\r\nBINARY\r\n[");
            if(Address->Name)
                fprintf(hFile, "\r\n%s", Address->Name);
        }

        opcode = data[hit][addr];
        if(opcode == 0 || opcode > 96){
            fprintf(stderr, "%sIllegal opcode 0x%02X at address 0x%08X.\n", "hitdump: Error: ", opcode, addr);
            return -1;
        }

        instruction = Instructions + opcode - 1;
        operands = instruction->Operands;
        if(operands == UNIMPLEMENTED){
            fprintf(stderr, "%sUnimplemented instruction '%s' at address 0x%08X.\n", "hitdump: Error: ",
                instruction->Name, addr);
            return -1;
        }

        addr++;

        if(filesize[hit] - addr < (operands & 15)){
            fprintf(stderr, "%sInsufficient operand bytes for '%s' instruction at address 0x%08X (%u of %u supplied).\n",
                "hitdump: Error: ", instruction->Name, addr, filesize[hit] - addr, instruction->Operands);
            return -1;
        }

        fprintf(hFile, "\r\n\t\t%s", instruction->Name);
        for(i=0; (operands >>= 4) != 0; i++){
            int type = operands & 15;
            const char *position[] = {"first","second","third","fourth"};
            if(type == o_byte){
                fprintf(hFile, " #%u", data[hit][addr]);
                addr += 1;
            }else if(type == o_dword){
                fprintf(hFile, " #%u", read_uint32(data[hit]+addr));
                addr += 4;
            }else if(type == o_address){
                int LogicalAddress = read_uint32(data[hit]+addr);

                Address = find_address_by_logical_address(&AddressList, LogicalAddress);
                if(Address && Address->Name) fprintf(hFile, " #%s", Address->Name);
                else                         fprintf(hFile, " #%u", LogicalAddress);
                addr += 4;
            }else if(type == o_variable){
                int x = data[hit][addr];
                if(x > 16){
                    const char * Global = find_global(x, Globals, GlobalCount);
                    if(Global == NULL){
                        fprintf(stderr, "%sInvalid %s operand 0x%02X for '%s' instruction at address 0x%08X (expected %s).\n",
                            "hitdump: Error: ", position[i], x, instruction->Name, addr, "argument, register, or global");
                        return -1;
                    }
                    fprintf(hFile, " %s", Global);
                } else fprintf(hFile, " %s", Registers[x]);
                addr += 1;
            }else if(type == o_jump){
                unsigned x = 0;

                if(filesize[hit]-addr >= 4)
                    x = read_uint32(data[hit]+addr);
                else if(data[hit][addr] != 0x05 && data[hit][addr] != 0x06){
                    fprintf(stderr,
                        "%sInsufficient operand bytes for '%s' instruction at address 0x%08X (%u of %u supplied).\n",
                        "hitdump: Error: ", instruction->Name, addr, filesize[hit] - addr, 4);
                    return -1;
                }

                if(x >= 16 && x < filesize[hit]){
                    Address = find_address_by_logical_address(&AddressList, x);
                    if(Address && Address->Name) fprintf(hFile, " #%s", Address->Name);
                    else                         fprintf(hFile, " #%u", x);
                    addr += 4;
                }else{
                    x = data[hit][addr];
                    if(x > 16){
                        const char * Global = find_global(x, Globals, GlobalCount);
                        if(Global == NULL){
                            fprintf(stderr,
                                "%sInvalid %s operand 0x%02X for '%s' instruction at address 0x%08X (expected %s).\n",
                                "hitdump: Error: ", position[i], x, instruction->Name, addr, "argument, register, or global");
                            return -1;
                        }
                        fprintf(hFile, " %s", Global);
                    } else fprintf(hFile, " %s", Registers[x]);
                    addr += (data[hit][addr] != 0x05 && data[hit][addr] != 0x06) ? 4 : 1;
                }
            }
        }
    }

    fprintf(hFile, "\r\n]\r\n\r\n");

    fclose(hFile);

    return 0;
}