static char *keywords[] = { "int",
			    "char",
			    "float",
			    "double",
			    "struct",
			    "union",
			    "long",
			    "short",
			    "unsigned",
			    "auto",
			    "extern",
			    "register",
			    "typedef",
			    "static",
			    "goto",
			    "return",
			    "sizeof",
			    "break",
			    "continue",
			    "if",
			    "else",
			    "for",
			    "do",
			    "while",
			    "switch",
			    "case",
			    "default",
			    "entry",
			    "fortran",
			    "asm" };

char *malloc();
#define NEW(type) ((type *) malloc(sizeof(type)))

struct _def_chain {
  struct _def_chain *link;
  char *name;
  int fxnlike;
  struct _call_chain {
    struct _call_chain *link;
    char *name; } *calls;
  struct ecodeChain {
    struct ecodeChain *link;
    char *name; } *ecodes; };

typedef struct _def_chain DEF_CHAIN;
typedef struct _call_chain CALL_CHAIN;
typedef struct ecodeChain ECODE_CHAIN;

static DEF_CHAIN *defs;
static DEF_CHAIN *last_fxn;
static char *filename;
static int unput_buffer[256];
static int unput_num = 0;
static char *pgm;
static int argc;
static char **argv;


static numIsCalled;
static numIsDefined;
static numStrcmp;
static numInput;
static numUnput;

#define STRCMP(a,b)	(numStrcmp++, strcmp((a),(b)))


int more_input()
{
 char *cp;

 if (++argv,--argc)
  { if (yyin != stdin)
     { fclose(yyin);
     }
    if (STRCMP(argv[0],"-") == 0)
     { yyin = stdin;
       filename = "-";
     }
    else
     { yyin = fopen(argv[0],"r");
       if (yyin == NULL)
	{ fprintf(stderr,"%s: cannot open %s for input\n",pgm,argv[0]);
	  yyin = fopen("/dev/null","r");
	}
       filename = argv[0];
     }
    return(1);
  }
 else
  { return(0);
  }
}
#if 0
int input()
{
 int c;
 static int last = 0;

 numInput++;

 if (unput_num > 0)
  { c = unput_buffer[--unput_num];
  }
 else
  { c = getc(yyin);
    while (feof(yyin))
     { if (! more_input())
	{ return(0);
	}
       c = getc(yyin);
     }
  }
 if (commenting)
  { if ((last == '*') && (c == '/'))
     { commenting = 0;
       last = 0;
     }
    last = c;
    c = ' ';
  }
 if (quoting)
  { if (c == quoting)
     { quoting = 0;
     }
    c = ' ';
  }
 return(c);
}

unput(c)
int c;
{
 numUnput++;
 unput_buffer[unput_num++] = c;
}
#endif

static DEF_CHAIN *sharp_last;

is_sharp_defined(fxn,isfxnlike)
char *fxn;
int isfxnlike;
{
 sharp_last = last_fxn;
 is_defined(fxn,isfxnlike);
}

end_sharp_define()
{
 last_fxn = sharp_last;
}

is_defined(fxn,isfxnlike)
char *fxn;
int isfxnlike;
{
 DEF_CHAIN *dcp;
 DEF_CHAIN *dcp2;

 numIsDefined++;

 for (dcp=defs;dcp;dcp=dcp->link)
  { if (STRCMP(dcp->name,fxn) == 0)
     { last_fxn = dcp;
       return;
     }
  }
 dcp2 = last_fxn = NEW(DEF_CHAIN);
 dcp2->link = defs;
 defs = dcp2;
 dcp2->fxnlike = isfxnlike;
 dcp2->name = malloc(strlen(fxn)+3+strlen(filename)+1);
 strcpy(dcp2->name,fxn);
 strcat(dcp2->name," : ");
 strcat(dcp2->name,filename);
 dcp2->calls = 0;
 dcp2->ecodes = 0;
}

static int errorMsgCalled = 0;

is_called(fxn)
char *fxn;
{
 CALL_CHAIN *ccp;
 CALL_CHAIN *ccp2;
 int i;

 numIsCalled++;

 errorMsgCalled = !(strcmp ("errorMsg", fxn));

 for (i=0;i<(sizeof(keywords)/sizeof(keywords[0]));i++)
  { if (keywords[i][0] == fxn[0] && STRCMP(keywords[i],fxn) == 0)
     { return;
     }
  }
 for (ccp=last_fxn->calls;ccp;ccp=ccp->link)
  { if (ccp->name[0] == fxn[0] && STRCMP(ccp->name,fxn) == 0)
     { return;
     }
  }
 ccp2 = NEW(CALL_CHAIN);
 ccp2->link = last_fxn->calls;
 last_fxn->calls = ccp2;
 ccp2->name = malloc(strlen(fxn)+1);
 strcpy(ccp2->name,fxn);
}

main(Argc,Argv)
int Argc;
char **Argv;
{
 char c;
 DEF_CHAIN *dcp;
 CALL_CHAIN *ccp;
 ECODE_CHAIN *ecodes;

 argc = Argc;
 argv = Argv;
 pgm = *argv;
 if (argc == 1)
  { yyin = stdin;
    filename = "-";
  }
 else
  { yyin = stdin;
    more_input();
  }
 brace_level = 0;
 commenting = 0;
 quoting = 0;
 defs = 0;
 BEGIN NORM;
 yylex();
 for (dcp=defs;dcp;dcp=dcp->link)
  { if (! dcp->fxnlike) continue;
    printf("%s\n",dcp->name);
    for (ccp=dcp->calls;ccp;ccp=ccp->link)
     { printf("  %s\n",ccp->name);
     }
    printf ("ERRORS:\n");
    for (ecodes=dcp->ecodes;ecodes;ecodes=ecodes->link)
     { printf("  %s\n",ecodes->name);
     }
    if (dcp->link)
     { putchar('\n');
     }
  }
 printf ("STATS\n");
 printf ("isDefined %d\n", numIsDefined);
 printf ("isCalled %d\n", numIsCalled);
 printf ("strcmp %d\n", numStrcmp);
 printf ("input %d\n", numInput);
 printf ("unput %d\n", numUnput);
}

yywrap()
{
	if (!more_input())
	 { return (1);
	 }
	else
	 { return(0);
	 }
}

errorUsed (s)
char *s;
{
       struct ecodeChain *ecodes;

       if (!errorMsgCalled)
	{ return;
	}
       errorMsgCalled = 0;

       for (ecodes=last_fxn->ecodes;ecodes;ecodes=ecodes->link)
	{ if (ecodes->name[0] == s[0] && STRCMP(ecodes->name,s) == 0)
	   { return;
	   }
	}
       ecodes = NEW(ECODE_CHAIN);
       ecodes->link = last_fxn->ecodes;
       last_fxn->ecodes = ecodes;
       ecodes->name = malloc(strlen(s)+1);
       strcpy(ecodes->name,s);
}

	
