Jspice3
inptabpa.c
Go to the documentation of this file.
1 /***************************************************************************
2 JSPICE3 adaptation of Spice3e2 - Copyright (c) Stephen R. Whiteley 1992
3 Copyright 1990 Regents of the University of California. All rights reserved.
4 Authors: 1992 Stephen R. Whiteley
5 ****************************************************************************/
6 
7 /*
8  * Routines for parsing and checking data tables input by the user.
9  * Note: these tables are completely different from those manipulated
10  * with the INPsymTab routines.
11  */
12 
13 #include "spice.h"
14 #include <stdio.h>
15 #include "util.h"
16 #include "cpdefs.h"
17 #include "inpdefs.h"
18 #include "tabdefs.h"
19 #include "iferrmsg.h"
20 
21 /*
22 #define debug
23 */
24 
25 #ifdef __STDC__
26 static void tablfix(struct sCKTtable *);
27 static void testprnt(GENERIC*);
28 static int tabl_add(GENERIC*,struct sCKTtable*);
29 #else
30 static void tablfix();
31 static void testprnt();
32 static int tabl_add();
33 #endif
34 
35 char *
37 
38 /* Parse a line containing a table description of the form
39  * .table tabname [val1] {stuff1} val2 {stuff2} ... valN [{stuffN}]
40  * where {stuffI} can be:
41  * a real number, or
42  * function function_string, or
43  * table table_name.
44  * If the first val is omitted the first {stuff} must be a function or table.
45  * the last {stuff} can be omitted.
46  * The function_string must not contain but be surrounded by white space.
47  */
48 
49 char **line; /* the line to parse */
50 GENERIC *ckt; /* the circuit this device is a member of */
51 {
52  char *t, *errbuf;
53  int error;
54  struct sCKTtable *table;
55  struct sCKTentry *entry, *etmp;
56  double ord, val;
57 
58  /* throw out .table */
59  error = INPgetTok(line,&t,1);
60  if (error) return(INPerror(error));
61  txfree(t);
62 
63  if (*line == NULL) return NULL;
64 
65  error = INPgetTok(line,&t,1);
66  if (error) return(INPerror(error));
67  if (INPtablFind(t,ckt,(GENERIC **)NULL) == 0) {
68  /* already there - error */
69  errbuf = MALLOC(strlen(t) + 40);
70  (void) sprintf(errbuf," Table %d already defined - ignored\n",t);
71  txfree(t);
72  return errbuf;
73  }
74 
75  table = (struct sCKTtable *) MALLOC(sizeof(struct sCKTtable));
76  if (table == NULL) return(INPerror(E_NOMEM));
77  table->tab_name = t;
78 
79  while (**line != (char)0) {
80 
81  etmp = (struct sCKTentry *) MALLOC(sizeof(struct sCKTentry));
82  if (etmp == NULL) return(INPerror(E_NOMEM));
83 
84  if (table->tab_entry == NULL) {
85  entry = table->tab_entry = etmp;
86  ord = INPevaluate(line,&error,1);
87  if (error == 0)
88  entry->ent_val = ord;
89  else
90  entry->ent_val = 0;
91  }
92  else {
93  entry->ent_next = etmp;
94  entry = entry->ent_next;
95  ord = INPevaluate(line,&error,1);
96  if (error == 0)
97  entry->ent_val = ord;
98  else {
99  t = gettok(line);
100  errbuf = MALLOC(strlen(t) + 40);
101  (void) sprintf(errbuf,
102  " Syntax error: expected value, got %s\n",t);
103  txfree(t);
104  return errbuf;
105  }
106  }
107  if (**line == (char)0) {
108  /* last entry omitted */
109  entry->ent_type = ENT_OMITTED;
110  break;
111  }
112 
113  val = INPevaluate(line,&error,1);
114  if (error == 0) {
115  /* entry is a real */
116  entry->ent_type = ENT_NUMBER;
117  entry->ent_real = val;
118  continue;
119  }
120  error = INPgetTok(line,&t,1);
121  if (error) return(INPerror(error));
122 
123  if (strcmp(t,"table") == 0) {
124  /* table specified */
125  txfree(t);
126  entry->ent_type = ENT_TABLE;
127  error = INPgetTok(line,&t,1);
128  if (error) return(INPerror(error));
129  entry->ent_string = t;
130  continue;
131  }
132  /* uh-oh */
133  errbuf = MALLOC(strlen(t) + 40);
134  (void) sprintf(errbuf," Syntax error: unknown keyword %s\n",t);
135  txfree(t);
136  return errbuf;
137  }
138  tabl_add(ckt,table);
139  return NULL;
140 }
141 
142 /************************************************************************/
143 
144 
145 char *
147 
148 /* Check a .table line for sub-table existence. Returns NULL except if
149  * an undefined table reference is found. A syntax error will return NULL
150  * immediately, such errors are already flagged. If an unknown table
151  * is found, an error message is returned.
152  * If no syntx errors, fix up the corresponding table structure so that
153  * sub-table references are pointers to the sub-table, not to the name.
154  */
155 
156 char *line; /* the .table line to check (".table" stripped) */
157 GENERIC *ckt;
158 {
159  char *t, *errbuf = NULL;
160  int error;
161  struct sCKTtable *table, *tb, *tt;
162  struct sCKTentry *e;
163 
164  if (line == NULL) return NULL;
165 
166  error = INPgetTok(&line,&t,1); /* table name */
167  if (error) return(INPerror(error));
168 
169  (void)INPtablFind(NULL,ckt,(GENERIC**)&table);
170  if (table == NULL) {
171  /* no tables saved (syntax error) */
172  txfree(t);
173  return NULL;
174  }
175 
176  for (tb = table; tb; tb = tb->tab_next)
177  if (eq(t,tb->tab_name)) break;
178 
179  txfree(t);
180  if (tb == NULL) /* can't find own symbol (syntax error) */
181  return NULL;
182 
183  while (*line != (char)0) {
184 
185  (void) INPevaluate(&line,&error,1);
186  if (*line == (char)0) /* last entry was omitted */
187  break;
188  INPevaluate(&line,&error,1);
189  if (error == 0) continue; /* entry is a real */
190  error = INPgetTok(&line,&t,1);
191  if (error) return(INPerror(error));
192  if (strcmp(t,"table") == 0) {
193  /* table specified */
194  txfree(t);
195  error = INPgetTok(&line,&t,1); /* table reference */
196  if (error) return(INPerror(error));
197  if (INPtablFind(t,ckt,(GENERIC **)NULL) != 0) {
198  if (errbuf) {
199  char *temp = errbuf;
200  errbuf = MALLOC(strlen(temp) + strlen(t) + 40);
201  (void) sprintf(errbuf,
202  "%s Unresolved table reference: %s\n",temp,t);
203  }
204  else {
205  errbuf = MALLOC(strlen(t) + 40);
206  (void) sprintf(errbuf,
207  " Unresolved table reference: %s\n",t);
208  }
209  /* find the reference and null it */
210  for (e = tb->tab_entry; e; e = e->ent_next) {
211  if (e->ent_type != ENT_TABLE) continue;
212  if (e->ent_string && eq(e->ent_string,t)) {
213  tfree(e->ent_string); /* tfree NULLs it */
214  break;
215  }
216  }
217  }
218  txfree(t);
219  continue;
220  }
221  return NULL; /* syntax error */
222  }
223  /* no syntax errors */
224  /* replace known table name references with pointers to tables */
225 
226  for (e = tb->tab_entry; e; e = e->ent_next) {
227  if (e->ent_type == ENT_TABLE && e->ent_string != NULL) {
228  for (tt = table; tt; tt = tt->tab_next)
229  if (eq(e->ent_string,tt->tab_name)) {
230  /* replace with pointer to table */
231  txfree(e->ent_string);
232  e->ent_string = (char *)tt;
233  break;
234  }
235  }
236  }
237  return errbuf;
238 }
239 
240 /************************************************************************/
241 
242 
243 void
245 
246 /*
247  * Fix the actual values for the omitted final entries, and
248  * set the ent_real components to the function or table evaluated
249  * with the ent_val component.
250  */
251 
252 GENERIC *ckt;
253 {
254  struct sCKTtable *t;
255 
256  for (t = *DEVtableHead(ckt); t; t = t->tab_next)
257  tablfix(t);
258 
259 #ifdef debug
260  testprnt(ckt);
261 #endif
262 }
263 
264 /************************************************************************/
265 
266 
267 static void
269 
270 /*
271  * If the final entry argument is omitted, the final entry will be taken
272  * as a number equal to the previous entry evaluated at the final value.
273  * The ent_real component of each function or table entry is set to the
274  * function or table evaluated at the entry value.
275  */
276 
277 struct sCKTtable *table;
278 {
279  struct sCKTentry *e, *ee;
280 
281  if (table == NULL) return;
282 
283  for (e = table->tab_entry; e; e = ee) {
284  ee = e->ent_next;
285 
286  if (ee && ee->ent_type == ENT_OMITTED) {
287  if (e->ent_type == ENT_NUMBER)
288  ee->ent_real = e->ent_real;
289  else if (e->ent_type == ENT_TABLE) {
290  tablfix((struct sCKTtable *)e->ent_string);
291  ee->ent_real =
292  INPtablEval((struct sCKTtable *)e->ent_string,
293  ee->ent_val);
294  }
295  ee->ent_type = ENT_NUMBER;
296  break;
297  }
298 
299  if (e->ent_type == ENT_NUMBER)
300  continue;
301  if (e->ent_type == ENT_TABLE) {
302  tablfix((struct sCKTtable *)e->ent_string);
303  e->ent_real =
304  INPtablEval((struct sCKTtable *)e->ent_string,
305  ee->ent_val);
306  continue;
307  }
308  /* should never get here */
309  continue;
310  }
311 }
312 
313 /************************************************************************/
314 
315 #ifdef debug
316 
317 static void
318 testprnt(ckt)
319 GENERIC *ckt;
320 {
321  struct sCKTtable *table, *t;
322  struct sCKTentry *e, *ee;
323 
324  (void)INPtablFind(NULL,ckt,&table);
325 
326  for (t = table; t; t = t->tab_next) {
327  printf("%s\n",t->tab_name);
328  for (e = t->tab_entry; e; e = e->ent_next) {
329  switch(e->ent_type) {
330  case ENT_NUMBER:
331  printf(" type=%d val=%g real=%g\n",e->ent_type,
332  e->ent_val,e->ent_real);
333  continue;
334  case ENT_TABLE:
335  printf(" type=%d val=%g real=%g (table %s)\n",
336  e->ent_type,e->ent_val,e->ent_real,
337  e->ent_string ?
338  ((struct sCKTtable *)e->ent_string)->tab_name : "(null)");
339  continue;
340  case ENT_OMITTED:
341  printf(" type=%d val=%g omitted\n",e->ent_type,
342  e->ent_val);
343  continue;
344  default:
345  printf(" type=%d error\n",e->ent_type);
346  }
347  }
348  }
349 }
350 
351 #endif
352 
353 /************************************************************************/
354 
355 
356 static int
358 
359 /* Add table to the list kept in the ckt structure.
360  */
361 
362 GENERIC *ckt;
363 struct sCKTtable *table;
364 {
365  if (!table) return (0);
366  if (!ckt) return (1);
367  table->tab_next = *DEVtableHead(ckt);
368  *DEVtableHead(ckt) = table;
369 }
370 
371 /************************************************************************/
372 
373 
374 int
376 
377 /* Find the list head of the table named in str which is kept in ckt
378  * return 0 if found, 1 if not found.
379  */
380 
381 char *str;
382 GENERIC *ckt;
383 GENERIC **table;
384 {
385  struct sCKTtable *t;
386 
387  if (!ckt) return (1);
388  if (!str) {
389  if (table)
390  *table = (GENERIC*) *DEVtableHead(ckt);
391  return (0);
392  }
393  for (t = *DEVtableHead(ckt); t; t = t->tab_next)
394  if (!strcmp(str,t->tab_name)) break;
395 
396  if (!t) return (1);
397  if (table)
398  *table = (GENERIC*)t;
399  return (0);
400 }
401 
402 /************************************************************************/
403 
404 
405 double
407 
408 GENERIC *tab;
409 double x;
410 {
411  struct sCKTentry *ee, *e;
412 
413  if (tab == NULL) return (0);
414 
415  e = ((struct sCKTtable *)tab)->tab_entry;
416 
417  if (x <= e->ent_val) {
418  return (e->ent_real);
419  }
420 
421  for ( ; e; e = ee) {
422  ee = e->ent_next;
423  if (ee == NULL) break;
424  if (x >= e->ent_val && x < ee->ent_val) {
425  if (e->ent_type == ENT_TABLE)
426  return (INPtablEval((struct sCKTtable*)e->ent_string,x));
427  else
428  return (e->ent_real + (x - e->ent_val)*
429  (ee->ent_real - e->ent_real)/(ee->ent_val - e->ent_val));
430  }
431  }
432  if (e->ent_type == ENT_TABLE)
433  return (INPtablEval((struct sCKTtable*)e->ent_string,x));
434  return (e->ent_real);
435 }
436 
437 /************************************************************************/
438 
439 
440 double
442 
443 GENERIC *tab;
444 double x;
445 {
446  struct sCKTentry *ee, *e;
447 
448  if (tab == NULL) return (0);
449 
450  e = ((struct sCKTtable *)tab)->tab_entry;
451 
452  if (x <= e->ent_val) {
453  return (0);
454  }
455 
456  for ( ; e; e = ee) {
457  ee = e->ent_next;
458  if (ee == NULL) break;
459  if (x >= e->ent_val && x < ee->ent_val) {
460  if (e->ent_type == ENT_TABLE)
461  return
462  (INPtablEvalDeriv((struct sCKTtable*)e->ent_string),x);
463  else
464  return
465  ((ee->ent_real - e->ent_real)/(ee->ent_val - e->ent_val));
466  }
467  }
468  return (0);
469 }
470 
471 /************************************************************************/
472 
473 
474 void
476 
477 /*
478  * Free the storage used for tables.
479  */
480 
481 GENERIC *ckt;
482 {
483  struct sCKTtable *t, *tn;
484  struct sCKTentry *e, *en;
485 
486  for (t = *DEVtableHead(ckt); t; t = tn) {
487  tn = t->tab_next;
488  txfree(t->tab_name);
489  for (e = t->tab_entry; e; e = en) {
490  en = e->ent_next;
491  txfree((char*)e);
492  }
493  txfree((char*)t);
494  }
495 }
char * ent_string
Definition: tabdefs.h:28
char * gettok()
#define eq(a, b)
Definition: misc.h:29
double ent_val
Definition: tabdefs.h:19
char * INPerror()
struct sCKTentry * tab_entry
Definition: tabdefs.h:40
static struct tab table[512]
static int tabl_add()
Definition: xforms.c:16
double INPtablEvalDeriv(GENERIC *tab, double x)
Definition: inptabpa.c:441
char * INPtablParse(char **line, GENERIC *ckt)
Definition: inptabpa.c:36
double INPevaluate()
double INPtablEval(GENERIC *tab, double x)
Definition: inptabpa.c:406
static double e
Definition: vectors.c:17
double ent_real
Definition: tabdefs.h:22
Definition: subckt.c:51
void INPtablFix(GENERIC *ckt)
Definition: inptabpa.c:244
void INPtablFree(GENERIC *ckt)
Definition: inptabpa.c:475
Definition: fteinp.h:14
#define MALLOC(x)
Definition: util.h:9
#define tfree(x)
Definition: cdmacs.h:22
void txfree()
#define NULL
Definition: spdefs.h:121
static void testprnt()
#define E_NOMEM
Definition: iferrmsg.h:27
char * INPtablCheck(char *line, GENERIC *ckt)
Definition: inptabpa.c:146
#define ENT_OMITTED
Definition: tabdefs.h:14
int ent_type
Definition: tabdefs.h:31
int INPtablFind(char *str, GENERIC *ckt, GENERIC **table)
Definition: inptabpa.c:375
struct sCKTentry * ent_next
Definition: tabdefs.h:25
#define ENT_TABLE
Definition: tabdefs.h:13
struct sCKTtable * tab_next
Definition: tabdefs.h:43
char * tab_name
Definition: tabdefs.h:37
struct sCKTtable ** DEVtableHead()
Definition: cddefs.h:192
#define ENT_NUMBER
Definition: tabdefs.h:12
static void tablfix()
char GENERIC
Definition: ifsim.h:27
int INPgetTok()