
/*  A Bison parser, made from parse.y
 by  GNU Bison version 1.25
  */

#define YYBISON 1  /* Identify Bison output.  */

#define	ALLAFFIXES	258
#define	ALTSTRINGCHAR	259
#define	ALTSTRINGTYPE	260
#define	BOUNDARYCHARS	261
#define	COMPOUNDMIN	262
#define	COMPOUNDWORDS	263
#define	CONTROLLED	264
#define	DEFSTRINGTYPE	265
#define	FLAG	266
#define	FLAGMARKER	267
#define	NROFFCHARS	268
#define	OFF	269
#define	ON	270
#define	PREFIXES	271
#define	RANGE	272
#define	SUFFIXES	273
#define	STRING	274
#define	STRINGCHAR	275
#define	TEXCHARS	276
#define	TEXLEFTPAREN	277
#define	TEXRIGHTPAREN	278
#define	TEXLEFTSQUARE	279
#define	TEXRIGHTSQUARE	280
#define	TEXLEFTCURLY	281
#define	TEXRIGHTCURLY	282
#define	TEXLEFTTANGLE	283
#define	TEXRIGHTTANGLE	284
#define	TEXBACKSLASH	285
#define	TEXDOLLAR	286
#define	TEXSTAR	287
#define	TEXDOT	288
#define	TEXPERCENT	289
#define	WORDCHARS	290

#line 1 "parse.y"

/*
 * Copyright 1992, 1993, Geoff Kuenning, Granada Hills, CA
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All modifications to the source code must be clearly marked as
 *    such.  Binary redistributions based on modified source code
 *    must be clearly marked as modified versions in the documentation
 *    and/or other materials provided with the distribution.
 * 4. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgment:
 *      This product includes software developed by Geoff Kuenning and
 *      other unpaid contributors.
 * 5. The name of Geoff Kuenning may not be used to endorse or promote
 *    products derived from this software without specific prior
 *    written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY GEOFF KUENNING AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL GEOFF KUENNING OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * $Log: parse.y,v $
 * Revision 1.52  1994/11/21  07:03:03  geoff
 * Get rid of the last vestiges of the "+" flag option.
 *
 * Revision 1.51  1994/11/02  06:56:13  geoff
 * Remove the anyword feature, which I've decided is a bad idea.
 *
 * Revision 1.50  1994/10/25  05:46:22  geoff
 * Add support for the "+" (any word) flag modifier.
 *
 * Revision 1.49  1994/09/16  04:48:30  geoff
 * Allow more than 128 string characters, by using different types in the
 * appropriate places.
 *
 * Revision 1.48  1994/05/24  05:31:25  geoff
 * Remember to convert the flag bit from a character to a bit number
 * before putting it in the hash file.
 *
 * Revision 1.47  1994/05/24  04:54:33  geoff
 * Improve the error checking for affix flag names, detecting bad flags
 * and duplicates.
 *
 * Revision 1.46  1994/05/22  01:38:02  geoff
 * Don't force flags to uppercase if lowercase flags are legal
 *
 * Revision 1.45  1994/05/17  06:44:17  geoff
 * Add support for controlled compound formation and the COMPOUNDONLY
 * option to affix flags.
 *
 * Revision 1.44  1994/02/07  05:51:03  geoff
 * Fix a place where atoi got the wrong argument type (lint error only)
 *
 * Revision 1.43  1994/01/25  07:12:01  geoff
 * Get rid of all old RCS log lines in preparation for the 3.1 release.
 *
 */

#include <ctype.h>
#include <stdlib.h>
#include "ispell.h"
#include "msgs.h"


#line 85 "parse.y"
typedef union
    {
    int			simple;		/* Simple char or lval from yylex */
    struct
	{
	char *		set;		/* Character set */
	int		complement;	/* NZ if it is a complement set */
	}
			charset;
    unsigned char *	string;		/* String */
    ichar_t *		istr;		/* Internal string */
    struct flagent *	entry;		/* Flag entry */
    } YYSTYPE;
#line 99 "parse.y"


Local int	yylex (void); /* Trivial lexical analyzer */
Local int	kwanalyze (int backslashed, unsigned char * str);
				/* Analyze a possible keyword */
Local void	getqstring (void);
				/* Get (double-)quoted string */
Local void	getrange (void); /* Get a lexical character range */
Local int	backch (void); /* Process a backslashed character */
Local void	yyerror (char * msg);
				/* Print out an error message */
Global Logical	yyopen (char * file);
				/* Open a table file */
Global void	yyinit (void); /* Initialize for parsing */
Local int	grabchar (void);
				/* Get a character and track line number */
Local void	ungrabchar (int ch);
				/* Unget a character, tracking line numbers */
Local int	sufcmp (struct flagent * flag1, struct flagent * flag2);
				/* Compare suffix flags for qsort */
Local int	precmp (struct flagent * flag1, struct flagent * flag2);
				/* Compare prefix flags for qsort */
Local int	addstringchar (unsigned char * str, int lower, int upper);
				/* Add a string character to the table */
Local int	stringcharcmp (char * a, char * b);
				/* Strcmp() done right, for Sun 4's */
#ifdef TBLDEBUG
Local void	tbldump (struct flagent * flagp, int numflags);
				/* Dump a flag table */
Local void	entdump (struct flagent * flagp);
				/* Dump one flag entry */
Local void	setdump (char * setp, int mask);
				/* Dump a set specification */
Local void	subsetdump (char * setp, int mask, int dumpval);
				/* Dump part of a set spec */
#endif

struct kwtab
    {
    char *	kw;		/* Syntactic keyword */
    int		val;		/* Lexical value */
    };

#define TBLINC		10		/* Size to allocate table by */

Local FILE *		aff_file = NULL; /* Input file pointer */
Local int		centnum;	/* Number of entries in curents */
Local int		centsize = 0;	/* Size of alloc'ed space in curents */
Local int		ctypechars;	/* Size of string in current strtype */
Local int		ctypenum = 0;	/* Number of entries in chartypes */
Local int		ctypesize = 0;	/* Size of alloc'ed spc in chartypes */
Local struct flagent * curents;	/* Current flag entry collection */
Local char *		fname = "(stdin)"; /* Current file name */
Local char		lexungrab[MAXSTRINGCHARLEN * 2]; /* Spc for ungrabch */
Local int		lineno = 1;	/* Current line number in file */
Local struct flagent * table;		/* Current table being built */
Local int		tblnum;		/* Numer of entries in table */
Local int		tblsize = 0;	/* Size of the flag table */
Local int		ungrablen;	/* Size of ungrab area */
#include <stdio.h>

#ifndef __cplusplus
#ifndef __STDC__
#define const
#endif
#endif



#define	YYFINAL		128
#define	YYFLAG		-32768
#define	YYNTBASE	43

#define YYTRANSLATE(x) ((unsigned)(x) <= 290 ? yytranslate[x] : 71)

static const char yytranslate[] = {     0,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     8,     2,     5,     3,     7,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     6,     2,     2,
     2,     4,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     9,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     1,     2,    10,    11,    12,
    13,    14,    15,    16,    17,    18,    19,    20,    21,    22,
    23,    24,    25,    26,    27,    28,    29,    30,    31,    32,
    33,    34,    35,    36,    37,    38,    39,    40,    41,    42
};

#if YYDEBUG != 0
static const short yyprhs[] = {     0,
     0,     3,     5,     8,    12,    14,    17,    19,    22,    25,
    27,    30,    33,    35,    38,    42,    45,    48,    51,    54,
    57,    60,    63,    66,    69,    72,    75,    78,    81,    84,
    88,    91,    94,    98,   101,   105,   109,   111,   114,   116,
   118,   121,   125,   128,   131,   134,   137,   141,   144,   147,
   149,   151,   153,   155,   157,   160,   163,   165,   167,   170,
   173,   175,   178,   183,   189,   191,   193,   196,   198,   200,
   202,   205,   209,   216,   223,   229,   230,   232,   234,   237
};

static const short yyrhs[] = {    44,
    59,     0,    59,     0,    45,    46,     0,    45,    46,    48,
     0,    46,     0,    46,    48,     0,    56,     0,    45,    56,
     0,    47,    49,     0,    49,     0,    46,    49,     0,    17,
    51,     0,    50,     0,    48,    50,     0,    42,    57,    57,
     0,    42,    57,     0,    30,    26,     0,    31,    26,     0,
    32,    26,     0,    33,    26,     0,    34,    26,     0,    35,
    26,     0,    36,    26,     0,    37,    26,     0,    38,    26,
     0,    39,    26,     0,    40,    26,     0,    41,    26,     0,
    29,    26,     0,    13,    57,    57,     0,    13,    57,     0,
    27,    26,     0,    27,    26,    26,     0,    12,    51,     0,
    12,    51,    54,     0,    26,    26,    52,     0,    53,     0,
    52,    53,     0,    26,     0,    55,     0,    54,    55,     0,
    11,    26,    26,     0,    20,    26,     0,    28,    26,     0,
    14,    26,     0,    15,    58,     0,    15,    16,    26,     0,
    10,    58,     0,    19,    26,     0,     7,     0,    26,     0,
    24,     0,    22,     0,    21,     0,    60,    61,     0,    61,
    60,     0,    60,     0,    61,     0,    23,    62,     0,    25,
    62,     0,    63,     0,    62,    63,     0,    18,    26,     6,
    66,     0,    18,    64,    26,     6,    66,     0,     1,     0,
    65,     0,    64,    65,     0,     8,     0,     9,     0,    67,
     0,    66,    67,     0,    68,     4,    70,     0,    68,     4,
     3,    70,     5,    70,     0,    68,     4,     3,    70,     5,
     3,     0,    68,     4,     3,     5,     3,     0,     0,    69,
     0,    57,     0,    69,    57,     0,    26,     0
};

#endif

#if YYDEBUG != 0
static const short yyrline[] = { 0,
   231,   232,   235,   236,   237,   238,   241,   242,   245,   246,
   247,   250,   253,   254,   257,   318,   342,   350,   358,   366,
   374,   382,   390,   398,   406,   414,   422,   430,   438,   446,
   503,   527,   542,   581,   582,   585,   609,   644,   676,   680,
   681,   684,   725,   736,   745,   759,   763,   789,   793,   803,
   819,   845,   848,   852,   858,   859,   860,   861,   864,   886,
   905,   935,   958,   990,  1022,  1026,  1027,  1033,  1035,  1039,
  1057,  1077,  1107,  1134,  1161,  1188,  1204,  1207,  1247,  1285
};
#endif


#if YYDEBUG != 0 || defined (YYERROR_VERBOSE)

static const char * const yytname[] = {   "$","error","$undefined.","'-'","'>'",
"','","':'","'.'","'*'","'~'","ALLAFFIXES","ALTSTRINGCHAR","ALTSTRINGTYPE","BOUNDARYCHARS",
"COMPOUNDMIN","COMPOUNDWORDS","CONTROLLED","DEFSTRINGTYPE","FLAG","FLAGMARKER",
"NROFFCHARS","OFF","ON","PREFIXES","RANGE","SUFFIXES","STRING","STRINGCHAR",
"TEXCHARS","TEXLEFTPAREN","TEXRIGHTPAREN","TEXLEFTSQUARE","TEXRIGHTSQUARE","TEXLEFTCURLY",
"TEXRIGHTCURLY","TEXLEFTTANGLE","TEXRIGHTTANGLE","TEXBACKSLASH","TEXDOLLAR",
"TEXSTAR","TEXDOT","TEXPERCENT","WORDCHARS","file","headers","option_group",
"charset_group","deftype_stmt","altchar_group","charset_stmt","altchar_stmt",
"stringtype_info","filesuf_list","filesuf","altchar_spec_group","altchar_spec",
"option_stmt","char_set","on_or_off","tables","prefix_table","suffix_table",
"table","flagdef","flagoptions","flagoption","rules","affix_rule","cond_or_null",
"conditions","ichar_string", NULL
};
#endif

static const short yyr1[] = {     0,
    43,    43,    44,    44,    44,    44,    45,    45,    46,    46,
    46,    47,    48,    48,    49,    49,    49,    49,    49,    49,
    49,    49,    49,    49,    49,    49,    49,    49,    49,    49,
    49,    49,    49,    50,    50,    51,    52,    52,    53,    54,
    54,    55,    56,    56,    56,    56,    56,    56,    56,    57,
    57,    57,    58,    58,    59,    59,    59,    59,    60,    61,
    62,    62,    63,    63,    63,    64,    64,    65,    65,    66,
    66,    67,    67,    67,    67,    68,    68,    69,    69,    70
};

