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