/* ffigen.c * * Written by Lars Thomas Hansen (lth@cs.uoregon.edu) * * Copyright 1996 The University of Oregon. * * These sources are freely redistributable with no restrictions whatsoever, * except that you may not remove this copyright notice. */ #include #include #undef NULL #include "c.h" void print_type( Type t, FILE *out, int attrs ); void print_fields( Symbol sym, FILE *out ) { Field f; f = sym->u.s.flist; while (f) { fprintf( out, "(\"%s\" ", f->name ); print_type( f->type, out, 0 ); fprintf( out, ")" ); f = f->link; if (f) fprintf( out, " " ); } } void basetype( FILE *out, char *name, int attrs ) { fprintf( out, "(%s (", name ); if (attrs == CONST) fprintf( out, "const" ); else if (attrs == VOLATILE) fprintf( out, "volatile" ); else if (attrs) fprintf( out, "const volatile" ); fprintf( out, "))" ); } void print_type( Type t, FILE *out, int attrs ) { Type *a; /* Handle special cases */ if (t == chartype) basetype( out, "char", attrs ); else if (t == doubletype) basetype( out, "double", attrs ); else if (t == floattype) basetype( out, "float", attrs ); else if (t == inttype) basetype( out, "int", attrs ); else if (t == longdouble) basetype( out, "long-double", attrs ); else if (t == longtype) basetype( out, "long", attrs ); else if (t == shorttype) basetype( out, "short", attrs ); else if (t == signedchar) basetype( out, "signed-char", attrs ); else if (t == unsignedchar) basetype( out, "unsigned-char", attrs ); else if (t == unsignedlong) basetype( out, "unsigned-long", attrs ); else if (t == unsignedshort) basetype( out, "unsigned-short", attrs ); else if (t == unsignedtype) basetype( out, "unsigned", attrs ); else if (t == voidtype) basetype( out, "void", attrs ); switch (t->op) { case CHAR : case SHORT : case INT : case UNSIGNED : case LONG : case FLOAT : case DOUBLE : case VOID : break; case ARRAY : fprintf( out, "(array %d ", t->size/t->type->size ); print_type( t->type, out, attrs ); fputc( ')', out ); break; case ENUM : fprintf( out, "(enum-ref \"%s\")", t->u.sym->name ); break; case STRUCT : fprintf( out, "(struct-ref \"%s\")", t->u.sym->name ); break; case UNION : fprintf( out, "(union-ref \"%s\")", t->u.sym->name ); break; case POINTER : fprintf( out, "(pointer " ); print_type( t->type, out, 0 ); fprintf( out, ")" ); break; case FUNCTION : fprintf( out, "(function (" ); a = t->u.f.proto; if (a) while (*a) { print_type( *a, out, 0 ); if (*++a) fprintf( out, " " ); } fprintf( out, ") " ); print_type( t->type, out, 0 ); fprintf( out, ")" ); break; case CONST : case VOLATILE : case CONST+VOLATILE : print_type( t->type, out, t->op ); break; } } void print_global( Symbol s, void *args ) { FILE *out = (FILE*)args; char *class; class = "var"; if (s->sclass == TYPEDEF) class = "type"; else if ((s->sclass == STATIC || s->sclass == EXTERN || s->sclass == AUTO) && (s->type->op == FUNCTION)) class = "function"; /* if (s->type && s->type->op == FUNCTION) printf( "%d\n", s->sclass ); */ else if (s->sclass == ENUM) class = "enum-ident"; fprintf( out, "(%s \"%s\" \"%s\" ", class, (s->src.file ? s->src.file : ""), s->name ); if (s->sclass == ENUM) fprintf( out, "%d", s->u.value ); else { fprintf( out, "\n\t" ); print_type( s->type, out, 0 ); } if (strcmp( class, "type" ) != 0) switch (s->sclass) { case STATIC : fprintf( out, " (static)" ); break; case EXTERN : fprintf( out, " (extern)" ); break; default : fprintf( out, " ()" ); break; } fprintf( out, ")\n", out ); } void print_tag( Symbol s, void *args ) { FILE *out = (FILE*)args; char *fn; Symbol *p; if (!s->type) return; fn = (s->src.file ? s->src.file : ""); if (s->type->op == UNION) fprintf( out, "(union \"%s\" \"%s\"", fn, s->name ); else if (s->type->op == STRUCT) fprintf( out, "(struct \"%s\" \"%s\"", fn, s->name ); else if (s->type->op == ENUM) { /* FIXME: print tags and values. */ fprintf( out, "(enum \"%s\" \"%s\" (", fn, s->name ); for ( p = s->u.idlist ; *p ; p++ ) fprintf( out, "(\"%s\" %d)", (*p)->name, (*p)->u.value ); fprintf( out, "))\n" ); return; } else return; fprintf( out, "\n\t(" ); print_fields( s, out ); fprintf( out, "))\n" ); } void do_ffigen() { FILE *fp; #if 0 if ((fp = fopen( "SYMBOLS", "w" )) == 0) error( "can't open SYMBOLS" ); #else fp = stdout; #endif foreach( globals, GLOBAL, print_global, (void*)fp ); fflush( fp ); foreach( types, GLOBAL, print_tag, (void*)fp ); fclose( fp ); }