Recognise *ng_script_with_params" in the first line of the first
program input file to mean that the file is a pure interpreter script that receives any remaining command arguments. In winmain.c ensure that the argv array is NULL-terminated and tidy some code.
This commit is contained in:
parent
89851872ed
commit
07ce9c788e
|
|
@ -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 */
|
||||
|
|
|
|||
34
src/main.c
34
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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue