
/*	C functions definitions	*/

#include <stdio.h>
#include "cc65.h"
#include "cclex.h"

extern char * Lmalloc();
extern struct hashent * decl();
extern struct hashent * declare();
#ifndef M6502
extern int outcnt;
extern int stats;
#endif

/*
  Parse function dummy arguments.
*/
funargs()
{
  n_funargs = 0;		/* -- jrd */

  if (curtok == RPAREN)
    {
      gettok();
      return;
    }
  if (lovptr != 0)
    {
      fatal("err 4");
    }

  while (1)
    {
      if (curtok == IDENT)
	{
	  addloc((struct hashent *) curval, NULL, SC_STACK, 0);
	  ++n_funargs;		/* -- jrd.  count the arg */
	  gettok();
	}
      else
	{
	  Syntax();
	}
      if (curtok == COMMA)
	{
	  gettok();
	}
      else if (curtok == RPAREN)
	{
	  gettok();
	  break;
	}
      else
	{
	  Syntax();
	}
    }
}

/*
  declargs( )
  Process argument declarations.
*/
declargs()
{
  int i;
  char * p;
  struct hashent * psym;
  struct hashent * sadr;
  int stoff;
  char tarray[MAXTYPELEN];
  char * tptr;
  int type;

  while ((curtok != LCURLY)	/* && (curtok != ASM) */ )
    {
      getsclass(1, SC_STACK);
      type = gettype(INT, &sadr);
      while (1)
	{
	  absdecl = 0;
	  if ((psym = declare(tarray, type, sadr)) != NULL)
	    {
	      if (psym->h_loc == 0)
		{
		  Error("declaration of parameter not in argument list");
		  addloc(psym, tarray, SC_STACK, 0);
		}
	      else
		{
		  tptr = Lmalloc(strlen(tarray) + 1);
		  strcpy(tptr, tarray);
		  if (tptr[0] == T_ARRAY)
		    {
		      (tptr += 3)[0] = T_PTR;
		    }
		  psym->h_ltptr = tptr;
		}
	    }

	  if (curtok != COMMA)
	    break;
	  gettok();
	}
      if (curtok == SEMI)
	{
	  gettok();
	}
    }

  /*
    Assign offsets and default undeclared arguments to int.
  */
  tarray[0] = T_INT;
  tarray[1] = '\0';
  stoff = 2;
  for (i = lovptr - 1; i >= 0; --i)
    {
      psym = lvtab[i];
      tptr = psym->h_ltptr;
      if (tptr == NULL)
	{
	  /*
	   * default to "int"
	   */
	  tptr = Lmalloc(2);
	  strcpy(tptr, tarray);
	  psym->h_ltptr = tptr;
	}
      psym->h_ldata = stoff;
      stoff += (SizeOf(tarray) + 1) & (~1);
    }
}

/*
  newfunc( psym )
  Parse argument declarations and function body.
*/
newfunc(psym)
struct hashent * psym;
{
#ifndef M6502
  int sbyte;
#endif
#ifdef M6502
  if (verbose)
    {
      printmsg("\034\n\234%s\n", psym->h_name);
    }
#endif
  psym->h_glb |= SC_DEFINED;
  /* this busted??     outcdf(psym->h_gdata); -- jrd */
  startfun(psym->h_name);	/* start a function preamble */

  declargs();

#ifdef old_cruft
  if (curtok == ASM)
    {
      struct expent lval;

      gettok();
      /*
	outbyte(0);
	constexp(&lval);
	outconst(lval.e_flags, lval.e_const, 0);
	*/
      ns();
    }
  else
#endif
    {
      if (curtok != LCURLY)
	{
	  Syntax();
	}
      oursp = 0;
#ifndef M6502
      sbyte = outcnt;
#endif
      if (!compound())
	{
	  ret();
	  dumplits();
	  n_funargs = -1;	/* reset arg counter */
	}
#ifndef M6502
      if (stats)
	{
	  printf("%s: %d bytes\n", psym->h_name, outcnt - sbyte);
	}
#endif
    }
}

/*
  declloc()
  Declare local variables.
*/
declloc()
{
  int offs;
  int lab;
  int varlab;
  char * p;
  struct hashent * psym;
  struct hashent * sadr;
  int sc;
  char tarray[MAXTYPELEN];
  int type;

  offs = oursp;
  while (1)
    {
      sc = getsclass(1, SC_STACK);
      if ((type = gettype(0, &sadr)) == 0)
	break;

      while (1)
	{
	  absdecl = 0;
	  psym = declare(tarray, type, sadr);

	  {
	    int siz;

	    if (tarray[0] != T_FUNC)
	      siz = SizeOf(tarray);
	    else
	      siz = 2;
	    addloc(psym, tarray, sc, offs - siz);
	  }
	  if (tarray[0] != T_FUNC)
	    {
	      if (sc & SC_STACK)
		{
		  offs -= SizeOf(tarray);
		}
	      else if (sc == SC_STATIC)
		{
		  jump(lab = getlabel());
		  outcdf(psym->h_ldata = getlabel());
		  outsp(SizeOf(tarray));
		  outcdf(lab);
		}
	    }

	  if (curtok != COMMA)
	    break;
	  gettok();
	}
      if (curtok == SEMI)
	{
	  gettok();
	}
    }
  oursp = modstk(offs);
}
