From f2c9f24b03b45f683d6eae93779b315bd3a453bb Mon Sep 17 00:00:00 2001 From: Gitea Date: Sat, 19 Dec 2020 21:25:41 -0600 Subject: [PATCH] started work --- nl.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 nl.c diff --git a/nl.c b/nl.c new file mode 100644 index 0000000..9cea5ed --- /dev/null +++ b/nl.c @@ -0,0 +1,121 @@ +#define _POSIX_C_SOURCE 200809L + +#include +#include +#include +#include +#include +#include + +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 + 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); + } + } + } + + +} \ No newline at end of file