181 lines
4.7 KiB
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 );
|
|
}
|
|
|