From b91d57b505f560db25b66deff3bae80695c05703 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Thu, 5 Aug 2021 00:10:46 +0200 Subject: Standardise @(( )), add -R option, and fix critical bug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bug was that if the code buffered was increased, the new character that should have been pushed to it was not pushed into the code buffer, leaving out some characters before preprocessing takes place. Signed-off-by: Mattias Andrée --- README | 27 ++++++--- gpp.1 | 23 +++++++- gpp.c | 197 +++++++++++++++++++++++++++++++---------------------------------- 3 files changed, 132 insertions(+), 115 deletions(-) diff --git a/README b/README index 9d39bdf..8e7137f 100644 --- a/README +++ b/README @@ -3,7 +3,8 @@ NAME SYNOPSIS gpp [-D name[=value]] [-f file | [-i input-file] - [-o output-file]] [-n count] [-s symbol] [-u [-u]] + [-o output-file]] [-n count] [-s symbol] + [-R macroline-replacement-text] [-u [-u]] [shell [argument] ...] ETYMOLOGY @@ -35,10 +36,13 @@ DESCRIPTION Additionally, gpp supports variable substitution. @{VARIABLE} will be replaces by the value if the variable (possibility environment variable) VARIABLE. - gpp supports all modifiers thats Bash supports. For - example, if you want the value to be included but - uppercase you can write @{VARIABLE^^}, or @{VARIABLE,,} - for lowercase. + gpp supports all modifiers thats Bash (or which ever + shell is selected) supports. For example, if you want + the value to be included but uppercase you can write + @{VARIABLE^^}, or @{VARIABLE,,} for lowercase. gpp + also supports mathematical expressions that the via + the shells $((EXPRESSION)) syntax, by using + @((EXPRESSION)). Everything that is not a preprocessing directive is echo verbatim, except all @@ are replaced by @. @@ -56,18 +60,23 @@ OPTIONS Equivalent to -i FILE -o FILE. -i input-file - Select file to process. Defaults to /dev/stdin. + Select file to process. Default value is /dev/stdin. -n count Process the file recursively count times. - Defaults to 1 time. + Default value is 1. -o output-file - Select output file. Defaults to /dev/stdout. + Select output file. Defaults value is /dev/stdout. + + -R macroline-replacement-text + Text to replace macrolines with in the output. + You may for example want to use % for TeX files. + Default value is the empty string. -s symbol Set the prefix symbol for preprocessor directives. - Defaults to @. + Default value is @. -u Clear the shebang line, remove it if this flag diff --git a/gpp.1 b/gpp.1 index 8841a2e..bf4b982 100644 --- a/gpp.1 +++ b/gpp.1 @@ -14,6 +14,8 @@ gpp - Bash-based preprocessor for anything .IR output-file ]] [-n .IR count ] +[-R +.IR macroline-replacement-text ] [-s .IR symbol ] [-u [-u]] @@ -77,12 +79,20 @@ will be replaces by the value if the variable .B gpp supports all modifiers that .BR bash (1) -supports. For example, if you want the value to be -included but uppercase you can write +(or which ever +.I shell +is selected) supports. For example, if you want the +value to be included but uppercase you can write .BR @{ \fIVARIABLE\fP ^^} , or .BI @{ VARIABLE ,,} for lowercase. +.B gpp +also supports mathematical expressions that the via +the shells +.BI $(( EXPRESSION )) +syntax, by using +.BR @(( \fIEXPRESSION\fP )) . .PP Everything that is not a preprocessing directive is echo verbatim, except all @@ -130,6 +140,13 @@ Select output file. If is specified, /dev/stdout will be used. Default value is /dev/stdout. .TP +.BI \-R\ macroline-replacement-text +Text to replace macrolines with in the output. +You may for example want to use +.B % +for TeX files. +Default value is the empty string. +.TP .BI \-s\ symbol Set the prefix symbol for preprocessor directives. Default value is @@ -336,7 +353,7 @@ preprocessors. .SH NOTES None. -.SH BUS +.SH BUGS None. .SH FUTURE DIRECTIONS diff --git a/gpp.c b/gpp.c index bc466af..c79c822 100644 --- a/gpp.c +++ b/gpp.c @@ -22,7 +22,37 @@ static void usage(void) { fprintf(stderr, "usage: %s [-D name[=value]] [-f file | [-i input-file] [-o output-file]] " - "[-n count] [-s symbol] [-u [-u]] [shell [argument] ...]\n", argv0); + "[-n count] [-R macroline-replacement-text] [-s symbol] [-u [-u]] " + "[shell [argument] ...]\n", argv0); + exit(1); +} + + +static void +vweprintf(const char *fmt, va_list ap) +{ + int errnum = errno; + fprintf(stderr, "%s: ", argv0); + vfprintf(stderr, fmt, ap); + fprintf(stderr, " %s\n", strerror(errnum)); +} + +static void +weprintf(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vweprintf(fmt, ap); + va_end(ap); +} + +static void +eprintf(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vweprintf(fmt, ap); + va_end(ap); exit(1); } @@ -67,10 +97,8 @@ xopen(const char *path, int *do_close) return fd; } fd = open(path, O_RDONLY); - if (fd < 0) { - fprintf(stderr, "%s: open %s O_RDONLY: %s\n", argv0, path, strerror(errno)); - exit(1); - } + if (fd < 0) + eprintf("open %s O_RDONLY:", path); *do_close = 1; return fd; } @@ -83,10 +111,8 @@ xcreate(const char *path) if (fd >= 0) return fd; fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0666); - if (fd < 0) { - fprintf(stderr, "%s: open %s O_WRONLY|O_CREAT|O_TRUNC 0666: %s\n", argv0, path, strerror(errno)); - exit(1); - } + if (fd < 0) + eprintf("open %s O_WRONLY|O_CREAT|O_TRUNC 0666:", path); return fd; } @@ -103,10 +129,8 @@ append(char **restrict out_datap, size_t *restrict out_lenp, size_t *restrict ou if (*out_lenp + len + 1 > *out_sizep) { *out_sizep = *out_lenp + len + 1; *out_datap = realloc(*out_datap, *out_sizep); - if (!*out_datap) { - fprintf(stderr, "%s: realloc: %s\n", argv0, strerror(errno)); - exit(1); - } + if (!*out_datap) + eprintf("realloc:"); } vsprintf(&(*out_datap)[*out_lenp], fmt, ap); *out_lenp += len; @@ -121,6 +145,7 @@ main(int argc, char *argv[]) const char *input_file = NULL; const char *output_file = NULL; const char *symbol = NULL; + const char *replacement = NULL; size_t symlen = 1; int iterations = -1; int unshebang = 0; @@ -135,7 +160,7 @@ main(int argc, char *argv[]) char buffer[4096], c, *quotes = NULL, quote; size_t brackets, nquotes, quotes_size = 0; int symb, esc, dollar; - size_t len, j, lineno, no = 0, cnt; + size_t len, j, lineno, no = 0; int i, n, status, state, entered; ssize_t r; pid_t pid; @@ -148,10 +173,8 @@ main(int argc, char *argv[]) p = strchr(arg, '='); if (p) *p++ = '\0'; - if (setenv(arg, p ? p : "1", 1)) { - fprintf(stderr, "%s: setenv %s %s 1: %s\n", argv0, arg, p ? p : "1", strerror(errno)); - return 1; - } + if (setenv(arg, p ? p : "1", 1)) + eprintf("setenv %s %s 1:", arg, p ? p : "1"); break; case 'f': if (input_file || output_file) @@ -186,6 +209,11 @@ main(int argc, char *argv[]) if (!*output_file) usage(); break; + case 'R': + if (replacement) + usage(); + replacement = EARGF(usage()); + break; case 's': if (symbol) usage(); @@ -210,10 +238,12 @@ main(int argc, char *argv[]) } if (setenv("_GPP", argv0, 1)) - fprintf(stderr, "%s: setenv _GPP %s 1: %s\n", argv0, argv0, strerror(errno)); + weprintf("setenv _GPP %s 1:", argv0); if (iterations < 0) iterations = 1; + if (!replacement) + replacement = ""; if (!symbol) symbol = "@"; if (!input_file || (input_file[0] == '-' && !input_file[1])) @@ -225,16 +255,14 @@ main(int argc, char *argv[]) for (;;) { if (in_len == in_size) { in_data = realloc(in_data, in_size += 8096); - if (!in_data) { - fprintf(stderr, "%s: realloc: %s\n", argv0, strerror(errno)); - return 1; - } + if (!in_data) + eprintf("realloc:"); } r = read(in_fd, &in_data[in_len], in_size - in_len); if (r <= 0) { if (!r) break; - fprintf(stderr, "%s: read %s: %s\n", argv0, input_file, strerror(errno)); + eprintf("read %s:", input_file); } in_len += (size_t)r; } @@ -261,7 +289,7 @@ after_unshebang: while (iterations--) { entered = 0; state = 0; - lineno = 0; + lineno = 1; brackets = nquotes = 0; symb = esc = dollar = 0; while (in_off < in_len) { @@ -269,6 +297,7 @@ after_unshebang: preprocess: c = in_data[in_off++]; if (c == '\n') { + lineno += 1; state = 0; brackets = nquotes = 0; symb = esc = dollar = 0; @@ -302,10 +331,8 @@ after_unshebang: add_to_quotes: if (nquotes == quotes_size) { quotes = realloc(quotes, quotes_size += 1); - if (!quotes) { - fprintf(stderr, "%s: realloc: %s\n", argv0, strerror(errno)); - return 1; - } + if (!quotes) + eprintf("realloc:"); } quotes[nquotes++] = quote; } else if (c == ')' || c == '}') { @@ -340,29 +367,26 @@ after_unshebang: } else { if (out_len == out_size) { out_data = realloc(out_data, out_size += 4096); - if (!out_data) { - fprintf(stderr, "%s: realloc: %s\n", argv0, strerror(errno)); - return 1; - } - } else { - if ((out_data[out_len++] = c) == '\n') - state = 0; + if (!out_data) + eprintf("realloc:"); + } + if ((out_data[out_len++] = c) == '\n') { + lineno += 1; + state = 0; } } } else if (state == 1) { append_char: if (out_len == out_size) { out_data = realloc(out_data, out_size += 4096); - if (!out_data) { - fprintf(stderr, "%s: realloc: %s\n", argv0, strerror(errno)); - return 1; - } - } else { - if ((out_data[out_len++] = in_data[in_off++]) == '\n') - state = 0; + if (!out_data) + eprintf("realloc:"); + } + if ((out_data[out_len++] = in_data[in_off++]) == '\n') { + lineno += 1; + state = 0; } } else { - lineno += 1; if (in_len - in_off > symlen && !memcmp(&in_data[in_off], symbol, symlen) && (in_data[in_off + symlen] == '<' || in_data[in_off + symlen] == '>')) { state = 1; @@ -383,31 +407,23 @@ after_unshebang: in_len = 0; in_off = 0; - if (pipe(fds_in) || pipe(fds_out)) { - fprintf(stderr, "%s: pipe: %s\n", argv0, strerror(errno)); - return 1; - } + if (pipe(fds_in) || pipe(fds_out)) + eprintf("pipe:"); pid = fork(); switch (pid) { case -1: - fprintf(stderr, "%s: fork: %s\n", argv0, strerror(errno)); - return 1; + eprintf("fork:"); case 0: close(fds_in[1]); close(fds_out[0]); - if (dup2(fds_in[0], STDIN_FILENO) != STDIN_FILENO) { - fprintf(stderr, "%s: dup2 STDIN_FILENO: %s\n", argv0, strerror(errno)); - return 1; - } - if (dup2(fds_out[1], STDOUT_FILENO) != STDOUT_FILENO) { - fprintf(stderr, "%s: dup2 STDOUT_FILENO: %s\n", argv0, strerror(errno)); - return 1; - } + if (dup2(fds_in[0], STDIN_FILENO) != STDIN_FILENO) + eprintf("dup2 STDIN_FILENO:"); + if (dup2(fds_out[1], STDOUT_FILENO) != STDOUT_FILENO) + eprintf("dup2 STDOUT_FILENO:"); close(fds_in[0]); close(fds_out[1]); execvp(*shell, (void *)shell); - fprintf(stderr, "%s: execvp %s: %s\n", argv0, *shell, strerror(errno)); - return 1; + eprintf("execvp %s:", *shell); default: close(fds_in[0]); close(fds_out[1]); @@ -422,35 +438,27 @@ after_unshebang: state = 0; while (npfds) { n = poll(pfds, npfds, -1); - if (n < 0) { - fprintf(stderr, "%s: poll: %s\n", argv0, strerror(errno)); - return 1; - } + if (n < 0) + eprintf("poll:"); for (i = 0; i < n; i++) { if (!pfds[i].revents) continue; if (pfds[i].fd == fds_in[1]) { if (out_off == out_len) { - if (close(fds_in[1])) { - fprintf(stderr, "%s: write : %s\n", argv0, strerror(errno)); - return 1; - } + if (close(fds_in[1])) + eprintf("write :"); pfds[i] = pfds[--npfds]; continue; } r = write(fds_in[1], &out_data[out_off], out_len - out_off); - if (r <= 0) { - fprintf(stderr, "%s: write : %s\n", argv0, strerror(errno)); - return 1; - } + if (r <= 0) + eprintf("write :"); out_off += (size_t)r; } else { r = read(fds_out[0], buffer, sizeof(buffer)); if (r <= 0) { - if (r < 0 || close(fds_out[0])) { - fprintf(stderr, "%s: read : %s\n", argv0, strerror(errno)); - return 1; - } + if (r < 0 || close(fds_out[0])) + eprintf("read :"); pfds[i] = pfds[--npfds]; continue; } @@ -485,20 +493,9 @@ after_unshebang: } no = no * 10 + (buffer[j] & 15); } else if (!buffer[j]) { - if (no > lineno) { - cnt = no - lineno; - lineno = no; - if (in_len + cnt > in_size) { - in_size = in_len + cnt; - in_data = realloc(in_data, in_size); - if (!in_data) { - fprintf(stderr, "%s: realloc: %s\n", - argv0, strerror(errno)); - return 1; - } - } - while (cnt--) - in_data[in_len++] = '\n'; + while (lineno < no) { + append(&in_data, &in_len, &in_size, "%s\n", replacement); + lineno += 1; } state = 3; } else { @@ -512,10 +509,8 @@ after_unshebang: if (in_len == in_size) { in_size += 4096; in_data = realloc(in_data, in_size); - if (!in_data) { - fprintf(stderr, "%s: realloc: %s\n", argv0, strerror(errno)); - return 1; - } + if (!in_data) + eprintf("realloc:"); } in_data[in_len++] = buffer[j]; if (buffer[j] == '\n') { @@ -528,10 +523,8 @@ after_unshebang: } } } - if (waitpid(pid, &status, 0) != pid) { - fprintf(stderr, "%s: waitpid %s <&status> 0: %s\n", argv0, *shell, strerror(errno)); - return 1; - } + if (waitpid(pid, &status, 0) != pid) + eprintf("waitpid %s <&status> 0:", *shell); if (status) return WIFEXITED(status) ? WEXITSTATUS(status) : 1; @@ -546,14 +539,12 @@ after_unshebang: out_fd = xcreate(output_file); while (in_off < in_len) { r = write(out_fd, &in_data[in_off], in_len - in_off); - if (r <= 0) { - fprintf(stderr, "%s: write %s: %s\n", argv0, output_file, strerror(errno)); - return 1; - } + if (r <= 0) + eprintf("write %s:", output_file); in_off += (size_t)r; } if (close(out_fd)) - fprintf(stderr, "%s: write %s: %s\n", argv0, output_file, strerror(errno)); + eprintf("write %s:", output_file); free(in_data); return 0; } -- cgit v1.2.3-70-g09d2