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