ffigen/ffigen.c

181 lines
4.7 KiB
C

/* 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 <stdio.h>
#include <ctype.h>
#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 );
}