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->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);
|
||||
}
|
||||
|
|
@ -1432,17 +1437,14 @@ static struct inp_read_t inp_read(FILE* fp, int call_depth, const char* dir_name
|
|||
if (!y_resolved) {
|
||||
fprintf(cp_err, "Error: Could not find include file %s\n",
|
||||
y);
|
||||
if (ft_stricterror)
|
||||
controlled_exit(EXIT_FAILURE);
|
||||
rv.line_number = line_number;
|
||||
rv.cc = NULL;
|
||||
return rv;
|
||||
controlled_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
newfp = fopen(y_resolved, "r");
|
||||
|
||||
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 */
|
||||
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 */
|
||||
{
|
||||
end = insert_new_line(
|
||||
end, copy(buffer), line_number, end->linenum_orig, end->linesource);
|
||||
if (end)
|
||||
end = insert_new_line(
|
||||
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)
|
||||
cc = end;
|
||||
|
|
@ -5868,8 +5874,10 @@ static void inp_compat(struct card *card)
|
|||
&cut_line, '}', TRUE, TRUE); /* expression */
|
||||
if (!expression || !str_ptr) {
|
||||
fprintf(stderr,
|
||||
"Error: bad syntax in line %d\n %s\n",
|
||||
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);
|
||||
}
|
||||
tfree(str_ptr);
|
||||
|
|
@ -6063,8 +6071,11 @@ static void inp_compat(struct card *card)
|
|||
// skip "table"
|
||||
cut_line = skip_ws(cut_line);
|
||||
if (!ciprefix("table", cut_line)) {
|
||||
fprintf(stderr, "Error: bad syntax in line %d\n %s\n",
|
||||
card->linenum_orig, 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);
|
||||
controlled_exit(EXIT_BAD);
|
||||
}
|
||||
cut_line += 5;
|
||||
|
|
@ -6075,8 +6086,11 @@ static void inp_compat(struct card *card)
|
|||
str_ptr = gettok_char(&cut_line, '{', FALSE, FALSE);
|
||||
expression = gettok_char(&cut_line, '}', TRUE, TRUE);
|
||||
if (!expression || !str_ptr) {
|
||||
fprintf(stderr, "Error: bad syntax in line %d\n %s\n",
|
||||
card->linenum_orig, 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);
|
||||
controlled_exit(EXIT_BAD);
|
||||
}
|
||||
tfree(str_ptr);
|
||||
|
|
|
|||
|
|
@ -1369,7 +1369,11 @@ struct card *pspice_compat(struct card *oldcard)
|
|||
for (i = 0; i < 6; i++) {
|
||||
stoks[i] = gettok_node(&cut_line);
|
||||
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;
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,7 +97,9 @@ struct INPmodel {
|
|||
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 */
|
||||
#define LOGICAL 1
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@ Author: 1985 Thomas L. Quarles
|
|||
/* gtri - end - wbk - 11/9/90 */
|
||||
#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 */
|
||||
/*#define TRACE*/
|
||||
|
|
@ -41,10 +44,6 @@ void INPpas2(CKTcircuit *ckt, struct card *data, INPtables * tab, TSKtask *task)
|
|||
printf("Entered INPpas2 . . . .\n");
|
||||
#endif
|
||||
|
||||
#ifdef XSPICE
|
||||
if (!ckt->CKTadevFlag) ckt->CKTadevFlag = 0;
|
||||
#endif
|
||||
|
||||
error = INPgetTok(&groundname, &gname, 1);
|
||||
if (error)
|
||||
data->error =
|
||||
|
|
@ -81,12 +80,16 @@ void INPpas2(CKTcircuit *ckt, struct card *data, INPtables * tab, TSKtask *task)
|
|||
#endif
|
||||
|
||||
#ifdef HAS_PROGREP
|
||||
if (linecount > 0) {
|
||||
if (linecount > 0) {
|
||||
SetAnalyse( "Parse", (int) (1000.*actcount/linecount));
|
||||
actcount++;
|
||||
}
|
||||
#endif
|
||||
|
||||
Current_parse_line =
|
||||
current->linenum_orig ? current->linenum_orig : current->linenum;
|
||||
Sourcefile = current->linesource;
|
||||
|
||||
c = *(current->line);
|
||||
if(islower_c(c))
|
||||
c = toupper_c(c);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "ngspice/ngspice.h"
|
||||
#include "ngspice/inpptree.h"
|
||||
#include "ngspice/inpdefs.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
|
@ -143,5 +144,11 @@ PTerror (YYLTYPE *locp, char **line, struct INPparseNode **retval, void *ckt, ch
|
|||
NG_IGNORE(retval);
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
@ -1041,7 +1042,10 @@ static INPparseNode *prepare_PTF_PWL(INPparseNode *p)
|
|||
i++;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
@ -1060,10 +1064,13 @@ static INPparseNode *prepare_PTF_PWL(INPparseNode *p)
|
|||
w->right->left->type == PT_CONSTANT) {
|
||||
data->vals[i] = - w->right->left->constant;
|
||||
} else {
|
||||
fprintf(stderr, "PWL-ERROR: %s, not a constant\n", __func__);
|
||||
fprintf(stderr, " type = %d\n", w->right->type);
|
||||
fprintf(stderr, "Error: PWL(expr, points...) only *literal* points are supported\n");
|
||||
controlled_exit(EXIT_BAD);
|
||||
fprintf(stderr,
|
||||
"Error: PWL(expr, points...) only *literal* points "
|
||||
"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);
|
||||
}
|
||||
|
||||
#ifdef TRACE
|
||||
|
|
@ -1073,7 +1080,9 @@ static INPparseNode *prepare_PTF_PWL(INPparseNode *p)
|
|||
|
||||
for (i = 2 ; i < data->n ; i += 2)
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
@ -1110,13 +1119,15 @@ INPparseNode *PT_mkfnode(const char *fname, INPparseNode * arg)
|
|||
char buf[128];
|
||||
|
||||
if (!fname) {
|
||||
fprintf(stderr, "Error: bogus function name \n");
|
||||
return mkfirst(NULL, arg);
|
||||
fprintf(stderr, "Error: bogus function name at line %d\nfrom file\n %s\n",
|
||||
Current_parse_line, Sourcefile);
|
||||
controlled_exit(EXIT_BAD);
|
||||
}
|
||||
|
||||
if (!arg) {
|
||||
fprintf(stderr, "Error: bad function arguments \n");
|
||||
return mkfirst(NULL, arg);
|
||||
fprintf(stderr, "Error: bad function arguments at line %d\nfrom file\n %s\n",
|
||||
Current_parse_line, Sourcefile);
|
||||
controlled_exit(EXIT_BAD);
|
||||
}
|
||||
|
||||
/* Make sure the case is ok. */
|
||||
|
|
@ -1143,8 +1154,9 @@ INPparseNode *PT_mkfnode(const char *fname, INPparseNode * arg)
|
|||
return mkfirst(p, arg);
|
||||
}
|
||||
|
||||
fprintf(stderr, "Error: bogus ternary_fcn form\n");
|
||||
return mkfirst(NULL, arg);
|
||||
fprintf(stderr, "Error: bogus ternary_fcn form at line %d\nfrom file\n %s\n",
|
||||
Current_parse_line, Sourcefile);
|
||||
controlled_exit(EXIT_BAD);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
if (a2 == 0.0 || a3 == 0.0) {
|
||||
fprintf(stderr, "Error: bogus gauss form\n");
|
||||
return mkfirst(NULL, arg); //return mkcon(a1);
|
||||
fprintf(stderr, "Error: bogus gauss form at line %d\nfrom file\n %s\n",
|
||||
Current_parse_line, Sourcefile);
|
||||
controlled_exit(EXIT_BAD);
|
||||
}
|
||||
|
||||
return mkcon(gauss(a1, a2, a3));
|
||||
|
|
@ -1176,10 +1189,9 @@ INPparseNode *PT_mkfnode(const char *fname, INPparseNode * arg)
|
|||
break;
|
||||
|
||||
if (i == NUM_FUNCS) {
|
||||
fprintf(stderr, "Error: no such function '%s'\n", buf);
|
||||
if (ft_stricterror)
|
||||
controlled_exit(EXIT_BAD);
|
||||
return mkfirst(NULL, arg);
|
||||
fprintf(stderr, "Error: no such function '%s' at line %d\nfrom file\n %s\n",
|
||||
buf, Current_parse_line, Sourcefile);
|
||||
controlled_exit(EXIT_BAD);
|
||||
}
|
||||
|
||||
p = TMALLOC(INPparseNode, 1);
|
||||
|
|
@ -1196,10 +1208,9 @@ INPparseNode *PT_mkfnode(const char *fname, INPparseNode * arg)
|
|||
if (p->funcnum == PTF_PWL) {
|
||||
p = prepare_PTF_PWL(p);
|
||||
if (p == NULL) {
|
||||
fprintf(stderr, "Error while parsing function '%s'\n", buf);
|
||||
if (ft_stricterror)
|
||||
controlled_exit(EXIT_BAD);
|
||||
return mkfirst(NULL, arg);
|
||||
fprintf(stderr, "Error while parsing function '%s' at line %d\nfrom file\n %s\n",
|
||||
buf, Current_parse_line, Sourcefile);
|
||||
controlled_exit(EXIT_BAD);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue