1#ifndef lint
2static char yysccsid[] = "@(#)yaccpar	1.9 (Berkeley) 02/21/93 (groff)";
3#endif
4#define YYBYACC 1
5#define YYMAJOR 1
6#define YYMINOR 9
7#define yyclearin (yychar=(-1))
8#define yyerrok (yyerrflag=0)
9#define YYRECOVERING (yyerrflag!=0)
10#define YYPREFIX "yy"
11#line 23 "label.y"
12
13#include "refer.h"
14#include "refid.h"
15#include "ref.h"
16#include "token.h"
17
18int yylex();
19void yyerror(const char *);
20int yyparse();
21
22static const char *format_serial(char c, int n);
23
24struct label_info {
25  int start;
26  int length;
27  int count;
28  int total;
29  label_info(const string &);
30};
31
32label_info *lookup_label(const string &label);
33
34struct expression {
35  enum {
36    /* Does the tentative label depend on the reference?*/
37    CONTAINS_VARIABLE = 01,
38    CONTAINS_STAR = 02,
39    CONTAINS_FORMAT = 04,
40    CONTAINS_AT = 010
41  };
42  virtual ~expression() { }
43  virtual void evaluate(int, const reference &, string &,
44			substring_position &) = 0;
45  virtual unsigned analyze() { return 0; }
46};
47
48class at_expr : public expression {
49public:
50  at_expr() { }
51  void evaluate(int, const reference &, string &, substring_position &);
52  unsigned analyze() { return CONTAINS_VARIABLE|CONTAINS_AT; }
53};
54
55class format_expr : public expression {
56  char type;
57  int width;
58  int first_number;
59public:
60  format_expr(char c, int w = 0, int f = 1)
61    : type(c), width(w), first_number(f) { }
62  void evaluate(int, const reference &, string &, substring_position &);
63  unsigned analyze() { return CONTAINS_FORMAT; }
64};
65
66class field_expr : public expression {
67  int number;
68  char name;
69public:
70  field_expr(char nm, int num) : number(num), name(nm) { }
71  void evaluate(int, const reference &, string &, substring_position &);
72  unsigned analyze() { return CONTAINS_VARIABLE; }
73};
74
75class literal_expr : public expression {
76  string s;
77public:
78  literal_expr(const char *ptr, int len) : s(ptr, len) { }
79  void evaluate(int, const reference &, string &, substring_position &);
80};
81
82class unary_expr : public expression {
83protected:
84  expression *expr;
85public:
86  unary_expr(expression *e) : expr(e) { }
87  ~unary_expr() { delete expr; }
88  void evaluate(int, const reference &, string &, substring_position &) = 0;
89  unsigned analyze() { return expr ? expr->analyze() : 0; }
90};
91
92/* This caches the analysis of an expression.*/
93
94class analyzed_expr : public unary_expr {
95  unsigned flags;
96public:
97  analyzed_expr(expression *);
98  void evaluate(int, const reference &, string &, substring_position &);
99  unsigned analyze() { return flags; }
100};
101
102class star_expr : public unary_expr {
103public:
104  star_expr(expression *e) : unary_expr(e) { }
105  void evaluate(int, const reference &, string &, substring_position &);
106  unsigned analyze() {
107    return ((expr ? (expr->analyze() & ~CONTAINS_VARIABLE) : 0)
108	    | CONTAINS_STAR);
109  }
110};
111
112typedef void map_func(const char *, const char *, string &);
113
114class map_expr : public unary_expr {
115  map_func *func;
116public:
117  map_expr(expression *e, map_func *f) : unary_expr(e), func(f) { }
118  void evaluate(int, const reference &, string &, substring_position &);
119};
120
121typedef const char *extractor_func(const char *, const char *, const char **);
122
123class extractor_expr : public unary_expr {
124  int part;
125  extractor_func *func;
126public:
127  enum { BEFORE = +1, MATCH = 0, AFTER = -1 };
128  extractor_expr(expression *e, extractor_func *f, int pt)
129    : unary_expr(e), part(pt), func(f) { }
130  void evaluate(int, const reference &, string &, substring_position &);
131};
132
133class truncate_expr : public unary_expr {
134  int n;
135public:
136  truncate_expr(expression *e, int i) : unary_expr(e), n(i) { }
137  void evaluate(int, const reference &, string &, substring_position &);
138};
139
140class separator_expr : public unary_expr {
141public:
142  separator_expr(expression *e) : unary_expr(e) { }
143  void evaluate(int, const reference &, string &, substring_position &);
144};
145
146class binary_expr : public expression {
147protected:
148  expression *expr1;
149  expression *expr2;
150public:
151  binary_expr(expression *e1, expression *e2) : expr1(e1), expr2(e2) { }
152  ~binary_expr() { delete expr1; delete expr2; }
153  void evaluate(int, const reference &, string &, substring_position &) = 0;
154  unsigned analyze() {
155    return (expr1 ? expr1->analyze() : 0) | (expr2 ? expr2->analyze() : 0);
156  }
157};
158
159class alternative_expr : public binary_expr {
160public:
161  alternative_expr(expression *e1, expression *e2) : binary_expr(e1, e2) { }
162  void evaluate(int, const reference &, string &, substring_position &);
163};
164
165class list_expr : public binary_expr {
166public:
167  list_expr(expression *e1, expression *e2) : binary_expr(e1, e2) { }
168  void evaluate(int, const reference &, string &, substring_position &);
169};
170
171class substitute_expr : public binary_expr {
172public:
173  substitute_expr(expression *e1, expression *e2) : binary_expr(e1, e2) { }
174  void evaluate(int, const reference &, string &, substring_position &);
175};
176
177class ternary_expr : public expression {
178protected:
179  expression *expr1;
180  expression *expr2;
181  expression *expr3;
182public:
183  ternary_expr(expression *e1, expression *e2, expression *e3)
184    : expr1(e1), expr2(e2), expr3(e3) { }
185  ~ternary_expr() { delete expr1; delete expr2; delete expr3; }
186  void evaluate(int, const reference &, string &, substring_position &) = 0;
187  unsigned analyze() {
188    return ((expr1 ? expr1->analyze() : 0)
189	    | (expr2 ? expr2->analyze() : 0)
190	    | (expr3 ? expr3->analyze() : 0));
191  }
192};
193
194class conditional_expr : public ternary_expr {
195public:
196  conditional_expr(expression *e1, expression *e2, expression *e3)
197    : ternary_expr(e1, e2, e3) { }
198  void evaluate(int, const reference &, string &, substring_position &);
199};
200
201static expression *parsed_label = 0;
202static expression *parsed_date_label = 0;
203static expression *parsed_short_label = 0;
204
205static expression *parse_result;
206
207string literals;
208
209#line 222 "label.y"
210typedef union {
211  int num;
212  expression *expr;
213  struct { int ndigits; int val; } dig;
214  struct { int start; int len; } str;
215} YYSTYPE;
216#line 217 "y.tab.c"
217#define TOKEN_LETTER 257
218#define TOKEN_LITERAL 258
219#define TOKEN_DIGIT 259
220#define YYERRCODE 256
221short yylhs[] = {                                        -1,
222    0,    1,    1,    6,    6,    2,    2,    2,    3,    3,
223    5,    5,    4,    4,    4,    4,    4,    4,    4,    4,
224    4,    4,    4,    4,    9,    9,    7,    7,    8,    8,
225   10,   10,   10,
226};
227short yylen[] = {                                         2,
228    1,    1,    5,    0,    1,    1,    3,    3,    1,    2,
229    1,    3,    1,    1,    1,    2,    2,    2,    5,    3,
230    3,    2,    3,    3,    0,    1,    1,    2,    1,    2,
231    0,    1,    1,
232};
233short yydefred[] = {                                      0,
234    0,   14,   13,    0,    0,    0,    0,    5,    0,    0,
235    0,    0,    1,   27,    0,   17,   29,    0,    0,    0,
236    0,    0,    0,    0,    0,    0,    0,   22,    0,   28,
237   30,   23,   24,    0,    0,    0,   32,   33,    0,    0,
238    0,    0,    0,    0,    3,    0,   19,
239};
240short yydgoto[] = {                                       7,
241    8,    9,   10,   11,   12,   13,   15,   18,   47,   39,
242};
243short yysindex[] = {                                    -32,
244 -257,    0,    0, -240,  -32,  -32,    0,    0,  -18,  -32,
245  -36, -114,    0,    0, -246,    0,    0, -241,  -14,  -39,
246  -32,  -32,  -32, -114,  -21, -257, -257,    0,  -32,    0,
247    0,    0,    0,  -25,  -32,  -32,    0,    0, -223, -246,
248 -246,  -36,  -32, -257,    0, -246,    0,
249};
250short yyrindex[] = {                                     35,
251    1,    0,    0,    0,   -5,   -4,    0,    0,   14,  208,
252  159,  224,    0,    0,   11,    0,    0,   40,    0,    0,
253    2,    0,    0,  253, -220,    0,    0,    0,    0,    0,
254    0,    0,    0,    0,  263,  281,    0,    0,    0,   50,
255  105,  214,    0,  115,    0,  149,    0,
256};
257short yygindex[] = {                                      0,
258   19,    0,    7,   37,  -10,   10,  -23,    0,    0,    0,
259};
260#define YYTABLESIZE 511
261short yytable[] = {                                      24,
262   15,   14,   40,   41,    4,   28,   26,    5,   27,   25,
263   16,   29,   30,    2,   19,   20,   16,   31,   17,   23,
264   46,   37,   33,   38,   24,   24,   32,    6,   35,   36,
265   34,    3,   43,   44,    4,    4,   31,   15,   15,   18,
266   15,   15,   15,   15,   21,   15,   15,   16,   16,   20,
267   16,   16,   16,   16,    2,   16,   16,    4,   15,    4,
268   15,   45,   15,   15,   15,   42,    0,    0,   16,    0,
269   16,    2,   16,   16,   16,    2,   18,   18,    0,   18,
270   18,   18,   18,    0,   18,   18,   20,   20,    0,   20,
271   20,   20,   20,    0,   20,   20,    0,   18,    0,   18,
272    0,   18,   18,   18,   21,   22,    0,   20,    0,   20,
273    0,   20,   20,   20,   25,    0,    0,    0,    0,    0,
274    0,    0,    0,    0,   15,    0,   15,    0,    0,    0,
275    0,    0,    0,    0,   16,    0,   16,    0,    0,    0,
276    0,   21,   21,    0,   21,   21,   21,   21,   26,   21,
277   21,   25,   25,    0,   25,   25,   25,   25,   11,   25,
278   25,    0,   21,   18,   21,   18,   21,   21,   21,    0,
279    0,    0,   25,   20,   25,   20,   25,   25,   25,    0,
280    0,    0,    0,    0,    0,   26,   26,    0,   26,   26,
281   26,   26,    0,   26,   26,   11,   11,    0,   11,   11,
282    0,    0,    0,    0,    0,    0,   26,    6,   26,    0,
283   26,   26,   26,   12,    0,    0,   11,    0,   11,    0,
284   11,   11,   11,    9,    1,    2,    0,    0,   21,    0,
285   21,    0,    0,    0,    0,    0,    0,    0,   25,    0,
286   25,    0,    0,    0,    0,    6,    0,    0,    6,    0,
287   12,   12,   10,   12,   12,    0,    0,   15,   15,    0,
288    9,    9,    7,    9,    9,    6,    0,   16,   16,    6,
289    6,   12,   26,   12,   26,   12,   12,   12,    0,    0,
290    8,    9,   11,    9,   11,    9,    9,    9,    0,   10,
291   10,    0,   10,   10,    0,    0,   18,   18,    0,    0,
292    7,    0,    0,    7,    0,    0,   20,   20,    0,    0,
293   10,    0,   10,    0,   10,   10,   10,    0,    8,    0,
294    7,    8,    0,    0,    7,    7,    0,    0,    0,    0,
295    0,    6,    0,    0,    0,    0,    0,   12,    8,   12,
296    0,    0,    8,    8,    0,    0,    0,    9,    0,    0,
297    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
298    0,   21,   21,    0,    0,    0,    0,    0,    0,    0,
299    0,   25,   25,    0,    0,    0,   10,    0,    0,    0,
300    0,    0,    0,    0,    0,    0,    7,    0,    0,    0,
301    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
302    0,    0,    0,    0,    8,   26,   26,    0,    0,    0,
303    0,    0,    0,    0,    0,   11,   11,    0,    0,    0,
304    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
305    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
306    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
307    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
308    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
309   12,   12,    0,    0,    0,    0,    0,    0,    0,    0,
310    9,    9,    0,    0,    0,    0,    0,    0,    0,    0,
311    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
312    0,    0,    0,    0,    0,    0,    0,    0,    0,   10,
313   10,
314};
315short yycheck[] = {                                      10,
316    0,  259,   26,   27,   37,   42,   43,   40,   45,   46,
317    0,  126,  259,    0,    5,    6,  257,  259,  259,   38,
318   44,   43,   62,   45,   35,   36,   41,   60,   22,   23,
319   21,   64,   58,  257,    0,   41,  257,   37,   38,    0,
320   40,   41,   42,   43,   63,   45,   46,   37,   38,    0,
321   40,   41,   42,   43,   41,   45,   46,   62,   58,   58,
322   60,   43,   62,   63,   64,   29,   -1,   -1,   58,   -1,
323   60,   58,   62,   63,   64,   62,   37,   38,   -1,   40,
324   41,   42,   43,   -1,   45,   46,   37,   38,   -1,   40,
325   41,   42,   43,   -1,   45,   46,   -1,   58,   -1,   60,
326   -1,   62,   63,   64,    0,  124,   -1,   58,   -1,   60,
327   -1,   62,   63,   64,    0,   -1,   -1,   -1,   -1,   -1,
328   -1,   -1,   -1,   -1,  124,   -1,  126,   -1,   -1,   -1,
329   -1,   -1,   -1,   -1,  124,   -1,  126,   -1,   -1,   -1,
330   -1,   37,   38,   -1,   40,   41,   42,   43,    0,   45,
331   46,   37,   38,   -1,   40,   41,   42,   43,    0,   45,
332   46,   -1,   58,  124,   60,  126,   62,   63,   64,   -1,
333   -1,   -1,   58,  124,   60,  126,   62,   63,   64,   -1,
334   -1,   -1,   -1,   -1,   -1,   37,   38,   -1,   40,   41,
335   42,   43,   -1,   45,   46,   37,   38,   -1,   40,   41,
336   -1,   -1,   -1,   -1,   -1,   -1,   58,    0,   60,   -1,
337   62,   63,   64,    0,   -1,   -1,   58,   -1,   60,   -1,
338   62,   63,   64,    0,  257,  258,   -1,   -1,  124,   -1,
339  126,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  124,   -1,
340  126,   -1,   -1,   -1,   -1,   38,   -1,   -1,   41,   -1,
341   37,   38,    0,   40,   41,   -1,   -1,  257,  258,   -1,
342   37,   38,    0,   40,   41,   58,   -1,  257,  258,   62,
343   63,   58,  124,   60,  126,   62,   63,   64,   -1,   -1,
344    0,   58,  124,   60,  126,   62,   63,   64,   -1,   37,
345   38,   -1,   40,   41,   -1,   -1,  257,  258,   -1,   -1,
346   38,   -1,   -1,   41,   -1,   -1,  257,  258,   -1,   -1,
347   58,   -1,   60,   -1,   62,   63,   64,   -1,   38,   -1,
348   58,   41,   -1,   -1,   62,   63,   -1,   -1,   -1,   -1,
349   -1,  124,   -1,   -1,   -1,   -1,   -1,  124,   58,  126,
350   -1,   -1,   62,   63,   -1,   -1,   -1,  124,   -1,   -1,
351   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
352   -1,  257,  258,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
353   -1,  257,  258,   -1,   -1,   -1,  124,   -1,   -1,   -1,
354   -1,   -1,   -1,   -1,   -1,   -1,  124,   -1,   -1,   -1,
355   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
356   -1,   -1,   -1,   -1,  124,  257,  258,   -1,   -1,   -1,
357   -1,   -1,   -1,   -1,   -1,  257,  258,   -1,   -1,   -1,
358   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
359   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
360   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
361   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
362   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
363  257,  258,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
364  257,  258,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
365   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
366   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  257,
367  258,
368};
369#define YYFINAL 7
370#ifndef YYDEBUG
371#define YYDEBUG 0
372#endif
373#define YYMAXTOKEN 259
374#if YYDEBUG
375char *yyname[] = {
376"end-of-file",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,0,0,0,0,0,
3770,0,0,"'%'","'&'",0,"'('","')'","'*'","'+'",0,"'-'","'.'",0,0,0,0,0,0,0,0,0,0,0,
378"':'",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,
3790,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,0,0,0,0,0,0,0,"'|'",0,
380"'~'",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,0,0,0,0,0,0,0,0,0,
3810,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,0,0,0,0,0,0,0,0,0,0,0,
3820,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,0,0,0,0,0,0,0,0,0,0,0,
3830,0,0,0,0,0,0,0,0,0,0,0,0,"TOKEN_LETTER","TOKEN_LITERAL","TOKEN_DIGIT",
384};
385char *yyrule[] = {
386"$accept : expr",
387"expr : optional_conditional",
388"conditional : alternative",
389"conditional : alternative '?' optional_conditional ':' conditional",
390"optional_conditional :",
391"optional_conditional : conditional",
392"alternative : list",
393"alternative : alternative '|' list",
394"alternative : alternative '&' list",
395"list : substitute",
396"list : list substitute",
397"substitute : string",
398"substitute : substitute '~' string",
399"string : '@'",
400"string : TOKEN_LITERAL",
401"string : TOKEN_LETTER",
402"string : TOKEN_LETTER number",
403"string : '%' TOKEN_LETTER",
404"string : '%' digits",
405"string : string '.' flag TOKEN_LETTER optional_number",
406"string : string '+' number",
407"string : string '-' number",
408"string : string '*'",
409"string : '(' optional_conditional ')'",
410"string : '<' optional_conditional '>'",
411"optional_number :",
412"optional_number : number",
413"number : TOKEN_DIGIT",
414"number : number TOKEN_DIGIT",
415"digits : TOKEN_DIGIT",
416"digits : digits TOKEN_DIGIT",
417"flag :",
418"flag : '+'",
419"flag : '-'",
420};
421#endif
422#ifdef YYSTACKSIZE
423#undef YYMAXDEPTH
424#define YYMAXDEPTH YYSTACKSIZE
425#else
426#ifdef YYMAXDEPTH
427#define YYSTACKSIZE YYMAXDEPTH
428#else
429#define YYSTACKSIZE 500
430#define YYMAXDEPTH 500
431#endif
432#endif
433int yydebug;
434int yynerrs;
435int yyerrflag;
436int yychar;
437short *yyssp;
438YYSTYPE *yyvsp;
439YYSTYPE yyval;
440YYSTYPE yylval;
441short yyss[YYSTACKSIZE];
442YYSTYPE yyvs[YYSTACKSIZE];
443#define yystacksize YYSTACKSIZE
444#line 398 "label.y"
445
446/* bison defines const to be empty unless __STDC__ is defined, which it
447isn't under cfront */
448
449#ifdef const
450#undef const
451#endif
452
453const char *spec_ptr;
454const char *spec_end;
455const char *spec_cur;
456
457static char uppercase_array[] = {
458  'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
459  'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
460  'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
461  'Y', 'Z',
462};
463
464static char lowercase_array[] = {
465  'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
466  'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
467  'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
468  'y', 'z',
469};
470
471int yylex()
472{
473  while (spec_ptr < spec_end && csspace(*spec_ptr))
474    spec_ptr++;
475  spec_cur = spec_ptr;
476  if (spec_ptr >= spec_end)
477    return 0;
478  unsigned char c = *spec_ptr++;
479  if (csalpha(c)) {
480    yylval.num = c;
481    return TOKEN_LETTER;
482  }
483  if (csdigit(c)) {
484    yylval.num = c - '0';
485    return TOKEN_DIGIT;
486  }
487  if (c == '\'') {
488    yylval.str.start = literals.length();
489    for (; spec_ptr < spec_end; spec_ptr++) {
490      if (*spec_ptr == '\'') {
491	if (++spec_ptr < spec_end && *spec_ptr == '\'')
492	  literals += '\'';
493	else {
494	  yylval.str.len = literals.length() - yylval.str.start;
495	  return TOKEN_LITERAL;
496	}
497      }
498      else
499	literals += *spec_ptr;
500    }
501    yylval.str.len = literals.length() - yylval.str.start;
502    return TOKEN_LITERAL;
503  }
504  return c;
505}
506
507int set_label_spec(const char *label_spec)
508{
509  spec_cur = spec_ptr = label_spec;
510  spec_end = strchr(label_spec, '\0');
511  literals.clear();
512  if (yyparse())
513    return 0;
514  delete parsed_label;
515  parsed_label = parse_result;
516  return 1;
517}
518
519int set_date_label_spec(const char *label_spec)
520{
521  spec_cur = spec_ptr = label_spec;
522  spec_end = strchr(label_spec, '\0');
523  literals.clear();
524  if (yyparse())
525    return 0;
526  delete parsed_date_label;
527  parsed_date_label = parse_result;
528  return 1;
529}
530
531int set_short_label_spec(const char *label_spec)
532{
533  spec_cur = spec_ptr = label_spec;
534  spec_end = strchr(label_spec, '\0');
535  literals.clear();
536  if (yyparse())
537    return 0;
538  delete parsed_short_label;
539  parsed_short_label = parse_result;
540  return 1;
541}
542
543void yyerror(const char *message)
544{
545  if (spec_cur < spec_end)
546    command_error("label specification %1 before `%2'", message, spec_cur);
547  else
548    command_error("label specification %1 at end of string",
549		  message, spec_cur);
550}
551
552void at_expr::evaluate(int tentative, const reference &ref,
553		       string &result, substring_position &)
554{
555  if (tentative)
556    ref.canonicalize_authors(result);
557  else {
558    const char *end, *start = ref.get_authors(&end);
559    if (start)
560      result.append(start, end - start);
561  }
562}
563
564void format_expr::evaluate(int tentative, const reference &ref,
565			   string &result, substring_position &)
566{
567  if (tentative)
568    return;
569  const label_info *lp = ref.get_label_ptr();
570  int num = lp == 0 ? ref.get_number() : lp->count;
571  if (type != '0')
572    result += format_serial(type, num + 1);
573  else {
574    const char *ptr = i_to_a(num + first_number);
575    int pad = width - strlen(ptr);
576    while (--pad >= 0)
577      result += '0';
578    result += ptr;
579  }
580}
581
582static const char *format_serial(char c, int n)
583{
584  assert(n > 0);
585  static char buf[128]; // more than enough.
586  switch (c) {
587  case 'i':
588  case 'I':
589    {
590      char *p = buf;
591      // troff uses z and w to represent 10000 and 5000 in Roman
592      // numerals; I can find no historical basis for this usage
593      const char *s = c == 'i' ? "zwmdclxvi" : "ZWMDCLXVI";
594      if (n >= 40000)
595	return i_to_a(n);
596      while (n >= 10000) {
597	*p++ = s[0];
598	n -= 10000;
599      }
600      for (int i = 1000; i > 0; i /= 10, s += 2) {
601	int m = n/i;
602	n -= m*i;
603	switch (m) {
604	case 3:
605	  *p++ = s[2];
606	  /* falls through */
607	case 2:
608	  *p++ = s[2];
609	  /* falls through */
610	case 1:
611	  *p++ = s[2];
612	  break;
613	case 4:
614	  *p++ = s[2];
615	  *p++ = s[1];
616	  break;
617	case 8:
618	  *p++ = s[1];
619	  *p++ = s[2];
620	  *p++ = s[2];
621	  *p++ = s[2];
622	  break;
623	case 7:
624	  *p++ = s[1];
625	  *p++ = s[2];
626	  *p++ = s[2];
627	  break;
628	case 6:
629	  *p++ = s[1];
630	  *p++ = s[2];
631	  break;
632	case 5:
633	  *p++ = s[1];
634	  break;
635	case 9:
636	  *p++ = s[2];
637	  *p++ = s[0];
638	}
639      }
640      *p = 0;
641      break;
642    }
643  case 'a':
644  case 'A':
645    {
646      char *p = buf;
647      // this is derived from troff/reg.c
648      while (n > 0) {
649	int d = n % 26;
650	if (d == 0)
651	  d = 26;
652	n -= d;
653	n /= 26;
654	*p++ = c == 'a' ? lowercase_array[d - 1] :
655			       uppercase_array[d - 1];
656      }
657      *p-- = 0;
658      // Reverse it.
659      char *q = buf;
660      while (q < p) {
661	char temp = *q;
662	*q = *p;
663	*p = temp;
664	--p;
665	++q;
666      }
667      break;
668    }
669  default:
670    assert(0);
671  }
672  return buf;
673}
674
675void field_expr::evaluate(int, const reference &ref,
676			  string &result, substring_position &)
677{
678  const char *end;
679  const char *start = ref.get_field(name, &end);
680  if (start) {
681    start = nth_field(number, start, &end);
682    if (start)
683      result.append(start, end - start);
684  }
685}
686
687void literal_expr::evaluate(int, const reference &,
688			    string &result, substring_position &)
689{
690  result += s;
691}
692
693analyzed_expr::analyzed_expr(expression *e)
694: unary_expr(e), flags(e ? e->analyze() : 0)
695{
696}
697
698void analyzed_expr::evaluate(int tentative, const reference &ref,
699			     string &result, substring_position &pos)
700{
701  if (expr)
702    expr->evaluate(tentative, ref, result, pos);
703}
704
705void star_expr::evaluate(int tentative, const reference &ref,
706			 string &result, substring_position &pos)
707{
708  const label_info *lp = ref.get_label_ptr();
709  if (!tentative
710      && (lp == 0 || lp->total > 1)
711      && expr)
712    expr->evaluate(tentative, ref, result, pos);
713}
714
715void separator_expr::evaluate(int tentative, const reference &ref,
716			      string &result, substring_position &pos)
717{
718  int start_length = result.length();
719  int is_first = pos.start < 0;
720  if (expr)
721    expr->evaluate(tentative, ref, result, pos);
722  if (is_first) {
723    pos.start = start_length;
724    pos.length = result.length() - start_length;
725  }
726}
727
728void map_expr::evaluate(int tentative, const reference &ref,
729			string &result, substring_position &)
730{
731  if (expr) {
732    string temp;
733    substring_position temp_pos;
734    expr->evaluate(tentative, ref, temp, temp_pos);
735    (*func)(temp.contents(), temp.contents() + temp.length(), result);
736  }
737}
738
739void extractor_expr::evaluate(int tentative, const reference &ref,
740			      string &result, substring_position &)
741{
742  if (expr) {
743    string temp;
744    substring_position temp_pos;
745    expr->evaluate(tentative, ref, temp, temp_pos);
746    const char *end, *start = (*func)(temp.contents(),
747				      temp.contents() + temp.length(),
748				      &end);
749    switch (part) {
750    case BEFORE:
751      if (start)
752	result.append(temp.contents(), start - temp.contents());
753      else
754	result += temp;
755      break;
756    case MATCH:
757      if (start)
758	result.append(start, end - start);
759      break;
760    case AFTER:
761      if (start)
762	result.append(end, temp.contents() + temp.length() - end);
763      break;
764    default:
765      assert(0);
766    }
767  }
768}
769
770static void first_part(int len, const char *ptr, const char *end,
771			  string &result)
772{
773  for (;;) {
774    const char *token_start = ptr;
775    if (!get_token(&ptr, end))
776      break;
777    const token_info *ti = lookup_token(token_start, ptr);
778    int counts = ti->sortify_non_empty(token_start, ptr);
779    if (counts && --len < 0)
780      break;
781    if (counts || ti->is_accent())
782      result.append(token_start, ptr - token_start);
783  }
784}
785
786static void last_part(int len, const char *ptr, const char *end,
787		      string &result)
788{
789  const char *start = ptr;
790  int count = 0;
791  for (;;) {
792    const char *token_start = ptr;
793    if (!get_token(&ptr, end))
794      break;
795    const token_info *ti = lookup_token(token_start, ptr);
796    if (ti->sortify_non_empty(token_start, ptr))
797      count++;
798  }
799  ptr = start;
800  int skip = count - len;
801  if (skip > 0) {
802    for (;;) {
803      const char *token_start = ptr;
804      if (!get_token(&ptr, end))
805	assert(0);
806      const token_info *ti = lookup_token(token_start, ptr);
807      if (ti->sortify_non_empty(token_start, ptr) && --skip < 0) {
808	ptr = token_start;
809	break;
810      }
811    }
812  }
813  first_part(len, ptr, end, result);
814}
815
816void truncate_expr::evaluate(int tentative, const reference &ref,
817			     string &result, substring_position &)
818{
819  if (expr) {
820    string temp;
821    substring_position temp_pos;
822    expr->evaluate(tentative, ref, temp, temp_pos);
823    const char *start = temp.contents();
824    const char *end = start + temp.length();
825    if (n > 0)
826      first_part(n, start, end, result);
827    else if (n < 0)
828      last_part(-n, start, end, result);
829  }
830}
831
832void alternative_expr::evaluate(int tentative, const reference &ref,
833				string &result, substring_position &pos)
834{
835  int start_length = result.length();
836  if (expr1)
837    expr1->evaluate(tentative, ref, result, pos);
838  if (result.length() == start_length && expr2)
839    expr2->evaluate(tentative, ref, result, pos);
840}
841
842void list_expr::evaluate(int tentative, const reference &ref,
843			 string &result, substring_position &pos)
844{
845  if (expr1)
846    expr1->evaluate(tentative, ref, result, pos);
847  if (expr2)
848    expr2->evaluate(tentative, ref, result, pos);
849}
850
851void substitute_expr::evaluate(int tentative, const reference &ref,
852			       string &result, substring_position &pos)
853{
854  int start_length = result.length();
855  if (expr1)
856    expr1->evaluate(tentative, ref, result, pos);
857  if (result.length() > start_length && result[result.length() - 1] == '-') {
858    // ought to see if pos covers the -
859    result.set_length(result.length() - 1);
860    if (expr2)
861      expr2->evaluate(tentative, ref, result, pos);
862  }
863}
864
865void conditional_expr::evaluate(int tentative, const reference &ref,
866				string &result, substring_position &pos)
867{
868  string temp;
869  substring_position temp_pos;
870  if (expr1)
871    expr1->evaluate(tentative, ref, temp, temp_pos);
872  if (temp.length() > 0) {
873    if (expr2)
874      expr2->evaluate(tentative, ref, result, pos);
875  }
876  else {
877    if (expr3)
878      expr3->evaluate(tentative, ref, result, pos);
879  }
880}
881
882void reference::pre_compute_label()
883{
884  if (parsed_label != 0
885      && (parsed_label->analyze() & expression::CONTAINS_VARIABLE)) {
886    label.clear();
887    substring_position temp_pos;
888    parsed_label->evaluate(1, *this, label, temp_pos);
889    label_ptr = lookup_label(label);
890  }
891}
892
893void reference::compute_label()
894{
895  label.clear();
896  if (parsed_label)
897    parsed_label->evaluate(0, *this, label, separator_pos);
898  if (short_label_flag && parsed_short_label)
899    parsed_short_label->evaluate(0, *this, short_label, short_separator_pos);
900  if (date_as_label) {
901    string new_date;
902    if (parsed_date_label) {
903      substring_position temp_pos;
904      parsed_date_label->evaluate(0, *this, new_date, temp_pos);
905    }
906    set_date(new_date);
907  }
908  if (label_ptr)
909    label_ptr->count += 1;
910}
911
912void reference::immediate_compute_label()
913{
914  if (label_ptr)
915    label_ptr->total = 2;	// force use of disambiguator
916  compute_label();
917}
918
919int reference::merge_labels(reference **v, int n, label_type type,
920			    string &result)
921{
922  if (abbreviate_label_ranges)
923    return merge_labels_by_number(v, n, type, result);
924  else
925    return merge_labels_by_parts(v, n, type, result);
926}
927
928int reference::merge_labels_by_number(reference **v, int n, label_type type,
929				      string &result)
930{
931  if (n <= 1)
932    return 0;
933  int num = get_number();
934  // Only merge three or more labels.
935  if (v[0]->get_number() != num + 1
936      || v[1]->get_number() != num + 2)
937    return 0;
938  int i;
939  for (i = 2; i < n; i++)
940    if (v[i]->get_number() != num + i + 1)
941      break;
942  result = get_label(type);
943  result += label_range_indicator;
944  result += v[i - 1]->get_label(type);
945  return i;
946}
947
948const substring_position &reference::get_separator_pos(label_type type) const
949{
950  if (type == SHORT_LABEL && short_label_flag)
951    return short_separator_pos;
952  else
953    return separator_pos;
954}
955
956const string &reference::get_label(label_type type) const
957{
958  if (type == SHORT_LABEL && short_label_flag)
959    return short_label;
960  else
961    return label;
962}
963
964int reference::merge_labels_by_parts(reference **v, int n, label_type type,
965				     string &result)
966{
967  if (n <= 0)
968    return 0;
969  const string &lb = get_label(type);
970  const substring_position &sp = get_separator_pos(type);
971  if (sp.start < 0
972      || sp.start != v[0]->get_separator_pos(type).start
973      || memcmp(lb.contents(), v[0]->get_label(type).contents(),
974		sp.start) != 0)
975    return 0;
976  result = lb;
977  int i = 0;
978  do {
979    result += separate_label_second_parts;
980    const substring_position &s = v[i]->get_separator_pos(type);
981    int sep_end_pos = s.start + s.length;
982    result.append(v[i]->get_label(type).contents() + sep_end_pos,
983		  v[i]->get_label(type).length() - sep_end_pos);
984  } while (++i < n
985	   && sp.start == v[i]->get_separator_pos(type).start
986	   && memcmp(lb.contents(), v[i]->get_label(type).contents(),
987		     sp.start) == 0);
988  return i;
989}
990
991string label_pool;
992
993label_info::label_info(const string &s)
994: start(label_pool.length()), length(s.length()), count(0), total(1)
995{
996  label_pool += s;
997}
998
999static label_info **label_table = 0;
1000static int label_table_size = 0;
1001static int label_table_used = 0;
1002
1003label_info *lookup_label(const string &label)
1004{
1005  if (label_table == 0) {
1006    label_table = new label_info *[17];
1007    label_table_size = 17;
1008    for (int i = 0; i < 17; i++)
1009      label_table[i] = 0;
1010  }
1011  unsigned h = hash_string(label.contents(), label.length()) % label_table_size;
1012  label_info **ptr;
1013  for (ptr = label_table + h;
1014       *ptr != 0;
1015       (ptr == label_table)
1016       ? (ptr = label_table + label_table_size - 1)
1017       : ptr--)
1018    if ((*ptr)->length == label.length()
1019	&& memcmp(label_pool.contents() + (*ptr)->start, label.contents(),
1020		  label.length()) == 0) {
1021      (*ptr)->total += 1;
1022      return *ptr;
1023    }
1024  label_info *result = *ptr = new label_info(label);
1025  if (++label_table_used * 2 > label_table_size) {
1026    // Rehash the table.
1027    label_info **old_table = label_table;
1028    int old_size = label_table_size;
1029    label_table_size = next_size(label_table_size);
1030    label_table = new label_info *[label_table_size];
1031    int i;
1032    for (i = 0; i < label_table_size; i++)
1033      label_table[i] = 0;
1034    for (i = 0; i < old_size; i++)
1035      if (old_table[i]) {
1036	h = hash_string(label_pool.contents() + old_table[i]->start,
1037			old_table[i]->length);
1038	label_info **p;
1039	for (p = label_table + (h % label_table_size);
1040	     *p != 0;
1041	     (p == label_table)
1042	     ? (p = label_table + label_table_size - 1)
1043	     : --p)
1044	    ;
1045	*p = old_table[i];
1046	}
1047    a_delete old_table;
1048  }
1049  return result;
1050}
1051
1052void clear_labels()
1053{
1054  for (int i = 0; i < label_table_size; i++) {
1055    delete label_table[i];
1056    label_table[i] = 0;
1057  }
1058  label_table_used = 0;
1059  label_pool.clear();
1060}
1061
1062static void consider_authors(reference **start, reference **end, int i);
1063
1064void compute_labels(reference **v, int n)
1065{
1066  if (parsed_label
1067      && (parsed_label->analyze() & expression::CONTAINS_AT)
1068      && sort_fields.length() >= 2
1069      && sort_fields[0] == 'A'
1070      && sort_fields[1] == '+')
1071    consider_authors(v, v + n, 0);
1072  for (int i = 0; i < n; i++)
1073    v[i]->compute_label();
1074}
1075
1076
1077/* A reference with a list of authors <A0,A1,...,AN> _needs_ author i
1078where 0 <= i <= N if there exists a reference with a list of authors
1079<B0,B1,...,BM> such that <A0,A1,...,AN> != <B0,B1,...,BM> and M >= i
1080and Aj = Bj for 0 <= j < i. In this case if we can't say ``A0,
1081A1,...,A(i-1) et al'' because this would match both <A0,A1,...,AN> and
1082<B0,B1,...,BM>.  If a reference needs author i we only have to call
1083need_author(j) for some j >= i such that the reference also needs
1084author j. */
1085
1086/* This function handles 2 tasks:
1087determine which authors are needed (cannot be elided with et al.);
1088determine which authors can have only last names in the labels.
1089
1090References >= start and < end have the same first i author names.
1091Also they're sorted by A+. */
1092
1093static void consider_authors(reference **start, reference **end, int i)
1094{
1095  if (start >= end)
1096    return;
1097  reference **p = start;
1098  if (i >= (*p)->get_nauthors()) {
1099    for (++p; p < end && i >= (*p)->get_nauthors(); p++)
1100      ;
1101    if (p < end && i > 0) {
1102      // If we have an author list <A B C> and an author list <A B C D>,
1103      // then both lists need C.
1104      for (reference **q = start; q < end; q++)
1105	(*q)->need_author(i - 1);
1106    }
1107    start = p;
1108  }
1109  while (p < end) {
1110    reference **last_name_start = p;
1111    reference **name_start = p;
1112    for (++p;
1113	 p < end && i < (*p)->get_nauthors()
1114	 && same_author_last_name(**last_name_start, **p, i);
1115	 p++) {
1116      if (!same_author_name(**name_start, **p, i)) {
1117	consider_authors(name_start, p, i + 1);
1118	name_start = p;
1119      }
1120    }
1121    consider_authors(name_start, p, i + 1);
1122    if (last_name_start == name_start) {
1123      for (reference **q = last_name_start; q < p; q++)
1124	(*q)->set_last_name_unambiguous(i);
1125    }
1126    // If we have an author list <A B C D> and <A B C E>, then the lists
1127    // need author D and E respectively.
1128    if (name_start > start || p < end) {
1129      for (reference **q = last_name_start; q < p; q++)
1130	(*q)->need_author(i);
1131    }
1132  }
1133}
1134
1135int same_author_last_name(const reference &r1, const reference &r2, int n)
1136{
1137  const char *ae1;
1138  const char *as1 = r1.get_sort_field(0, n, 0, &ae1);
1139  const char *ae2;
1140  const char *as2 = r2.get_sort_field(0, n, 0, &ae2);
1141  if (!as1 && !as2) return 1;	// they are the same
1142  if (!as1 || !as2) return 0;
1143  return ae1 - as1 == ae2 - as2 && memcmp(as1, as2, ae1 - as1) == 0;
1144}
1145
1146int same_author_name(const reference &r1, const reference &r2, int n)
1147{
1148  const char *ae1;
1149  const char *as1 = r1.get_sort_field(0, n, -1, &ae1);
1150  const char *ae2;
1151  const char *as2 = r2.get_sort_field(0, n, -1, &ae2);
1152  if (!as1 && !as2) return 1;	// they are the same
1153  if (!as1 || !as2) return 0;
1154  return ae1 - as1 == ae2 - as2 && memcmp(as1, as2, ae1 - as1) == 0;
1155}
1156
1157
1158void int_set::set(int i)
1159{
1160  assert(i >= 0);
1161  int bytei = i >> 3;
1162  if (bytei >= v.length()) {
1163    int old_length = v.length();
1164    v.set_length(bytei + 1);
1165    for (int j = old_length; j <= bytei; j++)
1166      v[j] = 0;
1167  }
1168  v[bytei] |= 1 << (i & 7);
1169}
1170
1171int int_set::get(int i) const
1172{
1173  assert(i >= 0);
1174  int bytei = i >> 3;
1175  return bytei >= v.length() ? 0 : (v[bytei] & (1 << (i & 7))) != 0;
1176}
1177
1178void reference::set_last_name_unambiguous(int i)
1179{
1180  last_name_unambiguous.set(i);
1181}
1182
1183void reference::need_author(int n)
1184{
1185  if (n > last_needed_author)
1186    last_needed_author = n;
1187}
1188
1189const char *reference::get_authors(const char **end) const
1190{
1191  if (!computed_authors) {
1192    ((reference *)this)->computed_authors = 1;
1193    string &result = ((reference *)this)->authors;
1194    int na = get_nauthors();
1195    result.clear();
1196    for (int i = 0; i < na; i++) {
1197      if (last_name_unambiguous.get(i)) {
1198	const char *e, *start = get_author_last_name(i, &e);
1199	assert(start != 0);
1200	result.append(start, e - start);
1201      }
1202      else {
1203	const char *e, *start = get_author(i, &e);
1204	assert(start != 0);
1205	result.append(start, e - start);
1206      }
1207      if (i == last_needed_author
1208	  && et_al.length() > 0
1209	  && et_al_min_elide > 0
1210	  && last_needed_author + et_al_min_elide < na
1211	  && na >= et_al_min_total) {
1212	result += et_al;
1213	break;
1214      }
1215      if (i < na - 1) {
1216	if (na == 2)
1217	  result += join_authors_exactly_two;
1218	else if (i < na - 2)
1219	  result += join_authors_default;
1220	else
1221	  result += join_authors_last_two;
1222      }
1223    }
1224  }
1225  const char *start = authors.contents();
1226  *end = start + authors.length();
1227  return start;
1228}
1229
1230int reference::get_nauthors() const
1231{
1232  if (nauthors < 0) {
1233    const char *dummy;
1234    int na;
1235    for (na = 0; get_author(na, &dummy) != 0; na++)
1236      ;
1237    ((reference *)this)->nauthors = na;
1238  }
1239  return nauthors;
1240}
1241#line 1242 "y.tab.c"
1242#define YYABORT goto yyabort
1243#define YYREJECT goto yyabort
1244#define YYACCEPT goto yyaccept
1245#define YYERROR goto yyerrlab
1246int
1247#if defined(__STDC__)
1248yyparse(void)
1249#else
1250yyparse()
1251#endif
1252{
1253    register int yym, yyn, yystate;
1254#if YYDEBUG
1255    register char *yys;
1256    extern char *getenv();
1257
1258    if (yys = getenv("YYDEBUG"))
1259    {
1260        yyn = *yys;
1261        if (yyn >= '0' && yyn <= '9')
1262            yydebug = yyn - '0';
1263    }
1264#endif
1265
1266    yynerrs = 0;
1267    yyerrflag = 0;
1268    yychar = (-1);
1269
1270    yyssp = yyss;
1271    yyvsp = yyvs;
1272    *yyssp = yystate = 0;
1273
1274yyloop:
1275    if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
1276    if (yychar < 0)
1277    {
1278        if ((yychar = yylex()) < 0) yychar = 0;
1279#if YYDEBUG
1280        if (yydebug)
1281        {
1282            yys = 0;
1283            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1284            if (!yys) yys = "illegal-symbol";
1285            printf("%sdebug: state %d, reading %d (%s)\n",
1286                    YYPREFIX, yystate, yychar, yys);
1287        }
1288#endif
1289    }
1290    if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
1291            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
1292    {
1293#if YYDEBUG
1294        if (yydebug)
1295            printf("%sdebug: state %d, shifting to state %d\n",
1296                    YYPREFIX, yystate, yytable[yyn]);
1297#endif
1298        if (yyssp >= yyss + yystacksize - 1)
1299        {
1300            goto yyoverflow;
1301        }
1302        *++yyssp = yystate = yytable[yyn];
1303        *++yyvsp = yylval;
1304        yychar = (-1);
1305        if (yyerrflag > 0)  --yyerrflag;
1306        goto yyloop;
1307    }
1308    if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
1309            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
1310    {
1311        yyn = yytable[yyn];
1312        goto yyreduce;
1313    }
1314    if (yyerrflag) goto yyinrecovery;
1315#ifdef lint
1316    goto yynewerror;
1317#endif
1318yynewerror:
1319    yyerror("syntax error");
1320#ifdef lint
1321    goto yyerrlab;
1322#endif
1323yyerrlab:
1324    ++yynerrs;
1325yyinrecovery:
1326    if (yyerrflag < 3)
1327    {
1328        yyerrflag = 3;
1329        for (;;)
1330        {
1331            if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&
1332                    yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
1333            {
1334#if YYDEBUG
1335                if (yydebug)
1336                    printf("%sdebug: state %d, error recovery shifting\
1337 to state %d\n", YYPREFIX, *yyssp, yytable[yyn]);
1338#endif
1339                if (yyssp >= yyss + yystacksize - 1)
1340                {
1341                    goto yyoverflow;
1342                }
1343                *++yyssp = yystate = yytable[yyn];
1344                *++yyvsp = yylval;
1345                goto yyloop;
1346            }
1347            else
1348            {
1349#if YYDEBUG
1350                if (yydebug)
1351                    printf("%sdebug: error recovery discarding state %d\n",
1352                            YYPREFIX, *yyssp);
1353#endif
1354                if (yyssp <= yyss) goto yyabort;
1355                --yyssp;
1356                --yyvsp;
1357            }
1358        }
1359    }
1360    else
1361    {
1362        if (yychar == 0) goto yyabort;
1363#if YYDEBUG
1364        if (yydebug)
1365        {
1366            yys = 0;
1367            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1368            if (!yys) yys = "illegal-symbol";
1369            printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
1370                    YYPREFIX, yystate, yychar, yys);
1371        }
1372#endif
1373        yychar = (-1);
1374        goto yyloop;
1375    }
1376yyreduce:
1377#if YYDEBUG
1378    if (yydebug)
1379        printf("%sdebug: state %d, reducing by rule %d (%s)\n",
1380                YYPREFIX, yystate, yyn, yyrule[yyn]);
1381#endif
1382    yym = yylen[yyn];
1383    yyval = yyvsp[1-yym];
1384    switch (yyn)
1385    {
1386case 1:
1387#line 251 "label.y"
1388{ parse_result = (yyvsp[0].expr ? new analyzed_expr(yyvsp[0].expr) : 0); }
1389break;
1390case 2:
1391#line 256 "label.y"
1392{ yyval.expr = yyvsp[0].expr; }
1393break;
1394case 3:
1395#line 258 "label.y"
1396{ yyval.expr = new conditional_expr(yyvsp[-4].expr, yyvsp[-2].expr, yyvsp[0].expr); }
1397break;
1398case 4:
1399#line 263 "label.y"
1400{ yyval.expr = 0; }
1401break;
1402case 5:
1403#line 265 "label.y"
1404{ yyval.expr = yyvsp[0].expr; }
1405break;
1406case 6:
1407#line 270 "label.y"
1408{ yyval.expr = yyvsp[0].expr; }
1409break;
1410case 7:
1411#line 272 "label.y"
1412{ yyval.expr = new alternative_expr(yyvsp[-2].expr, yyvsp[0].expr); }
1413break;
1414case 8:
1415#line 274 "label.y"
1416{ yyval.expr = new conditional_expr(yyvsp[-2].expr, yyvsp[0].expr, 0); }
1417break;
1418case 9:
1419#line 279 "label.y"
1420{ yyval.expr = yyvsp[0].expr; }
1421break;
1422case 10:
1423#line 281 "label.y"
1424{ yyval.expr = new list_expr(yyvsp[-1].expr, yyvsp[0].expr); }
1425break;
1426case 11:
1427#line 286 "label.y"
1428{ yyval.expr = yyvsp[0].expr; }
1429break;
1430case 12:
1431#line 288 "label.y"
1432{ yyval.expr = new substitute_expr(yyvsp[-2].expr, yyvsp[0].expr); }
1433break;
1434case 13:
1435#line 293 "label.y"
1436{ yyval.expr = new at_expr; }
1437break;
1438case 14:
1439#line 295 "label.y"
1440{
1441		  yyval.expr = new literal_expr(literals.contents() + yyvsp[0].str.start,
1442					yyvsp[0].str.len);
1443		}
1444break;
1445case 15:
1446#line 300 "label.y"
1447{ yyval.expr = new field_expr(yyvsp[0].num, 0); }
1448break;
1449case 16:
1450#line 302 "label.y"
1451{ yyval.expr = new field_expr(yyvsp[-1].num, yyvsp[0].num - 1); }
1452break;
1453case 17:
1454#line 304 "label.y"
1455{
1456		  switch (yyvsp[0].num) {
1457		  case 'I':
1458		  case 'i':
1459		  case 'A':
1460		  case 'a':
1461		    yyval.expr = new format_expr(yyvsp[0].num);
1462		    break;
1463		  default:
1464		    command_error("unrecognized format `%1'", char(yyvsp[0].num));
1465		    yyval.expr = new format_expr('a');
1466		    break;
1467		  }
1468		}
1469break;
1470case 18:
1471#line 320 "label.y"
1472{
1473		  yyval.expr = new format_expr('0', yyvsp[0].dig.ndigits, yyvsp[0].dig.val);
1474		}
1475break;
1476case 19:
1477#line 324 "label.y"
1478{
1479		  switch (yyvsp[-1].num) {
1480		  case 'l':
1481		    yyval.expr = new map_expr(yyvsp[-4].expr, lowercase);
1482		    break;
1483		  case 'u':
1484		    yyval.expr = new map_expr(yyvsp[-4].expr, uppercase);
1485		    break;
1486		  case 'c':
1487		    yyval.expr = new map_expr(yyvsp[-4].expr, capitalize);
1488		    break;
1489		  case 'r':
1490		    yyval.expr = new map_expr(yyvsp[-4].expr, reverse_name);
1491		    break;
1492		  case 'a':
1493		    yyval.expr = new map_expr(yyvsp[-4].expr, abbreviate_name);
1494		    break;
1495		  case 'y':
1496		    yyval.expr = new extractor_expr(yyvsp[-4].expr, find_year, yyvsp[-2].num);
1497		    break;
1498		  case 'n':
1499		    yyval.expr = new extractor_expr(yyvsp[-4].expr, find_last_name, yyvsp[-2].num);
1500		    break;
1501		  default:
1502		    yyval.expr = yyvsp[-4].expr;
1503		    command_error("unknown function `%1'", char(yyvsp[-1].num));
1504		    break;
1505		  }
1506		}
1507break;
1508case 20:
1509#line 355 "label.y"
1510{ yyval.expr = new truncate_expr(yyvsp[-2].expr, yyvsp[0].num); }
1511break;
1512case 21:
1513#line 357 "label.y"
1514{ yyval.expr = new truncate_expr(yyvsp[-2].expr, -yyvsp[0].num); }
1515break;
1516case 22:
1517#line 359 "label.y"
1518{ yyval.expr = new star_expr(yyvsp[-1].expr); }
1519break;
1520case 23:
1521#line 361 "label.y"
1522{ yyval.expr = yyvsp[-1].expr; }
1523break;
1524case 24:
1525#line 363 "label.y"
1526{ yyval.expr = new separator_expr(yyvsp[-1].expr); }
1527break;
1528case 25:
1529#line 368 "label.y"
1530{ yyval.num = -1; }
1531break;
1532case 26:
1533#line 370 "label.y"
1534{ yyval.num = yyvsp[0].num; }
1535break;
1536case 27:
1537#line 375 "label.y"
1538{ yyval.num = yyvsp[0].num; }
1539break;
1540case 28:
1541#line 377 "label.y"
1542{ yyval.num = yyvsp[-1].num*10 + yyvsp[0].num; }
1543break;
1544case 29:
1545#line 382 "label.y"
1546{ yyval.dig.ndigits = 1; yyval.dig.val = yyvsp[0].num; }
1547break;
1548case 30:
1549#line 384 "label.y"
1550{ yyval.dig.ndigits = yyvsp[-1].dig.ndigits + 1; yyval.dig.val = yyvsp[-1].dig.val*10 + yyvsp[0].num; }
1551break;
1552case 31:
1553#line 390 "label.y"
1554{ yyval.num = 0; }
1555break;
1556case 32:
1557#line 392 "label.y"
1558{ yyval.num = 1; }
1559break;
1560case 33:
1561#line 394 "label.y"
1562{ yyval.num = -1; }
1563break;
1564#line 1565 "y.tab.c"
1565    }
1566    yyssp -= yym;
1567    yystate = *yyssp;
1568    yyvsp -= yym;
1569    yym = yylhs[yyn];
1570    if (yystate == 0 && yym == 0)
1571    {
1572#if YYDEBUG
1573        if (yydebug)
1574            printf("%sdebug: after reduction, shifting from state 0 to\
1575 state %d\n", YYPREFIX, YYFINAL);
1576#endif
1577        yystate = YYFINAL;
1578        *++yyssp = YYFINAL;
1579        *++yyvsp = yyval;
1580        if (yychar < 0)
1581        {
1582            if ((yychar = yylex()) < 0) yychar = 0;
1583#if YYDEBUG
1584            if (yydebug)
1585            {
1586                yys = 0;
1587                if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1588                if (!yys) yys = "illegal-symbol";
1589                printf("%sdebug: state %d, reading %d (%s)\n",
1590                        YYPREFIX, YYFINAL, yychar, yys);
1591            }
1592#endif
1593        }
1594        if (yychar == 0) goto yyaccept;
1595        goto yyloop;
1596    }
1597    if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
1598            yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
1599        yystate = yytable[yyn];
1600    else
1601        yystate = yydgoto[yym];
1602#if YYDEBUG
1603    if (yydebug)
1604        printf("%sdebug: after reduction, shifting from state %d \
1605to state %d\n", YYPREFIX, *yyssp, yystate);
1606#endif
1607    if (yyssp >= yyss + yystacksize - 1)
1608    {
1609        goto yyoverflow;
1610    }
1611    *++yyssp = yystate;
1612    *++yyvsp = yyval;
1613    goto yyloop;
1614yyoverflow:
1615    yyerror("yacc stack overflow");
1616yyabort:
1617    return (1);
1618yyaccept:
1619    return (0);
1620}
1621