diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index a5a811252..134dcbdcc 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -103,6 +103,7 @@ int dynMaxckt = 0; /* subckt.c 307 */ /* number of parameter substitutions */ long dynsubst; /* spicenum.c 221 */ +static bool has_if = FALSE; /* if we have an .if ... .endif pair */ static char *readline(FILE *fd); static int get_number_terminals(char *c); @@ -143,7 +144,7 @@ static void subckt_params_to_param(struct card *deck); static void inp_fix_temper_in_param(struct card *deck); static void inp_fix_agauss_in_param(struct card *deck, char *fcn); static void inp_vdmos_model(struct card *deck); -static void inp_check_control(struct card *deck); +static void inp_check_syntax(struct card *deck); static char *inp_spawn_brace(char *s); @@ -585,10 +586,14 @@ inp_readall(FILE *fp, char *dir_name, bool comfile, bool intfile, bool *expr_w_t struct card *tmp_ptr1; struct names *subckt_w_params = new_names(); + /* skip title line */ struct card *working = cc->nextcard; delete_libs(); + /* some syntax checks, including title line */ + inp_check_syntax(cc); + if(inp_compat_mode == COMPATMODE_LTA) ltspice_compat_a(working); else if(inp_compat_mode == COMPATMODE_PSA) @@ -598,15 +603,15 @@ inp_readall(FILE *fp, char *dir_name, bool comfile, bool intfile, bool *expr_w_t pspice_compat_a(working); } - inp_check_control(working); - inp_fix_for_numparam(subckt_w_params, working); inp_remove_excess_ws(working); inp_vdmos_model(working); - - comment_out_unused_subckt_models(working); + /* don't remove unused model if we have an .if clause, because we cannot yet + decide here which model we finally will need */ + if (!has_if) + comment_out_unused_subckt_models(working); subckt_params_to_param(working); @@ -7675,11 +7680,20 @@ ltspice_compat_a(struct card *oldcard) oldcard->nextcard = ltspice_compat(oldcard->nextcard); } -/* check if we have a .control ... .endc pair */ -static void inp_check_control(struct card *deck) +/* syntax check: + Check if we have a .control ... .endc pair, + a .if ... .endif pair, a .suckt ... .ends pair */ +static void inp_check_syntax(struct card *deck) { struct card *card; - int check_control = 0; + int check_control = 0, check_subs = 0, check_if = 0; + + /* will lead to crash in inp.c, fcn inp_spsource */ + if (ciprefix(".param", deck->line) || ciprefix(".meas", deck->line)) { + fprintf(cp_err, "\nError: title line is missing!\n\n"); + controlled_exit(EXIT_BAD); + } + for (card = deck; card; card = card->nextcard) { char *cut_line = card->line; if (*cut_line == '*') @@ -7697,10 +7711,44 @@ static void inp_check_control(struct card *deck) check_control--; continue; } + // check for .subckt ... .ends + else if (ciprefix(".subckt", cut_line)) { + if (check_subs > 0) + fprintf(cp_err, "\nWarning: Nesting of subcircuits is only marginally supported!\n\n"); + check_subs++; + continue; + } + else if (ciprefix(".ends", cut_line)) { + check_subs--; + continue; + } + // check for .if ... .endif + if (ciprefix(".if", cut_line)) { + check_if++; + has_if = TRUE; + continue; + } + else if (ciprefix(".endif", cut_line)) { + check_if--; + continue; + } } if (check_control > 0) { fprintf(cp_err, "\nWarning: Missing .endc statement!\n"); fprintf(cp_err, " This may cause subsequent errors.\n\n"); } + if (check_control < 0) { + fprintf(cp_err, "\nWarning: Missing .control statement!\n"); + fprintf(cp_err, " This may cause subsequent errors.\n\n"); + } + if (check_subs != 0) { + fprintf(cp_err, "\nError: Mismatch of .subckt ... .ends statements!\n"); + fprintf(cp_err, " This will cause subsequent errors.\n\n"); + controlled_exit(EXIT_BAD); + } + if (check_if != 0) { + fprintf(cp_err, "\nError: Mismatch of .if ... .endif statements!\n"); + fprintf(cp_err, " This may cause subsequent errors.\n\n"); + } }