diff --git a/src/frontend/inp.c b/src/frontend/inp.c index 73208f5c5..3a1a22300 100644 --- a/src/frontend/inp.c +++ b/src/frontend/inp.c @@ -32,6 +32,7 @@ Author: 1985 Wayne A. Christopher #include "subckt.h" #include "spiceif.h" #include "com_let.h" +#include "com_set.h" #include "com_commands.h" #ifdef XSPICE @@ -637,10 +638,71 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile) * the cards .control and .endc, unless comfile is TRUE, in which * case every line must be a front-end command. There are too * many problems with matching the first word on the line. */ + ld = deck; if (comfile) { + bool with_params = FALSE; + +#ifndef SHARED_MODULE + if (ciprefix("*ng_script_with_params", deck->line)) { + extern char **Copy_of_argv; // main.c + extern int optind; // Library function getopt() + static const char header[] = "argc = %u argv = ( "; + wordlist *setarg; + unsigned int argc, size; + char *p_buf_active; /* buffer in use */ + char buf[BSIZE_SP]; + + /* Not just a command script, but one requesting arguments + * from the program's command line. + * This is similar to cp_oddcomm() (cpitf.c), + * but arguments are taken from the original program command. + */ + + with_params = TRUE; + size = sizeof header + 10; // Allow for %u and close. + for (argc = 0; Copy_of_argv[optind + argc]; ++argc) + size += strlen(Copy_of_argv[optind + argc]); + size += 3 * argc; // Spaces and quotes. + if (size <= sizeof buf) + p_buf_active = buf; + else + p_buf_active = TMALLOC(char, size); + + /* Fill the buffer. */ + + size = sprintf(p_buf_active, header, argc); + while (Copy_of_argv[optind]) { + char c, *fmt; + + c = Copy_of_argv[optind][0]; + if ((c >= '0' && c <= '9') || c == '+' || c == '-' || !c) { + /* Looks like a number or empty string - quote it. */ + + fmt = " \"%s\""; + } else { + fmt = " %s"; + } + size += sprintf(p_buf_active + size, fmt, + Copy_of_argv[optind++]); + } + strcpy(p_buf_active + size, " )"); + + /* Treat the buffer as a "set" command to create argv and argc. */ + + setarg = cp_lexer(p_buf_active); + com_set(setarg); + wl_free(setarg); + + /* Free buffer allocation if made */ + + if (p_buf_active != buf) + txfree(p_buf_active); + } +#endif /* Process each command, except 'option' which is assembled in a list and ingnored here */ + for (dd = deck; dd; dd = ld) { ld = dd->nextcard; if ((dd->line[0] == '*') && (dd->line[1] != '#')) @@ -655,6 +717,12 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile) cp_evloop(dd->line); } } + + if (with_params) { + cp_remvar("argc"); + cp_remvar("argv"); + } + /* free the control deck */ line_free(deck, TRUE); /* set to NULL to allow generation of a new dbs */ @@ -943,10 +1011,11 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile) } /* merge the two option line structs - com_options (comfile == TRUE, filled in from spinit, .spiceinit, and *ng_sript), and - options (comfile == FALSE, filled in from circuit with .OPTIONS) + com_options (comfile == TRUE, filled in from spinit, + .spiceinit, and *ng_script), and options + (comfile == FALSE, filled in from circuit with .OPTIONS) into options, thus keeping com_options, - options is loaded into circuit and freed when circuit is removed */ + options is loaded into circuit and freed when circuit is removed */ options = line_reverse(line_nconc(options, inp_deckcopy(com_options))); /* List of all expressions found in instance and .model lines */ diff --git a/src/main.c b/src/main.c index e3999a865..174931fd5 100644 --- a/src/main.c +++ b/src/main.c @@ -164,6 +164,8 @@ double EpsNorm, VNorm, NNorm, LNorm, TNorm, JNorm, GNorm, ENorm; /* end cider globals */ #endif /* CIDER */ +char **Copy_of_argv; // Used to recover args for *ng_script_with_params files + struct variable *(*if_getparam)(CKTcircuit *ckt, char **name, char *param, int ind, int do_model); /* static functions */ @@ -1382,13 +1384,16 @@ int main(int argc, char **argv) while (optind < argc) { char *arg = argv[optind++]; FILE *tp; + /* Copy the the path of the first filename only */ if (!Infile_Path) { Infile_Path = ngdirname(arg); } - /* unquote the input string, needed if it results from double clicking the filename */ #if defined(HAS_WINGUI) + /* Unquote the input string, needed if it results + * from double clicking the filename. + */ arg = cp_unquote(arg); #endif /* Copy all the arguments into the temporary file */ @@ -1408,8 +1413,9 @@ int main(int argc, char **argv) } } - /* Copy the input file name which otherwise will be lost due to the - temporary file */ + /* Copy the input file name which otherwise will be lost + * due to the temporary file. + */ dname = copy(arg); #if defined(HAS_WINGUI) /* write source file name into source window */ @@ -1418,11 +1424,32 @@ int main(int argc, char **argv) tfree(arg); #endif + if (!gotone) { + char line[256]; + + /* Check for "*ng_script_with_params" as first line. */ + + if (fgets(line, sizeof line, tp) && + ciprefix("*ng_script_with_params", line)) { + /* Special script file: remaining arguments are + * script parameters. + */ + + fclose(tempfile); + tempfile = tp; + Copy_of_argv = argv; + break; + } else { + fseek(tp, 0L, SEEK_SET); + gotone = TRUE; + } + } append_to_stream(tempfile, tp); fclose(tp); } fseek(tempfile, 0L, SEEK_SET); + gotone = FALSE; // Re-use if (tempfile && (!err || !ft_batchmode)) { /* Copy the input file name for becoming another file search path */ @@ -1450,7 +1477,6 @@ int main(int argc, char **argv) } if (ft_batchmode) { - int error3 = 1; /* If we get back here in batch mode then something is wrong, diff --git a/src/winmain.c b/src/winmain.c index 2fb22aa0c..1bf3bb5fb 100644 --- a/src/winmain.c +++ b/src/winmain.c @@ -850,7 +850,6 @@ ElementWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) static int MakeArgcArgv(char *cmdline, int *argc, char ***argv) { - char *pC1; /* a temporary character pointer */ char *pWorkString = NULL; /* a working copy of cmdline */ int i; /* a loop counter */ int quoteflag = 0; /* for the finite state machine parsing cmdline */ @@ -899,13 +898,13 @@ MakeArgcArgv(char *cmdline, int *argc, char ***argv) #endif /* If we still have a string left, parse it for all the arguments. */ - if (strlen(pWorkString)) + if (pWorkString[0]) { /* This could probably be done with strtok as well but strtok is destructive if I wanted to look for " \"" and I couldn't tell what delimiter that I had bumped against */ - for (i = 0; i < (signed)strlen(pWorkString); i++) + for (i = 0; pWorkString[i]; i++) switch (pWorkString[i]) { case SPACE: @@ -935,7 +934,7 @@ MakeArgcArgv(char *cmdline, int *argc, char ***argv) } } /* malloc an argv */ - tmpargv = (char**) malloc((unsigned)numargs * sizeof(char *)); + tmpargv = (char**) malloc((unsigned)(numargs + 1) * sizeof(char *)); if (NULL == tmpargv) { status = -1; @@ -949,18 +948,15 @@ MakeArgcArgv(char *cmdline, int *argc, char ***argv) deli[0] = DELIMITER; deli[1] = '\0'; /* delimiter for strtok */ - pC1 = NULL; /* Now actually strdup all the arguments out of the string and store them in the argv */ for (i = 1; i < numargs; i++) { - if (NULL == pC1) - pC1 = pWorkString; - if (i == 1) - tmpargv[i] = copy(strtok(pC1, deli)); + tmpargv[i] = copy(strtok(pWorkString, deli)); else tmpargv[i] = copy(strtok(NULL, deli)); } + tmpargv[i] = NULL; /* copy the working values over to the arguments */ *argc = numargs;