From 707936efe324436a32d2924ef9eb7ee9641bdc16 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Fri, 29 Nov 2019 23:55:13 +0100 Subject: [PATCH] enable setting a variable from an input file using the existing i/o redirection --- src/frontend/com_set.c | 61 ++++++++++++++++++++++++++++++++++++++++++ src/frontend/streams.c | 12 ++++++--- 2 files changed, 69 insertions(+), 4 deletions(-) diff --git a/src/frontend/com_set.c b/src/frontend/com_set.c index 62bfa7ca9..688c22feb 100644 --- a/src/frontend/com_set.c +++ b/src/frontend/com_set.c @@ -6,6 +6,8 @@ #include "variable.h" #include "com_set.h" +wordlist* readifile(wordlist*); + /* The set command. Syntax is set [opt ...] [opt = val ...]. Val may * be a string, an int, a float, or a list of the form (elt1 elt2 @@ -19,6 +21,12 @@ com_set(wordlist *wl) cp_vprint(); return; } + + /* special case input redirection*/ + wordlist *ww = wl->wl_next; + if (ww && eq(ww->wl_word, "<")) + wl = readifile(wl); + vars = cp_setparse(wl); /* This is sort of a hassle... */ @@ -54,3 +62,56 @@ com_set(wordlist *wl) tfree(oldvar); } } + +/* read a file from cp_in, add the tokens to a wordlist and + create an input for a string list like set ccc = ( 3 5 7 ). + Comment lines in input file (starting with '*') are ignored. */ +wordlist* +readifile(wordlist* win) +{ + /* max file size */ + char intoken[4096]; + /* save start address */ + wordlist* tw = win; + char *tmpstr; + + /* delete wordlist from '<' on */ + wl_free(win->wl_next); + wl_append_word(&win, &win, copy("=")); + wl_append_word(&win, &win, copy("(")); + /* read a line. If it starts with '*', ignore it */ + while (fgets(intoken, 4096, cp_in) != NULL) { + if (intoken[0] == '*') + continue; + char* delstr; + char* instr = delstr = copy(intoken); + /* get all tokens, ignoring '\n' + and add to string list */ + while ((tmpstr = gettok(&instr)) != NULL) { + wl_append_word(&win, &win, tmpstr); + } + tfree(delstr); + } + wl_append_word(&win, &win, copy(")")); + /* close and reset cp_in + (was opened in streams.c:84) */ + cp_ioreset(); + return tw; +#if 0 + size_t retval = fread(intoken, 1, 4096, cp_in); + intoken[retval] = '\0'; + char* delstr; + char* instr = delstr = copy(intoken); + /* get all tokens, ignoring '\n' + and add to string list */ + while ((tmpstr = gettok(&instr)) != NULL) { + wl_append_word(&win, &win, tmpstr); + } + tfree(delstr); + wl_append_word(&win, &win, copy(")")); + /* close and reset cp_in + (was opened in streams.c:84) */ + cp_ioreset(); + return tw; +#endif +} diff --git a/src/frontend/streams.c b/src/frontend/streams.c index 8906fd33c..8558220b1 100644 --- a/src/frontend/streams.c +++ b/src/frontend/streams.c @@ -82,16 +82,20 @@ cp_redirect(wordlist *wl) #endif fp = fopen(fname, "r"); - tfree(fname); - if (!fp) { perror(fname); + tfree(fname); goto error; } - + + tfree(fname); cp_in = fp; - wl_delete_slice(beg, w); + /* special case for set command: + keep i/o information (handled in com_set.c) */ + wordlist* bw = beg->wl_prev->wl_prev; + if (!(bw && cieq(bw->wl_word, "set"))) + wl_delete_slice(beg, w); } else if (*w->wl_word == cp_gt) {