2 /*static char yysccsid[] = "from: @(#)yaccpar 1.9 (Berkeley) 02/21/93";*/
3 static char yyrcsid
[] = "$Id$";
8 #define yyclearin (yychar=(-1))
9 #define yyerrok (yyerrflag=0)
10 #define YYRECOVERING (yyerrflag!=0)
20 void yyerror(const char *);
23 static const char *format_serial(char c
, int n
);
30 label_info(const string
&);
33 label_info
*lookup_label(const string
&label
);
37 /* Does the tentative label depend on the reference?*/
38 CONTAINS_VARIABLE
= 01,
43 virtual ~expression() { }
44 virtual void evaluate(int, const reference
&, string
&,
45 substring_position
&) = 0;
46 virtual unsigned analyze() { return 0; }
49 class at_expr
: public expression
{
52 void evaluate(int, const reference
&, string
&, substring_position
&);
53 unsigned analyze() { return CONTAINS_VARIABLE
|CONTAINS_AT
; }
56 class format_expr
: public expression
{
61 format_expr(char c
, int w
= 0, int f
= 1)
62 : type(c
), width(w
), first_number(f
) { }
63 void evaluate(int, const reference
&, string
&, substring_position
&);
64 unsigned analyze() { return CONTAINS_FORMAT
; }
67 class field_expr
: public expression
{
71 field_expr(char nm
, int num
) : number(num
), name(nm
) { }
72 void evaluate(int, const reference
&, string
&, substring_position
&);
73 unsigned analyze() { return CONTAINS_VARIABLE
; }
76 class literal_expr
: public expression
{
79 literal_expr(const char *ptr
, int len
) : s(ptr
, len
) { }
80 void evaluate(int, const reference
&, string
&, substring_position
&);
83 class unary_expr
: public expression
{
87 unary_expr(expression
*e
) : expr(e
) { }
88 ~unary_expr() { delete expr
; }
89 void evaluate(int, const reference
&, string
&, substring_position
&) = 0;
90 unsigned analyze() { return expr
? expr
->analyze() : 0; }
93 /* This caches the analysis of an expression.*/
95 class analyzed_expr
: public unary_expr
{
98 analyzed_expr(expression
*);
99 void evaluate(int, const reference
&, string
&, substring_position
&);
100 unsigned analyze() { return flags
; }
103 class star_expr
: public unary_expr
{
105 star_expr(expression
*e
) : unary_expr(e
) { }
106 void evaluate(int, const reference
&, string
&, substring_position
&);
108 return ((expr
? (expr
->analyze() & ~CONTAINS_VARIABLE
) : 0)
113 typedef void map_func(const char *, const char *, string
&);
115 class map_expr
: public unary_expr
{
118 map_expr(expression
*e
, map_func
*f
) : unary_expr(e
), func(f
) { }
119 void evaluate(int, const reference
&, string
&, substring_position
&);
122 typedef const char *extractor_func(const char *, const char *, const char **);
124 class extractor_expr
: public unary_expr
{
126 extractor_func
*func
;
128 enum { BEFORE
= +1, MATCH
= 0, AFTER
= -1 };
129 extractor_expr(expression
*e
, extractor_func
*f
, int pt
)
130 : unary_expr(e
), part(pt
), func(f
) { }
131 void evaluate(int, const reference
&, string
&, substring_position
&);
134 class truncate_expr
: public unary_expr
{
137 truncate_expr(expression
*e
, int i
) : unary_expr(e
), n(i
) { }
138 void evaluate(int, const reference
&, string
&, substring_position
&);
141 class separator_expr
: public unary_expr
{
143 separator_expr(expression
*e
) : unary_expr(e
) { }
144 void evaluate(int, const reference
&, string
&, substring_position
&);
147 class binary_expr
: public expression
{
152 binary_expr(expression
*e1
, expression
*e2
) : expr1(e1
), expr2(e2
) { }
153 ~binary_expr() { delete expr1
; delete expr2
; }
154 void evaluate(int, const reference
&, string
&, substring_position
&) = 0;
156 return (expr1
? expr1
->analyze() : 0) | (expr2
? expr2
->analyze() : 0);
160 class alternative_expr
: public binary_expr
{
162 alternative_expr(expression
*e1
, expression
*e2
) : binary_expr(e1
, e2
) { }
163 void evaluate(int, const reference
&, string
&, substring_position
&);
166 class list_expr
: public binary_expr
{
168 list_expr(expression
*e1
, expression
*e2
) : binary_expr(e1
, e2
) { }
169 void evaluate(int, const reference
&, string
&, substring_position
&);
172 class substitute_expr
: public binary_expr
{
174 substitute_expr(expression
*e1
, expression
*e2
) : binary_expr(e1
, e2
) { }
175 void evaluate(int, const reference
&, string
&, substring_position
&);
178 class ternary_expr
: public expression
{
184 ternary_expr(expression
*e1
, expression
*e2
, expression
*e3
)
185 : expr1(e1
), expr2(e2
), expr3(e3
) { }
186 ~ternary_expr() { delete expr1
; delete expr2
; delete expr3
; }
187 void evaluate(int, const reference
&, string
&, substring_position
&) = 0;
189 return ((expr1
? expr1
->analyze() : 0)
190 | (expr2
? expr2
->analyze() : 0)
191 | (expr3
? expr3
->analyze() : 0));
195 class conditional_expr
: public ternary_expr
{
197 conditional_expr(expression
*e1
, expression
*e2
, expression
*e3
)
198 : ternary_expr(e1
, e2
, e3
) { }
199 void evaluate(int, const reference
&, string
&, substring_position
&);
202 static expression
*parsed_label
= 0;
203 static expression
*parsed_date_label
= 0;
204 static expression
*parsed_short_label
= 0;
206 static expression
*parse_result
;
214 struct { int ndigits
; int val
; } dig
;
215 struct { int start
; int len
; } str
;
218 #define TOKEN_LETTER 257
219 #define TOKEN_LITERAL 258
220 #define TOKEN_DIGIT 259
221 #define YYERRCODE 256
222 short yylhs
[] = { -1,
223 0, 1, 1, 6, 6, 2, 2, 2, 3, 3,
224 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
225 4, 4, 4, 4, 9, 9, 7, 7, 8, 8,
229 1, 1, 5, 0, 1, 1, 3, 3, 1, 2,
230 1, 3, 1, 1, 1, 2, 2, 2, 5, 3,
231 3, 2, 3, 3, 0, 1, 1, 2, 1, 2,
234 short yydefred
[] = { 0,
235 0, 14, 13, 0, 0, 0, 0, 5, 0, 0,
236 0, 0, 1, 27, 0, 17, 29, 0, 0, 0,
237 0, 0, 0, 0, 0, 0, 0, 22, 0, 28,
238 30, 23, 24, 0, 0, 0, 32, 33, 0, 0,
239 0, 0, 0, 0, 3, 0, 19,
241 short yydgoto
[] = { 7,
242 8, 9, 10, 11, 12, 13, 15, 18, 47, 39,
244 short yysindex
[] = { -32,
245 -257, 0, 0, -240, -32, -32, 0, 0, -18, -32,
246 -36, -114, 0, 0, -246, 0, 0, -241, -14, -39,
247 -32, -32, -32, -114, -21, -257, -257, 0, -32, 0,
248 0, 0, 0, -25, -32, -32, 0, 0, -223, -246,
249 -246, -36, -32, -257, 0, -246, 0,
251 short yyrindex
[] = { 35,
252 1, 0, 0, 0, -5, -4, 0, 0, 14, 208,
253 159, 224, 0, 0, 11, 0, 0, 40, 0, 0,
254 2, 0, 0, 253, -220, 0, 0, 0, 0, 0,
255 0, 0, 0, 0, 263, 281, 0, 0, 0, 50,
256 105, 214, 0, 115, 0, 149, 0,
258 short yygindex
[] = { 0,
259 19, 0, 7, 37, -10, 10, -23, 0, 0, 0,
261 #define YYTABLESIZE 511
262 short yytable
[] = { 24,
263 15, 14, 40, 41, 4, 28, 26, 5, 27, 25,
264 16, 29, 30, 2, 19, 20, 16, 31, 17, 23,
265 46, 37, 33, 38, 24, 24, 32, 6, 35, 36,
266 34, 3, 43, 44, 4, 4, 31, 15, 15, 18,
267 15, 15, 15, 15, 21, 15, 15, 16, 16, 20,
268 16, 16, 16, 16, 2, 16, 16, 4, 15, 4,
269 15, 45, 15, 15, 15, 42, 0, 0, 16, 0,
270 16, 2, 16, 16, 16, 2, 18, 18, 0, 18,
271 18, 18, 18, 0, 18, 18, 20, 20, 0, 20,
272 20, 20, 20, 0, 20, 20, 0, 18, 0, 18,
273 0, 18, 18, 18, 21, 22, 0, 20, 0, 20,
274 0, 20, 20, 20, 25, 0, 0, 0, 0, 0,
275 0, 0, 0, 0, 15, 0, 15, 0, 0, 0,
276 0, 0, 0, 0, 16, 0, 16, 0, 0, 0,
277 0, 21, 21, 0, 21, 21, 21, 21, 26, 21,
278 21, 25, 25, 0, 25, 25, 25, 25, 11, 25,
279 25, 0, 21, 18, 21, 18, 21, 21, 21, 0,
280 0, 0, 25, 20, 25, 20, 25, 25, 25, 0,
281 0, 0, 0, 0, 0, 26, 26, 0, 26, 26,
282 26, 26, 0, 26, 26, 11, 11, 0, 11, 11,
283 0, 0, 0, 0, 0, 0, 26, 6, 26, 0,
284 26, 26, 26, 12, 0, 0, 11, 0, 11, 0,
285 11, 11, 11, 9, 1, 2, 0, 0, 21, 0,
286 21, 0, 0, 0, 0, 0, 0, 0, 25, 0,
287 25, 0, 0, 0, 0, 6, 0, 0, 6, 0,
288 12, 12, 10, 12, 12, 0, 0, 15, 15, 0,
289 9, 9, 7, 9, 9, 6, 0, 16, 16, 6,
290 6, 12, 26, 12, 26, 12, 12, 12, 0, 0,
291 8, 9, 11, 9, 11, 9, 9, 9, 0, 10,
292 10, 0, 10, 10, 0, 0, 18, 18, 0, 0,
293 7, 0, 0, 7, 0, 0, 20, 20, 0, 0,
294 10, 0, 10, 0, 10, 10, 10, 0, 8, 0,
295 7, 8, 0, 0, 7, 7, 0, 0, 0, 0,
296 0, 6, 0, 0, 0, 0, 0, 12, 8, 12,
297 0, 0, 8, 8, 0, 0, 0, 9, 0, 0,
298 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
299 0, 21, 21, 0, 0, 0, 0, 0, 0, 0,
300 0, 25, 25, 0, 0, 0, 10, 0, 0, 0,
301 0, 0, 0, 0, 0, 0, 7, 0, 0, 0,
302 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
303 0, 0, 0, 0, 8, 26, 26, 0, 0, 0,
304 0, 0, 0, 0, 0, 11, 11, 0, 0, 0,
305 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
306 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
307 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
308 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
309 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
310 12, 12, 0, 0, 0, 0, 0, 0, 0, 0,
311 9, 9, 0, 0, 0, 0, 0, 0, 0, 0,
312 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
313 0, 0, 0, 0, 0, 0, 0, 0, 0, 10,
316 short yycheck
[] = { 10,
317 0, 259, 26, 27, 37, 42, 43, 40, 45, 46,
318 0, 126, 259, 0, 5, 6, 257, 259, 259, 38,
319 44, 43, 62, 45, 35, 36, 41, 60, 22, 23,
320 21, 64, 58, 257, 0, 41, 257, 37, 38, 0,
321 40, 41, 42, 43, 63, 45, 46, 37, 38, 0,
322 40, 41, 42, 43, 41, 45, 46, 62, 58, 58,
323 60, 43, 62, 63, 64, 29, -1, -1, 58, -1,
324 60, 58, 62, 63, 64, 62, 37, 38, -1, 40,
325 41, 42, 43, -1, 45, 46, 37, 38, -1, 40,
326 41, 42, 43, -1, 45, 46, -1, 58, -1, 60,
327 -1, 62, 63, 64, 0, 124, -1, 58, -1, 60,
328 -1, 62, 63, 64, 0, -1, -1, -1, -1, -1,
329 -1, -1, -1, -1, 124, -1, 126, -1, -1, -1,
330 -1, -1, -1, -1, 124, -1, 126, -1, -1, -1,
331 -1, 37, 38, -1, 40, 41, 42, 43, 0, 45,
332 46, 37, 38, -1, 40, 41, 42, 43, 0, 45,
333 46, -1, 58, 124, 60, 126, 62, 63, 64, -1,
334 -1, -1, 58, 124, 60, 126, 62, 63, 64, -1,
335 -1, -1, -1, -1, -1, 37, 38, -1, 40, 41,
336 42, 43, -1, 45, 46, 37, 38, -1, 40, 41,
337 -1, -1, -1, -1, -1, -1, 58, 0, 60, -1,
338 62, 63, 64, 0, -1, -1, 58, -1, 60, -1,
339 62, 63, 64, 0, 257, 258, -1, -1, 124, -1,
340 126, -1, -1, -1, -1, -1, -1, -1, 124, -1,
341 126, -1, -1, -1, -1, 38, -1, -1, 41, -1,
342 37, 38, 0, 40, 41, -1, -1, 257, 258, -1,
343 37, 38, 0, 40, 41, 58, -1, 257, 258, 62,
344 63, 58, 124, 60, 126, 62, 63, 64, -1, -1,
345 0, 58, 124, 60, 126, 62, 63, 64, -1, 37,
346 38, -1, 40, 41, -1, -1, 257, 258, -1, -1,
347 38, -1, -1, 41, -1, -1, 257, 258, -1, -1,
348 58, -1, 60, -1, 62, 63, 64, -1, 38, -1,
349 58, 41, -1, -1, 62, 63, -1, -1, -1, -1,
350 -1, 124, -1, -1, -1, -1, -1, 124, 58, 126,
351 -1, -1, 62, 63, -1, -1, -1, 124, -1, -1,
352 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
353 -1, 257, 258, -1, -1, -1, -1, -1, -1, -1,
354 -1, 257, 258, -1, -1, -1, 124, -1, -1, -1,
355 -1, -1, -1, -1, -1, -1, 124, -1, -1, -1,
356 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
357 -1, -1, -1, -1, 124, 257, 258, -1, -1, -1,
358 -1, -1, -1, -1, -1, 257, 258, -1, -1, -1,
359 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
360 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
361 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
362 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
363 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
364 257, 258, -1, -1, -1, -1, -1, -1, -1, -1,
365 257, 258, -1, -1, -1, -1, -1, -1, -1, -1,
366 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
367 -1, -1, -1, -1, -1, -1, -1, -1, -1, 257,
374 #define YYMAXTOKEN 259
377 "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,
378 0,0,0,"'%'","'&'",0,"'('","')'","'*'","'+'",0,"'-'","'.'",0,0,0,0,0,0,0,0,0,0,0,
379 "':'",0,"'<'",0,"'>'","'?'","'@'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
380 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"'|'",0,
381 "'~'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
382 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
383 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
384 0,0,0,0,0,0,0,0,0,0,0,0,0,"TOKEN_LETTER","TOKEN_LITERAL","TOKEN_DIGIT",
388 "expr : optional_conditional",
389 "conditional : alternative",
390 "conditional : alternative '?' optional_conditional ':' conditional",
391 "optional_conditional :",
392 "optional_conditional : conditional",
393 "alternative : list",
394 "alternative : alternative '|' list",
395 "alternative : alternative '&' list",
397 "list : list substitute",
398 "substitute : string",
399 "substitute : substitute '~' string",
401 "string : TOKEN_LITERAL",
402 "string : TOKEN_LETTER",
403 "string : TOKEN_LETTER number",
404 "string : '%' TOKEN_LETTER",
405 "string : '%' digits",
406 "string : string '.' flag TOKEN_LETTER optional_number",
407 "string : string '+' number",
408 "string : string '-' number",
409 "string : string '*'",
410 "string : '(' optional_conditional ')'",
411 "string : '<' optional_conditional '>'",
413 "optional_number : number",
414 "number : TOKEN_DIGIT",
415 "number : number TOKEN_DIGIT",
416 "digits : TOKEN_DIGIT",
417 "digits : digits TOKEN_DIGIT",
425 #define YYMAXDEPTH YYSTACKSIZE
428 #define YYSTACKSIZE YYMAXDEPTH
430 #define YYSTACKSIZE 500
431 #define YYMAXDEPTH 500
442 short yyss
[YYSTACKSIZE
];
443 YYSTYPE yyvs
[YYSTACKSIZE
];
444 #define yystacksize YYSTACKSIZE
447 /* bison defines const to be empty unless __STDC__ is defined, which it
448 isn't under cfront */
454 const char *spec_ptr
;
455 const char *spec_end
;
456 const char *spec_cur
;
460 while (spec_ptr
< spec_end
&& csspace(*spec_ptr
))
463 if (spec_ptr
>= spec_end
)
465 unsigned char c
= *spec_ptr
++;
471 yylval
.num
= c
- '0';
475 yylval
.str
.start
= literals
.length();
476 for (; spec_ptr
< spec_end
; spec_ptr
++) {
477 if (*spec_ptr
== '\'') {
478 if (++spec_ptr
< spec_end
&& *spec_ptr
== '\'')
481 yylval
.str
.len
= literals
.length() - yylval
.str
.start
;
482 return TOKEN_LITERAL
;
486 literals
+= *spec_ptr
;
488 yylval
.str
.len
= literals
.length() - yylval
.str
.start
;
489 return TOKEN_LITERAL
;
494 int set_label_spec(const char *label_spec
)
496 spec_cur
= spec_ptr
= label_spec
;
497 spec_end
= strchr(label_spec
, '\0');
502 parsed_label
= parse_result
;
506 int set_date_label_spec(const char *label_spec
)
508 spec_cur
= spec_ptr
= label_spec
;
509 spec_end
= strchr(label_spec
, '\0');
513 delete parsed_date_label
;
514 parsed_date_label
= parse_result
;
518 int set_short_label_spec(const char *label_spec
)
520 spec_cur
= spec_ptr
= label_spec
;
521 spec_end
= strchr(label_spec
, '\0');
525 delete parsed_short_label
;
526 parsed_short_label
= parse_result
;
530 void yyerror(const char *message
)
532 if (spec_cur
< spec_end
)
533 command_error("label specification %1 before `%2'", message
, spec_cur
);
535 command_error("label specification %1 at end of string",
539 void at_expr::evaluate(int tentative
, const reference
&ref
,
540 string
&result
, substring_position
&)
543 ref
.canonicalize_authors(result
);
545 const char *end
, *start
= ref
.get_authors(&end
);
547 result
.append(start
, end
- start
);
551 void format_expr::evaluate(int tentative
, const reference
&ref
,
552 string
&result
, substring_position
&)
556 const label_info
*lp
= ref
.get_label_ptr();
557 int num
= lp
== 0 ? ref
.get_number() : lp
->count
;
559 result
+= format_serial(type
, num
+ 1);
561 const char *ptr
= i_to_a(num
+ first_number
);
562 int pad
= width
- strlen(ptr
);
569 static const char *format_serial(char c
, int n
)
572 static char buf
[128]; // more than enough.
578 // troff uses z and w to represent 10000 and 5000 in Roman
579 // numerals; I can find no historical basis for this usage
580 const char *s
= c
== 'i' ? "zwmdclxvi" : "ZWMDCLXVI";
587 for (int i
= 1000; i
> 0; i
/= 10, s
+= 2) {
634 // this is derived from troff/reg.c
641 *p
++ = c
+ d
- 1; // ASCII dependent
661 void field_expr::evaluate(int, const reference
&ref
,
662 string
&result
, substring_position
&)
665 const char *start
= ref
.get_field(name
, &end
);
667 start
= nth_field(number
, start
, &end
);
669 result
.append(start
, end
- start
);
673 void literal_expr::evaluate(int, const reference
&,
674 string
&result
, substring_position
&)
679 analyzed_expr::analyzed_expr(expression
*e
)
680 : unary_expr(e
), flags(e
? e
->analyze() : 0)
684 void analyzed_expr::evaluate(int tentative
, const reference
&ref
,
685 string
&result
, substring_position
&pos
)
688 expr
->evaluate(tentative
, ref
, result
, pos
);
691 void star_expr::evaluate(int tentative
, const reference
&ref
,
692 string
&result
, substring_position
&pos
)
694 const label_info
*lp
= ref
.get_label_ptr();
696 && (lp
== 0 || lp
->total
> 1)
698 expr
->evaluate(tentative
, ref
, result
, pos
);
701 void separator_expr::evaluate(int tentative
, const reference
&ref
,
702 string
&result
, substring_position
&pos
)
704 int start_length
= result
.length();
705 int is_first
= pos
.start
< 0;
707 expr
->evaluate(tentative
, ref
, result
, pos
);
709 pos
.start
= start_length
;
710 pos
.length
= result
.length() - start_length
;
714 void map_expr::evaluate(int tentative
, const reference
&ref
,
715 string
&result
, substring_position
&)
719 substring_position temp_pos
;
720 expr
->evaluate(tentative
, ref
, temp
, temp_pos
);
721 (*func
)(temp
.contents(), temp
.contents() + temp
.length(), result
);
725 void extractor_expr::evaluate(int tentative
, const reference
&ref
,
726 string
&result
, substring_position
&)
730 substring_position temp_pos
;
731 expr
->evaluate(tentative
, ref
, temp
, temp_pos
);
732 const char *end
, *start
= (*func
)(temp
.contents(),
733 temp
.contents() + temp
.length(),
738 result
.append(temp
.contents(), start
- temp
.contents());
744 result
.append(start
, end
- start
);
748 result
.append(end
, temp
.contents() + temp
.length() - end
);
756 static void first_part(int len
, const char *ptr
, const char *end
,
760 const char *token_start
= ptr
;
761 if (!get_token(&ptr
, end
))
763 const token_info
*ti
= lookup_token(token_start
, ptr
);
764 int counts
= ti
->sortify_non_empty(token_start
, ptr
);
765 if (counts
&& --len
< 0)
767 if (counts
|| ti
->is_accent())
768 result
.append(token_start
, ptr
- token_start
);
772 static void last_part(int len
, const char *ptr
, const char *end
,
775 const char *start
= ptr
;
778 const char *token_start
= ptr
;
779 if (!get_token(&ptr
, end
))
781 const token_info
*ti
= lookup_token(token_start
, ptr
);
782 if (ti
->sortify_non_empty(token_start
, ptr
))
786 int skip
= count
- len
;
789 const char *token_start
= ptr
;
790 if (!get_token(&ptr
, end
))
792 const token_info
*ti
= lookup_token(token_start
, ptr
);
793 if (ti
->sortify_non_empty(token_start
, ptr
) && --skip
< 0) {
799 first_part(len
, ptr
, end
, result
);
802 void truncate_expr::evaluate(int tentative
, const reference
&ref
,
803 string
&result
, substring_position
&)
807 substring_position temp_pos
;
808 expr
->evaluate(tentative
, ref
, temp
, temp_pos
);
809 const char *start
= temp
.contents();
810 const char *end
= start
+ temp
.length();
812 first_part(n
, start
, end
, result
);
814 last_part(-n
, start
, end
, result
);
818 void alternative_expr::evaluate(int tentative
, const reference
&ref
,
819 string
&result
, substring_position
&pos
)
821 int start_length
= result
.length();
823 expr1
->evaluate(tentative
, ref
, result
, pos
);
824 if (result
.length() == start_length
&& expr2
)
825 expr2
->evaluate(tentative
, ref
, result
, pos
);
828 void list_expr::evaluate(int tentative
, const reference
&ref
,
829 string
&result
, substring_position
&pos
)
832 expr1
->evaluate(tentative
, ref
, result
, pos
);
834 expr2
->evaluate(tentative
, ref
, result
, pos
);
837 void substitute_expr::evaluate(int tentative
, const reference
&ref
,
838 string
&result
, substring_position
&pos
)
840 int start_length
= result
.length();
842 expr1
->evaluate(tentative
, ref
, result
, pos
);
843 if (result
.length() > start_length
&& result
[result
.length() - 1] == '-') {
844 // ought to see if pos covers the -
845 result
.set_length(result
.length() - 1);
847 expr2
->evaluate(tentative
, ref
, result
, pos
);
851 void conditional_expr::evaluate(int tentative
, const reference
&ref
,
852 string
&result
, substring_position
&pos
)
855 substring_position temp_pos
;
857 expr1
->evaluate(tentative
, ref
, temp
, temp_pos
);
858 if (temp
.length() > 0) {
860 expr2
->evaluate(tentative
, ref
, result
, pos
);
864 expr3
->evaluate(tentative
, ref
, result
, pos
);
868 void reference::pre_compute_label()
870 if (parsed_label
!= 0
871 && (parsed_label
->analyze() & expression::CONTAINS_VARIABLE
)) {
873 substring_position temp_pos
;
874 parsed_label
->evaluate(1, *this, label
, temp_pos
);
875 label_ptr
= lookup_label(label
);
879 void reference::compute_label()
883 parsed_label
->evaluate(0, *this, label
, separator_pos
);
884 if (short_label_flag
&& parsed_short_label
)
885 parsed_short_label
->evaluate(0, *this, short_label
, short_separator_pos
);
888 if (parsed_date_label
) {
889 substring_position temp_pos
;
890 parsed_date_label
->evaluate(0, *this, new_date
, temp_pos
);
895 label_ptr
->count
+= 1;
898 void reference::immediate_compute_label()
901 label_ptr
->total
= 2; // force use of disambiguator
905 int reference::merge_labels(reference
**v
, int n
, label_type type
,
908 if (abbreviate_label_ranges
)
909 return merge_labels_by_number(v
, n
, type
, result
);
911 return merge_labels_by_parts(v
, n
, type
, result
);
914 int reference::merge_labels_by_number(reference
**v
, int n
, label_type type
,
919 int num
= get_number();
920 // Only merge three or more labels.
921 if (v
[0]->get_number() != num
+ 1
922 || v
[1]->get_number() != num
+ 2)
925 for (i
= 2; i
< n
; i
++)
926 if (v
[i
]->get_number() != num
+ i
+ 1)
928 result
= get_label(type
);
929 result
+= label_range_indicator
;
930 result
+= v
[i
- 1]->get_label(type
);
934 const substring_position
&reference::get_separator_pos(label_type type
) const
936 if (type
== SHORT_LABEL
&& short_label_flag
)
937 return short_separator_pos
;
939 return separator_pos
;
942 const string
&reference::get_label(label_type type
) const
944 if (type
== SHORT_LABEL
&& short_label_flag
)
950 int reference::merge_labels_by_parts(reference
**v
, int n
, label_type type
,
955 const string
&lb
= get_label(type
);
956 const substring_position
&sp
= get_separator_pos(type
);
958 || sp
.start
!= v
[0]->get_separator_pos(type
).start
959 || memcmp(lb
.contents(), v
[0]->get_label(type
).contents(),
965 result
+= separate_label_second_parts
;
966 const substring_position
&s
= v
[i
]->get_separator_pos(type
);
967 int sep_end_pos
= s
.start
+ s
.length
;
968 result
.append(v
[i
]->get_label(type
).contents() + sep_end_pos
,
969 v
[i
]->get_label(type
).length() - sep_end_pos
);
971 && sp
.start
== v
[i
]->get_separator_pos(type
).start
972 && memcmp(lb
.contents(), v
[i
]->get_label(type
).contents(),
979 label_info::label_info(const string
&s
)
980 : start(label_pool
.length()), length(s
.length()), count(0), total(1)
985 static label_info
**label_table
= 0;
986 static int label_table_size
= 0;
987 static int label_table_used
= 0;
989 label_info
*lookup_label(const string
&label
)
991 if (label_table
== 0) {
992 label_table
= new label_info
*[17];
993 label_table_size
= 17;
994 for (int i
= 0; i
< 17; i
++)
997 unsigned h
= hash_string(label
.contents(), label
.length()) % label_table_size
;
999 for (ptr
= label_table
+ h
;
1001 (ptr
== label_table
)
1002 ? (ptr
= label_table
+ label_table_size
- 1)
1004 if ((*ptr
)->length
== label
.length()
1005 && memcmp(label_pool
.contents() + (*ptr
)->start
, label
.contents(),
1006 label
.length()) == 0) {
1010 label_info
*result
= *ptr
= new label_info(label
);
1011 if (++label_table_used
* 2 > label_table_size
) {
1012 // Rehash the table.
1013 label_info
**old_table
= label_table
;
1014 int old_size
= label_table_size
;
1015 label_table_size
= next_size(label_table_size
);
1016 label_table
= new label_info
*[label_table_size
];
1018 for (i
= 0; i
< label_table_size
; i
++)
1020 for (i
= 0; i
< old_size
; i
++)
1022 unsigned h
= hash_string(label_pool
.contents() + old_table
[i
]->start
,
1023 old_table
[i
]->length
);
1025 for (p
= label_table
+ (h
% label_table_size
);
1028 ? (p
= label_table
+ label_table_size
- 1)
1040 for (int i
= 0; i
< label_table_size
; i
++) {
1041 delete label_table
[i
];
1044 label_table_used
= 0;
1048 static void consider_authors(reference
**start
, reference
**end
, int i
);
1050 void compute_labels(reference
**v
, int n
)
1053 && (parsed_label
->analyze() & expression::CONTAINS_AT
)
1054 && sort_fields
.length() >= 2
1055 && sort_fields
[0] == 'A'
1056 && sort_fields
[1] == '+')
1057 consider_authors(v
, v
+ n
, 0);
1058 for (int i
= 0; i
< n
; i
++)
1059 v
[i
]->compute_label();
1063 /* A reference with a list of authors <A0,A1,...,AN> _needs_ author i
1064 where 0 <= i <= N if there exists a reference with a list of authors
1065 <B0,B1,...,BM> such that <A0,A1,...,AN> != <B0,B1,...,BM> and M >= i
1066 and Aj = Bj for 0 <= j < i. In this case if we can't say ``A0,
1067 A1,...,A(i-1) et al'' because this would match both <A0,A1,...,AN> and
1068 <B0,B1,...,BM>. If a reference needs author i we only have to call
1069 need_author(j) for some j >= i such that the reference also needs
1072 /* This function handles 2 tasks:
1073 determine which authors are needed (cannot be elided with et al.);
1074 determine which authors can have only last names in the labels.
1076 References >= start and < end have the same first i author names.
1077 Also they're sorted by A+. */
1079 static void consider_authors(reference
**start
, reference
**end
, int i
)
1083 reference
**p
= start
;
1084 if (i
>= (*p
)->get_nauthors()) {
1085 for (++p
; p
< end
&& i
>= (*p
)->get_nauthors(); p
++)
1087 if (p
< end
&& i
> 0) {
1088 // If we have an author list <A B C> and an author list <A B C D>,
1089 // then both lists need C.
1090 for (reference
**q
= start
; q
< end
; q
++)
1091 (*q
)->need_author(i
- 1);
1096 reference
**last_name_start
= p
;
1097 reference
**name_start
= p
;
1099 p
< end
&& i
< (*p
)->get_nauthors()
1100 && same_author_last_name(**last_name_start
, **p
, i
);
1102 if (!same_author_name(**name_start
, **p
, i
)) {
1103 consider_authors(name_start
, p
, i
+ 1);
1107 consider_authors(name_start
, p
, i
+ 1);
1108 if (last_name_start
== name_start
) {
1109 for (reference
**q
= last_name_start
; q
< p
; q
++)
1110 (*q
)->set_last_name_unambiguous(i
);
1112 // If we have an author list <A B C D> and <A B C E>, then the lists
1113 // need author D and E respectively.
1114 if (name_start
> start
|| p
< end
) {
1115 for (reference
**q
= last_name_start
; q
< p
; q
++)
1116 (*q
)->need_author(i
);
1121 int same_author_last_name(const reference
&r1
, const reference
&r2
, int n
)
1124 const char *as1
= r1
.get_sort_field(0, n
, 0, &ae1
);
1127 const char *as2
= r2
.get_sort_field(0, n
, 0, &ae2
);
1129 return ae1
- as1
== ae2
- as2
&& memcmp(as1
, as2
, ae1
- as1
) == 0;
1132 int same_author_name(const reference
&r1
, const reference
&r2
, int n
)
1135 const char *as1
= r1
.get_sort_field(0, n
, -1, &ae1
);
1138 const char *as2
= r2
.get_sort_field(0, n
, -1, &ae2
);
1140 return ae1
- as1
== ae2
- as2
&& memcmp(as1
, as2
, ae1
- as1
) == 0;
1144 void int_set::set(int i
)
1148 if (bytei
>= v
.length()) {
1149 int old_length
= v
.length();
1150 v
.set_length(bytei
+ 1);
1151 for (int j
= old_length
; j
<= bytei
; j
++)
1154 v
[bytei
] |= 1 << (i
& 7);
1157 int int_set::get(int i
) const
1161 return bytei
>= v
.length() ? 0 : (v
[bytei
] & (1 << (i
& 7))) != 0;
1164 void reference::set_last_name_unambiguous(int i
)
1166 last_name_unambiguous
.set(i
);
1169 void reference::need_author(int n
)
1171 if (n
> last_needed_author
)
1172 last_needed_author
= n
;
1175 const char *reference::get_authors(const char **end
) const
1177 if (!computed_authors
) {
1178 ((reference
*)this)->computed_authors
= 1;
1179 string
&result
= ((reference
*)this)->authors
;
1180 int na
= get_nauthors();
1182 for (int i
= 0; i
< na
; i
++) {
1183 if (last_name_unambiguous
.get(i
)) {
1184 const char *e
, *start
= get_author_last_name(i
, &e
);
1186 result
.append(start
, e
- start
);
1189 const char *e
, *start
= get_author(i
, &e
);
1191 result
.append(start
, e
- start
);
1193 if (i
== last_needed_author
1194 && et_al
.length() > 0
1195 && et_al_min_elide
> 0
1196 && last_needed_author
+ et_al_min_elide
< na
1197 && na
>= et_al_min_total
) {
1203 result
+= join_authors_exactly_two
;
1204 else if (i
< na
- 2)
1205 result
+= join_authors_default
;
1207 result
+= join_authors_last_two
;
1211 const char *start
= authors
.contents();
1212 *end
= start
+ authors
.length();
1216 int reference::get_nauthors() const
1221 for (na
= 0; get_author(na
, &dummy
) != 0; na
++)
1223 ((reference
*)this)->nauthors
= na
;
1227 #line 1228 "y.tab.c"
1228 #define YYABORT goto yyabort
1229 #define YYREJECT goto yyabort
1230 #define YYACCEPT goto yyaccept
1231 #define YYERROR goto yyerrlab
1233 #if defined(__STDC__)
1239 register int yym
, yyn
, yystate
;
1242 extern char *getenv();
1244 if (yys
= getenv("YYDEBUG"))
1247 if (yyn
>= '0' && yyn
<= '9')
1248 yydebug
= yyn
- '0';
1258 *yyssp
= yystate
= 0;
1261 if ((yyn
= yydefred
[yystate
]) != 0) goto yyreduce
;
1264 if ((yychar
= yylex()) < 0) yychar
= 0;
1269 if (yychar
<= YYMAXTOKEN
) yys
= yyname
[yychar
];
1270 if (!yys
) yys
= "illegal-symbol";
1271 printf("%sdebug: state %d, reading %d (%s)\n",
1272 YYPREFIX
, yystate
, yychar
, yys
);
1276 if ((yyn
= yysindex
[yystate
]) && (yyn
+= yychar
) >= 0 &&
1277 yyn
<= YYTABLESIZE
&& yycheck
[yyn
] == yychar
)
1281 printf("%sdebug: state %d, shifting to state %d\n",
1282 YYPREFIX
, yystate
, yytable
[yyn
]);
1284 if (yyssp
>= yyss
+ yystacksize
- 1)
1288 *++yyssp
= yystate
= yytable
[yyn
];
1291 if (yyerrflag
> 0) --yyerrflag
;
1294 if ((yyn
= yyrindex
[yystate
]) && (yyn
+= yychar
) >= 0 &&
1295 yyn
<= YYTABLESIZE
&& yycheck
[yyn
] == yychar
)
1300 if (yyerrflag
) goto yyinrecovery
;
1301 yyerror("syntax error");
1313 if ((yyn
= yysindex
[*yyssp
]) && (yyn
+= YYERRCODE
) >= 0 &&
1314 yyn
<= YYTABLESIZE
&& yycheck
[yyn
] == YYERRCODE
)
1318 printf("%sdebug: state %d, error recovery shifting\
1319 to state %d\n", YYPREFIX
, *yyssp
, yytable
[yyn
]);
1321 if (yyssp
>= yyss
+ yystacksize
- 1)
1325 *++yyssp
= yystate
= yytable
[yyn
];
1333 printf("%sdebug: error recovery discarding state %d\n",
1336 if (yyssp
<= yyss
) goto yyabort
;
1344 if (yychar
== 0) goto yyabort
;
1349 if (yychar
<= YYMAXTOKEN
) yys
= yyname
[yychar
];
1350 if (!yys
) yys
= "illegal-symbol";
1351 printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
1352 YYPREFIX
, yystate
, yychar
, yys
);
1361 printf("%sdebug: state %d, reducing by rule %d (%s)\n",
1362 YYPREFIX
, yystate
, yyn
, yyrule
[yyn
]);
1365 yyval
= yyvsp
[1-yym
];
1370 { parse_result
= (yyvsp
[0].expr
? new analyzed_expr(yyvsp
[0].expr
) : 0); }
1374 { yyval
.expr
= yyvsp
[0].expr
; }
1378 { yyval
.expr
= new conditional_expr(yyvsp
[-4].expr
, yyvsp
[-2].expr
, yyvsp
[0].expr
); }
1386 { yyval
.expr
= yyvsp
[0].expr
; }
1390 { yyval
.expr
= yyvsp
[0].expr
; }
1394 { yyval
.expr
= new alternative_expr(yyvsp
[-2].expr
, yyvsp
[0].expr
); }
1398 { yyval
.expr
= new conditional_expr(yyvsp
[-2].expr
, yyvsp
[0].expr
, 0); }
1402 { yyval
.expr
= yyvsp
[0].expr
; }
1406 { yyval
.expr
= new list_expr(yyvsp
[-1].expr
, yyvsp
[0].expr
); }
1410 { yyval
.expr
= yyvsp
[0].expr
; }
1414 { yyval
.expr
= new substitute_expr(yyvsp
[-2].expr
, yyvsp
[0].expr
); }
1418 { yyval
.expr
= new at_expr
; }
1423 yyval
.expr
= new literal_expr(literals
.contents() + yyvsp
[0].str
.start
,
1429 { yyval
.expr
= new field_expr(yyvsp
[0].num
, 0); }
1433 { yyval
.expr
= new field_expr(yyvsp
[-1].num
, yyvsp
[0].num
- 1); }
1438 switch (yyvsp
[0].num
) {
1443 yyval
.expr
= new format_expr(yyvsp
[0].num
);
1446 command_error("unrecognized format `%1'", char(yyvsp
[0].num
));
1447 yyval
.expr
= new format_expr('a');
1455 yyval
.expr
= new format_expr('0', yyvsp
[0].dig
.ndigits
, yyvsp
[0].dig
.val
);
1461 switch (yyvsp
[-1].num
) {
1463 yyval
.expr
= new map_expr(yyvsp
[-4].expr
, lowercase
);
1466 yyval
.expr
= new map_expr(yyvsp
[-4].expr
, uppercase
);
1469 yyval
.expr
= new map_expr(yyvsp
[-4].expr
, capitalize
);
1472 yyval
.expr
= new map_expr(yyvsp
[-4].expr
, reverse_name
);
1475 yyval
.expr
= new map_expr(yyvsp
[-4].expr
, abbreviate_name
);
1478 yyval
.expr
= new extractor_expr(yyvsp
[-4].expr
, find_year
, yyvsp
[-2].num
);
1481 yyval
.expr
= new extractor_expr(yyvsp
[-4].expr
, find_last_name
, yyvsp
[-2].num
);
1484 yyval
.expr
= yyvsp
[-4].expr
;
1485 command_error("unknown function `%1'", char(yyvsp
[-1].num
));
1492 { yyval
.expr
= new truncate_expr(yyvsp
[-2].expr
, yyvsp
[0].num
); }
1496 { yyval
.expr
= new truncate_expr(yyvsp
[-2].expr
, -yyvsp
[0].num
); }
1500 { yyval
.expr
= new star_expr(yyvsp
[-1].expr
); }
1504 { yyval
.expr
= yyvsp
[-1].expr
; }
1508 { yyval
.expr
= new separator_expr(yyvsp
[-1].expr
); }
1516 { yyval
.num
= yyvsp
[0].num
; }
1520 { yyval
.num
= yyvsp
[0].num
; }
1524 { yyval
.num
= yyvsp
[-1].num
*10 + yyvsp
[0].num
; }
1528 { yyval
.dig
.ndigits
= 1; yyval
.dig
.val
= yyvsp
[0].num
; }
1532 { yyval
.dig
.ndigits
= yyvsp
[-1].dig
.ndigits
+ 1; yyval
.dig
.val
= yyvsp
[-1].dig
.val
*10 + yyvsp
[0].num
; }
1546 #line 1547 "y.tab.c"
1552 if (yystate
== 0 && yym
== 0)
1556 printf("%sdebug: after reduction, shifting from state 0 to\
1557 state %d\n", YYPREFIX
, YYFINAL
);
1564 if ((yychar
= yylex()) < 0) yychar
= 0;
1569 if (yychar
<= YYMAXTOKEN
) yys
= yyname
[yychar
];
1570 if (!yys
) yys
= "illegal-symbol";
1571 printf("%sdebug: state %d, reading %d (%s)\n",
1572 YYPREFIX
, YYFINAL
, yychar
, yys
);
1576 if (yychar
== 0) goto yyaccept
;
1579 if ((yyn
= yygindex
[yym
]) && (yyn
+= yystate
) >= 0 &&
1580 yyn
<= YYTABLESIZE
&& yycheck
[yyn
] == yystate
)
1581 yystate
= yytable
[yyn
];
1583 yystate
= yydgoto
[yym
];
1586 printf("%sdebug: after reduction, shifting from state %d \
1587 to state %d\n", YYPREFIX
, *yyssp
, yystate
);
1589 if (yyssp
>= yyss
+ yystacksize
- 1)
1597 yyerror("yacc stack overflow");