static const short yyr2[] = {     0,
     2,     1,     2,     3,     1,     2,     1,     2,     2,     1,
     2,     2,     1,     2,     3,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     3,
     2,     2,     3,     2,     3,     3,     1,     2,     1,     1,
     2,     3,     2,     2,     2,     2,     3,     2,     2,     1,
     1,     1,     1,     1,     2,     2,     1,     1,     2,     2,
     1,     2,     4,     5,     1,     1,     2,     1,     1,     1,
     2,     3,     6,     6,     5,     0,     1,     1,     2,     1
};

static const short yydefact[] = {     0,
     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
     0,     0,     0,     0,     0,     0,     0,     5,     0,    10,
     7,     2,    57,    58,    54,    53,    48,    50,    52,    51,
    31,    45,     0,    46,     0,    12,    49,    43,    65,     0,
     0,    61,     0,    32,    44,    29,    17,    18,    19,    20,
    21,    22,    23,    24,    25,    26,    27,    28,    16,     1,
     3,     8,     0,     6,    11,    13,     9,    55,    56,    30,
    47,     0,    68,    69,     0,     0,    66,    62,    33,    15,
     4,    34,    14,    39,    36,    37,    76,     0,    67,     0,
    35,    40,    38,    78,    63,    70,     0,    77,    76,     0,
    41,    71,     0,    79,    64,    42,     0,    80,    72,     0,
     0,    75,     0,    74,    73,     0,     0,     0
};

static const short yydefgoto[] = {   126,
    26,    27,    28,    29,    74,    30,    76,    46,    95,    96,
   101,   102,    31,   104,    37,    32,    33,    34,    51,    52,
    86,    87,   105,   106,   107,   108,   119
};

static const short yypact[] = {    18,
    -9,   131,   -10,    -7,    -5,    36,    47,   155,   155,    49,
    50,    70,    71,    72,    73,    74,    75,    76,    77,    78,
    79,   100,   102,   104,   131,    17,    51,    82,   112,-32768,
-32768,-32768,    -8,    54,-32768,-32768,-32768,-32768,-32768,-32768,
   131,-32768,   105,-32768,   106,-32768,-32768,-32768,-32768,    10,
     4,-32768,     7,   107,-32768,-32768,-32768,-32768,-32768,-32768,
-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,   131,-32768,
    82,-32768,    -5,    12,-32768,-32768,-32768,-32768,-32768,-32768,
-32768,   108,-32768,-32768,   129,   150,-32768,-32768,-32768,-32768,
    12,    97,-32768,-32768,   108,-32768,   131,   130,-32768,   111,
    97,-32768,-32768,-32768,   103,-32768,   136,   131,   131,   135,
-32768,-32768,     0,-32768,   103,-32768,     1,-32768,-32768,   159,
   158,-32768,     8,-32768,-32768,   164,   165,-32768
};

static const short yypgoto[] = {-32768,
-32768,-32768,   139,-32768,    96,   -27,    86,    95,-32768,    80,
-32768,    68,   143,    -2,   167,   146,   140,   145,   170,    21,
-32768,    94,    81,   -95,-32768,-32768,   -54
};


#define	YYLAST		190


static const short yytable[] = {    41,
    75,    77,   117,   -59,    49,   120,   -60,    49,    43,   112,
   124,    35,    36,    35,    36,    42,     9,    83,    84,   112,
    45,    50,    69,    73,    50,   118,   118,     1,   -59,   -60,
     2,     3,     4,   118,     5,    85,     6,     7,    80,     8,
     8,     9,     9,    75,    10,    11,    12,    13,    14,    15,
    16,    17,    18,    19,    20,    21,    22,    23,    24,    25,
     1,    47,   121,     2,     3,     4,    90,     5,   125,     6,
     7,    88,    48,    88,    54,    55,     8,    10,    11,    12,
    13,    14,    15,    16,    17,    18,    19,    20,    21,    22,
    23,    24,    25,    73,     2,    56,    57,    58,    59,    60,
    61,    62,    63,    64,    65,   114,   -76,   100,    10,    38,
    12,    13,    14,    15,    16,    17,    18,    19,    20,    21,
    22,    23,    24,    25,     2,    66,    39,    67,    40,    68,
    81,    82,    89,    94,    97,   109,   110,    38,    10,   113,
    12,    13,    14,    15,    16,    17,    18,    19,    20,    21,
    22,    23,    24,    25,    39,    49,    40,    83,    84,    93,
   116,   122,   123,   127,   128,    71,    91,    92,   111,    72,
    44,    70,    50,    79,   103,    98,    93,    78,    53,    99,
     0,     0,     0,     0,     0,     0,     0,     0,     0,   115
};

static const short yycheck[] = {     2,
    28,    29,     3,     0,     1,     5,     0,     1,    16,   105,
     3,    21,    22,    21,    22,    26,    25,     8,     9,   115,
    26,    18,    25,    12,    18,    26,    26,    10,    25,    23,
    13,    14,    15,    26,    17,    26,    19,    20,    41,    23,
    23,    25,    25,    71,    27,    28,    29,    30,    31,    32,
    33,    34,    35,    36,    37,    38,    39,    40,    41,    42,
    10,    26,   117,    13,    14,    15,    69,    17,   123,    19,
    20,    51,    26,    53,    26,    26,    23,    27,    28,    29,
    30,    31,    32,    33,    34,    35,    36,    37,    38,    39,
    40,    41,    42,    12,    13,    26,    26,    26,    26,    26,
    26,    26,    26,    26,    26,   108,     4,    11,    27,     7,
    29,    30,    31,    32,    33,    34,    35,    36,    37,    38,
    39,    40,    41,    42,    13,    26,    24,    26,    26,    26,
    26,    26,    26,    26,     6,     6,    26,     7,    27,     4,
    29,    30,    31,    32,    33,    34,    35,    36,    37,    38,
    39,    40,    41,    42,    24,     1,    26,     8,     9,    74,
    26,     3,     5,     0,     0,    27,    71,    73,   101,    27,
     4,    26,    18,    34,    95,    26,    91,    33,     9,    86,
    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   109
};
/* -*-C-*-  Note some compilers choke on comments on `#line' lines.  */
#line 3 "bison.simple"

/* Skeleton output parser for bison,
   Copyright (C) 1984, 1989, 1990 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */

/* As a special exception, when this file is copied by Bison into a
   Bison output file, you may use that output file without restriction.
   This special exception was added by the Free Software Foundation
   in version 1.24 of Bison.  */

#ifndef alloca
#ifdef __GNUC__
#define alloca __builtin_alloca
#else /* not GNU C.  */
#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi)
#include <alloca.h>
#else /* not sparc */
#if defined (MSDOS) && !defined (__TURBOC__)
#include <malloc.h>
#else /* not MSDOS, or __TURBOC__ */
#if defined(_AIX)
#include <malloc.h>
 #pragma alloca
#else /* not MSDOS, __TURBOC__, or _AIX */
#ifdef __hpux
#ifdef __cplusplus
extern "C" {
void *alloca (unsigned int);
};
#else /* not __cplusplus */
void *alloca ();
#endif /* not __cplusplus */
#endif /* __hpux */
#endif /* not _AIX */
#endif /* not MSDOS, or __TURBOC__ */
#endif /* not sparc.  */
#endif /* not GNU C.  */
#endif /* alloca not defined.  */

/* This is the parser code that is written into each bison parser
  when the %semantic_parser declaration is not specified in the grammar.
  It was written by Richard Stallman by simplifying the hairy parser
  used when %semantic_parser is specified.  */

/* Note: there must be only one dollar sign in this file.
   It is replaced by the list of actions, each action
   as one case of the switch.  */

#define yyerrok		(yyerrstatus = 0)
#define yyclearin	(yychar = YYEMPTY)
#define YYEMPTY		-2
#define YYEOF		0
#define YYACCEPT	return(0)
#define YYABORT 	return(1)
#define YYERROR		goto yyerrlab1
/* Like YYERROR except do call yyerror.
   This remains here temporarily to ease the
   transition to the new meaning of YYERROR, for GCC.
   Once GCC version 2 has supplanted version 1, this can go.  */
#define YYFAIL		goto yyerrlab
#define YYRECOVERING()  (!!yyerrstatus)
#define YYBACKUP(token, value) \
do								\
  if (yychar == YYEMPTY && yylen == 1)				\
    { yychar = (token), yylval = (value);			\
      yychar1 = YYTRANSLATE (yychar);				\
      YYPOPSTACK;						\
      goto yybackup;						\
    }								\
  else								\
    { yyerror ("syntax error: cannot back up"); YYERROR; }	\
while (0)

#define YYTERROR	1
#define YYERRCODE	256

#ifndef YYPURE
#define YYLEX		yylex()
#endif

#ifdef YYPURE
#ifdef YYLSP_NEEDED
#ifdef YYLEX_PARAM
#define YYLEX		yylex(&yylval, &yylloc, YYLEX_PARAM)
#else
#define YYLEX		yylex(&yylval, &yylloc)
#endif
#else /* not YYLSP_NEEDED */
#ifdef YYLEX_PARAM
#define YYLEX		yylex(&yylval, YYLEX_PARAM)
#else
#define YYLEX		yylex(&yylval)
#endif
#endif /* not YYLSP_NEEDED */
#endif

/* If nonreentrant, generate the variables here */

#ifndef YYPURE

int	yychar;			/*  the lookahead symbol		*/
YYSTYPE	yylval;			/*  the semantic value of the		*/
				/*  lookahead symbol			*/

#ifdef YYLSP_NEEDED
YYLTYPE yylloc;			/*  location data for the lookahead	*/
				/*  symbol				*/
#endif

int yynerrs;			/*  number of parse errors so far       */
#endif  /* not YYPURE */

#if YYDEBUG != 0
int yydebug;			/*  nonzero means print parse trace	*/
/* Since this is uninitialized, it does not stop multiple parsers
   from coexisting.  */
#endif

/*  YYINITDEPTH indicates the initial size of the parser's stacks	*/

#ifndef	YYINITDEPTH
#define YYINITDEPTH 200
#endif

/*  YYMAXDEPTH is the maximum size the stacks can grow to
    (effective only if the built-in stack extension method is used).  */

#if YYMAXDEPTH == 0
#undef YYMAXDEPTH
#endif

#ifndef YYMAXDEPTH
#define YYMAXDEPTH 10000
#endif

/* Prevent warning if -Wstrict-prototypes.  */
#ifdef __GNUC__
int yyparse (void);
#endif

#if __GNUC__ > 1		/* GNU C and GNU C++ define this.  */
#define __yy_memcpy(FROM,TO,COUNT)	__builtin_memcpy(TO,FROM,COUNT)
#else				/* not GNU C or C++ */
#ifndef __cplusplus

/* This is the most reliable way to avoid incompatibilities
   in available built-in functions on various systems.  */
static void
__yy_memcpy (from, to, count)
     char *from;
     char *to;
     int count;
{
  register char *f = from;
  register char *t = to;
  register int i = count;

  while (i-- > 0)
    *t++ = *f++;
}

#else /* __cplusplus */

/* This is the most reliable way to avoid incompatibilities
   in available built-in functions on various systems.  */
static void
__yy_memcpy (char *from, char *to, int count)
{
  register char *f = from;
  register char *t = to;
  register int i = count;

  while (i-- > 0)
    *t++ = *f++;
}

#endif
#endif

#line 192 "bison.simple"

/* The user can define YYPARSE_PARAM as the name of an argument to be passed
   into yyparse.  The argument should have type void *.
   It should actually point to an object.
   Grammar actions can access the variable by casting it
   to the proper pointer type.  */

#ifdef YYPARSE_PARAM
#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
#else
#define YYPARSE_PARAM
#define YYPARSE_PARAM_DECL
#endif

int
yyparse(YYPARSE_PARAM)
     YYPARSE_PARAM_DECL
{
  register int yystate;
  register int yyn;
  register short *yyssp;
  register YYSTYPE *yyvsp;
  int yyerrstatus;	/*  number of tokens to shift before error messages enabled */
  int yychar1 = 0;		/*  lookahead token as an internal (translated) token number */

  short	yyssa[YYINITDEPTH];	/*  the state stack			*/
  YYSTYPE yyvsa[YYINITDEPTH];	/*  the semantic value stack		*/

  short *yyss = yyssa;		/*  refer to the stacks thru separate pointers */
  YYSTYPE *yyvs = yyvsa;	/*  to allow yyoverflow to reallocate them elsewhere */

#ifdef YYLSP_NEEDED
  YYLTYPE yylsa[YYINITDEPTH];	/*  the location stack			*/
  YYLTYPE *yyls = yylsa;
  YYLTYPE *yylsp;

#define YYPOPSTACK   (yyvsp--, yyssp--, yylsp--)
#else
#define YYPOPSTACK   (yyvsp--, yyssp--)
#endif

  int yystacksize = YYINITDEPTH;

#ifdef YYPURE
  int yychar;
  YYSTYPE yylval;
  int yynerrs;
#ifdef YYLSP_NEEDED
  YYLTYPE yylloc;
#endif
#endif

  YYSTYPE yyval;		/*  the variable used to return		*/
				/*  semantic values from the action	*/
				/*  routines				*/

  int yylen;

#if YYDEBUG != 0
  if (yydebug)
    fprintf(stderr, "Starting parse\n");
#endif

  yystate = 0;
  yyerrstatus = 0;
  yynerrs = 0;
  yychar = YYEMPTY;		/* Cause a token to be read.  */

  /* Initialize stack pointers.
     Waste one element of value and location stack
     so that they stay on the same level as the state stack.
     The wasted elements are never initialized.  */

  yyssp = yyss - 1;
  yyvsp = yyvs;
#ifdef YYLSP_NEEDED
  yylsp = yyls;
#endif

/* Push a new state, which is found in  yystate  .  */
/* In all cases, when you get here, the value and location stacks
   have just been pushed. so pushing a state here evens the stacks.  */
yynewstate:

  *++yyssp = yystate;

  if (yyssp >= yyss + yystacksize - 1)
    {
      /* Give user a chance to reallocate the stack */
      /* Use copies of these so that the &'s don't force the real ones into memory. */
      YYSTYPE *yyvs1 = yyvs;
      short *yyss1 = yyss;
#ifdef YYLSP_NEEDED
      YYLTYPE *yyls1 = yyls;
#endif

      /* Get the current used size of the three stacks, in elements.  */
      int size = yyssp - yyss + 1;

#ifdef yyoverflow
      /* Each stack pointer address is followed by the size of
	 the data in use in that stack, in bytes.  */
#ifdef YYLSP_NEEDED
      /* This used to be a conditional around just the two extra args,
	 but that might be undefined if yyoverflow is a macro.  */
      yyoverflow("parser stack overflow",
		 &yyss1, size * sizeof (*yyssp),
		 &yyvs1, size * sizeof (*yyvsp),
		 &yyls1, size * sizeof (*yylsp),
		 &yystacksize);
#else
      yyoverflow("parser stack overflow",
		 &yyss1, size * sizeof (*yyssp),
		 &yyvs1, size * sizeof (*yyvsp),
		 &yystacksize);
#endif

      yyss = yyss1; yyvs = yyvs1;
#ifdef YYLSP_NEEDED
      yyls = yyls1;
#endif
#else /* no yyoverflow */
      /* Extend the stack our own way.  */
      if (yystacksize >= YYMAXDEPTH)
	{
	  yyerror("parser stack overflow");
	  return 2;
	}
      yystacksize *= 2;
      if (yystacksize > YYMAXDEPTH)
	yystacksize = YYMAXDEPTH;
      yyss = (short *) alloca (yystacksize * sizeof (*yyssp));
      __yy_memcpy ((char *)yyss1, (char *)yyss, size * sizeof (*yyssp));
      yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp));
      __yy_memcpy ((char *)yyvs1, (char *)yyvs, size * sizeof (*yyvsp));
#ifdef YYLSP_NEEDED
      yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp));
      __yy_memcpy ((char *)yyls1, (char *)yyls, size * sizeof (*yylsp));
#endif
#endif /* no yyoverflow */

      yyssp = yyss + size - 1;
      yyvsp = yyvs + size - 1;
#ifdef YYLSP_NEEDED
      yylsp = yyls + size - 1;
#endif

#if YYDEBUG != 0
      if (yydebug)
	fprintf(stderr, "Stack size increased to %d\n", yystacksize);
#endif

      if (yyssp >= yyss + yystacksize - 1)
	YYABORT;
    }

#if YYDEBUG != 0
  if (yydebug)
    fprintf(stderr, "Entering state %d\n", yystate);
#endif

  goto yybackup;
 yybackup:

/* Do appropriate processing given the current state.  */
/* Read a lookahead token if we need one and don't already have one.  */
/* yyresume: */

  /* First try to decide what to do without reference to lookahead token.  */

  yyn = yypact[yystate];
  if (yyn == YYFLAG)
    goto yydefault;

  /* Not known => get a lookahead token if don't already have one.  */

  /* yychar is either YYEMPTY or YYEOF
     or a valid token in external form.  */

  if (yychar == YYEMPTY)
    {
#if YYDEBUG != 0
      if (yydebug)
	fprintf(stderr, "Reading a token: ");
#endif
      yychar = YYLEX;
    }

  /* Convert token to internal form (in yychar1) for indexing tables with */

  if (yychar <= 0)		/* This means end of input. */
    {
      yychar1 = 0;
      yychar = YYEOF;		/* Don't call YYLEX any more */

#if YYDEBUG != 0
      if (yydebug)
	fprintf(stderr, "Now at end of input.\n");
#endif
    }
  else
    {
      yychar1 = YYTRANSLATE(yychar);

#if YYDEBUG != 0
      if (yydebug)
	{
	  fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
	  /* Give the individual parser a way to print the precise meaning
	     of a token, for further debugging info.  */
#ifdef YYPRINT
	  YYPRINT (stderr, yychar, yylval);
#endif
	  fprintf (stderr, ")\n");
	}
#endif
    }

  yyn += yychar1;
  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
    goto yydefault;

  yyn = yytable[yyn];

  /* yyn is what to do for this token type in this state.
     Negative => reduce, -yyn is rule number.
     Positive => shift, yyn is new state.
       New state is final state => don't bother to shift,
       just return success.
     0, or most negative number => error.  */

  if (yyn < 0)
    {
      if (yyn == YYFLAG)
	goto yyerrlab;
      yyn = -yyn;
      goto yyreduce;
    }
  else if (yyn == 0)
    goto yyerrlab;

  if (yyn == YYFINAL)
    YYACCEPT;

  /* Shift the lookahead token.  */

#if YYDEBUG != 0
  if (yydebug)
    fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
#endif

  /* Discard the token being shifted unless it is eof.  */
  if (yychar != YYEOF)
    yychar = YYEMPTY;

  *++yyvsp = yylval;
#ifdef YYLSP_NEEDED
  *++yylsp = yylloc;
#endif

  /* count tokens shifted since error; after three, turn off error status.  */
  if (yyerrstatus) yyerrstatus--;

  yystate = yyn;
  goto yynewstate;

/* Do the default action for the current state.  */
yydefault:

  yyn = yydefact[yystate];
  if (yyn == 0)
    goto yyerrlab;

/* Do a reduction.  yyn is the number of a rule to reduce with.  */
yyreduce:
  yylen = yyr2[yyn];
  if (yylen > 0)
    yyval = yyvsp[1-yylen]; /* implement default value of the action */

#if YYDEBUG != 0
  if (yydebug)
    {
      int i;

      fprintf (stderr, "Reducing via rule %d (line %d), ",
	       yyn, yyrline[yyn]);

      /* Print the symbols being reduced, and their result.  */
      for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
	fprintf (stderr, "%s ", yytname[yyrhs[i]]);
      fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
    }
