This is binary.c in view mode; [Download] [Up]
#ifndef lint static char *RCSid = "$Id: binary.c%v 3.38.2.100 1993/03/22 03:23:10 woo Exp woo $"; #endif /* * The addition of gnubin and binary, along with a small patch * to command.c, will permit gnuplot to plot binary files. * gnubin - contains the code that relies on gnuplot include files * and other definitions * binary - contains those things that are independent of those * definitions and files * * With these routines, hidden line removal of your binary data is possible! * * Last update: 3/29/92 memory allocation bugs fixed. jvdwoude@hut.nl * 3/09/92 spelling errors, general cleanup, use alloc with no * nasty fatal errors * 3/03/92 for Gnuplot 3.24. * Created from code for written by RKC for gnuplot 2.0b. * * Copyright (c) 1991,1992 Robert K. Cunningham, MIT Lincoln Laboratory * */ #include <stdio.h> #if !defined(apollo) && !defined(sequent) && !defined(u3b2) #include <stdlib.h> /* realloc() */ #else #include <sys/types.h> /* typedef long size_t; */ extern char *realloc(); #endif #include <math.h> #if defined(MSDOS) && defined(__TURBOC__) && !defined(DOSX286) #include <alloc.h> /* for farmalloc, farrealloc */ #define SMALLMALLOC #endif #if defined(_Windows) && !defined(WIN32) #include <windows.h> #include <windowsx.h> #define farmalloc(s) GlobalAllocPtr(GHND,s) #define farrealloc(p,s) GlobalReAllocPtr(p,s,GHND) #define SMALLMALLOC #endif #ifdef sequent #include <sys/types.h> /* unsigned long size_t; */ #endif #include "plot.h" /* We have to get TRUE and FALSE */ float GPFAR *vector(); float GPFAR *extend_vector(); float GPFAR *retract_vector(); float GPFAR * GPFAR *matrix(); float GPFAR * GPFAR *extend_matrix(); float GPFAR * GPFAR *retract_matrix(); void free_matrix(); void free_vector(); /* versions of alloc, realloc and free that work with segmented architectures (yuk!) */ char GPFAR * gpfaralloc(size, message) unsigned long size; /* # of bytes */ char *message; /* description of what is being allocated */ { #ifdef SMALLMALLOC char GPFAR *p; /* the new allocation */ char errbuf[100]; /* error message string */ p = farmalloc(size); if (p == (char *)NULL) { /* really out of memory */ if (message != NULL) { (void) sprintf(errbuf, "out of memory for %s", message); int_error(errbuf, NO_CARET); /* NOTREACHED */ } /* else we return NULL */ } return(p); #else return alloc(size, message); #endif } char GPFAR * gpfarrealloc(p, size) char GPFAR *p; /* old pointer */ unsigned long size; /* # of bytes */ { #ifdef SMALLMALLOC return farrealloc(p, size); #else return realloc(p, (size_t)size); #endif } void gpfarfree(p) char GPFAR *p; { #ifdef SMALLMALLOC #ifdef _Windows HGLOBAL hGlobal = GlobalHandle(SELECTOROF(p)); GlobalUnlock(hGlobal); GlobalFree(hGlobal); #else farfree(p); #endif #else free(p); #endif } /* * This routine scans the first block of the file to see if the file is a * binary file. A file is considered binary if 10% of the characters in it * are not in the ascii character set. (values < 128), or if a NUL is found. * I hope this doesn't break when used on the bizzare PC's. */ int is_binary_file(fp) register FILE *fp; { register int i,len; register int odd; /* Contains a count of the odd characters */ long where; register unsigned char *c; unsigned char buffer[512]; if((where = ftell(fp)) == -1){ /* Find out where we start */ fprintf(stderr,"Notice: Assuming unseekable data is not binary\n"); return(FALSE); } else { rewind(fp); len = fread(buffer,sizeof(char),512,fp); if (len <= 0) /* Empty file is declared ascii */ return(FALSE); c = buffer; /* now scan buffer to look for odd characters */ odd = 0; for (i=0; i<len; i++,c++) { if (!*c) { /* NUL _never_ allowed in text */ odd += len; break; } else if ((*c & 128) ||/* Meta-characters--we hope it's not formatting */ (*c == 127)|| /* DEL */ (*c < 32 && *c != '\n' && *c != '\r' && *c != '\b' && *c != '\t' && *c != '\f' && *c != 27 /*ESC*/)) odd++; } fseek(fp,where,0); /* Go back to where we started */ if (odd * 10 > len) /* allow 10% of the characters to be odd */ return(TRUE); else return(FALSE); } } /*========================= I/O Routines ================================ These may be useful for situations other than just gnuplot. Note that I have included the reading _and_ the writing routines, so others can create the file as well as read the file. */ /* This function reads a matrix from a stream This routine never returns anything other than vectors and arrays that range from 0 to some number. */ #define START_ROWS 100/* Each of these must be at least 1 */ #define ADD_ROWS 50 int fread_matrix(fin,ret_matrix,nr,nc,row_title,column_title) FILE *fin; float GPFAR * GPFAR * GPFAR *ret_matrix,GPFAR * GPFAR * row_title, GPFAR * GPFAR *column_title; int *nr,*nc; { float GPFAR * GPFAR *m, GPFAR *rt, GPFAR *ct; register int num_rows = START_ROWS; register int num_cols; register int current_row = 0; register float GPFAR * GPFAR *temp_array; float fdummy; fread(&fdummy,sizeof(fdummy),1,fin); num_cols = (int)fdummy; /* Choose a reasonable number of rows, allocate space for it and continue until this space runs out, then extend the matrix as necessary. */ ct = vector(0,num_cols-1); fread(ct,sizeof(*ct),num_cols,fin); rt = vector(0,num_rows-1); m = matrix(0,num_rows-1,0,num_cols-1); while(fread(&rt[current_row], sizeof(rt[current_row]), 1, fin)==1){ /* We've got another row */ if(fread(m[current_row],sizeof(*(m[current_row])),num_cols,fin)!=num_cols) return(FALSE); /* Not a True matrix */ current_row++; if(current_row>=num_rows){ /* We've got to make a bigger rowsize */ temp_array = extend_matrix(m,0,num_rows-1,0,num_cols-1, num_rows+ADD_ROWS-1,num_cols-1); rt = extend_vector(rt,0,num_rows-1,num_rows+ADD_ROWS-1); num_rows+= ADD_ROWS; m = temp_array; } } /* finally we force the matrix to be the correct row size */ /* bug fixed. procedure called with incorrect 6th argument. jvdwoude@hut.nl */ temp_array = retract_matrix(m,0,num_rows-1,0,num_cols-1,current_row-1,num_cols-1); /* Now save the things that change */ *ret_matrix = temp_array; *row_title = retract_vector(rt, 0, num_rows-1, current_row-1); *column_title = ct; *nr = current_row;/* Really the total number of rows */ *nc = num_cols; return(TRUE); } /* This writes a matrix to a stream Note that our ranges are inclusive ranges--and we can specify subsets. This behaves similarly to the xrange and yrange operators in gnuplot that we all are familiar with. */ int fwrite_matrix(fout,m,nrl,nrh,ncl,nch,row_title,column_title) register FILE *fout; register float GPFAR * GPFAR *m, GPFAR *row_title, GPFAR *column_title; register int nrl,nrh,ncl,nch; { register int j; float length; register int col_length; register int status; float GPFAR *title = NULL; length = col_length = nch-ncl+1; if((status = fwrite((char*)&length,sizeof(float),1,fout))!=1){ fprintf(stderr,"fwrite 1 returned %d\n",status); return(FALSE); } if(!column_title){ column_title = title = vector(ncl,nch); for(j=ncl; j<=nch; j++) title[j] = j; } fwrite((char*)column_title,sizeof(float),col_length,fout); if(title){ free_vector(title,ncl,nch); title = NULL; } if(!row_title){ row_title = title = vector(nrl,nrh); for(j=nrl; j<=nrh; j++) title[j] = j; } for(j=nrl; j<=nrh; j++){ fwrite((char*)&row_title[j],sizeof(float),1,fout); fwrite((char*)(m[j]+ncl),sizeof(float),col_length,fout); } if(title) free_vector(title,nrl,nrh); return(TRUE); } /*===================== Support routines ==============================*/ /******************************** VECTOR ******************************* * The following routines interact with vectors. * * If there is an error we don't really return - int_error breaks us out. * * This subroutine based on a subroutine listed in "Numerical Recipies in C", * by Press, Flannery, Teukoilsky and Vetterling (1988). * */ float GPFAR *vector(nl,nh) register int nl,nh; { register float GPFAR *vec; if (!(vec = (float GPFAR *)gpfaralloc((unsigned long) (nh-nl+1)*sizeof(float),NULL))){ int_error("not enough memory to create vector",NO_CARET); return NULL;/* Not reached */ } return (vec-nl); } /* * Free a vector allocated above * * This subroutine based on a subroutine listed in "Numerical Recipies in C", * by Press, Flannery, Teukoilsky and Vetterling (1988). * */ void free_vector(vec,nl,nh) float GPFAR *vec; int nl,nh; { gpfarfree((char GPFAR *)(vec+nl)); } /************ Routines to modify the length of a vector ****************/ float GPFAR * extend_vector(vec,old_nl,old_nh,new_nh) float GPFAR *vec; register int old_nl,old_nh,new_nh; { register float GPFAR *new_v; if(!(new_v = (float GPFAR *)gpfarrealloc((void*)(vec+old_nl), (unsigned long)(new_nh-old_nl+1)*sizeof(float)) )){ int_error("not enough memory to extend vector",NO_CARET); return NULL; } return new_v-old_nl; } float GPFAR * retract_vector(v,old_nl,old_nh,new_nh) float GPFAR *v; register int old_nl,old_nh,new_nh; { register float GPFAR *new_v; if(!(new_v = (float GPFAR *)gpfarrealloc((void*)(v+old_nl), (unsigned long)(new_nh-old_nl+1)*sizeof(float)))){ int_error("not enough memory to retract vector",NO_CARET); return NULL; } return new_v-old_nl; } /***************************** MATRIX ************************ * * The following routines work with matricies * * I always get confused with this, so here I write it down: * for nrl<= nri <=nrh and * for ncl<= ncj <=nch * * This matrix is accessed as: * * matrix[nri][ncj]; * where nri is the offset to the pointer to a vector where the * ncjth element lies. * * If there is an error we don't really return - int_error breaks us out. * * This subroutine based on a subroutine listed in "Numerical Recipies in C", * by Press, Flannery, Teukoilsky and Vetterling (1988). * */ float GPFAR * GPFAR *matrix(nrl,nrh,ncl,nch) register int nrl,nrh,ncl,nch; { register int i; register float GPFAR * GPFAR *m; if (!(m = (float GPFAR * GPFAR *)gpfaralloc((unsigned long)(nrh-nrl+1)*sizeof(float GPFAR *),NULL))){ int_error("not enough memory to create matrix",NO_CARET); return NULL; } m -= nrl; for (i=nrl; i<=nrh; i++) { if (!(m[i] = (float GPFAR *) gpfaralloc((unsigned long)(nch-ncl+1)*sizeof(float),NULL))){ free_matrix(m,nrl,i-1,ncl,nch); int_error("not enough memory to create matrix",NO_CARET); return NULL; } m[i] -= ncl; } return m; } /* * Free a matrix allocated above * * * This subroutine based on a subroutine listed in "Numerical Recipies in C", * by Press, Flannery, Teukoilsky and Vetterling (1988). * */ void free_matrix(m,nrl,nrh,ncl,nch) float GPFAR * GPFAR *m; unsigned nrl,nrh,ncl,nch; { register int i; for (i=nrl; i<=nrh; i++) gpfarfree((char GPFAR *) (m[i]+ncl)); gpfarfree((char GPFAR *) (m+nrl)); } /* This routine takes a sub matrix and extends the number of rows and columns for a new matrix */ float GPFAR * GPFAR *extend_matrix(a,nrl,nrh,ncl,nch,srh,sch) register float GPFAR * GPFAR *a; register int nrl,nrh,ncl,nch; register int srh,sch; { register int i; register float GPFAR * GPFAR *m; /* bug fixed. realloc() called with incorrect 2nd argument. jvdwoude@hut.nl */ if(!(m = (float GPFAR * GPFAR *)gpfarrealloc((void*)(a+nrl),(unsigned long)(srh-nrl+1)*sizeof(float GPFAR *)) )){ int_error("not enough memory to extend matrix",NO_CARET); return NULL; } m -= nrl; if(sch != nch){ for(i=nrl; i<=nrh; i++) {/* Copy and extend rows */ if(!(m[i] = extend_vector(m[i],ncl,nch,sch))){ free_matrix(m,nrl,nrh,ncl,sch); int_error("not enough memory to extend matrix",NO_CARET); return NULL; } } } for(i=nrh+1; i<=srh; i++) { if(!(m[i] = (float GPFAR *) gpfaralloc((unsigned long) (nch-ncl+1)*sizeof(float),NULL))){ free_matrix(m,nrl,i-1,nrl,sch); int_error("not enough memory to extend matrix",NO_CARET); return NULL; } m[i] -= ncl; } return m; } /* this routine carves a large matrix down to size */ float GPFAR * GPFAR *retract_matrix(a,nrl,nrh,ncl,nch,srh,sch) register float GPFAR * GPFAR *a; register int nrl,nrh,ncl,nch; register int srh,sch; { register int i; register float GPFAR * GPFAR *m; for(i=srh+1; i<=nrh; i++) { free_vector(a[i],ncl,nch); } /* bug fixed. realloc() called with incorrect 2nd argument. jvdwoude@hut.nl */ if(!(m = (float GPFAR * GPFAR *)gpfarrealloc((void*)(a+nrl), (unsigned long)(srh-nrl+1)*sizeof(float GPFAR *)) )){ int_error("not enough memory to retract matrix",NO_CARET); return NULL; } m -= nrl; if(sch != nch){ for(i=nrl; i<=srh; i++) if(!(m[i] = retract_vector(m[i],ncl,nch,sch))){ {/* Shrink rows */ free_matrix(m,nrl,srh,ncl,sch); int_error("not enough memory to retract matrix",NO_CARET); return NULL; } } } return m; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.