Browse Source

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.
pre-master-46
Giles Atkinson 2 years ago
parent
commit
07ce9c788e
  1. 75
      src/frontend/inp.c
  2. 34
      src/main.c
  3. 14
      src/winmain.c

75
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 */

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,

14
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;

Loading…
Cancel
Save