2 /* A Bison parser, made from label.y */
4 #define YYBISON 1 /* Identify Bison output. */
6 #define TOKEN_LETTER 258
7 #define TOKEN_LITERAL 259
8 #define TOKEN_DIGIT 260
19 void yyerror(const char *);
22 static const char *format_serial(char c
, int n
);
29 label_info(const string
&);
32 label_info
*lookup_label(const string
&label
);
36 // Does the tentative label depend on the reference?
37 CONTAINS_VARIABLE
= 01,
42 virtual ~expression() { }
43 virtual void evaluate(int, const reference
&, string
&,
44 substring_position
&) = 0;
45 virtual unsigned analyze() { return 0; }
48 class at_expr
: public expression
{
51 void evaluate(int, const reference
&, string
&, substring_position
&);
52 unsigned analyze() { return CONTAINS_VARIABLE
|CONTAINS_AT
; }
55 class format_expr
: public expression
{
60 format_expr(char c
, int w
= 0, int f
= 1)
61 : type(c
), width(w
), first_number(f
) { }
62 void evaluate(int, const reference
&, string
&, substring_position
&);
63 unsigned analyze() { return CONTAINS_FORMAT
; }
66 class field_expr
: public expression
{
70 field_expr(char nm
, int num
) : name(nm
), number(num
) { }
71 void evaluate(int, const reference
&, string
&, substring_position
&);
72 unsigned analyze() { return CONTAINS_VARIABLE
; }
75 class literal_expr
: public expression
{
78 literal_expr(const char *ptr
, int len
) : s(ptr
, len
) { }
79 void evaluate(int, const reference
&, string
&, substring_position
&);
82 class unary_expr
: public expression
{
86 unary_expr(expression
*e
) : expr(e
) { }
87 ~unary_expr() { delete expr
; }
88 void evaluate(int, const reference
&, string
&, substring_position
&) = 0;
89 unsigned analyze() { return expr
? expr
->analyze() : 0; }
92 // This caches the analysis of an expression.
94 class analyzed_expr
: public unary_expr
{
97 analyzed_expr(expression
*);
98 void evaluate(int, const reference
&, string
&, substring_position
&);
99 unsigned analyze() { return flags
; }
102 class star_expr
: public unary_expr
{
104 star_expr(expression
*e
) : unary_expr(e
) { }
105 void evaluate(int, const reference
&, string
&, substring_position
&);
107 return ((expr
? (expr
->analyze() & ~CONTAINS_VARIABLE
) : 0)
112 typedef void map_t(const char *, const char *, string
&);
114 class map_expr
: public unary_expr
{
117 map_expr(expression
*e
, map_t
*f
) : unary_expr(e
), func(f
) { }
118 void evaluate(int, const reference
&, string
&, substring_position
&);
121 typedef const char *extractor_t(const char *, const char *, const char **);
123 class extractor_expr
: public unary_expr
{
127 enum { BEFORE
= +1, MATCH
= 0, AFTER
= -1 };
128 extractor_expr(expression
*e
, extractor_t
*f
, int pt
)
129 : unary_expr(e
), func(f
), part(pt
) { }
130 void evaluate(int, const reference
&, string
&, substring_position
&);
133 class truncate_expr
: public unary_expr
{
136 truncate_expr(expression
*e
, int i
) : n(i
), unary_expr(e
) { }
137 void evaluate(int, const reference
&, string
&, substring_position
&);
140 class separator_expr
: public unary_expr
{
142 separator_expr(expression
*e
) : unary_expr(e
) { }
143 void evaluate(int, const reference
&, string
&, substring_position
&);
146 class binary_expr
: public expression
{
151 binary_expr(expression
*e1
, expression
*e2
) : expr1(e1
), expr2(e2
) { }
152 ~binary_expr() { delete expr1
; delete expr2
; }
153 void evaluate(int, const reference
&, string
&, substring_position
&) = 0;
155 return (expr1
? expr1
->analyze() : 0) | (expr2
? expr2
->analyze() : 0);
159 class alternative_expr
: public binary_expr
{
161 alternative_expr(expression
*e1
, expression
*e2
) : binary_expr(e1
, e2
) { }
162 void evaluate(int, const reference
&, string
&, substring_position
&);
165 class list_expr
: public binary_expr
{
167 list_expr(expression
*e1
, expression
*e2
) : binary_expr(e1
, e2
) { }
168 void evaluate(int, const reference
&, string
&, substring_position
&);
171 class substitute_expr
: public binary_expr
{
173 substitute_expr(expression
*e1
, expression
*e2
) : binary_expr(e1
, e2
) { }
174 void evaluate(int, const reference
&, string
&, substring_position
&);
177 class ternary_expr
: public expression
{
183 ternary_expr(expression
*e1
, expression
*e2
, expression
*e3
)
184 : expr1(e1
), expr2(e2
), expr3(e3
) { }
185 ~ternary_expr() { delete expr1
; delete expr2
; delete expr3
; }
186 void evaluate(int, const reference
&, string
&, substring_position
&) = 0;
188 return ((expr1
? expr1
->analyze() : 0)
189 | (expr2
? expr2
->analyze() : 0)
190 | (expr3
? expr3
->analyze() : 0));
194 class conditional_expr
: public ternary_expr
{
196 conditional_expr(expression
*e1
, expression
*e2
, expression
*e3
)
197 : ternary_expr(e1
, e2
, e3
) { }
198 void evaluate(int, const reference
&, string
&, substring_position
&);
201 static expression
*parsed_label
= 0;
202 static expression
*parsed_date_label
= 0;
203 static expression
*parsed_short_label
= 0;
205 static expression
*parse_result
;
214 struct { int ndigits
; int val
; } dig
;
215 struct { int start
; int len
; } str
;
231 #define YYLTYPE yyltype
243 #define YYFLAG -32768
246 #define YYTRANSLATE(x) ((unsigned)(x) <= 260 ? yytranslate[x] : 32)
248 static const char yytranslate
[] = { 0,
249 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
250 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
251 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
252 2, 2, 2, 2, 2, 2, 12, 9, 2, 17,
253 18, 16, 14, 2, 15, 13, 2, 2, 2, 2,
254 2, 2, 2, 2, 2, 2, 2, 7, 2, 19,
255 2, 20, 6, 11, 2, 2, 2, 2, 2, 2,
256 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
257 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
258 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
259 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
260 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
261 2, 2, 2, 8, 2, 10, 2, 2, 2, 2,
262 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
263 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
264 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
265 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
266 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
267 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
268 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
269 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
270 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
271 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
272 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
273 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
274 2, 2, 2, 2, 2, 1, 2, 3, 4, 5
278 static const short yyprhs
[] = { 0,
279 0, 2, 4, 10, 11, 13, 15, 19, 23, 25,
280 28, 30, 34, 36, 38, 40, 43, 46, 49, 55,
281 59, 63, 66, 70, 74, 75, 77, 79, 82, 84,
287 static const short yyrhs
[] = { 23,
288 0, 24, 0, 24, 6, 23, 7, 22, 0, 0,
289 22, 0, 25, 0, 24, 8, 25, 0, 24, 9,
290 25, 0, 26, 0, 25, 26, 0, 27, 0, 26,
291 10, 27, 0, 11, 0, 4, 0, 3, 0, 3,
292 29, 0, 12, 3, 0, 12, 30, 0, 27, 13,
293 31, 3, 28, 0, 27, 14, 29, 0, 27, 15,
294 29, 0, 27, 16, 0, 17, 23, 18, 0, 19,
295 23, 20, 0, 0, 29, 0, 5, 0, 29, 5,
296 0, 5, 0, 30, 5, 0, 0, 14, 0, 15,
301 static const short yyrline
[] = { 0,
302 248, 253, 256, 260, 263, 267, 270, 272, 276, 279,
303 283, 286, 290, 293, 298, 300, 302, 318, 322, 353,
304 355, 357, 359, 361, 365, 368, 372, 375, 379, 382,
308 static const char * const yytname
[] = { "$","error","$illegal.","TOKEN_LETTER",
309 "TOKEN_LITERAL","TOKEN_DIGIT","'?'","':'","'|'","'&'","'~'","'@'","'%'","'.'",
310 "'+'","'-'","'*'","'('","')'","'<'","'>'","expr","conditional","optional_conditional",
311 "alternative","list","substitute","string","optional_number","number","digits",
316 static const short yyr1
[] = { 0,
317 21, 22, 22, 23, 23, 24, 24, 24, 25, 25,
318 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
319 27, 27, 27, 27, 28, 28, 29, 29, 30, 30,
323 static const short yyr2
[] = { 0,
324 1, 1, 5, 0, 1, 1, 3, 3, 1, 2,
325 1, 3, 1, 1, 1, 2, 2, 2, 5, 3,
326 3, 2, 3, 3, 0, 1, 1, 2, 1, 2,
330 static const short yydefact
[] = { 4,
331 15, 14, 13, 0, 4, 4, 5, 1, 2, 6,
332 9, 11, 27, 16, 17, 29, 18, 0, 0, 4,
333 0, 0, 10, 0, 31, 0, 0, 22, 28, 30,
334 23, 24, 0, 7, 8, 12, 32, 33, 0, 20,
335 21, 0, 25, 3, 19, 26, 0, 0, 0
338 static const short yydefgoto
[] = { 47,
339 7, 8, 9, 10, 11, 12, 45, 14, 17, 39
342 static const short yypact
[] = { 0,
343 4,-32768,-32768, 5, 0, 0,-32768,-32768, 7, 0,
344 -5, 13,-32768, 15,-32768,-32768, 27, -4, 14, 0,
345 0, 0, -5, 0, 8, 4, 4,-32768,-32768,-32768,
346 -32768,-32768, 26, 0, 0, 13,-32768,-32768, 32, 15,
347 15, 0, 4,-32768,-32768, 15, 36, 37,-32768
350 static const short yypgoto
[] = {-32768,
351 -3, 1,-32768, 9, -10, 16,-32768, -25,-32768,-32768
358 static const short yytable
[] = { 23,
359 40, 41, 1, 2, 24, 18, 19, 15, 13, 16,
360 3, 4, 20, 31, 21, 22, 5, 46, 6, 29,
361 33, 37, 38, 23, 23, 25, 26, 27, 28, 34,
362 35, 30, 42, 32, 43, 48, 49, 0, 44, 36
365 static const short yycheck
[] = { 10,
366 26, 27, 3, 4, 10, 5, 6, 3, 5, 5,
367 11, 12, 6, 18, 8, 9, 17, 43, 19, 5,
368 20, 14, 15, 34, 35, 13, 14, 15, 16, 21,
369 22, 5, 7, 20, 3, 0, 0, -1, 42, 24
371 /* -*-C-*- Note some compilers choke on comments on `#line' lines. */
372 #line 3 "/usr/local/lib/bison.simple"
374 /* Skeleton output parser for bison,
375 Copyright (C) 1984, 1989, 1990 Bob Corbett and Richard Stallman
377 This program is free software; you can redistribute it and/or modify
378 it under the terms of the GNU General Public License as published by
379 the Free Software Foundation; either version 2, or (at your option)
382 This program is distributed in the hope that it will be useful,
383 but WITHOUT ANY WARRANTY; without even the implied warranty of
384 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
385 GNU General Public License for more details.
387 You should have received a copy of the GNU General Public License
388 along with this program; if not, write to the Free Software
389 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
394 #define alloca __builtin_alloca
395 #else /* not GNU C. */
396 #if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc)
398 #else /* not sparc */
399 #if defined (MSDOS) && !defined (__TURBOC__)
401 #else /* not MSDOS, or __TURBOC__ */
405 #endif /* not _AIX */
406 #endif /* not MSDOS, or __TURBOC__ */
407 #endif /* not sparc. */
408 #endif /* not GNU C. */
409 #endif /* alloca not defined. */
411 /* This is the parser code that is written into each bison parser
412 when the %semantic_parser declaration is not specified in the grammar.
413 It was written by Richard Stallman by simplifying the hairy parser
414 used when %semantic_parser is specified. */
416 /* Note: there must be only one dollar sign in this file.
417 It is replaced by the list of actions, each action
418 as one case of the switch. */
420 #define yyerrok (yyerrstatus = 0)
421 #define yyclearin (yychar = YYEMPTY)
424 #define YYACCEPT return(0)
425 #define YYABORT return(1)
426 #define YYERROR goto yyerrlab1
427 /* Like YYERROR except do call yyerror.
428 This remains here temporarily to ease the
429 transition to the new meaning of YYERROR, for GCC.
430 Once GCC version 2 has supplanted version 1, this can go. */
431 #define YYFAIL goto yyerrlab
432 #define YYRECOVERING() (!!yyerrstatus)
433 #define YYBACKUP(token, value) \
435 if (yychar == YYEMPTY && yylen == 1) \
436 { yychar = (token), yylval = (value); \
437 yychar1 = YYTRANSLATE (yychar); \
442 { yyerror ("syntax error: cannot back up"); YYERROR; } \
446 #define YYERRCODE 256
449 #define YYLEX yylex()
454 #define YYLEX yylex(&yylval, &yylloc)
456 #define YYLEX yylex(&yylval)
460 /* If nonreentrant, generate the variables here */
464 int yychar
; /* the lookahead symbol */
465 YYSTYPE yylval
; /* the semantic value of the */
466 /* lookahead symbol */
469 YYLTYPE yylloc
; /* location data for the lookahead */
473 int yynerrs
; /* number of parse errors so far */
474 #endif /* not YYPURE */
477 int yydebug
; /* nonzero means print parse trace */
478 /* Since this is uninitialized, it does not stop multiple parsers
482 /* YYINITDEPTH indicates the initial size of the parser's stacks */
485 #define YYINITDEPTH 200
488 /* YYMAXDEPTH is the maximum size the stacks can grow to
489 (effective only if the built-in stack extension method is used). */
496 #define YYMAXDEPTH 10000
499 #if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
500 #define __yy_bcopy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT)
501 #else /* not GNU C or C++ */
504 /* This is the most reliable way to avoid incompatibilities
505 in available built-in functions on various systems. */
507 __yy_bcopy (from
, to
, count
)
512 register char *f
= from
;
513 register char *t
= to
;
514 register int i
= count
;
520 #else /* __cplusplus */
522 /* This is the most reliable way to avoid incompatibilities
523 in available built-in functions on various systems. */
525 __yy_bcopy (char *from
, char *to
, int count
)
527 register char *f
= from
;
528 register char *t
= to
;
529 register int i
= count
;
538 #line 169 "/usr/local/lib/bison.simple"
542 register int yystate
;
544 register short *yyssp
;
545 register YYSTYPE
*yyvsp
;
546 int yyerrstatus
; /* number of tokens to shift before error messages enabled */
547 int yychar1
; /* lookahead token as an internal (translated) token number */
549 short yyssa
[YYINITDEPTH
]; /* the state stack */
550 YYSTYPE yyvsa
[YYINITDEPTH
]; /* the semantic value stack */
552 short *yyss
= yyssa
; /* refer to the stacks thru separate pointers */
553 YYSTYPE
*yyvs
= yyvsa
; /* to allow yyoverflow to reallocate them elsewhere */
556 YYLTYPE yylsa
[YYINITDEPTH
]; /* the location stack */
557 YYLTYPE
*yyls
= yylsa
;
560 #define YYPOPSTACK (yyvsp--, yyssp--, yylsp--)
562 #define YYPOPSTACK (yyvsp--, yyssp--)
565 int yystacksize
= YYINITDEPTH
;
576 YYSTYPE yyval
; /* the variable used to return */
577 /* semantic values from the action */
584 fprintf(stderr
, "Starting parse\n");
590 yychar
= YYEMPTY
; /* Cause a token to be read. */
592 /* Initialize stack pointers.
593 Waste one element of value and location stack
594 so that they stay on the same level as the state stack. */
602 /* Push a new state, which is found in yystate . */
603 /* In all cases, when you get here, the value and location stacks
604 have just been pushed. so pushing a state here evens the stacks. */
609 if (yyssp
>= yyss
+ yystacksize
- 1)
611 /* Give user a chance to reallocate the stack */
612 /* Use copies of these so that the &'s don't force the real ones into memory. */
613 YYSTYPE
*yyvs1
= yyvs
;
616 YYLTYPE
*yyls1
= yyls
;
619 /* Get the current used size of the three stacks, in elements. */
620 int size
= yyssp
- yyss
+ 1;
623 /* Each stack pointer address is followed by the size of
624 the data in use in that stack, in bytes. */
625 yyoverflow("parser stack overflow",
626 &yyss1
, size
* sizeof (*yyssp
),
627 &yyvs1
, size
* sizeof (*yyvsp
),
629 &yyls1
, size
* sizeof (*yylsp
),
633 yyss
= yyss1
; yyvs
= yyvs1
;
637 #else /* no yyoverflow */
638 /* Extend the stack our own way. */
639 if (yystacksize
>= YYMAXDEPTH
)
641 yyerror("parser stack overflow");
645 if (yystacksize
> YYMAXDEPTH
)
646 yystacksize
= YYMAXDEPTH
;
647 yyss
= (short *) alloca (yystacksize
* sizeof (*yyssp
));
648 __yy_bcopy ((char *)yyss1
, (char *)yyss
, size
* sizeof (*yyssp
));
649 yyvs
= (YYSTYPE
*) alloca (yystacksize
* sizeof (*yyvsp
));
650 __yy_bcopy ((char *)yyvs1
, (char *)yyvs
, size
* sizeof (*yyvsp
));
652 yyls
= (YYLTYPE
*) alloca (yystacksize
* sizeof (*yylsp
));
653 __yy_bcopy ((char *)yyls1
, (char *)yyls
, size
* sizeof (*yylsp
));
655 #endif /* no yyoverflow */
657 yyssp
= yyss
+ size
- 1;
658 yyvsp
= yyvs
+ size
- 1;
660 yylsp
= yyls
+ size
- 1;
665 fprintf(stderr
, "Stack size increased to %d\n", yystacksize
);
668 if (yyssp
>= yyss
+ yystacksize
- 1)
674 fprintf(stderr
, "Entering state %d\n", yystate
);
679 /* Do appropriate processing given the current state. */
680 /* Read a lookahead token if we need one and don't already have one. */
683 /* First try to decide what to do without reference to lookahead token. */
685 yyn
= yypact
[yystate
];
689 /* Not known => get a lookahead token if don't already have one. */
691 /* yychar is either YYEMPTY or YYEOF
692 or a valid token in external form. */
694 if (yychar
== YYEMPTY
)
698 fprintf(stderr
, "Reading a token: ");
703 /* Convert token to internal form (in yychar1) for indexing tables with */
705 if (yychar
<= 0) /* This means end of input. */
708 yychar
= YYEOF
; /* Don't call YYLEX any more */
712 fprintf(stderr
, "Now at end of input.\n");
717 yychar1
= YYTRANSLATE(yychar
);
722 fprintf (stderr
, "Next token is %d (%s", yychar
, yytname
[yychar1
]);
723 /* Give the individual parser a way to print the precise meaning
724 of a token, for further debugging info. */
726 YYPRINT (stderr
, yychar
, yylval
);
728 fprintf (stderr
, ")\n");
734 if (yyn
< 0 || yyn
> YYLAST
|| yycheck
[yyn
] != yychar1
)
739 /* yyn is what to do for this token type in this state.
740 Negative => reduce, -yyn is rule number.
741 Positive => shift, yyn is new state.
742 New state is final state => don't bother to shift,
744 0, or most negative number => error. */
759 /* Shift the lookahead token. */
763 fprintf(stderr
, "Shifting token %d (%s), ", yychar
, yytname
[yychar1
]);
766 /* Discard the token being shifted unless it is eof. */
775 /* count tokens shifted since error; after three, turn off error status. */
776 if (yyerrstatus
) yyerrstatus
--;
781 /* Do the default action for the current state. */
784 yyn
= yydefact
[yystate
];
788 /* Do a reduction. yyn is the number of a rule to reduce with. */
791 yyval
= yyvsp
[1-yylen
]; /* implement default value of the action */
798 fprintf (stderr
, "Reducing via rule %d (line %d), ",
801 /* Print the symboles being reduced, and their result. */
802 for (i
= yyprhs
[yyn
]; yyrhs
[i
] > 0; i
++)
803 fprintf (stderr
, "%s ", yytname
[yyrhs
[i
]]);
804 fprintf (stderr
, " -> %s\n", yytname
[yyr1
[yyn
]]);
813 { parse_result
= (yyvsp
[0].expr
? new analyzed_expr(yyvsp
[0].expr
) : 0); ;
817 { yyval
.expr
= yyvsp
[0].expr
; ;
821 { yyval
.expr
= new conditional_expr(yyvsp
[-4].expr
, yyvsp
[-2].expr
, yyvsp
[0].expr
); ;
829 { yyval
.expr
= yyvsp
[0].expr
; ;
833 { yyval
.expr
= yyvsp
[0].expr
; ;
837 { yyval
.expr
= new alternative_expr(yyvsp
[-2].expr
, yyvsp
[0].expr
); ;
841 { yyval
.expr
= new conditional_expr(yyvsp
[-2].expr
, yyvsp
[0].expr
, 0); ;
845 { yyval
.expr
= yyvsp
[0].expr
; ;
849 { yyval
.expr
= new list_expr(yyvsp
[-1].expr
, yyvsp
[0].expr
); ;
853 { yyval
.expr
= yyvsp
[0].expr
; ;
857 { yyval
.expr
= new substitute_expr(yyvsp
[-2].expr
, yyvsp
[0].expr
); ;
861 { yyval
.expr
= new at_expr
; ;
866 yyval
.expr
= new literal_expr(literals
.contents() + yyvsp
[0].str
.start
,
872 { yyval
.expr
= new field_expr(yyvsp
[0].num
, 0); ;
876 { yyval
.expr
= new field_expr(yyvsp
[-1].num
, yyvsp
[0].num
- 1); ;
881 switch (yyvsp
[0].num
) {
886 yyval
.expr
= new format_expr(yyvsp
[0].num
);
889 command_error("unrecognized format `%1'", char(yyvsp
[0].num
));
890 yyval
.expr
= new format_expr('a');
898 yyval
.expr
= new format_expr('0', yyvsp
[0].dig
.ndigits
, yyvsp
[0].dig
.val
);
904 switch (yyvsp
[-1].num
) {
906 yyval
.expr
= new map_expr(yyvsp
[-4].expr
, lowercase
);
909 yyval
.expr
= new map_expr(yyvsp
[-4].expr
, uppercase
);
912 yyval
.expr
= new map_expr(yyvsp
[-4].expr
, capitalize
);
915 yyval
.expr
= new map_expr(yyvsp
[-4].expr
, reverse_name
);
918 yyval
.expr
= new map_expr(yyvsp
[-4].expr
, abbreviate_name
);
921 yyval
.expr
= new extractor_expr(yyvsp
[-4].expr
, find_year
, yyvsp
[-2].num
);
924 yyval
.expr
= new extractor_expr(yyvsp
[-4].expr
, find_last_name
, yyvsp
[-2].num
);
927 yyval
.expr
= yyvsp
[-4].expr
;
928 command_error("unknown function `%1'", char(yyvsp
[-1].num
));
935 { yyval
.expr
= new truncate_expr(yyvsp
[-2].expr
, yyvsp
[0].num
); ;
939 { yyval
.expr
= new truncate_expr(yyvsp
[-2].expr
, -yyvsp
[0].num
); ;
943 { yyval
.expr
= new star_expr(yyvsp
[-1].expr
); ;
947 { yyval
.expr
= yyvsp
[-1].expr
; ;
951 { yyval
.expr
= new separator_expr(yyvsp
[-1].expr
); ;
959 { yyval
.num
= yyvsp
[0].num
; ;
963 { yyval
.num
= yyvsp
[0].num
; ;
967 { yyval
.num
= yyvsp
[-1].num
*10 + yyvsp
[0].num
; ;
971 { yyval
.dig
.ndigits
= 1; yyval
.dig
.val
= yyvsp
[0].num
; ;
975 { yyval
.dig
.ndigits
= yyvsp
[-1].dig
.ndigits
+ 1; yyval
.dig
.val
= yyvsp
[-1].dig
.val
*10 + yyvsp
[0].num
; ;
990 /* the action file gets copied in in place of this dollarsign */
991 #line 440 "/usr/local/lib/bison.simple"
1002 short *ssp1
= yyss
- 1;
1003 fprintf (stderr
, "state stack now");
1004 while (ssp1
!= yyssp
)
1005 fprintf (stderr
, " %d", *++ssp1
);
1006 fprintf (stderr
, "\n");
1016 yylsp
->first_line
= yylloc
.first_line
;
1017 yylsp
->first_column
= yylloc
.first_column
;
1018 yylsp
->last_line
= (yylsp
-1)->last_line
;
1019 yylsp
->last_column
= (yylsp
-1)->last_column
;
1024 yylsp
->last_line
= (yylsp
+yylen
-1)->last_line
;
1025 yylsp
->last_column
= (yylsp
+yylen
-1)->last_column
;
1029 /* Now "shift" the result of the reduction.
1030 Determine what state that goes to,
1031 based on the state we popped back to
1032 and the rule number reduced by. */
1036 yystate
= yypgoto
[yyn
- YYNTBASE
] + *yyssp
;
1037 if (yystate
>= 0 && yystate
<= YYLAST
&& yycheck
[yystate
] == *yyssp
)
1038 yystate
= yytable
[yystate
];
1040 yystate
= yydefgoto
[yyn
- YYNTBASE
];
1044 yyerrlab
: /* here on detecting error */
1047 /* If not already recovering from an error, report this error. */
1051 #ifdef YYERROR_VERBOSE
1052 yyn
= yypact
[yystate
];
1054 if (yyn
> YYFLAG
&& yyn
< YYLAST
)
1061 for (x
= 0; x
< (sizeof(yytname
) / sizeof(char *)); x
++)
1062 if (yycheck
[x
+ yyn
] == x
)
1063 size
+= strlen(yytname
[x
]) + 15, count
++;
1064 msg
= (char *) malloc(size
+ 15);
1067 strcpy(msg
, "parse error");
1072 for (x
= 0; x
< (sizeof(yytname
) / sizeof(char *)); x
++)
1073 if (yycheck
[x
+ yyn
] == x
)
1075 strcat(msg
, count
== 0 ? ", expecting `" : " or `");
1076 strcat(msg
, yytname
[x
]);
1085 yyerror ("parse error; also virtual memory exceeded");
1088 #endif /* YYERROR_VERBOSE */
1089 yyerror("parse error");
1092 yyerrlab1
: /* here on error raised explicitly by an action */
1094 if (yyerrstatus
== 3)
1096 /* if just tried and failed to reuse lookahead token after an error, discard it. */
1098 /* return failure if at end of input */
1099 if (yychar
== YYEOF
)
1104 fprintf(stderr
, "Discarding token %d (%s).\n", yychar
, yytname
[yychar1
]);
1110 /* Else will try to reuse lookahead token
1111 after shifting the error token. */
1113 yyerrstatus
= 3; /* Each real token shifted decrements this */
1117 yyerrdefault
: /* current state does not do anything special for the error token. */
1120 /* This is wrong; only states that explicitly want error tokens
1121 should shift them. */
1122 yyn
= yydefact
[yystate
]; /* If its default is to accept any token, ok. Otherwise pop it.*/
1123 if (yyn
) goto yydefault
;
1126 yyerrpop
: /* pop the current state because it cannot handle the error token */
1128 if (yyssp
== yyss
) YYABORT
;
1138 short *ssp1
= yyss
- 1;
1139 fprintf (stderr
, "Error: state stack now");
1140 while (ssp1
!= yyssp
)
1141 fprintf (stderr
, " %d", *++ssp1
);
1142 fprintf (stderr
, "\n");
1148 yyn
= yypact
[yystate
];
1153 if (yyn
< 0 || yyn
> YYLAST
|| yycheck
[yyn
] != YYTERROR
)
1172 fprintf(stderr
, "Shifting error token, ");
1186 /* bison defines const to be empty unless __STDC__ is defined, which it
1187 isn't under cfront */
1193 const char *spec_ptr
;
1194 const char *spec_end
;
1195 const char *spec_cur
;
1199 while (spec_ptr
< spec_end
&& csspace(*spec_ptr
))
1201 spec_cur
= spec_ptr
;
1202 if (spec_ptr
>= spec_end
)
1204 unsigned char c
= *spec_ptr
++;
1207 return TOKEN_LETTER
;
1210 yylval
.num
= c
- '0';
1214 yylval
.str
.start
= literals
.length();
1215 for (; spec_ptr
< spec_end
; spec_ptr
++) {
1216 if (*spec_ptr
== '\'') {
1217 if (++spec_ptr
< spec_end
&& *spec_ptr
== '\'')
1220 yylval
.str
.len
= literals
.length() - yylval
.str
.start
;
1221 return TOKEN_LITERAL
;
1225 literals
+= *spec_ptr
;
1227 yylval
.str
.len
= literals
.length() - yylval
.str
.start
;
1228 return TOKEN_LITERAL
;
1233 int set_label_spec(const char *label_spec
)
1235 spec_cur
= spec_ptr
= label_spec
;
1236 spec_end
= strchr(label_spec
, '\0');
1240 delete parsed_label
;
1241 parsed_label
= parse_result
;
1245 int set_date_label_spec(const char *label_spec
)
1247 spec_cur
= spec_ptr
= label_spec
;
1248 spec_end
= strchr(label_spec
, '\0');
1252 delete parsed_date_label
;
1253 parsed_date_label
= parse_result
;
1257 int set_short_label_spec(const char *label_spec
)
1259 spec_cur
= spec_ptr
= label_spec
;
1260 spec_end
= strchr(label_spec
, '\0');
1264 delete parsed_short_label
;
1265 parsed_short_label
= parse_result
;
1269 void yyerror(const char *message
)
1271 if (spec_cur
< spec_end
)
1272 command_error("label specification %1 before `%2'", message
, spec_cur
);
1274 command_error("label specification %1 at end of string",
1278 void at_expr::evaluate(int tentative
, const reference
&ref
,
1279 string
&result
, substring_position
&)
1282 ref
.canonicalize_authors(result
);
1284 const char *end
, *start
= ref
.get_authors(&end
);
1286 result
.append(start
, end
- start
);
1290 void format_expr::evaluate(int tentative
, const reference
&ref
,
1291 string
&result
, substring_position
&)
1295 const label_info
*lp
= ref
.get_label_ptr();
1296 int num
= lp
== 0 ? ref
.get_number() : lp
->count
;
1298 result
+= format_serial(type
, num
+ 1);
1300 const char *ptr
= itoa(num
+ first_number
);
1301 int pad
= width
- strlen(ptr
);
1308 static const char *format_serial(char c
, int n
)
1311 static char buf
[128]; // more than enough.
1317 // troff uses z and w to represent 10000 and 5000 in Roman
1318 // numerals; I can find no historical basis for this usage
1319 const char *s
= c
== 'i' ? "zwmdclxvi" : "ZWMDCLXVI";
1322 while (n
>= 10000) {
1326 for (int i
= 1000; i
> 0; i
/= 10, s
+= 2) {
1373 // this is derived from troff/reg.c
1380 *p
++ = c
+ d
- 1; // ASCII dependent
1400 void field_expr::evaluate(int, const reference
&ref
,
1401 string
&result
, substring_position
&)
1404 const char *start
= ref
.get_field(name
, &end
);
1406 start
= nth_field(number
, start
, &end
);
1408 result
.append(start
, end
- start
);
1412 void literal_expr::evaluate(int, const reference
&,
1413 string
&result
, substring_position
&)
1418 analyzed_expr::analyzed_expr(expression
*e
)
1419 : unary_expr(e
), flags(e
? e
->analyze() : 0)
1423 void analyzed_expr::evaluate(int tentative
, const reference
&ref
,
1424 string
&result
, substring_position
&pos
)
1427 expr
->evaluate(tentative
, ref
, result
, pos
);
1430 void star_expr::evaluate(int tentative
, const reference
&ref
,
1431 string
&result
, substring_position
&pos
)
1433 const label_info
*lp
= ref
.get_label_ptr();
1435 && (lp
== 0 || lp
->total
> 1)
1437 expr
->evaluate(tentative
, ref
, result
, pos
);
1440 void separator_expr::evaluate(int tentative
, const reference
&ref
,
1441 string
&result
, substring_position
&pos
)
1443 int start_length
= result
.length();
1444 int is_first
= pos
.start
< 0;
1446 expr
->evaluate(tentative
, ref
, result
, pos
);
1448 pos
.start
= start_length
;
1449 pos
.length
= result
.length() - start_length
;
1453 void map_expr::evaluate(int tentative
, const reference
&ref
,
1454 string
&result
, substring_position
&)
1458 substring_position temp_pos
;
1459 expr
->evaluate(tentative
, ref
, temp
, temp_pos
);
1460 (*func
)(temp
.contents(), temp
.contents() + temp
.length(), result
);
1464 void extractor_expr::evaluate(int tentative
, const reference
&ref
,
1465 string
&result
, substring_position
&)
1469 substring_position temp_pos
;
1470 expr
->evaluate(tentative
, ref
, temp
, temp_pos
);
1471 const char *end
, *start
= (*func
)(temp
.contents(),
1472 temp
.contents() + temp
.length(),
1477 result
.append(temp
.contents(), start
- temp
.contents());
1483 result
.append(start
, end
- start
);
1487 result
.append(end
, temp
.contents() + temp
.length() - end
);
1495 static void first_part(int len
, const char *ptr
, const char *end
,
1499 const char *token_start
= ptr
;
1500 if (!get_token(&ptr
, end
))
1502 const token_info
*ti
= lookup_token(token_start
, ptr
);
1503 int counts
= ti
->sortify_non_empty(token_start
, ptr
);
1504 if (counts
&& --len
< 0)
1506 if (counts
|| ti
->is_accent())
1507 result
.append(token_start
, ptr
- token_start
);
1511 static void last_part(int len
, const char *ptr
, const char *end
,
1514 const char *start
= ptr
;
1517 const char *token_start
= ptr
;
1518 if (!get_token(&ptr
, end
))
1520 const token_info
*ti
= lookup_token(token_start
, ptr
);
1521 if (ti
->sortify_non_empty(token_start
, ptr
))
1525 int skip
= count
- len
;
1528 const char *token_start
= ptr
;
1529 if (!get_token(&ptr
, end
))
1531 const token_info
*ti
= lookup_token(token_start
, ptr
);
1532 if (ti
->sortify_non_empty(token_start
, ptr
) && --skip
< 0) {
1538 first_part(len
, ptr
, end
, result
);
1541 void truncate_expr::evaluate(int tentative
, const reference
&ref
,
1542 string
&result
, substring_position
&)
1546 substring_position temp_pos
;
1547 expr
->evaluate(tentative
, ref
, temp
, temp_pos
);
1548 const char *start
= temp
.contents();
1549 const char *end
= start
+ temp
.length();
1551 first_part(n
, start
, end
, result
);
1553 last_part(-n
, start
, end
, result
);
1557 void alternative_expr::evaluate(int tentative
, const reference
&ref
,
1558 string
&result
, substring_position
&pos
)
1560 int start_length
= result
.length();
1562 expr1
->evaluate(tentative
, ref
, result
, pos
);
1563 if (result
.length() == start_length
&& expr2
)
1564 expr2
->evaluate(tentative
, ref
, result
, pos
);
1567 void list_expr::evaluate(int tentative
, const reference
&ref
,
1568 string
&result
, substring_position
&pos
)
1571 expr1
->evaluate(tentative
, ref
, result
, pos
);
1573 expr2
->evaluate(tentative
, ref
, result
, pos
);
1576 void substitute_expr::evaluate(int tentative
, const reference
&ref
,
1577 string
&result
, substring_position
&pos
)
1579 int start_length
= result
.length();
1581 expr1
->evaluate(tentative
, ref
, result
, pos
);
1582 if (result
.length() > start_length
&& result
[result
.length() - 1] == '-') {
1583 // ought to see if pos covers the -
1584 result
.set_length(result
.length() - 1);
1586 expr2
->evaluate(tentative
, ref
, result
, pos
);
1590 void conditional_expr::evaluate(int tentative
, const reference
&ref
,
1591 string
&result
, substring_position
&pos
)
1594 substring_position temp_pos
;
1596 expr1
->evaluate(tentative
, ref
, temp
, temp_pos
);
1597 if (temp
.length() > 0) {
1599 expr2
->evaluate(tentative
, ref
, result
, pos
);
1603 expr3
->evaluate(tentative
, ref
, result
, pos
);
1607 void reference::pre_compute_label()
1609 if (parsed_label
!= 0
1610 && (parsed_label
->analyze() & expression::CONTAINS_VARIABLE
)) {
1612 substring_position temp_pos
;
1613 parsed_label
->evaluate(1, *this, label
, temp_pos
);
1614 label_ptr
= lookup_label(label
);
1618 void reference::compute_label()
1622 parsed_label
->evaluate(0, *this, label
, separator_pos
);
1623 if (short_label_flag
&& parsed_short_label
)
1624 parsed_short_label
->evaluate(0, *this, short_label
, short_separator_pos
);
1625 if (date_as_label
) {
1627 if (parsed_date_label
) {
1628 substring_position temp_pos
;
1629 parsed_date_label
->evaluate(0, *this, new_date
, temp_pos
);
1634 label_ptr
->count
+= 1;
1637 void reference::immediate_compute_label()
1640 label_ptr
->total
= 2; // force use of disambiguator
1644 int reference::merge_labels(reference
**v
, int n
, label_type type
,
1647 if (abbreviate_label_ranges
)
1648 return merge_labels_by_number(v
, n
, type
, result
);
1650 return merge_labels_by_parts(v
, n
, type
, result
);
1653 int reference::merge_labels_by_number(reference
**v
, int n
, label_type type
,
1658 int num
= get_number();
1659 // Only merge three or more labels.
1660 if (v
[0]->get_number() != num
+ 1
1661 || v
[1]->get_number() != num
+ 2)
1663 for (int i
= 2; i
< n
; i
++)
1664 if (v
[i
]->get_number() != num
+ i
+ 1)
1666 result
= get_label(type
);
1667 result
+= label_range_indicator
;
1668 result
+= v
[i
- 1]->get_label(type
);
1672 const substring_position
&reference::get_separator_pos(label_type type
) const
1674 if (type
== SHORT_LABEL
&& short_label_flag
)
1675 return short_separator_pos
;
1677 return separator_pos
;
1680 const string
&reference::get_label(label_type type
) const
1682 if (type
== SHORT_LABEL
&& short_label_flag
)
1688 int reference::merge_labels_by_parts(reference
**v
, int n
, label_type type
,
1693 const string
&lb
= get_label(type
);
1694 const substring_position
&sp
= get_separator_pos(type
);
1696 || sp
.start
!= v
[0]->get_separator_pos(type
).start
1697 || memcmp(lb
.contents(), v
[0]->get_label(type
).contents(),
1703 result
+= separate_label_second_parts
;
1704 const substring_position
&s
= v
[i
]->get_separator_pos(type
);
1705 int sep_end_pos
= s
.start
+ s
.length
;
1706 result
.append(v
[i
]->get_label(type
).contents() + sep_end_pos
,
1707 v
[i
]->get_label(type
).length() - sep_end_pos
);
1709 && sp
.start
== v
[i
]->get_separator_pos(type
).start
1710 && memcmp(lb
.contents(), v
[i
]->get_label(type
).contents(),
1717 label_info::label_info(const string
&s
)
1718 : count(0), total(1), length(s
.length()), start(label_pool
.length())
1723 static label_info
**label_table
= 0;
1724 static int label_table_size
= 0;
1725 static int label_table_used
= 0;
1727 label_info
*lookup_label(const string
&label
)
1729 if (label_table
== 0) {
1730 label_table
= new label_info
*[17];
1731 label_table_size
= 17;
1732 for (int i
= 0; i
< 17; i
++)
1735 unsigned h
= hash_string(label
.contents(), label
.length()) % label_table_size
;
1736 for (label_info
**ptr
= label_table
+ h
;
1738 (ptr
== label_table
)
1739 ? (ptr
= label_table
+ label_table_size
- 1)
1741 if ((*ptr
)->length
== label
.length()
1742 && memcmp(label_pool
.contents() + (*ptr
)->start
, label
.contents(),
1743 label
.length()) == 0) {
1747 label_info
*result
= *ptr
= new label_info(label
);
1748 if (++label_table_used
* 2 > label_table_size
) {
1749 // Rehash the table.
1750 label_info
**old_table
= label_table
;
1751 int old_size
= label_table_size
;
1752 label_table_size
= next_size(label_table_size
);
1753 label_table
= new label_info
*[label_table_size
];
1755 for (i
= 0; i
< label_table_size
; i
++)
1757 for (i
= 0; i
< old_size
; i
++)
1759 unsigned h
= hash_string(label_pool
.contents() + old_table
[i
]->start
,
1760 old_table
[i
]->length
);
1761 for (label_info
**p
= label_table
+ (h
% label_table_size
);
1764 ? (p
= label_table
+ label_table_size
- 1)
1776 for (int i
= 0; i
< label_table_size
; i
++) {
1777 delete label_table
[i
];
1780 label_table_used
= 0;
1784 static void consider_authors(reference
**start
, reference
**end
, int i
);
1786 void compute_labels(reference
**v
, int n
)
1789 && (parsed_label
->analyze() & expression::CONTAINS_AT
)
1790 && sort_fields
.length() >= 2
1791 && sort_fields
[0] == 'A'
1792 && sort_fields
[1] == '+')
1793 consider_authors(v
, v
+ n
, 0);
1794 for (int i
= 0; i
< n
; i
++)
1795 v
[i
]->compute_label();
1799 /* A reference with a list of authors <A0,A1,...,AN> _needs_ author i
1800 where 0 <= i <= N if there exists a reference with a list of authors
1801 <B0,B1,...,BM> such that <A0,A1,...,AN> != <B0,B1,...,BM> and M >= i
1802 and Aj = Bj for 0 <= j < i. In this case if we can't say ``A0,
1803 A1,...,A(i-1) et al'' because this would match both <A0,A1,...,AN> and
1804 <B0,B1,...,BM>. If a reference needs author i we only have to call
1805 need_author(j) for some j >= i such that the reference also needs
1808 /* This function handles 2 tasks:
1809 determine which authors are needed (cannot be elided with et al.);
1810 determine which authors can have only last names in the labels.
1812 References >= start and < end have the same first i author names.
1813 Also they're sorted by A+. */
1815 static void consider_authors(reference
**start
, reference
**end
, int i
)
1819 reference
**p
= start
;
1820 if (i
>= (*p
)->get_nauthors()) {
1821 for (++p
; p
< end
&& i
>= (*p
)->get_nauthors(); p
++)
1823 if (p
< end
&& i
> 0) {
1824 // If we have an author list <A B C> and an author list <A B C D>,
1825 // then both lists need C.
1826 for (reference
**q
= start
; q
< end
; q
++)
1827 (*q
)->need_author(i
- 1);
1832 reference
**last_name_start
= p
;
1833 reference
**name_start
= p
;
1835 p
< end
&& i
< (*p
)->get_nauthors()
1836 && same_author_last_name(**last_name_start
, **p
, i
);
1838 if (!same_author_name(**name_start
, **p
, i
)) {
1839 consider_authors(name_start
, p
, i
+ 1);
1843 consider_authors(name_start
, p
, i
+ 1);
1844 if (last_name_start
== name_start
) {
1845 for (reference
**q
= last_name_start
; q
< p
; q
++)
1846 (*q
)->set_last_name_unambiguous(i
);
1848 // If we have an author list <A B C D> and <A B C E>, then the lists
1849 // need author D and E respectively.
1850 if (name_start
> start
|| p
< end
) {
1851 for (reference
**q
= last_name_start
; q
< p
; q
++)
1852 (*q
)->need_author(i
);
1857 int same_author_last_name(const reference
&r1
, const reference
&r2
, int n
)
1860 const char *as1
= r1
.get_sort_field(0, n
, 0, &ae1
);
1863 const char *as2
= r2
.get_sort_field(0, n
, 0, &ae2
);
1865 return ae1
- as1
== ae2
- as2
&& memcmp(as1
, as2
, ae1
- as1
) == 0;
1868 int same_author_name(const reference
&r1
, const reference
&r2
, int n
)
1871 const char *as1
= r1
.get_sort_field(0, n
, -1, &ae1
);
1874 const char *as2
= r2
.get_sort_field(0, n
, -1, &ae2
);
1876 return ae1
- as1
== ae2
- as2
&& memcmp(as1
, as2
, ae1
- as1
) == 0;
1880 void int_set::set(int i
)
1884 if (bytei
>= v
.length()) {
1885 int old_length
= v
.length();
1886 v
.set_length(bytei
+ 1);
1887 for (int j
= old_length
; j
<= bytei
; j
++)
1890 v
[bytei
] |= 1 << (i
& 7);
1893 int int_set::get(int i
) const
1897 return bytei
>= v
.length() ? 0 : (v
[bytei
] & (1 << (i
& 7))) != 0;
1900 void reference::set_last_name_unambiguous(int i
)
1902 last_name_unambiguous
.set(i
);
1905 void reference::need_author(int n
)
1907 if (n
> last_needed_author
)
1908 last_needed_author
= n
;
1911 const char *reference::get_authors(const char **end
) const
1913 if (!computed_authors
) {
1914 ((reference
*)this)->computed_authors
= 1;
1915 string
&result
= ((reference
*)this)->authors
;
1916 int na
= get_nauthors();
1918 for (int i
= 0; i
< na
; i
++) {
1919 if (last_name_unambiguous
.get(i
)) {
1920 const char *e
, *start
= get_author_last_name(i
, &e
);
1922 result
.append(start
, e
- start
);
1925 const char *e
, *start
= get_author(i
, &e
);
1927 result
.append(start
, e
- start
);
1929 if (i
== last_needed_author
1930 && et_al
.length() > 0
1931 && et_al_min_elide
> 0
1932 && last_needed_author
+ et_al_min_elide
< na
1933 && na
>= et_al_min_total
) {
1939 result
+= join_authors_exactly_two
;
1940 else if (i
< na
- 2)
1941 result
+= join_authors_default
;
1943 result
+= join_authors_last_two
;
1947 const char *start
= authors
.contents();
1948 *end
= start
+ authors
.length();
1952 int reference::get_nauthors() const
1956 for (int na
= 0; get_author(na
, &dummy
) != 0; na
++)
1958 ((reference
*)this)->nauthors
= na
;