#endif


  switch (yyn) {

case 15:
#line 258 "parse.y"
{
			    int nextlower;
			    int nextupper;

			    for (nextlower = SET_SIZE + hashheader.nstrchars;
						      --nextlower > SET_SIZE;)
				{
				if (yyvsp[-1].charset.set[nextlower] != 0
					      ||  yyvsp[0].charset.set[nextlower] != 0)
				    {
				    yyerror (PARSE_Y_NO_WORD_STRINGS);
				    break;
				    }
				}
			    for (nextlower = 0;
					      nextlower < SET_SIZE;
							      nextlower++)
				{
				hashheader.wordchars[nextlower]
				      |= yyvsp[-1].charset.set[nextlower] | yyvsp[0].charset.set[nextlower];
				hashheader.lowerchars[nextlower]
						      |= yyvsp[-1].charset.set[nextlower];
				hashheader.upperchars[nextlower]
							  |= yyvsp[0].charset.set[nextlower];
				}
			    for (nextlower = nextupper = 0;
						  nextlower < SET_SIZE;
								  nextlower++)
				{
				if (yyvsp[-1].charset.set[nextlower])
				    {
				    for (  ;
				      nextupper < SET_SIZE
						    &&  !yyvsp[0].charset.set[nextupper];
								  nextupper++)
					;
				    if (nextupper == SET_SIZE)
					yyerror (PARSE_Y_UNMATCHED);
				    else
					{
					hashheader.lowerconv[nextupper]
					  = (ichar_t) nextlower;
					hashheader.upperconv[nextlower]
						      = (ichar_t) nextupper;
					hashheader.sortorder[nextupper]
						      = hashheader.sortval++;
					hashheader.sortorder[nextlower]
						      = hashheader.sortval++;
					nextupper++;
					}
				    }
				}
			    for (; nextupper < SET_SIZE;  nextupper++)
				{
				if (yyvsp[0].charset.set[nextupper])
				    yyerror (PARSE_Y_UNMATCHED);
				}
			    free (yyvsp[-1].charset.set);
			    free (yyvsp[0].charset.set);
			    ;
    break;}
case 16:
#line 319 "parse.y"
{
			    int i;

			    for (i = SET_SIZE + hashheader.nstrchars;
							  --i > SET_SIZE;)
				{
				if (yyvsp[0].charset.set[i] != 0)
				    {
				    yyerror (PARSE_Y_NO_WORD_STRINGS);
				    break;
				    }
				}
			    for (i = 0;  i < SET_SIZE;  i++)
				{
				if (yyvsp[0].charset.set[i])
				    {
				    hashheader.wordchars[i] = 1;
				    hashheader.sortorder[i]
						      = hashheader.sortval++;
				    }
				}
			    free (yyvsp[0].charset.set);
			    ;
    break;}
case 17:
#line 343 "parse.y"
{
			    if (strlen ((char *) yyvsp[0].string) != 1)
				yyerror (PARSE_Y_LONG_FLAG);
			    else
				hashheader.TeXrightparen = (char ) yyvsp[0].string[0];
			    free ((char *) yyvsp[0].string);
			    ;
    break;}
case 18:
#line 351 "parse.y"
{
			    if (strlen ((char *) yyvsp[0].string) != 1)
				yyerror (PARSE_Y_LONG_FLAG);
			    else
				hashheader.TeXleftsquare = (char ) yyvsp[0].string[0];
			    free ((char *) yyvsp[0].string);
			    ;
    break;}
case 19:
#line 359 "parse.y"
{
			    if (strlen ((char *) yyvsp[0].string) != 1)
				yyerror (PARSE_Y_LONG_FLAG);
			    else
				hashheader.TeXrightsquare = (char ) yyvsp[0].string[0];
			    free ((char *) yyvsp[0].string);
			    ;
    break;}
case 20:
#line 367 "parse.y"
{
			    if (strlen ((char *) yyvsp[0].string) != 1)
				yyerror (PARSE_Y_LONG_FLAG);
			    else
				hashheader.TeXleftcurly = (char ) yyvsp[0].string[0];
			    free ((char *) yyvsp[0].string);
			    ;
    break;}
case 21:
#line 375 "parse.y"
{
			    if (strlen ((char *) yyvsp[0].string) != 1)
				yyerror (PARSE_Y_LONG_FLAG);
			    else
				hashheader.TeXrightcurly = (char ) yyvsp[0].string[0];
			    free ((char *) yyvsp[0].string);
			    ;
    break;}
case 22:
#line 383 "parse.y"
{
			    if (strlen ((char *) yyvsp[0].string) != 1)
				yyerror (PARSE_Y_LONG_FLAG);
			    else
				hashheader.TeXlefttangle = (char ) yyvsp[0].string[0];
			    free ((char *) yyvsp[0].string);
			    ;
    break;}
case 23:
#line 391 "parse.y"
{
			    if (strlen ((char *) yyvsp[0].string) != 1)
				yyerror (PARSE_Y_LONG_FLAG);
			    else
				hashheader.TeXrighttangle = (char ) yyvsp[0].string[0];
			    free ((char *) yyvsp[0].string);
			    ;
    break;}
case 24:
#line 399 "parse.y"
{
			    if (strlen ((char *) yyvsp[0].string) != 1)
				yyerror (PARSE_Y_LONG_FLAG);
			    else
				hashheader.TeXbackslash = (char ) yyvsp[0].string[0];
			    free ((char *) yyvsp[0].string);
			    ;
    break;}
case 25:
#line 407 "parse.y"
{
			    if (strlen ((char *) yyvsp[0].string) != 1)
				yyerror (PARSE_Y_LONG_FLAG);
			    else
				hashheader.TeXdollar = (char ) yyvsp[0].string[0];
			    free ((char *) yyvsp[0].string);
			    ;
    break;}
case 26:
#line 415 "parse.y"
{
			    if (strlen ((char *) yyvsp[0].string) != 1)
				yyerror (PARSE_Y_LONG_FLAG);
			    else
				hashheader.TeXstar = (char ) yyvsp[0].string[0];
			    free ((char *) yyvsp[0].string);
			    ;
    break;}
case 27:
#line 423 "parse.y"
{
			    if (strlen ((char *) yyvsp[0].string) != 1)
				yyerror (PARSE_Y_LONG_FLAG);
			    else
				hashheader.TeXdot = (char ) yyvsp[0].string[0];
			    free ((char *) yyvsp[0].string);
			    ;
    break;}
case 28:
#line 431 "parse.y"
{
			    if (strlen ((char *) yyvsp[0].string) != 1)
				yyerror (PARSE_Y_LONG_FLAG);
			    else
				hashheader.TeXpercent = (char ) yyvsp[0].string[0];
			    free ((char *) yyvsp[0].string);
			    ;
    break;}
case 29:
#line 439 "parse.y"
{
			    if (strlen ((char *) yyvsp[0].string) != 1)
				yyerror (PARSE_Y_LONG_FLAG);
			    else
				hashheader.TeXleftparen = (char ) yyvsp[0].string[0];
			    free ((char *) yyvsp[0].string);
			    ;
    break;}
case 30:
#line 447 "parse.y"
{
			    int nextlower;
			    int nextupper;

			    for (nextlower = SET_SIZE + hashheader.nstrchars;
						      --nextlower > SET_SIZE;)
				{
				if (yyvsp[-1].charset.set[nextlower] != 0
				  ||  yyvsp[0].charset.set[nextlower] != 0)
				    {
				    yyerror (PARSE_Y_NO_BOUNDARY_STRINGS);
				    break;
				    }
				}
			    for (nextlower = 0;
					      nextlower < SET_SIZE;
							      nextlower++)
				{
				hashheader.boundarychars[nextlower]
				      |= yyvsp[-1].charset.set[nextlower] | yyvsp[0].charset.set[nextlower];
				hashheader.lowerchars[nextlower]
						      |= yyvsp[-1].charset.set[nextlower];
				hashheader.upperchars[nextlower]
						      |= yyvsp[0].charset.set[nextlower];
				}
			    for (nextlower = nextupper = 0;
				      nextlower < SET_SIZE; nextlower++)
				{
				if (yyvsp[-1].charset.set[nextlower])
				    {
				    for (; nextupper < SET_SIZE
						&&  !yyvsp[0].charset.set[nextupper];
								  nextupper++)
					;
				    if (nextupper == SET_SIZE)
					yyerror (PARSE_Y_UNMATCHED);
				    else
					{
					hashheader.lowerconv[nextupper]
						      = (ichar_t) nextlower;
					hashheader.upperconv[nextlower]
							  = (ichar_t) nextupper;
					hashheader.sortorder[nextupper]
						      = hashheader.sortval++;
					hashheader.sortorder[nextlower]
						      = hashheader.sortval++;
					nextupper++;
					}
				    }
				}
			    for (;  nextupper < SET_SIZE;  nextupper++)
				if (yyvsp[0].charset.set[nextupper])
				    yyerror (PARSE_Y_UNMATCHED);
			    free (yyvsp[-1].charset.set);
			    free (yyvsp[0].charset.set);
			    ;
    break;}
case 31:
#line 504 "parse.y"
{
			    int i;

			    for (i = SET_SIZE + hashheader.nstrchars;
							      --i > SET_SIZE;)
				{
				if (yyvsp[0].charset.set[i] != 0)
				    {
				    yyerror (PARSE_Y_NO_BOUNDARY_STRINGS);
				    break;
				    }
				}
			    for (i = 0;  i < SET_SIZE;  i++)
				{
				if (yyvsp[0].charset.set[i])
				    {
				    hashheader.boundarychars[i] = 1;
				    hashheader.sortorder[i]
						  = hashheader.sortval++;
				    }
				}
			    free (yyvsp[0].charset.set);
			    ;
    break;}
case 32:
#line 528 "parse.y"
{
			    int len;

			    len = strlen ((char *) yyvsp[0].string);
			    if (len > MAXSTRINGCHARLEN)
				yyerror (PARSE_Y_LONG_STRING);
			    else if (len == 0)
				yyerror (PARSE_Y_NULL_STRING);
			    else if (hashheader.nstrchars >= MAXSTRINGCHARS)
				yyerror (PARSE_Y_MANY_STRINGS);
			    else
				(void) addstringchar (yyvsp[0].string, 0, 0);
			    free ((char *) yyvsp[0].string);
			    ;
    break;}
case 33:
#line 543 "parse.y"
{
			    int lcslot;
			    int len;
			    int ucslot;

			    len = strlen ((char *) yyvsp[-1].string);
			    if (strlen ((char *) yyvsp[0].string) != len)
				yyerror (PARSE_Y_LENGTH_MISMATCH);
			    else if (len > MAXSTRINGCHARLEN)
				yyerror (PARSE_Y_LONG_STRING);
			    else if (len == 0)
				yyerror (PARSE_Y_NULL_STRING);
			    else if (hashheader.nstrchars >= MAXSTRINGCHARS)
				yyerror (PARSE_Y_MANY_STRINGS);
			    else
				{
				/*
				 * Add the uppercase character first, so that
				 * it will sort first.
				 */
				lcslot = ucslot = addstringchar (yyvsp[0].string, 0, 1);
				if (ucslot >= 0)
				    lcslot = addstringchar (yyvsp[-1].string, 1, 0);
				if (ucslot >= 0  &&  lcslot >= 0)
				    {
				    if (ucslot >= lcslot)
					ucslot++;
				    hashheader.lowerconv[ucslot] =
				      (ichar_t) lcslot;
				    hashheader.upperconv[lcslot] =
				      (ichar_t) ucslot;
				    }
				}
			    free ((char *) yyvsp[-1].string);
			    free ((char *) yyvsp[0].string);
			    ;
    break;}
case 36:
#line 586 "parse.y"
{
			    chartypes[ctypenum].name = (char *) yyvsp[-2].string;
			    chartypes[ctypenum].deformatter = (char *) yyvsp[-1].string;
			    /*
			     * Implement a few common synonyms.  This should
			     * be generalized.
			     */
			    if (strcmp ((char *) yyvsp[-1].string, "TeX") == 0)
				(void) strcpy ((char *) yyvsp[-1].string, "tex");
			    else if (strcmp ((char *) yyvsp[-1].string, "troff") == 0)
				(void) strcpy ((char *) yyvsp[-1].string, "nroff");
			    /*
			     * Someday, we'll accept generalized deformatters.
			     * Then we can get rid of this test.
			     */
			    if (strcmp ((char *) yyvsp[-1].string, "nroff") != 0
			      &&  strcmp ((char *) yyvsp[-1].string, "tex") != 0)
				yyerror (PARSE_Y_BAD_DEFORMATTER);
			    ctypenum++;
			    hashheader.nstrchartype = ctypenum;
			    ;
    break;}
case 37:
#line 610 "parse.y"
{
			    if (ctypenum >= ctypesize)
				{
				if (ctypesize == 0)
				    chartypes = (struct strchartype *)
					  malloc (TBLINC
						* sizeof (struct strchartype));
				else
				    chartypes = (struct strchartype *)
				      realloc ((char *) chartypes,
						(ctypesize + TBLINC)
					      * sizeof (struct strchartype));
				if (chartypes == NULL)
				    {
				    yyerror (PARSE_Y_NO_SPACE);
				    exit (1);
				    }
				ctypesize += TBLINC;
				}
			    ctypechars =
				      TBLINC * (strlen ((char *) yyvsp[0].string) + 1) + 1;
			    chartypes[ctypenum].suffixes =
				      malloc ((unsigned int) ctypechars);
			    if (chartypes[ctypenum].suffixes == NULL)
				{
				yyerror (PARSE_Y_NO_SPACE);
				exit (1);
				}
			    (void) strcpy (chartypes[ctypenum].suffixes,
								 (char *) yyvsp[0].string);
			    chartypes[ctypenum].suffixes
					    [strlen ((char *) yyvsp[0].string) + 1] = '\0';
			    free ((char *) yyvsp[0].string);
			    ;
    break;}
case 38:
#line 645 "parse.y"
{
			    char *	nexttype;
			    int		offset;

			    for (nexttype = chartypes[ctypenum].suffixes;
					      *nexttype != '\0';
					      nexttype += strlen (nexttype) + 1)
				;
			    offset = nexttype - chartypes[ctypenum].suffixes;
			    if ((int) (offset + strlen ((char *) yyvsp[0].string) + 1)
							       >= ctypechars)
				{
				ctypechars +=
				  TBLINC * (strlen ((char *) yyvsp[0].string) + 1);
				chartypes[ctypenum].suffixes =
				      realloc (chartypes[ctypenum].suffixes,
						(unsigned int) ctypechars);
				if (chartypes[ctypenum].suffixes == NULL)
				    {
				    yyerror (PARSE_Y_NO_SPACE);
				    exit (1);
				    }
				nexttype =
				      chartypes[ctypenum].suffixes + offset;
				}
			    (void) strcpy (nexttype, (char *) yyvsp[0].string);
			    nexttype[strlen ((char *) yyvsp[0].string) + 1] = '\0';
			    free ((char *) yyvsp[0].string);
			    ;
    break;}
case 42:
#line 685 "parse.y"
{
			    int i;
			    int len;
			    int slot;

			    len = strlen ((char *) yyvsp[-1].string);
			    if (len > MAXSTRINGCHARLEN)
				yyerror (PARSE_Y_LONG_STRING);
			    else if (len == 0)
				yyerror (PARSE_Y_NULL_STRING);
			    else if (hashheader.nstrchars >= MAXSTRINGCHARS)
				yyerror (PARSE_Y_MANY_STRINGS);
			    else if (!isstringch ((char *) yyvsp[0].string, 1))
				yyerror (PARSE_Y_NO_SUCH_STRING);
			    else
				{
				slot = addstringchar (yyvsp[-1].string, 0, 0) - SET_SIZE;
				if (laststringch >= slot)
				    laststringch++;
				hashheader.stringdups[slot] = laststringch;
				for (i = hashheader.nstrchars;  --i >= 0;  )
				    {
				    if (hashheader.stringdups[i]
						  == laststringch)
						    hashheader.dupnos[slot]++;
				    }
				/*
				 * The above code sets dupnos one too high,
				 * because it counts the character itself.
				 */
				if (hashheader.dupnos[slot]
					      != hashheader.nstrchartype)
					    yyerror (PARSE_Y_MULTIPLE_STRINGS);
				hashheader.dupnos[slot]--;
				}
			    free ((char *) yyvsp[-1].string);
			    free ((char *) yyvsp[0].string);
			    ;
    break;}
case 43:
#line 726 "parse.y"
{
			    if (strlen ((char *) yyvsp[0].string)
					  == sizeof (hashheader.nrchars))
				(void) bcopy ((char *) yyvsp[0].string, hashheader.nrchars,
					      sizeof (hashheader.nrchars));
			    else
				yyerror (PARSE_Y_WRONG_NROFF);
			    free ((char *) yyvsp[0].string);
			    ;
    break;}
case 44:
#line 737 "parse.y"
{
			    if (strlen ((char *) yyvsp[0].string) < MAXSTRINGCHARS)
				(void) bcopy ((char *) yyvsp[0].string, hashheader.texchars,
						      strlen ((char *) yyvsp[0].string));
			    else
				yyerror (PARSE_Y_WRONG_TEX);
			    free ((char *) yyvsp[0].string);
			    ;
    break;}
case 45:
#line 746 "parse.y"
{
			    unsigned char * digitp; /* Pointer to next digit */

			    for (digitp = yyvsp[0].string;  *digitp != '\0';  digitp++)
				{
				if (*digitp <= '0'  ||  *digitp >= '9')
				    {
				    yyerror (PARSE_Y_BAD_NUMBER);
				    break;
				    }
				}
			    hashheader.compoundmin = atoi ((char *) yyvsp[0].string);
			    ;
    break;}
case 46:
#line 760 "parse.y"
{
			    hashheader.compoundflag = yyvsp[0].simple;
			    ;
    break;}
case 47:
#line 764 "parse.y"
{
			    if (strlen ((char *) yyvsp[0].string) != 1)
				yyerror (PARSE_Y_LONG_FLAG);
			    else if (hashheader.compoundbit >= 0)
				yyerror (PARSE_Y_DOUBLE_COMPOUND);
			    else
				{
				hashheader.compoundbit = (unsigned char) yyvsp[0].string[0];
#if MASKBITS <= 128
				hashheader.compoundbit &= 0x7f;
#endif /* MASKBITS */
#if MASKBITS <= 32
				if (islower (hashheader.compoundbit))
				    hashheader.compoundbit =
					  toupper (hashheader.compoundbit);
#endif /* MASKBITS */
#if MASKBITS <= 64
				if (!isalpha (hashheader.compoundbit))
				    yyerror (PARSE_Y_BAD_FLAG);
#endif /* MASKBITS */
				hashheader.compoundbit =
				  CHARTOBIT (hashheader.compoundbit);
				}
			    hashheader.compoundflag = COMPOUND_CONTROLLED;
			    ;
    break;}
case 48:
#line 790 "parse.y"
{
			    hashheader.defhardflag = yyvsp[0].simple;
			    ;
    break;}
case 49:
#line 794 "parse.y"
{
			    if (strlen ((char *) yyvsp[0].string) != 1)
				yyerror (PARSE_Y_LONG_FLAG);
			    else
				hashheader.flagmarker = yyvsp[0].string[0];
			    free ((char *) yyvsp[0].string);
			    ;
    break;}
case 50:
#line 804 "parse.y"
{
			    int		i;
			    char *	set;

			    set = malloc (SET_SIZE + MAXSTRINGCHARS);
			    if (set == NULL)
				{
				yyerror (PARSE_Y_NO_SPACE);
				exit (1);
				}
			    yyval.charset.set = set;
			    for (i = SET_SIZE + MAXSTRINGCHARS;  --i >= 0;  )
				*set++ = 1;
			    yyval.charset.complement = 0;
			    ;
    break;}
case 51:
#line 820 "parse.y"
{
			    int		setlen;

			    yyval.charset.set = malloc (SET_SIZE + MAXSTRINGCHARS);
			    if (yyval.charset.set == NULL)
				{
				yyerror (PARSE_Y_NO_SPACE);
				exit (1);
				}
			    (void) bzero (yyval.charset.set, SET_SIZE + MAXSTRINGCHARS);
			    if (l1_isstringch ((char *) yyvsp[0].string, setlen, 1))
				{
				if (setlen != strlen ((char *) yyvsp[0].string))
				    yyerror (PARSE_Y_NEED_BLANK);
				yyval.charset.set[SET_SIZE + laststringch] = 1;
				}
			    else
				{
				if (strlen ((char *) yyvsp[0].string) != 1)
				    yyerror (PARSE_Y_NEED_BLANK);
				yyval.charset.set[*yyvsp[0].string] = 1;
				}
			    free ((char *) yyvsp[0].string);
			    yyval.charset.complement = 0;
			    ;
    break;}
case 53:
#line 849 "parse.y"
{
			    yyval.simple = 1;
			    ;
    break;}
case 54:
#line 853 "parse.y"
{
			    yyval.simple = 0;
			    ;
    break;}
case 59:
#line 865 "parse.y"
{
			    pflaglist = table;
			    numpflags = tblnum;
			    /*
			     * Sort the flag table.  This is critical so
			     * that ispell can build a correct index
			     * table.  The idea is to put similar affixes
			     * together.
			     */
			    qsort ((char *) table, (unsigned) tblnum,
			      sizeof (*table),
			      (int (*) (const void *, const void *))
								    precmp);
#ifdef TBLDEBUG
			    (void) fprintf (stderr, "prefixes\n");
			    tbldump (table, tblnum);
#endif
			    tblsize = 0;
			    ;
    break;}
case 60:
#line 887 "parse.y"
{
			    sflaglist = table;
			    numsflags = tblnum;
			    /*
			     * See comments on the prefix sort.
			     */
			    qsort ((char *) table, (unsigned) tblnum,
			      sizeof (*table),
			      (int (*) (const void *, const void *))
				sufcmp);
#ifdef TBLDEBUG
			    (void) fprintf (stderr, "suffixes\n");
			    tbldump (table, tblnum);
#endif
			    tblsize = 0;
			    ;
    break;}
case 61:
#line 906 "parse.y"
{
			    if (tblsize == 0)
				{
				tblsize = centnum + TBLINC;
				tblnum = 0;
				table = (struct flagent *)
				  malloc (tblsize * (sizeof (struct flagent)));
				if (table == NULL)
				    {
				    yyerror (PARSE_Y_NO_SPACE);
				    exit (1);
				    }
				}
			    else if (tblnum + centnum >= tblsize)
				{
				tblsize = tblnum + centnum + TBLINC;
				table = (struct flagent *)
				      realloc ((char *) table,
					tblsize * (sizeof (struct flagent)));
				if (table == NULL)
				    {
				    yyerror (PARSE_Y_NO_SPACE);
				    exit (1);
				    }
				}
			    for (tblnum = 0;  tblnum < centnum;  tblnum++)
				table[tblnum] = curents[tblnum];
			    centnum = 0;
			    ;
    break;}
case 62:
#line 936 "parse.y"
{
			    int i;

			    if (tblnum + centnum >= tblsize)
				{
				tblsize = tblnum + centnum + TBLINC;
				table = (struct flagent *)
					  realloc ((char *) table,
					tblsize * (sizeof (struct flagent)));
				if (table == NULL)
				    {
				    yyerror (PARSE_Y_NO_SPACE);
				    exit (1);
				    }
				}
			    for (i = 0;  i < centnum;  i++)
				table[tblnum + i] = curents[i];
			    tblnum += centnum;
			    centnum = 0;
			    ;
    break;}
case 63:
#line 959 "parse.y"
{
			    int flagbit;
			    int i;

			    if (strlen ((char *) yyvsp[-2].string) != 1)
				yyerror (PARSE_Y_LONG_FLAG);
			    flagbit = (unsigned char) yyvsp[-2].string[0];
#if MASKBITS <= 128
			    flagbit &= 0x7f;
#endif /* MASKBITS */
#if MASKBITS <= 32
			    if (islower (flagbit))
				flagbit = toupper (flagbit);
#endif /* MASKBITS */
#if MASKBITS <= 64
			    if (!isalpha (flagbit))
				yyerror (PARSE_Y_BAD_FLAG);
#endif /* MASKBITS */
			    flagbit = CHARTOBIT (flagbit);
			    for (i = 0;  i < tblnum;  i++)
				{
				if (table[i].flagbit == flagbit)
				    yyerror (PARSE_Y_DUP_FLAG);
				}
			    for (i = 0;  i < centnum;  i++)
				{
				curents[i].flagbit = flagbit;
				curents[i].flagflags = 0;
				}
			    free ((char *) yyvsp[-2].string);
			    ;
    break;}
case 64:
#line 991 "parse.y"
{
			    int flagbit;
			    int i;

			    if (strlen ((char *) yyvsp[-2].string) != 1)
				yyerror (PARSE_Y_LONG_FLAG);
			    flagbit = (unsigned char) yyvsp[-2].string[0];
#if MASKBITS <= 128
			    flagbit &= 0x7f;
#endif /* MASKBITS */
#if MASKBITS <= 32
			    if (islower (flagbit))
				flagbit = toupper (flagbit);
#endif /* MASKBITS */
#if MASKBITS <= 64
			    if (!isalpha (flagbit))
				yyerror (PARSE_Y_BAD_FLAG);
#endif /* MASKBITS */
			    flagbit = CHARTOBIT (flagbit);
			    for (i = 0;  i < tblnum;  i++)
				{
				if (table[i].flagbit == flagbit)
				    yyerror (PARSE_Y_DUP_FLAG);
				}
			    for (i = 0;  i < centnum;  i++)
				{
				curents[i].flagbit = flagbit;
				curents[i].flagflags = yyvsp[-3].simple;
				}
			    free ((char *) yyvsp[-2].string);
			    ;
    break;}
case 65:
#line 1023 "parse.y"
{ yyval.simple = 0; ;
    break;}
case 67:
#line 1028 "parse.y"
{
			    yyval.simple = yyvsp[-1].simple | yyvsp[0].simple;
			    ;
    break;}
case 68:
#line 1034 "parse.y"
{ yyval.simple = FF_CROSSPRODUCT; ;
    break;}
case 69:
#line 1036 "parse.y"
{ yyval.simple = FF_COMPOUNDONLY; ;
    break;}
case 70:
#line 1040 "parse.y"
{
			    if (centsize == 0)
				{
				curents = (struct flagent *)
				  malloc (TBLINC * (sizeof (struct flagent)));
				if (curents == NULL)
				    {
				    yyerror (PARSE_Y_NO_SPACE);
				    exit (1);
				    }
				centsize = TBLINC;
				}
			    curents[0] = *yyvsp[0].entry;
			    centnum = 1;
			    free ((char *) yyvsp[0].entry);
			    yyval.simple = 0;
			    ;
    break;}
case 71:
#line 1058 "parse.y"
{
			    if (centnum >= centsize)
				{
				centsize += TBLINC;
				curents = (struct flagent *)
				  realloc ((char *) curents,
				    centsize * (sizeof (struct flagent)));
				if (curents == NULL)
				    {
				    yyerror (PARSE_Y_NO_SPACE);
				    exit (1);
				    }
				}
			    curents[centnum] = *yyvsp[0].entry;
			    centnum++;
			    free ((char *) yyvsp[0].entry);
			    ;
    break;}
case 72:
#line 1078 "parse.y"
{
			    int		i;

			    yyvsp[-2].entry->stripl = 0;
			    yyvsp[-2].entry->strip = NULL;
			    yyvsp[-2].entry->affl = icharlen (yyvsp[0].istr);
			    yyvsp[-2].entry->affix = yyvsp[0].istr;
			    upcase (yyvsp[0].istr);
			    /*
			     * As a special optimization (and a
			     * concession to those who prefer the syntax
			     * that way), convert any single condition
			     * that accepts all characters into no
			     * condition at all.
			     */
			    if (yyvsp[-2].entry->numconds == 1)
				{
				for (i = SET_SIZE + hashheader.nstrchars;
				  --i >= 0;
				  )
				    {
				    if ((yyvsp[-2].entry->conds[i] & 1) == 0)
					break;
				    }
				if (i < 0)
				    yyvsp[-2].entry->numconds = 0;
				}
			    yyval.entry = yyvsp[-2].entry;
			    ;
    break;}
case 73:
#line 1108 "parse.y"
{
			    register int    i;

			    yyvsp[-5].entry->stripl = icharlen (yyvsp[-2].istr);
			    yyvsp[-5].entry->strip = yyvsp[-2].istr;
			    upcase (yyvsp[-2].istr);
			    yyvsp[-5].entry->affl = icharlen (yyvsp[0].istr);
			    yyvsp[-5].entry->affix = yyvsp[0].istr;
			    upcase (yyvsp[0].istr);
			    /*
			     * Convert the syntax ". > -xxx,yyy" into
			     * " > -xxx,yyy", as in the code just above.
			     */
			    if (yyvsp[-5].entry->numconds == 1)
				{
				for (i = SET_SIZE + hashheader.nstrchars;
								  --i >= 0;)
				    {
				    if ((yyvsp[-5].entry->conds[i] & 1) == 0)
					break;
				    }
				if (i < 0)
				    yyvsp[-5].entry->numconds = 0;
				}
			    yyval.entry = yyvsp[-5].entry;
			    ;
    break;}
case 74:
#line 1135 "parse.y"
{
			    int		    i;

			    yyvsp[-5].entry->stripl = icharlen (yyvsp[-2].istr);
			    yyvsp[-5].entry->strip = yyvsp[-2].istr;
			    upcase (yyvsp[-2].istr);
			    yyvsp[-5].entry->affl = 0;
			    yyvsp[-5].entry->affix = NULL;
			    /*
			     * Convert the syntax ". > -xxx," into
			     * " > -xxx,", as in the code just above.
			     */
			    if (yyvsp[-5].entry->numconds == 1)
				{
				for (i = SET_SIZE + hashheader.nstrchars;
				  --i >= 0;
				  )
				    {
				    if ((yyvsp[-5].entry->conds[i] & 1) == 0)
					break;
				    }
				if (i < 0)
				    yyvsp[-5].entry->numconds = 0;
				}
			    yyval.entry = yyvsp[-5].entry;
			    ;
    break;}
case 75:
#line 1162 "parse.y"
{
			    int		    i;

			    yyvsp[-4].entry->stripl = 0;
			    yyvsp[-4].entry->strip = NULL;
			    yyvsp[-4].entry->affl = 0;
			    yyvsp[-4].entry->affix = NULL;
			    /*
			     * Convert the syntax ". > -,-" into
			     * " > -,-", as in the code just above.
			     */
			    if (yyvsp[-4].entry->numconds == 1)
				{
				for (i = SET_SIZE + hashheader.nstrchars;
								  --i >= 0;)
				    {
				    if ((yyvsp[-4].entry->conds[i] & 1) == 0)
					break;
				    }
				if (i < 0)
				    yyvsp[-4].entry->numconds = 0;
				}
			    yyval.entry = yyvsp[-4].entry;
			    ;
    break;}
case 76:
#line 1189 "parse.y"
{
			    struct flagent *	ent;

			    ent = (struct flagent *)
					  malloc (sizeof (struct flagent));
			    if (ent == NULL)
				{
				yyerror (PARSE_Y_NO_SPACE);
				exit (1);
				}
			    ent->numconds = 0;
			    (void) bzero (ent->conds,
			       SET_SIZE + MAXSTRINGCHARS);
			    yyval.entry = ent;
			    ;
    break;}
case 78:
#line 1208 "parse.y"
{
			    struct flagent *	ent;
			    int			i;

			    ent = (struct flagent *)
					  malloc (sizeof (struct flagent));
			    if (ent == NULL)
				{
				yyerror (PARSE_Y_NO_SPACE);
				exit (1);
				}
			    ent->numconds = 1;
			    (void) bzero (ent->conds,
			       SET_SIZE + MAXSTRINGCHARS);
			    /*
			     * Copy conditions to the new entry, making
			     * sure that uppercase versions are generated
			     * for lowercase input.
			     */
			    for (i = SET_SIZE + MAXSTRINGCHARS;  --i >= 0;  )
				{
				if (yyvsp[0].charset.set[i])
				    {
				    ent->conds[i] = 1;
				    if (!yyvsp[0].charset.complement)
					ent->conds[mytoupper ((ichar_t) i)] = 1;
				    }
				}
			    if (yyvsp[0].charset.complement)
				{
				for (i = SET_SIZE + MAXSTRINGCHARS; --i >= 0;)
				    {
				    if (yyvsp[0].charset.set[i] == 0)
					ent->conds[mytoupper ((ichar_t) i)] = 0;
				    }
				}
			    free (yyvsp[0].charset.set);
			    yyval.entry = ent;
			    ;
    break;}
case 79:
#line 1248 "parse.y"
{
			    int			i;
			    int			mask;

			    if (yyvsp[-1].entry->numconds >= 8)
				{
				yyerror (PARSE_Y_MANY_CONDS);
				yyvsp[-1].entry->numconds = 7;
				}
			    mask = 1 << yyvsp[-1].entry->numconds;
			    yyvsp[-1].entry->numconds++;
			    for (i = SET_SIZE + MAXSTRINGCHARS;
			      --i >= 0;
			      )
				{
				if (yyvsp[0].charset.set[i])
				    {
				    yyvsp[-1].entry->conds[i] |= mask;
				    if (!yyvsp[0].charset.complement)
					yyvsp[-1].entry->conds[mytoupper ((ichar_t) i)]
					  |= mask;
				    }
				}
			    if (yyvsp[0].charset.complement)
				{
				mask = ~mask;
				for (i = SET_SIZE + MAXSTRINGCHARS; --i >= 0;)
				    {
				    if (yyvsp[0].charset.set[i] == 0)
					yyvsp[-1].entry->conds[mytoupper ((ichar_t) i)]
					  &= mask;
				    }
				}
			    free (yyvsp[0].charset.set);
			    ;
    break;}
case 80:
#line 1286 "parse.y"
{
			    ichar_t *tichar;

			    tichar = strtosichar ((char *) yyvsp[0].string, 1);
			    yyval.istr = (ichar_t *) malloc (sizeof (ichar_t)
					      * (icharlen (tichar) + 1));
			    if (yyval.istr == NULL)
				{
				yyerror (PARSE_Y_NO_SPACE);
				exit (1);
				}
			    (void) icharcpy (yyval.istr, tichar);
			    free ((char *) yyvsp[0].string);
			    ;
    break;}
}
   /* the action file gets copied in in place of this dollarsign */
