/* ------------------------------------------------------------------------
@NAME       : parse_auxiliary.c
@INPUT      : 
@OUTPUT     : 
@RETURNS    : 
@DESCRIPTION: Anything needed by the parser that's too hairy to go in the
              grammar itself.  Currently, just stuff needed for generating
              syntax errors. (See error.c for how they're actually
              printed.)
@GLOBALS    : 
@CALLS      : 
@CALLERS    : 
@CREATED    : 1996/08/07, Greg Ward
@MODIFIED   : 
@VERSION    : $Id: parse_auxiliary.c,v 1.13 1997/09/10 02:02:07 greg Exp $
@COPYRIGHT  : Copyright (c) 1996-97 by Gregory P. Ward.  All rights reserved.

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

#include "bt_config.h"
#include "stdpccts.h"
#include "error.h"
#include "lex_auxiliary.h"
#include "parse_auxiliary.h"
#include "my_dmalloc.h"

/* this is stolen from PCCTS' err.h */
static SetWordType bitmask[] = 
{
    0x00000001, 0x00000002, 0x00000004, 0x00000008,
    0x00000010, 0x00000020, 0x00000040, 0x00000080
};

static struct 
{
   int    token;
   char  *new_name;
} new_tokens[] = 
{
   { AT,         "\"@\"" },
   { NAME,       "name (entry type, key, field, or macro name)" },
   { LBRACE,     "left brace (\"{\")" },
   { RBRACE,     "right brace (\"}\")" },
   { ENTRY_OPEN, "start of entry (\"{\" or \"(\")" },
   { ENTRY_CLOSE,"end of entry (\"}\" or \")\")" },
   { EQUALS,     "\"=\"" },
   { HASH,       "\"#\"" },
   { COMMA,      "\",\"" },
   { NUMBER,     "number" },
   { STRING,     "quoted string ({...} or \"...\")" }
};

#if 0
char **token_names;
#endif

void
fix_token_names (void)
{
   int    i;
   int    num_replace;

#if 0
   /* arg! this doesn't work because I don't know how to find out the
    * number of tokens
    */

   int    num_tok;

   num_tok = (sizeof(zztokens) / sizeof(*zztokens));
   sizeof (zztokens);
   sizeof (*zztokens);
   token_names = (char **) malloc (sizeof (char *) * num_tok);

   for (i = 0; i < num_tok; i++)
   {
      token_names[i] = zztokens[i];
   }
#endif

   num_replace = (sizeof(new_tokens) / sizeof(*new_tokens));
   for (i = 0; i < num_replace; i++)
   {
      char  *new = new_tokens[i].new_name;
      char **old = zztokens + new_tokens[i].token;

      *old = new;
   }
}


#ifdef USER_ZZSYN

static void
append_token_set (char *msg, SetWordType *a)
{
   SetWordType *p = a;
   SetWordType *endp = &(p[zzSET_SIZE]);
   unsigned e = 0;
   int      tokens_printed = 0;
   
   do 
   {
      SetWordType t = *p;
      SetWordType *b = &(bitmask[0]);
      do
      {
         if (t & *b)
         {
            strcat (msg, zztokens[e]);
            tokens_printed++;
            if (tokens_printed < zzset_deg (a) - 1)
               strcat (msg, ", ");
            else if (tokens_printed == zzset_deg (a) - 1)
               strcat (msg, " or ");
         }
         e++;
      } while (++b < &(bitmask[sizeof(SetWordType)*8]));
   } while (++p < endp);
}


void
zzsyn(char *text, int tok, 
      char *egroup, SetWordType *eset, int etok,
      int k, char *bad_text)
{
#if 0
   extern char    InputFilename[]; /* from bibparse.c (main program) */
   extern int     SyntaxErrors;
#endif
   static char    msg [MAX_ERROR];
   int            len;

   /* Initial message: give location of error */

   msg[0] = (char) 0;           /* make sure string is empty to start! */
   if (tok == zzEOF_TOKEN)
      strcat (msg, "at end of input, ");
   else
      sprintf (msg, "found \"%s\", ", bad_text);

   len = strlen (msg);

   
   /* Caller supplied neither a single token nor set of tokens expected... */

   if (!etok && !eset)
   {
      syntax_error ("%s", msg);
      return;
   }

   
   /* I'm not quite sure what this is all about, or where k would be != 1... */
   
   if (k != 1)
   {
      sprintf (msg+len, "; \"%s\" not", bad_text);
      if (zzset_deg (eset) > 1) strcat (msg, " in");
      len = strlen (msg);
   }


   /* This is the code that usually gets run */
   
   if (zzset_deg (eset) > 0) 
   {
      if (zzset_deg (eset) == 1)
         strcat (msg, "expected ");
      else
         strcat (msg, "expected one of: ");

      append_token_set (msg, eset);
   }
   else
   {
      sprintf (msg+len, "expected %s", zztokens[etok]);
      if (etok == ENTRY_CLOSE)
      {
         strcat (msg, " (skipping to next \"@\")");
         initialize_lexer_state ();
      }
   }

   len = strlen (msg);
   if (egroup && strlen (egroup) > 0) 
      sprintf (msg+len, " in %s", egroup);

   syntax_error ("%s", msg);

}
#endif /* USER_ZZSYN */


void show_ast_stack_elem (int num)
{
   extern char *nodetype_names[];       /* nicked from bibtex_ast.c */
   /*   bt_nodetype_t    nodetype;
   bt_metatype_t    metatype; */
   AST   *elem;

   elem = zzastStack[num];
   printf ("zzastStack[%3d] = ", num);
   if (elem)
   {
      /*      get_node_type (elem, &nodetype, &metatype); */
      if (elem->nodetype >= BTAST_BOGUS && elem->nodetype <= BTAST_MACRO)
      {
         printf ("{ %s: \"%s\" (line %d, char %d) }\n",
                 nodetype_names[elem->nodetype], 
                 elem->text, elem->line, elem->offset);
      }
      else
      {
         printf ("bogus node (uninitialized?)\n");
      }
   }
   else
   {
      printf ("NULL\n");
   }
}


void show_ast_stack_top (char *label)
{
   if (label)
      printf ("%s: ast stack top: ", label);
   else
      printf ("ast stack top: ");
   show_ast_stack_elem (zzast_sp);
}


void dump_ast_stack (char *label)
{
   int   i;

   if (label)
      printf ("%s: complete ast stack:\n", label);
   else
      printf ("complete ast stack:\n");

   for (i = zzast_sp; i < ZZAST_STACKSIZE; i++)
   {
      printf ("  ");
      show_ast_stack_elem (i);
   }   
}


void show_attrib_stack_elem (int num)
{
   Attrib   elem;

   elem = zzaStack[num];
   printf ("zzaStack[%3d] = ", num);
   printf ("{ \"%s\" (token %d (%s), line %d, char %d) }\n",
           elem.text, elem.token, zztokens[elem.token],
           elem.line, elem.offset);
}


void show_attrib_stack_top (char *label)
{
   if (label)
      printf ("%s: attrib stack top: ", label);
   else
      printf ("attrib stack top: ");
   show_attrib_stack_elem (zzasp);
}


void dump_attrib_stack (char *label)
{
   int   i;

   if (label)
      printf ("%s: complete attrib stack:\n", label);
   else
      printf ("complete attrib stack:\n");

   for (i = zzasp; i < ZZA_STACKSIZE; i++)
   {
      printf ("  ");
      show_attrib_stack_elem (i);
   }   
}
