📄 inpcom.c
字号:
/**********Copyright 1990 Regents of the University of California. All rights reserved.Author: 1985 Wayne A. Christopher**********//* * For dealing with spice input decks and command scripts *//* * SJB 21 April 2005 * Added support for end-of-line comments that begin with any of the following: * ';' (for PSpice compatability) * '$ ' (for HSpice compatability) * '//' (like in c++ and as per the numparam code) * '--' (as per the numparam code) * Any following text to the end of the line is ignored. * Note requirement for $ to be followed by a space. This is to avoid conflict * with use in front of a variable. * Comments on a contunuation line (i.e. line begining with '+') are allowed * and are removed before lines are stitched. * Lines that contain only an end-of-line comment with or withou leading white * space are also allowed. *//* * SJB 22 May 2001 * Fixed memory leaks in inp_readall() when first(?) line of input begins with a '@'. * Fixed memory leaks in inp_readall() when .include lines have errors * Fixed crash where a NULL pointer gets freed in inp_readall() */#include <config.h>#include "ngspice.h"#include "cpdefs.h"#include "ftedefs.h"#include "dvec.h"#include "fteinp.h"#include "inpcom.h"#include "variable.h"#ifdef XSPICE/* gtri - add - 12/12/90 - wbk - include new stuff */#include "ipctiein.h"#include "enh.h"/* gtri - end - 12/12/90 */#endif/* SJB - Uncomment this line for debug tracing *//*#define TRACE *//* static declarations */static char * readline(FILE *fd);static void inp_stripcomments_deck(struct line *deck);static void inp_stripcomments_line(char * s);/*-------------------------------------------------------------------------* * This routine reads a line (of arbitrary length), up to a '\n' or 'EOF' * * and returns a pointer to the resulting null terminated string. * * The '\n' if found, is included in the returned string. * * From: jason@ucbopal.BERKELEY.EDU (Jason Venner) * * Newsgroups: net.sources * *-------------------------------------------------------------------------*/#define STRGROW 256static char *readline(FILE *fd){ int c; int memlen; char *strptr; int strlen; strptr = NULL; strlen = 0; memlen = STRGROW; strptr = tmalloc(memlen); memlen -= 1; /* Save constant -1's in while loop */ while((c = getc(fd)) != EOF) { if (strlen == 0 && (c == '\n' || c == ' ')) /* Leading spaces away */ continue; strptr[strlen] = c; strlen++; if( strlen >= memlen ) { memlen += STRGROW; if( !(strptr = trealloc(strptr, memlen + 1))) { return (NULL); } } if (c == '\n') { break; } } if (!strlen) { tfree(strptr); return (NULL); } strptr[strlen] = '\0'; /* Trim the string */ strptr = trealloc(strptr, strlen + 1); return (strptr);}/*-------------------------------------------------------------------------* * Look up the variable sourcepath and try everything in the list in order * * if the file isn't in . and it isn't an abs path name. * *-------------------------------------------------------------------------*/FILE *inp_pathopen(char *name, char *mode){ FILE *fp; char buf[BSIZE_SP]; struct variable *v; /* If this is an abs pathname, or there is no sourcepath var, just * do an fopen. */ if (index(name, DIR_TERM) || !cp_getvar("sourcepath", VT_LIST, (char *) &v)) return (fopen(name, mode)); while (v) { switch (v->va_type) { case VT_STRING: cp_wstrip(v->va_string); (void) sprintf(buf, "%s%s%s", v->va_string, DIR_PATHSEP, name); break; case VT_NUM: (void) sprintf(buf, "%d%s%s", v->va_num, DIR_PATHSEP, name); break; case VT_REAL: /* This is foolish */ (void) sprintf(buf, "%g%s%s", v->va_real, DIR_PATHSEP, name); break; } if ((fp = fopen(buf, mode))) return (fp); v = v->va_next; } return (NULL);}/*------------------------------------------------------------------------- * Read the entire input file and return a pointer to the first line of * the linked list of 'card' records in data. The pointer is stored in * *data. *-------------------------------------------------------------------------*/voidinp_readall(FILE *fp, struct line **data){ struct line *end = NULL, *cc = NULL, *prev = NULL, *working, *newcard; char *buffer, *s, *t, c; /* segfault fix */ char *copys=NULL; int line_number = 1; /* sjb - renamed to avoid confusion with struct line */ FILE *newfp; /* Must set this to NULL or non-tilde includes segfault. -- Tim Molteno */ /* copys = NULL; */ /* This caused a parse error with gcc 2.96. Why??? *//* gtri - modify - 12/12/90 - wbk - read from mailbox if ipc enabled */#ifdef XSPICE Ipc_Status_t ipc_status; char ipc_buffer[1025]; /* Had better be big enough */ int ipc_len; /* First read in all lines & put them in the struct cc */ while (1) { /* If IPC is not enabled, do equivalent of what SPICE did before */ if(! g_ipc.enabled) { 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 = (void *) MALLOC(strlen(ipc_buffer) + 3); strcpy(buffer, ipc_buffer); strcat(buffer, "\n"); } else { /* No good way to report this so just die */ exit(1); } }/* gtri - end - 12/12/90 */#else while ((buffer = readline(fp))) {#endif#ifdef TRACE /* SDB debug statement */ printf ("in inp_readall, just read '%s' . . .\n", buffer); #endif /* OK -- now we have loaded the next line into 'buffer'. Process it. */ /* If input line is blank, ignore it & continue looping. */ if ( (strcmp(buffer,"\n") == 0) || (strcmp(buffer,"\r\n") == 0) ) { continue; } if (*buffer == '@') { tfree(buffer); /* was allocated by readline() */ break; } /* loop through 'buffer' until end is reached. Then test for premature end. If premature end is reached, spew error and zap the line. */ for (s = buffer; *s && (*s != '\n'); s++); if (!*s) { fprintf(cp_err, "Warning: premature EOF\n"); } *s = '\0'; /* Zap the newline. */ if(*(s-1) == '\r') /* Zop the carriage return under windows */ *(s-1) = '\0'; /* now handle .include statements */ if (ciprefix(".include", buffer)) { for (s = buffer; *s && !isspace(*s); s++) /* advance past non-space chars */ ; while (isspace(*s)) /* now advance past space chars */ s++; if (!*s) { /* if at end of line, error */ fprintf(cp_err, "Error: .include filename missing\n"); tfree(buffer); /* was allocated by readline() */ continue; } /* Now s points to first char after .include */ for (t = s; *t && !isspace(*t); t++) /* now advance past non-space chars */ ; *t = '\0'; /* place \0 and end of file name in buffer */ if (*s == '~') { copys = cp_tildexpand(s); /* allocates memory, but can also return NULL */ if(copys != NULL) { s = copys; /* reuse s, but remember, buffer still points to allocated memory */ }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -