1 
2 #include "config.h"
3 
4 #ifndef MODULE
5 #ifdef HAVE_UNISTD_H
6 #include <unistd.h>
7 #endif
8 #ifdef HAVE_MALLOC_H
9 #include <malloc.h>
10 #endif
11 #ifdef HAVE_STRING_H
12 #include <string.h>
13 #endif
14 #include <sys/types.h>
15 #ifdef HAVE_NETINET_IN_H
16 #include <netinet/in.h>
17 #endif
18 #ifdef HAVE_WINDOWS_H
19 #include <winsock.h>
20 #endif
21 #include <ctype.h>
22 #include <time.h>
23 #ifdef HAVE_SYS_UIO_H
24 #include <sys/uio.h>
25 #define HAVE_IOVEC_DEFINE
26 #endif
27 #include <stdlib.h>
28 #ifdef HAVE_MEMORY_H
29 #include <memory.h>
30 #endif
31 #ifdef HAVE_NETDB_H
32 #include <netdb.h>
33 #endif
34 #include <stdio.h>
35 #include <sys/types.h>
36 #include <limits.h>
37 #include <strings.h>
38 #else
39 #include "kernel/pbio_kernel.h"
40 #include "kernel/kpbio.h"
41 #include "kernel/library.h"
42 #endif
43 
44 #include "assert.h"
45 #include "fm.h"
46 #include "fm_internal.h"
47 
48 static int server_register_format(FMContext fmc, FMFormat fmformat);
49 static int self_server_register_format(FMContext fmc,
50 					     FMFormat fmformat);
51 
52 static void byte_swap(char *data, int size);
53 static FMFormat server_get_format(FMContext iocontext, void *buffer);
54 static char *stringify_field_type(const char *type,
55 					FMFormat base_format,
56 					char *buffer, int size);
57 static int is_self_server(FMContext fmc);
58 static void expand_FMContext(FMContext fmc);
59 static int IOget_array_size_dimen(const char *str, FMFieldList fields,
60 				  int dimen, int *control_field);
61 static int field_type_eq(const char *str1, const char *str2);
62 
63 /*
64  * this reference to establish_server_connection is a function pointer
65  * rather than an extern so that the server_acts.o file is not loaded
66  * unless create_IOcontext() (which is also in that file) appears in
67  * the user program.  This avoids requiring the user to always link
68  * with -lnsl, -lsocket, etc when he might not otherwise need to.
69  */
70 int (*establish_server_connection_ptr)(FMContext fmc, action_t action);
71 
72 FMfloat_format fm_my_float_format = Format_Unknown;
73 /*
74  * fm_reverse_float_formats identifies for each format what,
75  * if any, format is its byte-swapped reverse.
76 */
77 FMfloat_format fm_reverse_float_formats[] = {
78     Format_Unknown, /* no format complements unknown */
79     Format_IEEE_754_littleendian, /* littleendian complements bigendian */
80     Format_IEEE_754_bigendian, /* bigendian complements littleendian */
81     Format_Unknown /* no exact opposite for mixed-endian (ARM) */
82 };
83 
84 static unsigned char IEEE_754_4_bigendian[] =
85   {0x3c, 0x00, 0x00, 0x00};
86 static unsigned char IEEE_754_4_littleendian[] =
87   {0x00, 0x00, 0x00, 0x3c};
88 static unsigned char IEEE_754_8_bigendian[] =
89   {0x3f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
90 static unsigned char IEEE_754_8_littleendian[] =
91   {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f};
92 static unsigned char IEEE_754_8_mixedendian[] =
93   {0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00};
94 static unsigned char IEEE_754_16_bigendian[] =
95   {0x3f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
96    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
97 static unsigned char IEEE_754_16_littleendian[] =
98   {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
99    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x3f};
100 static unsigned char IEEE_754_16_mixedendian[] =
101   {0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0x00, 0x00,
102    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
103 
104 static char *float_format_str[] = {
105     "Unknown float format",
106     "IEEE 754 float (bigendian)",
107     "IEEE 754 float (littleendian)",
108     "IEEE 754 float (mixedendian)"};
109 
110 static FMfloat_format
infer_float_format(char * float_magic,int object_len)111 infer_float_format(char *float_magic, int object_len)
112 {
113     switch (object_len) {
114     case 4:
115 	if (memcmp(float_magic, &IEEE_754_4_bigendian[0], 4) == 0) {
116 	    return Format_IEEE_754_bigendian;
117 	} else if (memcmp(float_magic, &IEEE_754_4_littleendian[0], 4) == 0) {
118 	    return Format_IEEE_754_littleendian;
119 	}
120 	break;
121     case 8:
122 	if (memcmp(float_magic, &IEEE_754_8_bigendian[0], 8) == 0) {
123 	    return Format_IEEE_754_bigendian;
124 	} else if (memcmp(float_magic, &IEEE_754_8_littleendian[0], 8) == 0) {
125 	    return Format_IEEE_754_littleendian;
126 	} else if (memcmp(float_magic, &IEEE_754_8_mixedendian[0], 8) == 0) {
127 	    return Format_IEEE_754_mixedendian;
128 	}
129 	break;
130     case 16:
131 	if (memcmp(float_magic, &IEEE_754_16_bigendian[0], 16) == 0) {
132 	    return Format_IEEE_754_bigendian;
133 	} else if (memcmp(float_magic, &IEEE_754_16_littleendian[0], 16) ==0){
134 	    return Format_IEEE_754_littleendian;
135 	} else if (memcmp(float_magic, &IEEE_754_16_mixedendian[0], 16) == 0){
136 	    return Format_IEEE_754_mixedendian;
137 	}
138 	break;
139     }
140     return Format_Unknown;
141 }
142 
143 static void
init_float_formats()144 init_float_formats()
145 {
146     static int done = 0;
147     if (!done) {
148 	double d = MAGIC_FLOAT;
149 	fm_my_float_format = infer_float_format((char*)&d, sizeof(d));
150 	switch (fm_my_float_format) {
151 	case Format_IEEE_754_bigendian:
152 	case Format_IEEE_754_littleendian:
153 	case Format_IEEE_754_mixedendian:
154 	    break;
155 	case Format_Unknown:
156 	    fprintf(stderr, "Warning, unknown local floating point format\n");
157 	    break;
158 	}
159 	done++;
160     }
161 }
162 
163 
164 extern
165 FMContext
new_FMContext()166 new_FMContext()
167 {
168     FMContext c;
169     init_float_formats();
170     c = (FMContext) malloc((size_t) sizeof(FMContextStruct));
171     memset(c, 0, sizeof(FMContextStruct));
172     c->ref_count = 1;
173     c->format_list_size = 0;
174     c->format_list = NULL;
175     c->reg_format_count = 0;
176     c->byte_reversal = 0;
177     c->native_float_format = fm_my_float_format;
178     c->native_column_major_arrays = 0;
179     c->native_pointer_size = sizeof(char*);
180     c->errno_val = 0;
181     c->result = NULL;
182 
183     c->self_server = 0;
184     c->self_server_fallback = 0;
185     c->server_fd = (char *) -1;
186     c->server_pid = 0;
187     c->server_byte_reversal = 0;
188     c->master_context = NULL;
189 
190     return (c);
191 }
192 
193 extern
194 FMContext
create_local_FMcontext()195 create_local_FMcontext()
196 {
197     FMContext fmc = new_FMContext();
198     fmc->self_server = 1;
199     return fmc;
200 }
201 
202 static void
free_FMformat(body)203 free_FMformat(body)
204 FMFormat body;
205 {
206     int i;
207     body->ref_count--;
208     if (body->ref_count != 0)
209 	return;
210     free(body->format_name);
211     free(body->master_struct_list);  /* not subelements */
212     for (i = 0; i < body->field_count; i++) {
213 
214 	free((char*)body->field_list[i].field_name);
215 	free((char*)body->field_list[i].field_type);
216 	if (body->var_list != NULL) {
217 	    if (body->var_list[i].dimens != NULL) {
218 /*		int j;
219 		for (j = 0; j < body->var_list[i].dimen_count; j++) {
220 		    if (body->var_list[i].dimens[j].control_field_index != -1)
221 			free(body->var_list[i].dimens[j].control_field);
222 		}*/
223 		free(body->var_list[i].dimens);
224 	    }
225 	    if (body->var_list[i].type_desc.next != NULL) {
226 		FMTypeDesc *tmp = body->var_list[i].type_desc.next;
227 		while (tmp != NULL) {
228 		    FMTypeDesc *next = tmp->next;
229 		    free(tmp);
230 		    tmp = next;
231 		}
232 	    }
233 	}
234     }
235     free(body->field_list);
236     free(body->var_list);
237     i = 0;
238     while (body->subformats && body->subformats[i]) {
239 	body->subformats[i]->subformats = NULL;
240 	free_FMformat(body->subformats[i++]);
241     }
242     free(body->subformats);
243     free(body->field_subformats);
244     if (body->server_format_rep != NULL)
245 	free(body->server_format_rep);
246     if (body->ffs_info)
247 	body->free_ffs_info(body->ffs_info);
248     if (body->server_ID.value != NULL)
249 	free(body->server_ID.value);
250     if (body->opt_info != NULL) {
251 	FMOptInfo *o = body->opt_info;
252 /*	while (o->info_type != -1) {
253 	    free(o->info_block);
254 	    o++;
255 	    }*/
256 	free(o);
257     }
258     if ((body->xml_out != NULL) && (body->xml_out != (void*)-1)) {
259 /*	free_XML_output_info(body->xml_out);*/
260     }
261     free(body);
262 }
263 
264 #if defined(__has_feature)
265 #if __has_feature(thread_sanitizer)
266 #define NO_SANITIZE_THREAD __attribute__((no_sanitize("thread")))
267 #endif
268 #endif
269 
270 #ifndef NO_SANITIZE_THREAD
271 #define NO_SANITIZE_THREAD
272 #endif
273 
274 static int format_server_verbose = -1;
275 static int NO_SANITIZE_THREAD
get_format_server_verbose()276 get_format_server_verbose()
277 {
278     if (format_server_verbose == -1) {
279 	if (getenv("FORMAT_SERVER_VERBOSE") == NULL) {
280 	    format_server_verbose = 0;
281 	} else {
282 	    format_server_verbose = 1;
283 	}
284     }
285     return format_server_verbose;
286 }
287 
288 extern void dump_FMFormat(FMFormat fmformat);
289 unsigned char ID_length[] = {8, 10, 12};
290 
291 extern int
FMformatID_len(char * buffer)292 FMformatID_len(char *buffer)
293 {
294     return ID_length[version_of_format_ID(buffer)];
295 }
296 
297 extern void
298 add_opt_info_FMformat(format, typ, len, block)
299 FMFormat format;
300 int typ;
301 int len;
302 void *block;
303 {
304     int count = 0;
305     if (format->opt_info == NULL) {
306 	format->opt_info = malloc(2*sizeof(FMOptInfo));
307     } else {
308 	while(format->opt_info[count].info_type != -1) count++;
309 	format->opt_info = realloc(format->opt_info,
310 					 (count + 2) *sizeof(FMOptInfo));
311     }
312     format->opt_info[count].info_type = typ;
313     format->opt_info[count].info_len = len;
314     format->opt_info[count].info_block = (char*)block;
315     format->opt_info[count + 1].info_type = -1;
316 }
317 
318 #ifdef NOT_DEF
319 static FMFormat
copy_fmformat_to_fmc(format,fmc)320 copy_fmformat_to_fmc(format, fmc)
321 FMFormat format;
322 FMContext fmc;
323 {
324     FMFormat new_format;
325     int i;
326 
327     for (i = 0; i < fmc->reg_format_count; i++) {
328 	if (fmc->format_list[i] == format) {
329 	    if (get_format_server_verbose()) {
330 		printf("Copy, format %lx exists in context %lx as format %lx\n",
331 		       (long)format, (long)fmc, (long)fmc->format_list[i]);
332 	    }
333 	    return fmc->format_list[i];
334 	}
335     }
336     new_format = malloc(sizeof(struct _FMFormatBody));
337     if (get_format_server_verbose()) {
338 	printf("Copy, entering format %lx into context %lx as new format %lx\n",
339 	       (long) format, (long) fmc, (long) new_format);
340     }
341     new_format->context = fmc;
342     new_format = format;
343     format->ref_count++;
344 
345     if (fmc->reg_format_count == fmc->format_list_size) {
346 	expand_FMContext(fmc);
347     }
348     fmc->format_list[fmc->reg_format_count++] = new_format;
349 
350     return new_format;
351 }
352 #endif
353 
354 extern FMcompat_formats
FMget_compat_formats(FMFormat fmformat)355 FMget_compat_formats(FMFormat fmformat)
356 {
357     FMcompat_formats ret;
358     int count = 0;
359     int i = 0;
360     /*printf("%s:%d In funtion %s\n", __FILE__, __LINE__, __FUNCTION__);*/
361     if(fmformat->opt_info)
362 	ret = malloc(sizeof(struct compat_formats));
363     else
364 	return NULL;
365     while (fmformat->opt_info[i].info_type != 0) {
366 	if (fmformat->opt_info[i].info_type == COMPAT_OPT_INFO) {
367 	    char *buffer = (void*)fmformat->opt_info[i].info_block;
368 	    int fid_length = ID_length[version_of_format_ID(buffer)];
369 	    ret[count].prior_format =
370 		FMformat_from_ID(fmformat->context, buffer);
371 	    ret[count].xform_code = buffer + fid_length;
372 	    count++;
373 	    ret = realloc(ret, sizeof(struct compat_formats) * (count + 1));
374 	}
375 	i++;
376     }
377     if (count == 0) {
378 	free(ret);
379 	ret = NULL;
380     } else {
381 	ret[count].prior_format = NULL;
382 	ret[count].xform_code = NULL;
383     }
384     return ret;
385 }
386 
387 FMFormat
get_local_format_IOcontext(iocontext,buffer)388 get_local_format_IOcontext(iocontext, buffer)
389 FMContext iocontext;
390 void *buffer;
391 {
392     FMContext fmc = (FMContext) iocontext;
393     int i;
394     if (get_format_server_verbose()) {
395 	printf("Get Format searching in context %lx for format ",
396 	       (long)iocontext);
397 	print_server_ID(buffer);
398 	printf("\n");
399     }
400     switch (version_of_format_ID(buffer)) {
401     case 1:
402     {
403 	INT2 format_id = ((version_1_format_ID*) buffer)->format_identifier;
404 	/* shortcut on comparisons.  check likely difference first */
405 	for (i = fmc->reg_format_count - 1; i >= 0; i--) {
406 	    version_1_format_ID* id = (version_1_format_ID*)
407 		fmc->format_list[i]->server_ID.value;
408 	    if (format_id != id->format_identifier) continue;
409 	    if (memcmp(buffer, fmc->format_list[i]->server_ID.value,
410 		       fmc->format_list[i]->server_ID.length) == 0) {
411 		return fmc->format_list[i];
412 	    }
413 	}
414 	break;
415     }
416     case 2:
417     {
418 	UINT2 rep_len = ((version_2_format_ID*) buffer)->rep_len;
419 	/* shortcut on comparisons.  check likely difference first */
420 	for (i = fmc->reg_format_count - 1; i >= 0; i--) {
421 	    version_2_format_ID* id = (version_2_format_ID*)
422 		fmc->format_list[i]->server_ID.value;
423 	    if (rep_len != id->rep_len) continue;
424 	    if (memcmp(buffer, fmc->format_list[i]->server_ID.value,
425 		       fmc->format_list[i]->server_ID.length) == 0) {
426 		return fmc->format_list[i];
427 	    }
428 	}
429 	break;
430     }
431     case 3:
432     {
433 	UINT4 rep_len = ((version_3_format_ID*) buffer)->rep_len;
434 	rep_len += (((version_3_format_ID*) buffer)->top_byte_rep_len) << 16;
435 	/* shortcut on comparisons.  check likely difference first */
436 	for (i = fmc->reg_format_count - 1; i >= 0; i--) {
437 	    version_3_format_ID* id = (version_3_format_ID*)
438 		fmc->format_list[i]->server_ID.value;
439 	    if (rep_len != id->rep_len) continue;
440 	    if (memcmp(buffer, fmc->format_list[i]->server_ID.value,
441 		       fmc->format_list[i]->server_ID.length) == 0) {
442 		return fmc->format_list[i];
443 	    }
444 	}
445 	break;
446     }
447     default:
448 	for (i = fmc->reg_format_count - 1; i >= 0; i--) {
449 	    if (memcmp(buffer, fmc->format_list[i]->server_ID.value,
450 		       fmc->format_list[i]->server_ID.length) == 0) {
451 		return fmc->format_list[i];
452 	    }
453 	}
454     }
455     if (fmc->master_context != NULL) {
456 	return get_local_format_IOcontext(fmc->master_context, buffer);
457     }
458     return NULL;
459 }
460 
461 FMFormat
FMformat_from_ID(iocontext,buffer)462 FMformat_from_ID(iocontext, buffer)
463 FMContext iocontext;
464 char *buffer;
465 {
466     FMContext fmc = (FMContext) iocontext;
467     FMFormat new_format;
468     int i;
469 
470     if (get_format_server_verbose() && (memcmp(buffer, "\0\0\0\0\0\0\0\0", 6) == 0)) {
471 	printf("   ->>>>   Null id in FMformat_from_ID\n");
472     }
473 
474     switch (version_of_format_ID(buffer)) {
475     case 1:
476     {
477 	unsigned INT2 format_id = ((version_1_format_ID*) buffer)->format_identifier;
478 	/* shortcut on comparisons.  check likely difference first */
479 	for (i = fmc->reg_format_count - 1; i >= 0; i--) {
480 	    version_1_format_ID* id = (version_1_format_ID*)
481 		fmc->format_list[i]->server_ID.value;
482 	    if (format_id != id->format_identifier) continue;
483 	    if (memcmp(buffer, fmc->format_list[i]->server_ID.value,
484 		       fmc->format_list[i]->server_ID.length) == 0) {
485 		return fmc->format_list[i];
486 	    }
487 	}
488 	break;
489     }
490     case 2:
491     {
492 	UINT2 rep_len = ((version_2_format_ID*) buffer)->rep_len;
493 	/* shortcut on comparisons.  check likely difference first */
494 	for (i = fmc->reg_format_count - 1; i >= 0; i--) {
495 	    version_2_format_ID* id = (version_2_format_ID*)
496 		fmc->format_list[i]->server_ID.value;
497 	    if (rep_len != (UINT2) id->rep_len) continue;
498 	    if (memcmp(buffer, fmc->format_list[i]->server_ID.value,
499 		       fmc->format_list[i]->server_ID.length) == 0) {
500 		return fmc->format_list[i];
501 	    }
502 	}
503 	break;
504     }
505     case 3:
506     {
507 	UINT4 rep_len = ((version_3_format_ID*) buffer)->rep_len;
508 	rep_len += (((version_3_format_ID*) buffer)->top_byte_rep_len) << 16;
509 	/* shortcut on comparisons.  check likely difference first */
510 	for (i = fmc->reg_format_count - 1; i >= 0; i--) {
511 	    version_3_format_ID* id = (version_3_format_ID*)
512 		fmc->format_list[i]->server_ID.value;
513 	    if (rep_len != id->rep_len) continue;
514 	    if (memcmp(buffer, fmc->format_list[i]->server_ID.value,
515 		       fmc->format_list[i]->server_ID.length) == 0) {
516 		return fmc->format_list[i];
517 	    }
518 	}
519 	break;
520     }
521     default:
522 	for (i = fmc->reg_format_count - 1; i >= 0; i--) {
523 	    if (memcmp(buffer, fmc->format_list[i]->server_ID.value,
524 		       fmc->format_list[i]->server_ID.length) == 0) {
525 		return fmc->format_list[i];
526 	    }
527 	}
528     }
529     if (is_self_server(fmc)) {
530 	return NULL;
531     } else {
532 	new_format = server_get_format(iocontext, buffer);
533     }
534     if (get_format_server_verbose()) {
535 	printf("Read format from format server  %lx\n",
536 	       (long)new_format);
537 	if (new_format != NULL) {
538 	    dump_FMFormat(new_format);
539 	} else {
540 	    printf("Format unknown.  Request was: ");
541 	    print_server_ID((void*)buffer);
542 	    printf("\n\tcontext was %lx\n", (long)iocontext);
543 	}
544     }
545     return new_format;
546 }
547 
548 char **
get_subformat_names(field_list)549 get_subformat_names(field_list)
550 FMFieldList field_list;
551 {
552     int name_count = 0;
553     int field = 0;
554     char **name_list = malloc(sizeof(char *));
555     while (field_list[field].field_name != NULL) {
556 	char *base_type = base_data_type(field_list[field].field_type);
557 	if (FMstr_to_data_type(base_type) == unknown_type) {
558 	    name_list = realloc(name_list, sizeof(char *) * (name_count + 1));
559 	    name_list[name_count++] = base_type;
560 	} else {
561 	    free(base_type);
562 	}
563 	field++;
564     }
565     name_list = realloc(name_list, sizeof(char *) * (name_count + 1));
566     name_list[name_count] = NULL;
567     if (name_count == 0) {
568 	free(name_list);
569 	name_list = NULL;
570     }
571     return name_list;
572 }
573 
574 static
575 void
get_subformats_context(fmformat,format_list_p,format_count_p,stack_p)576 get_subformats_context(fmformat, format_list_p, format_count_p, stack_p)
577 FMFormat fmformat;
578 FMFormat **format_list_p;
579 int *format_count_p;
580 FMFormat **stack_p;
581 {
582     int field;
583     int stack_depth = 0;
584     FMFormat *stack = *stack_p;
585     while(stack[stack_depth] != NULL) stack_depth++;
586     *stack_p = stack = realloc(stack, sizeof(stack[0]) * (stack_depth + 2));
587     stack[stack_depth] = fmformat;
588     stack[stack_depth+1] = NULL;
589     for (field = 0; field < fmformat->field_count; field++) {
590 	FMFormat subformat = fmformat->field_subformats[field];
591 	if (subformat != NULL) {
592 	    int i;
593 	    int j = 0;
594 	    while((stack[j] != subformat) && (stack[j] != NULL)) j++;
595 	    if (stack[j] != subformat) {
596 		/* if we're not already getting this subformat, recurse */
597 		get_subformats_context(subformat, format_list_p, format_count_p, stack_p);
598 		/* stack might have been realloc'd */
599 		stack = *stack_p;
600 	    }
601 	    *format_list_p = realloc(*format_list_p,
602 			       sizeof(FMFormat) * (*format_count_p + 2));
603 	    for (i=0; i< *format_count_p; i++) {
604 		if ((*format_list_p)[i] == subformat) {
605 		    /* don't add it if it's already there */
606 		    subformat = NULL;
607 		}
608 	    }
609 	    if (subformat != NULL) {
610 		(*format_list_p)[(*format_count_p)++] = subformat;
611 	    }
612 	}
613     }
614 }
615 
616 FMFormat *
get_subformats_IOformat(fmformat)617 get_subformats_IOformat(fmformat)
618 FMFormat fmformat;
619 {
620     int format_count = 0;
621     FMFormat *format_list = malloc(sizeof(FMFormat));
622     FMFormat *stack = malloc(sizeof(FMFormat)*2);
623     stack[0] = NULL;
624     get_subformats_context(fmformat, &format_list, &format_count, &stack);
625     free(stack);
626     format_list = realloc(format_list, sizeof(FMFormat) * (format_count + 2));
627     format_list[format_count] = fmformat;
628     format_list[format_count + 1] = NULL;
629     return format_list;
630 }
631 
632 int
FMformat_index(FMFormat f)633 FMformat_index(FMFormat f)
634 {
635     return f->format_index;
636 }
637 
638 FMFormat
FMformat_by_index(fmc,index)639 FMformat_by_index(fmc, index)
640 FMContext fmc;
641 int index;
642 {
643     if (index < fmc->reg_format_count) {
644 	return fmc->format_list[index];
645     } else {
646 	return NULL;
647     }
648 }
649 
650 
651 FMFormat
new_FMFormat()652 new_FMFormat()
653 {
654     FMFormat fmformat;
655     fmformat = (FMFormat) malloc(sizeof(FMFormatBody));
656     fmformat->field_subformats = NULL;
657     fmformat->superformat = NULL;
658     fmformat->subformats = NULL;
659     fmformat->ref_count = 1;
660     fmformat->master_struct_list = NULL;
661     fmformat->format_name = NULL;
662     fmformat->byte_reversal = 0;
663     fmformat->alignment = 0;
664     fmformat->column_major_arrays = 0; /* by default, C mode */
665     fmformat->recursive = 0;
666     fmformat->float_format = fm_my_float_format;
667     fmformat->pointer_size = 0;
668     fmformat->IOversion = -1;
669     fmformat->field_list = NULL;
670     fmformat->var_list = NULL;
671     fmformat->server_format_rep = NULL;
672     fmformat->server_ID.length = 0;
673     fmformat->server_ID.value = NULL;
674     fmformat->opt_info = NULL;
675     fmformat->xml_out = NULL;
676     fmformat->ffs_info = NULL;
677     fmformat->free_ffs_info = NULL;
678     return (fmformat);
679 }
680 
681 extern
682 void
683 expand_FMContext(fmc)
684 FMContext fmc;
685 {
686     int new_count = fmc->format_list_size + 10;
687     int new_size = sizeof(FMFormat) * (new_count);
688     int i;
689 
690     if (fmc->format_list != NULL) {
691 	fmc->format_list = (FMFormat *)
692 	    realloc((void *) fmc->format_list, (unsigned) new_size);
693     } else {
694 	fmc->format_list = (FMFormat *) malloc((unsigned) new_size);
695     }
696     fmc->format_list_size = new_count;
697     for (i = fmc->reg_format_count; i < fmc->format_list_size; i++) {
698 	fmc->format_list[i] = NULL;
699     }
700 }
701 
702 static int
is_var_array_field(FMFieldList field_list,int field)703 is_var_array_field(FMFieldList field_list, int field)
704 {
705     int done = 0;
706     int ret = 0;
707     int dimen_count = 0;
708     int control_val;
709     while (!done) {
710 	int static_size = IOget_array_size_dimen(field_list[field].field_type,
711 						 field_list, dimen_count,
712 						 &control_val);
713 	dimen_count++;
714 	if (static_size == 0) {
715 	    done++;
716 	    continue;
717 	}
718 	if ((static_size == -1) && (control_val == -1)) {
719 	    /* failed validation, errors already delivered */
720 	    return -1;
721 	}
722 	if (control_val != -1) {
723 	    /* dynamic array */
724 	    ret = 1;
725 	}
726     }
727     return ret;
728 }
729 
730 static FMTypeDesc *
new_FMTypeDesc()731 new_FMTypeDesc()
732 {
733     FMTypeDesc *tmp = malloc(sizeof(*tmp));
734     memset(tmp, 0, sizeof(*tmp));
735     return tmp;
736 }
737 
738 /*
739 	integer			an integer
740 	*integer		a pointer to an integer
741 	integer[35]		35 integers
742 	*integer[35]		a pointer to 35 integers
743 	*integer[35][10]	a pointer to
744 	*(integer[35])[10]	10 pointers to 35 integers
745 */
746 
747 char *FMTypeEnumString[] = {"pointer", "array", "string", "subformat", "simple"};
748 char *FMDatatypeString[] = {"unknown", "integer", "unsigned", "float", "char", "string", "enumeration",
749 			    "boolean"};
750 
751 static void
dump_FMTypeDesc(FMTypeDesc * l,int indent)752 dump_FMTypeDesc(FMTypeDesc *l, int indent)
753 {
754     printf("Type Enumeration is %s\n", FMTypeEnumString[l->type]);
755     printf("Data Type is %s\n", FMDatatypeString[l->data_type]);
756     if (l->pointer_recursive) printf("Data Type is recursively defined.\n");
757     printf("Field index %d, static size %d, control_field_index %d\n", l->field_index, l->static_size, l->control_field_index);
758     if (l->next) dump_FMTypeDesc(l->next, indent+1);
759 }
760 
761 
762 extern FMTypeDesc*
gen_FMTypeDesc(FMFieldList fl,int field,const char * typ)763 gen_FMTypeDesc(FMFieldList fl, int field, const char *typ)
764 {
765     char *first_open = strchr(typ, '(');
766     char *last_close = strrchr(typ, ')');
767     if ((first_open && !last_close) || (!first_open && last_close)) {
768 	fprintf(stderr, "Mismatched parenthesis in type spec \"%s\" .\n",
769 		fl[field].field_type);
770 	return NULL;
771     }
772     if (first_open) {
773 	FMTypeDesc *base, *root, *tmp;
774 	/* recurse */
775 	char *t = strdup(typ);
776 	char *first = strchr(t, '(');
777 	char *last = strrchr(t, ')');
778 	*last = 0;
779 	base = gen_FMTypeDesc(fl, field, first +1);
780 	while (first <= last) *(first++) = 'a';   /* wash it out */
781 	tmp = root = gen_FMTypeDesc(fl, field, t);
782 	while (tmp->next) tmp = tmp->next;
783 	*tmp = *base;   /* wipe out Simple */
784 	free(base);
785 	free(t);
786 	return root;
787     } else {
788 	int dimen_count = 0;
789 	FMTypeDesc *root = new_FMTypeDesc();
790 	FMTypeDesc *pointer_root = NULL;
791 	const char *tmp_typ;
792 	int var_array = 0;
793 	long junk;
794 	root->type = FMType_simple;
795 	root->next = NULL;
796 	root->field_index = field;
797 	root->data_type = FMarray_str_to_data_type(typ, &junk);
798 	while (isspace((int)*typ)) {	/* skip preceeding space */
799 	    typ++;
800 	}
801 	while (*typ == '*') {
802 	    FMTypeDesc *tmp = new_FMTypeDesc();
803 	    tmp->type = FMType_pointer;
804 	    tmp->field_index = field;
805 	    tmp->next = pointer_root;
806 	    pointer_root = tmp;
807 	    typ++;
808 	    while (isspace((int)*typ)) {	/* skip preceeding space */
809 		typ++;
810 	    }
811 	}
812 	/* now we've handled any pointer specs */
813 	if (strncmp(typ, "string", 6) == 0) {
814 	    if ((*(typ + 6) == 0) || (*(typ + 6) == '[') ||
815 		(isspace(*(typ+6)))) {
816 		root->type = FMType_string;
817 	    }
818 	}
819 	if (root->data_type == unknown_type) {
820 	    root->type = FMType_subformat;
821 	}
822 
823 	tmp_typ = typ;
824 	while ((tmp_typ = strchr(tmp_typ, '[')) != NULL) {
825 	    dimen_count++;
826 	    tmp_typ++;
827 	}
828 	dimen_count--;
829 	while(dimen_count >= 0) {
830 	    int control_val;
831 	    FMTypeDesc *tmp;
832 	    int static_size = IOget_array_size_dimen(typ, fl, dimen_count,
833 						     &control_val);
834 	    tmp = new_FMTypeDesc();
835 	    tmp->type = FMType_array;
836 	    tmp->field_index = field;
837 	    tmp->static_size = static_size;
838 	    if (static_size == -1) {
839 		tmp->static_size = 0;
840 		var_array = 1;
841 	    }
842 	    tmp->control_field_index = control_val;
843 	    tmp->next = root;
844 	    root = tmp;
845 	    dimen_count--;
846 	}
847 	if (var_array) {
848 	    FMTypeDesc *tmp = new_FMTypeDesc();
849 	    tmp->type = FMType_pointer;
850 	    tmp->next = root;
851 	    root = tmp;
852 	}
853 	if (pointer_root) {
854 	    FMTypeDesc *last_pointer = pointer_root;
855 	    while (last_pointer->next != NULL) {
856 		last_pointer = last_pointer->next;
857 	    }
858 	    last_pointer->next = root;
859 	    root = pointer_root;
860 	}
861 	return root;
862     }
863 }
864 
865 static FMTypeDesc *
gen_type_desc(FMFormat f,int field,const char * typ)866 gen_type_desc(FMFormat f, int field, const char *typ)
867 {
868     return gen_FMTypeDesc(f->field_list, field, typ);
869 }
870 
871 typedef struct {
872     char tmp;
873     void *p;
874 } *sp;
875 
876 typedef struct {
877     char tmp;
878     short s;
879 } *ss;
880 
881 typedef struct {
882     char tmp;
883     int i;
884 } *si;
885 
886 typedef struct {
887     char tmp;
888     long l;
889 } *sl;
890 
891 typedef struct {
892     char tmp;
893     float f;
894 } *sf;
895 
896 typedef struct {
897     char tmp;
898     double d;
899 } *sd;
900 
901 static int
type_alignment(fmformat,field)902 type_alignment(fmformat, field)
903 FMFormat fmformat;
904 int field;
905 {
906     FMVarInfoList var = &fmformat->var_list[field];
907     FMTypeDesc *t = &var->type_desc;
908     int size = fmformat->field_list[field].field_size;
909     while (t != NULL) {
910 	switch (t->type) {
911 	case FMType_pointer:
912 	case FMType_string:
913 	    return FMOffset(sp, p);
914 	case FMType_array:
915 	    t = t->next;
916 	    break;
917 	case FMType_subformat:
918 	    assert(fmformat->field_subformats[field]->alignment != 0);
919 	    return fmformat->field_subformats[field]->alignment;
920 	case FMType_simple:
921 	    switch(t->data_type) {
922 	    case integer_type: case unsigned_type:
923 	    case enumeration_type: case boolean_type: case char_type:
924 		if (size == -1) return -1;
925 		if (size == 1) return 1;
926 		if ((size == sizeof(short)) || (size < sizeof(int)))
927 		    return FMOffset(ss, s);
928 		if ((size < sizeof(int))  || (size < sizeof(long)))
929 		    return FMOffset(si, i);
930 		return FMOffset(sl, l);
931 		break;
932 	    case unknown_type: case string_type:
933 		assert(0);
934 	    case float_type:
935 		if (size < sizeof(float)) return size;
936 		if (size < sizeof(double)) return FMOffset(sf, f);
937 		return FMOffset(sd, d);
938 	    }
939 	    break;
940 	}
941     }
942     return -1;
943 }
944 
945 static int
determine_size(FMFormat top,int index,int field,int actual)946 determine_size(FMFormat top, int index, int field, int actual)
947 {
948     FMFormat fmformat = top->subformats[index];
949     FMVarInfoList var = &fmformat->var_list[field];
950     FMTypeDesc *t = &var->type_desc;
951     int size = fmformat->field_list[field].field_size;
952     int array_size = 1;
953     while (t != NULL) {
954 	switch (t->type) {
955 	case FMType_pointer:
956 	    if (actual) {
957 		size= sizeof(char*);
958 		return size * array_size;
959 	    }
960 	    break;
961 	case FMType_string:
962 	    size = sizeof(char*);
963 	    break;
964 	case FMType_array:
965 	    if (actual && (t->static_size > 0)) {
966 		/* FFS size is only size of element, actual size is total */
967 		array_size *= t->static_size;
968 	    }
969 	    break;
970 	case FMType_subformat: {
971 	    int i = 0;
972 	    FMFormat subformat = fmformat->field_subformats[field];
973 	    while (top->subformats[i] != subformat) i++;
974 	    size = top->master_struct_list[i].struct_size;
975 	    break;
976 	}
977 	case FMType_simple:
978 	    switch(t->data_type) {
979 	    case integer_type: case unsigned_type:
980 	    case enumeration_type: case boolean_type: case char_type:
981 		if (size <= 0) size = sizeof(int);
982 		break;
983 	    case unknown_type: case string_type:
984 		assert(0);
985 	    case float_type:
986 		if (size <= 0) size = sizeof(double);
987 		break;
988 	    }
989 	    break;
990 	}
991 	t = t->next;
992     }
993     return size * array_size;
994 }
995 
996 
997 static void
set_sizes_and_offsets(FMFormat top,int index,FMStructDescList structs)998 set_sizes_and_offsets(FMFormat top, int index, FMStructDescList structs)
999 {
1000     int offset = 0;
1001     int i, field_count = 0;
1002     FMFormat f;
1003     FMFieldList fl = structs[index].field_list;
1004     int bad_size = 0;
1005 
1006     f = top->subformats[index];
1007     while (structs[index].field_list[field_count].field_name != NULL) {
1008 	field_count++;
1009     }
1010     if (f->field_subformats == NULL) {
1011 	FMTypeDesc *desc;
1012 	f->field_subformats = malloc(sizeof(char*) * field_count);
1013 	memset(f->field_subformats, 0, sizeof(char*) * field_count);
1014 	f->field_list = structs[index].field_list;
1015 	f->var_list = malloc(sizeof(f->var_list[0]) * field_count);
1016 	memset(f->var_list, 0, sizeof(f->var_list[0]) * field_count);
1017 	i = 0;
1018 	while (fl[i].field_name != NULL) {
1019 	    desc = gen_type_desc(f, i, structs[index].field_list[i].field_type);
1020 	    f->var_list[i].type_desc = *desc;
1021 	    free(desc);
1022 	    i++;
1023 	}
1024     }
1025 
1026     i = 0;
1027     while (fl[i].field_name != NULL) {
1028 	FMTypeDesc *tmp;
1029 	int align_req, actual_size;
1030 	tmp = &f->var_list[i].type_desc;
1031 	while (tmp->next != NULL) tmp = tmp->next;
1032 	if (tmp->data_type == unknown_type) {
1033 
1034 	    int j = 0;
1035 	    char *base_type = base_data_type(structs[index].field_list[i].field_type);
1036 
1037 	    while(structs[j].format_name) {
1038 		if (strcmp(base_type, structs[j].format_name) == 0) {
1039 		    tmp->type = FMType_subformat;
1040 		    f->field_subformats[i] = top->subformats[j];
1041 		}
1042 		j++;
1043 	    }
1044 	    assert(tmp->type != FMType_simple);
1045 	    free(base_type);
1046 	}
1047 	align_req = type_alignment(f, i);
1048 
1049 	if (align_req > 0) {
1050 	    if (align_req > f->alignment) {
1051 		f->alignment = align_req;
1052 	    }
1053 	    offset = (offset + align_req - 1) & (-align_req);
1054 	    fl[i].field_offset = offset;
1055 	}
1056 	if (fl[i].field_size <= 0) {
1057 	    fl[i].field_size = determine_size(top, index, i, 0);
1058 	}
1059 	actual_size = determine_size(top, index, i, 1);
1060 	if (actual_size > 0) {
1061 	    offset += actual_size;
1062 	} else {
1063 	    offset++;
1064 	    bad_size++;
1065 	}
1066 	i++;
1067     }
1068     if ((bad_size == 0) && (f->alignment != -1)) {
1069 	int struct_size = offset;
1070 	if ((struct_size % f->alignment) != 0) {
1071 	    int pad = -struct_size & (f->alignment -1);  /*  only works if req_align is power of two */
1072 	    struct_size += pad;
1073 	}
1074 	structs[index].struct_size = struct_size;
1075     }
1076 }
1077 
1078 extern void
FMlocalize_structs(FMStructDescList list)1079 FMlocalize_structs(FMStructDescList list)
1080 {
1081     int i, j, struct_count = 0;
1082     FMFormat f;
1083     while(list[struct_count].format_name != NULL) {
1084 	list[struct_count].struct_size = -1;
1085 	struct_count++;
1086     }
1087 
1088     f = malloc(sizeof(*f));
1089     memset(f, 0, sizeof(*f));
1090     f->subformats = malloc(sizeof(f->subformats[0]) * struct_count);
1091     for (j = 0; j < struct_count; j++) {
1092 	f->subformats[j] = malloc(sizeof(*f));
1093 	memset(f->subformats[j], 0, sizeof(*f));
1094 	f->subformats[j]->field_subformats = NULL;
1095 	f->subformats[j]->alignment = -1;
1096     }
1097     f->master_struct_list = list;
1098     for (j = 0; j < struct_count + 1; j++) {
1099 	for (i=0 ; i < struct_count ; i++) {
1100 	    set_sizes_and_offsets(f, i, list);
1101 	}
1102     }
1103     for (j = 0; j < struct_count; j++) {
1104 	int k = 0;
1105 	FMFormat sub = f->subformats[j];
1106 	free(sub->field_subformats);
1107 	if (sub->var_list) {
1108 	    while(sub->field_list[k].field_name != NULL) {
1109 		FMTypeDesc *d = sub->var_list[k].type_desc.next;
1110 		while (d != NULL) {
1111 		    FMTypeDesc *tmp = d->next;
1112 		    free(d);
1113 		    d = tmp;
1114 		}
1115 		k++;
1116 	    }
1117 	}
1118 	free(sub->var_list);
1119 	free(sub);
1120     }
1121     free(f->subformats);
1122     free(f);
1123 }
1124 
1125 static void
gen_var_dimens(FMFormat fmformat,int field)1126 gen_var_dimens(FMFormat fmformat, int field)
1127 {
1128     FMFieldList field_list = fmformat->field_list;
1129     FMVarInfoList new_var_list = fmformat->var_list;
1130     const char *typ = field_list[field].field_type;
1131     int dimen_count = 0;
1132     int done = 0;
1133     FMDimen *dimens = NULL;
1134     FMTypeDesc *tmp, *last;
1135     if ((!strchr(typ, '*')) && (!strchr(typ, '['))) {
1136 	new_var_list[field].type_desc.next = NULL;
1137 	new_var_list[field].type_desc.type = FMType_simple;
1138 	new_var_list[field].type_desc.field_index = field;
1139 	new_var_list[field].type_desc.data_type = FMstr_to_data_type(typ);
1140     } else {
1141 	FMTypeDesc *desc = gen_type_desc(fmformat, field, typ);
1142 	new_var_list[field].type_desc = *desc;
1143 	free(desc);
1144     }
1145     tmp = &new_var_list[field].type_desc;
1146     last = NULL;
1147     while(tmp->next != NULL) {
1148 	if (tmp->type == FMType_pointer) {
1149 	    fmformat->variant = 1;
1150 	}
1151 	last = tmp;
1152 	tmp = tmp->next;
1153     }
1154     if (new_var_list[field].data_type == string_type) {
1155 	tmp->type = FMType_string;
1156     } else if (fmformat->field_subformats[field] != NULL) {
1157 	tmp->type = FMType_subformat;
1158 	tmp->field_index = field;
1159 	if (fmformat->field_subformats[field]->recursive) {
1160 	    if (last) last->pointer_recursive++;
1161 	}
1162     }
1163     while (!done) {
1164 	int control_val;
1165 	int static_size = IOget_array_size_dimen(field_list[field].field_type,
1166 						 field_list, dimen_count,
1167 						 &control_val);
1168 	if (static_size == 0) {
1169 	    done++;
1170 	    continue;
1171 	}
1172 	if (dimens == NULL) {
1173 	    dimens = malloc(sizeof(dimens[0]));
1174 	} else {
1175 	    dimens = realloc(dimens, sizeof(dimens[0]) * (dimen_count + 1));
1176 	}
1177 	dimens[dimen_count].static_size = static_size;
1178 	dimens[dimen_count].control_field_index = -1;
1179 	if (control_val != -1) {
1180 	    /* got a variant array */
1181 	    fmformat->variant = 1;
1182 	    new_var_list[field].var_array = 1;
1183 	    dimens[dimen_count].control_field_index = control_val;
1184 	    dimens[dimen_count].static_size = 0;
1185 	} else {
1186 	    dimens[dimen_count].static_size = static_size;
1187 	}
1188 	dimen_count++;
1189     }
1190     new_var_list[field].dimens = dimens;
1191     new_var_list[field].dimen_count = dimen_count;
1192 }
1193 
1194 extern void
1195 set_alignment(fmformat)
1196 FMFormat fmformat;
1197 {
1198     int field_align;
1199     int field;
1200     if (fmformat->alignment != 0) return;
1201     for (field = 0; field < fmformat->field_count; field++) {
1202 	field_align = type_alignment(fmformat, field);
1203 	if (fmformat->alignment < field_align) {
1204 	    fmformat->alignment = field_align;
1205 	}
1206     }
1207 }
1208 
1209 
1210 extern int
1211 generate_var_list(fmformat, formats)
1212 FMFormat fmformat;
1213 FMFormat *formats;
1214 {
1215     FMVarInfoList new_var_list;
1216     FMFieldList field_list = fmformat->field_list;
1217     int field_count = fmformat->field_count;
1218     int field;
1219     if (fmformat->var_list)
1220 	free(fmformat->var_list);
1221     if (fmformat->field_subformats)
1222 	free(fmformat->field_subformats);
1223     new_var_list = (FMVarInfoList)
1224 	malloc((size_t) sizeof(FMVarInfoStruct) * field_count);
1225     fmformat->field_subformats = calloc(sizeof(FMFormat), field_count);
1226     fmformat->var_list = new_var_list;
1227     for (field = 0; field < field_count; field++) {
1228 	long elements;
1229 	new_var_list[field].string = 0;
1230 	new_var_list[field].var_array = 0;
1231 	new_var_list[field].byte_vector = 0;
1232 	new_var_list[field].dimen_count = 0;
1233 	new_var_list[field].dimens = NULL;
1234 	new_var_list[field].type_desc.next = NULL;
1235 	fmformat->field_subformats[field] = NULL;
1236 	new_var_list[field].data_type =
1237 	    FMarray_str_to_data_type(field_list[field].field_type,
1238 				   &elements);
1239 	if (new_var_list[field].data_type == string_type) {
1240 	    fmformat->variant = 1;
1241 	    new_var_list[field].string = 1;
1242 	}
1243 	if (new_var_list[field].data_type == unknown_type) {
1244 	    char *base_type = base_data_type(field_list[field].field_type);
1245 	    FMFormat subformat = NULL;
1246 	    int j = 0;
1247 	    while (formats && formats[j] != NULL) {
1248 		if (strcmp(base_type, formats[j]->format_name) == 0) {
1249 		    subformat = formats[j];
1250 		}
1251 		j++;
1252 	    }
1253 	    if (strcmp(base_type, fmformat->format_name) == 0) {
1254 		subformat = fmformat;
1255 		fmformat->recursive = 1;
1256 		fmformat->variant = 1;
1257 	    }
1258 	    if (subformat == NULL) {
1259 		(void) fprintf(stderr, "Field \"%s\" base type \"%s\" is not a simple type or registered format name.\n",
1260 			       fmformat->field_list[field].field_name,
1261 			       base_type);
1262 		(void) fprintf(stderr, "Format rejected.\n ");
1263 		return 0;
1264 	    }
1265 
1266 	    new_var_list[field].byte_vector =
1267 		(strcmp(base_type, "IOEncodeElem") == 0);
1268 	    free(base_type);
1269 	    if (subformat != NULL) {
1270 		fmformat->variant |= subformat->variant;
1271 		fmformat->recursive |= subformat->recursive;
1272 	    }
1273 	    fmformat->field_subformats[field] = subformat;
1274 	}
1275 	gen_var_dimens(fmformat, field);
1276     }
1277     return 1;
1278 }
1279 
1280 static format_rep
add_server_subformat_rep(fmformat,super_rep,super_rep_size)1281 add_server_subformat_rep(fmformat, super_rep, super_rep_size)
1282 FMFormat fmformat;
1283 char *super_rep;
1284 int *super_rep_size;
1285 {
1286     int byte_reversal = fmformat->byte_reversal;
1287     int rep_size = (sizeof(struct _field_wire_format_1) *
1288 		     (fmformat->field_count));
1289     int i;
1290     int opt_info_count = 0;
1291     struct _subformat_wire_format *rep;
1292     char *string_base;
1293     int cur_offset;
1294     struct _field_wire_format_1 *fields;
1295     int OUR_BYTE_ORDER = WORDS_BIGENDIAN;
1296     int OTHER_BYTE_ORDER = (WORDS_BIGENDIAN ? 0 : 1);
1297 
1298     rep_size += strlen(fmformat->format_name) + 1;
1299     for (i = 0; i < fmformat->field_count; i++) {
1300 	rep_size += strlen(fmformat->field_list[i].field_name) + 1;
1301 	rep_size += strlen(fmformat->field_list[i].field_type) + 1;
1302     }
1303 
1304     rep_size += sizeof(struct _subformat_wire_format_1);
1305 
1306     rep_size = (rep_size + 3) & -4;  /* round up by even 4 */
1307     while (fmformat->opt_info &&
1308 	   (fmformat->opt_info[opt_info_count].info_type != 0)) {
1309 	rep_size += fmformat->opt_info[opt_info_count].info_len;
1310 	rep_size = (rep_size + 3) & -4;  /* round up by even 4 */
1311 	opt_info_count++;
1312     }
1313     rep_size += (opt_info_count + 1) * sizeof(struct _opt_info_wire_format);
1314 
1315     super_rep = realloc(super_rep, *super_rep_size + rep_size+4); /* little extra */
1316     rep = (struct _subformat_wire_format *) (super_rep + *super_rep_size);
1317     cur_offset = (sizeof(struct _subformat_wire_format_1) +
1318 		  (sizeof(struct _field_wire_format_1) *
1319 		   (fmformat->field_count)));
1320     rep->f.f1.server_rep_version = 1;
1321     rep->f.f1.header_size = sizeof(struct _subformat_wire_format_1);
1322 
1323     rep->f.f1.column_major_arrays = fmformat->column_major_arrays;
1324     rep->f.f1.alignment = fmformat->alignment;
1325     rep->f.f1.opt_info_offset = 0; /* will be set later */
1326 
1327     string_base = (char *) rep;
1328 
1329     rep->f.f1.name_offset = cur_offset;
1330     if (byte_reversal) byte_swap((char*) &rep->f.f1.name_offset, 4);
1331     strcpy(string_base + cur_offset, fmformat->format_name);
1332     cur_offset += strlen(fmformat->format_name) + 1;
1333 
1334     rep->f.f1.field_count = fmformat->field_count;
1335     if (byte_reversal) byte_swap((char*) &rep->f.f1.field_count, 4);
1336     rep->f.f1.record_length = fmformat->record_length;
1337     if (byte_reversal) byte_swap((char*) &rep->f.f1.record_length, 4);
1338     rep->f.f1.record_byte_order = fmformat->byte_reversal ?
1339 	OTHER_BYTE_ORDER : OUR_BYTE_ORDER;
1340     rep->f.f1.pointer_size = fmformat->pointer_size;
1341     rep->f.f1.floating_point_rep = fmformat->float_format;
1342 
1343     fields = (struct _field_wire_format_1 *) ((char*) rep +
1344 					    rep->f.f1.header_size);
1345     for (i = 0; i < fmformat->field_count; i++) {
1346 	fields[i].field_size = fmformat->field_list[i].field_size;
1347 	if (byte_reversal) byte_swap((char*) &fields[i].field_size, 4);
1348 	fields[i].field_offset = fmformat->field_list[i].field_offset;
1349 	if (byte_reversal) byte_swap((char*) &fields[i].field_offset, 4);
1350 	fields[i].field_name_offset = cur_offset;
1351 	if (byte_reversal) byte_swap((char*) &fields[i].field_name_offset, 4);
1352 	strcpy(string_base + cur_offset,
1353 	       fmformat->field_list[i].field_name);
1354 	cur_offset += strlen(fmformat->field_list[i].field_name) + 1;
1355 	fields[i].field_type_offset = cur_offset;
1356 	if (byte_reversal) byte_swap((char*) &fields[i].field_type_offset, 4);
1357 	strcpy(string_base + cur_offset,
1358 	       fmformat->field_list[i].field_type);
1359 	cur_offset += strlen(fmformat->field_list[i].field_type) +1;
1360     }
1361     {
1362 	char *info_base;
1363 	struct _opt_info_wire_format tmp_base;
1364 
1365 	/* fill in opt info fields */
1366 	while ((cur_offset & 0x3) != 0) {
1367 	    *(string_base + cur_offset++) = 0;
1368 	}
1369 	rep->f.f1.opt_info_offset = cur_offset;
1370 	if (byte_reversal) byte_swap((char*) &rep->f.f1.opt_info_offset, 2);
1371 	info_base = cur_offset +string_base;
1372 	cur_offset += (opt_info_count + 1) *
1373 	    sizeof(struct _opt_info_wire_format);
1374 
1375 	tmp_base.info_type = 0;
1376 	tmp_base.info_len = 0;
1377 	tmp_base.info_offset = 0;
1378 
1379 	memcpy(info_base + opt_info_count* sizeof(tmp_base), &tmp_base,
1380 	       sizeof(tmp_base));
1381 	i = 0;
1382 	for ( ; i < opt_info_count; i++) {
1383 	    tmp_base.info_type = fmformat->opt_info[i].info_type;
1384 	    if (byte_reversal) byte_swap((char*) &tmp_base.info_type, 4);
1385 	    tmp_base.info_len = fmformat->opt_info[i].info_len;
1386 	    if (byte_reversal) byte_swap((char*) &tmp_base.info_len, 4);
1387 	    tmp_base.info_offset = cur_offset;
1388 	    if (byte_reversal) byte_swap((char*) &tmp_base.info_offset, 4);
1389 	    memcpy(info_base + i*sizeof(tmp_base), &tmp_base, sizeof(tmp_base));
1390 	    memcpy(string_base + cur_offset,
1391 		   fmformat->opt_info[i].info_block,
1392 		   fmformat->opt_info[i].info_len);
1393 	    cur_offset += tmp_base.info_len;
1394 	    while ((cur_offset & 0x3) != 0) {
1395 		*(string_base + cur_offset++) = 0;
1396 	    }
1397 	}
1398     }
1399 
1400     while ((cur_offset & 0x3) != 0) {
1401 	*(string_base + cur_offset++) = 0;
1402     }
1403     assert(cur_offset == rep_size);
1404     rep->f.f1.subformat_rep_length = htons(rep_size);
1405     rep->f.f1.top_bytes_subformat_rep_length = htons(rep_size>>16);
1406     rep->f.f1.unused0_f1 = 0;
1407     rep->f.f1.unused1_f1 = 0;
1408     *super_rep_size += rep_size;
1409     return (format_rep) super_rep;
1410 }
1411 
1412 static format_rep
build_server_format_rep(fmformat)1413 build_server_format_rep(fmformat)
1414 FMFormat fmformat;
1415 {
1416     int subformat_count = 0;
1417     FMFormat *subformats = fmformat->subformats;
1418     int i;
1419     struct _format_wire_format *rep = malloc(sizeof(*rep));
1420     int rep_size = sizeof(*rep);
1421     int OUR_BYTE_ORDER = WORDS_BIGENDIAN;
1422     int OTHER_BYTE_ORDER = (WORDS_BIGENDIAN ? 0 : 1);
1423 
1424     while(subformats && subformats[subformat_count]) subformat_count++;
1425     if (subformat_count >= 100) return NULL;  /* no way */
1426 
1427     rep = (struct _format_wire_format *)
1428 	add_server_subformat_rep(fmformat, (char*)rep, &rep_size);
1429     for (i=0; i < subformat_count; i++) {
1430         rep = (struct _format_wire_format *)
1431 	    add_server_subformat_rep(subformats[i], (char*)rep, &rep_size);
1432     }
1433 
1434     rep->f.f1.format_rep_length = htons(rep_size & 0xffff);
1435     rep->f.f1.record_byte_order = fmformat->byte_reversal ?
1436 	OTHER_BYTE_ORDER : OUR_BYTE_ORDER;
1437     rep->f.f1.server_rep_version = 1;
1438     rep->f.f1.subformat_count = subformat_count;
1439     rep->f.f1.recursive_flag = 0;  /* GSE must set right */
1440     rep->f.f1.top_bytes_format_rep_length = htons(rep_size>>16);
1441     return (format_rep) rep;
1442 }
1443 
1444 /*
1445  * search_compatible_formats looks in contexts to see if a format (for
1446  * which we are seeking a format_ID) has already been registered or has
1447  * been retrieved from the format server.  This is done by comparing their
1448  * server_format_rep fields.
1449  */
1450 static FMFormat
search_compatible_formats(iocontext,fmformat)1451 search_compatible_formats(iocontext, fmformat)
1452 FMContext iocontext;
1453 FMFormat fmformat;
1454 {
1455     int i, search_rep_length;
1456     FMContext fmc = (FMContext) iocontext;
1457 
1458     if (fmformat->server_format_rep == NULL) {
1459 	return NULL;
1460     }
1461     search_rep_length = ntohs(fmformat->server_format_rep->format_rep_length);
1462     if (fmformat->server_format_rep->server_rep_version > 0) {
1463 	search_rep_length += (ntohs(fmformat->server_format_rep->top_bytes_format_rep_length) >> 16);
1464     }
1465 
1466     /* search locally first */
1467     for (i = 0; i < fmc->reg_format_count; i++) {
1468 	FMFormat tmp = fmc->format_list[i];
1469 	int rep_length;
1470 
1471 	if (tmp == fmformat)
1472 	    continue;
1473 	if (tmp->server_format_rep == NULL) {
1474 	    continue;
1475 	}
1476 	if (strcmp(fmformat->format_name,
1477 		   fmc->format_list[i]->format_name) != 0)
1478 	    continue;
1479 	rep_length = ntohs(tmp->server_format_rep->format_rep_length);
1480 	if (search_rep_length != rep_length) {
1481 	    if (get_format_server_verbose()) {
1482 		printf("Format %s found in context %lx, but server reps have different lengths, %d and %d\n",
1483 		       fmformat->format_name, (long) iocontext,
1484 		       search_rep_length, rep_length);
1485 	    }
1486 	    continue;
1487 	}
1488 	if (memcmp(fmformat->server_format_rep, tmp->server_format_rep,
1489 		   search_rep_length) == 0) {
1490 	    return tmp;
1491 	} else {
1492 	    if (get_format_server_verbose()) {
1493 		printf("Format %s found in context %lx, but server reps are different\n",
1494 		       fmformat->format_name, (long) iocontext);
1495 	    }
1496 	}
1497     }
1498     if (fmc->master_context != NULL) {
1499 	return search_compatible_formats(fmc->master_context, fmformat);
1500     }
1501     return NULL;
1502 }
1503 
1504 static int
is_self_server(FMContext fmc)1505 is_self_server(FMContext fmc)
1506 {
1507     if (fmc->master_context != NULL) {
1508 	return is_self_server((FMContext) fmc->master_context);
1509     }
1510     return fmc->self_server;
1511 }
1512 
1513 static void
check_format_server_self_status(FMContext context)1514 check_format_server_self_status(FMContext context)
1515 {
1516     int result;
1517     if (context->self_server == 1) return;	/* we're already serving our own formats */
1518     if (context->self_server_fallback == 0) return;	/* we're not allowed to serve our own formats */
1519     /* if we got here, we can fallback to serving our own formats if we can't talk to the format server */
1520     result = establish_server_connection_ptr(context, host_and_fallback);
1521     if (result == 0) {
1522 	context->self_server = 1;
1523     }
1524     context->self_server_fallback = 0;	/* don't try again */
1525 }
1526 
FMcontext_allow_self_formats(FMContext fmc)1527 extern void FMcontext_allow_self_formats(FMContext fmc)
1528 {
1529     if (fmc->master_context != NULL) {
1530 	FMcontext_allow_self_formats((FMContext) fmc->master_context);
1531     }
1532     fmc->self_server_fallback = 1;
1533 
1534     check_format_server_self_status(fmc);
1535 }
1536 
1537 #ifndef MAXHOSTNAMELEN
1538 #define MAXHOSTNAMELEN 64
1539 #endif
1540 
1541 static void
field_name_strip_default(char * field_name)1542 field_name_strip_default(char *field_name)
1543 {
1544 	/* '(' will have to be changed if IODefaultDecl is changed */
1545 	char *s = strchr(field_name, '(');
1546 	if(s)
1547 		*s = '\0';
1548 }
1549 
1550 #define Max(i,j) ((i<j) ? j : i)
1551 extern int
field_offset_compar(const void * a,const void * b)1552 field_offset_compar(const void *a, const void *b)
1553 {
1554     FMFieldList ia = (FMFieldList) a;
1555     FMFieldList ib = (FMFieldList) b;
1556     return (ia->field_offset - ib->field_offset);
1557 }
1558 
1559 FMFieldList
validate_and_copy_field_list(FMFieldList field_list,FMFormat fmformat)1560 validate_and_copy_field_list(FMFieldList field_list, FMFormat fmformat)
1561 {
1562     int field;
1563     FMFieldList new_field_list;
1564     int field_count = count_FMfield(field_list);
1565     new_field_list = (FMFieldList) malloc((size_t) sizeof(FMField) *
1566 					     (field_count + 1));
1567     for (field = 0; field < field_count; field++) {
1568 	int field_size = 0;
1569 	if (strchr(field_list[field].field_type, '[') == NULL) {
1570 	    /* not an array */
1571 	    if (index(field_list[field].field_type, '*') == NULL) {
1572 		field_size = field_list[field].field_size;
1573 	    } else {
1574 		field_size = fmformat->pointer_size;
1575 	    }
1576 	} else {
1577 	    int ret = is_var_array_field(field_list, field);
1578 	    if (ret == -1) return NULL;   /* rejected */
1579 	    if ((ret == 1) || (index(field_list[field].field_type, '*'))) {
1580 		/* variant array, real_field_size is
1581 		 * fmc->pointer_size */
1582 		field_size = fmformat->pointer_size;
1583 		if (field_size <= 0) {
1584 		    fprintf(stderr, "Pointer Size is not positive! BAD! pointer size = %d\n",
1585 			    fmformat->pointer_size);
1586 		    return NULL;
1587 		}
1588 	    } else {
1589 		long elements;
1590 		FMdata_type base_type;
1591 
1592 		base_type = FMarray_str_to_data_type(field_list[field].field_type,
1593 						   &elements);
1594 		if ((base_type != unknown_type) &&
1595 		    (field_list[field].field_size > 16)) {
1596 		    fprintf(stderr, "Field size for field %s in format %s is large, check to see if it is valid.\n",
1597 			    field_list[field].field_name, fmformat->format_name);
1598 		}
1599 		field_size = field_list[field].field_size * elements;
1600 		if (field_size <= 0) {
1601 		    fprintf(stderr, "Field Size is not positive!  field type \"%s\" base= %d, elements=%ld\n",
1602 			    field_list[field].field_type,
1603 			    field_list[field].field_size, elements);
1604 		    return NULL;
1605 		}
1606 	    }
1607 	}
1608 
1609 	fmformat->record_length = Max(fmformat->record_length,
1610 					 field_list[field].field_offset +
1611 					    field_size);
1612 	new_field_list[field].field_name = strdup(field_list[field].field_name);
1613 	field_name_strip_default((char *)new_field_list[field].field_name);
1614 	new_field_list[field].field_type = strdup(field_list[field].field_type);
1615 	new_field_list[field].field_size = field_list[field].field_size;
1616 	new_field_list[field].field_offset = field_list[field].field_offset;
1617     }
1618     new_field_list[field_count].field_name = NULL;
1619     new_field_list[field_count].field_type = NULL;
1620     new_field_list[field_count].field_size = 0;
1621     new_field_list[field_count].field_offset = 0;
1622     fmformat->field_count = field_count;
1623     fmformat->field_list = new_field_list;
1624     qsort(fmformat->field_list, field_count, sizeof(FMField),
1625 	  field_offset_compar);
1626     return new_field_list;
1627 }
1628 
1629 static void
free_format_list(FMFormat * formats)1630 free_format_list(FMFormat *formats)
1631 {
1632     while (formats && formats[0]) {
1633 	free_FMformat(formats[0]);
1634 	formats++;
1635     }
1636 }
1637 
1638 FMFormat
FMregister_simple_format(FMContext context,char * struct_name,FMFieldList struct_field_list,int struct_size)1639 FMregister_simple_format(FMContext context, char *struct_name,
1640 		       FMFieldList struct_field_list,
1641 		       int struct_size)
1642 {
1643     FMStructDescRec str_rec[2];
1644     str_rec[0].format_name = struct_name;
1645     str_rec[0].field_list = struct_field_list;
1646     str_rec[0].struct_size = struct_size;
1647     str_rec[0].opt_info = NULL;
1648     str_rec[1].format_name = NULL;
1649     return register_data_format(context, &str_rec[0]);
1650 }
1651 
1652 static int
compare_by_name_FMFormat(const void * va,const void * vb)1653 compare_by_name_FMFormat(const void*va, const void*vb)
1654 {
1655     FMFormat a = *(FMFormat*)va;
1656     FMFormat b = *(FMFormat*)vb;
1657     return strcmp(a->format_name, b->format_name);
1658 }
1659 
1660 static int
on_list(FMFormat f,FMFormat * list)1661 on_list(FMFormat f, FMFormat *list)
1662 {
1663     while(*list != NULL) {
1664 	if (f == *list) return 1;
1665 	list++;
1666     }
1667     return 0;
1668 }
1669 
1670 static void
add_to_list(FMFormat f,FMFormat * list)1671 add_to_list(FMFormat f, FMFormat *list)
1672 {
1673     int count = 0;
1674     while(list[count] != NULL) count++;
1675     list[count] = f;
1676     list[count+1] = NULL;
1677 }
1678 
1679 static
add_format(FMFormat f,FMFormat * sorted,FMFormat * visited,FMFormat * stack)1680 void add_format(FMFormat f, FMFormat* sorted, FMFormat *visited, FMFormat* stack)
1681 {
1682     /* if n has not been visited yet then */
1683     if (!on_list(f, visited)) {
1684 	FMFormat tmp[100];
1685 	int count = 0;
1686 	int i;
1687         /* mark n as visited */
1688 	add_to_list(f, visited);
1689 
1690 	/* get subfields and sort them by name for predictability */
1691 	for (i=0; i < f->field_count; i++) {
1692 	    if (f->field_subformats[i] != NULL) {
1693 		tmp[count++] = f->field_subformats[i];
1694 	    }
1695 	}
1696 	qsort(&tmp[0], count, sizeof(tmp[0]), compare_by_name_FMFormat);
1697 
1698 	for (i=0; i < count; i++) {
1699 	    add_format(tmp[i], sorted, visited, stack);
1700 	}
1701 	add_to_list(f, sorted);
1702     }
1703 }
1704 
1705 
1706 static
1707 int
topo_order_subformats(super_format,format_count)1708 topo_order_subformats(super_format, format_count)
1709 FMFormat super_format;
1710 int format_count;
1711 {
1712     FMFormat sorted[100], visit[100], stack[100];
1713     int sorted_count = 1;
1714     int i = 0;
1715     sorted[0] = visit[0] = stack[0] = NULL;
1716 
1717     add_format(super_format, sorted, visit, stack);
1718     while(sorted[sorted_count] != 0) sorted_count++;
1719 
1720     if ((format_count +1) > sorted_count) {
1721 	for (i=0; i < format_count; i++) {
1722 	    int j, found = 0;
1723 	    for (j=0; j < sorted_count; j++) {
1724 		if (super_format->subformats[i] == sorted[j]) found++;
1725 	    }
1726 	    if (!found) {
1727 	        /* printf("Didn't find this format[%d] %p:\n", i, super_format->subformats[i]); */
1728 		/* printf("Name was %s\n", super_format->subformats[i]->format_name); */
1729 		/* printf("======= Choices were :\n"); */
1730 		/* for(j=0; j < sorted_count; j++) { */
1731 		/*     printf("Choice %d (%p):\n", j, sorted[j]); */
1732 		/*     printf(" %s\n", sorted[j]->format_name); */
1733 		/* } */
1734 		free_FMformat(super_format->subformats[i]);
1735 		super_format->subformats[i] = NULL;
1736 	    }
1737 	}
1738     }
1739     for (i=0; i< sorted_count-1; i++) {
1740       super_format->subformats[i] = sorted[sorted_count - 2 - i];
1741     }
1742 
1743     return sorted_count;
1744 }
1745 
1746 extern FMFormat
FMlookup_format(FMContext context,FMStructDescList struct_list)1747 FMlookup_format(FMContext context, FMStructDescList struct_list)
1748 {
1749     int i;
1750     for (i=0 ; i < context->reg_format_count; i++) {
1751 	if (context->format_list[i]->orig_struct_list == struct_list) {
1752 	    return context->format_list[i];
1753 	}
1754     }
1755     return NULL;
1756 }
1757 
1758 FMFormat
FMregister_data_format(FMContext context,FMStructDescList struct_list)1759 FMregister_data_format(FMContext context, FMStructDescList struct_list)
1760 {
1761     return register_data_format(context, struct_list);
1762 }
1763 
1764 FMFormat
register_data_format(FMContext context,FMStructDescList struct_list)1765 register_data_format(FMContext context, FMStructDescList struct_list)
1766 {
1767     int i, field;
1768     int struct_count = 0, new_struct_count;
1769     FMFormat *formats, ret;
1770     FMStructDescList master_struct_list;
1771 
1772     for (struct_count = 0; struct_list[struct_count].format_name != NULL;
1773 	 struct_count++) /* set struct_count */;
1774 
1775     formats = malloc(sizeof(formats[0]) * (struct_count+1));
1776     formats[struct_count] = NULL;
1777     for (i = 0 ; i < struct_count; i++ ) {
1778 	FMFormat fmformat = new_FMFormat();
1779 	FMFieldList new_field_list;
1780 	fmformat->format_name = strdup(struct_list[i].format_name);
1781 	fmformat->pointer_size = context->native_pointer_size;
1782 	fmformat->column_major_arrays = context->native_column_major_arrays;
1783 	fmformat->float_format = context->native_float_format;
1784 	fmformat->context = context;
1785 	fmformat->record_length = 0;
1786 	fmformat->variant = 0;
1787 	fmformat->record_length = struct_list[i].struct_size;
1788 
1789 	new_field_list =
1790 	    validate_and_copy_field_list(struct_list[i].field_list, fmformat);
1791 	formats[i] = fmformat;
1792 
1793 	if (new_field_list == NULL) {
1794 	    free_format_list(formats);
1795 	    free(formats);
1796 	    return NULL;
1797 	}
1798 	if (struct_list[i].opt_info != NULL) {
1799 	    FMOptInfo *opt_info = struct_list[i].opt_info;
1800 	    int opt_info_count = 0;
1801 	    while (opt_info[opt_info_count].info_type != 0) opt_info_count++;
1802 	    formats[i]->opt_info = malloc(sizeof(opt_info[0]) *
1803 						(opt_info_count + 1));
1804 	    memcpy(formats[i]->opt_info, opt_info, sizeof(opt_info[0]) *
1805 		   (opt_info_count + 1));
1806 	    /*
1807 	     * we should vet the opt_info that we understand here.  I.E. check
1808 	     * to see if the XML info is appropriate, that the compatability info
1809 	     * will work, etc.
1810 	     */
1811 	} else {
1812 	    formats[i]->opt_info = NULL;
1813 	}
1814     }
1815 
1816     for (i= 0; i < struct_count; i++) {
1817 	if (!generate_var_list(formats[struct_count -i - 1], formats)) {
1818 	    free_format_list(formats);
1819 	    free(formats);
1820 	    return NULL;
1821 	}
1822     }
1823 
1824     formats[0]->subformats = malloc(sizeof(FMFormat) * struct_count);
1825     memcpy(formats[0]->subformats, &formats[1], sizeof(FMFormat) * struct_count);
1826     formats[0]->subformats[struct_count-1] = NULL;
1827 
1828     new_struct_count = topo_order_subformats(formats[0], struct_count-1);
1829     struct_count = new_struct_count;
1830     formats[0]->subformats[struct_count-1] = NULL;
1831     /* after topo, build master_struct_list */
1832     master_struct_list = malloc(sizeof(struct_list[0]) * (struct_count+1));
1833     master_struct_list[0].format_name = formats[0]->format_name;
1834     master_struct_list[0].field_list = formats[0]->field_list;
1835     master_struct_list[0].struct_size = formats[0]->record_length;
1836     master_struct_list[0].opt_info = formats[0]->opt_info;
1837     for (i = 0; i < struct_count-1; i++) {
1838       master_struct_list[i+1].format_name = formats[0]->subformats[i]->format_name;
1839       master_struct_list[i+1].field_list = formats[0]->subformats[i]->field_list;
1840       master_struct_list[i+1].struct_size = formats[0]->subformats[i]->record_length;
1841       master_struct_list[i+1].opt_info = formats[0]->subformats[i]->opt_info;
1842     }
1843 
1844     for (i=struct_count-2; i>=0; i--) {
1845 	set_alignment(formats[0]->subformats[i]);
1846 	formats[i+1] = formats[0]->subformats[i];
1847     }
1848     set_alignment(formats[0]);
1849     /* bubble up the variant flags */
1850     for (i= 0; i < struct_count; i++) {
1851 	int j;
1852 	for (j= 0; j < struct_count; j++) {
1853 	    FMFormat iof = formats[j];
1854 	    for (field = 0; field < iof->field_count; field++) {
1855 		FMFormat subformat = iof->field_subformats[field];
1856 		if (subformat != NULL) {
1857 		    iof->variant |= subformat->variant;
1858 		}
1859 	    }
1860 	}
1861     }
1862     for (i= 0; i < struct_count; i++) {
1863 	FMFormat fmformat = formats[i];
1864 	int last_field_end = 0;
1865 	FMFieldList field_list = fmformat->field_list;
1866 	for (field = 0; field < fmformat->field_count; field++) {
1867 	    FMFormat subformat = fmformat->field_subformats[field];
1868 	    if (subformat != NULL) {
1869 
1870 		if (field_list[field].field_size <
1871 		    subformat->record_length) {
1872 		    (void) fprintf(stderr, "Field \"%s\" base type \"%s\" has size %d\n",
1873 				   field_list[field].field_name,
1874 				   field_list[field].field_type,
1875 				   field_list[field].field_size);
1876 		    (void) fprintf(stderr, "  this is smaller than record size for \"%s\" (%d bytes)\n",
1877 				   subformat->format_name,
1878 				   subformat->record_length);
1879 		    free_format_list(formats);
1880 		    free(formats);
1881 		    return NULL;
1882 		}
1883 	    }
1884 	    if (field_list[field].field_offset < last_field_end) {
1885 		(void) fprintf(stderr, "Fields \"%s\" and \"%s\" in format \"%s\" overlap!  Format rejected.\n",
1886 			       field_list[field - 1].field_name,
1887 			       field_list[field].field_name,
1888 			       fmformat->format_name);
1889 		free_format_list(formats);
1890 		free(formats);
1891 		return NULL;
1892 	    }
1893 	    last_field_end = field_list[field].field_offset +
1894 		field_list[field].field_size;
1895 	    if (fmformat->var_list[field].var_array) {
1896 		last_field_end = field_list[field].field_offset +
1897 		    fmformat->pointer_size;
1898 	    } else if (fmformat->var_list[field].type_desc.type == FMType_pointer) {
1899 		last_field_end = field_list[field].field_offset +
1900 		    fmformat->pointer_size;
1901 	    }
1902 	}
1903 	if (master_struct_list[i].struct_size < last_field_end) {
1904 	    (void) fprintf(stderr, "Structure size for structure %s is smaller than last field size + offset.  Format rejected structsize %d, last end %d.\n",
1905 			   fmformat->format_name, master_struct_list[i].struct_size, last_field_end);
1906 	    free_format_list(formats);
1907 	    free(formats);
1908 	    return NULL;
1909 	}
1910     }
1911 
1912     master_struct_list[struct_count].format_name = NULL;
1913     formats[0]->master_struct_list = master_struct_list;
1914     {
1915 	FMFormat cache_format;
1916 	formats[0]->server_format_rep = build_server_format_rep(formats[0]);
1917 	cache_format = search_compatible_formats(context, formats[0]);
1918 	if (cache_format == NULL) {
1919 	    /* register format with server */
1920 	    if (is_self_server(context)) {
1921 		if (self_server_register_format(context, formats[0]) == 0)
1922 		    return NULL;
1923 	    } else {
1924 		if (server_register_format(context, formats[0]) == 0)
1925 		    return NULL;
1926 	    }
1927 	    if (get_format_server_verbose()) {
1928 		printf("Registered format with format server - %lx  in context %lx\n",
1929 		    (long) formats[0], (long) context);
1930 		dump_FMFormat(formats[0]);
1931 	    }
1932 	} else {
1933 	    free_FMformat(formats[0]);
1934 	    free(formats);
1935 	    cache_format->ref_count++;
1936 
1937 	    if (get_format_server_verbose()) {
1938 		printf("Cache hit on format registration %lx \"%s\" ",
1939 		       (long)cache_format, cache_format->format_name);
1940 		print_format_ID(cache_format);
1941 		printf("\n");
1942 	    }
1943 	    return cache_format;
1944 	}
1945     }
1946     if (context->reg_format_count == context->format_list_size) {
1947 	expand_FMContext(context);
1948     }
1949     formats[0]->format_index = context->reg_format_count++;
1950     context->format_list[formats[0]->format_index] = formats[0];
1951     formats[0]->orig_struct_list = struct_list;
1952     ret = formats[0];
1953     free(formats);
1954     return ret;
1955 }
1956 
1957 INT4 FFS_self_server_IP_addr = 0;
1958 
1959 extern void hashlittle2(
1960   const void *key,       /* the key to hash */
1961   size_t      length,    /* length of the key */
1962   INT4   *pc,        /* IN: primary initval, OUT: primary hash */
1963   INT4   *pb)        /* IN: secondary initval, OUT: secondary hash */;
1964 
1965 
1966 extern void
generate_format3_server_ID(server_ID_type * server_ID,struct _format_wire_format_1 * server_format_rep)1967 generate_format3_server_ID(server_ID_type *server_ID,
1968 			   struct _format_wire_format_1 *server_format_rep)
1969 {
1970     INT4 hash1 = 0, hash2 = 0;
1971     UINT4 server_format_rep_length = ntohs(server_format_rep->format_rep_length);
1972     if (server_format_rep->server_rep_version > 0) {
1973 	server_format_rep_length += (ntohs(server_format_rep->top_bytes_format_rep_length) >> 16);
1974     }
1975     if (server_format_rep_length > (1 << 26)) fprintf(stderr, "Format rep too long in generate_format_server_ID\n");
1976     server_ID->length = 12;
1977     server_ID->value = malloc(12);
1978     ((version_3_format_ID *) server_ID->value)->version = 2;
1979     hashlittle2((int*)server_format_rep,
1980 		server_format_rep_length,
1981 		&hash1, &hash2);
1982     if (get_format_server_verbose()) {
1983 	unsigned char *tmp = (unsigned char*)server_format_rep;
1984 	int size = server_format_rep_length;
1985 	int i;
1986 	printf("Server rep is : ");
1987 	for (i=0; i< size; i++) {
1988 	    printf("%02x ", tmp[i]);
1989 	}
1990 	printf("\n");
1991     }
1992     ((version_3_format_ID *) server_ID->value)->rep_len =
1993 	htons(server_format_rep_length >> 2);   // Mod length by 4
1994     ((version_3_format_ID *) server_ID->value)->top_byte_rep_len =
1995 	htons(server_format_rep_length >> 18);  // Essentially, we capture the top 26 bytes of the server length
1996     ((version_3_format_ID *) server_ID->value)->hash1 = htonl(hash1);
1997     ((version_3_format_ID *) server_ID->value)->hash2 = htonl(hash2);
1998 }
1999 
2000 static int
self_server_register_format(fmc,fmformat)2001 self_server_register_format(fmc, fmformat)
2002 FMContext fmc;
2003 FMFormat fmformat;
2004 {
2005     format_rep server_format_rep;
2006     /* we're a format server ourselves, assign an ID */
2007     if (fmc->master_context != NULL) {
2008 	return self_server_register_format((FMContext) fmc->master_context,
2009 					   fmformat);
2010     }
2011     if (fmformat->context != fmc) {
2012 	/* registering in a master, copy it down */
2013 	assert(0);
2014     }
2015     if (fmformat->server_format_rep == NULL) {
2016 	server_format_rep = build_server_format_rep(fmformat);
2017     }
2018     server_format_rep = fmformat->server_format_rep;
2019 
2020     generate_format3_server_ID(&fmformat->server_ID, server_format_rep);
2021     if (get_format_server_verbose()) {
2022 	printf("Registering %s to locally-issued format ID ",
2023 	       fmformat->format_name);
2024 	print_format_ID(fmformat);
2025 	printf("\n");
2026     }
2027     return 1;
2028 }
2029 
2030 int
count_FMfield(list)2031 count_FMfield(list)
2032 FMFieldList list;
2033 {
2034     int i = 0;
2035     while (list[i].field_name != NULL) {
2036 	i++;
2037     }
2038     return i;
2039 }
2040 
2041 extern
2042 int
2043 struct_size_IOfield(fmc, list)
2044 FMContext fmc;
2045 FMFieldList list;
2046 {
2047     int i = 0;
2048     int struct_size = 0;
2049     while (list[i].field_name != NULL) {
2050 	int field_size = 0;
2051 	if (is_var_array_field(list, i) == 1) {
2052 	    /* variant array, real_field_size is fmformat->pointer_size */
2053 	    if ((fmc == NULL) || (fmc->native_pointer_size == 0)) {
2054 		field_size = sizeof(char *);
2055 	    } else {
2056 		field_size = fmc->native_pointer_size;
2057 	    }
2058 	} else {
2059 	    if (fmc) {
2060 		long elements;
2061 		FMarray_str_to_data_type(list[i].field_type, &elements);
2062 		field_size = list[i].field_size * elements;
2063 	    } else {
2064 		field_size = list[i].field_size;
2065 	    }
2066 	}
2067 	assert(field_size > 0);
2068 	struct_size = Max(struct_size,
2069 			  (list[i].field_offset + field_size));
2070 	i++;
2071     }
2072     return struct_size;
2073 }
2074 
2075 extern int
2076 struct_size_field_list(list, pointer_size)
2077 FMFieldList list;
2078 int pointer_size;
2079 {
2080     return FMstruct_size_field_list(list, pointer_size);
2081 }
2082 
2083 extern
2084 int
2085 FMstruct_size_field_list(list, pointer_size)
2086 FMFieldList list;
2087 int pointer_size;
2088 {
2089     int i = 0;
2090     int struct_size = 0;
2091     while (list[i].field_name != NULL) {
2092 	int field_size = 0;
2093 	if ((is_var_array_field(list, i) == 1) || (index(list[i].field_type, '*'))) {
2094 	    /* variant array, real_field_size is fmformat->pointer_size */
2095 	    field_size = pointer_size;
2096 	} else {
2097 	    long elements;
2098 	    FMarray_str_to_data_type(list[i].field_type, &elements);
2099 	    field_size = list[i].field_size * elements;
2100 	}
2101 	assert(field_size > 0);
2102 	struct_size = Max(struct_size,
2103 			  (list[i].field_offset + field_size));
2104 /*	printf("i=%d field_name=%s field_type=%s struct_size= %d, offset=%d size=%d\n", i, list[i].field_name, list[i].field_type, struct_size, list[i].field_offset, field_size);*/
2105 	i++;
2106     }
2107     return struct_size;
2108 }
2109 
2110 extern
2111 FMFieldList
2112 field_list_of_IOformat(format)
2113 FMFormat format;
2114 {
2115     return format->field_list;
2116 }
2117 
2118 extern
2119 int
2120 compare_field_lists(list1, list2)
2121 FMFieldList list1, list2;
2122 {
2123     int i = 0;
2124     do {
2125 	if ((strcmp(list1[i].field_name, list2[i].field_name) != 0) ||
2126 	    (list1[i].field_size != list2[i].field_size) ||
2127 	    (list1[i].field_offset != list2[i].field_offset) ||
2128 	    !field_type_eq(list1[i].field_type, list2[i].field_type)) {
2129 	    return 1;
2130 	}
2131 	i++;
2132     } while ((list1[i].field_name != NULL) || (list2[i].field_name != NULL));
2133 
2134     return 0;
2135 }
2136 
2137 /*
2138  * Max field list returns the "maximum" of two field lists.
2139  * Basically, it prefers list1.  If all fields in list2 are in list 1, and
2140  * if no fields in list2 are bigger than the corresponding field in
2141  * list1, the maximum returned is list1.  If there is a field in list2
2142  * that is bigger than the corresponding field in list1, we'll still
2143  * use the ordering and even try to use the offsets in list1.  If
2144  * there's actually a field in list2 that isn't in list1, then most
2145  * bets are off as to exactly what will happen.  Basically the
2146  * resulting list will contain all fields, but we'll use the offsets
2147  * from their original lists to establish an ordering and then bump
2148  * the offsets up as necessary to ensure no overlap.  The result is
2149  * likely a jumble that isn't necessarily terribly close to what was in
2150  * either list...  Bummer for performance perhaps, but being smarter is
2151  * hard.
2152  */
2153 extern
2154 FMFieldList
2155 max_field_lists(list1, list2)
2156 FMFieldList list1, list2;
2157 {
2158     FMFieldList max_field_list = NULL;
2159     FMFieldList tlist2;
2160     int field_count1 = count_FMfield(list1);
2161     int field_count2 = count_FMfield(list2);
2162     int max_field_count = 0;
2163     int i, j;
2164 
2165     /* make a copy of list2 that we can scratch on */
2166     tlist2 = (FMFieldList) malloc((size_t) sizeof(FMField) * field_count2);
2167     memcpy(tlist2, list2, sizeof(FMField) * field_count2);
2168 
2169     max_field_list = (FMFieldList) malloc((size_t) sizeof(FMField) *
2170 				      (field_count1 + field_count2 + 1));
2171 
2172     for (i = 0; i < field_count1; i++) {
2173 	/* for each field in list1 */
2174 	for (j = 0; j < field_count2; j++) {
2175 	    if (tlist2[j].field_name &&
2176 	      (strcmp(list1[i].field_name, tlist2[j].field_name) == 0)) {
2177 		break;
2178 	    }
2179 	}
2180 	if (j == field_count2) {
2181 	    /* field exists only in 1, use it as is */
2182 	    max_field_list[max_field_count].field_name =
2183 		strdup(list1[i].field_name);
2184 	    max_field_list[max_field_count].field_type =
2185 		strdup(list1[i].field_type);
2186 	    max_field_list[max_field_count].field_size =
2187 		list1[i].field_size;
2188 	    max_field_list[max_field_count].field_offset =
2189 		list1[i].field_offset;
2190 	    max_field_count++;
2191 	} else {
2192 	    /* field list in both.  Check types and take max size */
2193 	    if (!field_type_eq(list1[i].field_type, tlist2[j].field_type)) {
2194 		/* Yikes!  Types are bad!  Serious problem */
2195 		free(tlist2);
2196 		free(max_field_list);
2197 		return NULL;
2198 	    }
2199 	    max_field_list[max_field_count].field_name =
2200 		strdup(list1[i].field_name);
2201 	    max_field_list[max_field_count].field_type =
2202 		strdup(list1[i].field_type);
2203 	    max_field_list[max_field_count].field_size =
2204 		Max(list1[i].field_size, tlist2[j].field_size);
2205 	    /* tentative offset */
2206 	    max_field_list[max_field_count].field_offset =
2207 		list1[i].field_offset;
2208 	    max_field_count++;
2209 	    /* mark field in list 2 as used */
2210 	    tlist2[j].field_name = NULL;
2211 	}
2212     }
2213     for (j = 0; j < field_count2; j++) {
2214 	if (tlist2[j].field_name != NULL) {
2215 	    /* didn't mark this field as used.  Must only be in list2 */
2216 	    max_field_list[max_field_count].field_name =
2217 		strdup(tlist2[j].field_name);
2218 	    max_field_list[max_field_count].field_type =
2219 		strdup(tlist2[j].field_type);
2220 	    max_field_list[max_field_count].field_size =
2221 		tlist2[j].field_size;
2222 	    max_field_list[max_field_count].field_offset =
2223 		tlist2[j].field_offset;
2224 	    max_field_count++;
2225 	}
2226     }
2227     free(tlist2);
2228 
2229     max_field_list[max_field_count].field_name = NULL;
2230     max_field_list[max_field_count].field_type = NULL;
2231     max_field_list[max_field_count].field_size = 0;
2232     max_field_list[max_field_count].field_offset = 0;
2233 
2234     /* sort the max list by offset now */
2235     qsort(max_field_list, max_field_count, sizeof(FMField),
2236 	  field_offset_compar);
2237     for (i = 1; i < max_field_count; i++) {
2238 	int last_field_end = max_field_list[i - 1].field_offset +
2239 	max_field_list[i - 1].field_size;
2240 	if (max_field_list[i].field_offset < last_field_end) {
2241 	    /* damn, got some overlap.  Push this field up to fix. */
2242 	    max_field_list[i].field_offset = last_field_end;
2243 	}
2244     }
2245     return max_field_list;
2246 }
2247 
2248 extern
2249 FMFieldList
2250 copy_field_list(list)
2251 FMFieldList list;
2252 {
2253     int field_count = count_FMfield(list);
2254     FMFieldList new_field_list;
2255     int field;
2256 
2257     new_field_list = (FMFieldList) malloc((size_t) sizeof(FMField) *
2258 					     (field_count + 1));
2259     for (field = 0; field < field_count; field++) {
2260 	new_field_list[field].field_name = strdup(list[field].field_name);
2261 	new_field_list[field].field_type = strdup(list[field].field_type);
2262 	new_field_list[field].field_size = list[field].field_size;
2263 	new_field_list[field].field_offset = list[field].field_offset;
2264     }
2265     new_field_list[field_count].field_name = NULL;
2266     new_field_list[field_count].field_type = NULL;
2267     new_field_list[field_count].field_offset = 0;
2268     new_field_list[field_count].field_size = 0;
2269     return new_field_list;
2270 }
2271 
2272 extern
2273 FMStructDescList
2274 FMcopy_struct_list(list)
2275 FMStructDescList list;
2276 {
2277     int format_count = 0;
2278     FMStructDescList new_list;
2279     int format;
2280 
2281     while(list[format_count].format_name != NULL) format_count++;
2282 
2283     new_list = (FMStructDescList) malloc((size_t) sizeof(FMStructDescRec) *
2284 					     (format_count + 1));
2285     for (format = 0; format < format_count; format++) {
2286 	new_list[format].format_name = strdup(list[format].format_name);
2287 	new_list[format].field_list = copy_field_list(list[format].field_list);
2288 	new_list[format].struct_size = list[format].struct_size;
2289 	new_list[format].opt_info = list[format].opt_info;
2290     }
2291     new_list[format_count].format_name = NULL;
2292     new_list[format_count].field_list = NULL;
2293     new_list[format_count].struct_size = 0;
2294     new_list[format_count].opt_info = NULL;
2295     return new_list;
2296 }
2297 
2298 extern
2299 void
2300 free_field_list(list)
2301 FMFieldList list;
2302 {
2303     int i = 0;
2304     while (list[i].field_name != NULL) {
2305 	free((char*)list[i].field_name);
2306 	free((char*)list[i].field_type);
2307 	i++;
2308     }
2309     free(list);
2310 }
2311 
2312 extern
2313 void
2314 FMfree_struct_list(list)
2315 FMStructDescList list;
2316 {
2317     int format_count = 0;
2318     int format;
2319 
2320     while(list[format_count].format_name != NULL) format_count++;
2321 
2322     for (format = 0; format < format_count; format++) {
2323 	free(list[format].format_name);
2324 	free_field_list(list[format].field_list);
2325     }
2326     free(list);
2327 }
2328 
2329 extern
2330 void
free_FMfield_list(FMFieldList list)2331 free_FMfield_list(FMFieldList list)
2332 {
2333     free_field_list(list);
2334 }
2335 
2336 extern void
free_FMFormatList(FMFormatList format_list)2337 free_FMFormatList(FMFormatList format_list)
2338 {
2339     int i = 0;
2340     while(format_list[i].format_name){
2341 	free(format_list[i].format_name);
2342 	free_field_list(format_list[i].field_list);
2343 	if (format_list[i].opt_info) free(format_list[i].opt_info);
2344 	i++;
2345     }
2346 }
2347 
2348 extern int
field_name_compar(const void * a,const void * b)2349 field_name_compar(const void *a, const void *b)
2350 {
2351     FMFieldList ia = (FMFieldList) a;
2352     FMFieldList ib = (FMFieldList) b;
2353     return (strcmp(ia->field_name, ib->field_name));
2354 }
2355 
2356 FMformat_order
FMformat_cmp(format1,format2)2357 FMformat_cmp(format1, format2)
2358 FMFormat format1;
2359 FMFormat format2;
2360 {
2361     FMformat_order tmp_result = Format_Equal;
2362     FMFieldList field_list1 =
2363 	copy_field_list(field_list_of_IOformat(format1));
2364     FMFieldList field_list2 =
2365 	copy_field_list(field_list_of_IOformat(format2));
2366     FMFormat *subformats1 = NULL, *subformats2 = NULL, *tmp_subformats = NULL;
2367     int field_count1, field_count2;
2368     int i, j, limit;
2369 
2370     /* count fields */
2371     for (field_count1 = 0; field_list1[field_count1].field_name != NULL;
2372 	 field_count1++);
2373 
2374     /* count fields */
2375     for (field_count2 = 0; field_list2[field_count2].field_name != NULL;
2376 	 field_count2++);
2377 
2378     qsort(field_list1, field_count1, sizeof(FMField), field_name_compar);
2379     qsort(field_list2, field_count2, sizeof(FMField), field_name_compar);
2380 
2381     limit = field_count1;
2382     if (field_count2 < limit)
2383 	limit = field_count2;
2384     i = j = 0;
2385     while ((i < field_count1) && (j < field_count2)) {
2386 	int name_cmp;
2387 	if ((name_cmp = strcmp(field_list1[i].field_name,
2388 			       field_list2[j].field_name)) == 0) {
2389 	    /* fields have same name */
2390 	    if (!field_type_eq(field_list1[i].field_type,
2391 				  field_list2[j].field_type)) {
2392 		return Format_Incompatible;
2393 	    }
2394 	} else if (name_cmp < 0) {
2395 	    /* name_cmp>0  a field in field_list1 that doesn't appear in 2 */
2396 	    if (tmp_result == Format_Less) {
2397 		/* we previously found the opposite */
2398 		tmp_result = Format_Incompatible;
2399 		goto free_lists;
2400 	    } else {
2401 		/* tentatively decide that list1 is a superset of 2 */
2402 		tmp_result = Format_Greater;
2403 	    }
2404 	    /* skip fields in 1 until we find the next field in 2 */
2405 	    while (strcmp(field_list1[i].field_name,
2406 			  field_list2[j].field_name) < 0) {
2407 		i++;
2408 		if (i == field_count1) {
2409 		    /* didn't find one */
2410 		    tmp_result = Format_Incompatible;
2411 		    goto free_lists;
2412 		}
2413 	    }
2414 	    i--;
2415 	    j--;
2416 	} else {
2417 	    /* name_cmp>0  a field in field_list2 that doesn't appear in 1 */
2418 	    if (tmp_result == Format_Greater) {
2419 		tmp_result = Format_Incompatible;
2420 		goto free_lists;
2421 	    } else {
2422 		tmp_result = Format_Less;
2423 	    }
2424 	    /* skip fields in field_list2 until we find matching */
2425 	    while (strcmp(field_list1[i].field_name,
2426 			  field_list2[j].field_name) > 0) {
2427 		j++;
2428 		if (j == field_count2) {
2429 		    /* didn't find one */
2430 		    tmp_result = Format_Incompatible;
2431 		    goto free_lists;
2432 		}
2433 	    }
2434 	    i--;
2435 	    j--;
2436 	}
2437 	i++;
2438 	j++;
2439     }
2440     if (i < field_count1) {
2441 	if (tmp_result == Format_Less) {
2442 	    tmp_result = Format_Incompatible;
2443 	    goto free_lists;
2444 	} else {
2445 	    tmp_result = Format_Greater;
2446 	}
2447     } else if (j < field_count2) {
2448 	if (tmp_result == Format_Greater) {
2449 	    tmp_result = Format_Incompatible;
2450 	    goto free_lists;
2451 	} else {
2452 	    tmp_result = Format_Less;
2453 	}
2454     }
2455     /* go through subformats */
2456     tmp_subformats = subformats1 = get_subformats_IOformat(format1);
2457     subformats2 = get_subformats_IOformat(format2);
2458 
2459     while (*subformats1 != NULL) {
2460 	char *sub1_name = name_of_FMformat(*subformats1);
2461 	int i = 0;
2462 	if (*subformats1 == format1) {
2463 	    /* self appears in subformat list, skip it */
2464 	    subformats1++;
2465 	    continue;
2466 	}
2467 	while (subformats2[i] != NULL) {
2468 	    if (strcmp(sub1_name, name_of_FMformat(subformats2[i])) == 0) {
2469 		/* same name, compare */
2470 		FMformat_order sub_result;
2471 		sub_result = FMformat_cmp(*subformats1,
2472 					  subformats2[i]);
2473 		if (sub_result == Format_Incompatible) {
2474 		    tmp_result = Format_Incompatible;
2475 		    goto free_lists;
2476 		}
2477 		if (sub_result != Format_Equal) {
2478 		    /* subformats are not equal! */
2479 		    if (tmp_result == Format_Equal) {
2480 			/* we thought they were equal before */
2481 			tmp_result = sub_result;
2482 		    } else if (tmp_result != sub_result) {
2483 			tmp_result = Format_Incompatible;
2484 			goto free_lists;
2485 		    }
2486 		}
2487 		break;
2488 	    }
2489 	    i++;
2490 	}
2491 	subformats1++;
2492     }
2493 
2494  free_lists:
2495     free_field_list(field_list1);
2496     free_field_list(field_list2);
2497     if (tmp_subformats) free(tmp_subformats);
2498     if (subformats2) free(subformats2);
2499     return tmp_result;
2500 }
2501 
2502 extern
2503 char *
2504 name_of_FMformat(format)
2505 FMFormat format;
2506 {
2507     return format->format_name;
2508 }
2509 
2510 extern FMStructDescList
format_list_of_FMFormat(FMFormat format)2511 format_list_of_FMFormat(FMFormat format)
2512 {
2513     return format->master_struct_list;
2514 }
2515 
2516 extern FMdata_type
2517 FMarray_str_to_data_type(str, element_count_ptr)
2518 const char *str;
2519 long *element_count_ptr;
2520 {
2521     FMdata_type ret_type;
2522     char field_type[1024];
2523     char *left_paren;
2524     long element_count = 1;
2525     int field_type_len;
2526 #ifdef MODULE
2527     char *temp_ptr = 0;
2528 #endif
2529     if ((left_paren = strchr(str, '[')) == NULL) {
2530 	*element_count_ptr = 1;
2531 	ret_type = FMstr_to_data_type(str);
2532 	return ret_type;
2533     }
2534     field_type_len = left_paren - str;
2535     strncpy(field_type, str, field_type_len);
2536     field_type[field_type_len] = 0;
2537     ret_type = FMstr_to_data_type(field_type);
2538     while (left_paren != NULL) {
2539 	char *end;
2540 	long tmp = strtol(left_paren + 1, &end, 10);
2541 	if (end == (left_paren + 1)) {
2542 	    /* non numeric, likely variable array */
2543 	    *element_count_ptr = -1;
2544 	    return ret_type;
2545 	}
2546 	if (tmp <= 0) {
2547 	    printf("FFS - Illegal static array size, %ld in \"%s\"\n",
2548 		   tmp, str);
2549 	    break;
2550 	}
2551 	if (*end != ']') {
2552 	    printf("FFS - unexpected character at: \"%s\" in \"%s\"\n",
2553 		   end, str);
2554 	    break;
2555 	}
2556 	element_count = element_count * tmp;
2557 	left_paren = strchr(end, '[');
2558     }
2559     *element_count_ptr = element_count;
2560     return ret_type;
2561 }
2562 
2563 extern int
2564 field_type_eq(str1, str2)
2565 const char *str1;
2566 const char *str2;
2567 {
2568     FMdata_type t1, t2;
2569     long t1_count, t2_count;
2570 
2571     t1 = FMarray_str_to_data_type(str1, &t1_count);
2572     t2 = FMarray_str_to_data_type(str2, &t2_count);
2573 
2574     if ((t1_count == -1) && (t2_count == -1)) {
2575 	/* variant array */
2576 	char *tmp_str1 = base_data_type(str1);
2577 	char *tmp_str2 = base_data_type(str2);
2578 
2579 	char *colon1 = strchr(tmp_str1, ':');
2580 	char *colon2 = strchr(tmp_str2, ':');
2581 	char *lparen1 = strchr(str1, '[');
2582 	char *lparen2 = strchr(str2, '[');
2583 	int count1 = 0;
2584 	int count2 = 0;
2585 
2586 	if (colon1 != NULL) {
2587 	    count1 = colon1 - tmp_str1;
2588 	} else {
2589 	    count1 = strlen(tmp_str1);
2590 	}
2591 	if (colon2 != NULL) {
2592 	    count2 = colon2 - tmp_str2;
2593 	} else {
2594 	    count2 = strlen(tmp_str2);
2595 	}
2596 	/*compare base type */
2597 	if (strncmp(tmp_str1, tmp_str2,(count1>count2)?count1:count2) != 0) {
2598 	    /* base types differ */
2599 	    return 0;
2600 	}
2601 	free(tmp_str1);
2602 	free(tmp_str2);
2603 	if ((lparen1 == NULL) || (lparen2 == NULL)) return -1;
2604 	return (strcmp(lparen1, lparen2) == 0);
2605     }
2606     return ((t1 == t2) && (t1_count == t2_count));
2607 }
2608 
2609 extern char *
2610 base_data_type(str)
2611 const char *str;
2612 {
2613     char *typ;
2614     while (isspace((int)*str) || (*str == '*') || (*str == '(')) {	/* skip preceeding space */
2615 	str++;
2616     }
2617     typ = strdup(str);
2618     if (strchr(typ, '[') != NULL) {	/* truncate at array stuff */
2619 	*strchr(typ, '[') = 0;
2620     }
2621     if (strchr(typ, ')') != NULL) {	/* truncate close parens */
2622 	*strchr(typ, ')') = 0;
2623     }
2624     return typ;
2625 }
2626 
2627 extern char *
2628 FMbase_type(field_type)
2629 const char *field_type;
2630 {
2631     return base_data_type(field_type);
2632 }
2633 
2634 extern FMdata_type
2635 FMstr_to_data_type(str)
2636 const char *str;
2637 {
2638     const char *end;
2639     while (isspace((int)*str) || (*str == '*') || (*str == '(')) {	/* skip preceeding space */
2640 	str++;
2641     }
2642     end = str + strlen(str) - 1;
2643     while (isspace((int)*end) || (*end == ')')) {  /* test trailing space */
2644 	end--;
2645     }
2646     end++;
2647     switch(str[0]) {
2648     case 'i': case 'I': /* integer */
2649 	if (((end - str) == 7) &&
2650 	    ((str[1] == 'n') || (str[1] == 'N')) &&
2651 	    ((str[2] == 't') || (str[2] == 'T')) &&
2652 	    ((str[3] == 'e') || (str[3] == 'E')) &&
2653 	    ((str[4] == 'g') || (str[4] == 'G')) &&
2654 	    ((str[5] == 'e') || (str[5] == 'E')) &&
2655 	    ((str[6] == 'r') || (str[6] == 'R'))) {
2656 	    return integer_type;
2657 	}
2658 	break;
2659     case 'f': case 'F': /* float */
2660 	if (((end - str) == 5) &&
2661 	    ((str[1] == 'l') || (str[1] == 'L')) &&
2662 	    ((str[2] == 'o') || (str[2] == 'O')) &&
2663 	    ((str[3] == 'a') || (str[3] == 'A')) &&
2664 	    ((str[4] == 't') || (str[4] == 'T'))) {
2665 	    return float_type;
2666 	}
2667 	break;
2668     case 'd': case 'D': /* double */
2669 	if (((end - str) == 6) &&
2670 	    ((str[1] == 'o') || (str[1] == 'O')) &&
2671 	    ((str[2] == 'u') || (str[2] == 'U')) &&
2672 	    ((str[3] == 'b') || (str[3] == 'B')) &&
2673 	    ((str[4] == 'l') || (str[4] == 'L')) &&
2674 	    ((str[5] == 'e') || (str[5] == 'E'))) {
2675 	    return float_type;
2676 	}
2677 	break;
2678     case 'c': case 'C': /* char */
2679 	if (((end - str) == 4) &&
2680 	    ((str[1] == 'h') || (str[1] == 'H')) &&
2681 	    ((str[2] == 'a') || (str[2] == 'A')) &&
2682 	    ((str[3] == 'r') || (str[3] == 'R'))) {
2683 	    return char_type;
2684 	}
2685 	break;
2686     case 's': case 'S': /* string */
2687 	if (((end - str) == 6) &&
2688 	    ((str[1] == 't') || (str[1] == 'T')) &&
2689 	    ((str[2] == 'r') || (str[2] == 'R')) &&
2690 	    ((str[3] == 'i') || (str[3] == 'I')) &&
2691 	    ((str[4] == 'n') || (str[4] == 'N')) &&
2692 	    ((str[5] == 'g') || (str[5] == 'G'))) {
2693 	    return string_type;
2694 	}
2695 	break;
2696     case 'e': case 'E': /* enumeration */
2697 	if (((end - str) == 11) &&
2698 	    ((str[1] == 'n') || (str[1] == 'N')) &&
2699 	    ((str[2] == 'u') || (str[2] == 'U')) &&
2700 	    ((str[3] == 'm') || (str[3] == 'M')) &&
2701 	    ((str[4] == 'e') || (str[4] == 'E')) &&
2702 	    ((str[5] == 'r') || (str[5] == 'R')) &&
2703 	    ((str[6] == 'a') || (str[6] == 'A')) &&
2704 	    ((str[7] == 't') || (str[7] == 'T')) &&
2705 	    ((str[8] == 'i') || (str[8] == 'I')) &&
2706 	    ((str[9] == 'o') || (str[9] == 'O')) &&
2707 	    ((str[10] == 'n') || (str[10] == 'N'))) {
2708 	    return enumeration_type;
2709 	}
2710 	break;
2711     case 'b': case 'B': /* boolean */
2712 	if (((end - str) == 7) &&
2713 	    ((str[1] == 'o') || (str[1] == 'O')) &&
2714 	    ((str[2] == 'o') || (str[2] == 'O')) &&
2715 	    ((str[3] == 'l') || (str[3] == 'L')) &&
2716 	    ((str[4] == 'e') || (str[4] == 'E')) &&
2717 	    ((str[5] == 'a') || (str[5] == 'A')) &&
2718 	    ((str[6] == 'n') || (str[6] == 'N'))) {
2719 	    return boolean_type;
2720 	}
2721 	break;
2722     case 'u': case 'U': /* unsigned integer */
2723 	if (((end - str) == 16) &&
2724 	    ((str[1] == 'n') || (str[1] == 'N')) &&
2725 	    ((str[2] == 's') || (str[2] == 'S')) &&
2726 	    ((str[3] == 'i') || (str[3] == 'I')) &&
2727 	    ((str[4] == 'g') || (str[4] == 'G')) &&
2728 	    ((str[5] == 'n') || (str[5] == 'N')) &&
2729 	    ((str[6] == 'e') || (str[6] == 'E')) &&
2730 	    ((str[7] == 'd') || (str[7] == 'D')) &&
2731 	    ((str[8] == ' ') || (str[8] == '	')) &&
2732 	    ((str[9] == 'i') || (str[9] == 'I')) &&
2733 	    ((str[10] == 'n') || (str[10] == 'N')) &&
2734 	    ((str[11] == 't') || (str[11] == 'T')) &&
2735 	    ((str[12] == 'e') || (str[12] == 'E')) &&
2736 	    ((str[13] == 'g') || (str[13] == 'G')) &&
2737 	    ((str[14] == 'e') || (str[14] == 'E')) &&
2738 	    ((str[15] == 'r') || (str[15] == 'R'))) {
2739 	    return unsigned_type;
2740 	} else 	if (((end - str) == 8) &&
2741 	    ((str[1] == 'n') || (str[1] == 'N')) &&
2742 	    ((str[2] == 's') || (str[2] == 'S')) &&
2743 	    ((str[3] == 'i') || (str[3] == 'I')) &&
2744 	    ((str[4] == 'g') || (str[4] == 'G')) &&
2745 	    ((str[5] == 'n') || (str[5] == 'N')) &&
2746 	    ((str[6] == 'e') || (str[6] == 'E')) &&
2747 	    ((str[7] == 'd') || (str[7] == 'D'))) {
2748 	    return unsigned_type;
2749 	}
2750 
2751 	break;
2752     }
2753     return unknown_type;
2754 }
2755 
2756 extern int
2757 IOget_array_size_dimen(str, fields, dimen, control_field)
2758 const char *str;
2759 FMFieldList fields;
2760 int dimen;
2761 int *control_field;
2762 {
2763     char *left_paren, *end;
2764     long static_size;
2765 
2766     *control_field = -1;
2767     if ((left_paren = strchr(str, '[')) == NULL) {
2768 	return 0;
2769     }
2770     while (dimen != 0) {
2771 	left_paren = strchr(left_paren + 1, '[');
2772 	if (left_paren == NULL) return 0;
2773 	dimen--;
2774     }
2775     static_size = strtol(left_paren + 1, &end, 0);
2776     if (left_paren + 1 == end) {
2777 	/* dynamic element */
2778 	char field_name[1024];
2779 	int count = 0;
2780 	int i = 0;
2781 	while (((left_paren+1)[count] != ']') &&
2782 	       ((left_paren+1)[count] != 0)) {
2783 	    field_name[count] = (left_paren+1)[count];
2784 	    count++;
2785 	}
2786 	field_name[count] = 0;
2787 	while (fields[i].field_name != NULL) {
2788 	    if (strcmp(field_name, fields[i].field_name) == 0) {
2789 		if ((FMstr_to_data_type(fields[i].field_type) ==
2790 		    integer_type) ||
2791 		    (FMstr_to_data_type(fields[i].field_type) ==
2792 		     unsigned_type)) {
2793 		    *control_field = i;
2794 		    return -1;
2795 		} else {
2796 		    fprintf(stderr, "Variable length control field \"%s\" not of integer type.\n", field_name);
2797 		    return 0;
2798 		}
2799 	    }
2800 	    i++;
2801 	}
2802 	fprintf(stderr, "Array dimension \"%s\" in type spec\"%s\" not recognized.\n",
2803 		field_name, str);
2804 	fprintf(stderr, "Dimension must be a field name (for dynamic arrays) or a positive integer.\n");
2805 	fprintf(stderr, "To use a #define'd value for the dimension, use the IOArrayDecl() macro.\n");
2806 	return -1;
2807     }
2808     if (*end != ']') {
2809 	fprintf(stderr, "Malformed array dimension, unexpected character '%c' in type spec \"%s\"\n",
2810 		*end, str);
2811 	fprintf(stderr, "Dimension must be a field name (for dynamic arrays) or a positive integer.\n");
2812 	fprintf(stderr, "To use a #define'd value for the dimension, use the IOArrayDecl() macro.\n");
2813 	return -1;
2814     }
2815     if (static_size <= 0) {
2816 	fprintf(stderr, "Non-positive array dimension %ld in type spec \"%s\"\n",
2817 		static_size, str);
2818 	fprintf(stderr, "Dimension must be a field name (for dynamic arrays) or a positive integer.\n");
2819 	fprintf(stderr, "To use a #define'd value for the dimension, use the IOArrayDecl() macro.\n");
2820 	return -1;
2821     }
2822     return static_size;
2823 }
2824 
2825 extern const char *
2826 data_type_to_str(dat)
2827 FMdata_type dat;
2828 {
2829     switch (dat) {
2830     case integer_type:
2831 	return "integer";
2832     case unsigned_type:
2833 	return "unsigned integer";
2834     case float_type:
2835 	return "float";
2836     case char_type:
2837 	return "char";
2838     case string_type:
2839 	return "string";
2840     case enumeration_type:
2841 	return "enumeration";
2842     case boolean_type:
2843 	return "boolean";
2844     default:
2845 	return "unknown_type";
2846     }
2847 }
2848 
2849 extern
2850 void
2851 get_FMformat_characteristics(format, ff, intf, column_major, pointer_size)
2852 FMFormat format;
2853 FMfloat_format *ff;
2854 FMinteger_format *intf;
2855 int *column_major;
2856 int *pointer_size;
2857 {
2858     if (WORDS_BIGENDIAN) {
2859 	if (format->byte_reversal) {
2860 	    *intf = Format_Integer_littleendian;
2861 	} else {
2862 	    *intf = Format_Integer_bigendian;
2863 	}
2864     } else{
2865 	if (format->byte_reversal) {
2866 	    *intf = Format_Integer_bigendian;
2867 	} else {
2868 	    *intf = Format_Integer_littleendian;
2869 	}
2870     }
2871 
2872     *ff = format->float_format;
2873     *column_major = format->column_major_arrays;
2874     *pointer_size = format->pointer_size;
2875 }
2876 
2877 extern
2878 int
2879 pointer_size_of_IOformat(format)
2880 FMFormat format;
2881 {
2882     return format->pointer_size;
2883 }
2884 
2885 extern
2886 FMContext
2887 fmc_of_IOformat(format)
2888 FMFormat format;
2889 {
2890     return format->context;
2891 }
2892 
2893 
2894 extern void
2895 dump_FMFormat(fmformat)
2896 FMFormat fmformat;
2897 {
2898     int index, i;
2899     printf("\tFormat \"%s\"; size = %d; Field_Count = %d; Endian = %d; Float format = %s;\n\t\t  Pointer size = %d; Column_major_arrays = %d; Alignment = %d; Index = %d, File Version = %d; ",
2900 	   fmformat->format_name, fmformat->record_length,
2901 	   fmformat->field_count, fmformat->byte_reversal,
2902 	   float_format_str[fmformat->float_format],
2903 	   fmformat->pointer_size, fmformat->column_major_arrays,
2904 	   fmformat->alignment, fmformat->format_index, fmformat->IOversion);
2905     printf("Server ID = ");
2906     for (i = 0; i < fmformat->server_ID.length; i++) {
2907 	printf("%02x", ((unsigned char *) fmformat->server_ID.value)[i]);
2908     }
2909     printf("\n");
2910     for (index = 0; index < fmformat->field_count; index++) {
2911 	printf("\t\t%s \"%s\"; size = %d; offset = %d\n",
2912 	       fmformat->field_list[index].field_name,
2913 	       fmformat->field_list[index].field_type,
2914 	       fmformat->field_list[index].field_size,
2915 	       fmformat->field_list[index].field_offset);
2916     }
2917     if (fmformat->subformats) {
2918 	int i = 0;
2919 	printf("SUBFORMATS : \n");
2920 	while(fmformat->subformats[i]) {
2921 	    if (fmformat->subformats[i] != fmformat) {
2922 		dump_FMFormat(fmformat->subformats[i]);
2923 	    }
2924 	    i++;
2925 	}
2926     }
2927     if (fmformat->opt_info == NULL) {
2928 	printf("\tNo Optional Format Info\n");
2929     } else {
2930 	int i = 0;
2931 	while (fmformat->opt_info[i].info_type != 0) {
2932 	    int typ = fmformat->opt_info[i].info_type;
2933 	    int j, text = 1, len = fmformat->opt_info[i].info_len;
2934 /*	    if (fmformat->opt_info[i].info_type == COMPAT_OPT_INFO) {
2935 		char *buffer = fmformat->opt_info[i].info_block;
2936 		int fid_length = ID_length[version_of_format_ID(buffer)];
2937 		printf("\t Opt Info Backwards Compatability\n");
2938 		printf("\t\t Compatible with format ");
2939 		print_server_ID((unsigned char *)buffer);
2940 		printf("\t\t through transform code:  \n");
2941 		printf("%s", buffer + fid_length);
2942 		i++;
2943 		continue;
2944 		}*/
2945 	    printf("\t Opt Info \"%c%c%c%c\", size %d, block begins:\n\t\t",
2946 		   (typ >> 24) & 0xff, (typ >> 16) & 0xff, (typ >> 8) & 0xff,
2947 		   typ & 0xff, len);
2948 	    for(j=0; ((j < 10) && (j < len)); j++) {
2949 		if (!isprint((int)((char*)fmformat->opt_info[i].info_block)[j])) text = 0;
2950 	    }
2951 	    if (text == 1) {
2952 		printf("\"");
2953 		for(j=0;((j < 50) && (j < len)); j++) {
2954 		    printf("%c", ((char*)fmformat->opt_info[i].info_block)[j]);
2955 		}
2956 		printf("\"\n");
2957 	    } else {
2958 		for(j=0;((j < 20) && (j < len)); j++) {
2959 		    printf("%02x ", ((unsigned char*)fmformat->opt_info[i].info_block)[j]);
2960 		}
2961 		printf("\n");
2962 	    }
2963 	    i++;
2964 	}
2965     }
2966 }
2967 
2968 extern void
2969 dump_FMFormat_as_XML(fmformat)
2970 FMFormat fmformat;
2971 {
2972     int index, i;
2973     printf("<FMFormat>\n");
2974     printf("<formatID>%d</formatID>\n", fmformat->format_index);
2975     printf("<formatName>%s</formatName>\n", fmformat->format_name);
2976     printf("<recordLength>%d</recordLength>\n", fmformat->record_length);
2977     printf("<fieldCount>%d</fieldCount>\n", fmformat->field_count);
2978     printf("<byteReversal>%d</byteReversal>\n", fmformat->byte_reversal);
2979     printf("<alignment>%d</alignment>\n", fmformat->alignment);
2980     printf("<columnMajorArrays>%d</columnMajorArrays>\n", fmformat->column_major_arrays);
2981     printf("<pointerSize>%d</pointerSize>\n", fmformat->pointer_size);
2982     printf("<IOversion>%d</IOversion>\n", fmformat->IOversion);
2983     printf("<serverID>");
2984     for (i = 0; i < fmformat->server_ID.length; i++) {
2985 	printf("%02x", ((unsigned char *) fmformat->server_ID.value)[i]);
2986     }
2987     printf("</serverID>\n");
2988     for (index = 0; index < fmformat->field_count; index++) {
2989 	printf("<IOField>\n");
2990 	printf("<fieldName>%s</fieldName>\n<fieldType>%s</fieldType>\n<fieldSize>%d</fieldSize>\n<fieldOffset>%d</fieldOffset>\n",
2991 	       fmformat->field_list[index].field_name,
2992 	       fmformat->field_list[index].field_type,
2993 	       fmformat->field_list[index].field_size,
2994 	       fmformat->field_list[index].field_offset);
2995     }
2996 
2997 }
2998 
2999 extern void
3000 add_ref_FMcontext(c)
3001 FMContext c;
3002 {
3003     c->ref_count++;
3004 }
3005 
3006 extern void
3007 free_FMcontext(c)
3008 FMContext c;
3009 {
3010     int i;
3011     c->ref_count--;
3012     if (c->ref_count != 0) return;
3013     for (i = 0; i < c->reg_format_count; i++) {
3014 	/* make sure all are freed, lingering refs will fail */
3015 	c->format_list[i]->ref_count = 1;
3016 	free_FMformat(c->format_list[i]);
3017     }
3018     free(c->format_list);
3019     free(c);
3020 }
3021 
3022 #define DUMP
3023 #ifdef DUMP
3024 static void
free_FMfield(fmformat,field,data,string_base,encode,verbose)3025 free_FMfield(fmformat, field, data, string_base, encode, verbose)
3026 FMFormat fmformat;
3027 int field;
3028 void *data;
3029 void *string_base;
3030 int encode;
3031 int verbose;
3032 {
3033     FMFieldList iofield = &fmformat->field_list[field];
3034     FMVarInfoList iovar = &fmformat->var_list[field];
3035     int field_offset = iofield->field_offset;
3036     int field_size = iofield->field_size;
3037     const char *field_type = iofield->field_type;
3038     int data_offset = field_offset;
3039     int byte_reversal = fmformat->byte_reversal;
3040     int dimension;
3041     FMFormat subformat = NULL;
3042     int sub_field_size;
3043 
3044     if ((iovar->string == 0) &&
3045 	(iovar->var_array == 0) &&
3046 	(index(iofield->field_type, '*') == NULL) &&
3047 	(iovar->data_type != unknown_type)) {
3048 	/* must be simple data type or array of simple data types */
3049 	return;
3050     }
3051     dimension = FMget_array_element_count(fmformat, iovar, data, encode);
3052     if ((iovar->var_array) || (index(iofield->field_type, '*') != NULL)) {
3053 	FMgetFieldStruct descr;  /* OK */
3054 	long tmp_offset;
3055 	descr.offset = iofield->field_offset;
3056 	descr.size = fmformat->pointer_size;
3057 	descr.data_type = integer_type;
3058 	descr.byte_swap = byte_reversal;
3059 
3060 	tmp_offset = get_FMlong(&descr, data);
3061 	data = (void *) tmp_offset;
3062 	data_offset = 0;
3063 	sub_field_size = iofield->field_size;
3064     } else {
3065 	sub_field_size = iofield->field_size;
3066     }
3067     if (!iovar->string) {
3068 	/* must be substructured */
3069 	char *typ = base_data_type(field_type);
3070 	subformat = fmformat->field_subformats[field];
3071 	free(typ);
3072     }
3073     if (iovar->string || (subformat && subformat->variant)){
3074 	for (; dimension > 0; dimension--) {
3075 	    if (iovar->string) {
3076 		char *tmp_str;
3077 		FMgetFieldStruct descr;  /* OK */
3078 		descr.offset = data_offset;
3079 		descr.size = fmformat->pointer_size;
3080 		descr.data_type = string_type;
3081 		descr.byte_swap = 0;
3082 		tmp_str = (char *) get_FMaddr(&descr, data, string_base, encode);
3083 		free(tmp_str);
3084 	    } else if (subformat != NULL) {
3085 		FMfree_var_rec_elements(subformat, (char*)data + data_offset);
3086 	    }
3087 	    data_offset += sub_field_size;
3088 	}
3089     }
3090     if ((iovar->var_array) || (index(iofield->field_type, '*') != NULL)) {
3091 	free(data);
3092     }
3093 }
3094 
3095 extern void
3096 FMfree_var_rec_elements(fmformat, data)
3097 FMFormat fmformat;
3098 void *data;
3099 {
3100     int index;
3101     if (fmformat->variant == 0) return;  /* nothing to do */
3102     for (index=0; index < fmformat->field_count; index++) {
3103 	free_FMfield(fmformat, index, data, data, 0, 1);
3104     }
3105 }
3106 
3107 extern long
FMget_array_element_count(FMFormat f,FMVarInfoList var,char * data,int encode)3108 FMget_array_element_count(FMFormat f, FMVarInfoList var, char *data, int encode)
3109 {
3110     int i;
3111     long count = 1;
3112     long tmp;
3113     for (i = 0; i < var->dimen_count; i++) {
3114 	if (var->dimens[i].static_size != 0) {
3115 	    count = count * var->dimens[i].static_size;
3116 	} else {
3117 	    int field = var->dimens[i].control_field_index;
3118 	    struct _FMgetFieldStruct tmp_src_spec;
3119 	    memset(&tmp_src_spec, 0, sizeof(tmp_src_spec));
3120 	    tmp_src_spec.size = f->field_list[field].field_size;
3121 	    tmp_src_spec.offset = f->field_list[field].field_offset;
3122 	    tmp_src_spec.data_type = integer_type;
3123 	    tmp_src_spec.byte_swap = f->byte_reversal;
3124 	    if (!encode) {
3125 		tmp_src_spec.byte_swap = 0;
3126 		tmp_src_spec.src_float_format = tmp_src_spec.target_float_format;
3127 	    }
3128 	    tmp = get_FMlong(&tmp_src_spec, data);
3129 	    count = count * tmp;
3130 	}
3131     }
3132     return count;
3133 }
3134 #endif
3135 
3136 static void
byte_swap(data,size)3137 byte_swap(data, size)
3138 char *data;
3139 int size;
3140 {
3141     int i;
3142     assert((size % 2) == 0);
3143     for (i = 0; i < size / 2; i++) {
3144 	char tmp = data[i];
3145 	data[i] = data[size - i - 1];
3146 	data[size - i - 1] = tmp;
3147     }
3148 }
3149 
3150 /*
3151  * ** Code below this point relates to operations to and from the format
3152  * server  */
3153 
3154 #define FILE_INT INT4
3155 
3156 static int
put_serverAtomicInt(fd,file_int_ptr,fmc)3157 put_serverAtomicInt(fd, file_int_ptr, fmc)
3158 void *fd;
3159 FILE_INT *file_int_ptr;
3160 FMContext fmc;
3161 {
3162 #if SIZEOF_INT == 4
3163     int tmp_value = *file_int_ptr;
3164     int junk_errno;
3165     char *junk_result_str;
3166     if (os_server_write_func(fd, &tmp_value, 4, &junk_errno, &junk_result_str) != 4) {
3167 	printf("SERVER WRITE FAILED, ERRNO = %d\n", junk_errno);
3168 	return 0;
3169     }
3170 #else
3171     Baaad shit;
3172 #endif
3173     return 1;
3174 }
3175 
3176 static int
get_serverAtomicInt(fd,file_int_ptr,byte_reversal)3177 get_serverAtomicInt(fd, file_int_ptr, byte_reversal)
3178 void *fd;
3179 FILE_INT *file_int_ptr;
3180 int byte_reversal;
3181 {
3182 #if SIZEOF_INT == 4
3183     int tmp_value;
3184     int junk_errno;
3185     char *junk_result_str;
3186     if (os_server_read_func(fd, &tmp_value, 4, &junk_errno, &junk_result_str) != 4) {
3187 	printf("SERVER READ FAILED, ERRNO = %d\n", junk_errno);
3188 
3189 	return 0;
3190     }
3191 #else
3192     Baaad shit;
3193 #endif
3194     if (byte_reversal)
3195 	byte_swap((char *) &tmp_value, 4);
3196     *file_int_ptr = tmp_value;
3197     return 1;
3198 }
3199 
3200 extern int
3201 unix_timeout_read_func(void *conn, void *buffer, int length,
3202 		       int *errno_p, char **result_p);
3203 
3204 extern int
3205 serverAtomicRead(fd, buffer, length)
3206 void *fd;
3207 void *buffer;
3208 int length;
3209 {
3210     char *junk_result_str = NULL;
3211     int junk_errno;
3212     int ret = os_server_read_func(fd, buffer, length, &junk_errno,
3213 				  &junk_result_str);
3214 
3215     if (getenv("BAD_CLIENT") && (drand48() < 0.0001)) sleep(600);
3216     if (ret != length) {
3217 	if (get_format_server_verbose()) {
3218 	    printf("server read error, return is %d, length %d, errno %d\n",
3219 		   ret, length, junk_errno);
3220 	    if (junk_result_str != NULL) {
3221 		printf("result_string is %s\n", junk_result_str);
3222 	    }
3223 	}
3224     }
3225     return ret;
3226 }
3227 
3228 extern int
3229 serverAtomicWrite(fd, buffer, length)
3230 void *fd;
3231 void *buffer;
3232 int length;
3233 {
3234     char *junk_result_str;
3235     int junk_errno;
3236     if (getenv("BAD_CLIENT") && (drand48() < 0.001)) sleep(600);
3237     return os_server_write_func(fd, buffer, length, &junk_errno,
3238 				&junk_result_str);
3239 }
3240 
3241 
3242 static void
provisional_use_warning(fd)3243 provisional_use_warning(fd)
3244 int fd;
3245 {
3246     static int warned = 0;
3247 
3248     if (warned)
3249 	return;
3250     warned++;
3251 
3252     fprintf(stderr, "The contacted format_server daemon allows only temporary use.\n");
3253     fprintf(stderr, " See http://www.cc.gatech.edu/systems/projects/MOSS/servers.html for more info.\n");
3254 }
3255 
3256 static void
dump_server_error(char * string,FMContext context)3257 dump_server_error(char *string, FMContext context)
3258 {
3259 /*    printf("%s\n", string); */
3260 }
3261 
3262 static int
server_register_format(fmc,format)3263 server_register_format(fmc, format)
3264 FMContext fmc;
3265 FMFormat format;
3266 {
3267     int tries = 0;
3268 
3269     if (fmc->master_context != NULL) {
3270 	return server_register_format((FMContext) fmc->master_context,
3271 				      format);
3272     }
3273   retry:
3274     if (tries++ > 2) {
3275 	dump_server_error("Failed to contact format server\n", fmc);
3276     }
3277     if (establish_server_connection_ptr == NULL) {
3278 	assert(0);
3279     }
3280     if (establish_server_connection_ptr(fmc, host_and_fallback) == 0) {
3281 	if (establish_server_connection_ptr(fmc, host_and_fallback) == 0) {
3282 	    dump_server_error("Failed to contact format server\n", fmc);
3283 	    return 0;
3284 	}
3285     } else {
3286 	struct {
3287 	    char reg[2];
3288 	    unsigned short len;
3289 	    } tmp = {{'f', 2}, 0 };	/* format reg, version 2 */
3290 	int ret;
3291 	int errno;
3292 	char *errstr;
3293 	char ret_info[2];
3294 
3295 	format_rep rep = format->server_format_rep;
3296 
3297 	tmp.len = rep->format_rep_length;
3298 	ret = os_server_write_func(fmc->server_fd, &tmp, sizeof(tmp),
3299 				   &errno, &errstr);
3300 	if (ret != sizeof(tmp))
3301 	    goto retry;
3302 
3303 	ret = os_server_write_func(fmc->server_fd,
3304 				   (char*) rep + sizeof(tmp.len),
3305 				   ntohs(rep->format_rep_length) - sizeof(tmp.len),
3306 				   &errno, &errstr);
3307 	if (ret != ntohs(rep->format_rep_length) - sizeof(tmp.len))
3308 	    goto retry;
3309 
3310 	if (serverAtomicRead(fmc->server_fd, &ret_info[0], 2) != 2) {
3311 	    dump_server_error("Read failed for format server.  Out of domain?\n",
3312 			      fmc);
3313 	    goto retry;
3314 	}
3315 	if (ret_info[0] == 'P') {
3316 	    provisional_use_warning((int) (long) fmc->server_fd);
3317 	} else {
3318 	    if (ret_info[0] != 'I') {
3319 		dump_server_error("Bad character from format server\n", fmc);
3320 		goto retry;
3321 	    }
3322 	}
3323 	format->server_ID.length = ret_info[1];
3324 	format->server_ID.value = malloc(format->server_ID.length);
3325 	if (serverAtomicRead(fmc->server_fd, (void *) format->server_ID.value,
3326 			     format->server_ID.length)
3327 	    != format->server_ID.length) {
3328 	    goto retry;
3329 	}
3330     }
3331 
3332     if (format->context != fmc) {
3333 	/* registering in a master, copy it down */
3334 	assert(0);
3335     }
3336     return 1;
3337 }
3338 
3339 static const char xchars[] = "0123456789abcdef";
3340 #define nibble2hex(val) (xchars[val & 0x0f])
3341 
3342 static char *
stringify_field_type(type,base_format,buffer,size)3343 stringify_field_type(type, base_format, buffer, size)
3344 const char *type;
3345 FMFormat base_format;
3346 char *buffer;
3347 int size;
3348 {
3349     char *index_start;
3350     unsigned char *server_ID;
3351 
3352     if (base_format == NULL) {
3353 	strcpy(buffer, type);
3354 	return (char*)type;
3355     }
3356     if (strchr(type, ':') != NULL) {
3357 	strcpy(buffer, type);
3358 	return (char*)type;		/* already stringified */
3359     }
3360     server_ID = (unsigned char *) base_format->server_ID.value;
3361 
3362     index_start = strchr(type, '[');
3363     assert(strlen(type) + 2 * base_format->server_ID.length + 2 <= (unsigned int) size);
3364     if (base_format->server_ID.length == 8) {
3365 	if (index_start == NULL) {
3366 	    sprintf(buffer, "%s:%02x%02x%02x%02x:%02x%02x%02x%02x", type,
3367 		  server_ID[0], server_ID[1], server_ID[2], server_ID[3],
3368 		 server_ID[4], server_ID[5], server_ID[6], server_ID[7]);
3369 	} else {
3370 	    *index_start = 0;
3371 	    sprintf(buffer, "%s:%02x%02x%02x%02x:%02x%02x%02x%02x[%s", type,
3372 		  server_ID[0], server_ID[1], server_ID[2], server_ID[3],
3373 		  server_ID[4], server_ID[5], server_ID[6], server_ID[7],
3374 		    (index_start + 1));
3375 	    *index_start = '[';
3376 	}
3377     } else {
3378 	int i;
3379 	char *end;
3380 	strcpy(buffer, type);
3381 	index_start = strchr(buffer, '[');
3382 	if (index_start != NULL)
3383 	    *index_start = 0;
3384 	strcat(buffer, ":");
3385 	end = buffer + strlen(buffer);
3386 	for (i = 0; i < base_format->server_ID.length; i++) {
3387 	    end[2 * i] = nibble2hex(base_format->server_ID.value[i] >> 4);
3388 	    end[2 * i + 1] = nibble2hex(base_format->server_ID.value[i]);
3389 	}
3390 	end[2 * i] = 0;
3391 	if (index_start != NULL) {
3392 	    index_start = strchr(type, '[');
3393 	    strcat(buffer, index_start);
3394 	}
3395     }
3396     return buffer;
3397 }
3398 
3399 extern int
3400 global_name_eq(format1, format2)
3401 FMFormat format1;
3402 FMFormat format2;
3403 {
3404     if (format1->server_ID.length != format2->server_ID.length)
3405 	return 0;
3406     return !memcmp(format1->server_ID.value, format2->server_ID.value,
3407 		   format1->server_ID.length);
3408 }
3409 
3410 extern
3411 char *
3412 global_name_of_FMFormat(format)
3413 FMFormat format;
3414 {
3415     int size = strlen(format->format_name) + 3 +
3416     2 * format->server_ID.length;
3417     char *buffer = malloc(size);
3418     return stringify_field_type(format->format_name, format, buffer, size);
3419 }
3420 
3421 static FMFormat
expand_subformat_from_rep_0(rep)3422 expand_subformat_from_rep_0(rep)
3423 struct _subformat_wire_format *rep;
3424 {
3425     FMFormat format = new_FMFormat();
3426     struct _field_wire_format_0 *fields;
3427     int field;
3428     UINT2 tmp;
3429     INT4 tmp2;
3430     int OUR_BYTE_ORDER = WORDS_BIGENDIAN;
3431     int OTHER_BYTE_ORDER = (WORDS_BIGENDIAN ? 0 : 1);
3432     int byte_reversal = ((rep->f.f0.record_byte_order & 0x1) != OUR_BYTE_ORDER);
3433 
3434     tmp = rep->f.f0.name_offset;
3435     if (byte_reversal) byte_swap((char*)&tmp, 2);
3436     format->format_name = malloc(strlen((char *) rep + tmp) + 1);
3437     strcpy(format->format_name, (char *) rep + tmp);
3438     tmp = rep->f.f0.field_count;
3439     if (byte_reversal) byte_swap((char*)&tmp, 2);
3440     format->field_count = tmp;
3441     format->variant = 0;
3442     tmp2 = rep->f.f0.record_length;
3443     if (byte_reversal) byte_swap((char*)&tmp2, 4);
3444     format->record_length = tmp2;
3445     format->byte_reversal = ((rep->f.f0.record_byte_order & 0x1) != OUR_BYTE_ORDER);
3446     format->pointer_size = rep->f.f0.pointer_size;
3447     tmp = rep->f.f0.floating_point_rep;
3448     if (byte_reversal) byte_swap((char*)&tmp, 2);
3449     format->float_format = (FMfloat_format) tmp;
3450     if (format->float_format == Format_Unknown) {
3451 	/* old data must be pure-endian IEEE 754*/
3452 	if (rep->f.f0.record_byte_order == 1) {
3453 	    /* bigendian */
3454 	    format->float_format = Format_IEEE_754_bigendian;
3455 	} else {
3456 	    format->float_format = Format_IEEE_754_littleendian;
3457 	}
3458     }
3459     format->field_list = (FMFieldList) malloc(sizeof(FMField) *
3460 				      (format->field_count + 1));
3461     format->var_list = NULL;
3462 
3463     if (rep->f.f0.server_rep_version == 0) {
3464 	fields = (struct _field_wire_format_0 *)
3465 	    ((char*)rep + sizeof(struct _subformat_wire_format_0));
3466     } else {
3467 	fields = (struct _field_wire_format_0 *)
3468 	    ((char*) rep + rep->f.f0.header_size);
3469     }
3470     for (field = 0; field < format->field_count; field++) {
3471 	FMField *fmfield = &(format->field_list[field]);
3472 	struct _field_wire_format_0 *wire = &fields[field];
3473 	tmp = wire->field_name_offset;
3474 	if (byte_reversal) byte_swap((char*)&tmp, 2);
3475 	fmfield->field_name = malloc(strlen((char *) rep + tmp) + 1);
3476 	strcpy((char*)fmfield->field_name, (char *) rep + tmp);
3477 	tmp = wire->field_type_offset;
3478 	if (byte_reversal) byte_swap((char*)&tmp, 2);
3479 	fmfield->field_type = malloc(strlen((char *) rep + tmp) + 1);
3480 	strcpy((char*)fmfield->field_type, (char *) rep + tmp);
3481 	fmfield->field_size = wire->field_size;
3482 	if (byte_reversal) byte_swap((char*)&fmfield->field_size, 4);
3483 	fmfield->field_offset = wire->field_offset;
3484 	if (byte_reversal) byte_swap((char*)&fmfield->field_offset, 4);
3485     }
3486     format->field_list[format->field_count].field_size = 0;
3487     format->field_list[format->field_count].field_offset = 0;
3488     format->field_list[format->field_count].field_name = NULL;
3489     format->field_list[format->field_count].field_type = NULL;
3490     format->column_major_arrays = 0;
3491     {
3492 	struct _opt_info_wire_format tmp_info;
3493 	int offset, info_count = 0;
3494 
3495 	format->alignment = rep->f.f0.alignment;
3496 	format->column_major_arrays = rep->f.f0.column_major_arrays;
3497 	tmp = rep->f.f0.opt_info_offset;
3498 	if (byte_reversal) byte_swap((char*)&tmp, 2);
3499 
3500 	if (tmp != 0) {
3501 	    offset = tmp;
3502 	    format->opt_info = malloc(sizeof(FMOptInfo));
3503 	    do {
3504 		memcpy(&tmp_info, offset + (char*) rep, sizeof(tmp_info));
3505 		if (tmp_info.info_type != 0) {
3506 		    format->opt_info =
3507 			realloc(format->opt_info,
3508 				sizeof(FMOptInfo) * (info_count + 2));
3509 		    tmp2 = tmp_info.info_type;
3510 		    if (byte_reversal) byte_swap((char*)&tmp2, 4);
3511 		    format->opt_info[info_count].info_type = tmp2;
3512 
3513 		    tmp2 = tmp_info.info_len;
3514 		    if (byte_reversal) byte_swap((char*)&tmp2, 4);
3515 		    format->opt_info[info_count].info_len = tmp2;
3516 
3517 		    tmp2 = tmp_info.info_offset;
3518 		    if (byte_reversal) byte_swap((char*)&tmp2, 4);
3519 		    format->opt_info[info_count].info_block =
3520 			(char*)rep + tmp2;
3521 		    info_count++;
3522 		    offset += sizeof(tmp_info);
3523 		}
3524 	    } while (tmp_info.info_type != 0);
3525 	    format->opt_info[info_count].info_type = 0;
3526 	    format->opt_info[info_count].info_len = 0;
3527 	    format->opt_info[info_count].info_block = 0;
3528 	}
3529     }
3530     return format;
3531 }
3532 
3533 
3534 static FMFormat
expand_subformat_from_rep_1(rep)3535 expand_subformat_from_rep_1(rep)
3536 struct _subformat_wire_format *rep;
3537 {
3538     FMFormat format = new_FMFormat();
3539     struct _field_wire_format_1 *fields;
3540     int field;
3541     UINT2 tmp;
3542     INT4 tmp2;
3543     int OUR_BYTE_ORDER = WORDS_BIGENDIAN;
3544     int OTHER_BYTE_ORDER = (WORDS_BIGENDIAN ? 0 : 1);
3545     int byte_reversal = ((rep->f.f1.record_byte_order & 0x1) != OUR_BYTE_ORDER);
3546 
3547     tmp2 = rep->f.f1.name_offset;
3548     if (byte_reversal) byte_swap((char*)&tmp2, 4);
3549     format->format_name = malloc(strlen((char *) rep + tmp2) + 1);
3550     strcpy(format->format_name, (char *) rep + tmp2);
3551     tmp2 = rep->f.f1.field_count;
3552     if (byte_reversal) byte_swap((char*)&tmp2, 4);
3553     format->field_count = tmp2;
3554     format->variant = 0;
3555     tmp2 = rep->f.f1.record_length;
3556     if (byte_reversal) byte_swap((char*)&tmp2, 4);
3557     format->record_length = tmp2;
3558     format->byte_reversal = ((rep->f.f1.record_byte_order & 0x1) != OUR_BYTE_ORDER);
3559     format->pointer_size = rep->f.f1.pointer_size;
3560     tmp = rep->f.f1.floating_point_rep;
3561     if (byte_reversal) byte_swap((char*)&tmp, 2);
3562     format->float_format = (FMfloat_format) tmp;
3563     if (format->float_format == Format_Unknown) {
3564 	/* old data must be pure-endian IEEE 754*/
3565 	if (rep->f.f1.record_byte_order == 1) {
3566 	    /* bigendian */
3567 	    format->float_format = Format_IEEE_754_bigendian;
3568 	} else {
3569 	    format->float_format = Format_IEEE_754_littleendian;
3570 	}
3571     }
3572     format->field_list = (FMFieldList) malloc(sizeof(FMField) *
3573 				      (format->field_count + 1));
3574     format->var_list = NULL;
3575 
3576     if (rep->f.f1.server_rep_version == 0) {
3577 	fields = (struct _field_wire_format_1 *)
3578 	    ((char*)rep + sizeof(struct _subformat_wire_format_1));
3579     } else {
3580 	fields = (struct _field_wire_format_1 *)
3581 	    ((char*) rep + rep->f.f1.header_size);
3582     }
3583     for (field = 0; field < format->field_count; field++) {
3584 	FMField *fmfield = &(format->field_list[field]);
3585 	struct _field_wire_format_1 *wire = &fields[field];
3586 	tmp2 = wire->field_name_offset;
3587 	if (byte_reversal) byte_swap((char*)&tmp2, 4);
3588 	fmfield->field_name = malloc(strlen((char *) rep + tmp2) + 1);
3589 	strcpy((char*)fmfield->field_name, (char *) rep + tmp2);
3590 	tmp2 = wire->field_type_offset;
3591 	if (byte_reversal) byte_swap((char*)&tmp2, 4);
3592 	fmfield->field_type = malloc(strlen((char *) rep + tmp2) + 1);
3593 	strcpy((char*)fmfield->field_type, (char *) rep + tmp2);
3594 	fmfield->field_size = wire->field_size;
3595 	if (byte_reversal) byte_swap((char*)&fmfield->field_size, 4);
3596 	fmfield->field_offset = wire->field_offset;
3597 	if (byte_reversal) byte_swap((char*)&fmfield->field_offset, 4);
3598     }
3599     format->field_list[format->field_count].field_size = 0;
3600     format->field_list[format->field_count].field_offset = 0;
3601     format->field_list[format->field_count].field_name = NULL;
3602     format->field_list[format->field_count].field_type = NULL;
3603     format->column_major_arrays = 0;
3604     {
3605 	struct _opt_info_wire_format tmp_info;
3606 	int offset, info_count = 0;
3607 
3608 	format->alignment = rep->f.f1.alignment;
3609 	format->column_major_arrays = rep->f.f1.column_major_arrays;
3610 	tmp = rep->f.f1.opt_info_offset;
3611 	if (byte_reversal) byte_swap((char*)&tmp, 2);
3612 
3613 	if (tmp != 0) {
3614 	    offset = tmp;
3615 	    format->opt_info = malloc(sizeof(FMOptInfo));
3616 	    do {
3617 		memcpy(&tmp_info, offset + (char*) rep, sizeof(tmp_info));
3618 		if (tmp_info.info_type != 0) {
3619 		    format->opt_info =
3620 			realloc(format->opt_info,
3621 				sizeof(FMOptInfo) * (info_count + 2));
3622 		    tmp2 = tmp_info.info_type;
3623 		    if (byte_reversal) byte_swap((char*)&tmp2, 4);
3624 		    format->opt_info[info_count].info_type = tmp2;
3625 
3626 		    tmp2 = tmp_info.info_len;
3627 		    if (byte_reversal) byte_swap((char*)&tmp2, 4);
3628 		    format->opt_info[info_count].info_len = tmp2;
3629 
3630 		    tmp2 = tmp_info.info_offset;
3631 		    if (byte_reversal) byte_swap((char*)&tmp2, 4);
3632 		    format->opt_info[info_count].info_block =
3633 			(char*)rep + tmp2;
3634 		    info_count++;
3635 		    offset += sizeof(tmp_info);
3636 		}
3637 	    } while (tmp_info.info_type != 0);
3638 	    format->opt_info[info_count].info_type = 0;
3639 	    format->opt_info[info_count].info_len = 0;
3640 	    format->opt_info[info_count].info_block = 0;
3641 	}
3642     }
3643     return format;
3644 }
3645 
3646 
3647 static FMFormat
expand_subformat_from_rep(rep)3648 expand_subformat_from_rep(rep)
3649 struct _subformat_wire_format *rep;
3650 {
3651     if (rep->f.f0.server_rep_version == 0) {
3652 	return expand_subformat_from_rep_0(rep);
3653     } else if (rep->f.f0.server_rep_version == 1) {
3654 	return expand_subformat_from_rep_1(rep);
3655     } else {
3656 	return NULL;
3657     }
3658 }
3659 
3660 extern FMFormat
3661 expand_format_from_rep(rep)
3662 format_rep rep;
3663 {
3664     int format_count;
3665     FMFormat top_format;
3666     FMFormat *subformats;
3667     FMStructDescList master_struct_list;
3668     int i;
3669 
3670     struct _subformat_wire_format *subrep = (struct _subformat_wire_format*)
3671 	(((char*)rep ) + sizeof(struct _format_wire_format_1));
3672     format_count = rep->subformat_count;
3673     top_format = expand_subformat_from_rep(subrep);
3674     subformats = malloc(sizeof(subformats[0]) * (format_count + 1));
3675     master_struct_list = malloc(sizeof(master_struct_list[0]) * (format_count+2));
3676     for (i = 0; i < format_count; i++) {
3677 	UINT4 last_subrep_size = ntohs(subrep->f.f1.subformat_rep_length);
3678 	if (subrep->f.f1.server_rep_version > 0) {
3679 	    last_subrep_size += (ntohs(subrep->f.f1.top_bytes_subformat_rep_length) << 16);
3680 	}
3681 	subrep = (struct _subformat_wire_format*)(((char*)subrep) + last_subrep_size);
3682 	subformats[i] = expand_subformat_from_rep(subrep);
3683 	master_struct_list[i+1].format_name = subformats[i]->format_name;
3684 	master_struct_list[i+1].field_list = subformats[i]->field_list;
3685 	master_struct_list[i+1].struct_size = subformats[i]->record_length;
3686 	master_struct_list[i+1].opt_info = NULL;
3687     }
3688     subformats[format_count] = NULL;
3689     master_struct_list[format_count+1].format_name = NULL;
3690     master_struct_list[format_count+1].field_list = NULL;
3691     master_struct_list[format_count+1].struct_size = 0;
3692     master_struct_list[format_count+1].opt_info = NULL;
3693     master_struct_list[0].format_name = top_format->format_name;
3694     master_struct_list[0].field_list = top_format->field_list;
3695     master_struct_list[0].struct_size = top_format->record_length;
3696     master_struct_list[0].opt_info = NULL;
3697     top_format->subformats = subformats;
3698     top_format->server_format_rep = rep;
3699     top_format->master_struct_list = master_struct_list;
3700     return top_format;
3701 }
3702 
3703 
3704 static void
fill_derived_format_values(FMContext fmc,FMFormat format)3705 fill_derived_format_values(FMContext fmc, FMFormat format)
3706 {
3707     FMFieldList field_list;
3708     int field;
3709     format->context = fmc;
3710     format->variant = 0;
3711     format->recursive = 0;
3712     field_list = format->field_list;
3713     for (field = 0; field < format->field_count; field++) {
3714 	int field_size = 0;
3715 	if (is_var_array_field(field_list, field) == 1) {
3716 	    /* variant array, real_field_size is format->pointer_size */
3717 	    field_size = format->pointer_size;
3718 	} else {
3719 	    long elements = 1;
3720 	    FMdata_type base_type;
3721 	    base_type = FMarray_str_to_data_type(field_list[field].field_type,
3722 					       &elements);
3723 	    if ((base_type != unknown_type) &&
3724 		(field_list[field].field_size > 16)) {
3725 		fprintf(stderr, "Field size for field %s in format %s is large, check to see if it is valid.\n",
3726 			field_list[field].field_name, format->format_name);
3727 	    }
3728 	    field_size = field_list[field].field_size * elements;
3729 	}
3730     }
3731     generate_var_list(format, format->subformats);
3732     for (field = 0; field < format->field_count; field++) {
3733 	if (format->var_list[field].string == 1) {
3734 	    format->variant = 1;
3735 	} else {
3736 	    char *base_type =
3737 		base_data_type(field_list[field].field_type);
3738 	    FMFormat subformat = NULL;
3739 	    FMTypeDesc* desc = NULL;
3740 
3741 	    /* if field is of another record format, fill that in */
3742 	    if (FMstr_to_data_type(base_type) == unknown_type) {
3743 	        FMFormat *subformats = format->subformats;
3744 		while (subformats && subformats[0]) {
3745 		    if (strcmp(base_type, subformats[0]->format_name) == 0) {
3746 
3747 		        format->field_subformats[field] = subformats[0];
3748 		    }
3749 		    subformats++;
3750 		}
3751 		subformat = format->field_subformats[field];
3752 	    }
3753 	    if (format->var_list[field].var_array == 1) {
3754 		/* got a variant array */
3755 		format->variant = 1;
3756 	    } else {
3757 		/* if field is variant by its subformat being variant */
3758 		if (subformat != NULL) {
3759 		    format->variant |= subformat->variant;
3760 		}
3761 	    }
3762 	    desc = &format->var_list[field].type_desc;
3763 	    while (desc != NULL) {
3764 		if (desc->type == FMType_pointer) format->variant = 1;
3765 		desc = desc->next;
3766 	    }
3767 	    free(base_type);
3768 	}
3769     }
3770 }
3771 
3772 extern void
3773 add_format_to_iofile(fmc, format, id_size, id_buffer, index)
3774 FMContext fmc;
3775 FMFormat format;
3776 int id_size;
3777 void *id_buffer;
3778 int index;
3779 {
3780     int subformat_count = 0;
3781     int i, field;
3782 
3783     if (get_format_server_verbose()) {
3784 	printf("Entering format %s (%lx) into context %lx ",
3785 	       format->format_name, (long)format,
3786 	       (long)fmc);
3787 	print_server_ID(id_buffer);
3788     }
3789     while (format->subformats && format->subformats[subformat_count]) {
3790 	format->subformats[subformat_count]->subformats = format->subformats;
3791 	subformat_count++;
3792     }
3793     if (id_size) {
3794 	format->server_ID.length = id_size;
3795 	format->server_ID.value = malloc(id_size);
3796 	memcpy(format->server_ID.value, id_buffer, id_size);
3797     }
3798 
3799     fill_derived_format_values(fmc, format);
3800     for (i=0; i < subformat_count; i++) {
3801 	fill_derived_format_values(fmc, format->subformats[i]);
3802     }
3803     if (fmc->reg_format_count == fmc->format_list_size) {
3804 	expand_FMContext(fmc);
3805     }
3806     if (index == -1) {
3807 	index = fmc->reg_format_count++;
3808     } else {
3809  	if (fmc->format_list[index] != NULL) {
3810   	    free_FMformat(fmc->format_list[index]);
3811   	}
3812   	if (index > fmc->reg_format_count) {
3813   	    printf("Internal error. skipped format ids format %s.\n",
3814 		   format->format_name);
3815 	    return;
3816   	}
3817   	if (index == fmc->reg_format_count) {
3818  	    /* new format came in */
3819   	    fmc->reg_format_count++;
3820   	}
3821     }
3822     fmc->format_list[index] = format;
3823     format->format_index = index;
3824     topo_order_subformats(format, subformat_count);
3825     /* bubble up the variant flags */
3826     for (i= 0; i < subformat_count; i++) {
3827 	int j;
3828 	for (j= 0; j < subformat_count; j++) {
3829 	    FMFormat iof = format->subformats[j];
3830 	    for (field = 0; field < iof->field_count; field++) {
3831 		FMFormat subformat = iof->field_subformats[field];
3832 		if (subformat != NULL) {
3833 		    iof->variant |= subformat->variant;
3834 		}
3835 	    }
3836 	}
3837     }
3838     for (field = 0; field < format->field_count; field++) {
3839 	FMFormat subformat = format->field_subformats[field];
3840 	if (subformat != NULL) {
3841 	    format->variant |= subformat->variant;
3842 	}
3843     }
3844 }
3845 
3846 int
FMcontext_get_format_server_identifier(FMContext fmc)3847 FMcontext_get_format_server_identifier(FMContext fmc)
3848 {
3849     if (fmc->self_server == 1) {
3850 	return -1;
3851     }
3852     if (fmc->format_server_identifier == 0) {
3853 	srand48(getpid());
3854 	if (establish_server_connection_ptr(fmc, host_and_fallback) == 0) {
3855 	    if (establish_server_connection_ptr(fmc, host_and_fallback) == 0) {
3856 		printf("Failed to contact format server\n");
3857 	    }
3858 	}
3859     }
3860     return fmc->format_server_identifier;
3861 }
3862 
3863 static FMFormat
server_get_format(iocontext,buffer)3864 server_get_format(iocontext, buffer)
3865 FMContext iocontext;
3866 void *buffer;
3867 {
3868     FMContext fmc = (FMContext) iocontext;
3869     FMFormat format = NULL;
3870     int id_size = 8;
3871     int retry_count = 0;
3872 
3873   retry:
3874     if (retry_count > 3)
3875 	return NULL;
3876     if (establish_server_connection_ptr == NULL) {
3877 	assert(0);
3878     }
3879     if (establish_server_connection_ptr(fmc, host_and_fallback) == 0) {
3880 	if (establish_server_connection_ptr(fmc, host_and_fallback) == 0) {
3881 	    printf("Failed to contact format server\n");
3882 	    exit(1);
3883 	}
3884     } else {
3885 	char get[2] =
3886 	{'g', 8};		/* format get, size */
3887 	char block_version;
3888 	UINT2 length;
3889 	char return_char = 0;
3890 	format_rep rep;
3891 
3892 	if (version_of_format_ID(buffer) < sizeof(ID_length)) {
3893 	    id_size = get[1] = ID_length[version_of_format_ID(buffer)];
3894 	}
3895 	if (serverAtomicWrite(fmc->server_fd, &get[0], 2) != 2) {
3896 	    perror("write to Format server failed");
3897 	    return NULL;
3898 	}
3899 	if (serverAtomicWrite(fmc->server_fd, buffer, id_size) != id_size) {
3900 	    perror("write to Format server failed");
3901 	    return NULL;
3902 	}
3903 	if (serverAtomicRead(fmc->server_fd, &return_char, 1) != 1) {
3904 	    if (get_format_server_verbose()) {
3905 		printf("Retrying because of failed read\n");
3906 	    }
3907 	    retry_count++;
3908 	    goto retry;
3909 	}
3910 	if (return_char == 'P') {
3911 	    provisional_use_warning((int) (long) fmc->server_fd);
3912 	    if (serverAtomicRead(fmc->server_fd, &return_char, 1) != 1) {
3913 		if (get_format_server_verbose()) {
3914 		    printf("Retrying because of failed read\n");
3915 		}
3916 		retry_count++;
3917 		goto retry;
3918 	    }
3919 	}
3920 	if (return_char != 'f') {
3921 	    if (get_format_server_verbose()) {
3922 		printf("Retrying because of failed read\n");
3923 	    }
3924 	    retry_count++;
3925 	    goto retry;
3926 	}
3927 	if (serverAtomicRead(fmc->server_fd, &block_version, 1) != 1) {
3928 	    if (get_format_server_verbose()) {
3929 		printf("Retrying because of failed read\n");
3930 	    }
3931 	    retry_count++;
3932 	    goto retry;
3933 	}
3934 	if (block_version != 1) {
3935 	    if (get_format_server_verbose()) {
3936 		fprintf(stderr, "Unknown version \"%d\"in block registration\n", block_version);
3937 	    }
3938 	    return NULL;
3939 	}
3940 	if (serverAtomicRead(fmc->server_fd, &length, sizeof(length)) !=
3941 	    sizeof(length)) {
3942 	    if (get_format_server_verbose()) {
3943 		printf("Retrying because of failed read\n");
3944 	    }
3945 	    retry_count++;
3946 	    goto retry;
3947 	}
3948 	length = ntohs(length);
3949 	if (length == 0) {
3950 	    format = NULL;
3951 	} else {
3952 	    rep = malloc(length);
3953 	    rep->format_rep_length = htons((short)length);
3954 	    if (serverAtomicRead(fmc->server_fd, ((char *) rep) + sizeof(length),
3955 		 length - sizeof(length)) != (length - sizeof(length))) {
3956 		if (get_format_server_verbose()) {
3957 		    printf("Retrying because of failed read\n");
3958 		}
3959 		retry_count++;
3960 		goto retry;
3961 	    }
3962 	    format = expand_format_from_rep(rep);
3963 
3964 	}
3965     }
3966     if (format == NULL)
3967 	return NULL;
3968     add_format_to_iofile(fmc, format, id_size, buffer, -1);
3969     return format;
3970 }
3971 
3972 extern void
3973 server_get_server_ID(fd, server_ID)
3974 void *fd;
3975 void *server_ID;
3976 {
3977     int id_size = 8;
3978 
3979     serverAtomicRead(fd, server_ID, id_size);
3980 }
3981 
3982 extern void
stringify_server_ID(unsigned char * ID,char * buffer,int len)3983 stringify_server_ID(unsigned char *ID, char *buffer, int len)
3984 {
3985     int id_size = 8;
3986     int point = 0;
3987     int i;
3988     switch (version_of_format_ID(ID)) {
3989     case 0:
3990 	if (len < id_size * 2) break;
3991 	for (i = 0; i < id_size; i++) {
3992 	    point += sprintf(&buffer[point], "%2x", ID[i]);
3993 	}
3994 	break;
3995     case 1:{
3996 	version_1_format_ID id1;
3997 	memcpy(&id1, ID, 10);
3998 	if (len < 3+3+6+10+6+50) /* approx size */ return;
3999 	sprintf(buffer, "<ID ver=%d, salt %d, port %d, IP_addr %x, formatID %d>\n",
4000 	       id1.version, id1.salt, ntohs(id1.port),
4001 	       ntohl(id1.IP_addr), ntohs(id1.format_identifier));
4002 	    break;
4003 	}
4004     case 2:{
4005 	version_2_format_ID *id2 = (version_2_format_ID*)ID;
4006 	if (len < 3+3+6+10+6+50) /* approx size */ return;
4007 	sprintf(buffer, "<ID ver=%d, unused %d, rep_len %d, hash1 %x, hash2 %x>\n",
4008 	       id2->version, id2->unused, ntohs(id2->rep_len) << 2,
4009 	       ntohl(id2->hash1), ntohl(id2->hash2));
4010 	    break;
4011 	}
4012     default:
4013 	if (len < 30) return;
4014 	sprintf(buffer, "<Unknown format version %d\n",
4015 	       *((unsigned char *) ID));
4016 	break;
4017     }
4018 }
4019 
4020 extern void
4021 print_server_ID(ID)
4022 unsigned char *ID;
4023 {
4024     char buffer[256];
4025     stringify_server_ID(ID, buffer, sizeof(buffer));
4026     printf("%s", buffer);
4027 }
4028 
4029 extern void
fprint_server_ID(void * file,unsigned char * ID)4030 fprint_server_ID(void *file, unsigned char *ID)
4031 {
4032     char buffer[256];
4033     stringify_server_ID(ID, buffer, sizeof(buffer));
4034     fprintf((FILE*)file, "%s", buffer);
4035 }
4036 
4037 extern void
4038 print_format_ID(format)
4039 FMFormat format;
4040 {
4041     print_server_ID( (unsigned char *) format->server_ID.value);
4042 }
4043 
4044 #ifdef NOT_DEF
4045 static int
get_host_IP_format_ID(format_ID)4046 get_host_IP_format_ID(format_ID)
4047 void *format_ID;
4048 {
4049     switch (version_of_format_ID(format_ID)) {
4050     case 0:
4051     case 2:
4052 	return 0;
4053 	break;
4054     case 1:{
4055 	    version_1_format_ID *id1 = (version_1_format_ID *) format_ID;
4056 	    int tmp;
4057 	    memcpy(&tmp, &id1->IP_addr, 4);
4058 	    return ntohl(tmp);
4059 	    break;
4060 	}
4061     default:
4062 	printf("<Unknown format version %d\n",
4063 	       *((unsigned char *) format_ID));
4064 	break;
4065     }
4066     return 0;
4067 }
4068 #endif
4069 
4070 extern int
4071 get_rep_len_format_ID(format_ID)
4072 void *format_ID;
4073 {
4074     switch (version_of_format_ID(format_ID)) {
4075     case 2:{
4076 	    version_2_format_ID *id2 = (version_2_format_ID *) format_ID;
4077 	    short tmp;
4078 	    memcpy(&tmp, &id2->rep_len, 2);
4079 		tmp = ntohs(tmp);
4080 	    return tmp << 2;
4081 	    break;
4082 	}
4083     case 0:
4084     case 1:
4085 	printf("Format version %d has no size information \n",
4086 	       *((unsigned char *) format_ID));
4087 	break;
4088     default:
4089 	printf("Unknown format version %d\n",
4090 	       *((unsigned char *) format_ID));
4091 	break;
4092     }
4093     return 0;
4094 }
4095 
4096 #ifdef NOT_DEF
4097 static int
get_host_port_format_ID(format_ID)4098 get_host_port_format_ID(format_ID)
4099 void *format_ID;
4100 {
4101     switch (version_of_format_ID(format_ID)) {
4102     case 0:
4103     case 2:
4104 	return 0;
4105 	break;
4106     case 1:{
4107 	    version_1_format_ID *id1 = (version_1_format_ID *) format_ID;
4108 	    short port;
4109 	    memcpy(&port, &id1->port, 2);
4110 	    return ntohs(port);
4111 	    break;
4112 	}
4113     default:
4114 	printf("<Unknown format version %d\n",
4115 	       *((unsigned char *) format_ID));
4116 	break;
4117     }
4118     /* not reached */
4119     return 0;
4120 }
4121 #endif
4122 
4123 #define CURRENT_PROTOCOL_VERSION 3
4124 
4125 /* write header information to the format server */
4126 extern int
4127 server_write_header(fmc, enc_len, enc_buffer)
4128 FMContext fmc;
4129 int enc_len;
4130 unsigned char *enc_buffer;
4131 {
4132     FILE_INT magic = MAGIC_NUMBER + CURRENT_PROTOCOL_VERSION;
4133     FILE_INT server_pid;
4134     if (enc_len == 0) {
4135 	put_serverAtomicInt(fmc->server_fd, &magic, fmc);
4136 	put_serverAtomicInt(fmc->server_fd, &enc_len, fmc);
4137     } else {
4138 	FILE_INT key_len = enc_len;
4139 	put_serverAtomicInt(fmc->server_fd, &magic, fmc);
4140 	put_serverAtomicInt(fmc->server_fd, &key_len, fmc);
4141 	serverAtomicWrite(fmc->server_fd, enc_buffer, key_len);
4142     }
4143     get_serverAtomicInt(fmc->server_fd, &magic, 0);
4144     get_serverAtomicInt(fmc->server_fd, &server_pid, 0);
4145     get_serverAtomicInt(fmc->server_fd, &fmc->format_server_identifier, 0);
4146     if ((fmc->server_pid != 0) && (fmc->server_pid != server_pid)) {
4147 	return 0;
4148     } else {
4149 	fmc->server_pid = server_pid;
4150     }
4151     if (magic != MAGIC_NUMBER) {
4152 	if (magic == REVERSE_MAGIC_NUMBER) {
4153 	    fmc->server_byte_reversal = 1;
4154 	} else {
4155 	    /* close client */
4156 	    return -1;
4157 	}
4158     }
4159     return 1;
4160 }
4161 
4162 extern int
version_of_format_ID(void * server_ID)4163 version_of_format_ID(void *server_ID)
4164 {
4165     /* format ID is at least 64 bits */
4166     char *char_ID = (char *) server_ID;
4167     if (server_ID == NULL) return -1;
4168     if ((char_ID[4] == 0) && (char_ID[5] == 0) &&
4169 	(char_ID[6] == 0) && (char_ID[7] == 0)) {
4170 	/* version 0 format_IDs have no version info, but second int is
4171 	 * zero */
4172 	return 0;
4173     } else {
4174 	/* first byte is version ID */
4175 	return *((char *) server_ID);
4176     }
4177 }
4178 
4179 extern char *
4180 get_server_rep_FMformat(format, rep_length)
4181 FMFormat format;
4182 int *rep_length;
4183 {
4184     if (format->server_format_rep == NULL) {
4185 	format->server_format_rep =
4186 	    build_server_format_rep(format);
4187     }
4188     *rep_length = ntohs(format->server_format_rep->format_rep_length);
4189     if (format->server_format_rep->server_rep_version > 0) {
4190 	*rep_length += (ntohs(format->server_format_rep->top_bytes_format_rep_length) << 16);
4191     }
4192     return (char*)format->server_format_rep;
4193 }
4194 
4195 extern char *
4196 get_server_ID_FMformat(format, id_length)
4197 FMFormat format;
4198 int *id_length;
4199 {
4200     *id_length = format->server_ID.length;
4201     return format->server_ID.value;
4202 }
4203 
4204 extern FMContext
4205 FMContext_from_FMformat(format)
4206 FMFormat format;
4207 {
4208     return format->context;
4209 }
4210 
4211 
4212 extern FMFormat
4213 load_external_format_FMcontext(iocontext, server_id, id_size, server_rep)
4214 FMContext iocontext;
4215 char *server_id;
4216 int id_size;
4217 char *server_rep;
4218 {
4219     FMFormat format = get_local_format_IOcontext(iocontext, server_id);
4220 
4221     if (format != NULL) {
4222 	if (get_format_server_verbose()) {
4223 	    printf("Load external format already exists  - ");
4224 	    print_server_ID((void*)server_id);
4225 	}
4226 	/* format is already here */
4227 	free(server_rep);
4228 	return format;
4229     }
4230     format = expand_format_from_rep((format_rep)server_rep);
4231 
4232     if (format == NULL) {
4233 	if (get_format_server_verbose()) {
4234 	    printf("Couldn't expand external format  - ");
4235 	    print_server_ID((void*)server_id);
4236 	}
4237 	free(server_rep);
4238 	return NULL;
4239     }
4240     add_format_to_iofile((FMContext)iocontext, format, id_size, server_id, -1);
4241     return format;
4242 }
4243 
4244 extern int
format_server_restarted(FMContext context)4245 format_server_restarted(FMContext context)
4246 {
4247     int ret = establish_server_connection_ptr((FMContext)context, host_and_fallback);
4248     return (ret == 0);
4249 }
4250 
4251 extern void
set_array_order_FMContext(FMContext iofile,int column_major)4252 set_array_order_FMContext(FMContext iofile, int column_major)
4253 {
4254     iofile->native_column_major_arrays = column_major;
4255 }
4256 
4257