diff options
author | John Ericson <John.Ericson@Obsidian.Systems> | 2017-08-23 16:23:30 -0400 |
---|---|---|
committer | John Ericson <John.Ericson@Obsidian.Systems> | 2017-08-25 11:21:09 -0400 |
commit | 287fce6402100c40317233de6b4f749f2b79b0a5 (patch) | |
tree | 845fac8eeaba363f5ddd3dcc720a5dd7b61f36de /pkgs/build-support/expand-response-params | |
parent | 2e7a3902122a269d751e31823c1c6c6b3ffa5c9b (diff) | |
download | nixpkgs-287fce6402100c40317233de6b4f749f2b79b0a5.tar nixpkgs-287fce6402100c40317233de6b4f749f2b79b0a5.tar.gz nixpkgs-287fce6402100c40317233de6b4f749f2b79b0a5.tar.bz2 nixpkgs-287fce6402100c40317233de6b4f749f2b79b0a5.tar.lz nixpkgs-287fce6402100c40317233de6b4f749f2b79b0a5.tar.xz nixpkgs-287fce6402100c40317233de6b4f749f2b79b0a5.tar.zst nixpkgs-287fce6402100c40317233de6b4f749f2b79b0a5.zip |
expand-response-params: Pull out of cc-wrapper
No hashes were changed
Diffstat (limited to 'pkgs/build-support/expand-response-params')
-rw-r--r-- | pkgs/build-support/expand-response-params/default.nix | 13 | ||||
-rw-r--r-- | pkgs/build-support/expand-response-params/expand-response-params.c | 84 |
2 files changed, 97 insertions, 0 deletions
diff --git a/pkgs/build-support/expand-response-params/default.nix b/pkgs/build-support/expand-response-params/default.nix new file mode 100644 index 00000000000..7afbb727fc3 --- /dev/null +++ b/pkgs/build-support/expand-response-params/default.nix @@ -0,0 +1,13 @@ +{ stdenv }: + +stdenv.mkDerivation { + name = "expand-response-params"; + src = ./expand-response-params.c; + buildCommand = '' + # Work around "stdenv-darwin-boot-2 is not allowed to refer to path /nix/store/...-expand-response-params.c" + cp "$src" expand-response-params.c + "$CC" -std=c99 -O3 -o "$out" expand-response-params.c + strip -S $out + ${stdenv.lib.optionalString stdenv.hostPlatform.isLinux "patchelf --shrink-rpath $out"} + ''; +} diff --git a/pkgs/build-support/expand-response-params/expand-response-params.c b/pkgs/build-support/expand-response-params/expand-response-params.c new file mode 100644 index 00000000000..05b9c62b1e8 --- /dev/null +++ b/pkgs/build-support/expand-response-params/expand-response-params.c @@ -0,0 +1,84 @@ +#include <assert.h> +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +typedef struct { char *data; size_t len, cap; } String; + +void resize(String *s, size_t len) { + s->len = len; + if (s->cap < s->len) { + s->cap = s->len * 2; + s->data = (char *)realloc(s->data, s->cap); + assert(s->data); + } +} + +void append(String *s, const char *data, size_t len) { + resize(s, s->len + len); + memcpy(s->data + s->len - len, data, len); +} + +typedef enum { space = 0, other = 1, backslash = 2, apostrophe = 3, quotation_mark = 4 } CharClass; +typedef enum { outside, unq, unq_esc, sq, sq_esc, dq, dq_esc } State; + +// current State -> CharClass -> next State +const State transitions[][5] = { + [outside] = {outside, unq, unq_esc, sq, dq}, + [unq] = {outside, unq, unq_esc, sq, dq}, + [unq_esc] = {unq, unq, unq, unq, unq}, + [sq] = {sq, sq, sq_esc, unq, sq}, + [sq_esc] = {sq, sq, sq, sq, sq}, + [dq] = {dq, dq, dq_esc, dq, unq}, + [dq_esc] = {dq, dq, dq, dq, dq}, +}; + +CharClass charClass(int c) { + return c == '\\' ? backslash : c == '\'' ? apostrophe : c == '"' ? quotation_mark : + isspace(c) ? space : other; +} + +// expandArg writes NULL-terminated expansions of `arg', a NULL-terminated +// string, to stdout. If arg does not begin with `@' or does not refer to a +// file, it is written as is. Otherwise the contents of the file are +// recursively expanded. On unexpected EOF in malformed response files an +// incomplete final argument is written, even if it is empty, to parse like GCC. +void expandArg(String *arg) { + FILE *f; + if (arg->data[0] != '@' || !(f = fopen(&arg->data[1], "r"))) { + fwrite(arg->data, 1, arg->len, stdout); + return; + } + + resize(arg, 0); + State cur = outside; + int c; + do { + c = fgetc(f); + State next = transitions[cur][charClass(c)]; + if ((cur == unq && next == outside) || (cur != outside && c == EOF)) { + append(arg, "", 1); + expandArg(arg); + resize(arg, 0); + } else if (cur == unq_esc || cur == sq_esc || cur == dq_esc || + (cur == outside ? next == unq : cur == next)) { + char s = c; + append(arg, &s, 1); + } + cur = next; + } while (c != EOF); + + fclose(f); +} + +int main(int argc, char **argv) { + String arg = { 0 }; + while (*++argv) { + resize(&arg, 0); + append(&arg, *argv, strlen(*argv) + 1); + expandArg(&arg); + } + free(arg.data); + return EXIT_SUCCESS; +} |