/*
* 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 <ctype.h>
#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;
}
}
syntax highlighted by Code2HTML, v. 0.9.1