#line 487 "bison.simple"

  yyvsp -= yylen;
  yyssp -= yylen;
#ifdef YYLSP_NEEDED
  yylsp -= yylen;
#endif

#if YYDEBUG != 0
  if (yydebug)
    {
      short *ssp1 = yyss - 1;
      fprintf (stderr, "state stack now");
      while (ssp1 != yyssp)
	fprintf (stderr, " %d", *++ssp1);
      fprintf (stderr, "\n");
    }
#endif

  *++yyvsp = yyval;

#ifdef YYLSP_NEEDED
  yylsp++;
  if (yylen == 0)
    {
      yylsp->first_line = yylloc.first_line;
      yylsp->first_column = yylloc.first_column;
      yylsp->last_line = (yylsp-1)->last_line;
      yylsp->last_column = (yylsp-1)->last_column;
      yylsp->text = 0;
    }
  else
    {
      yylsp->last_line = (yylsp+yylen-1)->last_line;
      yylsp->last_column = (yylsp+yylen-1)->last_column;
    }
#endif

  /* Now "shift" the result of the reduction.
     Determine what state that goes to,
     based on the state we popped back to
     and the rule number reduced by.  */

  yyn = yyr1[yyn];

  yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
  if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
    yystate = yytable[yystate];
  else
    yystate = yydefgoto[yyn - YYNTBASE];

  goto yynewstate;

