Clean up a slew of warnings from gcc -Wall - mostly unused variables.
[gwave-svn.git] / spicefile / ss_spice3.c
blob7e17994c00acc06e50e949f2addf0c662116c789
1 /*
2 * ss_spice3.c: routines for SpiceStream that handle the file formats
3 * known as Berkeley Spice3 Rawfile
5 * Copyright (C) 1998,1999 Stephen G. Tell
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "ssintern.h"
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <ctype.h>
29 #include <float.h>
31 #include <config.h>
32 #include <glib.h>
33 #include "spicestream.h"
35 static int sf_readrow_s3raw(SpiceStream *sf, double *ivar, double *dvars);
36 char *msgid = "s3raw";
37 static int sf_readrow_s3bin(SpiceStream *sf, double *ivar, double *dvars);
39 /* convert variable type string from spice3 raw file to
40 * our type numbers
42 static VarType
43 sf_str2type_s3raw(char *s)
45 if(strcasecmp(s, "voltage") == 0)
46 return VOLTAGE;
47 else if(strcasecmp(s, "current") == 0)
48 return CURRENT;
49 else if(strcasecmp(s, "frequency") == 0)
50 return FREQUENCY;
51 else if(strcasecmp(s, "time") == 0)
52 return TIME;
53 else return UNKNOWN;
57 /* Read spice-type file header - Berkeley Spice3 "raw" format */
58 SpiceStream *
59 sf_rdhdr_s3raw(char *name, FILE *fp)
61 SpiceStream *sf = NULL;
62 char *line = NULL;
63 int lineno = 0;
64 int linesize = 1024;
65 char *key, *val;
66 int nvars, npoints;
67 int got_nvars = 0;
68 int got_values = 0;
69 int dtype_complex = 0;
70 int binary = 0;
71 char *vnum, *vname, *vtypestr;
72 int i;
74 while(fread_line(fp, &line, &linesize) != EOF) {
75 lineno++;
76 if(lineno == 1 && strncmp(line, "Title: ", 7)) {
77 /* not a spice3raw file; bail out */
78 ss_msg(DBG, msgid, "%s:%d: Doesn't look like a spice3raw file; \"Title:\" expected\n", name, lineno);
80 return NULL;
83 key = strtok(line, ":");
84 if(!key) {
85 ss_msg(ERR, msgid, "%s:%d: syntax error, expected \"keyword:\"", name, lineno);
86 g_free(line);
87 return NULL;
89 if(strcmp(key, "Flags") == 0) {
90 while(val = strtok(NULL, " ,\t\n")) {
91 if(strcmp(val, "real") == 0) {
92 dtype_complex = 0;
94 if(strcmp(val, "complex") == 0) {
95 dtype_complex = 1;
98 } else if(strcmp(key, "No. Variables") == 0) {
99 val = strtok(NULL, " \t\n");
100 if(!val) {
101 ss_msg(ERR, msgid, "%s:%d: syntax error, expected integer", name, lineno);
102 g_free(line);
103 return NULL;
105 nvars = atoi(val);
106 got_nvars = 1;
107 } else if(strcmp(key, "No. Points") == 0) {
108 val = strtok(NULL, " \t\n");
109 if(!val) {
110 ss_msg(ERR, msgid, "%s:%d: syntax error, expected integer", name, lineno);
111 g_free(line);
112 return NULL;
114 npoints = atoi(val);
115 } else if(strcmp(key, "Variables") == 0) {
116 if(!got_nvars) {
117 ss_msg(ERR, msgid, "%s:%d: \"Variables:\" before \"No. Variables:\"", name, lineno, i);
118 goto err;
121 sf = ss_new(fp, name, nvars-1, 0);
122 sf->ncols = 1;
123 sf->ntables = 1;
124 /* first variable may be described on the same line
125 * as "Variables:" keyword
127 vnum = strtok(NULL, " \t\n");
129 for(i = 0; i < nvars; i++) {
130 if(i || !vnum) {
131 if(fread_line(fp, &line, &linesize) == EOF) {
132 ss_msg(ERR, msgid, "%s:%d: Unexpected EOF in \"Variables:\" at var %d", name, lineno, i);
133 goto err;
135 lineno++;
136 vnum = strtok(line, " \t\n");
138 vname = strtok(NULL, " \t\n");
139 vtypestr = strtok(NULL, " \t\n");
140 if(!vnum || !vname || !vtypestr) {
141 ss_msg(ERR, msgid, "%s:%d: expected number name type", name, lineno);
142 goto err;
144 if(i == 0) { /* assume Ind.Var. first */
145 sf->ivar->name = g_strdup(vname);
146 sf->ivar->type = sf_str2type_s3raw(vtypestr);
147 sf->ivar->col = 0;
148 /* ivar can't really be two-column,
149 this is a flag that says to
150 discard 2nd point */
151 if(dtype_complex)
152 sf->ivar->ncols = 2;
153 else
154 sf->ivar->ncols = 1;
156 } else {
157 sf->dvar[i-1].name = g_strdup(vname);
158 sf->dvar[i-1].type = sf_str2type_s3raw(vtypestr);
159 sf->dvar[i-1].col = sf->ncols;
160 if(dtype_complex)
161 sf->dvar[i-1].ncols = 2;
162 else
163 sf->dvar[i-1].ncols = 1;
165 sf->ncols += sf->dvar[i-1].ncols;
168 } else if(strcmp(key, "Values") == 0) {
169 got_values = 1;
170 break;
171 } else if(strcmp(key, "Binary") == 0) {
172 binary = 1;
173 got_values = 1;
174 break;
176 if(got_values)
177 break;
179 if(!sf) {
180 ss_msg(ERR, msgid, "%s:%d: no \"Variables:\" section in header", name, lineno);
181 goto err;
183 if(!got_values) {
184 ss_msg(ERR, msgid, "%s:%d: EOF without \"Values:\" in header", name, lineno);
185 goto err;
188 if(binary) {
189 sf->readrow = sf_readrow_s3bin;
190 } else {
191 sf->readrow = sf_readrow_s3raw;
193 sf->read_rows = 0;
194 sf->expected_vals = npoints * (sf->ncols + (dtype_complex ? 1 : 0));
195 ss_msg(DBG, msgid, "expecting %d values\n", sf->expected_vals);
196 sf->lineno = lineno;
197 sf->linebuf = line;
198 sf->lbufsize = linesize;
199 ss_msg(DBG, msgid, "Done with header at offset 0x%lx\n", (long) ftello64(sf->fp));
201 return sf;
202 err:
203 if(line)
204 g_free(line);
205 if(sf) {
206 sf->fp = NULL;
207 /* prevent ss_delete from cleaning up FILE*; ss_open callers
208 may rewind and try another format on failure. */
209 ss_delete(sf);
211 return NULL;
215 /* return pointer to the next whitespace-seperated token in the file
216 * advances to the next lines of the file as needed.
217 * pointer points into the line buffer linebuf.
218 * token will not be nul-terminated; whole line remains available.
220 * upon return, sf->linep points to the char after the end of the token,
221 * which might be the trailing nul or might be whitespace.
223 static char *sf_nexttoken(SpiceStream *sf)
225 char *cp;
226 char *tok = NULL;
228 if(sf->linep)
229 cp = sf->linep;
230 else {
231 if(fread_line(sf->fp, &sf->linebuf, &sf->lbufsize) == EOF) {
232 return 0; /* normal EOF */
234 sf->lineno++;
235 cp = sf->linebuf;
238 // search for start of token
239 while(!tok) {
240 if(*cp == 0) {
241 do {
242 if(fread_line(sf->fp, &sf->linebuf, &sf->lbufsize) == EOF) {
243 return 0; /* normal EOF */
245 sf->lineno++;
246 cp = sf->linebuf;
247 } while (*cp == 0); // skip multiple blank lines
249 if(!isspace(*cp))
250 tok = cp;
251 else
252 cp++;
254 // tok now points to start of the token; search for the end
255 while(*cp && !isspace(*cp))
256 cp++;
257 sf->linep = cp;
258 return tok;
263 * Read row of values from an ascii spice3 raw file
265 static int
266 sf_readrow_s3raw(SpiceStream *sf, double *ivar, double *dvars)
268 int i;
269 int frownum;
270 char *tok;
271 double v;
273 if((sf->flags & SSF_PUSHBACK) == 0) {
274 tok = sf_nexttoken(sf);
275 if(!tok) {
276 return 0;
277 // ss_msg(ERR, msgid, "%s:%d: expected row number",
278 // sf->filename, sf->lineno);
279 // return -1;
281 if(!isdigit(*tok)) {
282 ss_msg(WARN, msgid, "%s:%d: expected row number, got \"%s\". Note: only one dataset per file is supported, extra garbage ignored",
283 sf->filename, sf->lineno, tok);
284 return 0;
286 frownum = atoi(tok);
287 /* todo: check for expected and maximum row number */
289 tok = sf_nexttoken(sf);
290 if(!tok) {
291 ss_msg(WARN, msgid, "%s:%d: expected ivar value",
292 sf->filename, sf->lineno);
293 return -1;
295 v = atof(tok);
296 if(v < sf->ivval) {
297 /* independent-variable value decreased, this must
298 * be the start of another sweep. hold the value and
299 * return flag to caller.
301 sf->ivval = v;
302 sf->flags |= SSF_PUSHBACK;
303 return -2;
304 } else {
305 sf->ivval = v;
306 *ivar = v;
308 } else {
309 /* iv value for start of new sweep was read last time */
310 sf->flags &= ~SSF_PUSHBACK;
311 *ivar = sf->ivval;
314 for(i = 0; i < sf->ndv; i++) {
315 SpiceVar *dv;
316 dv = &sf->dvar[i];
318 tok = sf_nexttoken(sf);
319 if(!tok) {
320 ss_msg(ERR, msgid, "%s:%d: expected value",
321 sf->filename, sf->lineno);
322 return -1;
324 dvars[dv->col-1] = atof(tok);
326 if(dv->ncols > 1) {
327 tok = strchr(tok, ',');
328 if(!tok || !*(tok+1)) {
329 ss_msg(ERR, msgid, "%s:%d: expected second value",
330 sf->filename, sf->lineno);
331 return -1;
333 tok++;
334 dvars[dv->col] = atof(tok);
337 sf->read_rows++;
338 return 1;
342 * Read a single value from binary spice3 rawfile, and do
343 * the related error-checking.
346 static int
347 sf_getval_s3bin(SpiceStream *sf, double *dval)
349 off64_t pos;
350 double val;
352 if(sf->read_vals >= sf->expected_vals) {
353 pos = ftello64(sf->fp);
354 ss_msg(DBG, "sf_getval_s3bin", "past last expected value offset 0x%lx", (long) pos);
355 return 0;
357 if(fread(&val, sizeof(double), 1, sf->fp) != 1) {
358 pos = ftello64(sf->fp);
359 ss_msg(ERR, "sf_getval_s3bin", "unexepected EOF in data at offset 0x%lx", (long) pos);
360 return -1;
362 sf->read_vals++;
364 *dval = val;
365 return 1;
370 * Read row of values from a binay spice3 raw file
372 static int
373 sf_readrow_s3bin(SpiceStream *sf, double *ivar, double *dvars)
375 int i, rc;
376 double v;
377 double dummy;
379 if((sf->flags & SSF_PUSHBACK) == 0) {
380 rc = sf_getval_s3bin(sf, &v);
381 if(rc == 0) /* file EOF */
382 return 0;
383 if(rc < 0)
384 return -1;
385 if(sf->ivar->ncols == 2) {
386 rc = sf_getval_s3bin(sf, &dummy);
387 if(rc == 0) /* file EOF */
388 return 0;
389 if(rc < 0)
390 return -1;
392 if(v < sf->ivval) {
393 /* independent-variable value decreased, this must
394 * be the start of another sweep. hold the value and
395 * return flag to caller.
397 sf->ivval = v;
398 sf->flags |= SSF_PUSHBACK;
399 return -2;
400 } else {
401 sf->ivval = v;
402 *ivar = v;
404 } else {
405 /* iv value for start of new sweep was read last time */
406 sf->flags &= ~SSF_PUSHBACK;
407 *ivar = sf->ivval;
410 for(i = 0; i < sf->ncols-1; i++) {
411 if(sf_getval_s3bin(sf, &dvars[i]) != 1) {
412 ss_msg(WARN, "sf_readrow_s3bin", "%s: EOF or error reading data field %d in row %d; file is incomplete.", sf->filename, i, sf->read_rows);
413 return 0;
417 sf->read_rows++;
418 return 1;