state to FLD.
void m_unknown(FILE *iob): Determines the message delimiter string
- for the maildrop. Called by inc, scan, and msh when reading from a
+ for the maildrop. Called by inc and scan when reading from a
maildrop file.
- void m_eomsbr (int (*action)(int)): Sets the hook to check for end
- of message in a maildrop. Called only by msh.
-
State variables
===============
m_getfld() retains state internally between calls in the
int edelimlen
char *msg_delim
int msg_style
- int (*eom_action)(int)
Usage
=====
be parsed as well. Unfortunately the speed issue finally caught up with
us since this routine is at the very heart of MH.
- To speed things up considerably, the routine Eom() was made an auxilary
+ To speed things up considerably, the routine Eom() was made an auxiliary
function called by the macro eom(). Unless we are bursting a maildrop,
the eom() macro returns FALSE saying we aren't at the end of the
message.
* static prototypes
*/
struct m_getfld_state;
-static int m_Eom (m_getfld_state_t, int);
+static int m_Eom (m_getfld_state_t);
static char *matchc(int, char *, int, char *);
#define eom(c,s) (s->msg_style != MS_DEFAULT && \
- (((c) == *s->msg_delim && m_Eom(s,c)) || \
- (s->eom_action && (*s->eom_action)(c))))
+ ((c) == *s->msg_delim && m_Eom(s)))
/* This replaces the old approach, with its direct access to stdio
* internals. It uses one fread() to load a buffer that we manage.
* separate messages in a maildrop, such as mbox "From ".
*
* Some of the tests in the test suite assume a MSG_INPUT_SIZE
- * of 4096.
+ * of 8192.
*/
-#define MSG_INPUT_SIZE 4096
+#define MSG_INPUT_SIZE NMH_BUFSIZ
#define MAX_DELIMITER_SIZE 5
struct m_getfld_state {
char *end; /* One past the last character read in. */
/* The following support tracking of the read position in the
input file stream so that callers can interleave m_getfld()
- calls with ftell() and fseek(). ytes_read replaces the old
+ calls with ftell() and fseek(). bytes_read replaces the old
m_getfld() msg_count global. last_caller_pos is stored when
leaving m_getfld()/m_unknown(), then checked on the next entry.
last_internal_pos is used to remember the position used
* The "full" delimiter string for a packed maildrop consists
* of a newline followed by the actual delimiter. E.g., the
* full string for a Unix maildrop would be: "\n\nFrom ".
- * "Fdelim" points to the start of the full string and is used
+ * "fdelim" points to the start of the full string and is used
* in the BODY case of the main routine to search the buffer for
* a possible eom. Msg_delim points to the first character of
- * the actual delim. string (i.e., fdelim+1). Edelim
+ * the actual delim. string (i.e., fdelim+1). edelim
* points to the 2nd character of actual delimiter string. It
* is used in m_Eom because the first character of the string
* has been read and matched before m_Eom is called.
int fdelimlen;
char *edelim;
int edelimlen;
- int (*eom_action)(int);
int state;
int track_filepos;
};
m_getfld_state_init (m_getfld_state_t *gstate, FILE *iob) {
m_getfld_state_t s;
- s = *gstate = (m_getfld_state_t) mh_xmalloc(sizeof (struct m_getfld_state));
+ NEW(s);
+ *gstate = s;
s->readpos = s->end = s->msg_buf;
s->bytes_read = s->total_bytes_read = 0;
s->last_caller_pos = s->last_internal_pos = 0;
s->msg_delim = "";
s->fdelim = s->delimend = s->edelim = NULL;
s->fdelimlen = s->edelimlen = 0;
- s->eom_action = NULL;
s->state = FLD;
s->track_filepos = 0;
}
m_getfld_state_t s = *gstate;
if (s) {
- if (s->fdelim) free (s->fdelim-1);
+ if (s->fdelim) {
+ free (s->fdelim-1);
+ free (s->pat_map);
+ }
free (s);
*gstate = 0;
}
static void
enter_getfld (m_getfld_state_t *gstate, FILE *iob) {
m_getfld_state_t s;
- off_t pos = ftello (iob);
+ off_t pos;
+ off_t pos_movement;
if (! *gstate) {
m_getfld_state_init (gstate, iob);
readpos shift code being currently unused. */
s->iob = iob;
- if (s->track_filepos && (pos != 0 || s->last_internal_pos != 0)) {
- if (s->last_internal_pos == 0) {
- s->total_bytes_read = pos;
- } else {
- off_t pos_movement = pos - s->last_caller_pos; /* Can be < 0. */
-
- if (pos_movement == 0) {
- pos = s->last_internal_pos;
- } else {
- /* The current file stream position differs from the
- last one, so caller must have called ftell/o().
- Or, this is the first call and the file position
- was not at 0. */
-
- if (s->readpos + pos_movement >= s->msg_buf &&
- s->readpos + pos_movement < s->end) {
- /* This is currently unused. It could be used by
- parse_mime() if it was changed to use a global
- m_getfld_state. */
- /* We can shift readpos and remain within the
- bounds of msg_buf. */
- s->readpos += pos_movement;
- s->total_bytes_read += pos_movement;
- pos = s->last_internal_pos;
- } else {
- size_t num_read;
-
- /* This seek skips past an integral number of
- chunks of size MSG_INPUT_SIZE. */
- fseeko (iob, pos/MSG_INPUT_SIZE * MSG_INPUT_SIZE, SEEK_SET);
- num_read = fread (s->msg_buf, 1, MSG_INPUT_SIZE, iob);
- s->readpos = s->msg_buf + pos % MSG_INPUT_SIZE;
- s->end = s->msg_buf + num_read;
- s->total_bytes_read = pos;
- }
- }
+ if (!s->track_filepos)
+ return;
- fseeko (iob, pos, SEEK_SET);
- }
+ pos = ftello(iob);
+ if (pos == 0 && s->last_internal_pos == 0)
+ return;
+
+ if (s->last_internal_pos == 0) {
+ s->total_bytes_read = pos;
+ return;
}
+
+ pos_movement = pos - s->last_caller_pos; /* Can be < 0. */
+ if (pos_movement == 0) {
+ pos = s->last_internal_pos;
+ } else {
+ /* The current file stream position differs from the
+ last one, so caller must have called ftell/o().
+ Or, this is the first call and the file position
+ was not at 0. */
+
+ if (s->readpos + pos_movement >= s->msg_buf &&
+ s->readpos + pos_movement < s->end) {
+ /* This is currently unused. It could be used by
+ parse_mime() if it was changed to use a global
+ m_getfld_state. */
+ /* We can shift readpos and remain within the
+ bounds of msg_buf. */
+ s->readpos += pos_movement;
+ s->total_bytes_read += pos_movement;
+ pos = s->last_internal_pos;
+ } else {
+ size_t num_read;
+
+ /* This seek skips past an integral number of
+ chunks of size MSG_INPUT_SIZE. */
+ fseeko (iob, pos/MSG_INPUT_SIZE * MSG_INPUT_SIZE, SEEK_SET);
+ num_read = fread (s->msg_buf, 1, MSG_INPUT_SIZE, iob);
+ s->readpos = s->msg_buf + pos % MSG_INPUT_SIZE;
+ s->end = s->msg_buf + num_read;
+ s->total_bytes_read = pos;
+ }
+ }
+
+ fseeko (iob, pos, SEEK_SET);
}
static void
but EOF is typically 0xffffffff. */
static int
Getc (m_getfld_state_t s) {
- if (s->end - s->readpos < 1) {
- if (read_more (s) == 0) {
- /* Pretend that we read a character. That's what stdio does. */
- ++s->readpos;
- return EOF;
- }
- }
+ if ((s->end - s->readpos < 1 && read_more (s) == 0) ||
+ s->readpos >= s->end)
+ return EOF;
- ++s->bytes_read;
- return s->readpos < s->end ? (unsigned char) *s->readpos++ : EOF;
+ s->bytes_read++;
+ return (unsigned char)*s->readpos++;
}
static int
Peek (m_getfld_state_t s) {
- if (s->end - s->readpos < 1) {
- if (read_more (s) == 0) {
- /* Pretend that we read a character. That's what stdio does. */
- ++s->readpos;
- return EOF;
- }
+ if (s->end - s->readpos < 1 && read_more (s) == 0) {
+ return EOF;
+ } else {
+ return s->readpos < s->end ? (unsigned char) *s->readpos : EOF;
}
-
- return s->readpos < s->end ? (unsigned char) *s->readpos : EOF;
}
static int
FILE *iob)
{
m_getfld_state_t s;
- register char *cp;
- register int max, n, c;
+ char *cp;
+ int max, n, c;
enter_getfld (gstate, iob);
s = *gstate;
- if ((c = Getc(s)) < 0) {
+ if ((c = Getc(s)) == EOF) {
*bufsz = *buf = 0;
leave_getfld (s);
return s->state = FILEEOF;
}
if (eom (c, s)) {
- if (! s->eom_action) {
- /* flush null messages */
- while ((c = Getc(s)) >= 0 && eom (c, s))
- ;
+ /* flush null messages */
+ while ((c = Getc(s)) != EOF && eom (c, s))
+ ;
- if (c >= 0)
- Ungetc(c, s);
- }
+ if (c != EOF)
+ Ungetc(c, s);
*bufsz = *buf = 0;
leave_getfld (s);
return s->state = FILEEOF;
case FLD:
if (c == '\n' || c == '-') {
/* we hit the header/body separator */
- while (c != '\n' && (c = Getc(s)) >= 0) continue;
-
- if (c < 0 || (c = Getc(s)) < 0 || eom (c, s)) {
- if (! s->eom_action) {
- /* flush null messages */
- while ((c = Getc(s)) >= 0 && eom (c, s))
- ;
- if (c >= 0)
- Ungetc(c, s);
- }
+ while (c != '\n' && (c = Getc(s)) != EOF)
+ ;
+
+ if (c == EOF || (c = Getc(s)) == EOF || eom (c, s)) {
+ /* flush null messages */
+ while ((c = Getc(s)) != EOF && eom (c, s))
+ ;
+ if (c != EOF)
+ Ungetc(c, s);
*bufsz = *buf = 0;
leave_getfld (s);
return s->state = FILEEOF;
n = 0;
for (finished = 0; ! finished; ) {
while (c != '\n' && c != EOF && n++ < max) {
- *cp++ = c = Getc (s);
+ if ((c = Getc (s)) != EOF) { *cp++ = c; }
}
if (c != EOF) c = Peek (s);
if (max < n) {
- /* the dest buffer is full */
+ /* The dest buffer is full. Need to back the read
+ pointer up by one because when m_getfld() is
+ reentered, it will read a character. Then
+ we'll jump right to the FLDPLUS handling code,
+ which will not store that character, but
+ instead move on to the next one. */
+ if (s->readpos > s->msg_buf) {
+ --s->readpos;
+ --s->bytes_read;
+ }
s->state = FLDPLUS;
finished = 1;
} else if (c != ' ' && c != '\t') {
m_unknown(m_getfld_state_t *gstate, FILE *iob)
{
m_getfld_state_t s;
- register int c;
+ int c;
char text[MAX_DELIMITER_SIZE];
char from[] = "From ";
- register char *cp;
- register char *delimstr;
+ char *cp;
+ char *delimstr;
unsigned int i;
enter_getfld (gstate, iob);
s->msg_style = MS_UNKNOWN;
for (i = 0, cp = text; i < sizeof text; ++i, ++cp) {
- if ((*cp = Getc (s)) == EOF) {
+ if ((c = Getc (s)) == EOF) {
+ *cp = '\0';
break;
+ } else {
+ *cp = c;
}
}
if (i == sizeof from-1 && strncmp (text, "From ", sizeof from-1) == 0) {
s->msg_style = MS_MBOX;
delimstr = "\nFrom ";
- while ((c = Getc (s)) != '\n' && c >= 0) continue;
+ while ((c = Getc(s)) != EOF && c != '\n')
+ ;
} else {
/* not a Unix style maildrop */
s->readpos -= s->bytes_read;
* separator) or the last char (since the matchc would have found it
* if it was a real delim).
*/
- s->pat_map = (char **) calloc (256, sizeof(char *));
+ s->pat_map = (char **) mh_xcalloc (256, sizeof(char *));
for (cp = s->fdelim + 1; cp < s->delimend; cp++ )
s->pat_map[(unsigned char)*cp] = cp;
if (s->msg_style == MS_MMDF) {
/* flush extra msg hdrs */
- while ((c = Getc(s)) >= 0 && eom (c, s))
+ while ((c = Getc(s)) != EOF && eom (c, s))
;
- if (c >= 0)
+ if (c != EOF)
Ungetc(c, s);
}
}
-void
-m_eomsbr (m_getfld_state_t s, int (*action)(int))
-{
- if ((s->eom_action = action)) {
- s->msg_style = MS_MSH;
- *s->msg_delim = 0;
- s->fdelimlen = 1;
- s->delimend = s->fdelim;
- } else {
- s->msg_style = MS_MMDF;
- s->msg_delim = s->fdelim + 1;
- s->fdelimlen = strlen (s->fdelim);
- s->delimend = s->msg_delim + s->edelimlen;
- }
-}
-
-
/*
* test for msg delimiter string
*/
static int
-m_Eom (m_getfld_state_t s, int c)
+m_Eom (m_getfld_state_t s)
{
- register int i;
+ int i;
char text[MAX_DELIMITER_SIZE];
char *cp;
for (i = 0, cp = text; i < s->edelimlen; ++i, ++cp) {
- if ((*cp = Getc (s)) == EOF) {
+ int c2;
+
+ if ((c2 = Getc (s)) == EOF) {
+ *cp = '\0';
break;
+ } else {
+ *cp = c2;
}
}
}
if (s->msg_style == MS_MBOX) {
- while ((c = Getc (s)) != '\n')
- if (c < 0)
- break;
+ int c;
+ while ((c = Getc(s)) != EOF && c != '\n')
+ ;
}
return 1;
static char *
matchc(int patln, char *pat, int strln, char *str)
{
- register char *es = str + strln - patln;
- register char *sp;
- register char *pp;
- register char *ep = pat + patln;
- register char pc = *pat++;
+ char *es = str + strln - patln;
+ char *sp;
+ char *pp;
+ char *ep = pat + patln;
+ char pc = *pat++;
for(;;) {
while (pc != *str++)