yyerrlab:   /* here on detecting error */

  if (! yyerrstatus)
    /* If not already recovering from an error, report this error.  */
    {
      ++yynerrs;

#ifdef YYERROR_VERBOSE
      yyn = yypact[yystate];

      if (yyn > YYFLAG && yyn < YYLAST)
	{
	  int size = 0;
	  char *msg;
	  int x, count;

	  count = 0;
	  /* Start X at -yyn if nec to avoid negative indexes in yycheck.  */
	  for (x = (yyn < 0 ? -yyn : 0);
	       x < (sizeof(yytname) / sizeof(char *)); x++)
	    if (yycheck[x + yyn] == x)
	      size += strlen(yytname[x]) + 15, count++;
	  msg = (char *) malloc(size + 15);
	  if (msg != 0)
	    {
	      strcpy(msg, "parse error");

	      if (count < 5)
		{
		  count = 0;
		  for (x = (yyn < 0 ? -yyn : 0);
		       x < (sizeof(yytname) / sizeof(char *)); x++)
		    if (yycheck[x + yyn] == x)
		      {
			strcat(msg, count == 0 ? ", expecting `" : " or `");
			strcat(msg, yytname[x]);
			strcat(msg, "'");
			count++;
		      }
		}
	      yyerror(msg);
	      free(msg);
	    }
	  else
	    yyerror ("parse error; also virtual memory exceeded");
	}
      else
#endif /* YYERROR_VERBOSE */
	yyerror("parse error");
    }

  goto yyerrlab1;
yyerrlab1:   /* here on error raised explicitly by an action */

  if (yyerrstatus == 3)
    {
      /* if just tried and failed to reuse lookahead token after an error, discard it.  */

      /* return failure if at end of input */
      if (yychar == YYEOF)
	YYABORT;

#if YYDEBUG != 0
      if (yydebug)
	fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
#endif

      yychar = YYEMPTY;
    }

  /* Else will try to reuse lookahead token
     after shifting the error token.  */

  yyerrstatus = 3;		/* Each real token shifted decrements this */

  goto yyerrhandle;

yyerrdefault:  /* current state does not do anything special for the error token. */

#if 0
  /* This is wrong; only states that explicitly want error tokens
     should shift them.  */
  yyn = yydefact[yystate];  /* If its default is to accept any token, ok.  Otherwise pop it.*/
  if (yyn) goto yydefault;
#endif

yyerrpop:   /* pop the current state because it cannot handle the error token */

  if (yyssp == yyss) YYABORT;
  yyvsp--;
  yystate = *--yyssp;
#ifdef YYLSP_NEEDED
  yylsp--;
#endif

#if YYDEBUG != 0
  if (yydebug)
    {
      short *ssp1 = yyss - 1;
      fprintf (stderr, "Error: state stack now");
      while (ssp1 != yyssp)
	fprintf (stderr, " %d", *++ssp1);
      fprintf (stderr, "\n");
    }
#endif

yyerrhandle:

  yyn = yypact[yystate];
  if (yyn == YYFLAG)
    goto yyerrdefault;

  yyn += YYTERROR;
  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
    goto yyerrdefault;

  yyn = yytable[yyn];
  if (yyn < 0)
    {
      if (yyn == YYFLAG)
	goto yyerrpop;
      yyn = -yyn;
      goto yyreduce;
    }
  else if (yyn == 0)
    goto yyerrpop;

  if (yyn == YYFINAL)
    YYACCEPT;

#if YYDEBUG != 0
  if (yydebug)
    fprintf(stderr, "Shifting error token, ");
#endif

  *++yyvsp = yylval;
#ifdef YYLSP_NEEDED
  *++yylsp = yylloc;
#endif

  yystate = yyn;
  goto yynewstate;
}
#line 1301 "parse.y"

Local struct kwtab			/* Table of built-in keywords */
		keywords[] =
    {
    {"allaffixes", ALLAFFIXES},
    {"altstringchar", ALTSTRINGCHAR},
    {"altstringtype", ALTSTRINGTYPE},
    {"boundarychars", BOUNDARYCHARS},
    {"compoundmin", COMPOUNDMIN},
    {"compoundwords", COMPOUNDWORDS},
    {"controlled", CONTROLLED},
    {"defstringtype", DEFSTRINGTYPE},
    {"flag", FLAG},
    {"flagmarker", FLAGMARKER},
    {"nroffchars", NROFFCHARS},
    {"troffchars", NROFFCHARS},
    {"on", ON},
    {"off", OFF},
    {"prefixes", PREFIXES},
    {"stringchar", STRINGCHAR},
    {"suffixes", SUFFIXES},
    {"texchars", TEXCHARS},
    {"texleftparen", 	TEXLEFTPAREN},
    {"texrightparen",   TEXRIGHTPAREN},
    {"texleftsquare",   TEXLEFTSQUARE},
    {"texrightsquare",  TEXRIGHTSQUARE},
    {"texleftcurly",    TEXLEFTCURLY},
    {"texrightcurly",   TEXRIGHTCURLY},
    {"texlefttangle",   TEXLEFTTANGLE},
    {"texrighttangle",  TEXRIGHTTANGLE},
    {"texbackslash",    TEXBACKSLASH},
    {"texdollar",       TEXDOLLAR},
    {"texstar",         TEXSTAR},
    {"texdot",          TEXDOT},
    {"texpercent",      TEXPERCENT},
    {"wordchars", WORDCHARS},
    {NULL, 0}
    };

/*
 * Trivial lexical analyzer.
 */
