Annotation of coherent/g/usr/bin/vi/qiot, revision 1.1
1.1 ! root 1: fmt.c 000644 000003 000003 00000011727 05225061120 011411 0 ustar 00bin bin 000377 000377 /* fmt.c */
! 2:
! 3: /* usage: fmt [-width] [files]...
! 4: *
! 5: * Fmt rearrages text in order to make each line have roughly the
! 6: * same width. Indentation and word spacing is preserved.
! 7: *
! 8: * The default width is 72 characters, but you can override that via -width.
! 9: * If no files are given on the command line, then it reads stdin.
! 10: */
! 11:
! 12: #include <stdio.h>
! 13: #include <ctype.h>
! 14:
! 15: #ifndef TRUE
! 16: # define TRUE 1
! 17: # define FALSE 0
! 18: #endif
! 19:
! 20:
! 21:
! 22: int width = 72; /* the desired line width */
! 23: int isblank; /* is the current output line blank? */
! 24: int indent; /* width of the indentation */
! 25: char ind[512]; /* indentation text */
! 26: char word[1024]; /* word buffer */
! 27:
! 28: /* This function displays a usage message and quits */
! 29: void usage()
! 30: {
! 31: fprintf(stderr, "usage: fmt [-width] [files]...\n");
! 32: exit(2);
! 33: }
! 34:
! 35:
! 36:
! 37: /* This function outputs a single word. It takes care of spacing and the
! 38: * newlines within a paragraph.
! 39: */
! 40: void putword()
! 41: {
! 42: int i; /* index into word[], or whatever */
! 43: int ww; /* width of the word */
! 44: int sw; /* width of spacing after word */
! 45: static int psw; /* space width of previous word */
! 46: static int tab; /* the width of text already written */
! 47:
! 48:
! 49: /* separate the word and its spacing */
! 50: for (ww = 0; word[ww] && !isspace(word[ww]); ww++)
! 51: {
! 52: }
! 53: sw = strlen(word) - ww;
! 54: word[ww] = '\0';
! 55:
! 56: /* if no spacing (that is, the word was at the end of the line) then
! 57: * assume 1 space unless the last char of the word was punctuation
! 58: */
! 59: if (sw == 0)
! 60: {
! 61: sw = 1;
! 62: if (word[ww - 1] == '.' || word[ww - 1] == '?' || word[ww - 1] == '!')
! 63: sw = 2;
! 64: }
! 65:
! 66: /* if this is the first word on the line... */
! 67: if (isblank)
! 68: {
! 69: /* output the indentation first */
! 70: fputs(ind, stdout);
! 71: tab = indent;
! 72: }
! 73: else /* text has already been written to this output line */
! 74: {
! 75: /* will the word fit on this line? */
! 76: if (psw + ww + tab <= width)
! 77: {
! 78: /* yes - so write the previous word's spacing */
! 79: for (i = 0; i < psw; i++)
! 80: {
! 81: putchar(' ');
! 82: }
! 83: tab += psw;
! 84: }
! 85: else
! 86: {
! 87: /* no, so write a newline and the indentation */
! 88: putchar('\n');
! 89: fputs(ind, stdout);
! 90: tab = indent;
! 91: }
! 92: }
! 93:
! 94: /* write the word itself */
! 95: fputs(word, stdout);
! 96: tab += ww;
! 97:
! 98: /* remember this word's spacing */
! 99: psw = sw;
! 100:
! 101: /* this output line isn't blank anymore. */
! 102: isblank = FALSE;
! 103: }
! 104:
! 105:
! 106:
! 107: /* This function reformats text. */
! 108: void fmt(in)
! 109: FILE *in; /* the input stream */
! 110: {
! 111: int ch; /* character from input stream */
! 112: int prevch; /* the previous character in the loop */
! 113: int i; /* index into ind[] or word[] */
! 114: int inword; /* boolean: are we between indent & newline? */
! 115:
! 116:
! 117: /* for each character in the stream... */
! 118: for (indent = -1, isblank = TRUE, inword = FALSE, i = 0, prevch = '\n';
! 119: (ch = getc(in)) != EOF;
! 120: prevch = ch)
! 121: {
! 122: /* is this the end of a line? */
! 123: if (ch == '\n')
! 124: {
! 125: /* if end of last word in the input line */
! 126: if (inword)
! 127: {
! 128: /* if it really is a word */
! 129: if (i > 0)
! 130: {
! 131: /* output it */
! 132: word[i] = '\0';
! 133: putword();
! 134: }
! 135: }
! 136: else /* blank line in input */
! 137: {
! 138: /* finish the previous paragraph */
! 139: if (!isblank)
! 140: {
! 141: putchar('\n');
! 142: isblank = TRUE;
! 143: }
! 144:
! 145: /* output a blank line */
! 146: putchar('\n');
! 147: }
! 148:
! 149: /* continue with next input line... */
! 150: indent = -1;
! 151: i = 0;
! 152: inword = FALSE;
! 153: continue;
! 154: }
! 155:
! 156: /* if we're expecting indentation now... */
! 157: if (indent < 0)
! 158: {
! 159: /* if this is part of the indentation... */
! 160: if (isspace(ch))
! 161: {
! 162: /* remember it */
! 163: ind[i++] = ch;
! 164: }
! 165: else /* end of indentation */
! 166: {
! 167: /* mark the end of the indentation string */
! 168: ind[i] = '\0';
! 169:
! 170: /* calculate the width of the indentation */
! 171: for (i = indent = 0; ind[i]; i++)
! 172: {
! 173: if (ind[i] == '\t')
! 174: indent = (indent | 7) + 1;
! 175: else
! 176: indent++;
! 177: }
! 178:
! 179: /* reset the word index */
! 180: i = 0;
! 181:
! 182: /* reprocess that last character */
! 183: ungetc(ch, in);
! 184: }
! 185:
! 186: /* continue in the for-loop */
! 187: continue;
! 188: }
! 189:
! 190: /* if we get here, we're either in a word or in the space
! 191: * after a word.
! 192: */
! 193: inword = TRUE;
! 194:
! 195: /* is this the start of a new word? */
! 196: if (!isspace(ch) && isspace(prevch))
! 197: {
! 198: /* yes! output the previous word */
! 199: word[i] = '\0';
! 200: putword();
! 201:
! 202: /* reset `i' to the start of the word[] buffer */
! 203: i = 0;
! 204: }
! 205: word[i++] = ch;
! 206: }
! 207:
! 208: /* if necessary, write a final newline */
! 209: if (!isblank)
! 210: {
! 211: putchar('\n');
! 212: isblank = TRUE;
! 213: }
! 214: }
! 215:
! 216:
! 217:
! 218:
! 219:
! 220: int main(argc, argv)
! 221: int argc;
! 222: char **argv;
! 223: {
! 224: FILE *in; /* an input stream */
! 225: int error; /* if non-zero, then an error occurred */
! 226: int i;
! 227:
! 228:
! 229: /* handle the -width flag, if given */
! 230: if (argc > 1 && argv[1][0] == '-')
! 231: {
! 232: width = atoi(argv[1] + 1);
! 233: if (width <= 0)
! 234: {
! 235: usage();
! 236: }
! 237: argc--;
! 238: argv++;
! 239: }
! 240:
! 241: /* if no filenames given, then process stdin */
! 242: if (argc == 1)
! 243: {
! 244: fmt(stdin);
! 245: }
! 246: else /* one or more filenames given */
! 247: {
! 248: for (error = 0, i = 1; i < argc; i++)
! 249: {
! 250: in = fopen(argv[i], "r");
! 251: if (!in)
! 252: {
! 253: perror(argv[i]);
! 254: error = 3;
! 255: }
! 256: else
! 257: {
! 258: fmt(in);
! 259: fclose(in);
! 260: }
! 261: }
! 262: }
! 263:
! 264: /* exit, possibly indicating an error */
! 265: exit(error);
! 266: /*NOTREACHED*/
! 267: }
! 268: