📄 spice3.c
字号:
/*
Copyright (c) 1999,2000, Compaq Computer Corporation
See the file "license.terms" for information on usage and redistribution
of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <errno.h>
#if defined(__osf__)
/* Digital Unix specific */
#include <cvt.h>
#define FLOAT_CVT_TARGET CVT_IEEE_S
#elif defined(vms) || defined(__vms)
/* VMS specific */
#include <cvtdef>
#if defined(__D_FLOAT) || defined(__G_FLOAT)
#define FLOAT_CVT_TARGET CVT$K_VAX_F
#else
#define FLOAT_CVT_TARGET CVT$K_IEEE_S
#endif
#if __VMS_VER < 70000000
#define CVT_BIG_ENDIAN_IEEE_S CVT$K_IEEE_S
#define CVT_BIG_ENDIAN_IEEE_T CVT$K_IEEE_T
#define CVT_FORCE_ALL_SPECIAL_VALUES CVT$M_BIG_ENDIAN
#define cvt_ftof CVT$CONVERT_FLOAT
unsigned long cvt_ftof(void *, unsigned long, void *,
unsigned long, unsigned long);
#else
#define CVT_BIG_ENDIAN_IEEE_S CVT$K_BIG_ENDIAN_IEEE_S
#define CVT_BIG_ENDIAN_IEEE_T CVT$K_BIG_ENDIAN_IEEE_T
#define CVT_FORCE_ALL_SPECIAL_VALUES CVT$M_FORCE_ALL_SPECIAL_VALUES
#define cvt_ftof CVT$FTOF
int cvt_ftof(void *, int, void *, int, int);
#endif
#else
/* A limited set of constants from Digital Unix's cvt.h */
#define CVT_NORMAL 0
#define CVT_INVALID_INPUT_TYPE (1<<0)
#define CVT_INVALID_OUTPUT_TYPE (1<<1)
#define CVT_VAX_F 1
#define CVT_VAX_D 2
#define CVT_VAX_G 3
#define CVT_VAX_H 4
#define CVT_IEEE_S 5
#define CVT_IEEE_T 6
#define CVT_IEEE_X 7
#define CVT_BIG_ENDIAN_IEEE_S 8
#define CVT_BIG_ENDIAN_IEEE_T 9
#define CVT_BIG_ENDIAN_IEEE_X 10
#define CVT_FORCE_ALL_SPECIAL_VALUES (1<<8)
#define FLOAT_CVT_TARGET CVT_IEEE_S
int cvt_ftof(void *, int, void *, int, int);
int strncasecmp (const char *s1, const char *s2, size_t n);
int strcasecmp (const char *s1, const char *s2);
#endif
#include "spice3.h"
#if defined(_WIN32) || defined(vms) || defined(__vms)
/* Don't know where to look for these on Win32 yet... */
#define INT_MAX 2147483647 /* max value for a 32bit signed int */
#define INT_MIN (-INT_MAX-1) /* min value for a 32bit signed int */
/* Win32/Intel and VMS don't have the float variants, so use the double
variants */
#define sqrtf(a) sqrt((double)(a))
#define log10f(a) log10((double)(a))
#define M_PI 3.1415926535897932385E0
#define atand2f(a,b) 180.0*atan2((double)(a),(double)(b))/M_PI
#endif
#if defined(vms) || defined(__vms)
#if __VMS_VER < 70000000 /* Otherwise pick up V7.0 routines */
int strncasecmp (const char *s1, const char *s2, size_t n);
int strcasecmp (const char *s1, const char *s2);
#endif
#endif
/* #define DEBUG_SPICE3 1 */
#if !defined(MIN)
#define MIN(a,b) ((a) <= (b) ? (a) : (b))
#endif
#if !defined(NUL)
#define NUL '\0'
#endif
static void spice3_lookup_name(Spice3Data, char *, int *, int *);
static void kill_nl(char *);
static int lnblnk(char *, int);
/************************************************************************/
/* */
/* Open a spice3 file */
/* */
/************************************************************************/
Spice3File spice3_open (char *file_name, int *error_code) {
Spice3File f;
char mode[2] = "r";
#if defined(_WIN32)
char binmode[8];
#endif
*error_code = 0;
#if defined(vms) || defined(__vms)
f = fopen(file_name, mode);
#elif defined(_WIN32)
/* Windows requires opening file with "b" (binary) mode,
otherwise the file is opened in "text" mode, where
^Z is treated as EOF, CR-LF is translated to LF, etc. */
strncpy(binmode,mode,8);
strncat(binmode,"b",8);
f = fopen(file_name, binmode);
#else
f = fopen(file_name, mode);
#endif
if (f == NULL) {
*error_code = 2;
return NULL;
}
return (f);
}
/************************************************************************/
/* */
/* load the transient analysis data from a spice3 file. */
/* Returns a pointer to a spice3 data structure with the entire */
/* transient loaded into it. */
/* */
/************************************************************************/
Spice3Data spice3_load_transient (Spice3File file, int data_group,
int convert_type, int *error_code) {
char *get_stat, *token;
Spice3Data data;
char buffer[256], title[256], plotname[256], name[256], units[256];
int i, j, rc, name_len, units_len, num, file_type = 0;
float *fcvt_in_buffer = NULL, *fcvt_out_buffer = NULL;
double *dcvt_in_buffer = NULL, *dcvt_out_buffer = NULL;
int real_flag = FALSE;
int single_flag = FALSE;
int data_size = 1; /* == 2 for complex data */
*error_code = 0;
/* Allocate spice3 data structure */
data = (Spice3Data) malloc(sizeof(Spice3DataStruct));
if( data == NULL ) {
*error_code = 1;
goto error;
}
data->variable_array = NULL;
data->variable_names = NULL;
data->variable_units = NULL;
data->num_variables = 0;
data->num_points = 0;
data->data_group = data_group;
data->convert_type = convert_type;
data->complex_flag = FALSE;
/***** read title *****/
get_stat = fgets(buffer,254,file);
if ( get_stat == NULL ) {
*error_code = 3;
goto error;
}
strncpy(title, buffer, 255);
kill_nl(title);
if( strncmp(title,"Title:",6) != 0 ) {
*error_code = 13;
goto error;
}
/***** read time stamp *****/
get_stat = fgets(buffer,254,file);
if ( get_stat == NULL ) {
*error_code = 3;
goto error;
}
/* Here is where we would call a routine to skip to the next
data group (not implemented yet...) */
/***** read plotname *****/
get_stat = fgets(buffer,254,file);
if ( get_stat == NULL ) {
*error_code = 3;
goto error;
}
strncpy(plotname, buffer, 255);
kill_nl(plotname);
/***** read and parse flags *****/
get_stat = fgets(buffer,254,file);
if ( get_stat == NULL ) {
*error_code = 3;
goto error;
}
kill_nl(buffer);
token = strtok(buffer," ");
while ( (token = strtok((char *) NULL," ")) != NULL ) {
if( strncmp(token,"real",4) == 0 ) real_flag = TRUE;
if( strncmp(token,"single",6) == 0 ) single_flag = TRUE;
if( strncmp(token,"complex",7) == 0 ) data->complex_flag = TRUE;
}
/***** read and parse "No. Variables: nnn" *****/
get_stat = fgets(buffer,254,file);
if ( get_stat == NULL ) {
*error_code = 3;
goto error;
}
if( sscanf(buffer,"%*s %*s %d", &data->num_variables) != 1 ) {
*error_code = 3;
goto error;
}
if( data->num_variables <= 0 ) {
*error_code = 4;
goto error;
}
/***** read and parse "No. Points: nnn" *****/
get_stat = fgets(buffer,254,file);
if ( get_stat == NULL ) {
*error_code = 3;
goto error;
}
if( sscanf(buffer,"%*s %*s %d", &data->num_points) != 1 ) {
*error_code = 3;
goto error;
}
if( data->num_points <= 0 ) {
*error_code = 5;
goto error;
}
/***** read "Command: " *****/
get_stat = fgets(buffer,254,file);
if ( get_stat == NULL ) {
*error_code = 3;
goto error;
}
/***** read "Variables: " *****/
get_stat = fgets(buffer,254,file);
if ( get_stat == NULL ) {
*error_code = 3;
goto error;
}
if( strncmp(buffer,"Variables:",10) != 0 ) {
*error_code = 13;
goto error;
}
/* Allocate memory for (pointer to) variable names and units
(fill in later) */
data->variable_names = (char **) malloc ( sizeof(char *) * data->num_variables);
data->variable_units = (char **) malloc ( sizeof(char *) * data->num_variables);
if( data->variable_names == NULL || data->variable_units == NULL) {
*error_code = 2;
goto error;
}
/* Read in variable names and units */
for( i=0; i<data->num_variables; i++ ) {
get_stat = fgets(buffer,254,file);
if ( get_stat == NULL ) {
*error_code = 3;
goto error;
}
if( sscanf(buffer,"%*d %s %s", name, units) != 2 ) {
*error_code = 3;
goto error;
}
name_len = strlen(name);
data->variable_names[i] = (char *) malloc( sizeof(char) * name_len+1);
if( data->variable_names[i] == NULL ) {
*error_code = 2;
goto error;
}
strncpy(data->variable_names[i],name,name_len+1);
units_len = strlen(units);
data->variable_units[i] = (char *) malloc( sizeof(char) * units_len+1);
if( data->variable_units[i] == NULL ) {
*error_code = 2;
goto error;
}
strncpy(data->variable_units[i],units,units_len+1);
}
/***** read "Values:" or "Binary:" *****/
get_stat = fgets(buffer,254,file);
if ( get_stat == NULL ) {
*error_code = 3;
goto error;
}
if( strncmp(buffer,"Values:",7) == 0 ) {
file_type = SPICE3_ASCII;
} else if( strncmp(buffer,"Binary:",7) == 0 ) {
file_type = SPICE3_BINARY;
} else {
*error_code = 13;
goto error;
}
if( data->complex_flag ) {
data_size = 2;
}
/* Allocate memory for data */
data->variable_array = (float **) malloc ( sizeof(float *) * data->num_variables);
if( data->variable_array == NULL ) {
*error_code = 2;
goto error;
}
for( i=0; i<data_size*data->num_variables; i++ ) {
data->variable_array[i] = (float *) malloc ( sizeof(float) * data->num_points);
if( data->variable_array[i] == NULL ) {
*error_code = 2;
goto error;
}
}
/* Allocate memory for intermediate buffer (allows conversion) */
fcvt_in_buffer = (float *) malloc( sizeof(float) * data_size * data->num_variables);
fcvt_out_buffer = (float *) malloc( sizeof(float) * data_size * data->num_variables);
if( fcvt_in_buffer == NULL || fcvt_in_buffer == NULL ) {
*error_code = 2;
goto error;
}
dcvt_in_buffer = (double *) malloc( sizeof(double) * data_size * data->num_variables);
dcvt_out_buffer = (double *) malloc( sizeof(double) * data_size * data->num_variables);
if( dcvt_in_buffer == NULL || dcvt_in_buffer == NULL ) {
*error_code = 2;
goto error;
}
if( file_type == SPICE3_ASCII ) {
for(j=0; j<data->num_points; j++ ) {
if( fscanf(file,"%d",&num) != 1 ) {
*error_code = 3;
goto error;
}
for(i=0; i<data_size*data->num_variables; i++ ) {
if( fscanf(file,"%f",&data->variable_array[i][j]) != 1 ) {
*error_code = 3;
goto error;
}
}
}
} else {
if( single_flag ) {
for(j=0; j<data->num_points; j++ ) {
if( fread(fcvt_in_buffer,sizeof(float),
data_size*data->num_variables,file) !=
data_size*data->num_variables ) {
*error_code = 3;
goto error;
}
/* Apply endian conversions here */
if( convert_type == SPICE3_BIG_ENDIAN ) {
for(i=0; i<data_size*data->num_variables; i++) {
rc = cvt_ftof(&fcvt_in_buffer[i], CVT_BIG_ENDIAN_IEEE_S,
&fcvt_out_buffer[i],FLOAT_CVT_TARGET,
CVT_FORCE_ALL_SPECIAL_VALUES);
}
for(i=0; i<data_size*data->num_variables; i++ )
data->variable_array[i][j] = fcvt_out_buffer[i];
} else {
for(i=0; i<data_size*data->num_variables; i++ )
data->variable_array[i][j] = fcvt_in_buffer[i];
}
}
} else {
for(j=0; j<data->num_points; j++ ) {
if( fread(dcvt_in_buffer,sizeof(double),
data_size*data->num_variables,file) !=
data_size*data->num_variables ) {
*error_code = 3;
goto error;
}
/* Apply endian conversions here */
if( convert_type == SPICE3_BIG_ENDIAN ) {
for(i=0; i<data_size*data->num_variables; i++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -