home *** CD-ROM | disk | FTP | other *** search
/ Aminet 10 / aminetcdnumber101996.iso / Aminet / util / gnu / groff_src.lha / groff-1.10src / refer / label.cc < prev    next >
C/C++ Source or Header  |  1995-11-20  |  47KB  |  1,713 lines

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