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