wc: Added wc
[mutos-utils.git] / cut.c
blobe900fa5f085518abacf5e8f98b967b7d403f8c4e
1 /*
2 Copyright © 2013 Alastair Stuart
4 This program is open source software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <errno.h>
20 #include <sys/stat.h>
21 #include <sys/types.h>
23 #define VERSION "0.01"
25 char delim = '\0';
26 unsigned int field = 0;
28 int main(int argc, char* argv[])
30 // flag parsing
31 int arg = 0;
32 for (arg = 1; arg < argc; arg++)
34 if (strcmp("-d", argv[arg]) == 0) {
35 delim = argv[arg + 1][0];
36 arg++;
37 } else if (strcmp("-f", argv[arg]) == 0) {
38 field = atoi(argv[arg + 1]);
39 arg++;
40 } else if (strcmp("--help", argv[arg]) == 0 || strcmp("-h", argv[arg]) == 0) {
41 printf("Usage: %s -d [delim] -f [field] [file]\n", argv[0]);
42 printf("[delim] must be a character and [field] starts at 1.\n"
43 "\n"
44 " -h, --help Print this message.\n"
45 " -v, --version Show version info.\n");
46 return 0;
47 } else if (strcmp("--version", argv[arg]) == 0 || strcmp("-v", argv[arg]) == 0) {
48 printf("cut (mutos) v"VERSION"\n");
49 return 0;
50 } else {
51 // no more flags left
52 break;
56 if (!field) {
57 fprintf(stderr, "%s: you must specify a field.\n"
58 "Run '%s --help' for usage.\n",
59 argv[0], argv[0]);
60 return 1;
63 FILE* file = NULL;
64 char* buffer = NULL;
66 struct stat file_stat;
67 int buf_size = 0;
68 // if no file is specified or file is "-"
69 if ((argc - arg) == 0 || strcmp(argv[arg], "-") == 0) {
70 buffer = calloc(4096 + 1, sizeof(char));
71 buf_size = 4096 + 1;
72 file = stdin;
73 } else {
74 // stat the file to get its size
75 // if we statted successfully,
76 // allocate a buffer
77 int rc = stat(argv[argc - 1], &file_stat);
78 if (rc >= 0) {
79 buffer = calloc(file_stat.st_size + 1, sizeof(char));
80 buf_size = file_stat.st_size + 1;
81 file = fopen(argv[arg], "r");
82 } else {
83 fprintf(stderr, "%s: %s: %s\n",
84 argv[0], strerror(errno), argv[argc - 1]);
85 return 1;
89 int num_lines = 0;
91 int c = fgetc(file);
92 for (int i = 0; i < buf_size && c != EOF; i++)
94 buffer[i] = (char)c;
95 c = fgetc(file);
97 // Null-terminate the buffer
98 buffer[buf_size - 1] = '\0';
100 // for each char in the buffer
101 for (int i = 0; i < buf_size; i++)
103 if (buffer[i] == '\n') {
104 num_lines++;
108 size_t line_len[num_lines];
109 memset(line_len, 0, num_lines * sizeof(size_t));
111 char* lines[num_lines];
112 // for each line: i = current line, j = current character
113 for (int i = 0, j = 0, last_enter = -1; i < num_lines && j < file_stat.st_size; j++)
115 if (buffer[j] != '\n') {
116 line_len[i]++;
117 } else {
118 // allocate a string that's the length of the current line
119 lines[i] = malloc(line_len[i] + 1);
120 // copy the line
121 strncpy(lines[i], buffer+last_enter+1, line_len[i]);
122 // set last_enter to the current enter
123 // for the next line
124 last_enter = j;
125 // go to next line
126 i++;
130 // delete delimiter characters by setting it to -1
131 for (int i = 0; i < num_lines; i++)
133 for (size_t j = 0; j < strlen(lines[i]); j++)
135 if (lines[i][j] == delim) {
136 lines[i][j] = -1;
141 // go through the line and print the requested field
142 for (int i = 0; i < num_lines; i++)
144 for (size_t j = 0, field_count = 0; j < strlen(lines[i]); j++)
146 if (lines[i][j == 0 ? j : j - 1] == -1 && lines[i][j] != -1) {
147 field_count++;
150 if (field_count == field - 1 && lines[i][j] != -1) {
151 printf("%c", lines[i][j]);
154 printf("\n");
157 return 0;