started work
This commit is contained in:
parent
cffb313125
commit
f2c9f24b03
1 changed files with 121 additions and 0 deletions
121
nl.c
Normal file
121
nl.c
Normal file
|
@ -0,0 +1,121 @@
|
|||
#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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
Reference in a new issue