/* Copyright Per Bothner 1987. Read the file Q-INFO */
#include <stdlib.h>
#include <types.h>
#include <parsefile.h>
#include <Qcompile.h>
#include <procs.h>
#include <traverse.h>
#include <exceptions.h>
//#include <hash.h>
#include <newtype.h>
#include <methods.h>
#include "typetabs.h"

extern void EmitFields(struct Field *fields, CFile& cf);
extern "C" int encode_string_to_label(char *str, int length, char *buf);

extern Object DerefVar(), StdAllocOb();
extern union ObUnion EmpArray[1];
EXTERN char * GetTypeName(struct Type *type);
EXTERN void TypeCompile(struct RecordType *typ, CFile *cf, char *name);
EXTERN void PutType(FILE *f, struct Type *type);

/* options in struct TypeFieldInfo may be options of struct Type, plus: */
#define ShortField 0x4000 /* field is a short integer */
#define LongField 0x2000 /* field is a long integer */
#define CharField 0x1000
#define DirectField (ShortField|LongField|CharField) /* not a pointer field */
#define CProcField 0x400 /* field must point to a c-compatible procedure */
#define ControlField (DirectField|CProcField)
struct TypeFieldInfo
  {
    Name name;
    Object default_value;
    CHandle temp;
    unsigned short offset;	/* offset of field in type structure */
    unsigned short options;
  };
#define TypeFieldMAX 25
int TypeFieldCount = 0;
struct TypeFieldInfo TypeFieldTab[TypeFieldMAX];

struct TypeKindInfo
  {
    Symbol * name;
    short size;
    unsigned short options;
  };
#define TypeKindMAX 7
int TypeKindCount = 0;

#define FieldOkHere(field, opts) \
	(((field)->options & ~ControlField) == 0 \
      || ((field)->options & (opts) & ~ControlField))

char * GetTypeName(struct Type *type)
{
#if 1
    abort();
#else
    if (type->class_name == NULL) {
	static type_num = 0; /* SHOULD BE PER-MODULE !!! */
	char buf[20];
	sprintf(buf, "TYPE_%d", ++type_num);
	type->class_name = EnterSymbol(buf);
    }
    return SymbolString(type->class_name);
#endif
}

#if 0
struct TypeKindInfo TypeKindTab[TypeKindMAX];

struct Type * AllocType(struct TypeKindInfo *kind)
  {
    struct Type *typ;
    int size;
    register struct TypeFieldInfo *field;
    if (kind == NULL)
	kind = &TypeKindTab[TypeKindCount-1];
    size = kind->size;
    typ = Alloc(TypeT, size);
    bzero(typ, size);

 /* fill in default values */
    for (field = TypeFieldTab; field->name; field++)
      {
	if (field->default_value && FieldOkHere(field, kind->options))
	    if (field->options & ShortField)
		*(short*)((char*)typ + field->offset) =
		    (short)field->default_value;
	    else
		*(Object*)((char*)typ + field->offset) = field->default_value;
      }

    typ->options = kind->options;
    typ->kind = RecordTypeKind;
    return typ;
}
#endif

#if 0
struct Type *
CloneType(struct Type *old)
{
    int size = TypeKindTab[TypeKindCount-1].size;
    struct Type *new = Alloc(TypeT, size);
    bcopy(old, new, size);
    return new;
}

struct Type *GetConstructType(struct Type **proc)
{
    if (!HasHType(proc, Construct1)) RaiseDomainError(proc);
    return proc[-2];
}
Object Construct1Alloc(struct Type **proc)
  { return StdAllocOb(proc[-2]); }

Fillin_Construct(gen, type)
    register Object gen;	/* a4 */
    register struct Type *type;	/* a3 */
  {
    if (!HasHType(gen, Construct1))
	RAISE(Illegal_request, NoValue);
    *type = *((struct Type**)gen)[-2];
    type->options |= RecordType;
    *(Object*)(type+1) = gen;
  }
struct Type *
ConstructType(gen) Object gen;
  {
    register struct Type *type;
    type = AllocType(&TypeKindTab[0]); /* RecordType */
    Fillin_Construct(gen, type);    
    return type;
  }
#endif

#if 0
struct Any
ExtractType(struct Any fun)
  { /* new (struct Any) version of ConstructType */
    struct Clause *clause;
    struct Function *func = (struct Function*)fun.type;
    if (fun.addr != NULL) abort();
    if (func->t.kind != FunctionTypeKind) abort();
    if (func->nClauses != 1) abort();
    clause = func->clauses;
    if (clause->resultType == NULL) abort();
    return MAKE_ANY(clause->resultType, TypeT);
  }
