Annotation of 43BSD/contrib/mh/sbr/m_getfld.c, revision 1.1.1.1

1.1       root        1: /* m_getfld.c - read/parse a message */
                      2: 
                      3: #include "../h/mh.h"
                      4: #include <stdio.h>
                      5: #include "../zotnet/mts.h"
                      6: #include <ctype.h>
                      7: 
                      8: 
                      9: /* This module has a long and checkered history.  First, it didn't burst
                     10:    maildrops correctly because it considered two CTRL-A:s in a row to be
                     11:    an inter-message delimiter.  It really is four CTRL-A:s followed by a
                     12:    newline.  Unfortunately, MMDF will convert this delimiter *inside* a
                     13:    message to a CTRL-B followed by three CTRL-A:s and a newline.  This
                     14:    caused the old version of m_getfld() to declare eom prematurely.  The
                     15:    fix was a lot slower than
                     16: 
                     17:                c == '\001' && peekc (iob) == '\001'
                     18: 
                     19:    but it worked, and to increase generality, UUCP style maildrops could
                     20:    be parsed as well.  Unfortunately the speed issue finally caught up with
                     21:    us since this routine is at the very heart of MH.
                     22: 
                     23:    To speed things up considerably, the routine Eom() was made an auxilary
                     24:    function called by the macro eom().  Unless we are bursting a maildrop,
                     25:    the eom() macro returns FALSE saying we aren't at the end of the
                     26:    message.
                     27: 
                     28:    The next thing to do is to read the mtstailor file and initialize
                     29:    delimiter[] and delimlen accordingly...
                     30: 
                     31:    After mhl was made a built-in in msh, m_getfld() worked just fine
                     32:    (using m_unknown() at startup).  Until one day: a message which was
                     33:    the result of a bursting was shown. Then, since the burst boundaries
                     34:    aren't CTRL-A:s, m_getfld() would blinding plunge on past the boundary.
                     35:    Very sad.  The solution: introduce m_eomsbr().  This hook gets called
                     36:    after the end of each line (since testing for eom involves an fseek()).
                     37:    This worked fine, until one day: a message with no body portion arrived.
                     38:    Then the
                     39: 
                     40:                   while (eom (c = Getc (iob), iob))
                     41:                        continue;
                     42: 
                     43:    loop caused m_getfld() to return FMTERR.  So, that logic was changed to
                     44:    check for (*eom_action) and act accordingly.
                     45: 
                     46:    This worked fine, until one day: someone didn't use four CTRL:A's as
                     47:    their delimiters.  So, the bullet got bit and we read mts.h and
                     48:    continue to struggle on.  It's not that bad though, since the only time
                     49:    the code gets executed is when inc (or msh) calls it, and both of these
                     50:    have already called mts_init().
                     51: 
                     52:    ------------------------
                     53:    (Written by Van Jacobson for the mh6 m_getfld, January, 1986):
                     54: 
                     55:    This routine was accounting for 60% of the cpu time used by most mh
                     56:    programs.  I spent a bit of time tuning and it now accounts for <10%
                     57:    of the time used.  Like any heavily tuned routine, it's a bit
                     58:    complex and you want to be sure you understand everything that it's
                     59:    doing before you start hacking on it.  Let me try to emphasize
                     60:    that:  every line in this atrocity depends on every other line,
                     61:    sometimes in subtle ways.  You should understand it all, in detail,
                     62:    before trying to change any part.  If you do change it, test the
                     63:    result thoroughly (I use a hand-constructed test file that exercises
                     64:    all the ways a header name, header body, header continuation,
                     65:    header-body separator, body line and body eom can align themselves
                     66:    with respect to a buffer boundary).  "Minor" bugs in this routine
                     67:    result in garbaged or lost mail.
                     68: 
                     69:    If you hack on this and slow it down, I, my children and my
                     70:    children's children will curse you.
                     71: 
                     72:    This routine gets used on three different types of files: normal,
                     73:    single msg files, "packed" unix or mmdf mailboxs (when used by inc)
                     74:    and packed, directoried bulletin board files (when used by msh).
                     75:    The biggest impact of different file types is in "eom" testing.  The
                     76:    code has been carefully organized to test for eom at appropriate
                     77:    times and at no other times (since the check is quite expensive).
                     78:    I have tried to arrange things so that the eom check need only be
                     79:    done on entry to this routine.  Since an eom can only occur after a
                     80:    newline, this is easy to manage for header fields.  For the msg
                     81:    body, we try to efficiently search the input buffer to see if
                     82:    contains the eom delimiter.  If it does, we take up to the
                     83:    delimiter, otherwise we take everything in the buffer.  (The change
                     84:    to the body eom/copy processing produced the most noticeable
                     85:    performance difference, particularly for "inc" and "show".)
                     86: 
                     87:    There are three qualitatively different things this routine busts
                     88:    out of a message: field names, field text and msg bodies.  Field
                     89:    names are typically short (~8 char) and the loop that extracts them
                     90:    might terminate on a colon, newline or max width.  I considered
                     91:    using a Vax "scanc" to locate the end of the field followed by a
                     92:    "bcopy" but the routine call overhead on a Vax is too large for this
                     93:    to work on short names.  If Berkeley ever makes "inline" part of the
                     94:    C optimiser (so things like "scanc" turn into inline instructions) a
                     95:    change here would be worthwhile.
                     96: 
                     97:    Field text is typically 60 - 100 characters so there's (barely)
                     98:    a win in doing a routine call to something that does a "locc"
                     99:    followed by a "bmove".  About 30% of the fields have continuations
                    100:    (usually the 822 "received:" lines) and each continuation generates
                    101:    another routine call.  "Inline" would be a big win here, as well.
                    102: 
                    103:    Messages, as of this writing, seem to come in two flavors: small
                    104:    (~1K) and long (>2K).  Most messages have 400 - 600 bytes of headers
                    105:    so message bodies average at least a few hundred characters.
                    106:    Assuming your system uses reasonably sized stdio buffers (1K or
                    107:    more), this routine should be able to remove the body in large
                    108:    (>500 byte) chunks.  The makes the cost of a call to "bcopy"
                    109:    small but there is a premium on checking for the eom in packed
                    110:    maildrops.  The eom pattern is always a simple string so we can
                    111:    construct an efficient pattern matcher for it (e.g., a Vax "matchc"
                    112:    instruction).  Some thought went into recognizing the start of
                    113:    an eom that has been split across two buffers.
                    114: 
                    115:    This routine wants to deal with large chunks of data so, rather
                    116:    than "getc" into a local buffer, it uses stdio's buffer.  If
                    117:    you try to use it on a non-buffered file, you'll get what you
                    118:    deserve.  This routine "knows" that struct FILEs have a _ptr
                    119:    and a _cnt to describe the current state of the buffer and
                    120:    it knows that _filbuf ignores the _ptr & _cnt and simply fills
                    121:    the buffer.  If stdio on your system doesn't work this way, you
                    122:    may have to make small changes in this routine.
                    123:    
                    124:    This routine also "knows" that an EOF indication on a stream is
                    125:    "sticky" (i.e., you will keep getting EOF until you reposition the
                    126:    stream).  If your system doesn't work this way it is broken and you
                    127:    should complain to the vendor.  As a consequence of the sticky
                    128:    EOF, this routine will never return any kind of EOF status when
                    129:    there is data in "name" or "buf").
                    130:   */
                    131: 
                    132: 
                    133: #define Getc(iob)      getc(iob)
                    134: #define eom(c,iob)     (msg_style != MS_DEFAULT && \
                    135:                         (((c) == *msg_delim && m_Eom(c,iob)) ||\
                    136:                          (eom_action && (*eom_action)(c))))
                    137: 
                    138: static char *matchc();
                    139: static char *locc();
                    140: 
                    141: static char **pat_map;
                    142: 
                    143: int    msg_count = 0;  /* disgusting hack for "inc" so it can
                    144:                         * know how many characters were stuffed
                    145:                         * in the buffer on the last call (see
                    146:                         * comments in uip/scansbr.c) */
                    147: 
                    148: int    msg_style = MS_DEFAULT;
                    149: /*
                    150:  * The "full" delimiter string for a packed maildrop consists
                    151:  * of a newline followed by the actual delimiter.  E.g., the
                    152:  * full string for a Unix maildrop would be: "\n\nFrom ".
                    153:  * "Fdelim" points to the start of the full string and is used
                    154:  * in the BODY case of the main routine to search the buffer for
                    155:  * a possible eom.  Msg_delim points to the first character of
                    156:  * the actual delim. string (i.e., fdelim+1).  Edelim
                    157:  * points to the 2nd character of actual delimiter string.  It
                    158:  * is used in m_Eom because the first character of the string
                    159:  * has been read and matched before m_Eom is called.
                    160:  */
                    161: char   *msg_delim = "";
                    162: static char *fdelim;
                    163: static char *delimend;
                    164: static int  fdelimlen;
                    165: static char *edelim;
                    166: static int  edelimlen;
                    167: 
                    168: static int  (*eom_action) () = NULL;
                    169: 
                    170: /*  */
                    171: 
                    172: m_getfld (state, name, buf, bufsz, iob)
                    173: int            state;
                    174: int            bufsz;
                    175: char           *name,
                    176:                *buf;
                    177: register FILE  *iob;
                    178: {
                    179:     register char  *cp;
                    180:     register char  *bp;
                    181:     register int    cnt;
                    182:     register int    c;
                    183:     register int    i;
                    184:     register int    j;
                    185:     register char  *ep;
                    186:     register char  *sp;
                    187: 
                    188:     if ((c = Getc(iob)) < 0) {
                    189:        msg_count = 0;
                    190:        *buf = 0;
                    191:        return FILEEOF;
                    192:     }
                    193:     if (eom (c, iob)) {
                    194:        if (! eom_action) {
                    195:            /* flush null messages */
                    196:            while ((c = Getc(iob)) >= 0 && eom (c, iob))
                    197:                ;
                    198:            if (c >= 0)
                    199:                (void) ungetc(c, iob);
                    200:        }
                    201:        msg_count = 0;
                    202:        *buf = 0;
                    203:        return FILEEOF;
                    204:     }
                    205: 
                    206:     switch (state) {
                    207:        case FLDEOF: 
                    208:        case BODYEOF: 
                    209:        case FLD: 
                    210:            if (c == '\n' || c == '-') {
                    211:                /* we hit the header/body separator */
                    212:                while (c != '\n' && (c = Getc(iob)) >= 0)
                    213:                    ;
                    214: 
                    215:                if (c < 0 || (c = Getc(iob)) < 0 || eom (c, iob)) {
                    216:                    if (! eom_action) {
                    217:                        /* flush null messages */
                    218:                        while ((c = Getc(iob)) >= 0 && eom (c, iob))
                    219:                            ;
                    220:                        if (c >= 0)
                    221:                            (void) ungetc(c, iob);
                    222:                    }
                    223:                    msg_count = 0;
                    224:                    *buf = 0;
                    225:                    return FILEEOF;
                    226:                }
                    227:                state = BODY;
                    228:                goto body;
                    229:            }
                    230:            /*
                    231:             * get the name of this component.  take characters up
                    232:             * to a ':', a newline or NAMESZ-1 characters, whichever
                    233:             * comes first.  
                    234:             */
                    235:            cp = name; i = NAMESZ - 1;
                    236:            for (;;) {
                    237:                bp = sp = iob->_ptr - 1;
                    238:                j = (cnt = iob->_cnt+1) < i ? cnt : i;
                    239:                while ((c = *bp++) != ':' && c != '\n' && --j >= 0)
                    240:                    *cp++ = c;
                    241: 
                    242:                j = bp - sp;
                    243:                if ((cnt -= j) <= 0) {
                    244:                    if (_filbuf(iob) == EOF) {
                    245:                        *cp = *buf = NULL;
                    246:                        advise (NULLCP, "eof encountered in field \"%s\"",
                    247:                                name);
                    248:                        return FMTERR;
                    249:                    }
                    250:                } else {
                    251:                    iob->_ptr = bp + 1;
                    252:                    iob->_cnt = cnt - 1;
                    253:                }
                    254:                if (c == ':')
                    255:                    break;
                    256: 
                    257:                /*
                    258:                 * something went wrong.  possibilities are:
                    259:                 *  . hit a newline (error)
                    260:                 *  . got more than namesz chars. (error)
                    261:                 *  . hit the end of the buffer. (loop)
                    262:                 */
                    263:                if (c == '\n') {
                    264:                    *cp = *buf = NULL;
                    265:                    advise (NULLCP, "eol encountered in field \"%s\"", name);
                    266:                    state = FMTERR;
                    267:                    goto finish;
                    268:                }
                    269:                if ((i -= j) <= 0) {
                    270:                    *cp = *buf = NULL;
                    271:                    advise (NULLCP, "field name \"%s\" exceeds %d bytes",
                    272:                            name, NAMESZ - 1);
                    273:                    state = LENERR;
                    274:                    goto finish;
                    275:                }
                    276:            }
                    277: 
                    278:            while (isspace (*--cp) && cp >= name)
                    279:                ;
                    280:            *++cp = NULL;
                    281:            /* fall through */
                    282: 
                    283:        case FLDPLUS: 
                    284:            /*
                    285:             * get (more of) the text of a field.  take
                    286:             * characters up to the end of this field (newline
                    287:             * followed by non-blank) or bufsz-1 characters.
                    288:             */
                    289:            cp = buf; i = bufsz-1;
                    290:            for (;;) {
                    291:                cnt = iob->_cnt++; bp = --iob->_ptr;
                    292:                c = cnt < i ? cnt : i;
                    293:                while (ep = locc( c, bp, '\n' )) {
                    294:                    /*
                    295:                     * if we hit the end of this field, return.
                    296:                     */
                    297:                    if ((j = *++ep) != ' ' && j != '\t') {
                    298:                        j = ep - iob->_ptr;
                    299:                        (void) bcopy( iob->_ptr, cp, j);
                    300:                        iob->_ptr = ep; iob->_cnt -= j;
                    301:                        cp += j;
                    302:                        state = FLD;
                    303:                        goto finish;
                    304:                    }
                    305:                    c -= ep - bp; bp = ep;
                    306:                }
                    307:                /*
                    308:                 * end of input or dest buffer - copy what we've found.
                    309:                 */
                    310:                c += bp - iob->_ptr;
                    311:                (void) bcopy( iob->_ptr, cp, c);
                    312:                i -= c; cp += c;
                    313:                if (i <= 0) {
                    314:                    /* the dest buffer is full */
                    315:                    iob->_cnt -= c; iob->_ptr += c;
                    316:                    state = FLDPLUS;
                    317:                    break;
                    318:                }
                    319:                /* 
                    320:                 * There's one character left in the input buffer.
                    321:                 * Copy it & fill the buffer.  If the last char
                    322:                 * was a newline and the next char is not whitespace,
                    323:                 * this is the end of the field.  Otherwise loop.
                    324:                 */
                    325:                --i;
                    326:                *cp++ = j = *(iob->_ptr + c);
                    327:                c = _filbuf(iob);
                    328:                if (j == '\n' && c != ' ' && c != '\t') {
                    329:                    if (c != EOF)
                    330:                        --iob->_ptr, ++iob->_cnt;
                    331:                    state = FLD;
                    332:                    break;
                    333:                }
                    334:            }
                    335:            break;
                    336: 
                    337:        case BODY: 
                    338:        body:
                    339:            /*
                    340:             * get the message body up to bufsz characters or the
                    341:             * end of the message.  Sleazy hack: if bufsz is negative
                    342:             * we assume that we were called to copy directly into
                    343:             * the output buffer and we don't add an eos.
                    344:             */
                    345:            i = (bufsz < 0) ? -bufsz : bufsz-1;
                    346:            bp = --iob->_ptr; cnt = ++iob->_cnt;
                    347:            c = (cnt < i ? cnt : i);
                    348:            if (msg_style != MS_DEFAULT && c > 1) {
                    349:                /*
                    350:                 * packed maildrop - only take up to the (possible)
                    351:                 * start of the next message.  This "matchc" should
                    352:                 * probably be a Boyer-Moore matcher for non-vaxen,
                    353:                 * particularly since we have the alignment table
                    354:                 * all built for the end-of-buffer test (next).
                    355:                 * But our vax timings indicate that the "matchc"
                    356:                 * instruction is 50% faster than a carefully coded
                    357:                 * B.M. matcher for most strings.  (So much for elegant
                    358:                 * algorithms vs. brute force.)  Since I (currently)
                    359:                 * run MH on a vax, we use the matchc instruction. --vj
                    360:                 */
                    361:                if (ep = matchc( fdelimlen, fdelim, c, bp ) )
                    362:                    c = ep - bp + 1;
                    363:                else {
                    364:                    /*
                    365:                     * There's no delim in the buffer but there may be
                    366:                     * a partial one at the end.  If so, we want to leave
                    367:                     * it so the "eom" check on the next call picks it up.
                    368:                     * Use a modified Boyer-Moore matcher to make this
                    369:                     * check relatively cheap.  The first "while" figures
                    370:                     * out what position in the pattern matches the last
                    371:                     * character in the buffer.  The inner "while" matches
                    372:                     * the pattern against the buffer, backwards starting
                    373:                     * at that position.  Note that unless the buffer
                    374:                     * ends with one of the characters in the pattern
                    375:                     * (excluding the first and last), we do only one test.
                    376:                     */
                    377:                    sp = delimend;
                    378:                    ep = bp + c - 1;
                    379:                    while ((cp = pat_map[*ep]) < sp) {
                    380:                        ep = bp + c - 1; sp = cp;
                    381:                        while (*--ep == *--cp && cp > fdelim)
                    382:                            ;
                    383:                        if (cp == fdelim) {
                    384:                            if (*ep == *cp && ep > bp)
                    385:                                c = (ep - bp) + 1;
                    386:                            break;
                    387:                        }
                    388:                    }
                    389:                }
                    390:            }
                    391:            (void) bcopy( bp, buf, c );
                    392:            iob->_cnt -= c;
                    393:            iob->_ptr += c;
                    394:            if (bufsz < 0) {
                    395:                msg_count = c;
                    396:                return (state);
                    397:            }
                    398:            cp = buf + c;
                    399:            break;
                    400: 
                    401:        default: 
                    402:            adios (NULLCP, "m_getfld() called with bogus state of %d", state);
                    403:     }
                    404: finish:;
                    405:     *cp = NULL;
                    406:     msg_count = cp - buf;
                    407:     return (state);
                    408: }
                    409: 
                    410: /*  */
                    411: 
                    412: #ifdef RPATHS
                    413: static char  unixbuf[BUFSIZ] = "";
                    414: #endif RPATHS
                    415: 
                    416: void m_unknown (iob)
                    417: register FILE *iob;
                    418: {
                    419:     register   int c;
                    420:     register   long pos;
                    421:     char       text[10];
                    422:     register    char *cp;
                    423: 
                    424:     msg_style = MS_UNKNOWN;
                    425: 
                    426:     /* Figure out what the message delimitter string is for this
                    427:      * maildrop.  (This used to be part of m_Eom but I didn't like
                    428:      * the idea of an "if" statement that could only succeed on the
                    429:      * first call to m_Eom getting executed on each call, i.e., at
                    430:      * every newline in the message).
                    431:      *
                    432:      * If the first line of the maildrop is a Unix "from" line, we say the
                    433:      * style is UUCP and eat the rest of the line.  Otherwise we say the style
                    434:      * is MMDF & look for the delimiter string specified when MH was built
                    435:      * (or from the mtstailor file).
                    436:      */
                    437:     pos = ftell (iob);
                    438:     if (fread (text, sizeof *text, 5, iob) == 5
                    439:            && strncmp (text, "From ", 5) == 0) {
                    440:        msg_style = MS_UUCP;
                    441:        fdelim = "\n\nFrom ";
                    442: #ifndef        RPATHS
                    443:        while ((c = getc (iob)) != '\n' && c >= 0)
                    444:            ;
                    445: #else  RPATHS
                    446:        cp = unixbuf;
                    447:        while ((c = getc (iob)) != '\n')
                    448:            *cp++ = c;
                    449:        *cp = NULL;
                    450: #endif RPATHS
                    451:     } else {
                    452:        /* not a Unix style maildrop */
                    453:        (void) fseek (iob, pos, 0);
                    454:        if (mmdlm2 == NULLCP || *mmdlm2 == NULL)
                    455:            mmdlm2 = "\001\001\001\001\n";
                    456:        fdelim = (char *)malloc((unsigned)strlen(mmdlm2)+2);
                    457:        *fdelim = '\n';
                    458:        (void)strcpy(fdelim+1, mmdlm2);
                    459:        msg_style = MS_MMDF;
                    460:     }
                    461:     fdelimlen = strlen(fdelim);
                    462:     msg_delim = fdelim+1;
                    463:     edelim = msg_delim+1;
                    464:     edelimlen = fdelimlen-2;
                    465:     delimend = msg_delim + edelimlen;
                    466:     if (edelimlen <= 1)
                    467:        adios (NULLCP, "maildrop delimiter must be at least 2 bytes");
                    468:     /*
                    469:      * build a Boyer-Moore end-position map for the matcher in m_getfld.
                    470:      * N.B. - we don't match just the first char (since it's the newline
                    471:      * separator) or the last char (since the matchc would have found it
                    472:      * if it was a real delim).
                    473:      */
                    474:     pat_map = (char **) malloc( 256 * sizeof (char *));
                    475:     for (c = 256; c--; )
                    476:        pat_map[c] = delimend + 1;
                    477: 
                    478:     for (cp = fdelim + 1; cp < delimend; cp++ )
                    479:        pat_map[*cp] = cp;
                    480: 
                    481:     if (msg_style == MS_MMDF) {
                    482:        /* flush extra msg hdrs */
                    483:        while ((c = Getc(iob)) >= 0 && eom (c, iob))
                    484:            ;
                    485:        if (c >= 0)
                    486:            (void) ungetc(c, iob);
                    487:     }
                    488: }
                    489: 
                    490: 
                    491: void m_eomsbr (action)
                    492: int     (*action) ();
                    493: {
                    494:     if (eom_action = action) {
                    495:        msg_style = MS_MSH;
                    496:        *msg_delim = 0;
                    497:        fdelimlen = 1;
                    498:        delimend = fdelim;
                    499:     } else {
                    500:        msg_style = MS_MMDF;
                    501:        msg_delim = fdelim + 1;
                    502:        fdelimlen = strlen (fdelim);
                    503:        delimend = msg_delim + edelimlen;
                    504:     }
                    505: }
                    506: 
                    507: /*  */
                    508: 
                    509: /* test for msg delimiter string */
                    510: 
                    511: int  m_Eom (c, iob)
                    512: register int     c;
                    513: register FILE   *iob;
                    514: {
                    515:     register long pos = 0L;
                    516:     register int i;
                    517:     char    text[10];
                    518: #ifdef RPATHS
                    519:     register    char *cp;
                    520: #endif RPATHS
                    521: 
                    522:     pos = ftell (iob);
                    523:     if ((i = fread (text, sizeof *text, edelimlen, iob)) != edelimlen
                    524:            || strncmp (text, edelim, edelimlen)) {
                    525:        if (i == 0 && msg_style == MS_UUCP)
                    526:            /* the final newline in the (brain damaged) unix-format
                    527:             * maildrop is part of the delimitter - delete it.
                    528:             */
                    529:            return 1;
                    530: 
                    531:        (void) fseek (iob, pos, 0);
                    532:        return 0;
                    533:     }
                    534: 
                    535:     if (msg_style == MS_UUCP) {
                    536: #ifndef        RPATHS
                    537:        while ((c = getc (iob)) != '\n')
                    538:            if (c < 0)
                    539:                break;
                    540: #else  RPATHS
                    541:        cp = unixbuf;
                    542:        while ((c = getc (iob)) != '\n' && c >= 0)
                    543:            *cp++ = c;
                    544:        *cp = NULL;
                    545: #endif RPATHS
                    546:     }
                    547: 
                    548:     return 1;
                    549: }
                    550: 
                    551: /*  */
                    552: 
                    553: #ifdef RPATHS
                    554: char   *unixline () {
                    555:     register char  *cp,
                    556:                    *dp,
                    557:                    *pp;
                    558:     static char unixfrom[BUFSIZ];
                    559: 
                    560:     pp = unixfrom;
                    561:     if (cp = dp = index (unixbuf, ' ')) {
                    562:        while (cp = index (cp + 1, 'r'))
                    563:            if (strncmp (cp, "remote from ", 12) == 0) {
                    564:                *cp = NULL;
                    565:                (void) sprintf (pp, "%s!", cp + 12);
                    566:                pp += strlen (pp);
                    567:                break;
                    568:            }
                    569:        if (cp == NULL)
                    570:            cp = unixbuf + strlen (unixbuf);
                    571:        if ((cp -= 25) >= dp)
                    572:            *cp = NULL;
                    573:     }
                    574: 
                    575:     (void) sprintf (pp, "%s\n", unixbuf);
                    576:     unixbuf[0] = NULL;
                    577:     return unixfrom;
                    578: }
                    579: #endif RPATHS
                    580: 
                    581: /*  */
                    582: 
                    583: #if (vax && !lint)
                    584:        asm(".align 1");
                    585:        asm("_matchc: .word 0");
                    586:        asm("   movq 4(ap),r0");
                    587:        asm("   movq 12(ap),r2");
                    588:        asm("   matchc  r0,(r1),r2,(r3)");
                    589:        asm("   beql 1f");
                    590:        asm("   movl 4(ap),r3");
                    591:        asm("1: subl3  4(ap),r3,r0");
                    592:        asm("   ret");
                    593: #else
                    594: static char *
                    595: matchc( patln, pat, strln, str )
                    596:        int patln;
                    597:        char *pat;
                    598:        int strln;
                    599:        register char *str;
                    600: {
                    601:        register char *es = str + strln - patln;
                    602:        register char *sp;
                    603:        register char *pp;
                    604:        register char *ep = pat + patln;
                    605:        register char pc = *pat++;
                    606: 
                    607:        for(;;) {
                    608:                while (pc != *str++)
                    609:                        if (str > es)
                    610:                                return 0;
                    611: 
                    612:                sp = str; pp = pat;
                    613:                while (pp < ep && *sp++ == *pp++)
                    614:                        ;
                    615:                if (pp >= ep) 
                    616:                        return (--str);
                    617:        }
                    618: }
                    619: #endif
                    620: 
                    621: /*  */
                    622: 
                    623: /*
                    624:  * Locate character "term" in the next "cnt" characters of "src".
                    625:  * If found, return its address, otherwise return 0.
                    626:  */
                    627: #if (vax && !lint)
                    628:        asm(".align 1");
                    629:        asm("_locc: .word 0");
                    630:        asm("   movq  4(ap),r0");
                    631:        asm("   locc  12(ap),r0,(r1)");
                    632:        asm("   beql  1f");
                    633:        asm("   movl  r1,r0");
                    634:        asm("1: ret");
                    635: #else
                    636: static char *
                    637: locc( cnt, src, term )
                    638:        register int  cnt;
                    639:        register char *src;
                    640:        register char term;
                    641: {
                    642:     while (*src++ != term && --cnt > 0);
                    643: 
                    644:     return (cnt > 0 ? --src : NULLCP);
                    645: }
                    646: #endif
                    647: 
                    648: /*  */
                    649: 
                    650: #if    !defined (BSD42) && !defined (bcopy)
                    651: int    bcmp (b1, b2, length)
                    652: register char *b1,
                    653:              *b2;
                    654: register int   length;
                    655: {
                    656:     while (length-- > 0)
                    657:        if (*b1++ != *b2++)
                    658:            return 1;
                    659: 
                    660:     return 0;
                    661: }
                    662: 
                    663: 
                    664: bcopy (b1, b2, length)
                    665: register char *b1,
                    666:              *b2;
                    667: register int   length;
                    668: {
                    669:     while (length-- > 0)
                    670:        *b2++ = *b1++;
                    671: }
                    672: 
                    673: 
                    674: bzero (b, length)
                    675: register char *b;
                    676: register int   length;
                    677: {
                    678:     while (length-- > 0)
                    679:        *b++ = NULL;
                    680: }
                    681: #endif not BSD42 or SYS5

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.