/* * Copyright 1988 by Rayan S. Zachariassen, all rights reserved. * This will be free software, but only when it is finished. */ /* * Token manipulation functions. */ #include "hostenv.h" #include "mailer.h" #include "../libsh/io.h" #include #include "libz.h" token822 * makeToken(s, n) const char *s; register u_int n; { register token822 *t; t = (token822 *)tmalloc(sizeof (token822)); t->t_pname = strnsave(s, n); t->t_len = 0; t->t_type = Empty; t->t_next = 0; return t; } token822 * copyToken(t) register token822 *t; { register token822 *ct; int tlen; if (stickymem != MEM_TEMP) { tlen = TOKENLEN(t); } else { tlen = t->t_len; } if (tlen > 50000) { /* Eh ?! Got 50k chars of (header) token ? Umm... (indeed we have seen such monster; a 205 kB of SINGLE "To:" header with 8700+ addresses on it.) */ tlen = 50000; /* We use AT MOST 50k from start! */ } ct = (token822 *)tmalloc(sizeof (token822)); if (stickymem != MEM_TEMP) ct->t_pname = strnsave((const char *)t->t_pname, tlen); else ct->t_pname = t->t_pname; ct->t_len = tlen; ct->t_type = t->t_type; ct->t_next = t->t_next; return ct; } const char * formatToken(t) register token822 *t; { const char *name; int len; static char buf[2560]; switch (t->t_type) { case String: name = "string"; break; case Atom: name = "atom"; break; case Special: name = "special"; break; case DomainLiteral: name = "domainLiteral"; break; case Line: name = "line"; break; case Space: name = "space"; break; case Fold: name = "fold"; break; case Word: name = "word"; break; case Comment: name = "comment"; break; case Empty: name = "empty"; break; case Error: name = "error"; break; default: name = "unknown"; break; } buf[0] = '\''; len = TOKENLEN(t); if ((len + 4 + strlen(name)) >= sizeof(buf)) len = sizeof(buf) - strlen(name) - 4; memcpy(buf+1, (char *)(t->t_pname), len); sprintf(buf + len + 1, "' (%s)", name); return buf; } const char * formatAddr(d) AddrComponent d; { switch (d) { case aPhrase: return "aPhrase"; case aComment: return "aComment"; case aSpecial: return "aSpecial"; case aGroup: return "aGroup"; case anAddress: return "anAddress"; case aDomain: return "aDomain"; case aWord: return "aWord"; case anError: return "anError"; case reSync: return "reSync"; /*case aSpace: return "aSpace";*/ } return "unknown"; } int printToken(buf, eob, t, tend, quotespecials) char *buf, *eob; register token822 *t, *tend; int quotespecials; { register char *cp; register const char *s; register int len; --eob; /* make space for terminating NUL */ for (cp = buf; t != NULL && t != tend && cp < eob; t = t->t_next) { if (t->t_type == DomainLiteral) *cp++ = '['; else if (t->t_type == String) *cp++ = '"'; else if (quotespecials && t->t_type == Special) *cp++ = '\\'; for (s = t->t_pname, len = TOKENLEN(t); len > 0; --len) *cp++ = *s++; if (t->t_type == DomainLiteral) *cp++ = ']'; else if (t->t_type == String) *cp++ = '"'; } *cp = '\0'; return cp - buf; } int printdToken(bufp, buflenp, t, tend, quotespecials) char **bufp; register token822 *t, *tend; int quotespecials, *buflenp; { register char *cp, *buf = *bufp; register const char *s; register int len, buflen = *buflenp; for (cp = buf; t != NULL && t != tend; t = t->t_next) { /* If it won't fit in, extent the space */ while (((cp - buf) + 3 + TOKENLEN(t)) > buflen) { /* Must extend */ buflen <<= 1; /* Multiply by two ! */ len = (cp - buf); buf = erealloc(buf,buflen); cp = buf+len; } if (t->t_type == DomainLiteral) *cp++ = '['; else if (t->t_type == String) *cp++ = '"'; else if (quotespecials && t->t_type == Special) *cp++ = '\\'; for (s = t->t_pname, len = TOKENLEN(t); len > 0; --len) *cp++ = *s++; if (t->t_type == DomainLiteral) *cp++ = ']'; else if (t->t_type == String) *cp++ = '"'; } *cp = '\0'; *bufp = buf; *buflenp = buflen; return cp - buf; } /* return output cursor column if 'fp' is non-null, * else return the number of output chars. */ int fprintToken(fp, t, onlylength) FILE *fp; token822 *t; int onlylength; { int len, col = onlylength; len = TOKENLEN(t); if (t->t_type == DomainLiteral) { if (fp) putc('[', fp); else ++onlylength; ++col; } else if (t->t_type == String) { if (fp) putc('"', fp); else ++onlylength; ++col; } else if (t->t_type == Error) { if (fp) putc('?', fp); else ++onlylength; ++col; } if (fp) { const char *s = (const char *)t->t_pname; int i; fwrite(s, sizeof (char), len, fp); for (i = 0; i < len; ++i) { if (s[i] == '\t') col += 8 - (col % 8); else if (s[i] == '\n') col = 0; else ++col; } } else { onlylength += len; } if (t->t_type == DomainLiteral) { if (fp) putc(']', fp); else ++onlylength; ++col; } else if (t->t_type == String) { if (fp) putc('"', fp); else ++onlylength; ++col; } else if (t->t_type == Error) { if (fp) putc('?', fp); else ++onlylength; ++col; } return (fp ? col : onlylength); } #define LINELEN 80 /* return output cursor column if 'fp' is non-null, * else return the number of output chars. */ int fprintFold(fp, t, col, foldcol) FILE *fp; token822 *t; int col, foldcol; { int len; const char *cp, *ncp; len = TOKENLEN(t); if (fp) { if (t->t_type == DomainLiteral) putc('[', fp); else if (t->t_type == String) putc('"', fp); else if (t->t_type == Error) putc('?', fp); } ++col; cp = t->t_pname; do { /* find a breakpoint */ if (col < LINELEN && len > (LINELEN-col)) { /* there is a breakpoint */ for (ncp = cp + (LINELEN-col); ncp > cp; --ncp) { if (isascii((*ncp)&0xFF) && (isspace((*ncp)&0xFF) || *ncp == ',')) break; } if (ncp == cp) { for (ncp = cp + (LINELEN-col); ncp < cp + len; ++ncp) if (isascii((*ncp)&0xFF) && (isspace((*ncp)&0xFF) || *ncp == ',')) break; } /* found breakpoint */ } else ncp = cp + len; while (cp < ncp && len > 0) { int c = (*cp) & 0xFF; if (isascii(c) && isspace(c)) { ++col, putc(' ', fp); while (cp < ncp && len > 0) { c = (*cp) & 0xFF; if (!(isascii(c) && isspace(c))) break; --len; ++cp; } } else { ++col; putc(*cp, fp); --len; ++cp; } } if (len > 0) { /* gobble LWSP at beginning of line */ while (len > 0 && isascii((*cp)&0xFF) && isspace((*cp)&0xFF)) --len, ++cp; putc('\n', fp); for (col = 0; col + 8 <= foldcol; col += 8) putc('\t', fp); for (;col < foldcol; ++col) putc(' ', fp); if (col < 1) putc(' ', fp), ++col; } } while (len > 0); if (fp) { if (t->t_type == DomainLiteral) putc(']', fp); else if (t->t_type == String) putc('"', fp); else if (t->t_type == Error) putc('?', fp); } ++col; return col; } void freeTokens(t, memtype) token822 *t; int memtype; { token822 *nt; if (memtype != MEM_MALLOC) return; while (t != NULL) { if (t->t_len > 600000) abort(); /* The copyToken() builds at most 50k sized tokens, this is 600k, and thus it MUST be failure! */ nt = t->t_next; free((char *)t->t_pname); free((char *)t); t = nt; } }