Commit | Line | Data |
---|---|---|
c99f9605 ML |
1 | #include <stdio.h> |
2 | #include <stdlib.h> | |
3 | #include <ctype.h> | |
4 | ||
5 | static void init_state_machine (void); | |
6 | ||
7 | static void process (void); | |
8 | ||
9 | static void check_end_conditions (void); | |
10 | ||
11 | int | |
12 | main (int argc, char *argv[]) | |
13 | { | |
14 | init_state_machine (); | |
15 | process (); | |
16 | check_end_conditions (); | |
17 | ||
18 | return EXIT_SUCCESS; | |
19 | } | |
20 | ||
21 | typedef enum state_t | |
22 | { | |
23 | SKIP, | |
24 | SKIP_COOKIE, | |
25 | ||
a88ff5b6 | 26 | MULTILINE_BEGINNING_OF_LINE, |
c99f9605 ML |
27 | MULTILINE, |
28 | ||
29 | MULTILINE_COOKIE, | |
30 | STRINGS, | |
31 | ||
32 | SINGLELINE, | |
33 | ||
34 | } state_t; | |
35 | ||
36 | state_t state = SKIP; | |
37 | ||
38 | static void die (const char *msg); | |
39 | static void process_strings (void); | |
40 | static void process_single_line (void); | |
41 | ||
42 | void | |
43 | process () | |
44 | { | |
45 | int want_cookie = 0; | |
46 | int ch; | |
47 | ||
48 | while ((ch = getc (stdin)) != EOF) { | |
49 | char c = (char)ch; | |
50 | ||
51 | switch (state) { | |
52 | case SKIP: | |
53 | if (c == '^') { | |
54 | if (want_cookie) { | |
55 | state = SKIP_COOKIE; | |
56 | want_cookie = 0; | |
57 | } else | |
58 | want_cookie = 1; | |
47bcd646 | 59 | } else if (c != ' ') |
c99f9605 ML |
60 | want_cookie = 0; |
61 | break; | |
62 | case SKIP_COOKIE: | |
63 | switch (c) { | |
64 | case '[': | |
65 | fputs ("(doc-check\n", stdout); | |
66 | state = SINGLELINE; | |
67 | break; | |
68 | case '{': | |
69 | fputs ("(doc-block (\n", stdout); | |
70 | state = MULTILINE; | |
71 | break; | |
a88ff5b6 ML |
72 | case ' ': |
73 | break; | |
c99f9605 ML |
74 | default: |
75 | die ("bad snarf cookie"); | |
76 | break; | |
77 | } | |
78 | break; | |
a88ff5b6 ML |
79 | case MULTILINE_BEGINNING_OF_LINE: |
80 | if (c != ' ') { | |
81 | state = MULTILINE; | |
82 | putc (c, stdout); | |
83 | } | |
84 | break; | |
c99f9605 ML |
85 | case MULTILINE: |
86 | if (c == '^') { | |
87 | if (want_cookie) { | |
88 | fputs ("\n)\n(\n", stdout); | |
89 | state = MULTILINE_COOKIE; | |
90 | want_cookie = 0; | |
91 | } else | |
92 | want_cookie = 1; | |
93 | } else { | |
47bcd646 ML |
94 | if (c != ' ') |
95 | want_cookie = 0; | |
c99f9605 ML |
96 | putc (c, stdout); |
97 | } | |
98 | break; | |
99 | case MULTILINE_COOKIE: | |
100 | switch (c) { | |
101 | case '(': | |
102 | state = STRINGS; | |
103 | break; | |
a88ff5b6 ML |
104 | case '%': |
105 | state = MULTILINE_BEGINNING_OF_LINE; | |
c99f9605 ML |
106 | break; |
107 | case '}': | |
108 | fputs ("))\n", stdout); | |
109 | state = SKIP; | |
110 | break; | |
a88ff5b6 ML |
111 | case ' ': |
112 | break; | |
c99f9605 ML |
113 | default: |
114 | die ("bad snarf cookie in multiline context"); | |
115 | break; | |
116 | } | |
117 | break; | |
118 | case STRINGS: | |
119 | process_strings (); | |
120 | state = MULTILINE; | |
121 | break; | |
122 | case SINGLELINE: | |
123 | process_single_line (); | |
124 | fputs ("\n)\n", stdout); | |
125 | state = SKIP; | |
126 | break; | |
127 | default: | |
128 | abort (); | |
129 | break; | |
130 | } | |
131 | } | |
132 | } | |
133 | ||
134 | void | |
135 | init_state_machine () | |
136 | {} | |
137 | ||
138 | void | |
139 | die (const char *msg) | |
140 | { | |
141 | fprintf (stderr, "%s\n", msg); | |
142 | exit (EXIT_FAILURE); | |
143 | } | |
144 | ||
145 | void | |
146 | check_end_conditions () | |
147 | { | |
148 | if (state != SKIP) | |
149 | die ("something is unterminated"); | |
150 | } | |
151 | ||
152 | typedef enum str_state_t | |
153 | { | |
154 | STR_SKIP, | |
155 | STR_INSIDE, | |
156 | STR_HAD_ESCAPE, | |
157 | STR_EXIT | |
158 | } str_state_t; | |
159 | ||
160 | void | |
161 | process_strings () | |
162 | { | |
163 | /* read well-formed strings up to a ')', and break them up in the | |
164 | process if they are too long */ | |
165 | int count = 0; | |
166 | int ch; | |
167 | str_state_t state = STR_SKIP; | |
168 | ||
169 | fputs ("docstring\n", stdout); | |
170 | ||
171 | #define PUTC(c) putc (c, stdout); if (++count >= 512) { fputs ("\"\nstring \"", stdout); count = 0; } | |
172 | ||
173 | while (!(((ch = getc (stdin)) == EOF) | |
174 | || (state == STR_EXIT))) { | |
175 | char c = (char) ch; | |
176 | ||
177 | switch (state) { | |
178 | case STR_SKIP: | |
179 | switch (c) { | |
180 | case '"': | |
181 | fputs ("\nstring ", stdout); | |
182 | count = 0; | |
183 | PUTC (c); | |
184 | state = STR_INSIDE; | |
185 | break; | |
186 | case ')': | |
187 | state = STR_EXIT; | |
188 | break; | |
189 | default: | |
190 | if (!isspace (c)) | |
191 | die ("stray stuff where should be only strings"); | |
192 | break; | |
193 | } | |
194 | break; | |
195 | case STR_INSIDE: | |
196 | switch (c) { | |
197 | case '\\': | |
198 | putc (c, stdout); | |
199 | ++count; | |
200 | state = STR_HAD_ESCAPE; | |
201 | break; | |
202 | case '"': | |
203 | putc (c, stdout); | |
204 | state = STR_SKIP; | |
205 | break; | |
206 | default: | |
207 | PUTC (c); | |
208 | break; | |
209 | } | |
210 | break; | |
211 | case STR_HAD_ESCAPE: | |
212 | PUTC (c); | |
213 | state = STR_INSIDE; | |
214 | break; | |
215 | default: | |
216 | abort (); | |
217 | break; | |
218 | } | |
219 | } | |
220 | ||
221 | if (state != STR_EXIT) | |
222 | die ("docstrings don't terminate"); | |
223 | } | |
224 | ||
225 | void | |
226 | process_single_line () | |
227 | { | |
228 | /* read up to a ']' */ | |
229 | int ch; | |
230 | while (!(((ch = getc (stdin)) == EOF) | |
231 | || ((char) ch == ']'))) { | |
232 | char c = (char) ch; | |
233 | ||
234 | putc (c, stdout); | |
235 | } | |
236 | ||
237 | if ((char) ch != ']') | |
238 | die ("bad checking snarfage"); | |
239 | } | |
240 | ||
241 | ||
242 | /* | |
243 | Local Variables: | |
244 | c-file-style: "gnu" | |
245 | End: | |
246 | */ |