1 %{
2
3 #include "defs.h"
4
5 #include <glib.h>
6 #include <ctype.h>
7
8 #include "procmsg.h"
9 #include "procmime.h"
10 #include "utils.h"
11
12 #include "quote_fmt.h"
13 #include "quote_fmt_lex.h"
14
15 /* decl */
16 /*
17 flex quote_fmt.l
18 bison -p quote_fmt quote_fmt.y
19 */
20
21 int yylex(void);
22
23 static MsgInfo *msginfo = NULL;
24 static gboolean *visible = NULL;
25 static gint maxsize = 0;
26 static gint stacksize = 0;
27
28 static gchar *buffer = NULL;
29 static gint bufmax = 0;
30 static gint bufsize = 0;
31 static const gchar *quote_str = NULL;
32 static const gchar *body = NULL;
33 static gint error = 0;
34
add_visibility(gboolean val)35 static void add_visibility(gboolean val)
36 {
37 stacksize++;
38 if (maxsize < stacksize) {
39 maxsize += 128;
40 visible = g_realloc(visible, maxsize * sizeof(gboolean));
41 if (visible == NULL)
42 maxsize = 0;
43 }
44
45 visible[stacksize - 1] = val;
46 }
47
remove_visibility(void)48 static void remove_visibility(void)
49 {
50 stacksize--;
51 }
52
add_buffer(const gchar * s)53 static void add_buffer(const gchar *s)
54 {
55 gint len;
56
57 len = strlen(s);
58 if (bufsize + len + 1 > bufmax) {
59 if (bufmax == 0)
60 bufmax = 128;
61 while (bufsize + len + 1 > bufmax)
62 bufmax *= 2;
63 buffer = g_realloc(buffer, bufmax);
64 }
65 strcpy(buffer + bufsize, s);
66 bufsize += len;
67 }
68
69 #if 0
70 static void flush_buffer(void)
71 {
72 if (buffer != NULL)
73 *buffer = '\0';
74 bufsize = 0;
75 }
76 #endif
77
quote_fmt_get_buffer(void)78 gchar *quote_fmt_get_buffer(void)
79 {
80 if (error != 0)
81 return NULL;
82 else
83 return buffer;
84 }
85
86 #define INSERT(buf) \
87 if (stacksize != 0 && visible[stacksize - 1]) \
88 add_buffer(buf)
89
90 #define INSERT_CHARACTER(chr) \
91 if (stacksize != 0 && visible[stacksize - 1]) { \
92 gchar tmp[2]; \
93 tmp[0] = (chr); \
94 tmp[1] = '\0'; \
95 add_buffer(tmp); \
96 }
97
quote_fmt_init(MsgInfo * info,const gchar * my_quote_str,const gchar * my_body)98 void quote_fmt_init(MsgInfo *info, const gchar *my_quote_str,
99 const gchar *my_body)
100 {
101 quote_str = my_quote_str;
102 body = my_body;
103 msginfo = info;
104 stacksize = 0;
105 add_visibility(TRUE);
106 if (buffer != NULL)
107 *buffer = 0;
108 bufsize = 0;
109 error = 0;
110 }
111
quote_fmterror(char * str)112 void quote_fmterror(char *str)
113 {
114 g_warning("Error: %s\n", str);
115 error = 1;
116 }
117
quote_fmtwrap(void)118 int quote_fmtwrap(void)
119 {
120 return 1;
121 }
122
isseparator(int ch)123 static int isseparator(int ch)
124 {
125 return g_ascii_isspace(ch) || ch == '.' || ch == '-';
126 }
127 %}
128
129 %union {
130 char chr;
131 }
132
133 %token SHOW_NEWSGROUPS
134 %token SHOW_DATE SHOW_FROM SHOW_FULLNAME SHOW_FIRST_NAME
135 %token SHOW_SENDER_INITIAL SHOW_SUBJECT SHOW_TO SHOW_MESSAGEID
136 %token SHOW_PERCENT SHOW_CC SHOW_REFERENCES SHOW_MESSAGE
137 %token SHOW_QUOTED_MESSAGE SHOW_BACKSLASH SHOW_TAB
138 %token SHOW_QUOTED_MESSAGE_NO_SIGNATURE SHOW_MESSAGE_NO_SIGNATURE
139 %token SHOW_EOL SHOW_QUESTION_MARK SHOW_OPARENT SHOW_CPARENT
140 %token QUERY_DATE QUERY_FROM
141 %token QUERY_FULLNAME QUERY_SUBJECT QUERY_TO QUERY_NEWSGROUPS
142 %token QUERY_MESSAGEID QUERY_CC QUERY_REFERENCES
143 %token OPARENT CPARENT
144 %token CHARACTER
145
146 %start quote_fmt
147
148 %token <chr> CHARACTER
149 %type <chr> character
150
151 %%
152
153 quote_fmt:
154 character_or_special_or_query_list;
155
156 character_or_special_or_query_list:
157 character_or_special_or_query character_or_special_or_query_list
158 | character_or_special_or_query ;
159
160 character_or_special_or_query:
161 special
162 | character
163 {
164 INSERT_CHARACTER($1);
165 }
166 | query ;
167
168
169 character:
170 CHARACTER
171 ;
172
173 special:
174 SHOW_NEWSGROUPS
175 {
176 if (msginfo->newsgroups)
177 INSERT(msginfo->newsgroups);
178 }
179 | SHOW_DATE
180 {
181 if (msginfo->date) {
182 INSERT(msginfo->date);
183 } else if (msginfo->size == 0) {
184 gchar buf[64];
185
186 get_rfc822_date(buf, sizeof(buf));
187 INSERT(buf);
188 }
189 }
190 | SHOW_FROM
191 {
192 if (msginfo->from)
193 INSERT(msginfo->from);
194 }
195 | SHOW_FULLNAME
196 {
197 if (msginfo->fromname)
198 INSERT(msginfo->fromname);
199 }
200 | SHOW_FIRST_NAME
201 {
202 if (msginfo->fromname) {
203 gchar *p;
204 gchar *str;
205
206 str = alloca(strlen(msginfo->fromname) + 1);
207 if (str != NULL) {
208 strcpy(str, msginfo->fromname);
209 p = str;
210 while (*p && !g_ascii_isspace(*p)) p++;
211 *p = '\0';
212 INSERT(str);
213 }
214 }
215 }
216 | SHOW_SENDER_INITIAL
217 {
218 #define MAX_SENDER_INITIAL 20
219 if (msginfo->fromname) {
220 gchar tmp[MAX_SENDER_INITIAL];
221 gchar *p;
222 gchar *cur;
223 gint len = 0;
224
225 p = msginfo->fromname;
226 cur = tmp;
227 while (*p) {
228 if (*p && g_ascii_isalnum(*p)) {
229 *cur = g_ascii_toupper(*p);
230 cur++;
231 len++;
232 if (len >= MAX_SENDER_INITIAL - 1)
233 break;
234 } else
235 break;
236 while (*p && !isseparator(*p)) p++;
237 while (*p && isseparator(*p)) p++;
238 }
239 *cur = '\0';
240 INSERT(tmp);
241 }
242 }
243 | SHOW_SUBJECT
244 {
245 if (msginfo->subject)
246 INSERT(msginfo->subject);
247 }
248 | SHOW_TO
249 {
250 if (msginfo->to)
251 INSERT(msginfo->to);
252 }
253 | SHOW_MESSAGEID
254 {
255 if (msginfo->msgid)
256 INSERT(msginfo->msgid);
257 }
258 | SHOW_PERCENT
259 {
260 INSERT("%");
261 }
262 | SHOW_CC
263 {
264 if (msginfo->cc)
265 INSERT(msginfo->cc);
266 }
267 | SHOW_REFERENCES
268 {
269 /* if (msginfo->references)
270 INSERT(msginfo->references); */
271 }
272 | SHOW_MESSAGE
273 {
274 gchar buf[BUFFSIZE];
275 FILE *fp = NULL;
276
277 if (body)
278 fp = str_open_as_stream(body);
279 else if (msginfo->size > 0) {
280 fp = procmime_get_first_text_content(msginfo, NULL);
281 if (fp == NULL)
282 g_warning("quote_fmt_parse.y: Can't get text part\n");
283 }
284
285 if (fp) {
286 while (fgets(buf, sizeof(buf), fp) != NULL) {
287 strcrchomp(buf);
288 INSERT(buf);
289 }
290 fclose(fp);
291 }
292 }
293 | SHOW_QUOTED_MESSAGE
294 {
295 gchar buf[BUFFSIZE];
296 FILE *fp = NULL;
297
298 if (body)
299 fp = str_open_as_stream(body);
300 else if (msginfo->size > 0) {
301 fp = procmime_get_first_text_content(msginfo, NULL);
302 if (fp == NULL)
303 g_warning("quote_fmt_parse.y: Can't get text part\n");
304 }
305
306 if (fp) {
307 while (fgets(buf, sizeof(buf), fp) != NULL) {
308 strcrchomp(buf);
309 if (quote_str)
310 INSERT(quote_str);
311 INSERT(buf);
312 }
313 fclose(fp);
314 }
315 }
316 | SHOW_MESSAGE_NO_SIGNATURE
317 {
318 gchar buf[BUFFSIZE];
319 FILE *fp = NULL;
320
321 if (body)
322 fp = str_open_as_stream(body);
323 else if (msginfo->size > 0) {
324 fp = procmime_get_first_text_content(msginfo, NULL);
325 if (fp == NULL)
326 g_warning("quote_fmt_parse.y: Can't get text part\n");
327 }
328
329 if (fp) {
330 while (fgets(buf, sizeof(buf), fp) != NULL) {
331 strcrchomp(buf);
332 if (strncmp(buf, "-- \n", 4) == 0)
333 break;
334 INSERT(buf);
335 }
336 fclose(fp);
337 }
338 }
339 | SHOW_QUOTED_MESSAGE_NO_SIGNATURE
340 {
341 gchar buf[BUFFSIZE];
342 FILE *fp = NULL;
343
344 if (body)
345 fp = str_open_as_stream(body);
346 else if (msginfo->size > 0) {
347 fp = procmime_get_first_text_content(msginfo, NULL);
348 if (fp == NULL)
349 g_warning("Can't get text part\n");
350 }
351
352 if (fp) {
353 while (fgets(buf, sizeof(buf), fp) != NULL) {
354 strcrchomp(buf);
355 if (strncmp(buf, "-- \n", 4) == 0)
356 break;
357 if (quote_str)
358 INSERT(quote_str);
359 INSERT(buf);
360 }
361 fclose(fp);
362 }
363 }
364 | SHOW_BACKSLASH
365 {
366 INSERT("\\");
367 }
368 | SHOW_TAB
369 {
370 INSERT("\t");
371 }
372 | SHOW_EOL
373 {
374 INSERT("\n");
375 }
376 | SHOW_QUESTION_MARK
377 {
378 INSERT("?");
379 }
380 | SHOW_OPARENT
381 {
382 INSERT("{");
383 }
384 | SHOW_CPARENT
385 {
386 INSERT("}");
387 };
388
389 query:
390 QUERY_DATE
391 {
392 add_visibility(msginfo->date != NULL);
393 }
394 OPARENT quote_fmt CPARENT
395 {
396 remove_visibility();
397 }
398 | QUERY_FROM
399 {
400 add_visibility(msginfo->from != NULL);
401 }
402 OPARENT quote_fmt CPARENT
403 {
404 remove_visibility();
405 }
406 | QUERY_FULLNAME
407 {
408 add_visibility(msginfo->fromname != NULL);
409 }
410 OPARENT quote_fmt CPARENT
411 {
412 remove_visibility();
413 }
414 | QUERY_SUBJECT
415 {
416 add_visibility(msginfo->subject != NULL);
417 }
418 OPARENT quote_fmt CPARENT
419 {
420 remove_visibility();
421 }
422 | QUERY_TO
423 {
424 add_visibility(msginfo->to != NULL);
425 }
426 OPARENT quote_fmt CPARENT
427 {
428 remove_visibility();
429 }
430 | QUERY_NEWSGROUPS
431 {
432 add_visibility(msginfo->newsgroups != NULL);
433 }
434 OPARENT quote_fmt CPARENT
435 {
436 remove_visibility();
437 }
438 | QUERY_MESSAGEID
439 {
440 add_visibility(msginfo->msgid != NULL);
441 }
442 OPARENT quote_fmt CPARENT
443 {
444 remove_visibility();
445 }
446 | QUERY_CC
447 {
448 add_visibility(msginfo->cc != NULL);
449 }
450 OPARENT quote_fmt CPARENT
451 {
452 remove_visibility();
453 }
454 | QUERY_REFERENCES
455 {
456 /* add_visibility(msginfo->references != NULL); */
457 }
458 OPARENT quote_fmt CPARENT
459 {
460 remove_visibility();
461 };
462