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

1.1       root        1: /* formatsbr.c - format string interpretation */
                      2: 
                      3: #include "../h/mh.h"
                      4: #include "../h/addrsbr.h"
                      5: #include "../h/formatsbr.h"
                      6: #include "../zotnet/tws.h"
                      7: #include "../h/fmtcompile.h"
                      8: #include <ctype.h>
                      9: #include <stdio.h>
                     10: #include <sys/types.h>
                     11: #include <sys/stat.h>
                     12: 
                     13: /*  */
                     14: 
                     15: 
                     16: #define        NFMTS   MAXARGS
                     17: #define QUOTE '\\'
                     18: 
                     19: static char  *formats = 0;
                     20: extern char *formataddr ();    /* hook for custom address formatting */
                     21: 
                     22: int    fmt_norm = AD_NAME;
                     23: struct mailname fmt_mnull;
                     24: 
                     25: /*  */
                     26: 
                     27: /* MAJOR HACK: See MHCHANGES for discussion */
                     28: 
                     29: char  *new_fs (form, format, def)
                     30: register char  *form,
                     31:                *format,
                     32:                *def;
                     33: {
                     34:     struct stat st;
                     35:     register    FILE *fp;
                     36: 
                     37:     if (formats)
                     38:        free (formats);
                     39: 
                     40:     if (form) {
                     41:        if ((fp = fopen (libpath (form), "r")) == NULL)
                     42:            adios (form, "unable to open format file");
                     43: 
                     44:        if (fstat (fileno (fp), &st) == NOTOK)
                     45:            adios (form, "unable to stat format file");
                     46: 
                     47:        if ((formats = malloc ((unsigned) st.st_size)) == NULLCP)
                     48:            adios (form, "unable to allocate space for format");
                     49: 
                     50:        if (read (fileno(fp), formats, st.st_size) != st.st_size)
                     51:            adios (form, "error reading format file");
                     52: 
                     53:        (void) fclose (fp);
                     54:     }
                     55:     else {
                     56:        formats = getcpy (format ? format : def);
                     57:     }
                     58: 
                     59:     normalize (formats);
                     60: 
                     61:     return formats;
                     62: }
                     63: 
                     64: /*  */
                     65: 
                     66: static  normalize (cp)
                     67: register char  *cp;
                     68: {
                     69:     register char  *dp;
                     70: 
                     71:     for (dp = cp; *cp; cp++)
                     72:        if (*cp != QUOTE)
                     73:            *dp++ = *cp;
                     74:        else
                     75:            switch (*++cp) {
                     76: #define        grot(x) case 'x': *dp++ = '\x'; break;
                     77:                    grot (b);
                     78:                    grot (f);
                     79:                    grot (n);
                     80:                    grot (r);
                     81:                    grot (t);
                     82: 
                     83:                case '\n':
                     84:                    break;
                     85: 
                     86:                case NULL: 
                     87:                    cp--;       /* fall */
                     88:                default: 
                     89:                    *dp++ = *cp;
                     90:                    break;
                     91:            }
                     92: 
                     93:     *dp = NULL;
                     94: }
                     95: 
                     96: /*  */
                     97: /*
                     98:  * test if string "sub" appears anywhere in string "str"
                     99:  * (case insensitive).
                    100:  */
                    101: 
                    102: static int match (str, sub)
                    103: register char  *str,
                    104:                *sub;
                    105: {
                    106:     register int    c1;
                    107:     register int    c2;
                    108:     register char   *s1;
                    109:     register char   *s2;
                    110: 
                    111:     while (c1 = *sub) {
                    112:        while ((c2 = *str++) && (c1 | 040) != (c2 | 040))
                    113:            ;
                    114:        if (! c2)
                    115:            return 0;
                    116:        s1 = sub + 1; s2 = str;
                    117:        while ((c1 = *s1++) && (c1 | 040) == (*s2++ | 040))
                    118:            ;
                    119:        if (! c1)
                    120:            return 1;
                    121:     }
                    122:     return 1;
                    123: }
                    124: /*  */
                    125: 
                    126: /* macros to format data */
                    127: 
                    128: #define PUTDF(cp, num, wid, fill) if (cp + wid < ep){\
                    129:                if((i = (num))<0) i = -(num);\
                    130:                sp = cp + wid;\
                    131:                do {\
                    132:                    *--sp = (i % 10) + '0';\
                    133:                    i /= 10;\
                    134:                } while (i > 0 && sp > cp);\
                    135:                if (i > 0)\
                    136:                    *sp = '?';\
                    137:                else if ((num) < 0 && sp > cp)\
                    138:                    *--sp = '-';\
                    139:                while (sp > cp)\
                    140:                    *--sp = fill;\
                    141:                cp += wid;\
                    142:                }
                    143: #define PUTD(cp, num) if (cp < ep){\
                    144:                if((i = (num))==0) *cp++ = '0';\
                    145:                else {\
                    146:                    if((i = (num))<0) \
                    147:                        *cp++ = '-', i = -(num);\
                    148:                    c = 10;\
                    149:                    while (c <= i) \
                    150:                        c *= 10;\
                    151:                    while (cp < ep && c > 1) {\
                    152:                        c /= 10;\
                    153:                        *cp++ = (i / c) + '0';\
                    154:                        i %= c;\
                    155:                        }\
                    156:                    }\
                    157:                }
                    158: #define PUTSF(cp, str, wid, fill) {\
                    159:                i = (wid);\
                    160:                if (sp = (str)) {\
                    161:                    while ((c = *sp) && c <= 32)\
                    162:                        sp++;\
                    163:                    while( (c = *sp++) && --i >= 0 && cp < ep)\
                    164:                        if ( c > 32 ) \
                    165:                            *cp++ = c;\
                    166:                        else {\
                    167:                            while ( (c = *sp) && c <= 32 )\
                    168:                                sp++;\
                    169:                            *cp++ = ' ';\
                    170:                        }\
                    171:                }\
                    172:                while( --i >= 0 && cp < ep)\
                    173:                    *cp++ = fill;\
                    174:                }
                    175: #define PUTS(cp, str) {\
                    176:                if (sp = (str)) {\
                    177:                    while ((c = *sp) && c <= 32)\
                    178:                        sp++;\
                    179:                    while( (c = *sp++) && cp < ep)\
                    180:                        if ( c > 32 ) \
                    181:                            *cp++ = c;\
                    182:                        else {\
                    183:                            while ( (c = *sp) && c <= 32 )\
                    184:                                sp++;\
                    185:                            *cp++ = ' ';\
                    186:                        }\
                    187:                }\
                    188:                }
                    189: 
                    190: 
                    191: static char *lmonth[] = { "January",  "February","March",   "April",
                    192:                          "May",      "June",    "July",    "August",
                    193:                          "September","October", "November","December" };
                    194: 
                    195: 
                    196: fmtscan (format, scanl, width, dat)
                    197:        struct format *format;
                    198:        char    *scanl;
                    199:        int     width;
                    200:        int     dat[];
                    201: {
                    202:     register char      *cp = scanl;
                    203:     register char      *ep = scanl + width - 1;
                    204:     register struct format *fmt = format;
                    205:     register char      *str = NULLCP;
                    206:     register int       value = 0;
                    207:     register char      *sp;
                    208:     register int       i;
                    209:     register int       c;
                    210:     register struct comp *comp;
                    211:     register struct tws *tws;
                    212:     register struct mailname *mn;
                    213:     char        *savestr;
                    214:     char       buffer[BUFSIZ];
                    215: 
                    216:     while (cp < ep) {
                    217:        switch (fmt->f_type) {
                    218: 
                    219:        case FT_COMP:
                    220:            PUTS (cp, fmt->f_comp->c_text);
                    221:            break;
                    222:        case FT_COMPF:
                    223:            PUTSF (cp, fmt->f_comp->c_text, fmt->f_width, fmt->f_fill);
                    224:            break;
                    225: 
                    226:        case FT_LIT:
                    227:            sp = fmt->f_text;
                    228:            while( (c = *sp++) && cp < ep)
                    229:                *cp++ = c;
                    230:            break;
                    231:        case FT_LITF:
                    232:            sp = fmt->f_text; i = fmt->f_width;
                    233:            while( (c = *sp++) && --i >= 0 && cp < ep)
                    234:                *cp++ = c;
                    235:            while( --i >= 0 && cp < ep)
                    236:                *cp++ = fmt->f_fill;
                    237:            break;
                    238: 
                    239:        case FT_STR:
                    240:            PUTS (cp, str);
                    241:            break;
                    242:        case FT_STRF:
                    243:            PUTSF (cp, str, fmt->f_width, fmt->f_fill);
                    244:            break;
                    245:        case FT_STRFW:
                    246:            adios (NULLCP, "internal error (FT_STRFW)");
                    247: 
                    248:        case FT_NUM:
                    249:            PUTD (cp, value);
                    250:            break;
                    251:        case FT_NUMF:
                    252:            PUTDF (cp, value, fmt->f_width, fmt->f_fill);
                    253:            break;
                    254: 
                    255:        case FT_CHAR:
                    256:            *cp++ = fmt->f_char;
                    257:            break;
                    258: 
                    259:        case FT_DONE:
                    260:            goto finished;
                    261: 
                    262:        case FT_IF_S:
                    263:            if (str == NULLCP || *str == NULL) {
                    264:                fmt += fmt->f_skip;
                    265:                continue;
                    266:            }
                    267:            break;
                    268: 
                    269:        case FT_IF_S_NULL:
                    270:            if (str != NULLCP && *str != NULL) {
                    271:                fmt += fmt->f_skip;
                    272:                continue;
                    273:            }
                    274:            break;
                    275: 
                    276:        case FT_IF_V_EQ:
                    277:            if (value != fmt->f_value) {
                    278:                fmt += fmt->f_skip;
                    279:                continue;
                    280:            }
                    281:            break;
                    282: 
                    283:        case FT_IF_V_NE:
                    284:            if (value == fmt->f_value) {
                    285:                fmt += fmt->f_skip;
                    286:                continue;
                    287:            }
                    288:            break;
                    289: 
                    290:        case FT_IF_V_GT:
                    291:            if (value <= fmt->f_value) {
                    292:                fmt += fmt->f_skip;
                    293:                continue;
                    294:            }
                    295:            break;
                    296: 
                    297:        case FT_IF_MATCH:
                    298:            if (! match (str, fmt->f_text)) {
                    299:                fmt += fmt->f_skip;
                    300:                continue;
                    301:            }
                    302:            break;
                    303: 
                    304:        case FT_V_MATCH:
                    305:            value = match (str, fmt->f_text);
                    306:            break;
                    307: 
                    308:        case FT_IF_AMATCH:
                    309:            if (! uprf (str, fmt->f_text)) {
                    310:                fmt += fmt->f_skip;
                    311:                continue;
                    312:            }
                    313:            break;
                    314: 
                    315:        case FT_V_AMATCH:
                    316:            value = uprf (str, fmt->f_text);
                    317:            break;
                    318: 
                    319:        case FT_S_NONNULL:
                    320:            value = (str != NULLCP && *str != NULL);
                    321:            break;
                    322: 
                    323:        case FT_S_NULL:
                    324:            value = (str == NULLCP || *str == NULL);
                    325:            break;
                    326: 
                    327:        case FT_V_EQ:
                    328:            value = (fmt->f_value == value);
                    329:            break;
                    330: 
                    331:        case FT_V_NE:
                    332:            value = (fmt->f_value != value);
                    333:            break;
                    334: 
                    335:        case FT_V_GT:
                    336:            value = (fmt->f_value > value);
                    337:            break;
                    338: 
                    339:        case FT_GOTO:
                    340:            fmt += fmt->f_skip;
                    341:            continue;
                    342: 
                    343:        case FT_NOP:
                    344:            break;
                    345: 
                    346:        case FT_LS_COMP:
                    347:            str = fmt->f_comp->c_text;
                    348:            break;
                    349:        case FT_LS_LIT:
                    350:            str = fmt->f_text;
                    351:            break;
                    352: 
                    353:        case FT_LV_COMPFLAG:
                    354:            value = fmt->f_comp->c_flags;
                    355:            break;
                    356:        case FT_LV_COMP:
                    357:            value = (comp = fmt->f_comp)->c_text ? atoi(comp->c_text) : 0;
                    358:            break;
                    359:        case FT_LV_LIT:
                    360:            value = fmt->f_value;
                    361:            break;
                    362:        case FT_LV_DAT:
                    363:            value = dat[fmt->f_value];
                    364:            break;
                    365:        case FT_LV_STRLEN:
                    366:            value = strlen(str);
                    367:            break;
                    368:        case FT_LV_CHAR_LEFT:
                    369:            value = width - (cp - scanl);
                    370:            break;
                    371:        case FT_LV_PLUS_L:
                    372:            value += fmt->f_value;
                    373:            break;
                    374:        case FT_LV_MINUS_L:
                    375:            value = fmt->f_value - value;
                    376:            break;
                    377:        case FT_SAVESTR:
                    378:            savestr = str;
                    379:            break;
                    380: 
                    381:        case FT_LV_SEC:
                    382:            value = fmt->f_comp->c_tws->tw_sec;
                    383:            break;
                    384:        case FT_LV_MIN:
                    385:            value = fmt->f_comp->c_tws->tw_min;
                    386:            break;
                    387:        case FT_LV_HOUR:
                    388:            value = fmt->f_comp->c_tws->tw_hour;
                    389:            break;
                    390:        case FT_LV_MDAY:
                    391:            value = fmt->f_comp->c_tws->tw_mday;
                    392:            break;
                    393:        case FT_LV_MON:
                    394:            value = fmt->f_comp->c_tws->tw_mon + 1;
                    395:            break;
                    396:        case FT_LS_MONTH:
                    397:            str = tw_moty[fmt->f_comp->c_tws->tw_mon];
                    398:            break;
                    399:        case FT_LS_LMONTH:
                    400:            str = lmonth[fmt->f_comp->c_tws->tw_mon];
                    401:            break;
                    402:        case FT_LS_ZONE:
                    403:            str = dtwszone (fmt->f_comp->c_tws);
                    404:            break;
                    405:        case FT_LV_YEAR:
                    406:            value = fmt->f_comp->c_tws->tw_year;
                    407:            break;
                    408:        case FT_LV_WDAY:
                    409:            if (!(((tws = fmt->f_comp->c_tws)->tw_flags) & (TW_SEXP|TW_SIMP)))
                    410:                set_dotw (tws);
                    411:            value = tws->tw_wday;
                    412:            break;
                    413:        case FT_LS_DAY:
                    414:            if (!(((tws = fmt->f_comp->c_tws)->tw_flags) & (TW_SEXP|TW_SIMP)))
                    415:                set_dotw (tws);
                    416:            str = tw_dotw[tws->tw_wday];
                    417:            break;
                    418:        case FT_LS_WEEKDAY:
                    419:            if (!(((tws = fmt->f_comp->c_tws)->tw_flags) & (TW_SEXP|TW_SIMP)))
                    420:                set_dotw (tws);
                    421:            str = tw_ldotw[tws->tw_wday];
                    422:            break;
                    423:        case FT_LV_YDAY:
                    424:            value = fmt->f_comp->c_tws->tw_yday;
                    425:            break;
                    426:        case FT_LV_ZONE:
                    427:            value = fmt->f_comp->c_tws->tw_zone;
                    428:            break;
                    429:        case FT_LV_CLOCK:
                    430:            if ((value = fmt->f_comp->c_tws->tw_clock) == 0)
                    431:                value = twclock(fmt->f_comp->c_tws);
                    432:            break;
                    433:        case FT_LV_RCLOCK:
                    434:            if ((value = fmt->f_comp->c_tws->tw_clock) == 0)
                    435:                value = twclock(fmt->f_comp->c_tws);
                    436:            value = time((long *) 0) - value;
                    437:            break;
                    438:        case FT_LV_DAYF:
                    439:            if (!(((tws = fmt->f_comp->c_tws)->tw_flags) & (TW_SEXP|TW_SIMP)))
                    440:                set_dotw (tws);
                    441:            switch (fmt->f_comp->c_tws->tw_flags & TW_SDAY) {
                    442:                case TW_SEXP:
                    443:                    value = 1; break;
                    444:                case TW_SIMP:
                    445:                    value = 0; break;
                    446:                default:
                    447:                    value = -1; break;
                    448:            }
                    449:            break;
                    450:        case FT_LV_TZONEF:
                    451:            value = fmt->f_comp->c_tws->tw_flags & TW_DST;
                    452:            break;
                    453:        case FT_LS_822DATE:
                    454:            str = dasctime ( fmt->f_comp->c_tws , TW_ZONE);
                    455:            break;
                    456:        case FT_LS_PRETTY:
                    457:            str = dasctime ( fmt->f_comp->c_tws, TW_NULL);
                    458:            break;
                    459: 
                    460:        case FT_LS_PERS:
                    461:            str = fmt->f_comp->c_mn->m_pers;
                    462:            break;
                    463:        case FT_LS_MBOX:
                    464:            str = fmt->f_comp->c_mn->m_mbox;
                    465:            break;
                    466:        case FT_LS_HOST:
                    467:            str = fmt->f_comp->c_mn->m_host;
                    468:            break;
                    469:        case FT_LS_PATH:
                    470:            str = fmt->f_comp->c_mn->m_path;
                    471:            break;
                    472:        case FT_LS_GNAME:
                    473:            str = fmt->f_comp->c_mn->m_gname;
                    474:            break;
                    475:        case FT_LS_NOTE:
                    476:            str = fmt->f_comp->c_mn->m_note;
                    477:            break;
                    478:        case FT_LS_822ADDR:
                    479:            str = adrformat( fmt->f_comp->c_mn );
                    480:            break;
                    481:        case FT_LV_HOSTTYPE:
                    482:            value = fmt->f_comp->c_mn->m_type;
                    483:            break;
                    484:        case FT_LV_INGRPF:
                    485:            value = fmt->f_comp->c_mn->m_ingrp;
                    486:            break;
                    487:        case FT_LV_NOHOSTF:
                    488:            value = fmt->f_comp->c_mn->m_nohost;
                    489:            break;
                    490:        case FT_LS_FRIENDLY:
                    491: #ifdef BERK
                    492:            str = fmt->f_comp->c_mn->m_mbox;
                    493: #else not BERK
                    494:            mn = fmt -> f_comp -> c_mn;
                    495:            if ((str = mn -> m_pers) == NULL)
                    496:                switch (mn -> m_type) {
                    497:                    case LOCALHOST:
                    498:                        str = mn -> m_mbox;
                    499:                        break;
                    500:                    case UUCPHOST:
                    501:                        (void) sprintf (buffer, "%s!%s",
                    502:                                        mn -> m_host, mn -> m_mbox);
                    503:                        str = buffer;
                    504:                        break;
                    505:                    default:
                    506:                        if (mn -> m_mbox) {
                    507:                            (void) sprintf (buffer, "%s@%s",
                    508:                                            mn -> m_mbox, mn -> m_host);
                    509:                            str= buffer;
                    510:                        }
                    511:                        else
                    512:                            str = mn -> m_text;
                    513:                        break;
                    514:                }
                    515: #endif BERK
                    516:            break;
                    517: 
                    518:        case FT_PARSEDATE:
                    519:            comp = fmt->f_comp;
                    520:            if ((sp = comp->c_text) && (tws = dparsetime(sp))) {
                    521:                *comp->c_tws = *tws;
                    522:                comp->c_flags = 0;
                    523:            } else if (comp->c_flags >= 0) {
                    524:                bzero ((char *) comp -> c_tws, sizeof *comp -> c_tws);
                    525:                comp->c_flags = 1;
                    526:            }
                    527:            break;
                    528: 
                    529:        case FT_FORMATADDR:
                    530:            /* hook for custom address list formatting (see replsbr.c) */
                    531:            str = formataddr (savestr, str);
                    532:            break;
                    533: 
                    534:        case FT_PUTADDR:
                    535:            /* output the str register as an address component,
                    536:             * splitting it into multiple lines if necessary.  The
                    537:             * value reg. contains the max line length.  The lit.
                    538:             * field may contain a string to prepend to the result
                    539:             * (e.g., "To: ")
                    540:             */
                    541:            {
                    542:            register char *lp = str;
                    543:            register int indent;
                    544:            register int wid = value;
                    545:            register int len = strlen (str);
                    546:            register char *lastb;
                    547: 
                    548:            sp = fmt->f_text;
                    549:            indent = strlen (sp);
                    550:            wid -= indent;
                    551:            while( (c = *sp++) && cp < ep)
                    552:                *cp++ = c;
                    553:            while (len > wid) {
                    554:                /* try to break at a comma; failing that, break at a
                    555:                 * space, failing that, just split the line.
                    556:                 */
                    557:                lastb = 0; sp = lp + wid;
                    558:                while (sp > lp && (c = *--sp) != ',') {
                    559:                    if (! lastb && isspace(c))
                    560:                        lastb = sp - 1;
                    561:                }
                    562:                if (sp == lp)
                    563:                    if (! (sp = lastb))
                    564:                        sp = lp + wid - 1;
                    565:                len -= sp - lp + 1;
                    566:                while (cp < ep && lp <= sp)
                    567:                    *cp++ = *lp++;
                    568:                *cp++ = '\n';
                    569:                for (i=indent; cp < ep && i > 0; i--)
                    570:                    *cp++ = ' ';
                    571:                while (isspace(*lp))
                    572:                    lp++, len--;
                    573:            }
                    574:            PUTS (cp, lp);
                    575:            }
                    576:            break;
                    577: 
                    578:        case FT_PARSEADDR:
                    579:            comp = fmt->f_comp;
                    580:            if (comp->c_mn != &fmt_mnull)
                    581:                mnfree (comp->c_mn);
                    582:            if ((sp = comp->c_text) && (sp = getname(sp)) &&
                    583:                (mn = getm (sp, NULLCP, 0, fmt_norm, NULLCP))) {
                    584:                comp->c_mn = mn;
                    585:                while (getname(""))
                    586:                    ;
                    587:            } else
                    588:                comp->c_mn = &fmt_mnull;
                    589:            break;
                    590:            
                    591:        case FT_MYMBOX:
                    592:            /*
                    593:             * if there's no component, we say true.  Otherwise we
                    594:             * say "true" only if we can parse the address and it
                    595:             * matches one of our addresses.
                    596:             */
                    597:            comp = fmt->f_comp;
                    598:            if (comp->c_mn != &fmt_mnull)
                    599:                mnfree (comp->c_mn);
                    600:            if ((sp = comp->c_text) && (sp = getname(sp)) &&
                    601:                (mn = getm (sp, NULLCP, 0, AD_NAME, NULLCP))) {
                    602:                comp->c_mn = mn;
                    603:                comp->c_flags = ismymbox(mn);
                    604:                while (getname(""))
                    605:                    ;
                    606:            } else {
                    607:                comp->c_flags = (comp->c_text == 0);
                    608:                comp->c_mn = &fmt_mnull;
                    609:            }
                    610:            break;
                    611:        }
                    612:        fmt++;
                    613:     }
                    614:     finished:;
                    615:     if (cp[-1] != '\n')
                    616:        *cp++ = '\n';
                    617:     *cp   = NULL;
                    618:     return (value);
                    619: }

unix.superglobalmegacorp.com

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