Browse Source

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.
pre-master-46
Holger Vogt 2 years ago
parent
commit
97d9f38421
  1. 44
      src/frontend/inpcom.c
  2. 6
      src/frontend/inpcompat.c
  3. 4
      src/include/ngspice/inpdefs.h
  4. 13
      src/spicelib/parser/inppas2.c
  5. 9
      src/spicelib/parser/inpptree-parser.y
  6. 57
      src/spicelib/parser/inpptree.c

44
src/frontend/inpcom.c

@ -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);
rv.line_number = line_number;
rv.cc = NULL;
return rv;
controlled_exit(EXIT_FAILURE);
} }
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 */
{ {
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) 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",
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);
@ -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",
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); 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",
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); controlled_exit(EXIT_BAD);
} }
tfree(str_ptr); tfree(str_ptr);

6
src/frontend/inpcompat.c

@ -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;
} }

4
src/include/ngspice/inpdefs.h

@ -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

13
src/spicelib/parser/inppas2.c

@ -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 =
@ -81,12 +80,16 @@ void INPpas2(CKTcircuit *ckt, struct card *data, INPtables * tab, TSKtask *task)
#endif #endif
#ifdef HAS_PROGREP #ifdef HAS_PROGREP
if (linecount > 0) {
if (linecount > 0) {
SetAnalyse( "Parse", (int) (1000.*actcount/linecount)); SetAnalyse( "Parse", (int) (1000.*actcount/linecount));
actcount++; actcount++;
} }
#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);

9
src/spicelib/parser/inpptree-parser.y

@ -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.
} }

57
src/spicelib/parser/inpptree.c

@ -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,10 +1064,13 @@ 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, " 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 #ifdef TRACE
@ -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");
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) { 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. */ /* 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");
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 /* 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");
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)); 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);
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); 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);
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…
Cancel
Save