groff: update vendor branch to v1.20.1
[dragonfly.git] / contrib / groff / src / preproc / refer / label.cpp
CommitLineData
92d0a6a6 1#ifndef lint
4d3e9548 2static const char yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93";
92d0a6a6 3#endif
4d3e9548
JL
4
5#include <stdlib.h>
6#include <string.h>
7
92d0a6a6
JR
8#define YYBYACC 1
9#define YYMAJOR 1
10#define YYMINOR 9
4d3e9548
JL
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
30extern int YYPARSE_DECL();
31
32static int yygrowstack(void);
92d0a6a6 33#define YYPREFIX "yy"
4d3e9548 34#line 22 "label.y"
92d0a6a6
JR
35
36#include "refer.h"
37#include "refid.h"
38#include "ref.h"
39#include "token.h"
40
41int yylex();
42void yyerror(const char *);
43int yyparse();
44
45static const char *format_serial(char c, int n);
46
47struct label_info {
48 int start;
49 int length;
50 int count;
51 int total;
52 label_info(const string &);
53};
54
55label_info *lookup_label(const string &label);
56
57struct 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
71class at_expr : public expression {
72public:
73 at_expr() { }
74 void evaluate(int, const reference &, string &, substring_position &);
75 unsigned analyze() { return CONTAINS_VARIABLE|CONTAINS_AT; }
76};
77
78class format_expr : public expression {
79 char type;
80 int width;
81 int first_number;
82public:
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
89class field_expr : public expression {
90 int number;
91 char name;
92public:
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
98class literal_expr : public expression {
99 string s;
100public:
101 literal_expr(const char *ptr, int len) : s(ptr, len) { }
102 void evaluate(int, const reference &, string &, substring_position &);
103};
104
105class unary_expr : public expression {
106protected:
107 expression *expr;
108public:
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
117class analyzed_expr : public unary_expr {
118 unsigned flags;
119public:
120 analyzed_expr(expression *);
121 void evaluate(int, const reference &, string &, substring_position &);
122 unsigned analyze() { return flags; }
123};
124
125class star_expr : public unary_expr {
126public:
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
135typedef void map_func(const char *, const char *, string &);
136
137class map_expr : public unary_expr {
138 map_func *func;
139public:
140 map_expr(expression *e, map_func *f) : unary_expr(e), func(f) { }
141 void evaluate(int, const reference &, string &, substring_position &);
142};
143
144typedef const char *extractor_func(const char *, const char *, const char **);
145
146class extractor_expr : public unary_expr {
147 int part;
148 extractor_func *func;
149public:
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
156class truncate_expr : public unary_expr {
157 int n;
158public:
159 truncate_expr(expression *e, int i) : unary_expr(e), n(i) { }
160 void evaluate(int, const reference &, string &, substring_position &);
161};
162
163class separator_expr : public unary_expr {
164public:
165 separator_expr(expression *e) : unary_expr(e) { }
166 void evaluate(int, const reference &, string &, substring_position &);
167};
168
169class binary_expr : public expression {
170protected:
171 expression *expr1;
172 expression *expr2;
173public:
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
182class alternative_expr : public binary_expr {
183public:
184 alternative_expr(expression *e1, expression *e2) : binary_expr(e1, e2) { }
185 void evaluate(int, const reference &, string &, substring_position &);
186};
187
188class list_expr : public binary_expr {
189public:
190 list_expr(expression *e1, expression *e2) : binary_expr(e1, e2) { }
191 void evaluate(int, const reference &, string &, substring_position &);
192};
193
194class substitute_expr : public binary_expr {
195public:
196 substitute_expr(expression *e1, expression *e2) : binary_expr(e1, e2) { }
197 void evaluate(int, const reference &, string &, substring_position &);
198};
199
200class ternary_expr : public expression {
201protected:
202 expression *expr1;
203 expression *expr2;
204 expression *expr3;
205public:
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
217class conditional_expr : public ternary_expr {
218public:
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
224static expression *parsed_label = 0;
225static expression *parsed_date_label = 0;
226static expression *parsed_short_label = 0;
227
228static expression *parse_result;
229
230string literals;
231
4d3e9548 232#line 221 "label.y"
92d0a6a6
JR
233typedef union {
234 int num;
235 expression *expr;
236 struct { int ndigits; int val; } dig;
237 struct { int start; int len; } str;
238} YYSTYPE;
4d3e9548 239#line 239 "label.cpp"
92d0a6a6
JR
240#define TOKEN_LETTER 257
241#define TOKEN_LITERAL 258
242#define TOKEN_DIGIT 259
243#define YYERRCODE 256
4d3e9548 244static const short yylhs[] = { -1,
92d0a6a6
JR
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};
4d3e9548 250static const short yylen[] = { 2,
92d0a6a6
JR
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};
4d3e9548 256static const short yydefred[] = { 0,
92d0a6a6
JR
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};
4d3e9548 263static const short yydgoto[] = { 7,
92d0a6a6
JR
264 8, 9, 10, 11, 12, 13, 15, 18, 47, 39,
265};
4d3e9548 266static const short yysindex[] = { -32,
92d0a6a6
JR
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};
4d3e9548 273static const short yyrindex[] = { 35,
92d0a6a6
JR
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};
4d3e9548 280static const short yygindex[] = { 0,
92d0a6a6
JR
281 19, 0, 7, 37, -10, 10, -23, 0, 0, 0,
282};
283#define YYTABLESIZE 511
4d3e9548 284static const short yytable[] = { 24,
92d0a6a6
JR
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};
4d3e9548 338static const short yycheck[] = { 10,
92d0a6a6
JR
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
4d3e9548
JL
398static const char *yyname[] = {
399
92d0a6a6
JR
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,
4010,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,
4030,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,
4050,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,
4060,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,
4070,0,0,0,0,0,0,0,0,0,0,0,0,"TOKEN_LETTER","TOKEN_LITERAL","TOKEN_DIGIT",
408};
4d3e9548 409static const char *yyrule[] = {
92d0a6a6
JR
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 : '-'",
4d3e9548 444
92d0a6a6
JR
445};
446#endif
4d3e9548
JL
447#if YYDEBUG
448#include <stdio.h>
449#endif
450
451/* define the initial stack-sizes */
92d0a6a6
JR
452#ifdef YYSTACKSIZE
453#undef YYMAXDEPTH
4d3e9548 454#define YYMAXDEPTH YYSTACKSIZE
92d0a6a6
JR
455#else
456#ifdef YYMAXDEPTH
457#define YYSTACKSIZE YYMAXDEPTH
458#else
459#define YYSTACKSIZE 500
4d3e9548 460#define YYMAXDEPTH 500
92d0a6a6
JR
461#endif
462#endif
4d3e9548
JL
463
464#define YYINITSTACKSIZE 500
465
466int yydebug;
467int yynerrs;
468int yyerrflag;
469int yychar;
470short *yyssp;
92d0a6a6 471YYSTYPE *yyvsp;
4d3e9548
JL
472YYSTYPE yyval;
473YYSTYPE yylval;
474
475/* variables for the parser stack */
476static short *yyss;
477static short *yysslim;
478static YYSTYPE *yyvs;
479static unsigned yystacksize;
480#line 397 "label.y"
92d0a6a6
JR
481
482/* bison defines const to be empty unless __STDC__ is defined, which it
483isn't under cfront */
484
485#ifdef const
486#undef const
487#endif
488
489const char *spec_ptr;
490const char *spec_end;
491const char *spec_cur;
492
493static 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
500static 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
507int 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
543int 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
555int 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
567int 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
579void 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
588void 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
600void 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
618static 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
711void 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
723void literal_expr::evaluate(int, const reference &,
724 string &result, substring_position &)
725{
726 result += s;
727}
728
729analyzed_expr::analyzed_expr(expression *e)
730: unary_expr(e), flags(e ? e->analyze() : 0)
731{
732}
733
734void 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
741void 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
751void 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
764void 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
775void 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
806static 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
822static 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
852void 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
868void 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
878void 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
887void 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
901void 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
918void 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
929void 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
948void reference::immediate_compute_label()
949{
950 if (label_ptr)
951 label_ptr->total = 2; // force use of disambiguator
952 compute_label();
953}
954
955int 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
964int 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
984const 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
992const 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
1000int 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
1027string label_pool;
1028
1029label_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
1035static label_info **label_table = 0;
1036static int label_table_size = 0;
1037static int label_table_used = 0;
1038
1039label_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
1088void 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
1098static void consider_authors(reference **start, reference **end, int i);
1099
1100void 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
1114where 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
1116and Aj = Bj for 0 <= j < i. In this case if we can't say ``A0,
1117A1,...,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
1119need_author(j) for some j >= i such that the reference also needs
1120author j. */
1121
1122/* This function handles 2 tasks:
1123determine which authors are needed (cannot be elided with et al.);
1124determine which authors can have only last names in the labels.
1125
1126References >= start and < end have the same first i author names.
1127Also they're sorted by A+. */
1128
1129static 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
1171int 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
1182int 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
1194void 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
1207int 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
1214void reference::set_last_name_unambiguous(int i)
1215{
1216 last_name_unambiguous.set(i);
1217}
1218
1219void reference::need_author(int n)
1220{
1221 if (n > last_needed_author)
1222 last_needed_author = n;
1223}
1224
1225const 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
1266int 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}
4d3e9548
JL
1277#line 1277 "label.cpp"
1278/* allocate initial stack or double stack size, up to YYMAXDEPTH */
1279static 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
92d0a6a6
JR
1316#define YYREJECT goto yyabort
1317#define YYACCEPT goto yyaccept
4d3e9548
JL
1318#define YYERROR goto yyerrlab
1319
92d0a6a6 1320int
4d3e9548 1321YYPARSE_DECL()
92d0a6a6 1322{
4d3e9548 1323 int yym, yyn, yystate;
92d0a6a6 1324#if YYDEBUG
4d3e9548 1325 const char *yys;
92d0a6a6 1326
4d3e9548 1327 if ((yys = getenv("YYDEBUG")) != 0)
92d0a6a6
JR
1328 {
1329 yyn = *yys;
1330 if (yyn >= '0' && yyn <= '9')
1331 yydebug = yyn - '0';
1332 }
1333#endif
1334
1335 yynerrs = 0;
1336 yyerrflag = 0;
4d3e9548
JL
1337 yychar = YYEMPTY;
1338 yystate = 0;
92d0a6a6 1339
4d3e9548 1340 if (yyss == NULL && yygrowstack()) goto yyoverflow;
92d0a6a6
JR
1341 yyssp = yyss;
1342 yyvsp = yyvs;
4d3e9548
JL
1343 yystate = 0;
1344 *yyssp = 0;
92d0a6a6
JR
1345
1346yyloop:
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
4d3e9548 1370 if (yyssp >= yysslim && yygrowstack())
92d0a6a6
JR
1371 {
1372 goto yyoverflow;
1373 }
4d3e9548
JL
1374 yystate = yytable[yyn];
1375 *++yyssp = yytable[yyn];
92d0a6a6 1376 *++yyvsp = yylval;
4d3e9548 1377 yychar = YYEMPTY;
92d0a6a6
JR
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;
4d3e9548 1388
92d0a6a6 1389 yyerror("syntax error");
4d3e9548 1390
92d0a6a6 1391 goto yyerrlab;
4d3e9548 1392
92d0a6a6
JR
1393yyerrlab:
1394 ++yynerrs;
4d3e9548 1395
92d0a6a6
JR
1396yyinrecovery:
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
4d3e9548 1410 if (yyssp >= yysslim && yygrowstack())
92d0a6a6
JR
1411 {
1412 goto yyoverflow;
1413 }
4d3e9548
JL
1414 yystate = yytable[yyn];
1415 *++yyssp = yytable[yyn];
92d0a6a6
JR
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
4d3e9548 1445 yychar = YYEMPTY;
92d0a6a6
JR
1446 goto yyloop;
1447 }
4d3e9548 1448
92d0a6a6
JR
1449yyreduce:
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];
4d3e9548
JL
1456 if (yym)
1457 yyval = yyvsp[1-yym];
1458 else
1459 memset(&yyval, 0, sizeof yyval);
92d0a6a6
JR
1460 switch (yyn)
1461 {
1462case 1:
4d3e9548
JL
1463#line 250 "label.y"
1464 { parse_result = (yyvsp[0].expr ? new analyzed_expr(yyvsp[0].expr) : 0); }
92d0a6a6
JR
1465break;
1466case 2:
4d3e9548
JL
1467#line 255 "label.y"
1468 { yyval.expr = yyvsp[0].expr; }
92d0a6a6
JR
1469break;
1470case 3:
4d3e9548
JL
1471#line 257 "label.y"
1472 { yyval.expr = new conditional_expr(yyvsp[-4].expr, yyvsp[-2].expr, yyvsp[0].expr); }
92d0a6a6
JR
1473break;
1474case 4:
4d3e9548
JL
1475#line 262 "label.y"
1476 { yyval.expr = 0; }
92d0a6a6
JR
1477break;
1478case 5:
4d3e9548
JL
1479#line 264 "label.y"
1480 { yyval.expr = yyvsp[0].expr; }
92d0a6a6
JR
1481break;
1482case 6:
4d3e9548
JL
1483#line 269 "label.y"
1484 { yyval.expr = yyvsp[0].expr; }
92d0a6a6
JR
1485break;
1486case 7:
4d3e9548
JL
1487#line 271 "label.y"
1488 { yyval.expr = new alternative_expr(yyvsp[-2].expr, yyvsp[0].expr); }
92d0a6a6
JR
1489break;
1490case 8:
4d3e9548
JL
1491#line 273 "label.y"
1492 { yyval.expr = new conditional_expr(yyvsp[-2].expr, yyvsp[0].expr, 0); }
92d0a6a6
JR
1493break;
1494case 9:
4d3e9548
JL
1495#line 278 "label.y"
1496 { yyval.expr = yyvsp[0].expr; }
92d0a6a6
JR
1497break;
1498case 10:
4d3e9548
JL
1499#line 280 "label.y"
1500 { yyval.expr = new list_expr(yyvsp[-1].expr, yyvsp[0].expr); }
92d0a6a6
JR
1501break;
1502case 11:
4d3e9548
JL
1503#line 285 "label.y"
1504 { yyval.expr = yyvsp[0].expr; }
92d0a6a6
JR
1505break;
1506case 12:
4d3e9548
JL
1507#line 287 "label.y"
1508 { yyval.expr = new substitute_expr(yyvsp[-2].expr, yyvsp[0].expr); }
92d0a6a6
JR
1509break;
1510case 13:
4d3e9548
JL
1511#line 292 "label.y"
1512 { yyval.expr = new at_expr; }
92d0a6a6
JR
1513break;
1514case 14:
4d3e9548
JL
1515#line 294 "label.y"
1516 {
92d0a6a6
JR
1517 yyval.expr = new literal_expr(literals.contents() + yyvsp[0].str.start,
1518 yyvsp[0].str.len);
1519 }
1520break;
1521case 15:
4d3e9548
JL
1522#line 299 "label.y"
1523 { yyval.expr = new field_expr(yyvsp[0].num, 0); }
92d0a6a6
JR
1524break;
1525case 16:
4d3e9548
JL
1526#line 301 "label.y"
1527 { yyval.expr = new field_expr(yyvsp[-1].num, yyvsp[0].num - 1); }
92d0a6a6
JR
1528break;
1529case 17:
4d3e9548
JL
1530#line 303 "label.y"
1531 {
92d0a6a6
JR
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 }
1545break;
1546case 18:
4d3e9548
JL
1547#line 319 "label.y"
1548 {
92d0a6a6
JR
1549 yyval.expr = new format_expr('0', yyvsp[0].dig.ndigits, yyvsp[0].dig.val);
1550 }
1551break;
1552case 19:
4d3e9548
JL
1553#line 323 "label.y"
1554 {
92d0a6a6
JR
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 }
1583break;
1584case 20:
4d3e9548
JL
1585#line 354 "label.y"
1586 { yyval.expr = new truncate_expr(yyvsp[-2].expr, yyvsp[0].num); }
92d0a6a6
JR
1587break;
1588case 21:
4d3e9548
JL
1589#line 356 "label.y"
1590 { yyval.expr = new truncate_expr(yyvsp[-2].expr, -yyvsp[0].num); }
92d0a6a6
JR
1591break;
1592case 22:
4d3e9548
JL
1593#line 358 "label.y"
1594 { yyval.expr = new star_expr(yyvsp[-1].expr); }
92d0a6a6
JR
1595break;
1596case 23:
4d3e9548
JL
1597#line 360 "label.y"
1598 { yyval.expr = yyvsp[-1].expr; }
92d0a6a6
JR
1599break;
1600case 24:
4d3e9548
JL
1601#line 362 "label.y"
1602 { yyval.expr = new separator_expr(yyvsp[-1].expr); }
92d0a6a6
JR
1603break;
1604case 25:
4d3e9548
JL
1605#line 367 "label.y"
1606 { yyval.num = -1; }
92d0a6a6
JR
1607break;
1608case 26:
4d3e9548
JL
1609#line 369 "label.y"
1610 { yyval.num = yyvsp[0].num; }
92d0a6a6
JR
1611break;
1612case 27:
4d3e9548
JL
1613#line 374 "label.y"
1614 { yyval.num = yyvsp[0].num; }
92d0a6a6
JR
1615break;
1616case 28:
4d3e9548
JL
1617#line 376 "label.y"
1618 { yyval.num = yyvsp[-1].num*10 + yyvsp[0].num; }
92d0a6a6
JR
1619break;
1620case 29:
4d3e9548
JL
1621#line 381 "label.y"
1622 { yyval.dig.ndigits = 1; yyval.dig.val = yyvsp[0].num; }
92d0a6a6
JR
1623break;
1624case 30:
4d3e9548
JL
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; }
92d0a6a6
JR
1627break;
1628case 31:
4d3e9548
JL
1629#line 389 "label.y"
1630 { yyval.num = 0; }
92d0a6a6
JR
1631break;
1632case 32:
4d3e9548
JL
1633#line 391 "label.y"
1634 { yyval.num = 1; }
92d0a6a6
JR
1635break;
1636case 33:
4d3e9548
JL
1637#line 393 "label.y"
1638 { yyval.num = -1; }
92d0a6a6 1639break;
4d3e9548 1640#line 1640 "label.cpp"
92d0a6a6
JR
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 \
1681to state %d\n", YYPREFIX, *yyssp, yystate);
1682#endif
4d3e9548 1683 if (yyssp >= yysslim && yygrowstack())
92d0a6a6
JR
1684 {
1685 goto yyoverflow;
1686 }
4d3e9548 1687 *++yyssp = (short) yystate;
92d0a6a6
JR
1688 *++yyvsp = yyval;
1689 goto yyloop;
4d3e9548 1690
92d0a6a6
JR
1691yyoverflow:
1692 yyerror("yacc stack overflow");
4d3e9548 1693
92d0a6a6
JR
1694yyabort:
1695 return (1);
4d3e9548 1696
92d0a6a6
JR
1697yyaccept:
1698 return (0);
1699}