File indexing completed on 2025-02-23 04:46:17

0001 /* ------------------------------------------------------------------------
0002 @NAME       : parse_auxiliary.c
0003 @INPUT      : 
0004 @OUTPUT     : 
0005 @RETURNS    : 
0006 @DESCRIPTION: Anything needed by the parser that's too hairy to go in the
0007               grammar itself.  Currently, just stuff needed for generating
0008               syntax errors. (See error.c for how they're actually
0009               printed.)
0010 @GLOBALS    : 
0011 @CALLS      : 
0012 @CALLERS    : 
0013 @CREATED    : 1996/08/07, Greg Ward
0014 @MODIFIED   : 
0015 @VERSION    : $Id: parse_auxiliary.c,v 1.20 1999/11/29 01:13:10 greg Rel $
0016 @COPYRIGHT  : Copyright (c) 1996-99 by Gregory P. Ward.  All rights reserved.
0017 
0018               This file is part of the btparse library.  This library is
0019               free software; you can redistribute it and/or modify it under
0020               the terms of the GNU General Public License as
0021               published by the Free Software Foundation; either version 2
0022               of the License, or (at your option) any later version.
0023 -------------------------------------------------------------------------- */
0024 
0025 /*#include "bt_config.h"*/
0026 #include "stdpccts.h"
0027 #include "error.h"
0028 #include "lex_auxiliary.h"
0029 #include "parse_auxiliary.h"
0030 /*#include "my_dmalloc.h"*/
0031 
0032 extern const char * InputFilename;            /* from input.c */
0033 
0034 GEN_PRIVATE_ERRFUNC (syntax_error, (const char * fmt, ...),
0035                      BTERR_SYNTAX, InputFilename, zzline, NULL, -1, fmt)
0036 
0037 
0038 /* this is stolen from PCCTS' err.h */
0039 static SetWordType bitmask[] = 
0040 {
0041     0x00000001, 0x00000002, 0x00000004, 0x00000008,
0042     0x00000010, 0x00000020, 0x00000040, 0x00000080
0043 };
0044 
0045 static struct 
0046 {
0047    int    token;
0048    const char  *new_name;
0049 } new_tokens[] = 
0050 {
0051    { AT,         "\"@\"" },
0052    { NAME,       "name (entry type, key, field, or macro name)" },
0053    { LBRACE,     "left brace (\"{\")" },
0054    { RBRACE,     "right brace (\"}\")" },
0055    { ENTRY_OPEN, "start of entry (\"{\" or \"(\")" },
0056    { ENTRY_CLOSE,"end of entry (\"}\" or \")\")" },
0057    { EQUALS,     "\"=\"" },
0058    { HASH,       "\"#\"" },
0059    { COMMA,      "\",\"" },
0060    { NUMBER,     "number" },
0061    { STRING,     "quoted string ({...} or \"...\")" }
0062 };
0063 
0064 
0065 #ifdef CLEVER_TOKEN_STUFF
0066 char **token_names;
0067 #endif
0068 
0069 
0070 void
0071 fix_token_names (void)
0072 {
0073    int    i;
0074    int    num_replace;
0075 
0076 #ifdef CLEVER_TOKEN_STUFF               /* clever, but it doesn't work... */
0077    /* arg! this doesn't work because I don't know how to find out the
0078     * number of tokens
0079     */
0080 
0081    int    num_tok;
0082 
0083    num_tok = (sizeof(zztokens) / sizeof(*zztokens));
0084    sizeof (zztokens);
0085    sizeof (*zztokens);
0086    token_names = (char **) malloc (sizeof (char *) * num_tok);
0087 
0088    for (i = 0; i < num_tok; i++)
0089    {
0090       token_names[i] = zztokens[i];
0091    }
0092 #endif
0093 
0094    num_replace = (sizeof(new_tokens) / sizeof(*new_tokens));
0095    for (i = 0; i < num_replace; i++)
0096    {
0097       const char  *new = new_tokens[i].new_name;
0098       const char **old = zztokens + new_tokens[i].token;
0099 
0100       *old = new;
0101    }
0102 }
0103 
0104 
0105 #ifdef USER_ZZSYN
0106 
0107 static void
0108 append_token_set (char *msg, SetWordType *a)
0109 {
0110    SetWordType *p = a;
0111    SetWordType *endp = &(p[zzSET_SIZE]);
0112    unsigned e = 0;
0113    int      tokens_printed = 0;
0114    
0115    do 
0116    {
0117       SetWordType t = *p;
0118       SetWordType *b = &(bitmask[0]);
0119       do
0120       {
0121          if (t & *b)
0122          {
0123             strcat (msg, zztokens[e]);
0124             tokens_printed++;
0125             if (tokens_printed < zzset_deg (a) - 1)
0126                strcat (msg, ", ");
0127             else if (tokens_printed == zzset_deg (a) - 1)
0128                strcat (msg, " or ");
0129          }
0130          e++;
0131       } while (++b < &(bitmask[sizeof(SetWordType)*8]));
0132    } while (++p < endp);
0133 }
0134 
0135 
0136 void
0137 zzsyn(const char *  text,
0138       int           tok, 
0139       char *        egroup,
0140       SetWordType * eset,
0141       int           etok,
0142       int           k,
0143       const char *  bad_text)
0144 {
0145    static char    msg [MAX_ERROR];
0146    int            len;
0147 
0148 #ifndef ALLOW_WARNINGS
0149    text = NULL;                         /* avoid "unused parameter" warning */
0150 #endif
0151 
0152    /* Initial message: give location of error */
0153 
0154    msg[0] = (char) 0;           /* make sure string is empty to start! */
0155    if (tok == zzEOF_TOKEN)
0156       strcat (msg, "at end of input");
0157    else
0158       sprintf (msg, "found \"%s\"", bad_text);
0159 
0160    len = strlen (msg);
0161 
0162    
0163    /* Caller supplied neither a single token nor set of tokens expected... */
0164 
0165    if (!etok && !eset)
0166    {
0167       syntax_error (msg);
0168       return;
0169    }
0170    else
0171    {
0172       strcat (msg, ", ");
0173       len += 2;
0174    }
0175 
0176    
0177    /* I'm not quite sure what this is all about, or where k would be != 1... */
0178    
0179    if (k != 1)
0180    {
0181       sprintf (msg+len, "; \"%s\" not", bad_text);
0182       if (zzset_deg (eset) > 1) strcat (msg, " in");
0183       len = strlen (msg);
0184    }
0185 
0186 
0187    /* This is the code that usually gets run */
0188    
0189    if (zzset_deg (eset) > 0) 
0190    {
0191       if (zzset_deg (eset) == 1)
0192          strcat (msg, "expected ");
0193       else
0194          strcat (msg, "expected one of: ");
0195 
0196       append_token_set (msg, eset);
0197    }
0198    else
0199    {
0200       sprintf (msg+len, "expected %s", zztokens[etok]);
0201       if (etok == ENTRY_CLOSE)
0202       {
0203          strcat (msg, " (skipping to next \"@\")");
0204          initialize_lexer_state ();
0205       }
0206    }
0207 
0208    len = strlen (msg);
0209    if (egroup && strlen (egroup) > 0) 
0210       sprintf (msg+len, " in %s", egroup);
0211 
0212    syntax_error (msg);
0213 
0214 }
0215 #endif /* USER_ZZSYN */
0216 
0217 
0218 void
0219 check_field_name (AST * field)
0220 {
0221    char * name;
0222 
0223    if (! field || field->nodetype != BTAST_FIELD)
0224       return;
0225 
0226    name = field->text;
0227    if (strchr ("0123456789", name[0]))
0228       syntax_error ("invalid field name \"%s\": cannot start with digit",
0229                     name);
0230 }
0231 
0232 
0233 #ifdef STACK_DUMP_CODE
0234 
0235 static void
0236 show_ast_stack_elem (int num)
0237 {
0238    extern const char *nodetype_names[];       /* nicked from bibtex_ast.c */
0239    /*   bt_nodetype    nodetype;
0240    bt_metatype    metatype; */
0241    AST   *elem;
0242 
0243    elem = zzastStack[num];
0244    printf ("zzastStack[%3d] = ", num);
0245    if (elem)
0246    {
0247       /*      get_node_type (elem, &nodetype, &metatype); */
0248       if (elem->nodetype <= BTAST_MACRO)
0249       {
0250          printf ("{ %s: \"%s\" (line %d, char %d) }\n",
0251                  nodetype_names[elem->nodetype], 
0252                  elem->text, elem->line, elem->offset);
0253       }
0254       else
0255       {
0256          printf ("bogus node (uninitialized?)\n");
0257       }
0258    }
0259    else
0260    {
0261       printf ("NULL\n");
0262    }
0263 }
0264 
0265 
0266 static void
0267 show_ast_stack_top (char *label)
0268 {
0269    if (label)
0270       printf ("%s: ast stack top: ", label);
0271    else
0272       printf ("ast stack top: ");
0273    show_ast_stack_elem (zzast_sp);
0274 }
0275 
0276 
0277 static void
0278 dump_ast_stack (char *label)
0279 {
0280    int   i;
0281 
0282    if (label)
0283       printf ("%s: complete ast stack:\n", label);
0284    else
0285       printf ("complete ast stack:\n");
0286 
0287    for (i = zzast_sp; i < ZZAST_STACKSIZE; i++)
0288    {
0289       printf ("  ");
0290       show_ast_stack_elem (i);
0291    }   
0292 }
0293 
0294 
0295 static void
0296 show_attrib_stack_elem (int num)
0297 {
0298    Attrib   elem;
0299 
0300    elem = zzaStack[num];
0301    printf ("zzaStack[%3d] = ", num);
0302    printf ("{ \"%s\" (token %d (%s), line %d, char %d) }\n",
0303            elem.text, elem.token, zztokens[elem.token],
0304            elem.line, elem.offset);
0305 }
0306 
0307 
0308 static void
0309 show_attrib_stack_top (char *label)
0310 {
0311    if (label)
0312       printf ("%s: attrib stack top: ", label);
0313    else
0314       printf ("attrib stack top: ");
0315    show_attrib_stack_elem (zzasp);
0316 }
0317 
0318 
0319 static void
0320 dump_attrib_stack (char *label)
0321 {
0322    int   i;
0323 
0324    if (label)
0325       printf ("%s: complete attrib stack:\n", label);
0326    else
0327       printf ("complete attrib stack:\n");
0328 
0329    for (i = zzasp; i < ZZA_STACKSIZE; i++)
0330    {
0331       printf ("  ");
0332       show_attrib_stack_elem (i);
0333    }   
0334 }
0335 
0336 #endif /* STACK_DUMP_CODE */