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
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
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
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 */
57 sf_rdhdr_cazm(char *name
, FILE *fp
)
67 if((fread_line(fp
, &line
, &linesize
) == EOF
) || lineno
> 30) {
72 /* "section header" line */
73 if(strncmp(line
, "TRANSIENT", 9) == 0) {
76 } else if(strncmp(line
, "AC ANALYSIS", 11) == 0) {
79 } else if(strncmp(line
, "TRANSFER", 8) == 0) {
80 /* DC transfer function - ivar might also be current,
81 * but we can't tell */
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
) {
96 sf
= ascii_process_header(line
, ivtype
, name
, lineno
);
103 sf
->lbufsize
= linesize
;
113 /* Read spice-type file header - ascii format */
115 sf_rdhdr_ascii(char *name
, FILE *fp
)
124 * first line is expected to contain space-seperated
126 * first one is assumed to be the independent variable.
128 if(fread_line(fp
, &line
, &linesize
) == EOF
) {
133 /* Check for non-ascii characters in header, to reject
136 for(cp
= line
; *cp
; cp
++) {
137 if(!isgraph(*cp
) && *cp
!= ' ' && *cp
!= '\t') {
142 sf
= ascii_process_header(line
, UNKNOWN
, name
, lineno
);
149 sf
->lbufsize
= linesize
;
160 * Process a header line from an ascii or cazm format file.
161 * Returns a filled-in SpiceStream* with variable information.
164 SpiceStream
*ascii_process_header(char *line
, VarType ivtype
,
165 char *fname
, int lineno
)
171 signam
= strtok(line
, " \t\n");
173 ss_msg(ERR
, "ascii_process_header", "%s:%d: syntax error in header", fname
, lineno
);
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
;
186 sf
->ivar
->type
= ivtype
;
188 sf
->ivar
->name
= g_strdup(signam
);
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
);
201 sf
->readrow
= sf_readrow_ascii
;
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.
212 * 1 on success. also fills in *ivar scalar and *dvars vector
214 * -1 on error (may change some ivar/dvar values)
217 sf_readrow_ascii(SpiceStream
*sf
, double *ivar
, double *dvars
)
222 if(fread_line(sf
->fp
, &sf
->linebuf
, &sf
->lbufsize
) == EOF
) {
227 tok
= strtok(sf
->linebuf
, " \t\n");
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
);
242 for(i
= 0; i
< sf
->ncols
-1; i
++) {
243 tok
= strtok(NULL
, " \t\n");
245 ss_msg(ERR
, "sf_readrow_ascii", "%s:%d: data field %d missing", sf
->filename
, sf
->lineno
, i
);
248 dvars
[i
] = atof(tok
);