#endif

#if 0
struct Any
GiveNameToType(struct Any fun, struct Any name)
{
    struct Type *type;
#if 0
    if (fun.type == TypeT || fun.type == ExceptionT)
	type = fun.addr;
    else
#endif
      {
	struct Function *func = (struct Function*)fun.type;
	struct Clause *clause;
	if (fun.addr != NULL) abort();
	if (func->t.kind != FunctionTypeKind) abort();
	if (func->nClauses != 1) abort();
	clause = func->clauses;
	if (clause->resultType == NULL) abort();
	type = clause->resultType;
    }
    type->class_name = name.addr;
    return name;
}
#endif

#if 0
void TypeField(char *name, int offset, Object default_value, int options)
  {
  TypeFieldTab[TypeFieldCount].name = EnterSymbol(name);
  TypeFieldTab[TypeFieldCount].offset = offset;
  TypeFieldTab[TypeFieldCount].options = options;
  TypeFieldTab[TypeFieldCount].default_value = default_value;
  TypeFieldCount++;
  if (TypeFieldCount >= TypeFieldMAX)
    { fprintf(stderr, "!Too many TypeFields!\n"); fflush(stderr); abort(); }
  TypeFieldTab[TypeFieldCount].name = 0;
  }

void TypeKind(char *name, int size, int options)
  {
  TypeKindTab[TypeKindCount].name = EnterSymbol(name);
  TypeKindTab[TypeKindCount].size = size;
  TypeKindTab[TypeKindCount].options = options;
  TypeKindCount++;
  if (TypeKindCount >= TypeKindMAX)
    { fprintf(stderr, "!Too many TypeKinds!\n"); fflush(stderr); abort(); }
  }
#endif

#if 0
static
InsertRecordField(rField, type, name)
    struct RecordField *rField; struct Type *type; Name name;
  {
    int size = rField->size;
    if (size == 0) size = sizeof(Object);
    rField->offset = type->size;
    type->size += size;
    if (type->fieldList == NULL) type->fieldList = rField;
    else
      { struct RecordField *lastField = type->fieldList;
	for (; lastField->next != NULL; lastField = lastField->next) ;
	lastField->next = rField;
      }
    rField->name = name;
  }
#endif

#if 0
void CompileTypeDef(struct TypeDefExpr *expr, CFile *cf, struct Label *dest)
{
    register struct Statement *st;
    if (!expr->result)
      { struct Type *type = AllocType(expr->kind);
	type->name = expr->name;
	expr->result = type;
	for (st = expr->first; st != NULL; st = st->next)
	  { Name name;
	    if (st->decl == NULL)
		continue;
	    name = st->decl->name;
	    CompileExpr(st->src, cf, IgnoreResultToken);
	  }

	if (!EvalCompile(cf))
	    CompileError(cf,"CompileTypeDef only implemented for interpreter");
      }
    CompileLoadValue(expr->result, cf, dest);
}
#endif

#if 0
InsertTypeField(type, name, value)
    struct Type *type;
  {
    if (type->desc == NULL) {
	type->desc = HashTable::New(8, TObjectOb.hash);
	type->hash->flags |= HashDefaultIsProc;
    }
    Insert(type->hash, name, value);
  }
#endif

#if 0
struct RecordField *
MakeDirectField(type)
    struct Type *type;
  { struct RecordField *rField =
	Alloc(DeclarationT, sizeof(struct RecordField));
    rField->offset = -1;
    rField->next = NULL;
    if (MemGetType(type)==TypeT)
      {
	rField->type = MakeExType(ExDirectType, type);
	if (type->prefixLen > sizeof(struct Type*))
	    RunError(0, "Bad DIRECT - %s has prefixed fields", type->name);
	rField->size = type->size;
      }
#if 0
    else if (HasHType(type, FixInt))
      {
	rField->type = NULL;
	rField->size = *(long*)type;
      }
#endif
    else
	RunError(0, "Bad argument to DIRECT");
    return rField;
  }

struct Type *
MakeBytesType(n)
    long *n;
  { struct Type *type = AllocType(0);
    struct RecordField *rField = MakeDirectField(n);
    InsertRecordField(rField, type, NULL);
    return type;
  }
