#include #include #include // Object % Object new { %casts return ctor(allocate(self), app); } % Object ctor { %casts return self; } % Object dtor { %casts return self; } % Object differ { %casts return self != b; } % Object puto { const struct Class * class; %casts class = classOf(self); return fprintf(fp, "%s at %p\n", class -> name, self); } % Object delete { %casts free(dtor(self)); } % Object geto { void * dummy; %casts if (fscanf(fp, " at %p\n", & dummy) != 1) assert(0); return self; } % classOf { %casts return self -> class; } % sizeOf { const struct Class * class = classOf(_self); return class -> size; } % isA { if (_self) { %casts return classOf(self) == class; } return 0; } % isOf { if (_self) { const struct Class * myClass; %casts myClass = classOf(self); if (class != Object()) { while (myClass != class) if (myClass != Object()) myClass = super(myClass); else return 0; } return 1; } return 0; } static void catch (int sig) // signal handler: bad pointer { assert(sig == 0); // bad pointer, should not happen } #define isObject(p) \ ( assert(p), \ assert(((struct Object *) p) -> magic == MAGIC), p ) % cast { void (* sigsegv)(int) = signal(SIGSEGV, catch); #ifdef SIGBUS void (* sigbus)(int) = signal(SIGBUS, catch); #endif const struct Object * self = isObject(_self); const struct Class * myClass = isObject(self -> class); if (class != Object()) { isObject(class); while (myClass != class) { assert(myClass != Object()); // illegal cast myClass = myClass -> super; } } #ifdef SIGBUS signal(SIGBUS, sigbus); #endif signal(SIGSEGV, sigsegv); return (void *) self; } % respondsTo { if (tag && * tag) { const struct Class * class = classOf(_self); const struct Method * p = & class -> ctor; // first int nmeth = (sizeOf(class) - offsetof(struct Class, ctor)) / sizeof(struct Method); // # of Methods do if (p -> tag && strcmp(p -> tag, tag) == 0) return p -> method ? p -> selector : 0; while (++ p, -- nmeth); } return 0; } struct classList { const char * name; const void * class; }; static int cmp (const struct classList * a, const struct classList * b) { return strcmp(a -> name, b -> name); } void * retrieve (FILE * fp) { char buf [BUFSIZ]; extern const void * (* classes[]) (void); // munch static struct classList * cL; // local copy static int cD = -1; // # classes if (cD < 0) { for (cD = 0; classes[cD]; ++ cD) ; // count classes if (cD > 0) // collect name/desc { cL = malloc(cD * sizeof(struct classList)); assert(cL); for (cD = 0; classes[cD]; ++ cD) cL[cD].class = classes[cD](), cL[cD].name = nameOf(cL[cD].class); } } if (! cD) fputs("no classes known\n", stderr); else if (fp && ! feof(fp) && fscanf(fp, "%s", buf) == 1) { struct classList key, * p; key.name = buf; if ((p = bsearch(& key, cL, cD, sizeof key, (int (*) (const void *, const void *)) cmp))) return geto(allocate(p -> class), fp); fprintf(stderr, "%s: cannot retrieve\n", buf); } return 0; } // Class % Class dtor { assert(0); return 0; } % Class delete { %casts fprintf(stderr, "%s: cannot delete class\n", self -> name); } % Class geto { assert(0); return 0; // cannot happen } % allocate { struct Object * object; %casts assert(self -> size); object = calloc(1, self -> size); assert(object); object -> magic = MAGIC; object -> class = self; return object; } % super { %casts return self -> super; } % nameOf { %casts return self -> name; } // initialization // _Class and _Object are statically initialized structures extern const struct Class _Object; extern const struct Class _Class; %init static const struct Class _Object = { { MAGIC, & _Class }, "Object", & _Object, sizeof(struct Object), { "", (Method) 0, (Method) Object_ctor }, { "", (Method) 0, (Method) Object_dtor }, { "differ", (Method) differ,(Method) Object_differ }, { "puto", (Method) puto, (Method) Object_puto }, { "delete", (Method) delete,(Method) Object_delete }, { "", (Method) geto, (Method) Object_geto }, { "", (Method) 0, (Method) Object_new }, }; static const struct Class _Class = { { MAGIC, & _Class }, "Class", & _Object, sizeof(struct Class), { "", (Method) 0, (Method) Class_ctor }, { "", (Method) 0, (Method) Class_dtor }, { "differ", (Method) differ,(Method) Object_differ }, { "puto", (Method) puto, (Method) Object_puto }, { "delete", (Method) delete,(Method) Class_delete }, { "", (Method) 0, (Method) Class_geto }, { "", (Method) 0, (Method) Object_new }, };