]> granicus.if.org Git - linux-pam/blob - doc/specs/parse_y.y
Fix whitespace issues
[linux-pam] / doc / specs / parse_y.y
1
2 %{
3 #ifdef HAVE_CONFIG_H
4 #  include <config.h>
5 #endif
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10
11 #define MAXLINE  1000
12 #define INDENT_STRING "  "
13 #define PAPER_WIDTH   74
14
15     int indent=0;
16     int line=1;
17     char *last_label=NULL;
18
19     extern int yylex(void);
20     extern char *yytext;
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);
25 %}
26
27 %union {
28     int def;
29     char *string;
30 }
31
32 %token NEW_COUNTER LABEL HASH CHAR NEWLINE NO_INDENT RIGHT
33 %type <string> stuff text
34
35 %start doc
36
37 %%
38
39 doc:
40 | doc NEWLINE {
41     printf("\n");
42     ++line;
43 }
44 | doc stuff NEWLINE {
45     if (strlen($2) > (PAPER_WIDTH-(indent ? strlen(INDENT_STRING):0))) {
46         yyerror("line too long");
47     }
48     printf("%s%s\n", indent ? INDENT_STRING:"", $2);
49     free($2);
50     indent = 1;
51     ++line;
52 }
53 | doc stuff RIGHT stuff NEWLINE {
54     char fixed[PAPER_WIDTH+1];
55     int len;
56
57     len = PAPER_WIDTH-(strlen($2)+strlen($4));
58
59     if (len >= 0) {
60         memset(fixed, ' ', len);
61         fixed[len] = '\0';
62     } else {
63         yyerror("line too wide");
64         fixed[0] = '\0';
65     }
66     printf("%s%s%s\n", $2, fixed, $4);
67     free($2);
68     free($4);
69     indent = 1;
70     ++line;
71 }
72 | doc stuff RIGHT stuff RIGHT stuff NEWLINE {
73     char fixed[PAPER_WIDTH+1];
74     int len, l;
75
76     len = PAPER_WIDTH-(strlen($2)+strlen($4));
77
78     if (len < 0) {
79         len = 0;
80         yyerror("line too wide");
81     }
82
83     l = len/2;
84     memset(fixed, ' ', l);
85     fixed[l] = '\0';
86     printf("%s%s%s", $2, fixed, $4);
87     free($2);
88     free($4);
89
90     l = (len+1)/2;
91     memset(fixed, ' ', l);
92     fixed[l] = '\0';
93     printf("%s%s\n", fixed, $6);
94     free($6);
95
96     indent = 1;
97     ++line;
98 }
99 | doc stuff RIGHT stuff RIGHT stuff NEWLINE {
100     char fixed[PAPER_WIDTH+1];
101     int len, l;
102
103     len = PAPER_WIDTH-(strlen($2)+strlen($4));
104
105     if (len < 0) {
106         len = 0;
107         yyerror("line too wide");
108     }
109
110     l = len/2;
111     memset(fixed, ' ', l);
112     fixed[l] = '\0';
113     printf("%s%s%s", $2, fixed, $4);
114     free($2);
115     free($4);
116
117     l = (len+1)/2;
118     memset(fixed, ' ', l);
119     fixed[l] = '\0';
120     printf("%s%s\n", fixed, $6);
121     free($6);
122
123     indent = 1;
124     ++line;
125 }
126 ;
127
128 stuff: {
129     $$ = strdup("");
130 }
131 | stuff text {
132     $$ = malloc(strlen($1)+strlen($2)+1);
133     sprintf($$,"%s%s", $1, $2);
134     free($1);
135     free($2);
136 }
137 ;
138
139 text: CHAR {
140     $$ = strdup(yytext);
141 }
142 | text CHAR {
143     $$ = malloc(strlen($1)+2);
144     sprintf($$,"%s%s", $1, yytext);
145     free($1);
146 }
147 | NO_INDENT {
148     $$ = strdup("");
149     indent = 0;
150 }
151 | HASH {
152     $$ = strdup("#");
153 }
154 | LABEL {
155     if (($$ = get_label(yytext)) == NULL) {
156         set_label(yytext, last_label);
157         $$ = strdup("");
158     }
159 }
160 | NEW_COUNTER {
161     $$ = new_counter(yytext);
162 }
163 ;
164
165 %%
166
167 typedef struct node_s {
168     struct node_s *left, *right;
169     const char *key;
170     char *value;
171 } *node_t;
172
173 node_t label_root = NULL;
174 node_t counter_root = NULL;
175
176 static const char *find_key(node_t root, const char *key)
177 {
178     while (root) {
179         int cmp = strcmp(key, root->key);
180
181         if (cmp > 0) {
182             root = root->right;
183         } else if (cmp) {
184             root = root->left;
185         } else {
186             return root->value;
187         }
188     }
189     return NULL;
190 }
191
192 static node_t set_key(node_t root, const char *key, const char *value)
193 {
194     if (root) {
195         int cmp = strcmp(key, root->key);
196         if (cmp > 0) {
197             root->right = set_key(root->right, key, value);
198         } else if (cmp) {
199             root->left = set_key(root->left, key, value);
200         } else {
201             free(root->value);
202             root->value = strdup(value);
203         }
204     } else {
205         root = malloc(sizeof(struct node_s));
206         root->right = root->left = NULL;
207         root->key = strdup(key);
208         root->value = strdup(value);
209     }
210     return root;
211 }
212
213 void yyerror(const char *x)
214 {
215     fprintf(stderr, "line %d: %s\n", line, x);
216 }
217
218 char *get_label(const char *label)
219 {
220     const char *found = find_key(label_root, label);
221
222     if (found) {
223         return strdup(found);
224     }
225     return NULL;
226 }
227
228 void set_label(const char *label, const char *target)
229 {
230     if (target == NULL) {
231         yyerror("no hanging value for label");
232         target = "<??" ">";     /* avoid trigraph warning */
233     }
234     label_root = set_key(label_root, label, target);
235 }
236
237 char *new_counter(const char *key)
238 {
239     int i=0, j, ndollars = 0;
240     const char *old;
241     char *new;
242
243     if (key[i++] != '#') {
244         yyerror("bad index");
245         return strdup("<???" ">");      /* avoid trigraph warning */
246     }
247
248     while (key[i] == '$') {
249         ++ndollars;
250         ++i;
251     }
252
253     key += i;
254     old = find_key(counter_root, key);
255     new = malloc(20*ndollars);
256
257     if (old) {
258         for (j=0; ndollars > 1 && old[j]; ) {
259             if (old[j++] == '.' && --ndollars <= 0) {
260                 break;
261             }
262         }
263         if (j) {
264             strncpy(new, old, j);
265         }
266         if (old[j]) {
267             i = atoi(old+j);
268         } else {
269             new[j++] = '.';
270             i = 0;
271         }
272     } else {
273         j=0;
274         while (--ndollars > 0) {
275             new[j++] = '0';
276             new[j++] = '.';
277         }
278         i = 0;
279     }
280     new[j] = '\0';
281     sprintf(new+j, "%d", ++i);
282
283     counter_root = set_key(counter_root, key, new);
284
285     if (last_label) {
286         free(last_label);
287     }
288     last_label = strdup(new);
289
290     return new;
291 }
292
293 int
294 main(void)
295 {
296     return yyparse();
297 }