home *** CD-ROM | disk | FTP | other *** search
- /*
- * cut.c - a unix like filter
- *
- * Author: M. Steven Baker
- * Last Revision: October 17, 1988
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include <string.h>
-
- #ifndef FILENAME_MAX
- #define FILENAME_MAX 68
- #endif
-
- FILE *infp;
- FILE *outfp = stdout; /* our file pointers */
-
- char infile[FILENAME_MAX] = ""; /* our file names */
- char outfile[FILENAME_MAX] = "";
-
- int verbose = 0;
- int errflag = 0;
-
- char delim = '\t'; /* default delimiter character */
- int fieldflag = 0; /* logical flag for field delimited cut */
- int colflag = 0; /* logical flag fro column oriented cut */
- int sflag = 0; /* the cut -s flag -- not implemented yet */
-
- char *pgm = "cut"; /* our program name */
-
- #define MAXLINE 8192
-
- char map[MAXLINE+2]; /* our field map array */
- char line [MAXLINE+2]; /* our fgets() line buffer */
-
- void usage();
-
- char *help_msg[] = {
- "CUT various columns or fields from an ascii text file.",
- "The following options may be used singly or in combination:",
- "-c columns \t cut columns (ie 1,2,5,7-20)",
- "-d delimiter \t field delimiter character (default = tab)",
- "-f fields \t cut fields (ie 1,2,5,12-30)",
- "-o filename\t create output text file (default stdout)",
- /* "-s \t\t don't copy lines without delimiters" , */
- "-v\t\t verbose mode"
- };
-
- main(argc,argv)
- int argc;
- char **argv;
- {
- int ch; /* variable for getopt */
- int i;
-
- extern int getopt();
- extern char *optarg;
- extern int optind, opterr;
-
- for (i = 0; i < MAXLINE; i++) map[i] = 0; /* zero map array */
-
- /* process command-line arguments */
- opterr = 0; /* first turn off error messages from getopt */
- while ((ch = getopt(argc,argv, "vsc:d:f:o:")) != EOF)
- {
- switch (ch) {
- case 'c':
- colflag = 1;
- if (setfields(optarg) == EOF) {
- errflag++;
- if (verbose)
- fprintf(stderr,"%s: Error setting columns to cut\n",pgm);
- }
- break;
- case 'd':
- delim = *optarg;
- break;
- case 'f':
- fieldflag = 1;
- if (setfields(optarg) == EOF) {
- errflag++;
- if (verbose)
- fprintf(stderr,"%s: Error setting fields to cut\n",pgm);
- }
- break;
- case 'v':
- verbose = 1;
- break;
- case 'o': /* output specifed cut text file */
- strcpy(outfile, optarg);
- outfp = NULL;
- break;
- case 's': /* not implemented */
- sflag = 1;
- break;
- default: /* unknown option */
- errflag++;
- break;
- }
- }
- if (colflag && fieldflag) errflag++; /* can't have both options */
-
- if (errflag || !(argc-optind) ) {
- usage(pgm);
- exit(1);
- }
- if ( dofiles(argc - optind, argv += optind) ) /* did we have errors? */
- exit (1);
-
- exit(0);
- }
-
- /*
- * dofiles - process each filename or standard input
- */
-
- int dofiles(ac, av)
- int ac;
- char **av;
- {
- int ch, errcount = 0;
- char *p;
-
- for (; ac > 0; --ac, ++av) {
- p = *av;
- strcpy(infile,p); /* store binary data filename */
- if ((infp = fopen (infile,"rt")) == NULL) {
- fprintf(stderr,"%s: ERROR opening input file: %s\n",
- pgm,infile);
- continue;
- }
- if (outfp != stdout) {
- if ((outfp = fopen (outfile,"wt")) == NULL) {
- fprintf(stderr,"%s: ERROR opening output file: %s\n",pgm,outfile);
- fclose (infp);
- continue;
- }
- }
- if (cut(infp,outfp)== EOF) {
- fprintf(stderr,"%s: Error converting file: %s\n",pgm,infile);
- fclose(infp);
- fclose(outfp);
- errcount++;
- continue;
- }
- fclose(infp);
- if (fclose(outfp) == EOF) {
- fprintf(stderr,"%s: Error closing output file: %s\n",pgm,outfile);
- errcount++;
- continue;
- }
- } /* end of for loop */
- return (errcount);
- }
-
- /*
- * do the actual cut
- */
-
- cut(fp1,fp2)
- FILE *fp1, *fp2;
- {
- int i;
- char c;
- char *p;
-
- while ((p = fgets(line, MAXLINE+2, fp1)) != NULL) {
- i = 0;
- for (c = *p; *p; c = *++p) {
- if (fieldflag) {
- if (map[i] || c == '\n') fputc(c,fp2);
- if (c == delim) i++;
- }
- else {
- if (colflag) {
- if (map[i++] || c == '\n') fputc(c,fp2);
- }
- else fputc(c,fp2);
- }
- }
- }
- return (0);
- }
-
- #define BEGIN 0
- #define NUMBER 1
- #define COMMA 2
- #define RANGE 3
-
- /*
- * setfields - set fields to cut from command line
- */
-
- int setfields(optarg)
- char *optarg;
- {
- int i, last, state;
- char c;
- char *p;
-
- i = last = state = BEGIN;
- p = optarg;
-
- if ((c =*p) == '\0') return (EOF);
-
- while ((c = *p) && i < MAXLINE) {
- switch (state) {
- case BEGIN:
- i =stoi(&p); /* now pointing to next char */
- if (i > 0 && i < MAXLINE) {
- last = i;
- map[i-1] =1;
- state = NUMBER;
- }
- else return (EOF);
- break;
- case NUMBER: /* a number was last */
- if ( c == '-')
- state = RANGE;
- else {
- if (c == ',') state = COMMA;
- else return (EOF);
- }
- p++; /* increment pointer */
- break;
- case COMMA:
- if (isdigit(c)) {
- i = stoi(&p); /* stoi increments pointer */
- if (i > 0 && i < MAXLINE) {
- last = i;
- map[i-1] = 1;
- state = NUMBER;
- }
- else return (EOF);
- }
- else return (EOF);
- break;
- case RANGE:
- if (isdigit(c)) {
- i = stoi(&p); /* stoi increments pointer */
- if (i > 0 && i < MAXLINE) {
- if (last < i) {
- while (last < i)
- map[++last -1] = 1;
- state = NUMBER;
- }
- else return (EOF);
- }
- else return (EOF);
- }
- else return (EOF);
- break;
- default:
- return (EOF);
- }
- }
- return (0);
- }
-
- /* STOI.C More powerful version of atoi.
- *
- * chopped from the Allen Holub stoi(c)
- *
- */
-
- int stoi(instr)
- char **instr;
- {
- /* Convert string to integer. If string starts with 0x it is
- * interpreted as a hex number, else if it starts with a 0 it
- * is octal, else it is decimal. Conversion stops on encountering
- * the first character which is not a digit in the indicated
- * radix. *instr is updated to point past the end of the number.
-
- * patched to ignore leading '-' sign, since we need this for range
- */
-
- int num = 0 ;
- char *str = *instr;
-
- while( isspace(*str) )
- str++ ;
- if(*str == '0') {
- ++str;
- if (*str == 'x' || *str == 'X') {
- str++;
- while( ('0'<= *str && *str <= '9') ||
- ('a'<= *str && *str <= 'f') ||
- ('A'<= *str && *str <= 'F') )
- {
- num *= 16;
- num += ('0'<= *str && *str <= '9') ?
- *str - '0' :
- toupper(*str) - 'A' + 10 ;
- str++;
- }
- }
- else {
- while( '0' <= *str && *str <= '7' ) {
- num *= 8;
- num += *str++ - '0' ;
- }
- }
- }
- else {
- while( '0' <= *str && *str <= '9' ) {
- num *= 10;
- num += *str++ - '0' ;
- }
- }
-
- *instr = str;
- return( num );
- }
-
- /*
- * usage - display an abbreviated help usage message
- */
-
- void usage(pname)
- char *pname;
- {
- int i, n = sizeof(help_msg)/sizeof (char *);
-
- fprintf(stderr,"Usage: %s [options] file...\n\n",pname);
- for (i = 0; i < n; ++i)
- fprintf(stderr, "%s\n",help_msg[i]);
- return;
- }
-
-