121 lines
No EOL
4.5 KiB
C
121 lines
No EOL
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
} |