#endif

#if 0
struct FieldExtra
  {
    CFile *cf;
    struct Label *lab, *curName;
    char *format;
  };

TypeFieldCompile(struct FieldExtra *field_extra, fieldName, void *value)
    struct FieldExtra *field_extra;
    void *value;
  { struct Label *lab = field_extra->lab;
    register CFile *cf = field_extra->cf;
    lab->flags = 0; lab->offset = 0; lab->kind = StringLabel;
    if (value == NULL)
      { lab->label = NULL; return; }
    if (SearchPrevCompiled(lab, value, cf)) return;
    if (field_extra->curName == NULL || IsOffsetLabel(field_extra->curName))
	MakeGenLabel(lab, cf->generate_label_number());
    else
      { char nameBuf[60];
	if (field_extra->curName->kind == GeneratedLabel)
	  {
	    GenLabToString(nameBuf, (int)field_extra->curName->label);
	  }
	else
	    strcpy(nameBuf, field_extra->curName->label);
	sprintf(nameBuf+strlen(nameBuf), field_extra->format, fieldName);
	lab->label = strdup(nameBuf);
      }
    CPutGen(value, cf, lab);
  }
#endif

void PutAsCName(Symbol *sym, FILE *file)
{
    char encoded_name[2 * sym->length() + 10];
    encode_string_to_label(sym->string(), sym->length(), encoded_name);
    // KLUDGE: g++ claims (?) to allow $ in identifiers,
    // but doesn't. Change them to _ for now.
    for (char *p = encoded_name; *p; p++) {
	if (*p == '$') *p = '_';
	putc(*p, file);
    }
}
void PutAsCName(Symbol *sym, ostream& outs)
{
    char encoded_name[2 * sym->length() + 10];
    encode_string_to_label(sym->string(), sym->length(), encoded_name);
    // KLUDGE: g++ claims (?) to allow $ in identifiers,
    // but doesn't. Change them to _ for now.
    register streambuf* sbuf = outs.rdbuf();
    for (char *p = encoded_name; *p; p++) {
	if (*p == '$') *p = '_';
	sbuf->sputc(*p);
    }
}

void Type::cdecl(Symbol *var, ostream& outs) const
{
    char buf[20];
    sprintf(buf, "<%x>", this);
    outs << buf;
    if (var) outs << ' ' << var->string();
}

void PrimIntType::cdecl(Symbol *var, ostream& outs) const
{
    outs << c_name.string();
    if (var) outs << ' ', PutAsCName(var, outs);
}

void TextType::cdecl(Symbol *var, ostream& outs) const
{
    outs << "ostream*";
    if (var) outs << ' ', PutAsCName(var, outs);
}

void ReferenceType::cdecl(Symbol *var, ostream& outs) const
{
    base_class->cdecl(NULL, outs);
    outs << '*';
    if (var) outs << ' ', PutAsCName(var, outs);
}

void RecordType::cdecl(Symbol *var, ostream& outs) const
{
    outs << name();
    if (var) outs << ' ', PutAsCName(var, outs);
}

void PrintTypeAsC(Type * type, Symbol * var, ostream& outs)
/* Print a type in C syntax.
 * If var is given, write a declaration for var
 */
{
    if (type == NULL)
	outs << "Root*";
    else
	((const Type*)type)->cdecl(var, outs);
}

