FENIX_coreutils/nl.c

121 lines
4.5 KiB
C

#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <errno.h>
int main(int argc, char * argv[]) {
/*
Corresponds to -b (0), -f (1), and -h (2).
0 - -b a; 1 - -b t; 2 - -b n; 3 - -b p<bre>
number_regex is for -b (0), -f (1), -h (2)
*/
int numbering[3] = {1, 2, 2}; char * number_regex[3];
/*
delim is the delimiter used for sections specified by -d
incr is the number of lines to increment numbering by (-i)
*/
char delim[3] = "\\:"; int incr = 1;
/*
lines corresponds to the -l option
Only applies w/ -{b,f,h} t; -l 2 would number every
other blank line (i.e. first blank not numbered,
second blank numbered)
format is format for numbering given by -n.
00 - rn; 01 - ln; 02 - rz
restart is for -p, don't restart at page delimiters
1 is don't restart (-p given), 0 is restart (default)
*/
int lines = 1; int format = 00; int restart = 0;
char sep = '\t'; /* Separator of number and line, given by -s */
int init_val = 1; /* Initial line number, given by -v */
int width = 6; /* Width of line number given by -w */
char c; char line[LINE_MAX];
char ln_format[90]; char format_str[LINE_MAX + 90];
FILE * file = NULL;
int cur_section = 2; /* section being printed, as for -b, etc. */
while((c = getopt(argc, argv, "b:f:h:d:i:l:n:ps:v:w:")) != -1) {
switch(c) {
case 'p': restart = 1; break;
case 'b': switch(optarg[0]) {
case 'a': numbering[0] = 0; break;
case 't': numbering[0] = 1; break;
case 'n': numbering[0] = 2; break;
case 'p': numbering[0] = 3;
number_regex[0] = strdup(optarg+1); break;
} break;
case 'f': switch(optarg[0]) {
case 'a': numbering[1] = 0; break;
case 't': numbering[1] = 1; break;
case 'n': numbering[1] = 2; break;
case 'p': numbering[1] = 3;
number_regex[1] = strdup(optarg+1); break;
} break;
case 'h': switch(optarg[0]) {
case 'a': numbering[2] = 0; break;
case 't': numbering[2] = 1; break;
case 'n': numbering[2] = 2; break;
case 'p': numbering[2] = 3;
number_regex[2] = strdup(optarg+1); break;
} break;
case 'd': delim[0] = optarg[0];
delim[1] = optarg[1] == '\0' ? ':' : optarg[1]; break;
case 'i': incr = atoi(optarg); break;
case 'l': lines = atoi(optarg); break;
case 'n': format = optarg[0] == 'l' ? 01 : 00;
format = optarg[1] == 'z' ? format | 02 : format; break;
case 's': sep = optarg[0];
case 'v': init_val = atoi(optarg); break;
case 'w': width = atoi(width); break;
}
}
ln_format[0] = '%';
ln_format[1] = format & 01 ? '-' : format & 02 ? '0' : '\0';
sprintf(ln_format + (ln_format[1] == '\0' ? 1 : 2), "%dd", width);
strcpy(format_str, ln_format);
strcat(format_str, "%c%s");
while(file == NULL) {
file = fopen(argv[optind], "r");
if(file == NULL) {
switch(errno) {
case EACCES: fprintf(stderr, "%s: %s: access denied\n", argv[0], argv[optind]);
exit(1);
case EINTR: break;
case EISDIR: fprintf(stderr, "%s: %s: is a directory\n", argv[0], argv[optind]);
exit(2);
case ELOOP: fprintf(stderr, "%s: %s: symlink loop detected\n", argv[0], argv[optind]);
exit(3);
case EMFILE:
fprintf(stderr, "Hi, you shouldn't see this. %s somehow used up all the file descriptors available to it.\n", argv[0]);
fprintf(stderr, "This is a bug. If you could let us know about it, that'd be much appreciated\n");
fprintf(stderr, "If you wanna debug, check near line 83 of nl.c. Otherwise, we'll just exit now.\n");
exit(5);
case ENAMETOOLONG: fprintf(stderr, "%s: %s: name too long\n", argv[0], argv[optind]);
exit(6);
case ENFILE: fprintf(stderr, "%s: too many files open in system", argv[0]);
exit(7);
case ENOENT: fprintf(stderr, "%s: %s: file doesn't exist\n", argv[0], argv[optind]);
exit(8);
case ENOTDIR: int i = strlen(argv[optind]);
while(argv[optind][i-1] == '/') { i--; }
argv[optind][i] = '\0';
break;
case ENXIO: fprintf(stderr, "%s: Did you mean to feed a device file to nl?\n", argv[0]);
fprintf(stderr, "In any case, the device for this file doesn't exist (ENXIO). Sorry :P\n");
exit(9);
case EOVERFLOW: fprintf(stderr, "%s: %s: file too big\n", argv[0], argv[optind]);
exit(4);
}
}
}
}