8 #define INDENT_STRING " "
13 char *last_label=NULL;
15 extern void yyerror(const char *x);
16 extern char *get_label(const char *label);
17 extern void set_label(const char *label, const char *target);
18 char *new_counter(const char *key);
29 %token NEW_COUNTER LABEL HASH CHAR NEWLINE NO_INDENT RIGHT
30 %type <string> stuff text
42 if (strlen($2) > (PAPER_WIDTH-(indent ? strlen(INDENT_STRING):0))) {
43 yyerror("line too long");
45 printf("%s%s\n", indent ? INDENT_STRING:"", $2);
50 | doc stuff RIGHT stuff NEWLINE {
51 char fixed[PAPER_WIDTH+1];
54 len = PAPER_WIDTH-(strlen($2)+strlen($4));
57 memset(fixed, ' ', len);
60 yyerror("line too wide");
63 printf("%s%s%s\n", $2, fixed, $4);
69 | doc stuff RIGHT stuff RIGHT stuff NEWLINE {
70 char fixed[PAPER_WIDTH+1];
73 len = PAPER_WIDTH-(strlen($2)+strlen($4));
77 yyerror("line too wide");
81 memset(fixed, ' ', l);
83 printf("%s%s%s", $2, fixed, $4);
88 memset(fixed, ' ', l);
90 printf("%s%s\n", fixed, $6);
96 | doc stuff RIGHT stuff RIGHT stuff NEWLINE {
97 char fixed[PAPER_WIDTH+1];
100 len = PAPER_WIDTH-(strlen($2)+strlen($4));
104 yyerror("line too wide");
108 memset(fixed, ' ', l);
110 printf("%s%s%s", $2, fixed, $4);
115 memset(fixed, ' ', l);
117 printf("%s%s\n", fixed, $6);
129 $$ = malloc(strlen($1)+strlen($2)+1);
130 sprintf($$,"%s%s", $1, $2);
140 $$ = malloc(strlen($1)+2);
141 sprintf($$,"%s%s", $1, yytext);
152 if (($$ = get_label(yytext)) == NULL) {
153 set_label(yytext, last_label);
158 $$ = new_counter(yytext);
164 typedef struct node_s {
165 struct node_s *left, *right;
170 node_t label_root = NULL;
171 node_t counter_root = NULL;
173 const char *find_key(node_t root, const char *key)
176 int cmp = strcmp(key, root->key);
189 node_t set_key(node_t root, const char *key, const char *value)
192 int cmp = strcmp(key, root->key);
194 root->right = set_key(root->right, key, value);
196 root->left = set_key(root->left, key, value);
199 root->value = strdup(value);
202 root = malloc(sizeof(struct node_s));
203 root->right = root->left = NULL;
204 root->key = strdup(key);
205 root->value = strdup(value);
210 void yyerror(const char *x)
212 fprintf(stderr, "line %d: %s\n", line, x);
215 char *get_label(const char *label)
217 const char *found = find_key(label_root, label);
220 return strdup(found);
225 void set_label(const char *label, const char *target)
227 if (target == NULL) {
228 yyerror("no hanging value for label");
231 label_root = set_key(label_root, label, target);
234 char *new_counter(const char *key)
236 int i=0, j, ndollars = 0;
240 if (key[i++] != '#') {
241 yyerror("bad index");
242 return strdup("<???>");
245 while (key[i] == '$') {
251 old = find_key(counter_root, key);
252 new = malloc(20*ndollars);
255 for (j=0; ndollars > 1 && old[j]; ) {
256 if (old[j++] == '.' && --ndollars <= 0) {
261 strncpy(new, old, j);
271 while (--ndollars > 0) {
278 sprintf(new+j, "%d", ++i);
280 counter_root = set_key(counter_root, key, new);
285 last_label = strdup(new);