Ignore all generated/compiled files
[gwave-svn.git] / spicefile / ss_cazm.c
blob8be1e18dd6dfd9f647d4b64d044c3b9b1ce51ea5
1 /*
2 * ss_cazm.c: CAZM- and ASCII- format routines for SpiceStream
4 * Copyright (C) 1998,1999 Stephen G. Tell
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public
17 * License along with this software; if not, write to the Free
18 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * CAzM and "ascii" format are closely related, so they are both handled
22 * in this file.
24 * CAzM format is intended to handles files written by MCNC's CAzM simulator,
25 * used by a number of universities, and its commercial decendant,
26 * the TSPICE product from Tanner Research.
28 * CAzM-format files contain a multiline header. The second to last line
29 * of the header identifies the analysis type, for example TRANSIENT or AC.
30 * The last line of the header contains the names of the variables, seperated
31 * by whitespace.
33 * Ascii-format files have a one-line header, containing a space- or
34 * tab-speperated list of the variable names. To avoid treating a file
35 * containing random binary garbage as an ascii-format file, we require the
36 * header line to contain space, tab, and USASCII printable characters only.
39 #define _FILE_OFFSET_BITS 64
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <ctype.h>
45 #include <float.h>
47 #include <config.h>
48 #include <glib.h>
49 #include "spicestream.h"
51 static int sf_readrow_ascii(SpiceStream *sf, double *ivar, double *dvars);
52 static SpiceStream *ascii_process_header(char *line, VarType ivtype,
53 char *fname, int lineno);
55 /* Read spice-type file header - cazm format */
56 SpiceStream *
57 sf_rdhdr_cazm(char *name, FILE *fp)
59 SpiceStream *sf;
60 char *line = NULL;
61 int lineno = 0;
62 int linesize = 1024;
63 int done = 0;
64 VarType ivtype;
66 while(!done) {
67 if((fread_line(fp, &line, &linesize) == EOF) || lineno > 30) {
68 g_free(line);
69 return NULL;
71 lineno++;
72 /* "section header" line */
73 if(strncmp(line, "TRANSIENT", 9) == 0) {
74 ivtype = TIME;
75 done = 1;
76 } else if(strncmp(line, "AC ANALYSIS", 11) == 0) {
77 ivtype = FREQUENCY;
78 done = 1;
79 } else if(strncmp(line, "TRANSFER", 8) == 0) {
80 /* DC transfer function - ivar might also be current,
81 * but we can't tell */
82 ivtype = VOLTAGE;
83 done = 1;
87 /* line after header contains signal names
88 * first one is assumed to be the independent variable.
90 if(fread_line(fp, &line, &linesize) == EOF) {
91 g_free(line);
92 return NULL;
94 lineno++;
96 sf = ascii_process_header(line, ivtype, name, lineno);
97 if(!sf)
98 goto fail;
100 sf->fp = fp;
101 sf->lineno = lineno;
102 sf->linebuf = line;
103 sf->lbufsize = linesize;
104 return sf;
106 fail:
107 if(line)
108 g_free(line);
109 return NULL;
113 /* Read spice-type file header - ascii format */
114 SpiceStream *
115 sf_rdhdr_ascii(char *name, FILE *fp)
117 SpiceStream *sf;
118 char *line = NULL;
119 int lineno = 0;
120 int linesize = 1024;
121 char *cp;
124 * first line is expected to contain space-seperated
125 * variable names.
126 * first one is assumed to be the independent variable.
128 if(fread_line(fp, &line, &linesize) == EOF) {
129 goto fail;
131 lineno++;
133 /* Check for non-ascii characters in header, to reject
134 * binary files.
136 for(cp = line; *cp; cp++) {
137 if(!isgraph(*cp) && *cp != ' ' && *cp != '\t') {
138 goto fail;
142 sf = ascii_process_header(line, UNKNOWN, name, lineno);
143 if(!sf)
144 goto fail;
146 sf->fp = fp;
147 sf->lineno = lineno;
148 sf->linebuf = line;
149 sf->lbufsize = linesize;
150 return sf;
152 fail:
153 if(line)
154 g_free(line);
155 return NULL;
160 * Process a header line from an ascii or cazm format file.
161 * Returns a filled-in SpiceStream* with variable information.
163 static
164 SpiceStream *ascii_process_header(char *line, VarType ivtype,
165 char *fname, int lineno)
167 SpiceStream *sf;
168 char *signam;
169 int dvsize = 64;
171 signam = strtok(line, " \t\n");
172 if(!signam) {
173 ss_msg(ERR, "ascii_process_header", "%s:%d: syntax error in header", fname, lineno);
174 return NULL;
177 /* a bit of a hack: get ss_new to allocate additional
178 * dvars, then only use the entries we need or allocate more
180 sf = ss_new(NULL, fname, dvsize, 0);
182 if(ivtype == UNKNOWN) {
183 if(strcasecmp(signam, "time") == 0)
184 sf->ivar->type = TIME;
185 } else {
186 sf->ivar->type = ivtype;
188 sf->ivar->name = g_strdup(signam);
189 sf->ivar->col = 0;
190 sf->ivar->ncols = 1;
192 sf->ndv = 0;
193 sf->ncols = 1;
194 sf->ntables = 1;
195 while((signam = strtok(NULL, " \t\n")) != NULL) {
196 SpiceVar *dvar = ss_spicevar_new(signam, UNKNOWN, sf->ncols, 1);
197 g_ptr_array_add(sf->dvarp, dvar);
198 sf->ndv++;
199 sf->ncols++;
201 sf->readrow = sf_readrow_ascii;
203 return sf;
208 /* Read row of values from ascii- or cazm- format file.
209 * Possibly reusable for other future formats with lines of
210 * whitespace-seperated values.
211 * Returns:
212 * 1 on success. also fills in *ivar scalar and *dvars vector
213 * 0 on EOF
214 * -1 on error (may change some ivar/dvar values)
216 static int
217 sf_readrow_ascii(SpiceStream *sf, double *ivar, double *dvars)
219 int i;
220 char *tok;
222 if(fread_line(sf->fp, &sf->linebuf, &sf->lbufsize) == EOF) {
223 return 0;
225 sf->lineno++;
227 tok = strtok(sf->linebuf, " \t\n");
228 if(!tok) {
229 return 0; /* blank line can indicate end of data */
232 /* check to see if it is numeric: ascii format is so loosly defined
233 * that we might read a load of garbage otherwise. */
235 if(strspn(tok, "0123456789eE+-.") != strlen(tok)) {
236 ss_msg(ERR, "sf_readrow_ascii", "%s:%d: expected number; maybe this isn't an ascii data file at all?", sf->filename, sf->lineno, i);
237 return -1;
240 *ivar = atof(tok);
242 for(i = 0; i < sf->ncols-1; i++) {
243 tok = strtok(NULL, " \t\n");
244 if(!tok) {
245 ss_msg(ERR, "sf_readrow_ascii", "%s:%d: data field %d missing", sf->filename, sf->lineno, i);
246 return -1;
248 dvars[i] = atof(tok);
250 return 1;