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