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