inpcom.c: rewrite .lib processing

This commit is contained in:
rlar 2013-05-18 09:47:06 +02:00
parent 0cf4fa381c
commit e0b56ca877
1 changed files with 90 additions and 216 deletions

View File

@ -20,6 +20,7 @@ Author: 1985 Wayne A. Christopher
#include "inpcom.h"
#include "variable.h"
#include "subckt.h"
#include "../misc/util.h" /* ngdirname() */
#include "ngspice/stringutil.h"
#include "ngspice/wordlist.h"
@ -42,11 +43,8 @@ Author: 1985 Wayne A. Christopher
#define N_SUBCKT_W_PARAMS 4000
static char *library_name[N_LIBRARY];
static char *section_name[N_LIBRARY][N_SECTIONS];
static struct line *section_ref[N_LIBRARY][N_SECTIONS];
static struct line *library_deck[N_LIBRARY];
static int num_libraries;
static int num_sections[N_LIBRARY];
static char *global;
static char *subckt_w_params[N_SUBCKT_W_PARAMS];
static int num_subckt_w_params;
@ -72,8 +70,7 @@ static void inp_stripcomments_deck(struct line *deck);
static void inp_stripcomments_line(char *s);
static void inp_fix_for_numparam(struct line *deck);
static void inp_remove_excess_ws(struct line *deck);
static void collect_section_references(struct line *deck, char *section_name_);
static void inp_init_lib_data(void);
static void expand_section_references(struct line *deck, int call_depth, char *dir_name);
static void inp_grab_func(struct line *deck);
static void inp_fix_inst_calls_for_numparam(struct line *deck);
static void inp_expand_macros_in_func(void);
@ -121,25 +118,41 @@ find_lib(char *name)
}
static int
find_section(int lib_idx, char *section_name_) {
int j;
for (j = 0; j < num_sections[lib_idx]; j++)
if (strcmp(section_name[lib_idx][j], section_name_) == 0)
return j;
return -1;
}
static struct line *
find_section_definition(struct line *deck, char *name)
{
struct line *c;
for (c = deck; c; c = c->li_next) {
char *line = c->li_line;
if (ciprefix(".lib", line)) {
char *s, *t, *y;
s = skip_non_ws(line);
while (isspace(*s) || isquote(*s))
s++;
for (t = s; *t && !isspace(*t) && !isquote(*t); t++)
;
y = t;
while (isspace(*y) || isquote(*y))
y++;
static void
remember_section_ref(int lib_idx, char *section_name_, struct line *deck) {
int section_idx = num_sections[lib_idx]++;
if (section_idx >= N_SECTIONS) {
fprintf(stderr, "ERROR, N_SECTIONS overflow\n");
controlled_exit(EXIT_FAILURE);
if (!*y) {
/* library section definition: `.lib <section-name>' .. `.endl' */
char keep_char = *t;
*t = '\0';
if (strcasecmp(name, s) == 0) {
*t = keep_char;
return c;
}
*t = keep_char;
}
}
}
section_ref[lib_idx][section_idx] = deck;
section_name[lib_idx][section_idx] = strdup(section_name_);
return NULL;
}
@ -203,116 +216,6 @@ read_a_lib(char *y, int call_depth, char *dir_name)
}
static int
expand_section_references(int line_number)
{
struct line *tmp_ptr = NULL, *next;
int lib_idx;
for (lib_idx = 0; lib_idx < num_libraries; lib_idx++) {
bool found_section = FALSE;
struct line *working = library_deck[lib_idx];
while (working) {
char *buffer = working->li_line;
if (found_section && ciprefix(".endl", buffer)) {
struct line *next = working->li_next;
/* Make the .endl a comment */
*buffer = '*';
found_section = FALSE;
/* append the line following the library section reference */
working->li_next = tmp_ptr;
/* and continue with the line following */
/* the .endl of this section definition */
working = next;
continue;
}
if (ciprefix(".lib", buffer)) {
/* here we expect a libray section definition */
/* library section definition: `.lib <section-name>' .. `.endl' */
char keep_char;
int section_idx;
char *s, *t;
if (found_section) {
fprintf(stderr, "ERROR: .lib is missing .endl!\n");
controlled_exit(EXIT_FAILURE);
}
s = skip_non_ws(buffer); /* skip over .lib */
while (isspace(*s) || isquote(*s))
s++; /* advance past space chars */
for (t = s; *t && !isspace(*t) && !isquote(*t); t++)
; /* skip to end of word */
keep_char = *t;
*t = '\0';
/* check if we remember this section having been referenced somewhere */
section_idx = find_section(lib_idx, s);
*t = keep_char;
found_section = (section_idx >= 0);
if (found_section) {
struct line *c;
int line_number_lib;
/* make the .lib of this library section definition a comment */
*buffer = '*';
/* tmp_ptr is the line following the library section reference */
tmp_ptr = section_ref[lib_idx][section_idx]->li_next;
/* insert the section definition here, */
/* just behind the remembered section reference */
section_ref[lib_idx][section_idx]->li_next = working;
/* renumber lines */
line_number_lib = 1;
for (c = working; !ciprefix(".endl", c->li_line); c = c->li_next) {
c->li_linenum = line_number++;
c->li_linenum_orig = line_number_lib++;
}
c->li_linenum = line_number++; // renumber endl line
c->li_linenum_orig = line_number_lib++;
}
}
next = working->li_next;
/* drop this line in the current library file, if
* it is outside a library section definition
* or
* it is part of an unused library section definition
*/
if (!found_section) {
tfree(working->li_line);
tfree(working);
}
working = next;
}
if (found_section) {
fprintf(stderr, "ERROR: .lib is missing .endl!\n");
controlled_exit(EXIT_FAILURE);
}
}
return line_number;
}
/*-------------------------------------------------------------------------
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
@ -481,50 +384,13 @@ inp_readall(FILE *fp, int call_depth, char *dir_name, bool comfile, bool intfile
/* now handle .lib statements */
if (ciprefix(".lib", buffer)) {
char *y = NULL; /* filename */
char *z = NULL; /* libname */
char *s, *t;
inp_stripcomments_line(buffer);
s = skip_non_ws(buffer); /* skip over .lib */
s = strdup(s);
t = get_quoted_token(s, &y);
if (!y) {
fprintf(cp_err, "Error: .lib filename missing\n");
tfree(buffer); /* was allocated by readline() */
controlled_exit(EXIT_FAILURE);
}
t = get_quoted_token(t, &z);
if (z && (inp_compat_mode == COMPATMODE_ALL ||
inp_compat_mode == COMPATMODE_HS ||
inp_compat_mode == COMPATMODE_NATIVE))
{
/* here we have a */
/* library section reference: `.lib <library-file> <section-name>' */
if(!read_a_lib(y, call_depth, dir_name)) {
tfree(s);
tfree(buffer);
controlled_exit(EXIT_FAILURE);
}
tfree(s);
/* Make the .lib a comment */
*buffer = '*';
} else if (inp_compat_mode == COMPATMODE_PS) {
if (inp_compat_mode == COMPATMODE_PS) {
/* compatibility mode,
* this is neither a libray section definition nor a reference
* interpret as old style
* .lib <file name> (no lib name given)
*/
fprintf(cp_err, "Warning: library name missing in line\n %s", buffer);
char *s = skip_non_ws(buffer); /* skip over .lib */
fprintf(cp_err, " File included as: .inc %s\n", s);
memcpy(buffer, ".inc", 4);
}
@ -638,6 +504,7 @@ inp_readall(FILE *fp, int call_depth, char *dir_name, bool comfile, bool intfile
char *s;
if ( !ciprefix("write", buffer) &&
!ciprefix(".lib", buffer) &&
!ciprefix("codemodel", buffer) &&
!ciprefix("use", buffer) &&
!ciprefix("load", buffer)
@ -715,16 +582,13 @@ inp_readall(FILE *fp, int call_depth, char *dir_name, bool comfile, bool intfile
cc->li_next = global_card;
global_card->li_next = prev;
inp_init_lib_data();
collect_section_references(cc, NULL);
}
/*
add libraries
*/
if (call_depth == 0) {
line_number = expand_section_references(line_number);
if (inp_compat_mode == COMPATMODE_ALL ||
inp_compat_mode == COMPATMODE_HS ||
inp_compat_mode == COMPATMODE_NATIVE)
{
/* process all library section references */
expand_section_references(cc, call_depth, dir_name);
}
}
/*
@ -2345,7 +2209,7 @@ inp_fix_for_numparam(struct line *deck)
char *str_ptr;
while (c != NULL) {
if (ciprefix("*lib", c->li_line) || ciprefix("*inc", c->li_line)) {
if (ciprefix(".lib", c->li_line) || ciprefix("*lib", c->li_line) || ciprefix("*inc", c->li_line)) {
c = c->li_next;
continue;
}
@ -2405,7 +2269,7 @@ inp_remove_excess_ws(struct line *deck)
/*
* recursively collect library section references,
* recursively expand library section references,
* either
* every library section reference (when the given section_name_ === NULL)
* or
@ -2413,20 +2277,15 @@ inp_remove_excess_ws(struct line *deck)
*/
static void
collect_section_references(struct line *deck, char *section_name_)
expand_section_references(struct line *deck, int call_depth, char *dir_name)
{
bool read_line = (section_name_ == NULL);
struct line *c;
for (c = deck; c; c = c->li_next) {
char *line = c->li_line;
if (ciprefix(".endl", line) && section_name_ != NULL)
read_line = FALSE;
if (ciprefix("*lib", line) || ciprefix(".lib", line)) {
if (ciprefix(".lib", line)) {
char *s, *t, *y;
@ -2439,19 +2298,10 @@ collect_section_references(struct line *deck, char *section_name_)
while (isspace(*y) || isquote(*y))
y++;
if (!*y) {
/* library section definition: `.lib <section-name>' .. `.endl' */
char keep_char = *t;
*t = '\0';
if (section_name_ != NULL && strcmp(section_name_, s) == 0)
read_line = TRUE;
*t = keep_char;
}
else if (read_line == TRUE) {
if (*y) {
/* library section reference: `.lib <library-file> <section-name>' */
struct line *section_def;
char keep_char1, keep_char2;
char *z, *copys = NULL;
int lib_idx;
@ -2468,14 +2318,48 @@ collect_section_references(struct line *deck, char *section_name_)
if (copys)
s = copys;
}
lib_idx = find_lib(s);
if (lib_idx >= 0)
if (find_section(lib_idx, y) < 0) {
/* remember this section having been referenced */
remember_section_ref(lib_idx, y, c);
/* recursively check for nested section references */
collect_section_references(library_deck[lib_idx], y);
if (lib_idx < 0) {
if(!read_a_lib(s, call_depth, dir_name))
controlled_exit(EXIT_FAILURE);
lib_idx = find_lib(s);
}
if (lib_idx < 0) {
fprintf(stderr, "ERROR, library file %s not found\n", s);
controlled_exit(EXIT_FAILURE);
}
section_def = find_section_definition(library_deck[lib_idx], y);
if (!section_def) {
fprintf(stderr, "ERROR, library file %s, section definition %s not found\n", s, y);
controlled_exit(EXIT_FAILURE);
}
/* insert the library section definition into `c' */
{
struct line *t = inp_deckcopy(section_def);
struct line *rest = c->li_next;
c->li_next = t;
t->li_line[0] = '*';
t->li_line[1] = '<';
for (; t; t=t->li_next)
if(ciprefix(".endl", t->li_line))
break;
if (!t) {
fprintf(stderr, "ERROR, .endl not found\n");
controlled_exit(EXIT_FAILURE);
}
t->li_line[0] = '*';
t->li_line[1] = '>';
t->li_next = rest;
}
*line = '*'; /* comment out .lib line */
*t = keep_char1;
*z = keep_char2;
@ -2487,16 +2371,6 @@ collect_section_references(struct line *deck, char *section_name_)
}
static void
inp_init_lib_data(void)
{
int i;
for (i = 0; i < num_libraries; i++)
num_sections[i] = 0;
}
static char*
inp_get_subckt_name(char *s)
{