X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/2c9ef70f084977c3a34a64072adcb2d474aff44a..7559e1ebf:/uip/scansbr.c?ds=sidebyside diff --git a/uip/scansbr.c b/uip/scansbr.c index d1868451..a07889e4 100644 --- a/uip/scansbr.c +++ b/uip/scansbr.c @@ -14,11 +14,6 @@ #include #include -#ifdef _FSTDIO -# define _ptr _p /* Gag */ -# define _cnt _w /* Wretch */ -#endif - #define MAXSCANL 256 /* longest possible scan line */ /* @@ -41,6 +36,7 @@ static struct comp **used_buf = 0; /* stack for comp that use buffers */ static int dat[5]; /* aux. data for format routine */ char *scanl = 0; /* text of most recent scanline */ +m_getfld_state_t gstate; /* for access by msh */ #define DIEWRERR() adios (scnmsg, "write error on") @@ -65,14 +61,14 @@ scan (FILE *inb, int innum, int outnum, char *nfs, int width, int curflg, int unseen, char *folder, long size, int noisy) { int i, compnum, encrypted, state; - unsigned char *cp, *tmpbuf; - char **nxtbuf; + char *cp, *tmpbuf, *startbody, **nxtbuf; char *saved_c_text = NULL; struct comp *cptr; struct comp **savecomp; char *scnmsg = NULL; FILE *scnout = NULL; char name[NAMESZ]; + int bufsz; static int rlwidth, slwidth; static size_t scanl_size; @@ -93,7 +89,7 @@ scan (FILE *inb, int innum, int outnum, char *nfs, int width, int curflg, umask(~m_gmprot()); /* Compile format string */ - ncomps = fmt_compile (nfs, &fmt, 1) + 1; + ncomps = fmt_compile (nfs, &fmt, 1) + 2; bodycomp = fmt_findcomp("body"); datecomp = fmt_findcomp("date"); @@ -158,6 +154,7 @@ scan (FILE *inb, int innum, int outnum, char *nfs, int width, int curflg, nxtbuf = compbuffers; savecomp = used_buf; tmpbuf = *nxtbuf++; + startbody = NULL; dat[0] = innum ? innum : outnum; dat[1] = curflg; dat[4] = unseen; @@ -166,7 +163,9 @@ scan (FILE *inb, int innum, int outnum, char *nfs, int width, int curflg, * Get the first field. If the message is non-empty * and we're doing an "inc", open the output file. */ - if ((state = m_getfld (FLD, name, tmpbuf, rlwidth, inb)) == FILEEOF) { + bufsz = rlwidth; + m_getfld_state_reset (&gstate); + if ((state = m_getfld (&gstate, name, tmpbuf, &bufsz, inb)) == FILEEOF) { if (ferror(inb)) { advise("read", "unable to"); /* "read error" */ return SCNFAT; @@ -188,7 +187,8 @@ scan (FILE *inb, int innum, int outnum, char *nfs, int width, int curflg, } /* scan - main loop */ - for (compnum = 1; ; state = m_getfld (state, name, tmpbuf, rlwidth, inb)) { + for (compnum = 1; ; + bufsz = rlwidth, state = m_getfld (&gstate, name, tmpbuf, &bufsz, inb)) { switch (state) { case FLD: case FLDPLUS: @@ -209,7 +209,7 @@ scan (FILE *inb, int innum, int outnum, char *nfs, int width, int curflg, cptr->c_text = tmpbuf; for (cp = tmpbuf + strlen (tmpbuf) - 1; cp >= tmpbuf; cp--) - if (isspace (*cp)) + if (isspace ((unsigned char) *cp)) *cp = 0; else break; @@ -219,7 +219,8 @@ scan (FILE *inb, int innum, int outnum, char *nfs, int width, int curflg, } while (state == FLDPLUS) { - state = m_getfld (state, name, tmpbuf, rlwidth, inb); + bufsz = rlwidth; + state = m_getfld (&gstate, name, tmpbuf, &bufsz, inb); if (outnum) FPUTS (tmpbuf); } @@ -233,60 +234,55 @@ scan (FILE *inb, int innum, int outnum, char *nfs, int width, int curflg, */ if ((i = strlen(tmpbuf)) < rlwidth) { - state = m_getfld (state, name, tmpbuf + i, - rlwidth - i, inb); + bufsz = rlwidth - i; + state = m_getfld (&gstate, name, tmpbuf + i, &bufsz, inb); } + if (! outnum) { state = FILEEOF; /* stop now if scan cmd */ + if (bodycomp && startbody == NULL) + startbody = tmpbuf; goto finished; } if (putc ('\n', scnout) == EOF) DIEWRERR(); FPUTS (tmpbuf); /* - * performance hack: some people like to run "inc" on - * things like net.sources or large digests. We do a - * copy directly into the output buffer rather than - * going through an intermediate buffer. + * The previous code here used to call m_getfld() using + * pointers to the underlying output stdio buffers to + * avoid the extra copy. Tests by Markus Schnalke show + * no noticable performance loss on larger mailboxes + * if we incur an extra copy, and messing around with + * internal stdio buffers is becoming more and more + * unportable as times go on. So from now on just deal + * with the overhead of an extra copy. * - * We need the amount of data m_getfld found & don't - * want to do a strlen on the long buffer so there's - * a hack in m_getfld to save the amount of data it - * returned in the global "msg_count". + * Subtle change - with the previous code tmpbuf wasn't + * used, so we could reuse it for the {body} component. + * Now since we're using tmpbuf as our read buffer we + * need to save the beginning of the body for later. + * See the above (and below) use of startbody. */ body:; + if (bodycomp && startbody == NULL) { + startbody = tmpbuf; + tmpbuf = *nxtbuf++; + } + while (state == BODY) { -#ifdef LINUX_STDIO - if (scnout->_IO_write_ptr == scnout->_IO_write_end) { -#elif defined(__DragonFly__) - if (((struct __FILE_public *)scnout)->_w <= 0) { -#else - if (scnout->_cnt <= 0) { -#endif - if (fflush(scnout) == EOF) - DIEWRERR (); - } -#ifdef LINUX_STDIO - state = m_getfld(state, name, scnout->_IO_write_ptr, - (long)scnout->_IO_write_ptr-(long)scnout->_IO_write_end , inb); - scnout->_IO_write_ptr += msg_count; -#elif defined(__DragonFly__) - state = m_getfld( state, name, ((struct __FILE_public *)scnout)->_p, -(((struct __FILE_public *)scnout)->_w), inb ); - ((struct __FILE_public *)scnout)->_w -= msg_count; - ((struct __FILE_public *)scnout)->_p += msg_count; -#else - state = m_getfld( state, name, scnout->_ptr, -(scnout->_cnt), inb ); - scnout->_cnt -= msg_count; - scnout->_ptr += msg_count; -#endif + bufsz = rlwidth; + state = m_getfld (&gstate, name, tmpbuf, &bufsz, inb); + FPUTS(tmpbuf); } goto finished; case LENERR: case FMTERR: - fprintf (stderr, - innum ? "??Format error (message %d) in " - : "??Format error in ", - outnum ? outnum : innum); + if (innum) + fprintf (stderr, "??Format error (message %d) in ", + outnum ? outnum : innum); + else + fprintf (stderr, "??Format error in "); + fprintf (stderr, "component %d\n", compnum); if (outnum) { @@ -318,7 +314,7 @@ finished: /* Save and restore buffer so we don't trash our dynamic pool! */ if (bodycomp) { saved_c_text = bodycomp->c_text; - bodycomp->c_text = tmpbuf; + bodycomp->c_text = startbody; } if (size) @@ -350,7 +346,7 @@ finished: } } - fmt_scan (fmt, scanl, scanl_size, slwidth, dat); + fmt_scan (fmt, scanl, scanl_size, slwidth, dat, NULL); if (bodycomp) bodycomp->c_text = saved_c_text; @@ -363,10 +359,8 @@ finished: /* return dynamically allocated buffers to pool */ while ((cptr = *savecomp++)) { - *--nxtbuf = cptr->c_text; cptr->c_text = NULL; } - *--nxtbuf = tmpbuf; if (outnum && (ferror(scnout) || fclose (scnout) == EOF)) DIEWRERR(); @@ -386,3 +380,23 @@ mh_fputs(char *s, FILE *stream) return (0); } +/* The following three functions allow access to the global gstate above. */ +void +scan_finished () { + m_getfld_state_destroy (&gstate); +} + +void +scan_detect_mbox_style (FILE *f) { + m_unknown (&gstate, f); +} + +void +scan_eom_action (int (*action)()) { + m_eomsbr (gstate, action); +} + +void +scan_reset_m_getfld_state () { + m_getfld_state_reset (&gstate); +}