
/* PDC Compiler - A Freely Distributable C Compiler for the Amiga
 *                Based upon prior work by Matthew Brandt and Jeff Lydiatt.
 *
 * PDC Compiler release 3.3 Copyright (C) 1989 Paul Petersen and Lionel Hummel.
 * PDC Software Distribution (C) 1989 Lionel Hummel and Paul Petersen.
 *
 * This code is freely redistributable upon the conditions that this 
 * notice remains intact and that modified versions of this file not be 
 * distributed as part of the PDC Software Distribution without the express
 * consent of the copyright holders.
 */

/*
 * List.c
 * 
 * Generates a verbose listing of ACC's results from parsing the source.
 */

#include    <stdio.h>
#include    "C.h"
#include    "Expr.h"
#include    "Gen.h"
#include    "Cglbdec.h"

void   list_table();
extern char    *itoa();

void
put_sc(scl)
    enum e_sc       scl;
{
    switch (scl) {
    case sc_static:
        fputs("Static      ", list);
        break;
    case sc_auto:
        fputs("Auto        ", list);
        break;
    case sc_global:
        fputs("Global      ", list);
        break;
    case sc_external:
        fputs("External    ", list);
        break;
    case sc_type:
        fputs("Type        ", list);
        break;
    case sc_const:
        fputs("Constant    ", list);
        break;
    case sc_member:
        fputs("Member      ", list);
        break;
    case sc_proto:
        fputs("Prototype   ", list);
        break;
    case sc_parameter:
        fputs("Parameter   ", list);
        break;
    case sc_label:
        fputs("Label", list);
        break;
    case sc_ulabel:
        fputs("Undefined label", list);
        break;
    }
}

void
put_ty(tp)
    TYP            *tp;
{
    if (tp == NULL)
        return;
    switch (tp->type) {
    case bt_char:
        fputs("Char", list);
        break;
    case bt_uchar:
        fputs("unsigned Char", list);
        break;
    case bt_short:
        fputs("Short", list);
        break;
    case bt_ushort:
        fputs("unsigned Short", list);
        break;
    case bt_enum:
        fputs("enum ", list);
        goto ucont;
    case bt_long:
        fputs("Long", list);
        break;
    case bt_unsigned:
        fputs("unsigned long", list);
        break;
    case bt_float:
        fputs("Float", list);
        break;
    case bt_double:
        fputs("Double", list);
        break;
    case bt_pointer:
        if (tp->val_flag == 0)
            fputs("Pointer to ", list);
        else
            fputs("Array of ", list);
        put_ty(tp->btp);
        break;
    case bt_union:
        fputs("union ", list);
        goto ucont;
    case bt_struct:
        fputs("struct ", list);
ucont:      if (tp->sname == NULL)
            fputs("<no name> ", list);
        else {
            fputs(tp->sname, list);
            fputs(" ", list);
        }
        break;
    case bt_typedef:
        fputs("typedef ", list);
        goto ucont;
    case bt_ifunc:
    case bt_func:
        fputs("Function returning ", list);
        put_ty(tp->btp);
        break;
    }
}

void
list_var(sp, i)
    SYM            *sp;
    int             i;
{
    int             j, k;
    char           *snum, *disp;

    if (Options.List) {
        for (j = i; j; --j)
            fputs("    ", list);
        disp = sp->name;
        if (disp == NULL)
            disp = "(empty)";
        k = strlen(disp);
        fputs(disp, list);
        while (k++ < 10)
            fputs(" ", list);
        fputs(" = ", list);
        snum = itoa(sp->value.u);
        k = strlen(snum);
        while (k++ < 8)
            fputs(" ", list);
        fputs(snum, list);
        fputs(" ", list);
        put_sc(sp->storage_class);
        put_ty(sp->tp);
        fputs("\n", list);
    }
    if (sp->storage_class == sc_external) {
        if (strncmp("__BUILTIN_", sp->name, 10) != 0) {
            if (strncmp("__LIBCALL_", sp->name, 10) != 0) {
                if (sp->value.i != 0) { /* Don't do xref if not used */
                    if (sp->storage_type == sc_library)
                        fputs("\tXREF\t.", output);
                    else
                        fputs("\tXREF\t_", output);
                    fputs(sp->name, output);
                    fputs("\n", output);
                }
            }
        }
    }
    else if (sp->storage_class == sc_global) {
        if (sp->tp == NULL || sp->tp->type != bt_typedef) {
            if (strncmp("__BUILTIN_", sp->name, 10) != 0) {
                if (strncmp("__LIBCALL_", sp->name, 10) != 0) {
                    fputs("\tXDEF\t_", output);
                    fputs(sp->name, output);
                    fputs("\n", output);
                }
            }
        }
    }
    if (sp->tp == NULL)
        return;
    if ((sp->tp->type == bt_struct || sp->tp->type == bt_union) &&
        sp->storage_class == sc_type)
        list_table(&(sp->tp->lst), i + 1);
}

void
list_table(t, i)
    TABLE          *t;
    int             i;
{
    SYM            *sp;

    sp = t->head;
    while (sp != NULL) {
        list_var(sp, i);
        sp = sp->next;
    }
}
