5 #include "gen_allocdefs.h"
7 static struct token822 comma
= { TOKEN822_COMMA
};
9 void token822_reverse(ta
)
17 for (i
= 0;i
+ i
< n
;++i
)
20 ta
->t
[i
] = ta
->t
[n
- i
];
25 GEN_ALLOC_ready(token822_alloc
,struct token822
,t
,len
,a
,i
,n
,x
,30,token822_ready
)
26 GEN_ALLOC_readyplus(token822_alloc
,struct token822
,t
,len
,a
,i
,n
,x
,30,token822_readyplus
)
27 GEN_ALLOC_append(token822_alloc
,struct token822
,t
,len
,a
,i
,n
,x
,30,token822_readyplus
,token822_append
)
29 static int needspace(t1
,t2
)
34 if (t1
== TOKEN822_COLON
) return 1;
35 if (t1
== TOKEN822_COMMA
) return 1;
36 if (t2
== TOKEN822_LEFT
) return 1;
39 case TOKEN822_ATOM
: case TOKEN822_LITERAL
:
40 case TOKEN822_QUOTE
: case TOKEN822_COMMENT
:
43 case TOKEN822_ATOM
: case TOKEN822_LITERAL
:
44 case TOKEN822_QUOTE
: case TOKEN822_COMMENT
:
56 case ' ': case '\t': case '\r': case '\n':
57 case '(': case '[': case '"':
58 case '<': case '>': case ';': case ':':
59 case '@': case ',': case '.':
65 static void atomcheck(t
)
70 for (i
= 0;i
< t
->slen
;++i
)
73 if ((ch
< 32) || (ch
> 126) || (ch
== ')') || (ch
== ']') || (ch
== '\\'))
75 t
->type
= TOKEN822_QUOTE
;
81 int token822_unparse(sa
,ta
,linelen
)
99 for (i
= 0;i
< ta
->len
;++i
)
103 if (needspace(lasttype
,newtype
))
110 case TOKEN822_AT
: case TOKEN822_DOT
: case TOKEN822_LEFT
: case TOKEN822_RIGHT
:
111 case TOKEN822_SEMI
: case TOKEN822_COLON
:
113 case TOKEN822_ATOM
: case TOKEN822_QUOTE
: case TOKEN822_LITERAL
: case TOKEN822_COMMENT
:
114 if (t
->type
!= TOKEN822_ATOM
) len
+= 2;
115 for (j
= 0;j
< t
->slen
;++j
)
118 case '"': case '[': case ']': case '(': case ')':
119 case '\\': case '\r': case '\n': ++len
;
127 if (!stralloc_ready(sa
,len
))
135 for (i
= 0;i
< ta
->len
;++i
)
139 if (needspace(lasttype
,newtype
))
147 s[0] = '\n'; s[1] = ' '; \
148 if (linee && (!linelen || (s - lineb <= linelen))) \
149 { while (linee < s) { linee[0] = linee[2]; ++linee; } linee -= 2; } \
150 else { if (linee) lineb = linee + 1; linee = s; s += 2; }
153 case TOKEN822_AT
: *s
++ = '@'; break;
154 case TOKEN822_DOT
: *s
++ = '.'; break;
155 case TOKEN822_LEFT
: *s
++ = '<'; break;
156 case TOKEN822_RIGHT
: *s
++ = '>'; break;
157 case TOKEN822_SEMI
: *s
++ = ';'; break;
158 case TOKEN822_COLON
: *s
++ = ':'; break;
159 case TOKEN822_ATOM
: case TOKEN822_QUOTE
: case TOKEN822_LITERAL
: case TOKEN822_COMMENT
:
160 if (t
->type
== TOKEN822_QUOTE
) *s
++ = '"';
161 if (t
->type
== TOKEN822_LITERAL
) *s
++ = '[';
162 if (t
->type
== TOKEN822_COMMENT
) *s
++ = '(';
163 for (j
= 0;j
< t
->slen
;++j
)
166 case '"': case '[': case ']': case '(': case ')':
167 case '\\': case '\r': case '\n': *s
++ = '\\';
170 if (t
->type
== TOKEN822_QUOTE
) *s
++ = '"';
171 if (t
->type
== TOKEN822_LITERAL
) *s
++ = ']';
172 if (t
->type
== TOKEN822_COMMENT
) *s
++ = ')';
182 int token822_unquote(sa
,ta
)
193 for (i
= 0;i
< ta
->len
;++i
)
198 case TOKEN822_COMMA
: case TOKEN822_AT
: case TOKEN822_DOT
: case TOKEN822_LEFT
:
199 case TOKEN822_RIGHT
: case TOKEN822_SEMI
: case TOKEN822_COLON
:
201 case TOKEN822_LITERAL
:
203 case TOKEN822_ATOM
: case TOKEN822_QUOTE
:
208 if (!stralloc_ready(sa
,len
))
213 for (i
= 0;i
< ta
->len
;++i
)
218 case TOKEN822_COMMA
: *s
++ = ','; break;
219 case TOKEN822_AT
: *s
++ = '@'; break;
220 case TOKEN822_DOT
: *s
++ = '.'; break;
221 case TOKEN822_LEFT
: *s
++ = '<'; break;
222 case TOKEN822_RIGHT
: *s
++ = '>'; break;
223 case TOKEN822_SEMI
: *s
++ = ';'; break;
224 case TOKEN822_COLON
: *s
++ = ':'; break;
225 case TOKEN822_ATOM
: case TOKEN822_QUOTE
: case TOKEN822_LITERAL
:
226 if (t
->type
== TOKEN822_LITERAL
) *s
++ = '[';
227 for (j
= 0;j
< t
->slen
;++j
)
229 if (t
->type
== TOKEN822_LITERAL
) *s
++ = ']';
231 case TOKEN822_COMMENT
: break;
238 int token822_parse(ta
,sa
,buf
)
255 for (i
= 0;i
< salen
;++i
)
258 case '.': case ',': case '@': case '<': case '>': case ':': case ';':
260 case ' ': case '\t': case '\r': case '\n': break;
261 case ')': case ']': return 0;
262 /* other control chars and non-ASCII chars are also bad, in theory */
267 if (++i
>= salen
) return 0;
270 case '(': ++level
; break;
271 case ')': --level
; break;
272 case '\\': if (++i
>= salen
) return 0;
282 if (++i
>= salen
) return 0;
285 case '"': --level
; break;
286 case '\\': if (++i
>= salen
) return 0;
296 if (++i
>= salen
) return 0;
299 case ']': --level
; break;
300 case '\\': if (++i
>= salen
) return 0;
309 if (sa
->s
[i
] == '\\') if (++i
>= salen
) break;
314 while (atomok(sa
->s
[i
]));
319 if (!token822_ready(ta
,numtoks
))
321 if (!stralloc_ready(buf
,numchars
))
327 for (i
= 0;i
< salen
;++i
)
330 case '.': t
->type
= TOKEN822_DOT
; ++t
; break;
331 case ',': t
->type
= TOKEN822_COMMA
; ++t
; break;
332 case '@': t
->type
= TOKEN822_AT
; ++t
; break;
333 case '<': t
->type
= TOKEN822_LEFT
; ++t
; break;
334 case '>': t
->type
= TOKEN822_RIGHT
; ++t
; break;
335 case ':': t
->type
= TOKEN822_COLON
; ++t
; break;
336 case ';': t
->type
= TOKEN822_SEMI
; ++t
; break;
337 case ' ': case '\t': case '\r': case '\n': break;
339 t
->type
= TOKEN822_COMMENT
; t
->s
= cbuf
; t
->slen
= 0;
343 ++i
; /* assert: < salen */
346 case '(': ++level
; break;
347 case ')': --level
; break;
348 case '\\': ++i
; /* assert: < salen */
349 default: *cbuf
++ = sa
->s
[i
]; ++t
->slen
;
355 t
->type
= TOKEN822_QUOTE
; t
->s
= cbuf
; t
->slen
= 0;
359 ++i
; /* assert: < salen */
362 case '"': --level
; break;
363 case '\\': ++i
; /* assert: < salen */
364 default: *cbuf
++ = sa
->s
[i
]; ++t
->slen
;
370 t
->type
= TOKEN822_LITERAL
; t
->s
= cbuf
; t
->slen
= 0;
374 ++i
; /* assert: < salen */
377 case ']': --level
; break;
378 case '\\': ++i
; /* assert: < salen */
379 default: *cbuf
++ = sa
->s
[i
]; ++t
->slen
;
385 t
->type
= TOKEN822_ATOM
; t
->s
= cbuf
; t
->slen
= 0;
388 if (sa
->s
[i
] == '\\') if (++i
>= salen
) break;
389 *cbuf
++ = sa
->s
[i
]; ++t
->slen
;
393 while (atomok(sa
->s
[i
]));
401 static int gotaddr(taout
,taaddr
,callback
)
402 token822_alloc
*taout
;
403 token822_alloc
*taaddr
;
408 if (callback(taaddr
) != 1)
411 if (!token822_readyplus(taout
,taaddr
->len
))
414 for (i
= 0;i
< taaddr
->len
;++i
)
415 taout
->t
[taout
->len
++] = taaddr
->t
[i
];
421 int token822_addrlist(taout
,taaddr
,ta
,callback
)
422 token822_alloc
*taout
;
423 token822_alloc
*taaddr
;
428 struct token822
*beginning
;
435 if (!token822_readyplus(taout
,1)) return -1;
436 if (!token822_readyplus(taaddr
,1)) return -1;
441 beginning
= ta
->t
+ 2;
442 t
= ta
->t
+ ta
->len
- 1;
444 /* rfc 822 address lists are easy to parse from right to left */
446 #define FLUSH if (taaddr->len) if (!gotaddr(taout,taaddr,callback)) return -1;
447 #define FLUSHCOMMA if (taaddr->len) { \
448 if (!gotaddr(taout,taaddr,callback)) return -1; \
449 if (!token822_append(taout,&comma)) return -1; }
450 #define ADDRLEFT if (!token822_append(taaddr,t--)) return -1;
451 #define OUTLEFT if (!token822_append(taout,t--)) return -1;
453 while (t
>= beginning
)
459 if (ingroup
) return 0;
465 if (!ingroup
) return 0;
467 while ((t
>= beginning
) && (t
->type
!= TOKEN822_COMMA
))
476 while ((t
>= beginning
) && (t
->type
!= TOKEN822_LEFT
))
478 /* important to use address here even if it's empty: <> */
479 if (!gotaddr(taout
,taaddr
,callback
)) return -1;
480 if (t
< beginning
) return 0;
482 while ((t
>= beginning
) && ((t
->type
== TOKEN822_COMMENT
) || (t
->type
== TOKEN822_ATOM
) || (t
->type
== TOKEN822_QUOTE
) || (t
->type
== TOKEN822_AT
) || (t
->type
== TOKEN822_DOT
)))
486 case TOKEN822_ATOM
: case TOKEN822_QUOTE
: case TOKEN822_LITERAL
:
492 case TOKEN822_COMMENT
:
493 /* comment is lexically a space; shouldn't affect wordok */
509 if (!token822_append(taout
,--t
)) return -1;
511 token822_reverse(taout
);