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