+/* This replaces the old approach, with its direct access to stdio
+ * internals. It uses one fread() to load a buffer that we manage.
+ *
+ * MSG_INPUT_SIZE is the size of the buffer.
+ * MAX_DELIMITER_SIZE is the maximum size of the delimiter used to
+ * separate messages in a maildrop, such as mbox "From ".
+ *
+ * Some of the tests in the test suite assume a MSG_INPUT_SIZE
+ * of 8192.
+ */
+#define MSG_INPUT_SIZE NMH_BUFSIZ
+#define MAX_DELIMITER_SIZE 5
+
+struct m_getfld_state {
+ char msg_buf[2 * MSG_INPUT_SIZE + MAX_DELIMITER_SIZE];
+ char *readpos;
+ 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(). 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
+ internally by m_getfld() (read_more(), actually). */
+ off_t bytes_read;
+ off_t total_bytes_read; /* by caller, not necessarily from input file */
+ off_t last_caller_pos;
+ off_t last_internal_pos;
+ FILE *iob;
+
+ char **pat_map;
+ int msg_style;
+ /*
+ * 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
+ * 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
+ * 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.
+ */
+ char *msg_delim;
+ char *fdelim;
+ char *delimend;
+ int fdelimlen;
+ char *edelim;
+ int edelimlen;
+ int state;
+ int track_filepos;
+};
+
+static
+void
+m_getfld_state_init (m_getfld_state_t *gstate, FILE *iob) {
+ m_getfld_state_t s;
+
+ 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->iob = iob;
+ s->pat_map = NULL;
+ s->msg_style = MS_DEFAULT;
+ s->msg_delim = "";
+ s->fdelim = s->delimend = s->edelim = NULL;
+ s->fdelimlen = s->edelimlen = 0;
+ s->state = FLD;
+ s->track_filepos = 0;
+}
+
+/* scan() needs to force a state an initial state of FLD for each message. */
+void
+m_getfld_state_reset (m_getfld_state_t *gstate) {
+ if (*gstate) {
+ (*gstate)->state = FLD;
+ }
+}
+
+/* If the caller interleaves ftell*()/fseek*() calls with m_getfld()
+ calls, m_getfld() must keep track of the file position. The caller
+ must use this function to inform m_getfld(). */
+void
+m_getfld_track_filepos (m_getfld_state_t *gstate, FILE *iob) {
+ if (! *gstate) {
+ m_getfld_state_init (gstate, iob);
+ }
+
+ (*gstate)->track_filepos = 1;
+}