Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!seismo!ut-sally!husc6!linus!raybed2!rayssd!unisec!mark From: mark@unisec.USI.COM (Mark Rinfret) Newsgroups: comp.sys.amiga Subject: Text file tab utility Message-ID: <443@unisec.USI.COM> Date: Sun, 22-Mar-87 20:11:46 EST Article-I.D.: unisec.443 Posted: Sun Mar 22 20:11:46 1987 Date-Received: Tue, 24-Mar-87 01:59:17 EST Distribution: comp Organization: UniSecure Systems, Inc. Newport, R.I. Lines: 298 Keywords: entab detab sugar-free! In the past few months, I've used about 3.5 different editors (the .5 is for the ones I tried for a couple of days but gave up on quickly). First, there was Ed, next came MicroEmacs and now Z. I'll not attempt to justify my switching to Z, though it's the reason for this posting. In the course of all these changes, my "tabbing and indentation philosophy" (that sounds lofty!) has undergone severe trauma. With Ed, the default tab setting was 3 characters, but tab characters didn't actually get stored in the file. With MicroEmacs, the default was 8 but if you changed it, you got spaces (right?). Finally, I have Z which, for all its faults, allows me to set tabs where I want them (4) and stores true tab characters in the file. This should result in a significant reduction in the sizes of some of my sources, considering the 4:1 reduction of spaces to tabs. Unfortunately, most of my files are currently tabbed at 8 characters, with sprinklings of spaces for intervening indentations. If you find yourself in the same or similar situation, the following utility may be of use to you. This trivial offering simply expands an input file using its current tab setting (known by you, hopefully), reformatting the file with a new tab setting. It does nothing about C indentation - just plays with tabs. It is smart in a small way about not entabbing quoted strings. This is the first opportunity I've had to offer anything to this group, though I've taken much. It's one of those stupid little things that anyone can write if they need it bad enough - I did. I compiled this under Aztec C V3.4 but it's vanilla enough to port just about anywhere. Mark ========================================================================== /* :set ts=4 */ /* * Redefine tabs in a text file. * Mark Rinfret, 03/18/87 mark@unisec.USI.COM * Filename: retab.c * * Description: * This program inputs a text file with one tab width setting and * creates a new output file which has either a new tab setting or no * tabs. A few smarts have been included to avoid introducing tab * characters into quoted strings and character constants. This program * only supports tab settings which are an even multiple of a given value. * For instance, a tab width of 4 results in tab stops at columns * 5, 9, 13, etc. Minimum tab width is 3 columns, maximum is 32. * Examples: * * retab -i8 -o4 infile outfile * Converts infile, currently set at 8 column tabs to outfile which * will have 4 column tabs. * * retab -i8 -o0 -q infile outfile * Expands all tabs in infile and places the result in outfile, * suppressing statistical info. There will be no tab characters * in outfile. * * retab infile outfile * Converts infile, currently set at 4 column tabs, to outfile, which * will also have 4 column tabs. Used in this manner, a cleanup * function is provided, optimizing file size by replacing spaces * with tabs, where possible. * * The author releases this source to the public domain with no * restrictions which means that you can use, rewrite, redistribute, * sell or eat it. */ #include #include #define LINEMAX 255 /* max input line length */ #define MAXTAB 32 /* maximum tab width allowed */ #define MINTAB 3 /* minimum tab width allowed (except 0) */ #define TABIN 4 /* default input file tab setting */ #define TABOUT 4 /* default output file tab setting */ FILE *OpenFile(); FILE *infile,*outfile; /* input / output files */ char *iname, *oname; /* input / output file names */ char linebuf[LINEMAX+1]; /* line buffer */ unsigned intab = TABIN, outtab = TABOUT; unsigned incol, outcol; unsigned iccnt = 0, occnt = 0, ilcnt = 0, olcnt = 0; unsigned statistics = 1; main(argc,argv) int argc; char **argv; { char c,*arg; ++argv; /* skip program name */ while (--argc && **argv == '-') { arg = *argv; if ((c = *++arg) == 'i') { intab = atoi(++arg); cktab(intab); /* check tab value */ } else if (c == 'o') { outtab = atoi(++arg); cktab(outtab); } else if (c == 'q') /* quiet mode */ statistics = 0; else Usage(); /* bad option */ ++argv; /* point to next arg */ } if (argc < 2) Usage(); iname = argv[0]; oname = argv[1]; infile = OpenFile(iname,"r"); outfile = OpenFile(oname,"w"); retab(); stats(); } /* Perform the retabbing function. */ retab() { int c; unsigned endfile = 0; while(!endfile) { incol = 1; outcol = 0; while ((c = fgetc(infile)) != '\n') { if (c == EOF) { ++endfile; break; } ++iccnt; if (c == '\t') { /* input was a tab? */ do { putbuf(' '); } while (outcol % intab != 0); } else { putbuf(c); } } if (c == '\n') { ++iccnt; ++ilcnt; } else if (outcol) /* something on last line? */ ++ilcnt; linebuf[outcol] = '\0'; outline(); } } /* Put one character in the line buffer, testing for overflow and * maintaining the output column, outcol. */ putbuf(c) { if (outcol == LINEMAX) outline(); linebuf[outcol++] = c; } /* Output the current line. */ outline() { char c,*s; unsigned blanks = 0,escape = 0, i, j, outpos = 0, quote = 0; unsigned pass_through; s = linebuf; for (i = 0; i < outcol; ++i) { /* scan characters in buffer */ if (outtab) { /* entab output line? */ if (i % outtab == 0) { /* at a tab stop? */ if (blanks && !quote) { if (blanks > 1) { fputc('\t',outfile); ++occnt; outpos = i; } else { fputc(' ',outfile); ++occnt; ++outpos; } blanks = 0; } } pass_through = 0; /* allow blank checking */ c = *s++; /* get next character */ if (escape) { /* pass through as is */ escape = 0; ++pass_through; } else if (c == '"' || c == '\'') { /* quotes? */ if (quote) { if (quote == c) quote = 0; /* end of quote */ } else quote = c; ++pass_through; } else if (c == '\\') { /* character escape */ escape = 1; ++pass_through; } if (c == ' ' && !pass_through) ++blanks; else { blanks = 0; while (outpos < i) { fputc(' ',outfile); ++occnt; ++outpos; } fputc(c,outfile); ++occnt; ++outpos; } } else { fputc(*s++,outfile); ++occnt; } } fputc('\n',outfile); /* line terminator */ ++olcnt; /* count output lines */ } /* Display correct program usage. */ Usage() { printf( "Usage: retab [-i] [-o] [-q] \n\n"); printf( " is the tab value of the input file. If not given,\n"); printf("4 is assumed.\n"); printf( " is the new tab value for the output file. If not\n"); printf( "given, 4 is assumed. Zero is also legal, the net effect of which\n"); printf( "is to expand tabs in the input file to spaces.\n"); printf( "-q specifies quiet mode - no statistics will be output.\n"); exit(1); } /* Check tab value for allowable range */ cktab(val) unsigned val; { if (val && (val < MINTAB || val > MAXTAB)) { printf("Tab value must be in the range of %d..%d\n", MINTAB,MAXTAB); exit(1); } } FILE *OpenFile(name,how) char *name, *how; { FILE *fp; extern int errno; if ((fp = fopen(name,how)) == NULL) { printf("Can't open %s for %s access, errno is %d.\n",name,how,errno); exit(1); } return fp; } /* Report program statistics. */ stats() { char *format = " %s %-12s Tabs: %2d, %5u Characters, %5u Lines\n"; if (statistics) { printf("retab statistics:\n"); printf(format,"Input: ", iname, intab, iccnt, ilcnt); printf(format,"Output: ", oname, outtab, occnt, olcnt); } } -- | Mark R. Rinfret, SofTech, Inc. mark@unisec.usi.com | | Guest of UniSecure Systems, Inc., Newport, RI | | UUCP: {gatech|mirror|cbosgd|uiucdcs|ihnp4}!rayssd!unisec!mark | | work: (401)-849-4174 home: (401)-846-7639 |