diff --git a/src/frontend/commands.c b/src/frontend/commands.c index 86b13909d..bec672c31 100644 --- a/src/frontend/commands.c +++ b/src/frontend/commands.c @@ -146,6 +146,10 @@ struct comm spcp_coms[] = { { 1, 040000, 040000, 040000 }, E_DEFHMASK, 2, 2, NULL, "file : Load a snapshot." } , + { "circbyline", com_circbyline, FALSE, TRUE, + { 1, 040000, 040000, 040000 }, E_DEFHMASK, 1, LOTS, + NULL, + "line : Enter a circuit line." } , { "alias", com_alias, FALSE, FALSE, { 02, 04, 04, 04 }, E_ADVANCED, 0, LOTS, NULL, diff --git a/src/frontend/cpitf.c b/src/frontend/cpitf.c index 9b067337c..2b3f34302 100644 --- a/src/frontend/cpitf.c +++ b/src/frontend/cpitf.c @@ -263,7 +263,7 @@ ft_cpinit(void) if ((fp = fopen(buf, "r")) != NULL) { cp_interactive = FALSE; - inp_spsource(fp, TRUE, buf); + inp_spsource(fp, TRUE, buf, FALSE); cp_interactive = TRUE; found = TRUE; break; @@ -276,7 +276,7 @@ ft_cpinit(void) } else if ((fp = fopen("./spinit", "r")) != NULL) { #endif cp_interactive = FALSE; - inp_spsource(fp, TRUE, buf); + inp_spsource(fp, TRUE, buf, FALSE); cp_interactive = TRUE; found = TRUE; break; diff --git a/src/frontend/device.c b/src/frontend/device.c index 44a268321..8ef25eaaa 100644 --- a/src/frontend/device.c +++ b/src/frontend/device.c @@ -1464,7 +1464,7 @@ com_alter_mod(wordlist *wl) modfile = inp_pathopen(filename, readmode); { char *dir_name = ngdirname(filename); - modeldeck = inp_readall(modfile, 0, dir_name, 0); + modeldeck = inp_readall(modfile, 0, dir_name, 0, 0); free(dir_name); } tfree(input); diff --git a/src/frontend/inp.c b/src/frontend/inp.c index 48b5254b8..1b9b444d2 100644 --- a/src/frontend/inp.c +++ b/src/frontend/inp.c @@ -278,11 +278,12 @@ line_free_x(struct line *deck, bool recurse) * .plot, to perform after the run is over. * Then, we run dodeck, which parses up the deck. */ void -inp_spsource(FILE *fp, bool comfile, char *filename) +inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile) /* arguments: - * *fp = pointer to the input file - * comfile = whether it is a command file. Values are TRUE/FALSE - * *filename = name of input file + *fp = pointer to the input file + comfile = whether it is a command file. Values are TRUE/FALSE + *filename = name of input file + intfile = whether input is from internal array. Values are TRUE/FALSE */ { struct line *deck, *dd, *ld, *prev_param = NULL, *prev_card = NULL; @@ -301,13 +302,14 @@ inp_spsource(FILE *fp, bool comfile, char *filename) char *dir_name = ngdirname(filename ? filename : "."); startTime = seconds(); - deck = inp_readall(fp, 0, dir_name, comfile); + deck = inp_readall(fp, 0, dir_name, comfile, intfile); endTime = seconds(); tfree(dir_name); /* if nothing came back from inp_readall, just close fp and return to caller */ if (!deck) { /* MW. We must close fp always when returning */ - fclose(fp); + if (!intfile) + fclose(fp); return; } @@ -321,7 +323,8 @@ inp_spsource(FILE *fp, bool comfile, char *filename) if (!deck->li_next) fprintf(cp_err, "Warning: no lines in input\n"); } - fclose(fp); + if (!intfile) + fclose(fp); /* Now save the IO context and start a new control set. After we are done with the source we'll put the old file descriptors @@ -976,7 +979,7 @@ com_edit(wordlist *wl) cp_interactive = inter; return; } - inp_spsource(fp, FALSE, wl->wl_word); + inp_spsource(fp, FALSE, wl->wl_word, FALSE); } else { /* If there is no circuit yet, then create one */ if (ft_curckt && ft_curckt->ci_filename) { @@ -1016,7 +1019,7 @@ com_edit(wordlist *wl) cp_interactive = inter; return; } - inp_spsource(fp, FALSE, permfile ? filename : NULL); + inp_spsource(fp, FALSE, permfile ? filename : NULL, FALSE); /* fclose(fp); */ /* MW. inp_spsource already closed fp */ @@ -1107,9 +1110,9 @@ com_source(wordlist *wl) /* Don't print the title if this is a spice initialisation file. */ if (ft_nutmeg || substring(INITSTR, owl->wl_word) || substring(ALT_INITSTR, owl->wl_word)) - inp_spsource(fp, TRUE, tempfile ? NULL : wl->wl_word); + inp_spsource(fp, TRUE, tempfile ? NULL : wl->wl_word, FALSE); else - inp_spsource(fp, FALSE, tempfile ? NULL : wl->wl_word); + inp_spsource(fp, FALSE, tempfile ? NULL : wl->wl_word, FALSE); cp_interactive = inter; if (tempfile) @@ -1161,3 +1164,42 @@ cktislinear(CKTcircuit *ckt, struct line *deck) ckt->CKTisLinear = 1; } + + +/* global array for assembling circuit lines entered by fcn circbyline + or receiving array from external caller. Array is created once per ngspice call. + Last line of the array has to get the value NULL */ +char **circarray; + +void +create_circbyline(char *line) +{ + static int linec = 0; + static int memlen = 256; + FILE *fp = NULL; + if (!circarray) + circarray = TMALLOC(char*, memlen); + circarray[linec++] = line; + if (linec < memlen) { + if (ciprefix(".end", line) && (line[4] == '\0' || isspace(line[4]))) { + circarray[linec] = NULL; + inp_spsource(fp, FALSE, "", TRUE); + linec = 0; + } + } + else { + memlen += memlen; + circarray = TREALLOC(char*, circarray, memlen); + } +} + +/* fcn called by command 'circbyline' */ +void +com_circbyline(wordlist *wl) +{ + /* undo the automatic wordline creation. + wl_flatten allocates memory on the heap for each newline. + This memory will be released line by line in inp_source(). */ + char *newline = wl_flatten(wl); + create_circbyline(newline); +} diff --git a/src/frontend/inp.h b/src/frontend/inp.h index bf14b15be..0cf2be457 100644 --- a/src/frontend/inp.h +++ b/src/frontend/inp.h @@ -9,6 +9,6 @@ void com_listing(wordlist *wl); void com_edit(wordlist *wl); void com_source(wordlist *wl); - +void com_circbyline(wordlist *wl); #endif diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index 9101896d3..78e627efb 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -170,10 +170,10 @@ read_a_lib(char *y, int call_depth, char *dir_name) if (dir_name_flag == FALSE) { char *y_dir_name = ngdirname(y); - library_deck[num_libraries-1] = inp_readall(newfp, call_depth+1, y_dir_name, FALSE); + library_deck[num_libraries-1] = inp_readall(newfp, call_depth+1, y_dir_name, FALSE, FALSE); tfree(y_dir_name); } else { - library_deck[num_libraries-1] = inp_readall(newfp, call_depth+1, dir_name, FALSE); + library_deck[num_libraries-1] = inp_readall(newfp, call_depth+1, dir_name, FALSE, FALSE); } fclose(newfp); @@ -332,11 +332,12 @@ expand_section_references(int line_number) debug printout to debug-out.txt *-------------------------------------------------------------------------*/ struct line * -inp_readall(FILE *fp, int call_depth, char *dir_name, bool comfile) +inp_readall(FILE *fp, int call_depth, char *dir_name, bool comfile, bool intfile) /* fp: in, pointer to file to be read, call_depth: in, nested call to fcn dir_name: in, name of directory of file to be read - comfile: in, TRUE if command file (e.g. spinit, .spiceinit + comfile: in, TRUE if command file (e.g. spinit, .spiceinit) + intfile: in, TRUE if deck is generated from internal circarray */ { struct line *end = NULL, *cc = NULL, *prev, *working, *newcard, *global_card; @@ -353,6 +354,7 @@ inp_readall(FILE *fp, int call_depth, char *dir_name, bool comfile) int line_number = 1; /* sjb - renamed to avoid confusion with struct line */ int line_number_orig = 1, line_number_inc = 1; unsigned int no_braces = 0; /* number of '{' */ + int cirlinecount = 0; /* length of circarray */ size_t max_line_length; /* max. line length in input deck */ @@ -371,47 +373,55 @@ inp_readall(FILE *fp, int call_depth, char *dir_name, bool comfile) /* First read in all lines & put them in the struct cc */ for (;;) { - -#ifdef XSPICE - /* gtri - modify - 12/12/90 - wbk - read from mailbox if ipc enabled */ - - /* If IPC is not enabled, do equivalent of what SPICE did before */ - if (! g_ipc.enabled) { - if (call_depth == 0 && line_count == 0) { - line_count++; - if (fgets(big_buff, 5000, fp)) - buffer = copy(big_buff); - } else { - buffer = readline(fp); - if (!buffer) - break; - } - } else { - /* else, get the line from the ipc channel. */ - /* We assume that newlines are not sent by the client */ - /* so we add them here */ - ipc_status = ipc_get_line(ipc_buffer, &ipc_len, IPC_WAIT); - if (ipc_status == IPC_STATUS_END_OF_DECK) { - buffer = NULL; + /* derive lines from circarray */ + if (intfile) { + buffer = circarray[cirlinecount++]; + if (!buffer) { + tfree(circarray); break; - } else if (ipc_status == IPC_STATUS_OK) { - buffer = TMALLOC(char, strlen(ipc_buffer) + 3); - strcpy(buffer, ipc_buffer); - strcat(buffer, "\n"); - } else { /* No good way to report this so just die */ - controlled_exit(EXIT_FAILURE); } } + /* read lines from file fp */ + else { + +#ifdef XSPICE + /* gtri - modify - 12/12/90 - wbk - read from mailbox if ipc enabled */ + + /* If IPC is not enabled, do equivalent of what SPICE did before */ + if (! g_ipc.enabled) { + if (call_depth == 0 && line_count == 0) { + line_count++; + if (fgets(big_buff, 5000, fp)) + buffer = copy(big_buff); + } else { + buffer = readline(fp); + if (!buffer) + break; + } + } else { + /* else, get the line from the ipc channel. */ + /* We assume that newlines are not sent by the client */ + /* so we add them here */ + ipc_status = ipc_get_line(ipc_buffer, &ipc_len, IPC_WAIT); + if (ipc_status == IPC_STATUS_END_OF_DECK) { + buffer = NULL; + break; + } else if (ipc_status == IPC_STATUS_OK) { + buffer = TMALLOC(char, strlen(ipc_buffer) + 3); + strcpy(buffer, ipc_buffer); + strcat(buffer, "\n"); + } else { /* No good way to report this so just die */ + controlled_exit(EXIT_FAILURE); + } + } /* gtri - end - 12/12/90 */ #else - - buffer = readline(fp); - if(!buffer) - break; - + buffer = readline(fp); + if(!buffer) + break; #endif - + } #ifdef TRACE /* SDB debug statement */ printf("in inp_readall, just read %s", buffer); @@ -554,10 +564,10 @@ inp_readall(FILE *fp, int call_depth, char *dir_name, bool comfile) if (dir_name_flag == FALSE) { char *y_dir_name = ngdirname(y); - newcard = inp_readall(newfp, call_depth+1, y_dir_name, FALSE); /* read stuff in include file into netlist */ + newcard = inp_readall(newfp, call_depth+1, y_dir_name, FALSE, FALSE); /* read stuff in include file into netlist */ tfree(y_dir_name); } else { - newcard = inp_readall(newfp, call_depth+1, dir_name, FALSE); /* read stuff in include file into netlist */ + newcard = inp_readall(newfp, call_depth+1, dir_name, FALSE, FALSE); /* read stuff in include file into netlist */ } (void) fclose(newfp); diff --git a/src/frontend/nutinp.c b/src/frontend/nutinp.c index 631764d0e..f75ac1201 100644 --- a/src/frontend/nutinp.c +++ b/src/frontend/nutinp.c @@ -34,7 +34,7 @@ inp_nutsource(FILE *fp, bool comfile, char *filename) wordlist *controls = NULL; FILE *lastin, *lastout, *lasterr; - deck = inp_readall(fp, 0, NULL, comfile); /* still to check if . or filename instead of NULL */ + deck = inp_readall(fp, 0, NULL, comfile, FALSE); /* still to check if . or filename instead of NULL */ if (!deck) return; diff --git a/src/include/ngspice/fteext.h b/src/include/ngspice/fteext.h index e8e081062..ae7ca077a 100644 --- a/src/include/ngspice/fteext.h +++ b/src/include/ngspice/fteext.h @@ -203,12 +203,14 @@ extern bool gr_circular; void inp_dodeck(struct line *deck, char *tt, wordlist *end, bool reuse, struct line *options, char *filename); extern void inp_source(char *file); -void inp_spsource(FILE *fp, bool comfile, char *filename); +void inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile); extern void inp_casefix(char *string); extern void inp_list(FILE *file, struct line *deck, struct line *extras, int type); -extern struct line *inp_readall(FILE *fp, int call_depth, char *dir_name, bool comfile); +extern struct line *inp_readall(FILE *fp, int call_depth, char *dir_name, bool comfile, bool intfile); extern FILE *inp_pathopen(char *name, char *mode); +extern char** circarray; + /* nutinp.c */ void inp_nutsource(FILE *fp, bool comfile, char *filename); diff --git a/src/main.c b/src/main.c index 99457634e..4e56249d7 100644 --- a/src/main.c +++ b/src/main.c @@ -1222,10 +1222,10 @@ main(int argc, char **argv) if (tempfile && (!err || !ft_batchmode)) { #if defined(HAS_WINDOWS) || defined(_MSC_VER) || defined(__MINGW32__) /* Copy the input file name for adding another file search path */ - inp_spsource(tempfile, FALSE, dname); + inp_spsource(tempfile, FALSE, dname, FALSE); tfree(dname); #else - inp_spsource(tempfile, FALSE, NULL); + inp_spsource(tempfile, FALSE, NULL, FALSE); #endif gotone = TRUE; } @@ -1236,7 +1236,7 @@ main(int argc, char **argv) } /* --- if (!ft_servermode) --- */ if (!gotone && ft_batchmode) - inp_spsource(circuit_file, FALSE, NULL); + inp_spsource(circuit_file, FALSE, NULL, FALSE); }