1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * Copyright by The HDF Group. *
3 * Copyright by the Board of Trustees of the University of Illinois. *
4 * All rights reserved. *
5 * *
6 * This file is part of HDF. The full HDF copyright notice, including *
7 * terms governing use, modification, and redistribution, is contained in *
8 * the COPYING file, which can be found at the root of the source code *
9 * distribution tree, or in https://support.hdfgroup.org/ftp/HDF/releases/. *
10 * If you do not have access to either file, you may request a copy from *
11 * help@hdfgroup.org. *
12 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13
14 /* $Id$ */
15
16 #include <stdio.h>
17 #include "mfhdf.h"
18 #include "hdp.h"
19 #include <ctype.h>
20 #ifndef MIPSEL
21 #include <math.h>
22 #endif /* MIPSEL */
23
24 #define CARRIAGE_RETURN 13
25 #define LINE_FEED 10
26 #define HORIZONTAL_TAB 9
27
28 typedef intn (*fmtfunct_t) (VOIDP, file_format_t, FILE *);
29 fmtfunct_t select_func(int32 nt);
30
31 /*
32 * printing functions copied from vshow.c and used by sdsdumpfull().
33 *
34 * Please pay attention to the data types used in the print/output routines.
35 * Make sure the data type being dumped matches arguments in 'fwrite()' .etc.
36 *
37 */
38
39 intn
fmtbyte(unsigned char * x,file_format_t ff,FILE * ofp)40 fmtbyte(unsigned char *x, /* assumption: byte is the same as unsigned char */
41 file_format_t ff,
42 FILE *ofp)
43 {
44 unsigned char s;
45
46 if(ff == DASCII)
47 return (fprintf(ofp, "%02x ", (unsigned) *x));
48 else
49 {
50 s = (unsigned char) *x;
51 return(fwrite(&s, sizeof(unsigned char),1,ofp));
52 }
53 }
54
55 intn
fmtint8(VOIDP x,file_format_t ff,FILE * ofp)56 fmtint8(VOIDP x, /* assumption: int8 is same as signed char */
57 file_format_t ff,
58 FILE *ofp)
59 {
60 int8 s;
61
62 if(ff == DASCII)
63 return (fprintf(ofp, "%d", (int) *((signed char *) x)));
64 else
65 {
66 s = (int8) *((signed char *) x);
67 return(fwrite(&s, sizeof(int8), 1, ofp));
68 }
69 }
70
71 intn
fmtuint8(VOIDP x,file_format_t ff,FILE * ofp)72 fmtuint8(VOIDP x, /* assumption: uint8 is same as unsigned char */
73 file_format_t ff,
74 FILE *ofp)
75 {
76 uint8 s;
77
78 if(ff == DASCII)
79 return (fprintf(ofp, "%u", (unsigned) *((unsigned char *) x)));
80 else
81 {
82 s = (uint8) *((unsigned char *) x);
83 return(fwrite(&s, sizeof(uint8), 1, ofp));
84 }
85 }
86
87 intn
fmtint16(VOIDP x,file_format_t ff,FILE * ofp)88 fmtint16(VOIDP x,
89 file_format_t ff,
90 FILE *ofp)
91 {
92 int16 s;
93
94 HDmemcpy(&s, x, sizeof(int16));
95
96 if(ff == DASCII)
97 return (fprintf(ofp, "%d", (int) s));
98 else
99 return(fwrite(&s, sizeof(int16), 1, ofp));
100 }
101
102 intn
fmtuint16(VOIDP x,file_format_t ff,FILE * ofp)103 fmtuint16(VOIDP x,
104 file_format_t ff,
105 FILE *ofp)
106 {
107 uint16 s;
108
109 HDmemcpy(&s, x, sizeof(uint16));
110
111 if(ff == DASCII)
112 return (fprintf(ofp, "%u", (unsigned) s));
113 else
114 return(fwrite(&s, sizeof(uint16), 1, ofp));
115 }
116
117 intn
fmtchar(VOIDP x,file_format_t ff,FILE * ofp)118 fmtchar(VOIDP x,
119 file_format_t ff,
120 FILE *ofp)
121 {
122 if (isprint(*(unsigned char *) x))
123 {
124 putc(*((char *) x), ofp);
125 return (1);
126 }
127 else
128 {
129 putc('\\', ofp);
130 return (1 + fprintf(ofp, "%03o", *((uchar8 *) x)));
131 }
132 }
133
134 intn
fmtuchar8(VOIDP x,file_format_t ff,FILE * ofp)135 fmtuchar8(VOIDP x, /* assumption: uchar8 is same as unsigned char */
136 file_format_t ff,
137 FILE *ofp)
138 {
139 uchar8 s;
140
141 if(ff == DASCII)
142 /* replace %o with %d by Elena's suggestion: it doesn't make
143 sense to print in octal - BMR 06/23/00 */
144 return (fprintf(ofp, "%d", *((uchar8 *) x)));
145 else
146 {
147 s = (uchar8) *((unsigned char *)x);
148 return(fwrite(&s, sizeof(uchar8),1, ofp));
149 }
150 }
151
152 intn
fmtint(VOIDP x,file_format_t ff,FILE * ofp)153 fmtint(VOIDP x, /* assumption: int is same as 'intn' */
154 file_format_t ff,
155 FILE *ofp)
156 {
157 intn i;
158
159 HDmemcpy(&i, x, sizeof(intn));
160
161 if(ff == DASCII)
162 return (fprintf(ofp, "%d", (int) i));
163 else
164 return(fwrite(&i, sizeof(intn), 1, ofp));
165 }
166
167 #define FLOAT32_EPSILON ((float32)1.0e-20)
168 intn
fmtfloat32(VOIDP x,file_format_t ff,FILE * ofp)169 fmtfloat32(VOIDP x,
170 file_format_t ff,
171 FILE *ofp)
172 {
173 float32 fdata;
174
175 HDmemcpy(&fdata, x, sizeof(float32));
176
177 if(ff == DASCII)
178 {
179 if (fabs(fdata - FILL_FLOAT) <= FLOAT32_EPSILON)
180 return (fprintf(ofp, "FloatInf"));
181 else
182 return (fprintf(ofp, "%f", fdata));
183 }
184 else
185 {
186 return(fwrite(&fdata, sizeof(float32), 1, ofp));
187 }
188 }
189
190 intn
fmtint32(VOIDP x,file_format_t ff,FILE * ofp)191 fmtint32(VOIDP x,
192 file_format_t ff,
193 FILE *ofp)
194 {
195 int32 l;
196
197 HDmemcpy(&l, x, sizeof(int32));
198
199 if(ff == DASCII)
200 return (fprintf(ofp, "%ld", (long) l));
201 else
202 return(fwrite(&l, sizeof(int32), 1, ofp));
203 }
204
205 intn
fmtuint32(VOIDP x,file_format_t ff,FILE * ofp)206 fmtuint32(VOIDP x,
207 file_format_t ff,
208 FILE *ofp)
209 {
210 uint32 l;
211
212 HDmemcpy(&l, x, sizeof(uint32));
213
214 if(ff == DASCII)
215 return (fprintf(ofp, "%lu", (unsigned long) l));
216 else
217 return(fwrite(&l, sizeof(uint32), 1, ofp));
218 }
219
220 intn
fmtshort(VOIDP x,file_format_t ff,FILE * ofp)221 fmtshort(VOIDP x,
222 file_format_t ff,
223 FILE *ofp)
224 {
225 short s;
226
227 HDmemcpy(&s, x, sizeof(short));
228
229 if(ff == DASCII)
230 return (fprintf(ofp, "%d", (int) s));
231 else
232 return(fwrite(&s, sizeof(short), 1, ofp));
233 }
234
235 #define FLOAT64_EPSILON ((float64)1.0e-20)
236 intn
fmtfloat64(VOIDP x,file_format_t ff,FILE * ofp)237 fmtfloat64(VOIDP x,
238 file_format_t ff,
239 FILE *ofp)
240 {
241 float64 d;
242
243 HDmemcpy(&d, x, sizeof(float64));
244
245 if(ff == DASCII)
246 {
247 if (fabs(d - FILL_DOUBLE) <= FLOAT64_EPSILON)
248 return (fprintf(ofp, "DoubleInf"));
249 else
250 return (fprintf(ofp, "%f", d));
251 }
252 else
253 {
254 return(fwrite(&d, sizeof(float64), 1, ofp));
255 }
256 }
257
select_func(int32 nt)258 fmtfunct_t select_func(
259 int32 nt)
260 {
261 switch (nt & 0xff )
262 {
263 case DFNT_CHAR:
264 return( fmtchar );
265 break;
266 case DFNT_UCHAR:
267 return( fmtuchar8 );
268 break;
269 case DFNT_UINT8:
270 return( fmtuint8 );
271 break;
272 case DFNT_INT8:
273 return( fmtint8 );
274 break;
275 case DFNT_UINT16:
276 return( fmtuint16 );
277 break;
278 case DFNT_INT16:
279 return( fmtint16 );
280 break;
281 case DFNT_UINT32:
282 return( fmtuint32 );
283 break;
284 case DFNT_INT32:
285 return( fmtint32 );
286 break;
287 case DFNT_FLOAT32:
288 return( fmtfloat32 );
289 break;
290 case DFNT_FLOAT64:
291 return( fmtfloat64 );
292 break;
293 default:
294 fprintf(stderr, "HDP does not support type [%d]. Use signed character printing function.\n", (int) nt);
295 return( fmtchar );
296 } /* end switch */
297 } /* select_func */
298
299 intn
dumpfull(int32 nt,dump_info_t * dump_opts,int32 cnt,VOIDP databuf,FILE * ofp,intn indent,intn cont_indent)300 dumpfull(int32 nt,
301 dump_info_t* dump_opts,
302 int32 cnt, /* number of items in 'databuf' ? */
303 VOIDP databuf,
304 FILE *ofp,
305 intn indent, /* indentation on the first line */
306 intn cont_indent ) /* indentation on the continuous lines */
307 {
308 intn i;
309 VOIDP bufptr = NULL;
310 fmtfunct_t fmtfunct = NULL;
311 int32 off;
312 intn cn;
313 file_format_t ff = dump_opts->file_format;
314 intn ret_value = SUCCEED;
315
316 /* check inputs */
317 if( NULL == databuf )
318 ERROR_GOTO_1( "in %s: Data buffer to be dumped is NULL", "dumpfull" );
319 if( NULL == ofp )
320 ERROR_GOTO_1( "in %s: Output file pointer is NULL", "dumpfull" );
321
322 /* select the appropriate function to print data elements depending
323 on the data number type */
324 fmtfunct = select_func( nt );
325
326 /* assign to variables used in loop below (?)*/
327 bufptr = databuf;
328 off = DFKNTsize(nt | DFNT_NATIVE); /* what is offset for data type */
329 if (off == FAIL)
330 ERROR_GOTO_2("in %s: Failed to find native size of type [%d]",
331 "dumpfull", (int)nt );
332
333 cn = cont_indent; /* current column number, cont_indent because that's
334 where the data actually starts */
335
336 /* check if we're dumping data in ASCII or Binary mode. */
337 if(ff == DASCII)
338 {
339 /* print spaces in front of data on the first line */
340 for (i = 0; i < indent; i++)
341 putc(' ', ofp);
342
343 if (nt != DFNT_CHAR)
344 {
345 for (i = 0; i < cnt && bufptr != NULL; i++)
346 {
347 cn += fmtfunct(bufptr, ff, ofp); /* dump item to file */
348 bufptr = (char *) bufptr + off;
349 putc(' ', ofp);
350 cn++;
351
352 /* temporary fix bad alignment algo in dumpfull by
353 adding i < cnt-1 to remove extra line - BMR 4/10/99 */
354 if( !dump_opts->as_stream ) /* add \n after MAXPERLINE chars */
355 if (cn > MAXPERLINE && i < cnt-1 )
356 {
357 putc('\n', ofp);
358
359 /* print spaces in front of data on the continuous line */
360 for (cn = 0; cn < cont_indent; cn++)
361 putc(' ', ofp);
362 } /* end if */
363 } /* end for every item in buffer */
364 }
365 else /* DFNT_CHAR */
366 {
367 for (i = 0; i < cnt && bufptr != NULL; i++)
368 {
369 cn += fmtfunct(bufptr, ff, ofp); /* dump item to file */
370 bufptr = (char *) bufptr + off;
371 if( !dump_opts->as_stream ) /* add \n after MAXPERLINE chars */
372 if (cn > MAXPERLINE )
373 {
374 putc('\n', ofp);
375
376 /* print spaces in front of data on the continuous line */
377 for (cn = 0; cn < cont_indent; cn++)
378 putc(' ', ofp);
379 } /* end if */
380 } /* end for every item in buffer */
381 } /* end else DFNT_CHAR */
382
383 putc('\n', ofp); /* newline after a dataset or attribute */
384
385 } /* end DASCII */
386 else /* Binary */
387 {
388 for (i = 0; i < cnt && bufptr != NULL; i++)
389 {
390 cn += fmtfunct(bufptr, ff, ofp); /* dump item to file */
391 bufptr = (char *) bufptr + off; /* increment by offset? */
392 /* cn++; I don't see any reason of this increment being here 9/4/00*/
393 } /* end for all items in buffer */
394 }
395
396 done:
397 if (ret_value == FAIL)
398 { /* Failure cleanup */
399 }
400 /* Normal cleanup */
401
402 return ret_value;
403 } /* dumpfull */
404
405 intn
dumpclean(int32 nt,dump_info_t * dump_opts,int32 cnt,VOIDP databuf,FILE * ofp)406 dumpclean(int32 nt,
407 dump_info_t* dump_opts,
408 int32 cnt, /* number of items in 'databuf' ? */
409 VOIDP databuf,
410 FILE *ofp)
411 {
412 intn i;
413 VOIDP bufptr = NULL;
414 int32 off;
415 intn cn; /* # of characters being printed on a line */
416 intn small_attr = TRUE; /* data buffer of the attribute is small */
417 intn is_null; /* TRUE if current character is a null */
418 char* tempptr; /* used in finding CR or LF in data buffer */
419 intn ret_value = SUCCEED;
420
421 /* check inputs */
422 if( NULL == databuf )
423 ERROR_GOTO_1( "in %s: Data buffer to be dumped is NULL", "dumpclean" );
424 if( NULL == ofp )
425 ERROR_GOTO_1( "in %s: Output file pointer is NULL", "dumpclean" );
426
427 /* assign to variables used in loop below (?)*/
428 bufptr = databuf;
429 off = DFKNTsize(nt | DFNT_NATIVE); /* what is offset for data type */
430 if (off == FAIL)
431 ERROR_GOTO_2("in %s: Failed to find native size of type [%d]",
432 "dumpclean", (int)nt );
433
434 /* set char counter to the col. #, where the first attr value will be
435 printed in the case it is printed on the same line with "Value =" */
436 cn = ATTR_CONT_INDENT; /* this is the default */
437
438 is_null = FALSE; /* no null character is reached yet */
439
440 /***********************************************************************
441 * Requirement for printing attribute data (BMR - Oct 5, 2000):
442 * if the attribute is large, print all data at the left most column;
443 * otherwise (small attribute), print the first line of the data
444 * next to the title, i.e. "Value = ", and indent the succeeding lines
445 * ATTR_CONT_INDENT spaces.
446 * Large attribute: buffer size is >= MAXPERLINE and the buffer
447 * contains at least one \n (LF) or \r (CR).
448 * Small attribute: buffer size is < MAXPERLINE or the buffer doesn't
449 * contain any \n (LF) or \r (CR) among the data.
450 ***********************************************************************/
451
452 /* Setting variables to prepare for the printing */
453
454 /* check the size of the buffer first, if it's shorter than MAXPERLINE
455 then set flag small_attr. If the buffer size is larger, then
456 proceed to the next segment which determines whether the attribute
457 is small or large using the space char. criteria. */
458
459 if( cnt < MAXPERLINE )
460 small_attr = TRUE;
461
462 /* if the buffer contains at least one \n (LF) or \r (CR), reset
463 flag small_attr to indicate the attribute is considred large. */
464 else /* space char. criteria */
465 {
466 tempptr = strchr( (char *) bufptr, '\n'); /* find the first linefeed */
467 if( tempptr != NULL) /* if an LF is found within the data buffer */
468 {
469 putc('\n', ofp); /* start first line of data on the next line */
470 small_attr = FALSE; /* indicate data buffer contains CRs or LFs */
471 }
472 else /* no LF, maybe CR is there */
473 {
474 tempptr = strchr( (char *) bufptr, '\r');
475 if( tempptr != NULL) /* if a CR is found within the data buffer */
476 {
477 putc('\n', ofp); /* start first line of data on the next line */
478 small_attr = FALSE; /* indicate data buffer contains CRs or LFs */
479 }
480 }
481 } /* space char. criteria */
482
483 /* for each character in the buffer, print it accordingly */
484 for (i = 0; i < cnt; i++)
485 {
486 /* if number of characters printed on the current line reaches
487 the max defined and the data buffer doesn't contain any LF or
488 CR, print a new line and indent appropriately.
489 Note: this statement is at the top here is to prevent the
490 extra line and indentation when the last line of the attribute
491 data just reached MAXPERLINE */
492 if (cn >= MAXPERLINE && small_attr )
493 {
494 putc('\n', ofp);
495 for (cn = 0; cn < ATTR_CONT_INDENT; cn++)
496 putc(' ', ofp);
497 } /* end if */
498
499 /* if the current character is printable */
500 if (isprint(*(unsigned char *) bufptr))
501 {
502 /* if there has been null characters before this non-null char,
503 print "..." */
504 if( is_null )
505 {
506 cn = cn + fprintf( ofp, " ... " );
507 is_null = FALSE; /* reset flag */
508 }
509
510 /* then print the current non-null character */
511 putc(*((char *) bufptr), ofp);
512 cn++; /* increment character count */
513 }
514
515 /* when a \0 is reached, do not print it, set flag for its existence,
516 so when a non-null char is reached, "..." can be printed */
517 else if( *(unsigned char *) bufptr == '\0')
518 is_null = TRUE;
519
520 /* when a space character, such as LF, CR, or tab, is reached, print
521 it and increment the character counter accordingly */
522 else if( isspace(*(unsigned char *) bufptr))
523 {
524 /* when either LF or CR exists in the data buffer, character
525 counter, cn, is no longer needed since we don't need to keep
526 track of the number of chars being printed on a line anymore.
527 Yet, for logical purpose, reset it here just as a new line
528 of data starts */
529 if( *(unsigned char *) bufptr == CARRIAGE_RETURN
530 || *(unsigned char *) bufptr == LINE_FEED )
531 {
532 putc('\n', ofp); /* print \n for both CR and LF, otherwise, CR=^M*/
533 cn = 0; /* indicating that next data element will be printed
534 at column 1 */
535 }
536 else if( *(unsigned char *) bufptr == HORIZONTAL_TAB )
537 {
538 putc(*((char *) bufptr), ofp);
539 cn = cn + 8; /* compensate for the tab, at most 8 chars */
540 }
541
542 /* keep this else here to take care of other isspace cases, fill in
543 more cases as need; if all cases are taken care of, remove else */
544 else
545 {
546 putc('\\', ofp);
547 cn = cn + fprintf(ofp, "%03o", *((uchar8 *) bufptr));
548 }
549 }
550 else
551 {
552 /* this should be printed as binary intstead of \digits */
553 putc('\\', ofp);
554 cn = cn + fprintf(ofp, "%03o", *((uchar8 *) bufptr));
555 }
556
557 /* advance the buffer pointer */
558 bufptr = (char *) bufptr + off;
559
560 /* Move here to avoid internal compiler error on Cray J90 -QAK */
561 if(bufptr==NULL)
562 break;
563 } /* end for every item in buffer */
564
565 putc('\n', ofp); /* newline */
566
567 done:
568 if (ret_value == FAIL)
569 { /* Failure cleanup */
570 }
571 /* Normal cleanup */
572
573 return ret_value;
574 } /* dumpclean */
575
576