12 #define INDENT_STRING " "
13 #define PAPER_WIDTH 74
17 char *last_label=NULL;
19 extern int yylex(void);
21 extern void yyerror(const char *x);
22 extern char *get_label(const char *label);
23 extern void set_label(const char *label, const char *target);
24 char *new_counter(const char *key);
32 %token NEW_COUNTER LABEL HASH CHAR NEWLINE NO_INDENT RIGHT
33 %type <string> stuff text
45 if (strlen($2) > (PAPER_WIDTH-(indent ? strlen(INDENT_STRING):0))) {
46 yyerror("line too long");
48 printf("%s%s\n", indent ? INDENT_STRING:"", $2);
53 | doc stuff RIGHT stuff NEWLINE {
54 char fixed[PAPER_WIDTH+1];
57 len = PAPER_WIDTH-(strlen($2)+strlen($4));
60 memset(fixed, ' ', len);
63 yyerror("line too wide");
66 printf("%s%s%s\n", $2, fixed, $4);
72 | doc stuff RIGHT stuff RIGHT stuff NEWLINE {
73 char fixed[PAPER_WIDTH+1];
76 len = PAPER_WIDTH-(strlen($2)+strlen($4));
80 yyerror("line too wide");
84 memset(fixed, ' ', l);
86 printf("%s%s%s", $2, fixed, $4);
91 memset(fixed, ' ', l);
93 printf("%s%s\n", fixed, $6);
99 | doc stuff RIGHT stuff RIGHT stuff NEWLINE {
100 char fixed[PAPER_WIDTH+1];
103 len = PAPER_WIDTH-(strlen($2)+strlen($4));
107 yyerror("line too wide");
111 memset(fixed, ' ', l);
113 printf("%s%s%s", $2, fixed, $4);
118 memset(fixed, ' ', l);
120 printf("%s%s\n", fixed, $6);
132 $$ = malloc(strlen($1)+strlen($2)+1);
133 sprintf($$,"%s%s", $1, $2);
143 $$ = malloc(strlen($1)+2);
144 sprintf($$,"%s%s", $1, yytext);
155 if (($$ = get_label(yytext)) == NULL) {
156 set_label(yytext, last_label);
161 $$ = new_counter(yytext);
167 typedef struct node_s {
168 struct node_s *left, *right;
173 node_t label_root = NULL;
174 node_t counter_root = NULL;
176 static const char *find_key(node_t root, const char *key)
179 int cmp = strcmp(key, root->key);
192 static node_t set_key(node_t root, const char *key, const char *value)
195 int cmp = strcmp(key, root->key);
197 root->right = set_key(root->right, key, value);
199 root->left = set_key(root->left, key, value);
202 root->value = strdup(value);
205 root = malloc(sizeof(struct node_s));
206 root->right = root->left = NULL;
207 root->key = strdup(key);
208 root->value = strdup(value);
213 void yyerror(const char *x)
215 fprintf(stderr, "line %d: %s\n", line, x);
218 char *get_label(const char *label)
220 const char *found = find_key(label_root, label);
223 return strdup(found);
228 void set_label(const char *label, const char *target)
230 if (target == NULL) {
231 yyerror("no hanging value for label");
232 target = "<??" ">"; /* avoid trigraph warning */
234 label_root = set_key(label_root, label, target);
237 char *new_counter(const char *key)
239 int i=0, j, ndollars = 0;
243 if (key[i++] != '#') {
244 yyerror("bad index");
245 return strdup("<???" ">"); /* avoid trigraph warning */
248 while (key[i] == '$') {
254 old = find_key(counter_root, key);
255 new = malloc(20*ndollars);
258 for (j=0; ndollars > 1 && old[j]; ) {
259 if (old[j++] == '.' && --ndollars <= 0) {
264 strncpy(new, old, j);
274 while (--ndollars > 0) {
281 sprintf(new+j, "%d", ++i);
283 counter_root = set_key(counter_root, key, new);
288 last_label = strdup(new);