void DumpClassStruct(ClassDesc *classDesc, char* name, ostream& outs)
{
    struct Field *fld;
    int i = 0;
    outs << "struct " << name;
    FOR_EACH_FIELD(fld, classDesc) {
	if (fld->kind == Include_Field) {
	    outs << (i++ == 0 ? " : public " : " , public ");
	    PrintTypeAsC(fld->ftype(), NULL, outs);
	}
    }
    outs << " {\n";
    FOR_EACH_FIELD(fld, classDesc) {
/* NOTE: should be merged with PrintTypeAsC */
	switch (fld->kind) {
	  case Include_Field:
	    outs << "  /* Included field */\n";
	  case Method_Field:
	    outs << "    /* method " ;
	    PrintTypeAsC(fld->ftype(), fld->fname(), outs);
	    outs << " */;\n";
	    break;
	  case Constant_Field:
	    outs << "    static ";
	    PrintTypeAsC(fld->ftype(), fld->fname(), outs);
	    outs << ";\n";
	    break;
	  case Pointer_Field:
	  case Struct_Field:
	    outs << "    ";
	    PrintTypeAsC(fld->ftype(), fld->fname(), outs);
	    outs << ";\n";
	    break;
#if 0
	  case Bit_Field:
	    fprintf(ff, "    ");
	    if (fld->u.b.is_signed == 0) fprintf(ff, "unsigned ");
	    if (fld->u.b.size == 8 /* && (fld->offset & 8) == 0 */)
		fprintf(ff, "char %s;\n", SymbolString(fld->name));
	    else if (fld->u.b.size == 16 /* && (fld->offset & 16) == 0 */)
		fprintf(ff, "short %s;\n", SymbolString(fld->name));
	    else if (fld->u.b.size == 32 /* && (fld->offset & 32) == 0 */)
		fprintf(ff, "int %s;\n", SymbolString(fld->name));
	    else if (fld->u.b.size <= 32)
		fprintf(ff, "int %s : %d;\n",
		    SymbolString(fld->name), fld->u.b.size);
	    else if ((fld->offset & 15) || (fld->u.b.size & 15))
		fprintf(stderr, "Bad bit field %s\n", SymbolString(fld->name));
	    else
		fprintf(ff, "short %s[%d];\n",
		    SymbolString(fld->name), fld->u.b.size >> 4);
	    break;
#endif
	  default:
	    outs << "   ?strange[" << fld->kind << "] field "
		     << fld->name << ";\n";
	}
    }
    outs << "};\n";
}

extern struct Any Find_prefix_method();
extern struct Field *FindField();

void DumpClass(ClassDesc *classDesc, struct Label *name, register CFile *cf)
{   int i, n;
#if 0
    struct Label *labels;
    struct Field *fld;
    struct Label apply_label[4];
    struct FieldExtra field_extra;
    field_extra.cf = cf;
    field_extra.format = "_%s";
    field_extra.curName = name;
#define WriteFix(i, name, xxfix) \
    field_extra.lab = apply_label+i, \
    TypeFieldCompile(&field_extra, name, classDesc->xxfix)

    if (classDesc->prefix != Find_prefix_method) WriteFix(0, sPrefix, prefix);
    WriteFix(1, sPostfix, postfix);
/*    WriteFix(2, EnterSymbol("_namefix"), namefix); */
#endif

    n = classDesc->uFields + classDesc->nFields;
#if 0
    labels = (struct Label *)alloca(n*(sizeof(struct Label)));
    for (i = 1, fld = classDesc->fields + 1; i < n; i++, fld++)
	if (fld->kind == Constant_Field /*|| fld->kind == Method_Field*/) {
	    Object x = (Object)fld->u.value;
	    struct Label *label = labels+i;
	    if (IsVariable(x) && IsBound((Var*)x))
		x = ((Var*)x)->v.varlink.o;
#if 0
	    if (rField->flags & LookupDeclaration)
		MakeLabelToken(token, SymbolString(rField->name), 0, 0);
	    else
#endif
	    field_extra.lab = labels+i;
	    TypeFieldCompile(&field_extra, fld->name, x);
#if 0
	    cf->asm_stream() << "extern ObUnion " << *token;
	    cf->asm_stream() << "[1]; /* " << fld->name->string() << " */\n";
#endif
	}
#endif
#if 0
    cf->asm_stream() << "unsigned short " << *name;
    cf->asm_stream() << "_HASH[] = {";
    n = 1<<classDesc->nHashLog;
    for (i = 0; i < n; i++) cf->asm_stream() << classDesc->hash[i] << ",";
    cf->asm_stream() << "};\n";
#endif

    cf->asm_stream() << "struct Field " << *name << "_F[] = {\n";
    EmitFields(classDesc->fields, *cf);

    DumpPending(*cf);

    DumpPending(*cf);

    cf->asm_stream() << "struct ClassDesc _" << *name;
    cf->asm_stream() << "_[1] = {{" << *name;
    cf->asm_stream() << "_F, ";
#if 0
    cf->asm_stream() << *name << "_HASH,\n" << (int)classDesc->uFields << ", "
#else
    cf->asm_stream() << "0,\n" << (int)classDesc->uFields << ", "
#endif
	<< classDesc->nFields << ", " << (int)classDesc->nHashLog
	    << ", " << (int)classDesc->flags;
    cf->asm_stream() << "}};\n";
}

void TypeCompile(struct RecordType *typ, register CFile *cf, char *name)
{
    struct Label label[1];
    int length = sizeof(struct Type),
	widen_offset = 0, postfix_offset = 0;
#if 0
    register struct TypeKindInfo *kind;
    MakeLabelToken((struct DataToken*)label, name, 0, 0);
    for (kind = TypeKindTab; kind->name; kind++)
	if (typ->options == kind->options) break;
    register struct TypeFieldInfo *field;
    int i_field, pos;
    struct Label tmp_lab[1];
    struct Label field_label[TypeFieldMAX];
    struct FieldExtra field_extra;
    field_extra.curName = label;
    field_extra.cf = cf;
    field_extra.lab = tmp_lab;
    field_extra.format = ".%s";
    if (typ->hash != NULL)
	ForEachInTab(typ->hash, TypeFieldCompile, &field_extra);
#endif
#if 1
    label->kind = StringLabel; label->flags = 0; label->offset = 0;
    label->label = name;
    DumpClass(typ->desc, label, cf);
    DumpClassStruct(typ->desc,
		    typ->class_name ? typ->class_name->string() : name,
		    cf->aux_stream());
#else
    field_extra.format = "%s";
    for (field = TypeFieldTab, i_field = 0; field->name; field++, i_field++) {
	field_extra.lab = &field_label[i_field];
	if (typ->name
	 && field->offset == (unsigned short)&((struct Type*)0)->desc) {
	    struct Label tmp_lab[1];
	    char *save_format = field_extra.format;
	    MakeLabel(tmp_lab, SymbolString(typ->name), 0);
	    field_extra.curName = tmp_lab;
	    field_extra.format = "";
	    TypeFieldCompile(&field_extra, field->name,
		*(Object*)((char*)typ + field->offset));
	    field_extra.curName = label;
	    field_extra.format = save_format;
	}
	else if (FieldOkHere(field, kind->options)
	 && !(field->options & DirectField))
	    TypeFieldCompile(&field_extra, field->name,
		*(Object*)((char*)typ + field->offset));
      }
#endif

    cf->asm_stream() << "static char " << *label << "_S[] = \"";
    if (typ->class_name && typ->class_name->string())
	cf->asm_stream() << typ->name();
    else
	cf->asm_stream() << *label;
    cf->asm_stream() << "\";\n";
/*  CompStdPrefix(cf, NULL, &Type); */
    cf->asm_stream() << "struct Type " << name
	<< "T[1] = {{\n  " << name;
    cf->asm_stream() << "_S," << typ->inst_size << ",0,0,_" << name <<"_,0,0,";
    if (typ->kind == RecordTypeKind) cf->asm_stream() << "RecordTypeKind,";
    else cf->asm_stream() << "(enum TypeKind)" << (int)typ->kind << ",";
    cf->asm_stream() << typ->prefixLen << "," << typ->alignment << ","
	<< typ->excess_bits << ","
	    << (typ->options & ~TypeIsCompiled) << "|TypeIsCompiled}};\n";
}

#if 0
TypeDumpPtr(struct Any type, CFile *cf)
{
    struct Type *typ = type.addr;
    if (typ->name == NULL) typ->name = GenString();
    cf->aux_stream() << "extern struct Type " << typ->name << "T[1];\n";
    cf->asm_stream() << typ->name << "T";
    if (!(typ->options & TypeIsCompiled)) {
	struct Label label[1];
	MakeLabelToken(label, typ->name, 0, 0);
	SavePendingValue(cf, label, type);
	typ->options |= TypeIsCompiled;
    }
}
#endif

#if 0
InitPrevCompiled()
/* no longer needed ??? */
  { char buffer[80]; struct Label lab;
    register struct TypeFieldInfo *field;
    extern dbgmacros_MACROS[1];
//    extern UnaryPrefix__dump(); // needed for procedure _dump fields
    PrevCompiledList = NULL;
    lab.flags = 0; lab.kind = StringLabel;
    lab.label = buffer; lab.offset = 0;
    for (field = TypeFieldTab; field->name; field++)
      {
	if (field->default_value == 0) continue;
	sprintf(buffer, "Default%s", field->name);
	BindPrevCompiled(NULL, field->default_value, &lab);
      }
    lab.label = "EmpArray"; BindPrevCompiled(NULL, EmpArray, &lab);
    lab.label = "EOF_mark"; BindPrevCompiled(NULL, EOF_mark, &lab);
    lab.label = "NoValue"; BindPrevCompiled(NULL, NoValue, &lab);
    lab.label = "stdmacros_MACROS"; BindPrevCompiled(NULL, QStdMacros, &lab);
    lab.label = "dbgmacros_MACROS";
	BindPrevCompiled(NULL, dbgmacros_MACROS, &lab);
/* lab.label = "UnaryPrefix__dump";
	 BindPrevCompiled(NULL, UnaryPrefix__dump, &lab); */
  }
