/* 
   Copyright 1994-2003 Free Software Foundation, Inc.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
   02111-1307, USA.  

   You may contact the author at:

   mailto::camille@bluegrass.net

   or by snail mail at:

   David Lindauer
   850 Washburn Ave Apt 99
   Louisville, KY 40222
*/
/* 
 * Listing file
 */
#include        <stdio.h>
#include				<string.h>
#include        "lists.h"
#include        "expr.h"
#include        "c.h"

extern int prm_listfile;
extern HASHREC **globalhash;
extern FILE *listFile;
extern TABLE *gsyms;
extern char *registers[];

/* Unnamed structure tags */
char *tn_unnamed = "<no name> ";


static char * unmangledname(char *str)
{
	static char name[40];
	unmangle(name,str);
	return name;
}
/* Put the storage class */
void put_sc(int scl)
{
  if (!prm_listfile)
    return;
       switch(scl) {
                case sc_static:
                        fprintf(listFile,"Static      ");
                        break;
                case sc_auto:
                        fprintf(listFile,"Auto        ");
                        break;
                case sc_autoreg:
                case sc_memberreg:
                        fprintf(listFile,"Register    ");
                        break;
                case sc_global:
                        fprintf(listFile,"Global      ");
                        break;
                case sc_abs:
                        fprintf(listFile,"Absolute    ");
                        break;
                case sc_external:
                case sc_externalfunc:
                        fprintf(listFile,"External    ");
                        break;
                case sc_type:
                        fprintf(listFile,"Type        ");
                        break;
                case sc_const:
                        fprintf(listFile,"Constant    ");
                        break;
                case sc_member:
                        fprintf(listFile,"Member      ");
                        break;
                case sc_label:
                        fprintf(listFile,"Label       ");
                        break;
                case sc_ulabel:
                        fprintf(listFile,"Undefined label");
                        break;
                }
}

/* Put the type */
void put_ty(TYP *tp)
{       if((tp == 0) || (!prm_listfile))
                return;
        switch(tp->type) {
								case bt_matchall:
												fprintf(listFile,"Undefined");
												break;
                case bt_char:
                        fprintf(listFile,"Char");
                        break;
                case bt_bool:
                        fprintf(listFile,"Bool");
                        break;
                case bt_short:
                        fprintf(listFile,"Short");
                        break;
                case bt_enum:
                        fprintf(listFile,"enum ");
                        goto ucont;
                case bt_long:
                        fprintf(listFile,"Long");
                        break;
								case bt_int:
												fprintf(listFile,"Int");
												break ;
								case bt_unsigned:
												fprintf(listFile,"Unsigned");
												break ;
                case bt_unsignedlong:
                        fprintf(listFile,"Unsigned Long");
                        break;
                case bt_fcomplex:
                        fprintf(listFile,"Float Complex");
                        break;
                case bt_rcomplex:
                        fprintf(listFile,"Double Complex");
                        break;
                case bt_lrcomplex:
                        fprintf(listFile,"Long Double Complex");
                        break;
                case bt_float:
                        fprintf(listFile,"Float");
                        break;
                case bt_double:
                        fprintf(listFile,"Double");
                        break;
                case bt_longdouble:
                        fprintf(listFile,"Long Double");
                        break;
                case bt_pointer:
                        if( tp->val_flag == 0)
                                fprintf(listFile,"Pointer to ");
                        else
                                fprintf(listFile,"Array of ");
                        put_ty(tp->btp);
                        break;
                case bt_union:
                        fprintf(listFile,"union ");
                        goto ucont;
#ifdef CPLUSPLUS
								case bt_memberptr:
												fprintf(listFile,"Member Pointer to %s::",tp->sp->name);
												put_ty(tp->btp->btp);
												break;
								case bt_class:
                        fprintf(listFile,"class ");
                        goto ucont;
#endif
                case bt_struct:
                        fprintf(listFile,"struct ");
ucont:                  if(tp->sp == 0)
                                fprintf(listFile,tn_unnamed);
                        else
                                fprintf(listFile,"%s ",unmangledname(tp->sp->name));
                        break;
								case bt_void:
												fprintf(listFile,"Void");
												break;
                case bt_ifunc:
                case bt_func:
                        fprintf(listFile,"Function returning ");
                        put_ty(tp->btp);
                        break;
                }
	if (tp->startbit != -1)
		fprintf(listFile,"  Bits %d to %d",tp->startbit,tp->startbit+tp->bits-1);
}
/* List a variable */
void list_var(SYM *sp, int i)
{       int     j;
				long val;
				if (!prm_listfile)
					return;
        for(j = i; j; --j)
                fprintf(listFile,"    ");
				if ((sp->storage_class == sc_auto || sp->storage_class == sc_autoreg) && !sp->inreg)
					val = (long)getautoval(sp->value.i);
				else
					val = sp->value.u;
				if (sp->inreg)
        	fprintf(listFile,"%-10s = Register %-3s   ",unmangledname(sp->name),registers[-val]);
				else
        	fprintf(listFile,"%-10s = %08x     ",unmangledname(sp->name),val);
        put_sc(sp->storage_class);
        put_ty(sp->tp);
        fprintf(listFile,"\n");
        if(sp->tp == 0)
                return;
        if (isstructured(sp->tp) &&
                sp->storage_class == sc_type)
                list_table(&(sp->tp->lst),i+1);
}

/* List an entire table */
void list_table(TABLE *t,int j)
{       SYM     *sp;
				int i;
				if (!prm_listfile)
					return;
				if (t == gsyms) {
					for (i=0; i < HASHTABLESIZE; i++) {
						if ((sp=((SYM **) t)[i]) != 0) {
							while (sp) {
								list_var(sp,j);
        	 			sp = sp->next;
							}
						}
					}
				}
				else {
        	sp = t->head;
        	while(sp != NULL) {
                list_var(sp,j);
                sp = sp->next;
                }
				}
			
}