2 * cut.c - minimalist version of cut
4 * Copyright (C) 1999,2000 by Lineo, inc.
5 * Written by Mark Whitley <markw@lineo.com>, <markw@enol.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include <unistd.h> /* getopt */
32 /* globals from other files */
37 /* globals in this file only */
38 static char part = 0; /* (b)yte, (c)har, (f)ields */
39 static int startpos = 1;
40 static int endpos = -1;
41 static char delim = '\t'; /* delimiter, default is tab */
42 static unsigned int supress_non_delimited_lines = 0;
46 * decompose_list() - parses a list and puts values into startpos and endpos.
47 * valid list formats: N, N-, N-M, -M
49 static void decompose_list(const char *list)
51 unsigned int nminus = 0;
54 /* the list must contain only digits and no more than one minus sign */
55 for (ptr = (char *)list; *ptr; ptr++) {
56 if (!isdigit(*ptr) && *ptr != '-') {
57 fatalError("invalid byte or field list\n");
62 fatalError("invalid byte or field list\n");
67 /* handle single value 'N' case */
69 startpos = strtol(list, &ptr, 10);
71 fatalError("missing list of fields\n");
75 /* handle multi-value cases */
76 else if (nminus == 1) {
77 /* handle 'N-' case */
78 if (list[strlen(list) - 1] == '-') {
79 startpos = strtol(list, &ptr, 10);
81 /* handle '-M' case */
82 else if (list[0] == '-') {
83 endpos = strtol(&list[1], NULL, 10);
85 /* handle 'N-M' case */
87 startpos = strtol(list, &ptr, 10);
88 endpos = strtol(ptr+1, &ptr, 10);
102 static void cut_file(FILE *file)
106 /* go through every line in the file */
107 for (line = NULL; (line = get_line_from_file(file)) != NULL; free(line)) {
109 /* cut based on chars/bytes */
110 if (part == 'c' || part == 'b') {
112 /* a valid end position has been specified */
114 for (i = startpos-1; i < endpos; i++) {
115 fputc(line[i], stdout);
119 /* otherwise, just go to the end of the line */
121 for (i = startpos-1; line[i]; i++) {
122 fputc(line[i], stdout);
126 /* cut based on fields */
127 else if (part == 'f') {
130 unsigned int delims_hit = 0;
132 for (ptr = line; (ptr = strchr(ptr, delim)) != NULL; ptr++) {
134 if (delims_hit == (startpos - 1)) {
137 if (delims_hit == endpos) {
141 /* we didn't hit any delimeters */
142 if (delims_hit == 0 && !supress_non_delimited_lines) {
145 /* we =did= hit some delimiters */
146 else if (delims_hit > 0) {
147 /* we have a fixed end point */
149 while (start < ptr) {
150 fputc(*start, stdout);
155 /* or we're just going til the end of the line */
158 fputc(*start, stdout);
167 extern int cut_main(int argc, char **argv)
171 while ((opt = getopt(argc, argv, "b:c:d:f:ns")) > 0) {
176 /* make sure they didn't ask for two types of lists */
178 fatalError("only one type of list may be specified");
181 decompose_list(optarg);
184 if (strlen(optarg) > 1) {
185 fatalError("the delimiter must be a single character\n");
193 supress_non_delimited_lines++;
199 fatalError("you must specify a list of bytes, characters, or fields\n");
202 if (supress_non_delimited_lines && part != 'f') {
203 fatalError("suppressing non-delimited lines makes sense
204 only when operating on fields\n");
207 if (delim != '\t' && part != 'f') {
208 fatalError("a delimiter may be specified only when operating on fields\n");
211 /* argv[(optind)..(argc-1)] should be names of file to process. If no
212 * files were specified or '-' was specified, take input from stdin.
213 * Otherwise, we process all the files specified. */
214 if (argv[optind] == NULL || (strcmp(argv[optind], "-") == 0)) {
220 for (i = optind; i < argc; i++) {
221 file = fopen(argv[i], "r");
223 /* errorMsg("%s: %s\n", argv[i], strerror(errno)); */
224 fprintf(stderr, "%s: %s\n", argv[i], strerror(errno));