Add groff 1.19.1, stripped down appropriately.
[dragonfly.git] / contrib / groff-1.19 / src / preproc / refer / label.cpp
1 #ifndef lint
2 static 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
18 int yylex();
19 void yyerror(const char *);
20 int yyparse();
21
22 static const char *format_serial(char c, int n);
23
24 struct label_info {
25   int start;
26   int length;
27   int count;
28   int total;
29   label_info(const string &);
30 };
31
32 label_info *lookup_label(const string &label);
33
34 struct 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
48 class at_expr : public expression {
49 public:
50   at_expr() { }
51   void evaluate(int, const reference &, string &, substring_position &);
52   unsigned analyze() { return CONTAINS_VARIABLE|CONTAINS_AT; }
53 };
54
55 class format_expr : public expression {
56   char type;
57   int width;
58   int first_number;
59 public:
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
66 class field_expr : public expression {
67   int number;
68   char name;
69 public:
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
75 class literal_expr : public expression {
76   string s;
77 public:
78   literal_expr(const char *ptr, int len) : s(ptr, len) { }
79   void evaluate(int, const reference &, string &, substring_position &);
80 };
81
82 class unary_expr : public expression {
83 protected:
84   expression *expr;
85 public:
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
94 class analyzed_expr : public unary_expr {
95   unsigned flags;
96 public:
97   analyzed_expr(expression *);
98   void evaluate(int, const reference &, string &, substring_position &);
99   unsigned analyze() { return flags; }
100 };
101
102 class star_expr : public unary_expr {
103 public:
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
112 typedef void map_func(const char *, const char *, string &);
113
114 class map_expr : public unary_expr {
115   map_func *func;
116 public:
117   map_expr(expression *e, map_func *f) : unary_expr(e), func(f) { }
118   void evaluate(int, const reference &, string &, substring_position &);
119 };
120   
121 typedef const char *extractor_func(const char *, const char *, const char **);
122
123 class extractor_expr : public unary_expr {
124   int part;
125   extractor_func *func;
126 public:
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
133 class truncate_expr : public unary_expr {
134   int n;
135 public:
136   truncate_expr(expression *e, int i) : unary_expr(e), n(i) { } 
137   void evaluate(int, const reference &, string &, substring_position &);
138 };
139
140 class separator_expr : public unary_expr {
141 public:
142   separator_expr(expression *e) : unary_expr(e) { }
143   void evaluate(int, const reference &, string &, substring_position &);
144 };
145
146 class binary_expr : public expression {
147 protected:
148   expression *expr1;
149   expression *expr2;
150 public:
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
159 class alternative_expr : public binary_expr {
160 public:
161   alternative_expr(expression *e1, expression *e2) : binary_expr(e1, e2) { }
162   void evaluate(int, const reference &, string &, substring_position &);
163 };
164
165 class list_expr : public binary_expr {
166 public:
167   list_expr(expression *e1, expression *e2) : binary_expr(e1, e2) { }
168   void evaluate(int, const reference &, string &, substring_position &);
169 };
170
171 class substitute_expr : public binary_expr {
172 public:
173   substitute_expr(expression *e1, expression *e2) : binary_expr(e1, e2) { }
174   void evaluate(int, const reference &, string &, substring_position &);
175 };
176
177 class ternary_expr : public expression {
178 protected:
179   expression *expr1;
180   expression *expr2;
181   expression *expr3;
182 public:
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
194 class conditional_expr : public ternary_expr {
195 public:
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
201 static expression *parsed_label = 0;
202 static expression *parsed_date_label = 0;
203 static expression *parsed_short_label = 0;
204
205 static expression *parse_result;
206
207 string literals;
208
209 #line 222 "label.y"
210 typedef 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
221 short 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 };
227 short 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 };
233 short 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 };
240 short yydgoto[] = {                                       7,
241     8,    9,   10,   11,   12,   13,   15,   18,   47,   39,
242 };
243 short 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 };
250 short 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 };
257 short yygindex[] = {                                      0,
258    19,    0,    7,   37,  -10,   10,  -23,    0,    0,    0,
259 };
260 #define YYTABLESIZE 511
261 short 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 };
315 short 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
375 char *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,
377 0,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,
379 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,
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,
381 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,0,
382 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,0,
383 0,0,0,0,0,0,0,0,0,0,0,0,0,"TOKEN_LETTER","TOKEN_LITERAL","TOKEN_DIGIT",
384 };
385 char *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
433 int yydebug;
434 int yynerrs;
435 int yyerrflag;
436 int yychar;
437 short *yyssp;
438 YYSTYPE *yyvsp;
439 YYSTYPE yyval;
440 YYSTYPE yylval;
441 short yyss[YYSTACKSIZE];
442 YYSTYPE 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
447 isn't under cfront */
448
449 #ifdef const
450 #undef const
451 #endif
452
453 const char *spec_ptr;
454 const char *spec_end;
455 const char *spec_cur;
456
457 static 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   
464 static 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
471 int 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
507 int 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
519 int 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
531 int 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
543 void 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
552 void 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
564 void 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
582 static 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
675 void 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
687 void literal_expr::evaluate(int, const reference &,
688                             string &result, substring_position &)
689 {
690   result += s;
691 }
692
693 analyzed_expr::analyzed_expr(expression *e)
694 : unary_expr(e), flags(e ? e->analyze() : 0)
695 {
696 }
697
698 void 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
705 void 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
715 void 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
728 void 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
739 void 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
770 static 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
786 static 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
816 void 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
832 void 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
842 void 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
851 void 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
865 void 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
882 void 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
893 void 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
912 void reference::immediate_compute_label()
913 {
914   if (label_ptr)
915     label_ptr->total = 2;       // force use of disambiguator
916   compute_label();
917 }
918
919 int 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
928 int 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
948 const 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
956 const 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
964 int 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
991 string label_pool;
992
993 label_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
999 static label_info **label_table = 0;
1000 static int label_table_size = 0;
1001 static int label_table_used = 0;
1002
1003 label_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
1052 void 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
1062 static void consider_authors(reference **start, reference **end, int i);
1063
1064 void 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
1078 where 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
1080 and Aj = Bj for 0 <= j < i. In this case if we can't say ``A0,
1081 A1,...,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
1083 need_author(j) for some j >= i such that the reference also needs
1084 author j. */
1085
1086 /* This function handles 2 tasks:
1087 determine which authors are needed (cannot be elided with et al.);
1088 determine which authors can have only last names in the labels.
1089
1090 References >= start and < end have the same first i author names.
1091 Also they're sorted by A+. */
1092
1093 static 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
1135 int 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
1146 int 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
1158 void 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
1171 int 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
1178 void reference::set_last_name_unambiguous(int i)
1179 {
1180   last_name_unambiguous.set(i);
1181 }
1182
1183 void reference::need_author(int n)
1184 {
1185   if (n > last_needed_author)
1186     last_needed_author = n;
1187 }
1188
1189 const 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
1230 int 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
1246 int
1247 #if defined(__STDC__)
1248 yyparse(void)
1249 #else
1250 yyparse()
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
1274 yyloop:
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
1318 yynewerror:
1319     yyerror("syntax error");
1320 #ifdef lint
1321     goto yyerrlab;
1322 #endif
1323 yyerrlab:
1324     ++yynerrs;
1325 yyinrecovery:
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     }
1376 yyreduce:
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     {
1386 case 1:
1387 #line 251 "label.y"
1388 { parse_result = (yyvsp[0].expr ? new analyzed_expr(yyvsp[0].expr) : 0); }
1389 break;
1390 case 2:
1391 #line 256 "label.y"
1392 { yyval.expr = yyvsp[0].expr; }
1393 break;
1394 case 3:
1395 #line 258 "label.y"
1396 { yyval.expr = new conditional_expr(yyvsp[-4].expr, yyvsp[-2].expr, yyvsp[0].expr); }
1397 break;
1398 case 4:
1399 #line 263 "label.y"
1400 { yyval.expr = 0; }
1401 break;
1402 case 5:
1403 #line 265 "label.y"
1404 { yyval.expr = yyvsp[0].expr; }
1405 break;
1406 case 6:
1407 #line 270 "label.y"
1408 { yyval.expr = yyvsp[0].expr; }
1409 break;
1410 case 7:
1411 #line 272 "label.y"
1412 { yyval.expr = new alternative_expr(yyvsp[-2].expr, yyvsp[0].expr); }
1413 break;
1414 case 8:
1415 #line 274 "label.y"
1416 { yyval.expr = new conditional_expr(yyvsp[-2].expr, yyvsp[0].expr, 0); }
1417 break;
1418 case 9:
1419 #line 279 "label.y"
1420 { yyval.expr = yyvsp[0].expr; }
1421 break;
1422 case 10:
1423 #line 281 "label.y"
1424 { yyval.expr = new list_expr(yyvsp[-1].expr, yyvsp[0].expr); }
1425 break;
1426 case 11:
1427 #line 286 "label.y"
1428 { yyval.expr = yyvsp[0].expr; }
1429 break;
1430 case 12:
1431 #line 288 "label.y"
1432 { yyval.expr = new substitute_expr(yyvsp[-2].expr, yyvsp[0].expr); }
1433 break;
1434 case 13:
1435 #line 293 "label.y"
1436 { yyval.expr = new at_expr; }
1437 break;
1438 case 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                 }
1444 break;
1445 case 15:
1446 #line 300 "label.y"
1447 { yyval.expr = new field_expr(yyvsp[0].num, 0); }
1448 break;
1449 case 16:
1450 #line 302 "label.y"
1451 { yyval.expr = new field_expr(yyvsp[-1].num, yyvsp[0].num - 1); }
1452 break;
1453 case 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                 }
1469 break;
1470 case 18:
1471 #line 320 "label.y"
1472 {
1473                   yyval.expr = new format_expr('0', yyvsp[0].dig.ndigits, yyvsp[0].dig.val);
1474                 }
1475 break;
1476 case 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                 }
1507 break;
1508 case 20:
1509 #line 355 "label.y"
1510 { yyval.expr = new truncate_expr(yyvsp[-2].expr, yyvsp[0].num); }
1511 break;
1512 case 21:
1513 #line 357 "label.y"
1514 { yyval.expr = new truncate_expr(yyvsp[-2].expr, -yyvsp[0].num); }
1515 break;
1516 case 22:
1517 #line 359 "label.y"
1518 { yyval.expr = new star_expr(yyvsp[-1].expr); }
1519 break;
1520 case 23:
1521 #line 361 "label.y"
1522 { yyval.expr = yyvsp[-1].expr; }
1523 break;
1524 case 24:
1525 #line 363 "label.y"
1526 { yyval.expr = new separator_expr(yyvsp[-1].expr); }
1527 break;
1528 case 25:
1529 #line 368 "label.y"
1530 { yyval.num = -1; }
1531 break;
1532 case 26:
1533 #line 370 "label.y"
1534 { yyval.num = yyvsp[0].num; }
1535 break;
1536 case 27:
1537 #line 375 "label.y"
1538 { yyval.num = yyvsp[0].num; }
1539 break;
1540 case 28:
1541 #line 377 "label.y"
1542 { yyval.num = yyvsp[-1].num*10 + yyvsp[0].num; }
1543 break;
1544 case 29:
1545 #line 382 "label.y"
1546 { yyval.dig.ndigits = 1; yyval.dig.val = yyvsp[0].num; }
1547 break;
1548 case 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; }
1551 break;
1552 case 31:
1553 #line 390 "label.y"
1554 { yyval.num = 0; }
1555 break;
1556 case 32:
1557 #line 392 "label.y"
1558 { yyval.num = 1; }
1559 break;
1560 case 33:
1561 #line 394 "label.y"
1562 { yyval.num = -1; }
1563 break;
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 \
1605 to 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;
1614 yyoverflow:
1615     yyerror("yacc stack overflow");
1616 yyabort:
1617     return (1);
1618 yyaccept:
1619     return (0);
1620 }