Add (enhanced) patch by Giles Atkinson
Add controlled_exit() to errors when parsing functions. Add verbose error messages, including line number and name of the source file. .lib file handlinmg with its recursive structure probably needs testing and improvements. More error messages may need this update.
This commit is contained in:
parent
8d539aa9ba
commit
279fe0afcf
|
|
@ -583,7 +583,12 @@ static struct library *read_a_lib(const char *y, const char *dir_name)
|
||||||
lib->habitat = ngdirname(yy);
|
lib->habitat = ngdirname(yy);
|
||||||
|
|
||||||
lib->deck =
|
lib->deck =
|
||||||
inp_read(newfp, 1 /*dummy*/, lib->habitat, NULL, FALSE, FALSE).cc;
|
inp_read(newfp, 1 /*dummy*/, lib->habitat, lib->realpath, FALSE, FALSE).cc;
|
||||||
|
|
||||||
|
struct card* tmpdeck;
|
||||||
|
int cnumber = 1;
|
||||||
|
for (tmpdeck = lib->deck; tmpdeck; tmpdeck = tmpdeck->nextcard)
|
||||||
|
tmpdeck->linenum_orig = cnumber++;
|
||||||
|
|
||||||
fclose(newfp);
|
fclose(newfp);
|
||||||
}
|
}
|
||||||
|
|
@ -1432,17 +1437,14 @@ static struct inp_read_t inp_read(FILE* fp, int call_depth, const char* dir_name
|
||||||
if (!y_resolved) {
|
if (!y_resolved) {
|
||||||
fprintf(cp_err, "Error: Could not find include file %s\n",
|
fprintf(cp_err, "Error: Could not find include file %s\n",
|
||||||
y);
|
y);
|
||||||
if (ft_stricterror)
|
|
||||||
controlled_exit(EXIT_FAILURE);
|
controlled_exit(EXIT_FAILURE);
|
||||||
rv.line_number = line_number;
|
|
||||||
rv.cc = NULL;
|
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
newfp = fopen(y_resolved, "r");
|
newfp = fopen(y_resolved, "r");
|
||||||
|
|
||||||
if (!newfp) {
|
if (!newfp) {
|
||||||
fprintf(cp_err, "Error: .include statement failed.\n");
|
fprintf(cp_err, "Error: .include statement failed.\n"
|
||||||
|
"Could not open file\n%s\n", y_resolved);
|
||||||
tfree(buffer); /* allocated by readline() above */
|
tfree(buffer); /* allocated by readline() above */
|
||||||
controlled_exit(EXIT_FAILURE);
|
controlled_exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
@ -1465,8 +1467,12 @@ static struct inp_read_t inp_read(FILE* fp, int call_depth, const char* dir_name
|
||||||
|
|
||||||
/* append `buffer' to the (cc, end) chain of decks */
|
/* append `buffer' to the (cc, end) chain of decks */
|
||||||
{
|
{
|
||||||
|
if (end)
|
||||||
end = insert_new_line(
|
end = insert_new_line(
|
||||||
end, copy(buffer), line_number, end->linenum_orig, end->linesource);
|
end, copy(buffer), line_number, end->linenum_orig, end->linesource);
|
||||||
|
else
|
||||||
|
end = insert_new_line(
|
||||||
|
end, copy(buffer), line_number, 1, file_name);
|
||||||
|
|
||||||
if (!cc)
|
if (!cc)
|
||||||
cc = end;
|
cc = end;
|
||||||
|
|
@ -5868,8 +5874,10 @@ static void inp_compat(struct card *card)
|
||||||
&cut_line, '}', TRUE, TRUE); /* expression */
|
&cut_line, '}', TRUE, TRUE); /* expression */
|
||||||
if (!expression || !str_ptr) {
|
if (!expression || !str_ptr) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Error: bad syntax in line %d\n %s\n",
|
"Error: bad syntax in line %d\n %s\n"
|
||||||
card->linenum_orig, card->line);
|
"from file\n"
|
||||||
|
" %s\n",
|
||||||
|
card->linenum_orig, card->line, card->linesource);
|
||||||
controlled_exit(EXIT_BAD);
|
controlled_exit(EXIT_BAD);
|
||||||
}
|
}
|
||||||
tfree(str_ptr);
|
tfree(str_ptr);
|
||||||
|
|
@ -6063,8 +6071,11 @@ static void inp_compat(struct card *card)
|
||||||
// skip "table"
|
// skip "table"
|
||||||
cut_line = skip_ws(cut_line);
|
cut_line = skip_ws(cut_line);
|
||||||
if (!ciprefix("table", cut_line)) {
|
if (!ciprefix("table", cut_line)) {
|
||||||
fprintf(stderr, "Error: bad syntax in line %d\n %s\n",
|
fprintf(stderr,
|
||||||
card->linenum_orig, card->line);
|
"Error: bad syntax in line %d\n %s\n"
|
||||||
|
"from file\n"
|
||||||
|
" %s\n",
|
||||||
|
card->linenum_orig, card->line, card->linesource);
|
||||||
controlled_exit(EXIT_BAD);
|
controlled_exit(EXIT_BAD);
|
||||||
}
|
}
|
||||||
cut_line += 5;
|
cut_line += 5;
|
||||||
|
|
@ -6075,8 +6086,11 @@ static void inp_compat(struct card *card)
|
||||||
str_ptr = gettok_char(&cut_line, '{', FALSE, FALSE);
|
str_ptr = gettok_char(&cut_line, '{', FALSE, FALSE);
|
||||||
expression = gettok_char(&cut_line, '}', TRUE, TRUE);
|
expression = gettok_char(&cut_line, '}', TRUE, TRUE);
|
||||||
if (!expression || !str_ptr) {
|
if (!expression || !str_ptr) {
|
||||||
fprintf(stderr, "Error: bad syntax in line %d\n %s\n",
|
fprintf(stderr,
|
||||||
card->linenum_orig, card->line);
|
"Error: bad syntax in line %d\n %s\n"
|
||||||
|
"from file\n"
|
||||||
|
" %s\n",
|
||||||
|
card->linenum_orig, card->line, card->linesource);
|
||||||
controlled_exit(EXIT_BAD);
|
controlled_exit(EXIT_BAD);
|
||||||
}
|
}
|
||||||
tfree(str_ptr);
|
tfree(str_ptr);
|
||||||
|
|
|
||||||
|
|
@ -1369,7 +1369,11 @@ struct card *pspice_compat(struct card *oldcard)
|
||||||
for (i = 0; i < 6; i++) {
|
for (i = 0; i < 6; i++) {
|
||||||
stoks[i] = gettok_node(&cut_line);
|
stoks[i] = gettok_node(&cut_line);
|
||||||
if (!stoks[i]) {
|
if (!stoks[i]) {
|
||||||
fprintf(stderr, "Error: Bad syntax in line:\n %s\n", card->line);
|
fprintf(stderr,
|
||||||
|
"Error: bad syntax in line %d\n %s\n"
|
||||||
|
"from file\n"
|
||||||
|
" %s\n",
|
||||||
|
card->linenum_orig, card->line, card->linesource);
|
||||||
good = FALSE;
|
good = FALSE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,9 @@ struct INPmodel {
|
||||||
GENmodel *INPmodfast; /* high speed pointer to model for access */
|
GENmodel *INPmodfast; /* high speed pointer to model for access */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Ugly way to pass line onfo (number and source file) to lower-level error handlers.
|
||||||
|
extern int Current_parse_line;
|
||||||
|
extern char* Sourcefile;
|
||||||
|
|
||||||
/* listing types - used for debug listings */
|
/* listing types - used for debug listings */
|
||||||
#define LOGICAL 1
|
#define LOGICAL 1
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,9 @@ Author: 1985 Thomas L. Quarles
|
||||||
/* gtri - end - wbk - 11/9/90 */
|
/* gtri - end - wbk - 11/9/90 */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Ugly way to pass line info (number and source file) to lower-level error handlers.
|
||||||
|
int Current_parse_line;
|
||||||
|
char* Sourcefile;
|
||||||
|
|
||||||
/* uncomment to trace in this file */
|
/* uncomment to trace in this file */
|
||||||
/*#define TRACE*/
|
/*#define TRACE*/
|
||||||
|
|
@ -41,10 +44,6 @@ void INPpas2(CKTcircuit *ckt, struct card *data, INPtables * tab, TSKtask *task)
|
||||||
printf("Entered INPpas2 . . . .\n");
|
printf("Entered INPpas2 . . . .\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef XSPICE
|
|
||||||
if (!ckt->CKTadevFlag) ckt->CKTadevFlag = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
error = INPgetTok(&groundname, &gname, 1);
|
error = INPgetTok(&groundname, &gname, 1);
|
||||||
if (error)
|
if (error)
|
||||||
data->error =
|
data->error =
|
||||||
|
|
@ -87,6 +86,10 @@ void INPpas2(CKTcircuit *ckt, struct card *data, INPtables * tab, TSKtask *task)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Current_parse_line =
|
||||||
|
current->linenum_orig ? current->linenum_orig : current->linenum;
|
||||||
|
Sourcefile = current->linesource;
|
||||||
|
|
||||||
c = *(current->line);
|
c = *(current->line);
|
||||||
if(islower_c(c))
|
if(islower_c(c))
|
||||||
c = toupper_c(c);
|
c = toupper_c(c);
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include "ngspice/ngspice.h"
|
#include "ngspice/ngspice.h"
|
||||||
#include "ngspice/inpptree.h"
|
#include "ngspice/inpptree.h"
|
||||||
|
#include "ngspice/inpdefs.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
@ -143,5 +144,11 @@ PTerror (YYLTYPE *locp, char **line, struct INPparseNode **retval, void *ckt, ch
|
||||||
NG_IGNORE(retval);
|
NG_IGNORE(retval);
|
||||||
NG_IGNORE(ckt);
|
NG_IGNORE(ckt);
|
||||||
|
|
||||||
fprintf (stderr, "\n%s: %s, parsing stopped at\n %s\n\n", __func__, s, locp->start);
|
fprintf (stderr,
|
||||||
|
"\nYYparse error, %s, in expression: parsing stopped at line %d"
|
||||||
|
"\n %s in %s\n"
|
||||||
|
"\nfrom file"
|
||||||
|
" %s\n\n",
|
||||||
|
s, Current_parse_line, locp->start, *line, Sourcefile);
|
||||||
|
controlled_exit(EXIT_BAD); // Unsafe to continue.
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1029,7 +1029,8 @@ static INPparseNode *prepare_PTF_PWL(INPparseNode *p)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (p->funcnum != PTF_PWL) {
|
if (p->funcnum != PTF_PWL) {
|
||||||
fprintf(stderr, "PWL-INFO: %s, very unexpected\n", __func__);
|
fprintf(stderr, "PWL-INFO: %s, very unexpected at line %d\nfrom file\n %s\n\n",
|
||||||
|
__func__, Current_parse_line, Sourcefile);
|
||||||
controlled_exit(EXIT_BAD);
|
controlled_exit(EXIT_BAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1041,7 +1042,10 @@ static INPparseNode *prepare_PTF_PWL(INPparseNode *p)
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
if (i<2 || (i%1)) {
|
if (i<2 || (i%1)) {
|
||||||
fprintf(stderr, "Error: PWL(expr, points...) needs an even and >=2 number of constant args\n");
|
fprintf(stderr,
|
||||||
|
"Error: PWL(expr, points...) needs an even and >=2 number "
|
||||||
|
"of constant args at line %d\nfrom file\n %s\n\n",
|
||||||
|
Current_parse_line, Sourcefile);
|
||||||
controlled_exit(EXIT_BAD);
|
controlled_exit(EXIT_BAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1060,9 +1064,12 @@ static INPparseNode *prepare_PTF_PWL(INPparseNode *p)
|
||||||
w->right->left->type == PT_CONSTANT) {
|
w->right->left->type == PT_CONSTANT) {
|
||||||
data->vals[i] = - w->right->left->constant;
|
data->vals[i] = - w->right->left->constant;
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "PWL-ERROR: %s, not a constant\n", __func__);
|
fprintf(stderr,
|
||||||
fprintf(stderr, " type = %d\n", w->right->type);
|
"Error: PWL(expr, points...) only *literal* points "
|
||||||
fprintf(stderr, "Error: PWL(expr, points...) only *literal* points are supported\n");
|
"are supported at line %d\nfrom file\n %s\n",
|
||||||
|
Current_parse_line, Sourcefile);
|
||||||
|
// In case #671, "Crash when loading an Infineon model: IR4427S",
|
||||||
|
// a crash occurred after this error. There can be no recovery.
|
||||||
controlled_exit(EXIT_BAD);
|
controlled_exit(EXIT_BAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1073,7 +1080,9 @@ static INPparseNode *prepare_PTF_PWL(INPparseNode *p)
|
||||||
|
|
||||||
for (i = 2 ; i < data->n ; i += 2)
|
for (i = 2 ; i < data->n ; i += 2)
|
||||||
if(data->vals[i-2] >= data->vals[i]) {
|
if(data->vals[i-2] >= data->vals[i]) {
|
||||||
fprintf(stderr, "Error: PWL(expr, points...) the abscissa of points must be ascending\n");
|
fprintf(stderr,
|
||||||
|
"Error: PWL(expr, points...) the abscissa of points "
|
||||||
|
"must be ascending at line %d\nfrom file\n %s\n", Current_parse_line, Sourcefile);
|
||||||
controlled_exit(EXIT_BAD);
|
controlled_exit(EXIT_BAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1110,13 +1119,15 @@ INPparseNode *PT_mkfnode(const char *fname, INPparseNode * arg)
|
||||||
char buf[128];
|
char buf[128];
|
||||||
|
|
||||||
if (!fname) {
|
if (!fname) {
|
||||||
fprintf(stderr, "Error: bogus function name \n");
|
fprintf(stderr, "Error: bogus function name at line %d\nfrom file\n %s\n",
|
||||||
return mkfirst(NULL, arg);
|
Current_parse_line, Sourcefile);
|
||||||
|
controlled_exit(EXIT_BAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!arg) {
|
if (!arg) {
|
||||||
fprintf(stderr, "Error: bad function arguments \n");
|
fprintf(stderr, "Error: bad function arguments at line %d\nfrom file\n %s\n",
|
||||||
return mkfirst(NULL, arg);
|
Current_parse_line, Sourcefile);
|
||||||
|
controlled_exit(EXIT_BAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure the case is ok. */
|
/* Make sure the case is ok. */
|
||||||
|
|
@ -1143,8 +1154,9 @@ INPparseNode *PT_mkfnode(const char *fname, INPparseNode * arg)
|
||||||
return mkfirst(p, arg);
|
return mkfirst(p, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "Error: bogus ternary_fcn form\n");
|
fprintf(stderr, "Error: bogus ternary_fcn form at line %d\nfrom file\n %s\n",
|
||||||
return mkfirst(NULL, arg);
|
Current_parse_line, Sourcefile);
|
||||||
|
controlled_exit(EXIT_BAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is used only to evaluate fcn gauss(a1, a2, a3) in .model files, where
|
/* This is used only to evaluate fcn gauss(a1, a2, a3) in .model files, where
|
||||||
|
|
@ -1160,8 +1172,9 @@ INPparseNode *PT_mkfnode(const char *fname, INPparseNode * arg)
|
||||||
double a3 = arg3->constant;
|
double a3 = arg3->constant;
|
||||||
|
|
||||||
if (a2 == 0.0 || a3 == 0.0) {
|
if (a2 == 0.0 || a3 == 0.0) {
|
||||||
fprintf(stderr, "Error: bogus gauss form\n");
|
fprintf(stderr, "Error: bogus gauss form at line %d\nfrom file\n %s\n",
|
||||||
return mkfirst(NULL, arg); //return mkcon(a1);
|
Current_parse_line, Sourcefile);
|
||||||
|
controlled_exit(EXIT_BAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mkcon(gauss(a1, a2, a3));
|
return mkcon(gauss(a1, a2, a3));
|
||||||
|
|
@ -1176,10 +1189,9 @@ INPparseNode *PT_mkfnode(const char *fname, INPparseNode * arg)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (i == NUM_FUNCS) {
|
if (i == NUM_FUNCS) {
|
||||||
fprintf(stderr, "Error: no such function '%s'\n", buf);
|
fprintf(stderr, "Error: no such function '%s' at line %d\nfrom file\n %s\n",
|
||||||
if (ft_stricterror)
|
buf, Current_parse_line, Sourcefile);
|
||||||
controlled_exit(EXIT_BAD);
|
controlled_exit(EXIT_BAD);
|
||||||
return mkfirst(NULL, arg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p = TMALLOC(INPparseNode, 1);
|
p = TMALLOC(INPparseNode, 1);
|
||||||
|
|
@ -1196,10 +1208,9 @@ INPparseNode *PT_mkfnode(const char *fname, INPparseNode * arg)
|
||||||
if (p->funcnum == PTF_PWL) {
|
if (p->funcnum == PTF_PWL) {
|
||||||
p = prepare_PTF_PWL(p);
|
p = prepare_PTF_PWL(p);
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
fprintf(stderr, "Error while parsing function '%s'\n", buf);
|
fprintf(stderr, "Error while parsing function '%s' at line %d\nfrom file\n %s\n",
|
||||||
if (ft_stricterror)
|
buf, Current_parse_line, Sourcefile);
|
||||||
controlled_exit(EXIT_BAD);
|
controlled_exit(EXIT_BAD);
|
||||||
return mkfirst(NULL, arg);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue