home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / k95source / trim.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  5KB  |  208 lines

  1. /*  T R I M -- Trim trailing whitespace from file lines and/or untabify  */
  2.  
  3. /*
  4.   Author:      F. da Cruz, The Kermit Project, Columbia University
  5.   Email:       fdc@columbia.edu
  6.   Portability: Should be portable to most UNIXes and maybe VMS.
  7.  
  8.   Please send any changes back to the author.
  9.  
  10.   Copyright (C) 1999
  11.   Trustees of Columbia University in the City of New York
  12.  
  13.   This program is free software; you can redistribute it and/or modify
  14.   it under the terms of the GNU General Public License as published by
  15.   the Free Software Foundation; either version 2 of the License, or
  16.   (at your option) any later version.
  17.  
  18.   This program is distributed in the hope that it will be useful,
  19.   but WITHOUT ANY WARRANTY; without even the implied warranty of
  20.   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21.   GNU General Public License for more details.
  22.  
  23.   You should have received a copy of the GNU General Public License
  24.   along with this program; if not, write to the Free Software
  25.   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  26. */
  27. #include <stdio.h>
  28. #include <ctype.h>
  29. #include <sys/stat.h>
  30.  
  31. #ifndef S_ISREG
  32. #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
  33. #endif /* S_ISREG */
  34. #define MAX 32767
  35.  
  36. char buf[MAX];                /* I/O buffers */
  37. char obuf[MAX];
  38. char tmpname[256];            /* Filename buffers */
  39. char tmp2[256];
  40. FILE *fp, *op, *fopen();        /* Streams */
  41. int n = 0;                /* File counter */
  42. int warn = 0;                /* Warn-only flag */
  43. int untab = 0;                /* Untabify flag */
  44. int changed = 0;            /* Flag for file changed */
  45. struct stat statbuf;            /* For stat() */
  46.  
  47. char * hlptxt[] = {
  48.     "Usage: trim [ -w -t -h ] [ file [ file [ file ... ] ] ]",
  49.     " ",
  50.     "Trims trailing whitespace from lines in given file(s), replacing each",
  51.     "file with a trimmed version and renaming the original to *.untrimmed.",
  52.     "If no files are specified on the command line, operates on stdin and",
  53.     "writes to stdout.",
  54.     " ",
  55.     "  -t = also untabify (convert tabs to spaces)",
  56.     "  -w = warn only, don't change the files.",
  57.     "  -h = print this message",
  58.     " ",
  59.     "-w lists both lines with trailing whitespace and lines that would be",
  60.     "longer than 80 characters after tab expansion.  Tab settings are assumed",
  61.     "to be every 8 spaces",
  62.     "",
  63. };
  64.  
  65. usage(x) int x; {            /* Usage function */
  66.     int i;                /* Print usage message and exit */
  67.     for (i = 0; *hlptxt[i]; i++)
  68.       fprintf(stderr,"%s\n",hlptxt[i]);
  69.     exit(x);
  70. }
  71.  
  72. main(argc,argv) int argc; char *argv[]; { /* Main program */
  73.     int i;                /* Declare local variables */
  74.     int result;
  75.  
  76.     for (i = 1; i < argc; i++) {    /* For each argument... */
  77.     changed = 0;
  78.     if (n == 0 && *argv[i] == '-') { /* First do any options */
  79.         switch (*(argv[i]+1)) {
  80.           case 't':
  81.         untab = 1;
  82.         continue;
  83.           case 'w':
  84.         warn = 1;
  85.         continue;
  86.           case 'h':
  87.         usage(0);
  88.           default:
  89.         usage(1);
  90.         }
  91.         continue;
  92.     }
  93.     fprintf(stderr,"%3d. %s...",n,argv[i]);    /* Got a file */
  94.     if (stat(argv[i],&statbuf) < 0) {
  95.         printf("(skipped - stat error)\n");
  96.         continue;
  97.     }
  98.     if (!S_ISREG(statbuf.st_mode)) {
  99.         fprintf(stderr,"(skipped - not regular file)\n");
  100.         continue;
  101.     }
  102.     fp = fopen(argv[i], "r");    /* Try to open it */
  103.     if (fp == NULL) {        /* Check for errors */
  104.         perror(argv[i]);
  105.         continue;
  106.     }
  107.     n++;
  108.     result = process();
  109.     if (result < 0) continue;    /* "Process" the file */
  110.     if (fclose(fp) == EOF) {    /* Close the file */
  111.         perror(argv[i]);
  112.         continue;
  113.     }
  114.     if (!warn && changed) {
  115.         sprintf(tmp2,"%s.untrimmed",argv[i]);
  116.         if (rename(argv[i],tmp2) < 0) {
  117.         perror("rename");
  118.         exit(1);
  119.         }
  120.         if (rename(tmpname,argv[i]) < 0) {
  121.         perror("rename");
  122.         exit(1);
  123.         } else
  124.           fprintf(stderr,"(replaced OK)\n");
  125.     } else
  126.       if (result == 0)
  127.         fprintf(stderr,"(OK)\n");
  128.     }
  129.     if (n == 0) {            /* No files given - use stdio */
  130.     fp = stdin;
  131.     result = process();
  132.     }
  133.     exit(result == 0 ? 0 : 1);
  134. }
  135.  
  136. int
  137. process() {                /* Process the file */
  138.     int i, j, k, x, flag, bads = 0;
  139.     char * p;
  140.     long line = 0L;
  141.     if (!warn) {
  142.     sprintf(tmpname,"...tmp%03d",n);
  143.     if (fp == stdin)
  144.       op = stdout;
  145.     else
  146.       op = fopen(tmpname,"w");
  147.     if (op == NULL) { perror("fopen tmp file"); exit(1); }
  148.     }
  149.     while (fgets(buf, MAX, fp)) {
  150.     line++;
  151.     flag = 0;
  152.     x = strlen(buf) - 1;
  153.     while (buf[x] == '\n' || buf[x] == '\r') /* Trim trailing whitespace */
  154.       buf[x--] = 0;
  155.     while (buf[x] == ' ' || buf[x] == '\t') {
  156.         changed++;
  157.         flag = 1;
  158.         if (warn) break;
  159.         buf[x--] = 0;
  160.     }
  161.     if (warn) {
  162.         if (flag) {
  163.         bads++;
  164.         if (bads == 1) printf("\n");
  165.         fprintf(stderr,"TRAILING: %4ld. [%s\]\n",line,buf);
  166.         }
  167.     }
  168.     p = buf;
  169.     if (warn || untab) {        /* Expand tabs / check line length */
  170.         int z;
  171.         p = obuf;
  172.         x = strlen(buf);
  173.         for (i = 0, k = 0; k < x; k++) {
  174.         if (buf[k] != '\t') {
  175.             if (i >= MAX) {
  176.             printf("Overflow: %d\n", i);
  177.             exit(1);
  178.             }
  179.             obuf[i++] = buf[k];
  180.             continue;
  181.         }
  182.         changed++;
  183.         z = 8 - i%8;
  184.         if (z == 0) z = 8;
  185.         for (j = 0; j < z && i < MAX; j++)
  186.           obuf[i++] = ' ';
  187.         }
  188.         obuf[i] = 0;
  189.         if (i > 79) {
  190.         bads++;
  191.         if (bads == 1) printf("\n");
  192.         if (warn) {
  193.             obuf[58] = '.';
  194.             obuf[59] = '.';
  195.             obuf[60] = '.';
  196.             obuf[61] = 0;
  197.         }
  198.         fprintf(stderr,"LONGLINE: %4ld. [%s]\n",line,obuf);
  199.         }
  200.     }
  201.     if (!warn)
  202.       fprintf(op,"%s\n",p);
  203.     }
  204.     if (!warn)
  205.       fclose(op);
  206.     return(bads);
  207. }
  208.