/* print - Implements print function for variable types. */ #include "common.h" #include "hash.h" #include "../compiler/pfPreamble.h" #include "runType.h" #include "print.h" static void printEscapedString(FILE *f, char *s) /* Print string in such a way that C can use it. */ { char c; fputc('\'', f); while ((c = *s++) != 0) { switch (c) { case '\n': fputs("\\n", f); break; case '\r': fputs("\\r", f); break; case '\\': fputs("\\\\", f); break; case '\'': fputs("\\'", f); break; default: fputc(c, f); break; } } fputc('\'', f); } static int idLookup(struct hash *hash, void *obj) /* Look up object in hash. Return 0 if can't find it. * Otherwise return object id. */ { char buf[17]; safef(buf, sizeof(buf), "%p", obj); return hashIntValDefault(hash, buf, 0); } static void idAdd(struct hash *hash, void *obj) /* Add to object hash */ { char buf[17]; safef(buf, sizeof(buf), "%p", obj); hashAddInt(hash, buf, hash->elCount+1); } static boolean reuseObject(FILE *f, struct hash *idHash, void *obj) /* Print code for reuse of object if possible. Otherwise * print nothing, save object id and return FALSE. */ { int id = idLookup(idHash, obj); if (id != 0) { fprintf(f, "$%d", id); return TRUE; } else { idAdd(idHash, obj); return FALSE; } } static void printClass(FILE *f, struct _pf_object *obj, struct _pf_base *base, struct hash *idHash) /* Print out each field of class. */ { struct _pf_type *field; if (obj == NULL) fprintf(f, "nil"); else { if (idHash == NULL || !reuseObject(f, idHash, obj)) { char *s = (char *)obj; fprintf(f, "("); for (field = base->fields; field != NULL; field = field->next) { if (idHash != NULL || field->base->fields == NULL) _pf_printField(f, s+field->offset, field->base, idHash); else fprintf(f, "<%s>", field->base->name); if (field->next != NULL) fprintf(f, ","); } fprintf(f, ")"); } } } static void printString(FILE *f, struct _pf_string *string) /* Print out string. */ { if (string != NULL) { // fprintf(f, "[ugly:%d]", string->_pf_refCount); printEscapedString(f, string->s); } else fprintf(f, "nil"); } static void printArray(FILE *f, struct _pf_array *array, struct _pf_base *base, struct hash *idHash) /* Print out each element of Array. */ { if (array == NULL) fprintf(f, "nil"); else { if (idHash) { if (!reuseObject(f, idHash, array)) { struct _pf_type *elType = array->elType; int i; boolean needsComma = FALSE; char *s = array->elements; fprintf(f, "("); for (i=0; isize; ++i) { if (needsComma) fprintf(f, ","); needsComma = TRUE; _pf_printField(f, s, elType->base, idHash); s += array->elSize; } fprintf(f, ")"); } } else { fprintf(f, "", array->size); } } } static void printDir(FILE *f, struct _pf_dir *dir, struct _pf_base *base, struct hash *idHash) /* Print out each key/val pair in dir. */ { if (dir == NULL) fprintf(f, "()"); else { if (idHash) { if (!reuseObject(f, idHash, dir)) { struct hash *hash = dir->hash; struct hashEl *hel, *helList = hashElListHash(hash); struct _pf_base *base = dir->elType->base; slSort(&helList, hashElCmp); fprintf(f, "("); for (hel = helList; hel != NULL; hel = hel->next) { fprintf(f, "'%s'@", hel->name); if (base->needsCleanup) _pf_printField(f, &hel->val, base, idHash); else _pf_printField(f, hel->val, base, idHash); if (hel->next != NULL) fprintf(f, ","); } hashElFreeList(&helList); fprintf(f, ")"); } } else { fprintf(f, "", dir->hash->elCount); } } } void _pf_printField(FILE *f, void *data, struct _pf_base *base, struct hash *idHash) /* Print out a data from a single field of given type. */ { switch (base->singleType) { case pf_stBit: { _pf_Bit *p = data; fprintf(f, "%d", *p); break; } case pf_stChar: { _pf_Char *p = data; _pf_Char b = *p; fprintf(f, "%c", b); break; } case pf_stByte: { _pf_Byte *p = data; _pf_Byte b = *p; fprintf(f, "%d", b); break; } case pf_stShort: { _pf_Short *p = data; fprintf(f, "%d", *p); break; } case pf_stInt: { _pf_Int *p = data; fprintf(f, "%d", *p); break; } case pf_stLong: { _pf_Long *p = data; fprintf(f, "%lld", *p); break; } case pf_stFloat: { _pf_Float *p = data; fprintf(f, "%f", *p); break; } case pf_stDouble: { _pf_Double *p = data; fprintf(f, "%f", *p); break; } case pf_stString: { _pf_String *p = data; printString(f, *p); break; } case pf_stClass: { struct _pf_object **p = data; printClass(f, *p, base, idHash); break; } case pf_stArray: { struct _pf_array **p = data; printArray(f, *p, base, idHash); break; } case pf_stDir: { struct _pf_dir **p = data; printDir(f, *p, base, idHash); break; } case pf_stToPt: { _pf_FunctionPt **p = data; fprintf(f, "", *p); break; } case pf_stFlowPt: { _pf_FunctionPt **p = data; fprintf(f, "", *p); break; } case pf_stVar: { struct _pf_var *var = data; struct _pf_type *type = _pf_type_table[var->typeId]; _pf_printField(f, &var->val, type->base, idHash); break; } default: internalErr(); break; } } void _pf_prin(FILE *f, _pf_Stack *stack, boolean formal) /* Print out single variable where type is determined at run time. */ { struct _pf_type *type = _pf_type_table[stack->Var.typeId]; struct _pf_base *base = type->base; union _pf_varless val = stack->Var.val; struct hash *idHash = NULL; switch (base->singleType) { case pf_stBit: fprintf(f, "%d", val.Bit); break; case pf_stByte: fprintf(f, "%d", val.Byte); break; case pf_stChar: fprintf(f, "%c", val.Char); break; case pf_stShort: fprintf(f, "%d", val.Short); break; case pf_stInt: fprintf(f, "%d", val.Int); break; case pf_stLong: fprintf(f, "%lld", val.Long); break; case pf_stFloat: if (formal) fprintf(f, "%f", val.Float); else fprintf(f, "%0.2f", val.Float); break; case pf_stDouble: if (formal) fprintf(f, "%f", val.Double); else fprintf(f, "%0.2f", val.Double); break; case pf_stString: if (formal || val.String == NULL) printString(f, val.String); else fprintf(f, "%s", val.String->s); break; case pf_stClass: idHash = newHash(18); printClass(f, val.Obj, base, idHash); break; case pf_stArray: idHash = newHash(18); printArray(f, val.Array, base, idHash); break; case pf_stDir: idHash = newHash(18); printDir(f, val.Dir, base, idHash); break; case pf_stToPt: fprintf(f, "\n", val.FunctionPt); break; case pf_stFlowPt: fprintf(f, "\n", val.FunctionPt); break; default: fprintf(f, "\n", base->singleType); internalErr(); break; } if (base->needsCleanup) { if (val.Obj != NULL && val.Obj->_pf_cleanup != NULL && --val.Obj->_pf_refCount <= 0) val.Obj->_pf_cleanup(val.Obj, stack->Var.typeId); } freeHash(&idHash); } void pf_prin(_pf_Stack *stack) /* Print out single variable where type is determined at run time. */ { _pf_prin(stdout, stack, FALSE); } void pf_print(_pf_Stack *stack) /* Print out single variable where type is determined at run time. * Add newline. */ { pf_prin(stack); fputc('\n', stdout); } void pf_ugly(_pf_Stack *stack) /* This is just a synonym for print to distinguish debugging statement * from real prints. */ { pf_print(stack); } void pf__printBit(_pf_Stack *stack) /* Print integer, just for debugging really */ { printf("%d\n", stack->Bit); } void pf__printByte(_pf_Stack *stack) /* Print integer, just for debugging really */ { printf("%d\n", stack->Byte); } void pf__printShort(_pf_Stack *stack) /* Print integer, just for debugging really */ { printf("%d\n", stack->Short); } void pf__printInt(_pf_Stack *stack) /* Print integer, just for debugging really */ { printf("%d\n", stack->Int); } void pf__printLong(_pf_Stack *stack) /* Print long, just for debugging really */ { printf("%lld\n", stack->Long); } void pf__printFloat(_pf_Stack *stack) /* Print double, just for debugging really */ { printf("%f\n", stack->Float); } void pf__printDouble(_pf_Stack *stack) /* Print double, just for debugging really */ { printf("%f\n", stack->Double); } void pf__printString(_pf_Stack *stack) /* Print double, just for debugging really */ { struct _pf_string *string = stack->String; char *text = "(null)"; if (string != NULL) text = string->s; printf("%s\n", text); }