# 2.11BSD#431 - /usr/src/ucb/Mail/fmt.c

##### Functions

    fmt               X
    ispref            X
    leadin            X
    main              X
    oflush            X
    pack              X
    prefix            X
    savestr           X
    setout            X
    split             X
    tabulate          X
    value             X

##### Variables

    copyright         X
    goal_length       X
    headnames         X
    lineno            X
    mark              X
    max_length        X
    outbuf            X
    outp              X
    pfx               X

##### Macros

    GOAL_LENGTH       X
    MAX_LENGTH        X
    NOSTR             X

       1: /*
       2:  * Copyright (c) 1980 Regents of the University of California.
       3:  * All rights reserved.
       4:  *
       5:  * Redistribution and use in source and binary forms are permitted
       6:  * provided that: (1) source distributions retain this entire copyright
       7:  * notice and comment, and (2) distributions including binaries display
       8:  * the following acknowledgement:  ``This product includes software
       9:  * developed by the University of California, Berkeley and its contributors''
      10:  * in the documentation or other materials provided with the distribution
      11:  * and in all advertising materials mentioning features or use of this
      12:  * software. Neither the name of the University nor the names of its
      13:  * contributors may be used to endorse or promote products derived
      14:  * from this software without specific prior written permission.
      15:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
      16:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
      17:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
      18:  */
      19:
      20: #if !defined(lint) && defined(DOSCCS)
      21: char copyright[] =
      22: "@(#) Copyright (c) 1980 Regents of the University of California.\n\
      23:  All rights reserved.\n";
      24: static char sccsid[] = "@(#)fmt.c	5.10 (Berkeley) 6/1/90";
      25: #endif
      26:
      27: #include <stdio.h>
      28: #include <ctype.h>
      29:
      30: /*
      31:  * fmt -- format the concatenation of input files or standard input
      32:  * onto standard output.  Designed for use with Mail ~|
      33:  *
      34:  * Syntax : fmt [ goal [ max ] ] [ name ... ]
      35:  * Authors: Kurt Shoens (UCB) 12/7/78;
      36:  *          Liz Allen (UMCP) 2/24/83 [Addition of goal length concept].
      37:  */
      38:
      39: /* LIZ@UOM 6/18/85 -- Don't need LENGTH any more.
      40:  * #define	LENGTH	72		Max line length in output
      41:  */
      42: #define NOSTR   ((char *) 0)    /* Null string pointer for lint */
      43:
      44: /* LIZ@UOM 6/18/85 --New variables goal_length and max_length */
      45: #define GOAL_LENGTH 65
      46: #define MAX_LENGTH 75
      47: int goal_length;        /* Target or goal line length in output */
      48: int max_length;     /* Max line length in output */
      49: int pfx;            /* Current leading blank count */
      50: int lineno;         /* Current input line */
      51: int mark;           /* Last place we saw a head line */
      52:
      53: char    *malloc();      /* for lint . . . */
      54: char    *headnames[] = {"To", "Subject", "Cc", 0};
      55:
      56: /* ARGSUSED */
      57: /* stub of routine to allow fail() to be used in head.c */
      58: value(var)
      59:     char    *var;
      60:     {
      61:     return(0);
      62:     }
      63:
      64: /*
      65:  * Drive the whole formatter by managing input files.  Also,
      66:  * cause initialization of the output stuff and flush it out
      67:  * at the end.
      68:  */
      69:
      70: main(argc, argv)
      71:     int argc;
      72:     char **argv;
      73: {
      74:     register FILE *fi;
      75:     register int errs = 0;
      76:     int number;     /* LIZ@UOM 6/18/85 */
      77:
      78:     goal_length = GOAL_LENGTH;
      79:     max_length = MAX_LENGTH;
      80:     setout();
      81:     lineno = 1;
      82:     mark = -10;
      83:     /*
      84: 	 * LIZ@UOM 6/18/85 -- Check for goal and max length arguments
      85: 	 */
      86:     if (argc > 1 && (1 == (sscanf(argv[1], "%d", &number)))) {
      87:         argv++;
      88:         argc--;
      89:         goal_length = number;
      90:         if (argc > 1 && (1 == (sscanf(argv[1], "%d", &number)))) {
      91:             argv++;
      92:             argc--;
      93:             max_length = number;
      94:         }
      95:     }
      96:     if (max_length <= goal_length) {
      97:         fprintf(stderr, "Max length must be greater than %s\n",
      98:             "goal length");
      99:         exit(1);
     100:     }
     101:     if (argc < 2) {
     102:         fmt(stdin);
     103:         oflush();
     104:         exit(0);
     105:     }
     106:     while (--argc) {
     107:         if ((fi = fopen(*++argv, "r")) == NULL) {
     108:             perror(*argv);
     109:             errs++;
     110:             continue;
     111:         }
     112:         fmt(fi);
     113:         fclose(fi);
     114:     }
     115:     oflush();
     116:     exit(errs);
     117: }
     118:
     119: /*
     120:  * Read up characters from the passed input file, forming lines,
     121:  * doing ^H processing, expanding tabs, stripping trailing blanks,
     122:  * and sending each line down for analysis.
     123:  */
     124: fmt(fi)
     125:     FILE *fi;
     126: {
     127:     char linebuf[BUFSIZ], canonb[BUFSIZ];
     128:     register char *cp, *cp2;
     129:     register int c, col;
     130:
     131:     c = getc(fi);
     132:     while (c != EOF) {
     133:         /*
     134: 		 * Collect a line, doing ^H processing.
     135: 		 * Leave tabs for now.
     136: 		 */
     137:         cp = linebuf;
     138:         while (c != '\n' && c != EOF && cp-linebuf < BUFSIZ-1) {
     139:             if (c == '\b') {
     140:                 if (cp > linebuf)
     141:                     cp--;
     142:                 c = getc(fi);
     143:                 continue;
     144:             }
     145:             if ((c < ' ' || c >= 0177) && c != '\t') {
     146:                 c = getc(fi);
     147:                 continue;
     148:             }
     149:             *cp++ = c;
     150:             c = getc(fi);
     151:         }
     152:         *cp = '\0';
     153:
     154:         /*
     155: 		 * Toss anything remaining on the input line.
     156: 		 */
     157:         while (c != '\n' && c != EOF)
     158:             c = getc(fi);
     159:
     160:         /*
     161: 		 * Expand tabs on the way to canonb.
     162: 		 */
     163:         col = 0;
     164:         cp = linebuf;
     165:         cp2 = canonb;
     166:         while (c = *cp++) {
     167:             if (c != '\t') {
     168:                 col++;
     169:                 if (cp2-canonb < BUFSIZ-1)
     170:                     *cp2++ = c;
     171:                 continue;
     172:             }
     173:             do {
     174:                 if (cp2-canonb < BUFSIZ-1)
     175:                     *cp2++ = ' ';
     176:                 col++;
     177:             } while ((col & 07) != 0);
     178:         }
     179:
     180:         /*
     181: 		 * Swipe trailing blanks from the line.
     182: 		 */
     183:         for (cp2--; cp2 >= canonb && *cp2 == ' '; cp2--)
     184:             ;
     185:         *++cp2 = '\0';
     186:         prefix(canonb);
     187:         if (c != EOF)
     188:             c = getc(fi);
     189:     }
     190: }
     191:
     192: /*
     193:  * Take a line devoid of tabs and other garbage and determine its
     194:  * blank prefix.  If the indent changes, call for a linebreak.
     195:  * If the input line is blank, echo the blank line on the output.
     196:  * Finally, if the line minus the prefix is a mail header, try to keep
     197:  * it on a line by itself.
     198:  */
     199: prefix(line)
     200:     char line[];
     201: {
     202:     register char *cp, **hp;
     203:     register int np, h;
     204:
     205:     if (strlen(line) == 0) {
     206:         oflush();
     207:         putchar('\n');
     208:         return;
     209:     }
     210:     for (cp = line; *cp == ' '; cp++)
     211:         ;
     212:     np = cp - line;
     213:
     214:     /*
     215: 	 * The following horrible expression attempts to avoid linebreaks
     216: 	 * when the indent changes due to a paragraph.
     217: 	 */
     218:     if (np != pfx && (np > pfx || abs(pfx-np) > 8))
     219:         oflush();
     220:     if (h = ishead(cp))
     221:         oflush(), mark = lineno;
     222:     if (lineno - mark < 3 && lineno - mark > 0)
     223:         for (hp = &headnames[0]; *hp != (char *) 0; hp++)
     224:             if (ispref(*hp, cp)) {
     225:                 h = 1;
     226:                 oflush();
     227:                 break;
     228:             }
     229:     if (!h && (h = (*cp == '.')))
     230:         oflush();
     231:     pfx = np;
     232:     if (h)
     233:         pack(cp);
     234:     else    split(cp);
     235:     if (h)
     236:         oflush();
     237:     lineno++;
     238: }
     239:
     240: /*
     241:  * Split up the passed line into output "words" which are
     242:  * maximal strings of non-blanks with the blank separation
     243:  * attached at the end.  Pass these words along to the output
     244:  * line packer.
     245:  */
     246: split(line)
     247:     char line[];
     248: {
     249:     register char *cp, *cp2;
     250:     char word[BUFSIZ];
     251:     int wordl;      /* LIZ@UOM 6/18/85 */
     252:
     253:     cp = line;
     254:     while (*cp) {
     255:         cp2 = word;
     256:         wordl = 0;  /* LIZ@UOM 6/18/85 */
     257:
     258:         /*
     259: 		 * Collect a 'word,' allowing it to contain escaped white
     260: 		 * space.
     261: 		 */
     262:         while (*cp && *cp != ' ') {
     263:             if (*cp == '\\' && isspace(cp[1]))
     264:                 *cp2++ = *cp++;
     265:             *cp2++ = *cp++;
     266:             wordl++;/* LIZ@UOM 6/18/85 */
     267:         }
     268:
     269:         /*
     270: 		 * Guarantee a space at end of line. Two spaces after end of
     271: 		 * sentence punctuation.
     272: 		 */
     273:         if (*cp == '\0') {
     274:             *cp2++ = ' ';
     275:             if (index(".:!", cp[-1]))
     276:                 *cp2++ = ' ';
     277:         }
     278:         while (*cp == ' ')
     279:             *cp2++ = *cp++;
     280:         *cp2 = '\0';
     281:         /*
     282: 		 * LIZ@UOM 6/18/85 pack(word);
     283: 		 */
     284:         pack(word, wordl);
     285:     }
     286: }
     287:
     288: /*
     289:  * Output section.
     290:  * Build up line images from the words passed in.  Prefix
     291:  * each line with correct number of blanks.  The buffer "outbuf"
     292:  * contains the current partial line image, including prefixed blanks.
     293:  * "outp" points to the next available space therein.  When outp is NOSTR,
     294:  * there ain't nothing in there yet.  At the bottom of this whole mess,
     295:  * leading tabs are reinserted.
     296:  */
     297: char    outbuf[BUFSIZ];         /* Sandbagged output line image */
     298: char    *outp;              /* Pointer in above */
     299:
     300: /*
     301:  * Initialize the output section.
     302:  */
     303: setout()
     304: {
     305:     outp = NOSTR;
     306: }
     307:
     308: /*
     309:  * Pack a word onto the output line.  If this is the beginning of
     310:  * the line, push on the appropriately-sized string of blanks first.
     311:  * If the word won't fit on the current line, flush and begin a new
     312:  * line.  If the word is too long to fit all by itself on a line,
     313:  * just give it its own and hope for the best.
     314:  *
     315:  * LIZ@UOM 6/18/85 -- If the new word will fit in at less than the
     316:  *	goal length, take it.  If not, then check to see if the line
     317:  *	will be over the max length; if so put the word on the next
     318:  *	line.  If not, check to see if the line will be closer to the
     319:  *	goal length with or without the word and take it or put it on
     320:  *	the next line accordingly.
     321:  */
     322:
     323: /*
     324:  * LIZ@UOM 6/18/85 -- pass in the length of the word as well
     325:  * pack(word)
     326:  *	char word[];
     327:  */
     328: pack(word,wl)
     329:     char word[];
     330:     int wl;
     331: {
     332:     register char *cp;
     333:     register int s, t;
     334:
     335:     if (outp == NOSTR)
     336:         leadin();
     337:     /*
     338: 	 * LIZ@UOM 6/18/85 -- change condition to check goal_length; s is the
     339: 	 * length of the line before the word is added; t is now the length
     340: 	 * of the line after the word is added
     341: 	 *	t = strlen(word);
     342: 	 *	if (t+s <= LENGTH)
     343: 	 */
     344:     s = outp - outbuf;
     345:     t = wl + s;
     346:     if ((t <= goal_length) ||
     347:         ((t <= max_length) && (t - goal_length <= goal_length - s))) {
     348:         /*
     349: 		 * In like flint!
     350: 		 */
     351:         for (cp = word; *cp; *outp++ = *cp++);
     352:         return;
     353:     }
     354:     if (s > pfx) {
     355:         oflush();
     356:         leadin();
     357:     }
     358:     for (cp = word; *cp; *outp++ = *cp++);
     359: }
     360:
     361: /*
     362:  * If there is anything on the current output line, send it on
     363:  * its way.  Set outp to NOSTR to indicate the absence of the current
     364:  * line prefix.
     365:  */
     366: oflush()
     367: {
     368:     if (outp == NOSTR)
     369:         return;
     370:     *outp = '\0';
     371:     tabulate(outbuf);
     372:     outp = NOSTR;
     373: }
     374:
     375: /*
     376:  * Take the passed line buffer, insert leading tabs where possible, and
     377:  * output on standard output (finally).
     378:  */
     379: tabulate(line)
     380:     char line[];
     381: {
     382:     register char *cp;
     383:     register int b, t;
     384:
     385:     /*
     386: 	 * Toss trailing blanks in the output line.
     387: 	 */
     388:     cp = line + strlen(line) - 1;
     389:     while (cp >= line && *cp == ' ')
     390:         cp--;
     391:     *++cp = '\0';
     392:
     393:     /*
     394: 	 * Count the leading blank space and tabulate.
     395: 	 */
     396:     for (cp = line; *cp == ' '; cp++)
     397:         ;
     398:     b = cp-line;
     399:     t = b >> 3;
     400:     b &= 07;
     401:     if (t > 0)
     402:         do
     403:             putc('\t', stdout);
     404:         while (--t);
     405:     if (b > 0)
     406:         do
     407:             putc(' ', stdout);
     408:         while (--b);
     409:     while (*cp)
     410:         putc(*cp++, stdout);
     411:     putc('\n', stdout);
     412: }
     413:
     414: /*
     415:  * Initialize the output line with the appropriate number of
     416:  * leading blanks.
     417:  */
     418: leadin()
     419: {
     420:     register int b;
     421:     register char *cp;
     422:
     423:     for (b = 0, cp = outbuf; b < pfx; b++)
     424:         *cp++ = ' ';
     425:     outp = cp;
     426: }
     427:
     428: /*
     429:  * Save a string in dynamic space.
     430:  * This little goodie is needed for
     431:  * a headline detector in head.c
     432:  */
     433: char *
     434: savestr(str)
     435:     char str[];
     436: {
     437:     register char *top;
     438:
     439:     top = malloc(strlen(str) + 1);
     440:     if (top == NOSTR) {
     441:         fprintf(stderr, "fmt:  Ran out of memory\n");
     442:         exit(1);
     443:     }
     444:     strcpy(top, str);
     445:     return (top);
     446: }
     447:
     448: /*
     449:  * Is s1 a prefix of s2??
     450:  */
     451: ispref(s1, s2)
     452:     register char *s1, *s2;
     453: {
     454:
     455:     while (*s1++ == *s2)
     456:         ;
     457:     return (*s1 == '\0');
     458: }