Local int 
yylex ()
{
    int			backslashed; /* NZ if backslash appeared */
    register int	ch;	/* Next character seen */
    register unsigned char *
			lexp;	/* Pointer into lexstring */
    unsigned char	lexstring[256];	/* Space for collecting strings */

    while ((ch = grabchar ()) != EOF  &&  (isspace (ch)  ||  ch == '#'))
	{			/* Skip whitespace and comments */
	if (ch == '#')
	    while ((ch = grabchar ()) != EOF  &&  ch != '\n')
		;
	}
    switch (ch)
	{
	case EOF:
	    return EOF;
	case '"':
	    getqstring ();
	    return STRING;
	case '-':
	case '>':
	case ',':
	case ':':
	case '.':
	case '*':
	case '~':
	    yylval.simple = ch;
	    return ch;
	case '[':		/* Beginning of a range set ] */
	    getrange ();	/* Get the range */
	    return RANGE;
	}
    /*
     * We get here if the character is an ordinary one;  note that
     * this includes backslashes.
     */
    backslashed = 0;
    lexp = lexstring;
    for ( ; ; )
	{
	switch (ch)
	    {
	    case EOF:
		*lexp = '\0';
		return kwanalyze (backslashed, lexstring);
	    case '\\':
		backslashed = 1;
		ch = backch ();
		*lexp++ = (char) ch;
		break;
	    case ' ':
	    case '\t':
	    case '\n':
	    case '\f':
	    case '\r':
		*lexp = '\0';
		return kwanalyze (backslashed, lexstring);
	    case '#':
	    case '>':
	    case ':':
	    case '-':
	    case ',':
	    case '[':			/* ] */
		ungrabchar (ch);
		*lexp = '\0';
		return kwanalyze (backslashed, lexstring);
	    default:
		*lexp++ = (char) ch;
#ifdef NO8BIT
		if (ch & 0x80)
		    yyerror (PARSE_Y_8_BIT);
#endif /* NO8BIT */
		break;
	    }
	ch = grabchar ();
	}
}

Local int 
kwanalyze (
    int			backslashed,	/* NZ if string had a backslash */
    register unsigned char * str)		/* String to analyze */
{
    register struct kwtab *
			kwptr;		/* Pointer into keyword table */

    yylval.simple = 0;
    if (!backslashed)			/* Backslash means not keyword */
	for (kwptr = keywords;  kwptr->kw != NULL;  kwptr++)
	    if (strcmp (kwptr->kw, (char *) str) == 0)
		return (yylval.simple = kwptr->val);
    yylval.string =
	      (unsigned char *) malloc ((unsigned) strlen ((char *) str) + 1);
    if (yylval.string == NULL)
	{
	yyerror (PARSE_Y_NO_SPACE);
	exit (1);
	}
    (void) strcpy ((char *) yylval.string, (char *) str);
#ifdef NO8BIT
    while (*str != '\0')
	if (*str++ & 0x80)
	    yyerror (PARSE_Y_8_BIT);
#endif /* NO8BIT */
    return STRING;
}

/*
 * Analyze a string in double quotes.  The leading quote has already
 * been processed.
 */
Local void 
getqstring ()
{
    register int	ch;		/* Next character read */
    char		lexstring[256];	/* Room to collect the string */
    register char *	lexp;		/* Pointer into lexstring */

    for (lexp = lexstring;
      (ch = grabchar ()) != EOF  &&  ch != '"'
			    &&  lexp < &lexstring[sizeof lexstring - 1];)
	{
	if (ch == '\\')
	    ch = backch ();
	*lexp++ = (char) ch;
	}
    *lexp++ = '\0';
    if (ch == EOF)
	yyerror (PARSE_Y_EOF);
    else if (ch != '"')
	{
	yyerror (PARSE_Y_LONG_QUOTE);
	while ((ch = grabchar ()) != EOF  &&  ch != '"')
	    if (ch == '\\')
		ch = backch ();
	}
    yylval.string = (unsigned char *) malloc ((unsigned) (lexp - lexstring));
    if (yylval.string == NULL)
	{
	yyerror (PARSE_Y_NO_SPACE);
	exit (1);
	}
    (void) strcpy ((char *) yylval.string, lexstring);
#ifdef NO8BIT
    for (lexp = lexstring;  *lexp != '\0';  )
	if (*lexp++ & 0x80)
	    yyerror (PARSE_Y_8_BIT);
#endif /* NO8BIT */
}

/*
 * Analyze a range (e.g., [A-Za-z]).  The left square bracket
 * has already been processed.
 */
Local void 
getrange ()			/* Parse a range set */
{
    register int	ch;		/* Next character read */
    register int	lastch;		/* Previous char, for ranges */
    char		stringch[MAXSTRINGCHARLEN];
    int			stringchlen;

    yylval.charset.set = malloc (SET_SIZE + MAXSTRINGCHARS);
    if (yylval.charset.set == NULL)
	{
	yyerror (PARSE_Y_NO_SPACE);
	exit (1);
	}

    /* Start with a null set */
    (void) bzero (yylval.charset.set, SET_SIZE + MAXSTRINGCHARS);
    yylval.charset.complement = 0;

    lastch = -1;
    ch = grabchar ();
    if (ch == '^')
	{
	yylval.charset.complement = 1;
	ch = grabchar ();
	}
    /* [ */
    if (ch == ']')
	{
	/* [[ */
	lastch = ']';
	yylval.charset.set[']'] = 1;
	}
    else
	ungrabchar (ch);
    /* [ */
    while ((ch = grabchar ()) != EOF  &&  ch != ']')
	{
	if (isstringstart (ch))		/* Handle a possible string character */
	    {
	    stringch[0] = (char) ch;
	    for (stringchlen = 1; stringchlen < MAXSTRINGCHARLEN; stringchlen++)
		{
		stringch[stringchlen] = '\0';
		if (isstringch (stringch, 1))
		    {
		    yylval.charset.set[SET_SIZE + laststringch] = 1;
		    stringchlen = 0;
		    break;
		    }
		ch = grabchar ();
		if (ch == EOF)
		    break;
		else
		    stringch[stringchlen] = (char) ch;
		}
	    if (stringchlen == 0)
		{
		lastch = -1;		/* String characters can't be ranges */
		continue;		/* We found a string character */
		}
	    /*
	     * Not a string character - put it back
	     */
	    while (--stringchlen > 0)
		ungrabchar (stringch[stringchlen] & 0xFF);
	    ch = stringch[0] & 0xFF;
	    }
	if (ch == '\\')
	    {
	    lastch = ch = backch ();
	    yylval.charset.set[ch] = 1;
	    continue;
	    }
#ifdef NO8BIT
	if (ch & 0x80)
	    {
	    yyerror (PARSE_Y_8_BIT);
	    ch &= 0x7F;
	    }
#endif /* NO8BIT */
	if (ch == '-')			/* Handle a range */
	    {
	    if (lastch == -1)
		{
		lastch = ch = '-';	/* Not really a range */
		yylval.charset.set['-'] = 1;
		}
	    else
		{
		ch = grabchar ();
		/* [ */
		if (ch == EOF  ||  ch == ']')
		    {
		    lastch = ch = '-';	/* Not really range */
		    yylval.charset.set['-'] = 1;
		    if (ch != EOF)
			ungrabchar (ch);
		    }
		else
		    {
#ifdef NO8BIT
		    if (ch & 0x80)
			{
			yyerror (PARSE_Y_8_BIT);
			ch &= 0x7F;
			}
#endif /* NO8BIT */
		    if (ch == '\\')
			ch = backch ();
		    while (lastch <= ch)
			yylval.charset.set[lastch++] = 1;
		    lastch = -1;
		    }
		}
	    }
	else
	    {
	    lastch = ch;
	    yylval.charset.set[ch] = 1;
	    }
	}
    if (yylval.charset.complement)
	for (ch = 0;  ch < SET_SIZE + MAXSTRINGCHARS;  ch++)
	    yylval.charset.set[ch] = !yylval.charset.set[ch];
}

Local int 
backch ()			/* Process post-backslash characters */
{
    register int	ch;		/* Next character read */
    register int	octval;		/* Budding octal value */

    ch = grabchar ();
    if (ch == EOF)
	return '\\';
    else if (ch >= '0'  &&  ch <= '7')
	{
	octval = ch - '0';
	ch = grabchar ();
	if (ch >= '0'  &&  ch <= '7')
	    {
	    octval = (octval << 3) + ch - '0';
	    ch = grabchar ();
	    if (ch >= '0'  &&  ch <= '7')
		octval = (octval << 3) + ch - '0';
	    else
		ungrabchar (ch);
	    }
	else if (ch != EOF)
	    ungrabchar (ch);
	ch = octval;
	}
    else if (ch == 'x')
	{
	ch = grabchar ();
	octval = 0;
	if ((ch >= '0'  &&  ch <= '9')
	  ||  (ch >= 'a'  &&  ch <= 'f')
	  ||  (ch >= 'A'  &&  ch <= 'F'))
	    {
	    if (ch >= '0'  &&  ch <= '9')
		octval = ch - '0';
	    else if (ch >= 'a'  &&  ch <= 'f')
		octval = ch - 'a' + 0xA;
	    else if (ch >= 'A'  &&  ch <= 'F')
		octval = ch - 'A' + 0xA;
	    ch = grabchar ();
	    octval <<= 4;
	    if (ch >= '0'  &&  ch <= '9')
		octval |= ch -'0';
	    else if (ch >= 'a'  &&  ch <= 'f')
		octval |= ch - 'a' + 0xA;
	    else if (ch >= 'A'  &&  ch <= 'F')
		octval |= ch - 'A' + 0xA;
	    else if (ch != EOF)
		{
		octval >>= 4;
		ungrabchar (ch);
		}
	    }
	else if (ch != EOF)
	    ungrabchar (ch);
	ch = octval;
	}
    else
	{
	switch (ch)
	    {
	    case 'n':
		ch = '\n';
		break;
	    case 'f':
		ch = '\f';
		break;
	    case 'r':
		ch = '\r';
		break;
	    case 'b':
		ch = '\b';
		break;
	    case 't':
		ch = '\t';
		break;
	    case 'v':
		ch = '\v';
		break;
	    }
	}
#ifdef NO8BIT
    if (ch & 0x80)
	{
	yyerror (PARSE_Y_8_BIT);
	ch &= 0x7F;
	}
#endif /* NO8BIT */
    return ch;
}

Local void 
yyerror (char *		str)	/* Error string */
{
    (void) fflush (stdout);
    (void) fprintf (stderr, PARSE_Y_ERROR_FORMAT(fname, lineno, str));
    (void) fflush (stderr);
}

Public Logical 
yyopen (register char *	file)	/* File name to be opened */
{
    fname = malloc ((unsigned) strlen (file) + 1);
    if (fname == NULL)
	{
	(void) fprintf (stderr, PARSE_Y_MALLOC_TROUBLE);
	exit (1);
	}
    (void) strcpy (fname, file);
    aff_file = fopen (file, "r");
    if (aff_file == NULL)
	{
	(void) fprintf (stderr, CANT_OPEN, file);
	perror ("");
	return True;
	}
    lineno = 1;
    return False;
}

