140 #define COLLECT(t,s,c,cond) { \
141 while ((c = *(unsigned char *) s) != 0) { \
143 if ((c = *(unsigned char *)++s) == 0) \
145 } else if (!(cond)) { \
148 VSTRING_ADDCH(t->vstr, IS_SPACE_TAB_CR_LF(c) ? ' ' : c); \
151 VSTRING_TERMINATE(t->vstr); \
154 #define COLLECT_SKIP_LAST(t,s,c,cond) { COLLECT(t,s,c,cond); if (*s) s++; }
159 #define SKIP(tp, cond) { \
160 while (tp->type && (cond)) \
164 #define MOVE_COMMENT_AND_CONTINUE(tp, right) { \
165 TOK822 *prev = tok822_unlink(tp); \
166 right = tok822_prepend(right, tp); \
171 #define SKIP_MOVE_COMMENT(tp, cond, right) { \
172 while (tp->type && (cond)) { \
173 if (tp->type == TOK822_COMMENT) \
174 MOVE_COMMENT_AND_CONTINUE(tp, right); \
185 static void tok822_quote_atom(
TOK822 *);
186 static const char *tok822_comment(
TOK822 *,
const char *);
188 static void tok822_copy_quoted(
VSTRING *,
char *,
char *);
189 static int tok822_append_space(
TOK822 *);
191 #define DO_WORD (1<<0)
192 #define DO_GROUP (1<<1)
194 #define ADD_COMMA ','
195 #define NO_MISSING_COMMA 0
206 for (tp = tree; tp; tp = tp->
next) {
233 msg_panic(
"tok822_internalize: unknown operator %d", tp->
type);
236 if (tok822_append_space(tp))
246 static void strip_address(
VSTRING *vp, ssize_t start,
TOK822 *addr)
254 msg_warn(
"stripping too many comments from address: %.100s...",
306 #define MAX_NONADDR_LENGTH 250
308 #define RESET_NONADDR_LENGTH { \
309 start = VSTRING_LEN(vp); \
314 #define ENFORCE_NONADDR_LENGTH do { \
315 if (addr && VSTRING_LEN(vp) - addr_len > start + MAX_NONADDR_LENGTH) \
316 strip_address(vp, start, addr->head); \
325 for (tp = tree; tp; tp = tp->
next) {
328 if (flags & TOK822_STR_TRNC)
332 if (flags & TOK822_STR_TRNC)
379 msg_panic(
"tok822_externalize: unknown operator %d", tp->
type);
382 if (tok822_append_space(tp))
385 if (flags & TOK822_STR_TRNC)
395 static void tok822_copy_quoted(
VSTRING *vp,
char *str,
char *quote_set)
399 while ((ch = *(
unsigned char *) str++) != 0) {
400 if (strchr(quote_set, ch))
408 static int tok822_append_space(
TOK822 *tp)
412 if (tp == 0 || (next = tp->
next) == 0 || tp->
owner != 0)
417 #define NON_OPERATOR(x) \
418 (x->type == TOK822_ATOM || x->type == TOK822_QSTRING \
419 || x->type == TOK822_COMMENT || x->type == TOK822_DOMLIT \
420 || x->type == TOK822_ADDR)
442 while ((ch = *(
unsigned char *) str++) != 0) {
447 str = tok822_comment(tp, str);
448 }
else if (ch ==
'[') {
451 }
else if (ch ==
'"') {
454 }
else if (ch !=
'\\' && strchr(tok822_opchar, ch)) {
460 tok822_quote_atom(tp);
469 if (tok_count_limit > 0 && ++tok_count >= tok_count_limit)
501 #define GLUE(left,rite) { left->next = rite; rite->prev = left; }
504 GLUE(head, first_token);
506 GLUE(last_token, tail);
521 }
else if (tp->
type ==
';') {
524 }
else if (tp->
type ==
':' && (state &
DO_GROUP) != 0) {
530 }
else if (tp->
type ==
'>') {
534 SKIP(tp, tp->
type > 0xff || strchr(
">;,:", tp->
type) == 0);
543 }
else if (tp->
type ==
',') {
557 tp = (head->
next != tail ? head->
next : 0);
567 static void tok822_quote_atom(
TOK822 *tp)
576 for (cp =
vstring_str(tp->
vstr); (ch = *(
unsigned char *) cp) != 0; cp++) {
578 ||
ISCNTRL(ch) || strchr(tok822_opchar, ch)) {
587 static const char *tok822_comment(
TOK822 *tp,
const char *str)
600 while ((ch = *(
unsigned char *) str) != 0) {
605 }
else if (ch ==
')') {
608 }
else if (ch ==
'\\') {
609 if ((ch = *(
unsigned char *) str) == 0)
621 static TOK822 *tok822_group(
int group_type,
TOK822 *left,
TOK822 *right,
int sync_type)
631 if (left != right && (first = left->
next) != right) {
664 static void tok822_print(
TOK822 *list,
int indent)
668 for (tp = list; tp; tp = tp->
next) {
673 tok822_print(tp->
head, indent + 2);
688 int main(
int unused_argc,
char **unused_argv)
694 #define TEST_TOKEN_LIMIT 20
705 tok822_print(list, 0);
#define QUOTE_FLAG_8BITCLEAN
TOK822 * tok822_parse_limit(const char *str, int tok_count_limit)
NORETURN msg_panic(const char *fmt,...)
#define SKIP_MOVE_COMMENT(tp, cond, right)
#define tok822_scan(cp, ptr)
int main(int argc, char **argv)
#define COLLECT_SKIP_LAST(t, s, c, cond)
VSTRING * vstring_truncate(VSTRING *vp, ssize_t len)
TOK822 * tok822_scan_addr(const char *addr)
#define RESET_NONADDR_LENGTH
#define MOVE_COMMENT_AND_CONTINUE(tp, right)
TOK822 * tok822_sub_append(TOK822 *, TOK822 *)
TOK822 * tok822_scan_limit(const char *str, TOK822 **tailp, int tok_count_limit)
TOK822 * tok822_free_tree(TOK822 *)
#define VSTRING_TERMINATE(vp)
VSTRING * quote_822_local_flags(VSTRING *dst, const char *mbox, int flags)
#define IS_SPACE_TAB_CR_LF(ch)
#define VSTRING_ADDCH(vp, ch)
VSTREAM * vstream_printf(const char *fmt,...)
#define VSTRING_RESET(vp)
void msg_warn(const char *fmt,...)
VSTRING * vstring_alloc(ssize_t len)
VSTRING * tok822_internalize(VSTRING *vp, TOK822 *tree, int flags)
VSTRING * tok822_externalize(VSTRING *vp, TOK822 *tree, int flags)
TOK822 * tok822_append(TOK822 *, TOK822 *)
int vstream_fflush(VSTREAM *stream)
TOK822 * tok822_alloc(int, const char *)
TOK822 * tok822_free(TOK822 *)
#define ENFORCE_NONADDR_LENGTH
VSTRING * vstring_free(VSTRING *vp)
#define vstream_fileno(vp)
TOK822 * tok822_cut_before(TOK822 *)
#define COLLECT(t, s, c, cond)
char * printable(char *string, int replacement)
#define QUOTE_FLAG_APPEND
VSTRING * vstring_strcat(VSTRING *vp, const char *src)
#define readlline(bp, fp, lp)