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: }

Defined functions

fmtscan defined in line 196; never used
match defined in line 102; used 2 times
new_fs defined in line 29; never used
normalize defined in line 66; used 1 times
  • in line 59

Defined variables

fmt_mnull defined in line 23; used 7 times
fmt_norm defined in line 22; used 1 times
formats defined in line 19; used 7 times
lmonth defined in line 191; used 1 times

Defined macros

NFMTS defined in line 16; never used
PUTD defined in line 143; used 1 times
PUTDF defined in line 128; used 1 times
PUTS defined in line 175; used 3 times
PUTSF defined in line 158; used 2 times
QUOTE defined in line 17; used 1 times
  • in line 72
grot defined in line 76; used 5 times
Last modified: 1986-04-22
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1958
Valid CSS Valid XHTML 1.0 Strict