Public void 
yyinit ()
{
    register unsigned int i;	/* Loop counter */

    if (aff_file == NULL)
	aff_file = stdin;	/* Must be dynamically initialized on Amigas */
    for (i = 0;  i < SET_SIZE + MAXSTRINGCHARS;  i++)
	{
	hashheader.lowerconv[i] = (ichar_t) i;
	hashheader.upperconv[i] = (ichar_t) i;
	hashheader.wordchars[i] = 0;
	hashheader.lowerchars[i] = 0;
	hashheader.upperchars[i] = 0;
	hashheader.boundarychars[i] = 0;
	/*
	 * The default sort order is a big value so that there is room
	 * to insert "underneath" it.  In this way, special characters
	 * will sort last, but in ASCII order.
	 */
	hashheader.sortorder[i] = i + 1 + 2 * SET_SIZE;
	}
    for (i = 0;  i < SET_SIZE;  i++)
	hashheader.stringstarts[i] = 0;
    for (i = 0;  i < MAXSTRINGCHARS;  i++)
	{
	hashheader.stringdups[i] = i;
	hashheader.dupnos[i] = 0;
	}
    
    hashheader.sortval = 1;	/* This is so 0 can mean uninitialized */
    (void) bcopy (NRSPECIAL, hashheader.nrchars, sizeof hashheader.nrchars);
    (void) bcopy (TEXSPECIAL, hashheader.texchars, sizeof hashheader.texchars);
    hashheader.compoundflag = COMPOUND_NEVER; /* Dflt is report missing blks */
    hashheader.defhardflag = 0; /* Default is to try hard only if failures */
    hashheader.nstrchars = 0;	/* No string characters to start with */
    hashheader.flagmarker = '/'; /* Default flag marker is slash */
    hashheader.compoundmin = 3;	/* Dflt is at least 3 chars in cmpnd parts */
    hashheader.compoundbit = -1; /* Dflt is no compound bit */
    /* Set up magic numbers and compile options */
    hashheader.magic = hashheader.magic2 = SPELL_MAGIC;
    hashheader.compileoptions = COMPILEOPTIONS;
    hashheader.maxstringchars = MAXSTRINGCHARS;
    hashheader.maxstringcharlen = MAXSTRINGCHARLEN;
    hashheader.TeXleftparen	= '(';
    hashheader.TeXrightparen	= ')';
    hashheader.TeXleftsquare	= '[';
    hashheader.TeXrightsquare	= ']';
    hashheader.TeXleftcurly	= '{';
    hashheader.TeXrightcurly	= '}';
    hashheader.TeXlefttangle	= '<';
    hashheader.TeXrighttangle	= '>';
    hashheader.TeXbackslash	= '\\';
    hashheader.TeXdollar	= '$';
    hashheader.TeXstar		= '*';
    hashheader.TeXdot		= '.';
    hashheader.TeXpercent	= '%';
}

Local int 
grabchar ()		/* Get a character and count lines */
{
    int			ch;	/* Next input character */

    if (ungrablen > 0)
	ch = lexungrab[--ungrablen] & 0xFF;
    else
	ch = getc (aff_file);
    if (ch == '\n')
	lineno++;
    return ch;
}

Local void 
ungrabchar (int ch)	/* Unget a character, tracking line numbers */
              /* Character to put back */
{

    if (ch == '\n')
	lineno--;
    if (ch != EOF)
	{
	if (ungrablen == sizeof (lexungrab))
	    yyerror (PARSE_Y_UNGRAB_PROBLEM);
	else
	    lexungrab[ungrablen++] = (char) ch;
	}
}

Local int 
sufcmp (             	/* Compare suffix flags for qsort */
    register struct flagent *	flag1,	/* Flags to be compared */
    register struct flagent *	flag2)	/* ... */
{
    register ichar_t *		cp1;	/* Pointer into flag1's suffix */
    register ichar_t *		cp2;	/* Pointer into flag2's suffix */

    if (flag1->affl == 0  ||  flag2->affl == 0)
	return flag1->affl - flag2->affl;
    cp1 = flag1->affix + flag1->affl;
    cp2 = flag2->affix + flag2->affl;
    while (*--cp1 == *--cp2  &&  cp1 > flag1->affix  &&  cp2 > flag2->affix)
	;
    if (*cp1 == *cp2)
	{
	if (cp1 == flag1->affix)
	    {
	    if (cp2 == flag2->affix)
		return 0;
	    else
		return -1;
	    }
	else
	    return 1;
	}
    return *cp1 - *cp2;
}

Local int 
precmp (             	/* Compare prefix flags for qsort */
    register struct flagent *	flag1,	/* Flags to be compared */
    register struct flagent *	flag2)	/* ... */
{

    if (flag1->affl == 0  ||  flag2->affl == 0)
	return flag1->affl - flag2->affl;
    else
	return icharcmp (flag1->affix, flag2->affix);
}

Local int 
addstringchar (                   /* Add a string character */
    register unsigned char *	str,	/* String character to be added */
    int				lower,	/* NZ if a lower string */
    int				upper)	/* NZ if an upper string */
{
    int				len;	/* Length of the string */
    register unsigned int	mslot;	/* Slot being moved or modified */
    register unsigned int	slot;	/* Where to put it */

    len = strlen ((char *) str);
    if (len > MAXSTRINGCHARLEN)
	{
	yyerror (PARSE_Y_LONG_STRING);
	}
    else if (len == 0)
	{
	yyerror (PARSE_Y_NULL_STRING);
	return -1;
	}
    else if (hashheader.nstrchars >= MAXSTRINGCHARS)
	{
	yyerror (PARSE_Y_MANY_STRINGS);
	return -1;
	}

    /*
     * Find where to put the new character
     */
    for (slot = 0;  slot < hashheader.nstrchars;  slot++)
	{
	if (stringcharcmp (&hashheader.stringchars[slot][0], (char *) str) > 0)
	    break;
	}
    /*
     * Fix all duplicate numbers to reflect the new slot.
     */
    for (mslot = 0;  mslot < hashheader.nstrchars;  mslot++)
	{
	if (hashheader.stringdups[mslot] >= slot)
	    hashheader.stringdups[mslot]++;
	}
    /*
     * Fix all characters before it so that their case conversion reflects
     * the new locations of the characters that will follow the new one.
     */
    slot += SET_SIZE;
    for (mslot = SET_SIZE;  mslot < slot;  mslot++)
	{
	if (hashheader.lowerconv[mslot] >= (ichar_t) slot)
	    hashheader.lowerconv[mslot]++;
	if (hashheader.upperconv[mslot] >= (ichar_t) slot)
	    hashheader.upperconv[mslot]++;
	}
    /*
     * Slide up all the other characters to make room for the new one, also
     * making the appropriate changes in the case-conversion tables.
     */
    for (mslot = hashheader.nstrchars + SET_SIZE;  --mslot >= slot;  )
	{
	(void) strcpy (&hashheader.stringchars[mslot + 1 - SET_SIZE][0],
	  &hashheader.stringchars[mslot - SET_SIZE][0]);
	hashheader.lowerchars[mslot + 1] = hashheader.lowerchars[mslot];
	hashheader.upperchars[mslot + 1] = hashheader.upperchars[mslot];
	hashheader.wordchars[mslot + 1] = hashheader.wordchars[mslot];
	hashheader.boundarychars[mslot + 1] = hashheader.boundarychars[mslot];
	if (hashheader.lowerconv[mslot] >= (ichar_t) slot)
	    hashheader.lowerconv[mslot]++;
	if (hashheader.upperconv[mslot] >= (ichar_t) slot)
	    hashheader.upperconv[mslot]++;
	hashheader.lowerconv[mslot + 1] = hashheader.lowerconv[mslot];
	hashheader.upperconv[mslot + 1] = hashheader.upperconv[mslot];
	hashheader.sortorder[mslot + 1] = hashheader.sortorder[mslot];
	hashheader.stringdups[mslot + 1 - SET_SIZE] =
	  hashheader.stringdups[mslot - SET_SIZE];
	hashheader.dupnos[mslot + 1 - SET_SIZE] =
	  hashheader.dupnos[mslot - SET_SIZE];
	}
    /*
     * Insert the new string character into the slot we made.  The
     * caller may choose to change the case-conversion field.
     */
    (void) strcpy (&hashheader.stringchars[slot - SET_SIZE][0], (char *) str);
    hashheader.lowerchars[slot] = (char) lower;
    hashheader.upperchars[slot] = (char) upper;
    hashheader.wordchars[slot] = 1;
    hashheader.boundarychars[slot] = 0;
    hashheader.sortorder[slot] = hashheader.sortval++;
    hashheader.lowerconv[slot] = (ichar_t) slot;
    hashheader.upperconv[slot] = (ichar_t) slot;
    hashheader.stringdups[slot - SET_SIZE] = slot - SET_SIZE;
    hashheader.dupnos[slot - SET_SIZE] = 0;
    /*
     * Add the first character of the string to the string-starts table, and
     * bump the count.
     */
    hashheader.stringstarts[str[0]] = 1;
    hashheader.nstrchars++;
    return slot;
}

/*
 * This routine is a reimplemention of strcmp(), needed because the
 * idiots at Sun managed to screw up the implementation of strcmp on
 * Sun 4's (they used unsigned comparisons, even though characters
 * default to signed).  I hate hate HATE putting in this routine just
 * to support the stupidity of one programmer who ought to find a new
 * career digging ditches, but there are a lot of Sun 4's out there,
 * so I don't really have a lot of choice.
 */
Local int 
stringcharcmp (
    register char *		a,
    register char *		b)
{

#ifdef NO8BIT
    while (*a != '\0')
	{
	if (((*a++ ^ *b++) & NOPARITY) != 0)
	    return (*--a & NOPARITY) - (*--b & NOPARITY);
	}
    return (*a & NOPARITY) - (*b & NOPARITY);
#else /* NO8BIT */
    while (*a != '\0')
	{
	if (*a++ != *b++)
	    return *--a - *--b;
	}
    return *a - *b;
#endif /* NO8BIT */
}

#ifdef TBLDEBUG
Local void 
tbldump (                	/* Dump a flag table */
    register struct flagent *	flagp,	/* First flag entry to dump */
    register int		numflags) /* Number of flags to dump */
{
    while (--numflags >= 0)
	entdump (flagp++);
}

Local void 
entdump (      		/* Dump one flag entry */
    register struct flagent *	flagp)	/* Flag entry to dump */
{
    register int		cond;	/* Condition number */

    (void) fprintf (stderr, "flag %s%c:\t",
			  (flagp->flagflags & FF_CROSSPRODUCT) ? "*" : "",
						  BITTOCHAR (flagp->flagbit));
    for (cond = 0;  cond < flagp->numconds;  cond++)
	{
	setdump (flagp->conds, 1 << cond);
	if (cond < flagp->numconds - 1)
	    (void) putc (' ', stderr);
	}
    if (cond == 0)			/* No conditions at all? */
	(void) putc ('.', stderr);
    (void) fprintf (stderr, "\t> ");
    (void) putc ('\t', stderr);
    if (flagp->stripl)
	(void) fprintf (stderr, "-%s,", ichartosstr (flagp->strip, 1));
    (void) fprintf (stderr, "%s\n",
      flagp->affl ? ichartosstr (flagp->affix, 1) : "-");
}

Local void 
setdump (           	/* Dump a set specification */
    register char *		setp,	/* Set to be dumped */
    register int		mask)	/* Mask for bit to be dumped */
{
    register int		cnum;	/* Next character's number */
    register int		firstnz; /* Number of first NZ character */
    register int		numnz;	/* Number of NZ characters */

    numnz = 0;
    for (cnum = SET_SIZE + hashheader.nstrchars;  --cnum >= 0;  )
	{
	if (setp[cnum] & mask)
	    {
	    numnz++;
	    firstnz = cnum;
	    }
	}
    if (numnz == 1)
	{
	if (cnum < SET_SIZE)
	    (void) putc (firstnz, stderr);
	else
	    (void) fputs (hashheader.stringchars[cnum - SET_SIZE], stderr);
	}
    else if (numnz == SET_SIZE)
	(void) putc ('.', stderr);
    else if (numnz > SET_SIZE / 2)
	{
	(void) fprintf (stderr, "[^");
	subsetdump (setp, mask, 0);
	(void) putc (']', stderr);
	}
    else
	{
	(void) putc ('[', stderr);
	subsetdump (setp, mask, mask);
	(void) putc (']', stderr);
	}
}

Local void 
subsetdump (                     /* Dump part of a set spec */
    register char *		setp,	/* Set to be dumped */
    register int		mask,	/* Mask for bit to be dumped */
    register int		dumpval) /* Value to be printed */
{
    register int		cnum;	/* Next character's number */
    register int		rangestart; /* Value starting a range */

    for (cnum = 0;  cnum < SET_SIZE;  setp++, cnum++)
	{
	if (((*setp ^ dumpval) & mask) == 0)
	    {
	    for (rangestart = cnum;  cnum < SET_SIZE;  setp++, cnum++)
		if ((*setp ^ dumpval) & mask)
		    break;
	    if (cnum == rangestart + 1)
		(void) putc (rangestart, stderr);
	    else if (cnum <= rangestart + 3)
		while (rangestart < cnum)
		    {
		    (void) putc (rangestart, stderr);
		    rangestart++;
		    }
	    else
		(void) fprintf (stderr, "%c-%c", rangestart, cnum - 1);
	    }
	}
    for (  ;  cnum < SET_SIZE + hashheader.nstrchars;  setp++, cnum++)
	if (((*setp ^ dumpval) & mask) == 0)
	    (void) fputs (hashheader.stringchars[cnum - SET_SIZE], stderr);
}
#endif