#endif

#if 0
void PutType(FILE *file, struct Type *type)
{
    type->printon(file);
}

extern struct TypeFil TCharFileOb, Default_file_type;
#define FldOff(field) ((char*)&TypeT->field - (char*)TypeT)
#define FileOff(field) ((char*)&TCharFileOb.field - (char*)&TCharFileOb)
#define ExprOff(field) ((char*)IdentifierT->field - (char*)&Identifier)

#define Default_index NULL
extern Object Default_open(), Default_file_size();
Default_putbuf(file) { RAISE(Illegal_request, NoValue); }
Default_close(file) { return; }
extern Default_as();
Default_release(x) { ; }
extern TypeSeq Array;
#define SequOff(field) ((char*)&Array.field - (char*)&Array)
asm(" .globl	NULL");
asm("NULL = 0");
#endif

#if 0
Object
TypeApply(register Object ob, register struct Type *type)
{
    Func proc;
    if ((proc = type->as) == NULL)
      {
      retry:
	if (MemGetType(ob) == type) return ob;
	else if (IsVariable(ob))
	  {
	    ob = DerefVar(ob);
	    goto retry;
	  }
	else RaiseDomainError(ob);
      }
    return CallQProc(type->as, 1, ob);
}
#endif

#if 0
TypeExprPrint(struct TypeDefExpr *type, FILE *file)
{
    if (type->gen == NULL)
      {
	fprintf(file, "TYPE\n");
	PrintStatements(type->first, file);
      }
    fprintf(file, "CLASS [block:#%X]\n", type->block);
    PrintIt(type->gen, file);
}
#endif

#if 0
struct FieldValues
  {
    struct Type *type;
    struct RecordField *field;
    short fieldCount i;
    Object field[1];
  };

AllocWithField(type, field1)
  {
  }

AllocMoreFields(prevFields, fieldi)
  {
  }

Object
GetRecordConstructor(type)
    struct Type *type;
  {
     if (type->options & RecordType)
	return *(Object*)(type+1);
     RAISE(Undefined, NoValue);
  }
#endif

#if 0
struct RecordField *
PutObjectArg(Object ob, struct RecordField *rField, Object arg)
  { Object *ptr;
    if (rField == NULL) RAISE(Undefined, NoValue);
    ptr = (Object*)((char*)ob + rField->offset);
    *ptr = arg;
    rField = rField->next();
    if (rField == NULL) RAISE(Undefined, NoValue);
    return rField;
  }

CompileAllocNode(expr, cf, dest)
    struct AllocNode *expr; CFile *cf; struct Label *dest;
  {
    if (expr->node != 0)
      {
	CompileExprNode(expr->expr, cf, dest);
	return;
      }
    CallExternC(cf, "StdAllocOb", NULL, 2, dest);
  }
#endif

#if 0
DumpBlockType(block, cf, lab)
    struct Block *block;
    register CFile *cf;
    struct Label *lab;
  {
    register struct Declaration *decl;
    int size, pos;
    struct Type *typ = ExType_Type(block->type);
    if (typ == NULL) abort();
    TypeCompile(typ, cf, lab);
    CompStdPrefix(cf, name, &Type);
    pos = 0;
    for (field = TypeFieldTab, i_field = 0; field->name; field++, i_field++)
	if (field->default_value && FieldOkHere(field, kind->options))
	  {
	    CompZero(cf, field->offset - pos, 0);
	    if (field->options & ShortField)
	      {
		Comp1Short(cf, field->default_value, field->name);
		pos = field->offset + sizeof(short);
	      }
	    else if (field->options & LongField)
	      {
		Comp1Long(cf, field->default_value, field->name);
		pos = field->offset + sizeof(long);
	      }
	    else
	      {
	    CompHandle(cf, &field_label[i_field]);
		pos = field->offset + sizeof(Object);
	      }
	  }
    CompZero(cf, kind->size - pos, 0);
  }
#endif

void TypeDefTraverse() { abort(); }