#### Defined functions

fmt defined in line 124; used 2 times

- in line 102, 112

ispref defined in line 451; used 1 times

- in line 224

leadin defined in line 418; used 2 times

- in line 336, 356

main defined in line 70; never used
oflush defined in line 366; used 9 times

- in line 103, 115, 206, 219-230(4), 236, 355

pack defined in line 328; used 2 times

- in line 233, 284

prefix defined in line 199; used 1 times

- in line 186

savestr defined in line 433; used 15 times

- in /usr/src/ucb/Mail/collect.c line 240
- in /usr/src/ucb/Mail/def.h line 302
- in /usr/src/ucb/Mail/fio.c line 316, 324, 332-337(2), 381
- in /usr/src/ucb/Mail/list.c line 209, 461, 597
- in /usr/src/ucb/Mail/names.c line 61
- in /usr/src/ucb/Mail/temp.c line 85-89(2)
- in /usr/src/ucb/Mail/tty.c line 216, 245

setout defined in line 303; used 1 times

- in line 80

split defined in line 246; used 1 times

- in line 234

tabulate defined in line 379; used 1 times

- in line 371

value defined in line 58; never used

#### Defined variables

copyright defined in line 21; never used
goal_length defined in line 47; used 6 times

- in line 78, 89, 96, 346-347(3)

headnames defined in line 54; used 1 times

- in line 223

lineno defined in line 50; used 5 times

- in line 81, 221-222(3), 237

mark defined in line 51; used 4 times

- in line 82, 221-222(3)

max_length defined in line 48; used 4 times

- in line 79, 93-96(2), 347

outbuf defined in line 297; used 3 times

- in line 344, 371, 423

outp defined in line 298; used 9 times

- in line 305, 335, 344, 351, 358, 368-372(3), 425

pfx defined in line 49; used 6 times

- in line 218(3), 231, 354, 423

sccsid defined in line 24; never used

#### Defined macros

GOAL_LENGTH defined in line 45; used 1 times

- in line 78

MAX_LENGTH defined in line 46; used 1 times

- in line 79

NOSTR defined in line 42; used 5 times

- in line 305, 335, 368-372(2), 440

Last modified: 1992-10-27 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 978 |