1 #include "config.h"
2 
3 #ifdef HAVE_UNISTD_H
4 #include <unistd.h>
5 #endif
6 #ifdef HAVE_MALLOC_H
7 #include <malloc.h>
8 #endif
9 #ifdef HAVE_STRING_H
10 #include <string.h>
11 #endif
12 #include <sys/types.h>
13 #include <ctype.h>
14 #include <stdlib.h>
15 #ifdef HAVE_MEMORY_H
16 #include <memory.h>
17 #endif
18 #ifdef HAVE_NETDB_H
19 #include <netdb.h>
20 #endif
21 #include "unix_defs.h"
22 #include <limits.h>
23 
24 #include "assert.h"
25 #include "ffs.h"
26 #include "ffs_internal.h"
27 
28 struct _xml_output_info {
29     char *prestring;  /* output this before this field */
30     int field_num;
31     IOFieldPtr field_ptr;
32     IOdata_type base_type;
33     IOVarInfoStruct *iovar;	/* for dynamic arrays, array size */
34     char *element_prestring;
35     char *element_poststring;
36     char *poststring;  /* output this after this field */
37 };
38 
39 typedef struct dstring {
40     char *string;
41     int length;
42     int max_alloc;
43 } *ffs_dstring;
44 
45 static int get_int_attr(int *int_ptr, char *name, char *start, char *end);
46 static int get_str_attr(char **str_ptr, char *name, char *start, char *end);
47 static void internal_record_to_XML_string(IOFormat ioformat, void *data,
48 					  void *string_base, ffs_dstring ds,
49 					  int encoded);
50 static void
51 generic_field_to_XML ARGS((IOFile iofile, IOFormat ioformat, int field,
52 			   void *data, void *string_base, int encode,
53 			   ffs_dstring ds));
54 
55 
56 static int
is_tag(char * tag,char * xml_stream)57 is_tag(char *tag, char *xml_stream)
58 {
59     int len = strlen(tag);
60     if (strncmp(xml_stream, tag, len) != 0) return 0;
61     if (isalnum((int)xml_stream[len])) return 0;  /* not end of stream tag */
62     if (xml_stream[len] == '_') return 0;
63     if (xml_stream[len] == '-') return 0;
64     return 1;
65 }
66 
67 extern void
free_XML_output_info(xml_output_info info)68 free_XML_output_info(xml_output_info info)
69 {
70     int i = 0;
71     while(info[i].field_ptr == NULL) {
72 	if (info[i].prestring != NULL) free(info[i].prestring);
73 	if (info[i].poststring != NULL) free(info[i].poststring);
74 	if (info[i].element_prestring != NULL)
75 	    free(info[i].element_prestring);
76 	if (info[i].element_poststring != NULL)
77 	    free(info[i].element_poststring);
78     }
79     free(info);
80 }
81 
82 
83 
84 static void
expand_dstring(ffs_dstring ds,int min)85 expand_dstring(ffs_dstring ds, int min)
86 {
87     int len = ds->max_alloc;
88     int add = ds->max_alloc >> 3;   /* add an eighth */
89     if (add < min) add = min;
90     if (add < 128) add = 128;
91     ds->string = realloc(ds->string, len + add);
92     ds->max_alloc = len + add;
93 }
94 
95 static void
dcatstr(ffs_dstring ds,char * str)96 dcatstr(ffs_dstring ds, char *str)
97 {
98     int len = strlen(str);
99     if (ds->length + len + 1 > ds->max_alloc) {
100 	expand_dstring(ds, len + 1);
101     }
102     strcat(&ds->string[ds->length], str);
103     ds->length += len;
104 }
105 
106 static ffs_dstring
new_dstring()107 new_dstring()
108 {
109     ffs_dstring dstr = malloc(sizeof(struct dstring));
110     dstr->string = malloc(64);
111     dstr->string[0] = 0;
112     dstr->length = 0;
113     dstr->max_alloc = 64;
114     return dstr;
115 }
116 
117 static ffs_dstring
record_to_XML_string(IOFormat ioformat,void * data,int encoded)118 record_to_XML_string(IOFormat ioformat, void *data, int encoded)
119 {
120     ffs_dstring dstr = new_dstring();
121     internal_record_to_XML_string(ioformat, data, data, dstr, encoded);
122     return dstr;
123 }
124 
125 static ffs_dstring
raw_to_XML_string(iofile,ioformat,data,encoded)126 raw_to_XML_string(iofile, ioformat, data, encoded)
127 IOFile iofile;
128 IOFormat ioformat;
129 void *data;
130 int encoded;
131 {
132     int index;
133     ffs_dstring ds;
134     if (IOhas_XML_info(ioformat)) {
135 	return record_to_XML_string(ioformat, data, encoded);
136     }
137     ds = new_dstring();
138     dcatstr(ds, "<");
139     dcatstr(ds, ioformat->body->format_name);
140     dcatstr(ds, ">\n");
141     for (index = 0; index < ioformat->body->field_count; index++) {
142 	generic_field_to_XML(iofile, ioformat, index, data, data,
143 			     encoded, ds);
144     }
145     dcatstr(ds, "</");
146     dcatstr(ds, ioformat->body->format_name);
147     dcatstr(ds, ">\n");
148     return ds;
149 }
150 
151 extern void
152 dump_raw_IOrecord_as_XML(iofile, ioformat, data)
153 IOFile iofile;
154 IOFormat ioformat;
155 void *data;
156 {
157     ffs_dstring dstr = raw_to_XML_string(iofile, ioformat, data, 1);
158     printf("%s", dstr->string);
159 }
160 
161 extern char*
IOencoded_to_XML_string(IOContext iocontext,void * data)162 IOencoded_to_XML_string(IOContext iocontext, void *data)
163 {
164     IOFormat ioformat = get_format_IOcontext(iocontext, data);
165     int header_size;
166     ffs_dstring dstr = NULL;
167     char *str = NULL;
168 
169     if (ioformat == NULL) return NULL;
170     header_size = header_size_IOformat(ioformat);
171     dstr = raw_to_XML_string((IOFile)iocontext, ioformat,
172 			     (char*)data + header_size, 1);
173     str = dstr->string;
174     free(dstr);
175     return str;
176 }
177 
178 extern char*
IOunencoded_to_XML_string(IOContext iocontext,IOFormat ioformat,void * data)179 IOunencoded_to_XML_string(IOContext iocontext, IOFormat ioformat, void *data)
180 {
181     ffs_dstring dstr = raw_to_XML_string((IOFile)iocontext, ioformat, data, 0);
182     char *str = dstr->string;
183     free(dstr);
184     return str;
185 }
186 
187 extern void
dump_encoded_as_XML(IOContext context,void * data)188 dump_encoded_as_XML(IOContext context, void *data)
189 {
190     IOFormat ioformat = get_format_IOcontext(context, data);
191     int header_size;
192     if (ioformat == NULL) {
193 	printf("Encoded record has no valid IOFormat\n");
194 	return;
195     }
196     header_size = header_size_IOformat(ioformat);
197     dump_XML_record(ioformat, (char*)data + header_size, 1);
198 }
199 
200 extern void
internal_dump_XML_record(IOFormat ioformat,void * data,void * string_base,int encoded)201 internal_dump_XML_record(IOFormat ioformat, void *data, void *string_base, int encoded)
202 {
203     struct dstring ds;
204     ds.string = malloc(64);
205     ds.string[0] = 0;
206     ds.length = 0;
207     ds.max_alloc = 64;
208     internal_record_to_XML_string(ioformat, data, string_base, &ds, encoded);
209     printf("%s", ds.string);
210     free(ds.string);
211 }
212 
213 static void
internal_record_to_XML_string(IOFormat ioformat,void * data,void * string_base,ffs_dstring ds,int encoded)214 internal_record_to_XML_string(IOFormat ioformat, void *data, void *string_base, ffs_dstring ds, int encoded)
215 
216 {
217     int i = -1;
218     xml_output_info info;
219     if (!IOhas_XML_info(ioformat)) {
220 	dump_raw_IOrecord_as_XML(ioformat->context, ioformat, data);
221 	return;
222     }
223     info = ioformat->body->xml_out;
224     while(info[++i].field_ptr != NULL) {
225 	int j;
226 	int array_dimen = get_static_array_element_count(info[i].iovar);
227 	void *base = (char*)data;
228 	IOFieldPtr field_ptr = info[i].field_ptr;
229 	struct _IOgetFieldStruct dummy_ptr;
230 	if (info[i].prestring != NULL) {
231 	    dcatstr(ds, info[i].prestring);
232 /*	    printf("%s", info[i].prestring);*/
233 	}
234 	if (array_dimen == -1) {
235 	    array_dimen = get_array_element_count(info[i].iovar, base, 1);
236 	    dummy_ptr = *field_ptr;
237 	    dummy_ptr.size = ioformat->body->pointer_size;
238 	    dummy_ptr.data_type = integer_type;
239 	    base = get_IOaddr(&dummy_ptr, base, string_base, encoded);
240 	    dummy_ptr = *field_ptr;
241 	    field_ptr = &dummy_ptr;
242 	    dummy_ptr.offset = 0;
243 	}
244 	for(j=0; j<array_dimen; j++) {
245 	    if (info[i].element_prestring != NULL) {
246 		dcatstr(ds, info[i].element_prestring);
247 /*		printf("%s", info[i].element_prestring);*/
248 	    }
249 	    switch(info[i].base_type) {
250 	    case integer_type:
251 	    {
252 		char tmp[64];
253 		long l;
254 		l = get_IOlong(field_ptr, base);
255 		sprintf(tmp, "%ld", l);
256 		dcatstr(ds, tmp);
257 		break;
258 	    }
259 	    case unsigned_type:
260 	    case enumeration_type:
261 	    {
262 		char tmp[64];
263 		unsigned long l;
264 		l = get_IOulong(field_ptr, base);
265 		sprintf(tmp, "%lu", l);
266 		dcatstr(ds, tmp);
267 		break;
268 	    }
269 	    case boolean_type:
270 	    {
271 		unsigned long l;
272 		l = get_IOulong(field_ptr, base);
273 		if (l)
274 		    dcatstr(ds, "true");
275 		else
276 		    dcatstr(ds, "false");
277 		break;
278 	    }
279 	    case float_type:
280 	    {
281 		char tmp[64];
282 		double d;
283 		d = get_IOdouble(field_ptr, base);
284 		sprintf(tmp, "%g", d);
285 		dcatstr(ds, tmp);
286 		break;
287 	    }
288 	    case char_type:
289 	    {
290 		char tmp[2];
291 		tmp[0] = get_IOchar(field_ptr, base);
292 		tmp[1] = 0;
293 		dcatstr(ds, tmp);
294 		break;
295 	    }
296 	    case string_type:
297 	    {
298 		char *s;
299 		s = get_IOaddr(field_ptr, base, string_base, encoded);
300 		if (s) dcatstr(ds, s);
301 		break;
302 	    }
303 	    case unknown_type:
304 	    {
305 		int field = info[i].field_num;
306 		int offset = field_ptr->offset;
307 		IOFormat sub = ioformat->field_subformats[field];
308 		if (sub != NULL) {
309 		    internal_record_to_XML_string(sub, (char*)base+offset,
310 						  string_base, ds, encoded);
311 		} else {
312 		    dcatstr(ds, "<INCONSISTENCY!  SUBFORMAT NOT FOUND FOR FIELD TYPE \"");
313 		    dcatstr(ds, (char*)ioformat->body->field_list[field].field_type);
314 		    dcatstr(ds, "\">\n");
315 		}
316 		break;
317 	    }
318 	    }  /* end switch */
319 	    if (info[i].element_poststring != NULL) {
320 		dcatstr(ds, info[i].element_poststring);
321 	    }
322 	    if ((info[i].element_prestring == NULL) &&
323 		(info[i].element_poststring == NULL)
324 		&& (info[i].base_type != unknown_type)) {
325 		dcatstr(ds, " ");
326 	    }
327 
328 	    base =  (char *) base + field_ptr->size;
329 	}
330 	if (info[i].poststring != NULL) {
331 	    dcatstr(ds, info[i].poststring);
332 	}
333     }
334 }
335 
336 extern void
dump_XML_record(IOFormat ioformat,void * data,int encoded)337 dump_XML_record(IOFormat ioformat, void *data, int encoded)
338 {
339     internal_dump_XML_record(ioformat, data, data, encoded);
340 }
341 
342 static int
get_field_num(int * field_num_ptr,IOFormat ioformat,char * left,char * right)343 get_field_num(int* field_num_ptr, IOFormat ioformat, char *left, char *right)
344 {
345     char *field_name = NULL;
346     int field_num;
347     if (!get_str_attr(&field_name, "field_name", left, right)) {
348 	if (!get_int_attr(&field_num, "field_id", left, right)) {
349 	    printf("Neither Field_name nor Field_id attribute found\n");
350 	    return 0;
351 	}
352     } else {
353 	field_num = 0;
354 	while(strcmp(ioformat->body->field_list[field_num].field_name,
355 		     field_name) != 0) {
356 	    field_num++;
357 	    if (field_num >= ioformat->body->field_count) {
358 		printf("Field name %s not found in format\n", field_name);
359 		free(field_name);
360 		return 0;
361 	    }
362 	}
363 	free(field_name);
364     }
365     if (field_num >= ioformat->body->field_count) {
366 	printf("Field number %d too big\n", field_num);
367 	return 0;
368     }
369     *field_num_ptr = field_num;
370     return 1;
371 }
372 
373 extern void *
get_optinfo_IOFormat(IOFormat ioformat,int info_type,int * len_p)374 get_optinfo_IOFormat(IOFormat ioformat, int info_type, int *len_p)
375 {
376     int i = 0;
377     if (ioformat->body->opt_info == NULL) return NULL;
378     while(ioformat->body->opt_info[i].info_type != 0) {
379 	if (ioformat->body->opt_info[i].info_type == info_type) {
380 	    *len_p = ioformat->body->opt_info[i].info_len;
381 	    return ioformat->body->opt_info[i].info_block;
382 	}
383 	i++;
384     }
385     return NULL;
386 }
387 
388 static xml_output_info
build_XML_output_info(IOFormat ioformat)389 build_XML_output_info(IOFormat ioformat)
390 {
391     int i = 0, last_mark;
392     char *XML_opt_data = NULL;
393     int XML_data_len = 0;
394     xml_output_info info = NULL;
395     int info_count = 0;
396 
397     XML_opt_data = get_optinfo_IOFormat(ioformat, 0x584D4C20, &XML_data_len);
398 
399     if (XML_opt_data == NULL) return NULL;
400     last_mark = 0;
401     i = -1;
402     while (++i < XML_data_len) {
403 	if (XML_opt_data[i] != '<') {
404 	    continue;
405 	}
406 	if (is_tag("/FFS:array", &XML_opt_data[i+1])) {
407 	    /* array termination */
408 	    int post_len = i - last_mark + 1;
409 	    info[info_count].element_poststring = malloc(post_len);
410 	    strncpy(info[info_count].element_poststring,
411 		    &XML_opt_data[last_mark], post_len -1);
412 	    info[info_count].element_poststring[post_len -1] = 0;
413 	    info_count++;
414 	    i += 13;
415 	    last_mark = i;
416 	    continue;
417 	}
418 	if (is_tag("FFS:data", &XML_opt_data[i+1])) {
419 	    int pre_len = i - last_mark;
420 	    IOdata_type data_type;
421 	    int field_num;
422 	    long junk;
423 	    char *right_end = strchr(&XML_opt_data[i+9], '>');
424 	    char *prestring = malloc(pre_len + 1);
425 	    IOFieldPtr field_ptr = NULL;
426 
427 	    strncpy(prestring, &XML_opt_data[last_mark], pre_len);
428 	    prestring[pre_len] = 0;
429 	    if (!get_field_num(&field_num, ioformat, XML_opt_data + i + 9,
430 			       right_end)) {
431 		i = right_end - XML_opt_data;
432 		continue;
433 	    }
434 	    data_type = array_str_to_data_type(ioformat->body->field_list[field_num].field_type,
435 					       &junk);
436 	    field_ptr = io_malloc(sizeof(struct _IOgetFieldStruct));
437 	    field_ptr->offset = ioformat->body->field_list[field_num].field_offset;
438 	    field_ptr->size = ioformat->body->field_list[field_num].field_size;
439 	    field_ptr->data_type = data_type;
440 	    field_ptr->byte_swap = ioformat->body->byte_reversal;
441 	    field_ptr->src_float_format = ioformat->body->float_format;
442 	    field_ptr->target_float_format = ffs_my_float_format;
443 	    if (info_count == 0) {
444 		info = malloc(sizeof(*info) * 2);
445 	    } else {
446 		info = realloc(info, sizeof(*info) * (info_count + 2));
447 	    }
448 	    info[info_count+1].field_ptr = NULL;
449 	    info[info_count].prestring = prestring;
450 	    info[info_count].field_ptr = field_ptr;
451 	    info[info_count].base_type = data_type;
452 	    info[info_count].poststring = NULL;
453 	    info[info_count].field_num = field_num;
454 	    info[info_count].iovar = &ioformat->body->var_list[field_num];
455 	    info[info_count].element_prestring = NULL;
456 	    info[info_count].element_poststring = NULL;
457 	    info_count++;
458 	    i = right_end - XML_opt_data;
459 	    last_mark = i + 1;
460 	    continue;
461 	}
462 	if (is_tag("FFS:array", &XML_opt_data[i+1])) {
463 	    /* array termination */
464 	    int pre_len = i - last_mark;
465 	    char *right_end = strchr(&XML_opt_data[i+10], '>');
466 	    char *prestring = malloc(pre_len + 1);
467 
468 	    strncpy(prestring, &XML_opt_data[last_mark], pre_len);
469 	    prestring[pre_len] = 0;
470 	    if (info_count == 0) {
471 		info = malloc(sizeof(*info) * 2);
472 	    } else {
473 		info = realloc(info, sizeof(*info) * (info_count + 2));
474 	    }
475 	    info[info_count+1].field_ptr = NULL;
476 	    info[info_count].prestring = prestring;
477 	    info[info_count].poststring = NULL;
478 	    i = right_end - XML_opt_data;
479 	    last_mark = i + 1;
480 	    continue;
481 	}
482 	if (is_tag("FFS:array_data_mark", &XML_opt_data[i+1])) {
483 	    /* array termination */
484 	    int pre_len = i - last_mark;
485 	    int field_num;
486 	    char *right_end = strchr(&XML_opt_data[i+9], '>');
487 	    char *prestring = malloc(pre_len + 1);
488 	    long elements;
489 	    IOdata_type data_type;
490 	    IOFieldPtr field_ptr = NULL;
491 
492 	    strncpy(prestring, &XML_opt_data[last_mark], pre_len);
493 	    prestring[pre_len] = 0;
494 	    if (!get_field_num(&field_num, ioformat, XML_opt_data + i + 9,
495 			       right_end)) {
496 		i = right_end - XML_opt_data;
497 		continue;
498 	    }
499 	    info[info_count].element_prestring = prestring;
500 	    data_type = array_str_to_data_type(ioformat->body->field_list[field_num].field_type,
501 					       &elements);
502 	    info[info_count].iovar = &ioformat->body->var_list[field_num];
503 	    info[info_count].base_type = data_type;
504 	    info[info_count].field_num = field_num;
505 	    field_ptr = io_malloc(sizeof(struct _IOgetFieldStruct));
506 	    field_ptr->offset = ioformat->body->field_list[field_num].field_offset;
507 	    field_ptr->size = ioformat->body->field_list[field_num].field_size;
508 	    field_ptr->data_type = data_type;
509 	    field_ptr->byte_swap = ioformat->body->byte_reversal;
510 	    field_ptr->src_float_format = ioformat->body->float_format;
511 	    field_ptr->target_float_format = ffs_my_float_format;
512 	    info[info_count].field_ptr = field_ptr;
513 	    i = right_end - XML_opt_data;
514 	    last_mark = i + 1;
515 	    continue;
516 	}
517     }
518     if (info_count != 0) {
519 	int post_len = XML_data_len - last_mark;
520 	char *poststring = malloc(post_len + 1);
521 	strncpy(poststring, &XML_opt_data[last_mark], post_len);
522 	poststring[post_len] = 0;
523 	info[info_count-1].poststring = poststring;
524 	info[info_count].field_ptr = NULL;
525 /*	    for(i=0; i < info_count; i++) {
526 	    printf("XML field info:\n");
527 	    printf("    prestring = \"%s\"\n", info[i].prestring);
528 	    printf("    field num = \"%d\"\n", info[i].field_num);
529 	    printf("    field name = \"%s\"\n",
530 	       ioformat->body->field_list[info[i].field_num].field_name);
531 	    printf("    poststring = \"%s\"\n", info[i].poststring == NULL ?
532 	        "(NULL)":info[i].poststring);
533 	}*/
534 	return info;
535     } else {
536 	return NULL;
537     }
538 }
539 
540 static int
get_int_attr(int * int_ptr,char * name,char * start,char * end)541 get_int_attr(int *int_ptr, char *name, char *start, char *end)
542 {
543     int name_len = strlen(name);
544     start -= 1;
545     while(++start < (end - name_len)) {
546 	if (*start == *name) {
547 	    /* first char eq, check further */
548 	    if (is_tag(name, start)) {
549 		char *point = &start[name_len];
550 		char *tmp;
551 		while (isspace((int)*point)) point++;
552 		if (point > end) continue;
553 		if (*point != '=') continue;
554 		point++;
555 		*int_ptr = strtol(point, &tmp, 10);
556 		if (tmp != point) {
557 		    return 1;
558 		} else {
559 		    return 0;
560 		}
561 	    }
562 	}
563     }
564     return 0;
565 }
566 
567 static int
get_str_attr(char ** str_ptr,char * name,char * start,char * end)568 get_str_attr(char **str_ptr, char *name, char *start, char *end)
569 {
570     int name_len = strlen(name);
571     start -= 1;
572     while(++start < (end - name_len)) {
573 	if (*start == *name) {
574 	    /* first char eq, check further */
575 	    if (is_tag(name, start)) {
576 		char *point = &start[name_len];
577 		char *attr = NULL;
578 		while (isspace((int)*point)) point++;
579 		if (point > end) continue;
580 		if (*point != '=') continue;
581 		point++;
582 		while (isspace((int)*point)) point++;
583 		if (point > end) continue;
584 		if (*point == '"') {
585 		    /* begin quote */
586 		    char *end_quote = strchr(point+1, '"');
587 		    point++;
588 		    if ((end_quote == 0) || (end_quote > end)) continue;
589 		    attr = malloc(end_quote - point + 1);
590 		    strncpy(attr, point, end_quote - point);
591 		    attr[end_quote - point] = 0;
592 		    *str_ptr = attr;
593 		    return 1;
594 		} else {
595 		    char *next_space = point;
596 		    while(isalnum((int)*next_space) || (*next_space=='_'))
597 			next_space++;
598 		    attr = malloc(next_space - point+1);
599 		    strncpy(attr, point, next_space - point);
600 		    attr[next_space - point] = 0;
601 		    *str_ptr = attr;
602 		    return 1;
603 		}
604 	    }
605 	}
606     }
607     return 0;
608 }
609 
610 extern int
IOhas_XML_info(IOFormat ioformat)611 IOhas_XML_info(IOFormat ioformat)
612 {
613     if (ioformat->body->xml_out == (void*) -1) return 0;
614     if (ioformat->body->xml_out == NULL) {
615 	/* search opt info */
616 	ioformat->body->xml_out = build_XML_output_info(ioformat);
617 	if (ioformat->body->xml_out == NULL) {
618 	    ioformat->body->xml_out = (void*)-1;
619 	    return 0;
620 	}
621     }
622     return 1;
623 }
624 
625 extern void
626 dump_IOfield_as_XML(iofile, ioformat, field, data, string_base, encode, verbose)
627 IOFile iofile;
628 IOFormat ioformat;
629 int field;
630 void *data;
631 void *string_base;
632 int encode;
633 int verbose;
634 {
635     ffs_dstring ds = new_dstring();
636     generic_field_to_XML(iofile, ioformat, field, data, string_base, encode,
637 			 ds);
638     printf("%s", ds->string);
639     free(ds->string);
640     free(ds);
641 }
642 
643 extern int
644 add_single_value_as_XML(field_type, field_size, field_offset, iofile,
645 			data, string_base, byte_reversal, float_format,
646 			encode, ds)
647 char *field_type;
648 int field_size;
649 int field_offset;
650 IOFile iofile;
651 void *data;
652 void *string_base;
653 int byte_reversal;
654 int float_format;
655 int encode;
656 ffs_dstring ds;
657 {
658     IOgetFieldStruct descr;  /* OK */
659     char str[64];
660     descr.offset = field_offset;
661     descr.size = field_size;
662     descr.data_type = str_to_data_type(field_type);
663     descr.byte_swap = byte_reversal;
664     descr.src_float_format = float_format;
665     descr.target_float_format = ffs_my_float_format;
666 
667     str[0] = 0;
668     if (descr.data_type == integer_type) {
669 	if (field_size <= sizeof(long)) {
670 	    long tmp = get_IOlong(&descr, data);
671 	    sprintf(str, "%ld", tmp);
672 	} else if (field_size == 2 * sizeof(long) && field_size == 8) {
673 	    unsigned long low_long;
674 	    long high_long;
675 	    get_IOlong8(&descr, data, &low_long, &high_long);
676 	    if (high_long == 0) {
677 		sprintf(str, "%ld ", low_long);
678 	    } else {
679 		sprintf(str, "0x%lx%08lx ", high_long, low_long);
680 	    }
681 	} else if (field_size > sizeof(long)) {
682 	    sprintf(str, "<scalar type=\"long\" />");
683 	} else {
684 	    sprintf(str, "<scalar type=\"int\" size=\"%d\" />", field_size);
685 	}
686     } else if (descr.data_type == unsigned_type) {
687 	if (field_size <= sizeof(unsigned long)) {
688 	    unsigned long tmp = get_IOulong(&descr, data);
689 	    sprintf(str, "%lu ", tmp);
690 	} else if (field_size == 2 * sizeof(long) && field_size == 8) {
691 	    unsigned long low_long, high_long;
692 	    get_IOulong8(&descr, data, &low_long, &high_long);
693 	    if (high_long == 0) {
694 		sprintf(str, "%lu ", low_long);
695 	    } else {
696 		sprintf(str, "0x%lx%08lx ", high_long, low_long);
697 	    }
698 	} else if (field_size > sizeof(long)) {
699 	    sprintf(str, "<scalar type=\"unsignedLong\" />");
700 	} else {
701 	    sprintf(str, "<scalar type=\"unsignedInt\" size=\"%d\" />", field_size);
702 	}
703     } else if (descr.data_type == enumeration_type) {
704 	sprintf(str, "%u ", *(int *) ((char *) data + field_offset));
705     } else if (descr.data_type == boolean_type) {
706 	if (*(int *) ((char *) data + field_offset) == 0) {
707 	    strcpy(str, "false ");
708 	} else {
709 	    strcpy(str, "true ");
710 	}
711     } else if (descr.data_type == float_type) {
712 	if (field_size == sizeof(float)) {
713 	    float tmp = get_IOfloat(&descr, data);
714 	    sprintf(str, "%g ", tmp);
715 	} else if (field_size == sizeof(double)) {
716 	    double tmp = get_IOdouble(&descr, data);
717 	    sprintf(str, "%g ", tmp);
718 #if SIZEOF_LONG_DOUBLE != 0 && SIZEOF_LONG_DOUBLE != SIZEOF_DOUBLE
719 	} else if (field_size == sizeof(long double)) {
720 	    long double tmp;
721 	    memcpy(&tmp, (float *) ((char *) data + field_offset),
722 		   sizeof(double));
723 	    sprintf(str, "%Lg ", tmp);
724 #endif
725 	} else {
726 	    if (field_size < sizeof(float)) {
727 		sprintf(str, "<scalar type=\"small-float\" />");
728 	    } else if (field_size > sizeof(double)) {
729 		sprintf(str, "<scalar type=\"big-float\" />");
730 	    } else {
731 		sprintf(str, "<scalar type=\"float\" size=\"%u\" />", field_size);
732 	    }
733 	}
734     } else if (descr.data_type == char_type) {
735 	sprintf(str, "%c ", *(char *) ((char *) data + field_offset));
736     } else if (descr.data_type == string_type) {
737 	char *tmp_str = (char *) get_IOaddr(&descr, data, string_base, encode);
738 	if (tmp_str != 0) {
739 	    dcatstr(ds, tmp_str);
740 	    return 1;
741 	}
742     } else {
743 	return 0;
744     }
745     dcatstr(ds, str);
746     return 1;
747 }
748 
749 static void
add_value_as_XML(field_type,field_size,field_offset,iofile,data,string_base,byte_reversal,float_format,encode,in_array,ds)750 add_value_as_XML(field_type, field_size, field_offset, iofile, data,
751 		  string_base, byte_reversal, float_format, encode,
752 		 in_array, ds)
753 char *field_type;
754 int field_size;
755 int field_offset;
756 IOFile iofile;
757 void *data;
758 void *string_base;
759 int byte_reversal;
760 int float_format;
761 int encode;
762 int in_array;
763 ffs_dstring ds;
764 {
765     IOFormat ioformat;
766     if (add_single_value_as_XML(field_type, field_size, field_offset,
767 				iofile, data, string_base, byte_reversal,
768 				float_format, encode, ds)) {
769 	/* nothing */
770     } else {
771 	char *typ = base_data_type(field_type);
772 	if ((ioformat = get_IOformat_by_name(iofile, typ)) != NULL) {
773 	    int index;
774 	    if (in_array) {
775 		dcatstr(ds, "<");
776 		dcatstr(ds, ioformat->body->format_name);
777 		dcatstr(ds, ">\n");
778 	    } else {
779 		dcatstr(ds, "\n");
780 	    }
781 	    for (index = 0; index < ioformat->body->field_count; index++) {
782 		generic_field_to_XML(iofile, ioformat, index,
783 				     (void *) ((char *) data + field_offset),
784 				     string_base, encode, ds);
785 	    }
786 	    if (in_array) {
787 		dcatstr(ds, "</");
788 		dcatstr(ds, ioformat->body->format_name);
789 		dcatstr(ds, ">\n");
790 	    }
791 	} else {
792 	    printf("<scalar type=\"unknown\" />\n");
793 	}
794 	free(typ);
795     }
796 }
797 
798 static void
generic_field_to_XML(iofile,ioformat,field,data,string_base,encode,ds)799 generic_field_to_XML(iofile, ioformat, field, data, string_base, encode, ds)
800 IOFile iofile;
801 IOFormat ioformat;
802 int field;
803 void *data;
804 void *string_base;
805 int encode;
806 ffs_dstring ds;
807 {
808     IOFieldList iofield = &ioformat->body->field_list[field];
809     IOVarInfoList iovar = &ioformat->body->var_list[field];
810     int field_offset = iofield->field_offset;
811     int field_size = iofield->field_size;
812     const char *field_type = iofield->field_type;
813     int byte_reversal = ioformat->body->byte_reversal;
814     int float_format = ioformat->body->float_format;
815     char *left_paren = NULL;
816 
817     if (encode == 0) byte_reversal = 0;
818 
819     dcatstr(ds, "<");
820     dcatstr(ds, (char*)iofield->field_name);
821     dcatstr(ds, ">");
822     if ((left_paren = strchr(field_type, '[')) == NULL) {
823 	add_value_as_XML(field_type, field_size, field_offset, iofile, data,
824 			 string_base, byte_reversal, float_format,
825 			 encode, 0, ds);
826     } else if (strchr(left_paren + 1, '[') == NULL) {
827 	/* single dimen array */
828 	long dimension = 0;
829 	char sub_type[64];
830 	int sub_field_size;
831 	int offset = iofield->field_offset;
832 	dcatstr(ds, "\n");
833 	*left_paren = 0;
834 	strcpy(sub_type, field_type);
835 	*left_paren = '[';
836 	dimension = strtol(left_paren + 1, NULL, 10);
837 
838 	if ((dimension == LONG_MIN) || (dimension == LONG_MAX) ||
839 	    (dimension == 0)) {
840 	    if (iovar->var_array != TRUE) {
841 		fprintf(stderr, "Couldn't parse array size in \"%s\"\n",
842 			field_type);
843 		return;
844 	    } else {
845 		IOgetFieldStruct descr;  /* OK */
846 		long tmp_offset;
847 		descr.offset = iofield->field_offset;
848 		descr.size = ioformat->body->pointer_size;
849 		descr.data_type = integer_type;
850 		descr.byte_swap = byte_reversal;
851 
852 		dimension = get_IOlong(iovar->dimens[0].control_field, data);
853 
854 		tmp_offset = get_IOlong(&descr, data);
855 		if (encode) {
856 		    data = (char *) string_base + tmp_offset;
857 		} else {
858 		    data = (void *) tmp_offset;
859 		}
860 		offset = 0;
861 	    }
862 	    sub_field_size = iofield->field_size;
863 	} else {
864 	    /* normal internal array */
865 	    if (ioformat->body->IOversion <= 3) {
866 		sub_field_size = iofield->field_size / dimension;
867 	    } else {
868 		sub_field_size = iofield->field_size;
869 	    }
870 	}
871 	for (; dimension > 0; dimension--) {
872 	    add_value_as_XML(sub_type, sub_field_size, offset, iofile, data,
873 			     string_base, byte_reversal, float_format,
874 			     encode, 1, ds);
875 	    offset += sub_field_size;
876 	}
877     } else {
878 	/* double dimen array */
879 	long dimension1 = 0;
880 	long dimension2 = 0;
881 	char *temp_ptr;
882 	char sub_type[64];
883 	int sub_field_size, offset = iofield->field_offset;
884 	dcatstr(ds, "\n");
885 	*left_paren = 0;
886 	strcpy(sub_type, field_type);
887 	dimension1 = strtol(left_paren + 1, &temp_ptr, 10);
888 	dimension2 = strtol(temp_ptr + 2, &temp_ptr, 10);
889 
890 	if ((dimension2 == LONG_MIN) || (dimension2 == LONG_MAX) ||
891 	    (dimension2 == 0) || (dimension1 == 0)) {
892 	    *left_paren = '[';
893 	    fprintf(stderr, "Couldn't parse array size in \"%s\"\n",
894 		    field_type);
895 	    return;
896 	}
897 	*left_paren = '[';
898 	if (ioformat->body->IOversion <= 3) {
899 	    sub_field_size = iofield->field_size / (dimension1 * dimension2);
900 	} else {
901 	    sub_field_size = iofield->field_size;
902 	}
903 	for (; dimension2 > 0; dimension2--) {
904 	    int i = 0;
905 	    for (; i < dimension1; i++) {
906 		add_value_as_XML(sub_type, sub_field_size, offset, iofile,
907 				 data, string_base, byte_reversal,
908 				 float_format, encode, 1, ds);
909 		offset += sub_field_size;
910 	    }
911 	}
912     }
913 
914     dcatstr(ds, "</");
915     dcatstr(ds, (char*)iofield->field_name);
916     dcatstr(ds, ">\n");
917 }
918 
919