File: binary.c

package info (click to toggle)
gnuplot 3.5beta6.347-3
  • links: PTS
  • area: main
  • in suites: slink
  • size: 5,032 kB
  • ctags: 4,235
  • sloc: ansic: 42,086; makefile: 561; asm: 539; sh: 386; objc: 379; csh: 297; pascal: 194; perl: 138; lisp: 88
file content (422 lines) | stat: -rw-r--r-- 12,010 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
#ifndef lint
static char *RCSid = "$Id: binary.c,v 1.10 1998/04/14 00:14:49 drd Exp $";
#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 "plot.h"   /* We have to get TRUE and FALSE */
#include "stdfn.h"
#include "binary.h"

/* 
 * 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;
  
  if (fread(&fdummy,sizeof(fdummy),1,fin) != 1)
	return FALSE;

  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 = (float)(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] = (float)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] = (float)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 *)gp_alloc((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;
{
  free(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;
  new_v = (float GPFAR *)gp_realloc((void*)(vec+old_nl),
                       (unsigned long)(new_nh-old_nl+1)*sizeof(float),
		       "extend vector");
  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;
  new_v = (float GPFAR *)gp_realloc((void*)(v+old_nl),
   (unsigned long)(new_nh-old_nl+1)*sizeof(float), "retract vector");
  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;

  m = (float GPFAR * GPFAR *)gp_alloc((unsigned long)(nrh-nrl+1)*sizeof(float GPFAR *), "matrix");
  m -= nrl;

  for (i=nrl; i<=nrh; i++)
    {
      if(!(m[i] = (float GPFAR *) gp_alloc((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 unsigned int i;

  for (i=nrl; i<=nrh; i++) 
    free((char GPFAR *) (m[i]+ncl));
  free((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;

  m = (float GPFAR * GPFAR *)gp_realloc((void*)(a+nrl),(unsigned long)(srh-nrl+1)*sizeof(float GPFAR *), "extend matrix");

  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 *) gp_alloc((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);
  }

  m = (float GPFAR * GPFAR *)gp_realloc((void*)(a+nrl), (unsigned long)(srh-nrl+1)*sizeof(float GPFAR *), "retract matrix");

  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;
}

float 
   GPFAR * GPFAR *convert_matrix(a,nrl,nrh,ncl,nch)
float GPFAR *a;
register int nrl,nrh,ncl,nch;

/* allocate a float matrix m[nrl...nrh][ncl...nch] that points to the
matrix declared in the standard C manner as a[nrow][ncol], where 
nrow=nrh-nrl+1, ncol=nch-ncl+1.  The routine should be called with
the address &a[0][0] as the first argument.  This routine does
not free the memory used by the original array a but merely assigns
pointers to the rows. */

{
  register int i,j,ncol,nrow;
  register float GPFAR * GPFAR *m;

  nrow=nrh-nrl+1;
  ncol=nch-ncl+1;
  m = (float GPFAR * GPFAR *)gp_alloc((unsigned long)(nrh-nrl+1)*sizeof(float GPFAR *), "convert_matrix");
  m -= nrl;

  m[nrl]=a-ncl;
  for(i=1,j=nrl+1;i<=nrow-1;i++,j++) m[j]=m[j-1]+ncol;
  return m;
}

void free_convert_matrix(b,nrl,nrh,ncl,nch)
float GPFAR* GPFAR *b;
register int nrl,nrh,ncl,nch;
{
	free((char*) (b+nrl));
}