00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 #ifndef lint
00084 #define lint
00085 static char copyright[] =
00086 "@(#) Copyright (c) 1995 The Board of Trustees of the University of Illinois.\
00087 \nAll rights reserved.\n";
00088 #endif
00089
00090
00091 #define MD_DEBUG_MACROS
00092
00093 #include <stdio.h>
00094 #include <stdlib.h>
00095 #include <string.h>
00096 #include "md.h"
00097 #include <stdarg.h>
00098 #include <ctype.h>
00099 #include "l_alloc_new.h"
00100
00101
00102
00103
00104
00105 typedef struct MD_Buf
00106 {
00107 char *buf;
00108 int buf_size;
00109 } MD_Buf;
00110
00111
00112 static L_Alloc_Pool *MD_Buf_pool = NULL;
00113
00114
00115 static L_Alloc_Pool *MD_pool = NULL;
00116 static L_Alloc_Pool *MD_Symbol_Table_pool = NULL;
00117 static L_Alloc_Pool *MD_Symbol_pool = NULL;
00118 static L_Alloc_Pool *MD_Section_pool = NULL;
00119 static L_Alloc_Pool *MD_Entry_pool = NULL;
00120 static L_Alloc_Pool *MD_Field_Decl_pool = NULL;
00121 static L_Alloc_Pool *MD_Element_Req_pool = NULL;
00122 static L_Alloc_Pool *MD_Field_pool = NULL;
00123 static L_Alloc_Pool *MD_Element_pool = NULL;
00124
00125
00126 static char *MD_type_name[] = {"(UNDEFINED)", "INT", "DOUBLE", "STRING",
00127 "LINK", "(UNDEFINED)"};
00128
00129
00130 static void MD_resize_field_arrays (MD_Section *section, int max_index);
00131 static void MD_resize_element_array (MD_Field *field, int max_index);
00132 static int MD_legal_ident (char *ident);
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 static void MD_punt (MD *md, char *fmt, ...)
00146 {
00147 va_list args;
00148
00149
00150
00151
00152 fprintf (stderr, "\nMD library error");
00153 if (md == NULL)
00154 fprintf (stderr, ":\n");
00155 else
00156 fprintf (stderr, " (in \"%s\"):\n", md->name);
00157
00158
00159 va_start (args, fmt);
00160 vfprintf (stderr, fmt, args);
00161 va_end(args);
00162 fprintf (stderr,"\n");
00163
00164 exit (1);
00165 }
00166
00167
00168
00169
00170
00171
00172 static void MD_warn (FILE *out, char *fmt, ...)
00173 {
00174 va_list args;
00175
00176
00177 fprintf (out, "\n");
00178
00179
00180 va_start (args, fmt);
00181 vfprintf (out, fmt, args);
00182 va_end(args);
00183
00184
00185 fprintf (out,"\n");
00186 }
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196 static char *MD_concat_strings (char *string1, char *string2)
00197 {
00198 char *buf;
00199 int len;
00200
00201
00202
00203
00204 len = strlen (string1) + strlen (string2) + 1;
00205 if ((buf = (char *) malloc (len * sizeof(char))) == NULL)
00206 {
00207 MD_punt (NULL,
00208 "MD_concat_strings: Out of memory mallocing buffer (size %i)",
00209 len);
00210 }
00211
00212
00213 sprintf (buf, "%s%s", string1, string2);
00214
00215
00216 return (buf);
00217 }
00218
00219
00220
00221
00222
00223 static MD_Symbol_Table *MD_new_symbol_table (MD *md, char *name,
00224 int expected_size)
00225 {
00226 MD_Symbol_Table *table;
00227 MD_Symbol **hash;
00228 unsigned int min_size, hash_size;
00229 unsigned int i;
00230
00231
00232
00233 if (expected_size < 0)
00234 expected_size = 0;
00235
00236
00237
00238
00239 if (expected_size > 1000000000)
00240 MD_punt (md, "MD_Symbol_Table: unreasonable expected_size (%u)",
00241 expected_size);
00242
00243
00244 min_size = expected_size * 2;
00245
00246
00247
00248
00249 hash_size = 32;
00250
00251
00252 while (hash_size < min_size)
00253 hash_size = hash_size << 1;
00254
00255
00256
00257 if (MD_Symbol_Table_pool == NULL)
00258 {
00259 MD_punt (NULL,
00260 "MD routines not initialized (call MD_new_md() first)!");
00261
00262 }
00263
00264
00265 table = (MD_Symbol_Table *) L_alloc (MD_Symbol_Table_pool);
00266
00267
00268 hash = (MD_Symbol **) malloc (hash_size * sizeof(MD_Symbol *));
00269 if (hash == NULL)
00270 {
00271 MD_punt (md, "MD_new_symbol_table: Out of memory, hash array size %i.",
00272 hash_size);
00273 }
00274
00275
00276 for (i=0; i < (int) hash_size; i++)
00277 hash[i] = NULL;
00278
00279
00280 table->md = md;
00281 table->name = strdup (name);
00282 table->hash = hash;
00283 table->hash_size = hash_size;
00284 table->hash_mask = hash_size -1;
00285
00286 table->resize_size = hash_size - (hash_size >> 2);
00287 table->head_symbol = NULL;
00288 table->tail_symbol = NULL;
00289 table->symbol_count = 0;
00290
00291 return (table);
00292 }
00293
00294
00295 void MD_delete_symbol_table (MD_Symbol_Table *table,
00296 void (*free_routine)(void *))
00297 {
00298 MD_Symbol *symbol, *next_symbol;
00299
00300
00301 for (symbol = table->head_symbol; symbol != NULL;
00302 symbol = next_symbol)
00303 {
00304
00305 next_symbol = symbol->next_symbol;
00306
00307
00308 if (free_routine != NULL)
00309 free_routine (symbol->data);
00310
00311
00312 L_free (MD_Symbol_pool, symbol);
00313 }
00314
00315
00316 free (table->hash);
00317 free (table->name);
00318
00319
00320 L_free (MD_Symbol_Table_pool, table);
00321 }
00322
00323
00324 static void MD_resize_symbol_table (MD_Symbol_Table *table)
00325 {
00326 MD_Symbol **new_hash, *symbol, *hash_head;
00327 int new_hash_size;
00328 unsigned int new_hash_mask, new_hash_index;
00329 int i;
00330
00331
00332 new_hash_size = table->hash_size * 2;
00333
00334
00335 new_hash = (MD_Symbol **) malloc (new_hash_size * sizeof (MD_Symbol *));
00336 if (new_hash == NULL)
00337 {
00338 MD_punt (table->md,
00339 "MD_resize_symbol_table: Out of memory, new size %i.",
00340 new_hash_size);
00341 }
00342
00343
00344 for (i=0; i < new_hash_size; i++)
00345 new_hash[i] = NULL;
00346
00347
00348 new_hash_mask = new_hash_size -1;
00349
00350
00351
00352
00353 for (symbol = table->head_symbol; symbol != NULL;
00354 symbol = symbol->next_symbol)
00355 {
00356
00357 new_hash_index = symbol->hash_val & new_hash_mask;
00358
00359
00360 hash_head = new_hash[new_hash_index];
00361 symbol->next_hash = hash_head;
00362 symbol->prev_hash = NULL;
00363 if (hash_head != NULL)
00364 hash_head->prev_hash = symbol;
00365 new_hash[new_hash_index] = symbol;
00366 }
00367
00368
00369 free (table->hash);
00370
00371
00372 table->hash = new_hash;
00373 table->hash_size = new_hash_size;
00374 table->hash_mask = new_hash_mask;
00375
00376 table->resize_size = new_hash_size - (new_hash_size >> 2);
00377 }
00378
00379
00380 static unsigned int MD_hash_string (char *string)
00381 {
00382 unsigned int hash_val;
00383 unsigned char *ptr;
00384 unsigned int ch;
00385
00386 hash_val = 0;
00387
00388
00389
00390
00391
00392
00393
00394
00395 ptr = (unsigned char *) string;
00396 while ((ch = *ptr) != 0)
00397 {
00398
00399
00400
00401 hash_val += (hash_val << 4);
00402
00403
00404 hash_val += ch;
00405
00406
00407 ptr ++;
00408 }
00409
00410
00411 return (hash_val);
00412 }
00413
00414
00415
00416
00417
00418 static MD_Symbol *MD_add_symbol (MD_Symbol_Table *table, char *name,
00419 void *data)
00420 {
00421 MD_Symbol *symbol, *hash_head, *check_symbol, *tail_symbol;
00422 unsigned int hash_val, hash_index;
00423 int symbol_count;
00424
00425
00426
00427
00428 symbol_count = table->symbol_count;
00429 if (symbol_count >= table->resize_size)
00430 {
00431 MD_resize_symbol_table (table);
00432 }
00433
00434
00435 symbol = (MD_Symbol *) L_alloc (MD_Symbol_pool);
00436
00437
00438 symbol->name = name;
00439 symbol->data = data;
00440 symbol->table = table;
00441 symbol->symbol_id = -1;
00442
00443
00444 tail_symbol = table->tail_symbol;
00445
00446
00447 symbol->next_symbol = NULL;
00448 symbol->prev_symbol = tail_symbol;
00449
00450 if (tail_symbol == NULL)
00451 table->head_symbol = symbol;
00452 else
00453 tail_symbol->next_symbol = symbol;
00454 table->tail_symbol = symbol;
00455
00456
00457
00458
00459 hash_val = MD_hash_string (name);
00460 symbol->hash_val = hash_val;
00461
00462
00463 hash_index = hash_val & table->hash_mask;
00464
00465
00466 hash_head = table->hash[hash_index];
00467
00468
00469
00470
00471
00472
00473
00474 for (check_symbol = hash_head; check_symbol != NULL;
00475 check_symbol = check_symbol->next_hash)
00476 {
00477
00478
00479
00480 if ((check_symbol->hash_val == hash_val) &&
00481 (strcmp(check_symbol->name, name) == 0))
00482 {
00483 MD_punt (table->md,
00484 "%s: cannot add '%s', already in table!",
00485 table->name, name);
00486 }
00487 }
00488
00489
00490
00491 symbol->next_hash = hash_head;
00492 symbol->prev_hash = NULL;
00493 if (hash_head != NULL)
00494 hash_head->prev_hash = symbol;
00495 table->hash[hash_index] = symbol;
00496
00497
00498 table->symbol_count = symbol_count + 1;
00499
00500
00501 return (symbol);
00502 }
00503
00504
00505
00506
00507 static void MD_rename_symbol (MD_Symbol *symbol, char *new_name)
00508 {
00509 MD_Symbol_Table *table;
00510 MD_Symbol *hash_head, *check_symbol;
00511 unsigned int hash_val, hash_index;
00512
00513
00514 table = symbol->table;
00515
00516
00517
00518 hash_index = symbol->hash_val & table->hash_mask;
00519
00520
00521 if (symbol->prev_hash == NULL)
00522 table->hash[hash_index] = symbol->next_hash;
00523 else
00524 symbol->prev_hash->next_hash = symbol->next_hash;
00525
00526 if (symbol->next_hash != NULL)
00527 symbol->next_hash->prev_hash = symbol->prev_hash;
00528
00529
00530
00531
00532
00533 symbol->name = new_name;
00534 hash_val = MD_hash_string (new_name);
00535 symbol->hash_val = hash_val;
00536
00537
00538 hash_index = hash_val & table->hash_mask;
00539
00540
00541 hash_head = table->hash[hash_index];
00542
00543
00544
00545
00546
00547 for (check_symbol = hash_head; check_symbol != NULL;
00548 check_symbol = check_symbol->next_hash)
00549 {
00550
00551
00552
00553 if ((check_symbol->hash_val == hash_val) &&
00554 (strcmp(check_symbol->name, new_name) == 0))
00555 {
00556 MD_punt (table->md,
00557 "%s: cannot rename to '%s', already in table!",
00558 table->name, new_name);
00559 }
00560 }
00561
00562
00563
00564 symbol->next_hash = hash_head;
00565 symbol->prev_hash = NULL;
00566 if (hash_head != NULL)
00567 hash_head->prev_hash = symbol;
00568 table->hash[hash_index] = symbol;
00569 }
00570
00571
00572
00573
00574 static MD_Symbol *MD_find_symbol (MD_Symbol_Table *table, char *name)
00575 {
00576 MD_Symbol *symbol;
00577 unsigned int hash_val, hash_index;
00578
00579
00580 hash_val = MD_hash_string (name);
00581
00582
00583 hash_index = hash_val & table->hash_mask;
00584
00585
00586 for (symbol = table->hash[hash_index]; symbol != NULL;
00587 symbol = symbol->next_hash)
00588 {
00589
00590 if ((symbol->hash_val == hash_val) &&
00591 (strcmp(symbol->name, name) == 0))
00592 {
00593 return (symbol);
00594 }
00595 }
00596 return (NULL);
00597 }
00598
00599
00600
00601
00602
00603
00604 void *_MD_find_symbol_data (MD_Symbol_Table *table, char *name)
00605 {
00606 MD_Symbol *symbol;
00607 unsigned int hash_val, hash_index;
00608
00609
00610 hash_val = MD_hash_string (name);
00611
00612
00613 hash_index = hash_val & table->hash_mask;
00614
00615
00616 for (symbol = table->hash[hash_index]; symbol != NULL;
00617 symbol = symbol->next_hash)
00618 {
00619
00620 if ((symbol->hash_val == hash_val) &&
00621 (strcmp(symbol->name, name) == 0))
00622 {
00623 return (symbol->data);
00624 }
00625 }
00626 return (NULL);
00627 }
00628
00629
00630 void MD_delete_symbol (MD_Symbol *symbol, void (*free_routine)(void *))
00631 {
00632 MD_Symbol_Table *table;
00633 MD_Symbol *next_hash, *prev_hash, *next_symbol, *prev_symbol;
00634 unsigned int hash_index;
00635
00636
00637 table = symbol->table;
00638
00639
00640 hash_index = symbol->hash_val & table->hash_mask;
00641
00642
00643 prev_hash = symbol->prev_hash;
00644 next_hash = symbol->next_hash;
00645 if (prev_hash == NULL)
00646 table->hash[hash_index] = next_hash;
00647 else
00648 prev_hash->next_hash = next_hash;
00649
00650 if (next_hash != NULL)
00651 next_hash->prev_hash = prev_hash;
00652
00653
00654 prev_symbol = symbol->prev_symbol;
00655 next_symbol = symbol->next_symbol;
00656 if (prev_symbol == NULL)
00657 table->head_symbol = next_symbol;
00658 else
00659 prev_symbol->next_symbol = next_symbol;
00660
00661 if (next_symbol == NULL)
00662 table->tail_symbol = prev_symbol;
00663 else
00664 next_symbol->prev_symbol = prev_symbol;
00665
00666
00667
00668 if (free_routine != NULL)
00669 free_routine (symbol->data);
00670
00671
00672 L_free (MD_Symbol_pool, symbol);
00673
00674
00675 table->symbol_count --;
00676 }
00677
00678
00679
00680
00681 static void MD_print_symbol_table_hash (FILE *out, MD_Symbol_Table *table)
00682 {
00683 int hash_index, lines;
00684 #if 0
00685 MD_Symbol *symbol;
00686 #endif
00687
00688
00689 lines = 0;
00690 for (hash_index = 0; hash_index < table->hash_size; hash_index++)
00691 {
00692 if (table->hash[hash_index] != NULL)
00693 lines++;
00694 }
00695 fprintf (out, "%s has %i entries (hash size %i, used %i):\n",
00696 table->name, table->symbol_count, table->hash_size, lines);
00697
00698 #if 0
00699
00700 for (hash_index = 0; hash_index < table->hash_size; hash_index++)
00701 {
00702
00703 if (table->hash[hash_index] == NULL)
00704 continue;
00705
00706 fprintf (out, "%4i:", hash_index);
00707 for (symbol = table->hash[hash_index]; symbol != NULL;
00708 symbol = symbol->next_hash)
00709 {
00710 fprintf (out, " %s(%i)", symbol->name, symbol->hash_val);
00711 }
00712 fprintf (out, "\n");
00713 }
00714 #endif
00715 }
00716
00717
00718
00719
00720
00721 MD *MD_new_md (char *name, int num_sections)
00722 {
00723 MD *md;
00724
00725
00726 if (num_sections < 0)
00727 num_sections = 0;
00728
00729
00730
00731
00732
00733 if (num_sections > 1000000000)
00734 MD_punt (NULL, "MD_new_md: unreasonable num_sections (%u)",
00735 num_sections);
00736
00737
00738
00739
00740 if (MD_pool == NULL)
00741 {
00742 MD_pool = L_create_alloc_pool ("MD", sizeof (MD), 1);
00743 MD_Symbol_Table_pool = L_create_alloc_pool ("MD_Symbol_Table",
00744 sizeof (MD_Symbol_Table),
00745 16);
00746 MD_Symbol_pool = L_create_alloc_pool ("MD_Symbol", sizeof (MD_Symbol),
00747 64);
00748 MD_Section_pool = L_create_alloc_pool ("MD_Section",
00749 sizeof(MD_Section), 16);
00750 MD_Field_Decl_pool = L_create_alloc_pool ("MD_Field_Decl",
00751 sizeof(MD_Field_Decl), 16);
00752 MD_Element_Req_pool = L_create_alloc_pool ("MD_Element_Req",
00753 sizeof(MD_Element_Req), 64);
00754 MD_Entry_pool = L_create_alloc_pool ("MD_Entry", sizeof(MD_Entry), 64);
00755 MD_Field_pool = L_create_alloc_pool ("MD_Field", sizeof(MD_Field), 64);
00756 MD_Element_pool = L_create_alloc_pool ("MD_Element",
00757 sizeof(MD_Element), 64);
00758 }
00759
00760
00761 md = (MD *) L_alloc (MD_pool);
00762
00763
00764 md->name = strdup (name);
00765 md->section_table = MD_new_symbol_table (md, "Section table",
00766 num_sections);
00767
00768
00769 return (md);
00770 }
00771
00772
00773
00774
00775
00776 void MD_delete_md (MD *md)
00777 {
00778 char *name;
00779
00780
00781 name = md->name;
00782
00783
00784 MD_delete_symbol_table (md->section_table,
00785 (void(*)(void *))_MD_free_section);
00786
00787
00788 L_free (MD_pool, md);
00789
00790
00791
00792
00793 if (MD_pool->allocated == MD_pool->free)
00794 {
00795
00796
00797
00798
00799
00800 L_free_alloc_pool (MD_pool);
00801 L_free_alloc_pool (MD_Symbol_Table_pool);
00802 L_free_alloc_pool (MD_Symbol_pool);
00803 L_free_alloc_pool (MD_Section_pool);
00804 L_free_alloc_pool (MD_Entry_pool);
00805 L_free_alloc_pool (MD_Field_Decl_pool);
00806 L_free_alloc_pool (MD_Element_Req_pool);
00807 L_free_alloc_pool (MD_Field_pool);
00808 L_free_alloc_pool (MD_Element_pool);
00809
00810
00811
00812
00813 MD_pool = NULL;
00814 MD_Symbol_Table_pool = NULL;
00815 MD_Symbol_pool = NULL;
00816 MD_Section_pool = NULL;
00817 MD_Entry_pool = NULL;
00818 MD_Field_Decl_pool = NULL;
00819 MD_Element_Req_pool = NULL;
00820 MD_Field_pool = NULL;
00821 MD_Element_pool = NULL;
00822 }
00823
00824
00825 free (name);
00826 }
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837 int MD_check_md (FILE *out, MD *md)
00838 {
00839 MD_Symbol *symbol;
00840 MD_Section *section;
00841 int error_count;
00842
00843
00844 error_count = 0;
00845
00846
00847 for (symbol = md->section_table->head_symbol; symbol != NULL;
00848 symbol = symbol->next_symbol)
00849 {
00850
00851 section = (MD_Section *) symbol->data;
00852
00853
00854 error_count += _MD_check_section (out, section, "MD_check_md");
00855 }
00856
00857
00858 return (error_count);
00859 }
00860
00861
00862
00863 MD_Buf *MD_new_buf ()
00864 {
00865 MD_Buf *buf;
00866 int buf_size;
00867
00868
00869 buf = (MD_Buf *) L_alloc (MD_Buf_pool);
00870
00871
00872 buf_size = 128;
00873 buf->buf = (char *) malloc (buf_size);
00874 if (buf->buf == NULL)
00875 MD_punt (NULL, "MD_new_buf: out of memory (size %i)", buf_size);
00876 buf->buf_size = buf_size;
00877
00878
00879 return (buf);
00880 }
00881
00882
00883 void MD_resize_buf (MD_Buf *buf)
00884 {
00885 char *old_buf, *new_buf;
00886 int old_size, new_size, i;
00887
00888
00889 old_buf = buf->buf;
00890 old_size = buf->buf_size;
00891
00892
00893 new_size = old_size << 1;
00894
00895 new_buf = (char *) malloc (new_size);
00896 if (new_buf == NULL)
00897 MD_punt (NULL, "MD_resize_buf: out of memory (size %i)", new_size);
00898
00899
00900 for (i=0; i < old_size; i++)
00901 new_buf[i] = old_buf[i];
00902
00903
00904 free (old_buf);
00905 buf->buf = new_buf;
00906 buf->buf_size = new_size;
00907 }
00908
00909
00910 void MD_delete_buf (MD_Buf *buf)
00911 {
00912
00913 free (buf->buf);
00914
00915
00916 L_free (MD_Buf_pool, buf);
00917 }
00918
00919
00920
00921
00922
00923 int MD_read_int (FILE *in)
00924 {
00925 int value, ch, negate;
00926 unsigned int nibble;
00927
00928
00929 while ((ch = getc(in)) != EOF)
00930 {
00931 if (ch != ' ')
00932 break;
00933 }
00934
00935
00936 if (ch == EOF)
00937 MD_punt (NULL, "MD_read_int: unexpected EOF");
00938
00939
00940 negate = 0;
00941 if (ch == '-')
00942 {
00943 negate = 1;
00944 if ((ch = getc(in)) == EOF)
00945 MD_punt (NULL, "MD_read_int: unexpected EOF");
00946 }
00947
00948
00949 if (ch >= 'a')
00950 nibble = 10 + ch - 'a';
00951 else
00952 nibble = ch - '0';
00953
00954
00955 if (nibble > 15)
00956 MD_punt (NULL, "MD_read_int: int expected not '%c'", ch);
00957
00958
00959 value = nibble;
00960
00961
00962 while ((ch = getc(in)) != EOF)
00963 {
00964
00965 if ((ch == ' ') || (ch == '\n'))
00966 break;
00967
00968
00969 if (ch >= 'a')
00970 nibble = 10 + ch - 'a';
00971 else
00972 nibble = ch - '0';
00973
00974
00975 if (nibble > 15)
00976 MD_punt (NULL, "MD_read_int: int expected not '%c'", ch);
00977
00978
00979 value = (value << 4) + nibble;
00980 }
00981
00982
00983 if (ch != EOF)
00984 ungetc (ch, in);
00985
00986
00987 if (negate)
00988 value = -value;
00989
00990
00991 return (value);
00992 }
00993
00994
00995
00996 double MD_read_double (FILE *in, MD_Buf *value_buf)
00997 {
00998 char *buf, *end_ptr;
00999 int i, ch, resize_size;
01000 double value;
01001
01002
01003 buf = value_buf->buf;
01004 resize_size = value_buf->buf_size -2;
01005
01006
01007 while ((ch = getc(in)) != EOF)
01008 {
01009 if (ch != ' ')
01010 break;
01011 }
01012
01013
01014 if (ch == EOF)
01015 MD_punt (NULL, "MD_read_double: unexpected EOF");
01016
01017
01018 buf[0] = ch;
01019 i = 1;
01020
01021
01022 while ((ch = getc(in)) != EOF)
01023 {
01024
01025 if ((ch == ' ') || (ch == '\n'))
01026 break;
01027
01028
01029 if (i >= resize_size)
01030 {
01031 MD_resize_buf (value_buf);
01032
01033
01034 buf = value_buf->buf;
01035 resize_size = value_buf->buf_size -2;
01036 }
01037
01038 buf[i] = ch;
01039 i++;
01040 }
01041
01042
01043 if (ch != EOF)
01044 ungetc (ch, in);
01045
01046
01047 buf[i] = 0;
01048
01049
01050 value = strtod (buf, &end_ptr);
01051
01052
01053 if (*end_ptr != 0)
01054 MD_punt (NULL, "MD_read_double: double expected not '%s'!", buf);
01055
01056
01057 return (value);
01058 }
01059
01060
01061 void MD_read_string (FILE *in, MD_Buf *value_buf)
01062 {
01063 char *buf;
01064 int i, ch, resize_size;
01065
01066
01067 buf = value_buf->buf;
01068 resize_size = value_buf->buf_size -2;
01069
01070
01071
01072 i = 0;
01073
01074
01075 while ((ch = getc(in)) != EOF)
01076 {
01077
01078 if (ch == '\n')
01079 break;
01080
01081
01082 if (i >= resize_size)
01083 {
01084 MD_resize_buf (value_buf);
01085
01086
01087 buf = value_buf->buf;
01088 resize_size = value_buf->buf_size -2;
01089 }
01090
01091 buf[i] = ch;
01092 i++;
01093 }
01094
01095
01096 if (ch != EOF)
01097 ungetc (ch, in);
01098
01099 else if (i == 0)
01100 MD_punt (NULL, "MD_read_string: unexpected EOF");
01101
01102
01103 buf[i] = 0;
01104 }
01105
01106 void MD_read_nl (FILE *in)
01107 {
01108 int ch;
01109
01110 ch = getc (in);
01111 if (ch != '\n')
01112 {
01113 if (ch == EOF)
01114 MD_punt (NULL, "MD_read_nl: unexpected EOF");
01115
01116 MD_punt (NULL, "MD_read_nl: newline expected not '%c'!", ch);
01117 }
01118 }
01119
01120 void MD_read_sp (FILE *in)
01121 {
01122 int ch;
01123
01124 ch = getc (in);
01125 if (ch != ' ')
01126 {
01127 if (ch == EOF)
01128 MD_punt (NULL, "MD_read_sp: unexpected EOF");
01129
01130 MD_punt (NULL, "MD_read_sp: space expected not '%c'!", ch);
01131 }
01132 }
01133
01134
01135 MD *MD_read_md (FILE *in, char *name)
01136 {
01137 MD *md;
01138 MD_Section *section, **section_array, **target_array;
01139 MD_Entry *entry, **entry_array, *link;
01140 MD_Field_Decl *field_decl, **field_decl_array;
01141 MD_Buf *name_buf, *value_buf;
01142 MD_Field *field;
01143 int section_array_size, entry_array_size;
01144 int section_index, entry_index, field_decl_index;
01145 int entry_count, field_decl_count;
01146 char type_marker, kleene_marker, require_marker;
01147 MD_FIELD_TYPE field_type;
01148 int kleene_starred, require_count, require_index, target_index;
01149 int target_count, local_entry_index, element_index, element_count;
01150 int field_count, field_index, int_value, link_index;
01151 double double_value;
01152 int i;
01153
01154
01155 MD_Buf_pool = L_create_alloc_pool ("MD_Buf", sizeof(MD_Buf), 4);
01156
01157
01158 name_buf = MD_new_buf();
01159 value_buf = MD_new_buf();
01160
01161
01162 section_array_size = MD_read_int (in);
01163 entry_array_size = MD_read_int (in);
01164 MD_read_nl (in);
01165 MD_read_nl (in);
01166
01167
01168 md = MD_new_md (name, section_array_size);
01169
01170
01171
01172
01173
01174 section_array = (MD_Section **) malloc (sizeof(MD_Section *) *
01175 section_array_size);
01176 if (section_array == NULL)
01177 {
01178 MD_punt (NULL, "MD_read_md: out of memory (size %i).",
01179 section_array_size);
01180 }
01181
01182 entry_array = (MD_Entry **) malloc (sizeof(MD_Entry *) *
01183 entry_array_size);
01184 if (entry_array == NULL)
01185 {
01186 MD_punt (NULL, "MD_read_md: out of memory (size %i).",
01187 entry_array_size);
01188 }
01189
01190
01191 entry_index = 0;
01192
01193
01194 for (section_index = 0; section_index < section_array_size;
01195 section_index++)
01196 {
01197
01198 MD_read_string (in, name_buf);
01199 MD_read_nl(in);
01200
01201 entry_count = MD_read_int (in);
01202 field_decl_count = MD_read_int (in);
01203 MD_read_nl(in);
01204
01205
01206
01207
01208
01209 section = MD_new_section (md, name_buf->buf, entry_count,
01210 field_decl_count);
01211 section_array[section_index] = section;
01212
01213
01214 for (i = 0; i < entry_count; i++)
01215 {
01216 MD_read_string (in, name_buf);
01217 MD_read_nl (in);
01218
01219
01220 entry = MD_new_entry (section, name_buf->buf);
01221 entry_array[entry_index++] = entry;
01222 }
01223 MD_read_nl(in);
01224 }
01225 MD_read_nl(in);
01226
01227
01228 entry_index = 0;
01229
01230
01231
01232
01233 for (section_index = 0; section_index < section_array_size;
01234 section_index++)
01235 {
01236
01237 MD_read_string (in, name_buf);
01238
01239 MD_read_nl(in);
01240
01241 entry_count = MD_read_int (in);
01242 field_decl_count = MD_read_int (in);
01243 MD_read_nl(in);
01244
01245
01246 section = section_array[section_index];
01247
01248
01249 if (strcmp (name_buf->buf, section->name) != 0)
01250 {
01251 MD_punt (NULL, "Section '%s' expected, not '%s'!",
01252 section->name, name_buf->buf);
01253 }
01254
01255
01256 if (field_decl_count > 0)
01257 {
01258
01259 field_decl_array =
01260 (MD_Field_Decl **) malloc (sizeof(MD_Field_Decl *) *
01261 field_decl_count);
01262 if (field_decl_array == NULL)
01263 MD_punt (NULL, "MD_read_md: Out of memory (size %i)",
01264 field_decl_count);
01265 }
01266 else
01267 {
01268
01269 field_decl_array = NULL;
01270 }
01271
01272
01273 for (field_decl_index = 0; field_decl_index < field_decl_count;
01274 field_decl_index++)
01275 {
01276
01277 MD_read_string (in, name_buf);
01278
01279 MD_read_nl (in);
01280
01281
01282 type_marker = getc (in);
01283
01284 switch (type_marker)
01285 {
01286 case 'R':
01287 field_type = MD_REQUIRED_FIELD;
01288 break;
01289
01290 case 'O':
01291 field_type = MD_OPTIONAL_FIELD;
01292 break;
01293
01294 default:
01295 MD_punt (NULL, "MD_read_md: Unknown field decl type '%c'",
01296 type_marker);
01297 }
01298
01299 require_count = MD_read_int(in);
01300 MD_read_sp (in);
01301 kleene_marker = getc (in);
01302
01303 switch (kleene_marker)
01304 {
01305 case '*':
01306 kleene_starred = 1;
01307 break;
01308
01309 case '-':
01310 kleene_starred = 0;
01311 break;
01312
01313 default:
01314 MD_punt (NULL, "MD_read_md: Unknown kleene marker '%c'",
01315 kleene_marker);
01316 }
01317 MD_read_nl (in);
01318
01319
01320 field_decl = MD_new_field_decl (section, name_buf->buf,
01321 field_type);
01322 field_decl_array[field_decl_index] = field_decl;
01323
01324
01325
01326
01327 for (require_index = 0; require_index < require_count;
01328 require_index++)
01329 {
01330
01331 require_marker = getc (in);
01332
01333
01334 switch (require_marker)
01335 {
01336 case 'I':
01337 MD_require_int (field_decl, require_index);
01338 break;
01339
01340 case 'D':
01341 MD_require_double (field_decl, require_index);
01342 break;
01343
01344 case 'S':
01345 MD_require_string (field_decl, require_index);
01346 break;
01347
01348 case 'L':
01349
01350 target_count = MD_read_int (in);
01351
01352
01353 target_array =
01354 (MD_Section **) malloc (sizeof(MD_Section *) *
01355 target_count);
01356
01357 if (target_array == NULL)
01358 {
01359 MD_punt (NULL, "MD_read_md: Out of memory (size %i)",
01360 target_count);
01361 }
01362
01363
01364 for (i=0; i < target_count; i++)
01365 {
01366 target_index = MD_read_int (in);
01367 target_array[i] = section_array[target_index];
01368 }
01369
01370 MD_require_multi_target_link (field_decl, require_index,
01371 target_count, target_array);
01372
01373
01374 free (target_array);
01375
01376 break;
01377
01378 default:
01379 MD_punt (NULL,
01380 "MD_read_md: Unknown requirement type '%c'",
01381 require_marker);
01382
01383 }
01384 MD_read_nl(in);
01385
01386 }
01387 MD_read_nl(in);
01388
01389
01390 if (kleene_starred)
01391 {
01392 MD_kleene_star_requirement (field_decl, require_count -1);
01393 }
01394 }
01395
01396 for (local_entry_index = 0; local_entry_index < entry_count;
01397 local_entry_index++)
01398 {
01399
01400
01401
01402
01403 entry = entry_array[entry_index++];
01404
01405
01406 field_count = MD_read_int (in);
01407 MD_read_nl (in);
01408 MD_read_nl (in);
01409
01410
01411 for (i = 0; i < field_count; i++)
01412 {
01413
01414 field_index = MD_read_int (in);
01415 element_count = MD_read_int (in);
01416 MD_read_nl (in);
01417
01418 field_decl = field_decl_array[field_index];
01419
01420
01421
01422
01423 field = MD_new_field (entry, field_decl, element_count);
01424
01425
01426 for (element_index = 0; element_index < element_count;
01427 element_index++)
01428 {
01429
01430 type_marker = getc(in);
01431
01432
01433 switch (type_marker)
01434 {
01435 case 'I':
01436 int_value = MD_read_int (in);
01437 MD_set_int (field, element_index, int_value);
01438 break;
01439
01440 case 'D':
01441 double_value = MD_read_double (in, value_buf);
01442 MD_set_double (field, element_index, double_value);
01443 break;
01444
01445 case 'S':
01446 MD_read_string (in, value_buf);
01447 MD_set_string (field, element_index, value_buf->buf);
01448 break;
01449
01450 case 'L':
01451 link_index = MD_read_int (in);
01452 link = entry_array[link_index];
01453 MD_set_link (field, element_index, link);
01454 break;
01455
01456 default:
01457 MD_punt (NULL, "MD_read_md: Uknown element type '%c'.",
01458 type_marker);
01459 }
01460 MD_read_nl(in);
01461 }
01462 MD_read_nl(in);
01463 }
01464 }
01465 MD_read_nl(in);
01466
01467
01468 if (field_decl_array != NULL)
01469 free (field_decl_array);
01470 }
01471
01472
01473 free (section_array);
01474 free (entry_array);
01475
01476
01477
01478 MD_delete_buf (name_buf);
01479 MD_delete_buf (value_buf);
01480
01481
01482 L_free_alloc_pool (MD_Buf_pool);
01483
01484
01485 return (md);
01486 }
01487
01488
01489
01490
01491
01492
01493 void MD_write_md (FILE *out, MD *md)
01494 {
01495 MD_Symbol *section_symbol, *entry_symbol, *field_decl_symbol;
01496 MD_Section *section, **link_array;
01497 MD_Entry *entry;
01498 MD_Field_Decl *field_decl;
01499 MD_Element_Req *element_req, **require_array;
01500 MD_Field **field_array, *field;
01501 MD_Element *element, **element_array;
01502 int total_entry_count, max_require_index, i;
01503 int section_id, entry_id, field_decl_id, link_array_size;
01504 int max_field_index, field_count, max_assigned_index, require_index;
01505 char type_marker, kleene_marker;
01506
01507
01508 total_entry_count = 0;
01509
01510
01511 section_id = 0;
01512 entry_id = 0;
01513
01514
01515 for (section_symbol = md->section_table->head_symbol;
01516 section_symbol != NULL; section_symbol = section_symbol->next_symbol)
01517 {
01518
01519 section_symbol->symbol_id = section_id++;
01520
01521
01522 section = (MD_Section *) section_symbol->data;
01523
01524
01525
01526
01527 field_decl_id = 0;
01528 for (field_decl_symbol = section->field_decl_table->head_symbol;
01529 field_decl_symbol != NULL;
01530 field_decl_symbol = field_decl_symbol->next_symbol)
01531 {
01532 field_decl_symbol->symbol_id = field_decl_id++;
01533 }
01534
01535
01536
01537
01538
01539
01540 for (entry_symbol = section->entry_table->head_symbol;
01541 entry_symbol != NULL; entry_symbol = entry_symbol->next_symbol)
01542 {
01543 entry_symbol->symbol_id = entry_id++;
01544 }
01545
01546
01547 total_entry_count += section->entry_table->symbol_count;
01548 }
01549
01550
01551 fprintf (out, "%x %x\n\n", md->section_table->symbol_count,
01552 total_entry_count);
01553
01554
01555
01556
01557 for (section_symbol = md->section_table->head_symbol;
01558 section_symbol != NULL; section_symbol = section_symbol->next_symbol)
01559 {
01560
01561 section = (MD_Section *) section_symbol->data;
01562
01563
01564
01565
01566 #if 0
01567 fprintf (out, "%i %s %i %i\n", section_symbol->symbol_id,
01568 section->name,
01569 section->entry_table->symbol_count,
01570 section->field_decl_table->symbol_count);
01571 #endif
01572 fprintf (out, "%s\n%x %x\n",
01573 section->name,
01574 section->entry_table->symbol_count,
01575 section->field_decl_table->symbol_count);
01576
01577 for (entry_symbol = section->entry_table->head_symbol;
01578 entry_symbol != NULL; entry_symbol = entry_symbol->next_symbol)
01579 {
01580
01581 entry = (MD_Entry *) entry_symbol->data;
01582
01583
01584 #if 0
01585 fprintf (out, "%i %s\n", entry_symbol->symbol_id,
01586 entry->name);
01587 #endif
01588 fprintf (out, "%s\n", entry->name);
01589
01590 }
01591
01592 putc ('\n', out);
01593 }
01594 putc ('\n', out);
01595
01596
01597
01598
01599 for (section_symbol = md->section_table->head_symbol;
01600 section_symbol != NULL; section_symbol = section_symbol->next_symbol)
01601 {
01602
01603 section = (MD_Section *) section_symbol->data;
01604
01605
01606
01607
01608 #if 0
01609 fprintf (out, "%i %s %i %i\n", section_symbol->symbol_id,
01610 section->name,
01611 section->entry_table->symbol_count,
01612 section->field_decl_table->symbol_count);
01613 #endif
01614 fprintf (out, "%s\n%x %x\n",
01615 section->name,
01616 section->entry_table->symbol_count,
01617 section->field_decl_table->symbol_count);
01618
01619 for (field_decl_symbol = section->field_decl_table->head_symbol;
01620 field_decl_symbol != NULL;
01621 field_decl_symbol = field_decl_symbol->next_symbol)
01622 {
01623
01624 field_decl = (MD_Field_Decl *) field_decl_symbol->data;
01625
01626 switch (field_decl->type)
01627 {
01628 case MD_REQUIRED_FIELD:
01629 type_marker = 'R';
01630 break;
01631
01632 case MD_OPTIONAL_FIELD:
01633 type_marker = 'O';
01634 break;
01635
01636 default:
01637 MD_punt (NULL, "MD_write_md: Unknown field decl type '%i'.",
01638 field_decl->type);
01639 }
01640
01641 if (field_decl->kleene_starred_req != NULL)
01642 kleene_marker = '*';
01643 else
01644 kleene_marker = '-';
01645
01646
01647
01648 max_require_index = field_decl->max_require_index;
01649 require_array = field_decl->require;
01650
01651
01652
01653
01654 #if 0
01655 fprintf (out, "%i %s %i %c\n", field_decl_symbol->symbol_id,
01656 field_decl->name,
01657 max_require_index + 1,
01658 kleene_marker);
01659 #endif
01660 fprintf (out, "%s\n%c %x %c\n",
01661 field_decl->name,
01662 type_marker,
01663 max_require_index + 1,
01664 kleene_marker);
01665
01666 for (require_index=0; require_index <= max_require_index;
01667 require_index++)
01668 {
01669 element_req = require_array[require_index];
01670
01671 switch (element_req->type)
01672 {
01673 case MD_INT:
01674 putc ('I', out);
01675 putc ('\n', out);
01676 break;
01677
01678 case MD_DOUBLE:
01679 putc ('D', out);
01680 putc ('\n', out);
01681 break;
01682
01683 case MD_STRING:
01684 putc ('S', out);
01685 putc ('\n', out);
01686 break;
01687
01688 case MD_LINK:
01689 link_array = element_req->link;
01690 link_array_size = element_req->link_array_size;
01691 fprintf (out, "L %x", link_array_size);
01692 for (i=0; i < link_array_size; i++)
01693 fprintf (out, " %x", link_array[i]->symbol->symbol_id);
01694 putc ('\n', out);
01695 break;
01696
01697 default:
01698 MD_punt (NULL, "MD_write_md: Unknown req type %i",
01699 element_req->type);
01700 }
01701
01702 }
01703 putc ('\n', out);
01704 }
01705
01706
01707 max_field_index = section->max_field_index;
01708
01709
01710 for (entry_symbol = section->entry_table->head_symbol;
01711 entry_symbol != NULL;
01712 entry_symbol = entry_symbol->next_symbol)
01713 {
01714
01715 entry = (MD_Entry *) entry_symbol->data;
01716
01717
01718 field_array = entry->field;
01719
01720
01721 field_count = 0;
01722 for (i=0; i <= max_field_index; i++)
01723 {
01724 if (field_array[i] != NULL)
01725 field_count ++;
01726 }
01727
01728
01729
01730
01731 #if 0
01732 fprintf (out, "%i %i\n", entry_symbol->symbol_id,
01733 field_count);
01734 #endif
01735
01736 fprintf (out, "%x\n\n", field_count);
01737
01738 for (field_decl_symbol=section->field_decl_table->head_symbol;
01739 field_decl_symbol != NULL;
01740 field_decl_symbol = field_decl_symbol->next_symbol)
01741 {
01742
01743 field_decl = (MD_Field_Decl *) field_decl_symbol->data;
01744
01745 field = field_array[field_decl->field_index];
01746
01747 if (field == NULL)
01748 continue;
01749
01750
01751 element_array = field->element;
01752
01753
01754 for (max_assigned_index = field->max_element_index;
01755 max_assigned_index >= 0; max_assigned_index--)
01756 {
01757 if (element_array[max_assigned_index] != NULL)
01758 break;
01759 }
01760
01761
01762
01763
01764 fprintf (out, "%x %x\n",
01765 field_decl_symbol->symbol_id,
01766 max_assigned_index + 1);
01767
01768 for (i=0; i <= max_assigned_index; i++)
01769 {
01770
01771 element = element_array[i];
01772
01773 if (element == NULL)
01774 {
01775 fprintf (out, "-\n");
01776 }
01777 else
01778 {
01779 switch (element->type)
01780 {
01781
01782 case MD_INT:
01783 if (element->value.i < 0)
01784 fprintf (out, "I-%x\n", -element->value.i);
01785 else
01786 fprintf (out, "I%x\n", element->value.i);
01787
01788 break;
01789
01790 case MD_DOUBLE:
01791 fprintf (out, "D%0.16g\n", element->value.d);
01792 break;
01793
01794 case MD_STRING:
01795 fprintf (out, "S%s\n", element->value.s);
01796 break;
01797
01798 case MD_LINK:
01799 fprintf (out, "L%x\n",
01800 element->value.l->symbol->symbol_id);
01801 break;
01802
01803 default:
01804 MD_punt (NULL,
01805 "MD_write_md: Unknown element type %i.",
01806 element->type);
01807 }
01808 }
01809 }
01810
01811 putc ('\n', out);
01812 }
01813 }
01814
01815 putc ('\n', out);
01816
01817 }
01818 putc('\n', out);
01819 }
01820
01821
01822 void MD_print_md (FILE *out, MD *md, int page_width)
01823 {
01824 MD_Section *section;
01825 MD_Symbol *symbol;
01826
01827
01828 fprintf (out, "/*\n * %s:\n", md->name);
01829 fprintf (out,
01830 " * Field declarations and entry contents for each section\n");
01831 fprintf (out, " */");
01832
01833
01834 for (symbol = md->section_table->head_symbol; symbol != NULL;
01835 symbol = symbol->next_symbol)
01836 {
01837
01838 section = (MD_Section *) symbol->data;
01839
01840 putc ('\n', out);
01841
01842
01843 MD_print_section (out, section, page_width);
01844 }
01845 }
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857 void MD_print_md_declarations (FILE *out, MD *md, int page_width)
01858 {
01859 MD_Section *section;
01860 MD_Entry *entry, *next_entry;
01861 char *entry_name;
01862 int col, legal_ident, name_len;
01863 int comment_indent, cur_indent;
01864
01865
01866
01867 fprintf (out,
01868 "/*\n * %s:\n",
01869 md->name);
01870 fprintf (out,
01871 " * Declaration of all section and entry names\n */");
01872
01873
01874
01875
01876 comment_indent = 39;
01877 if (comment_indent > (page_width - 16))
01878 comment_indent = page_width - 16;
01879
01880
01881 for (section = MD_first_section (md); section != NULL;
01882 section = MD_next_section (section))
01883 {
01884 fprintf (out, "\nCREATE SECTION %s",
01885 section->name);
01886
01887
01888 cur_indent = 15 + strlen (section->name);
01889
01890
01891 while (cur_indent < comment_indent)
01892 {
01893 putc (' ', out);
01894 cur_indent++;
01895 }
01896
01897
01898 fprintf (out, " // Declaration\n");
01899 fprintf (out, "{\n");
01900
01901
01902 col = 0;
01903
01904
01905 for (entry = MD_first_entry (section); entry != NULL;
01906 entry = next_entry)
01907 {
01908
01909 next_entry = MD_next_entry (entry);
01910
01911
01912 entry_name = entry->name;
01913
01914
01915 name_len = strlen (entry_name);
01916
01917
01918 legal_ident = MD_legal_ident (entry_name);
01919
01920
01921 if (!legal_ident)
01922 name_len += 2;
01923
01924
01925
01926
01927 if ((col != 0) && (col + name_len + 4) >= page_width)
01928 {
01929 putc ('\n', out);
01930 col = 0;
01931 }
01932
01933
01934 if (col == 0)
01935 {
01936 putc (' ', out);
01937 col = 1;
01938 }
01939
01940
01941 if (!MD_legal_ident(entry_name))
01942 {
01943 fprintf (out, " '%s'();", entry_name);
01944 }
01945 else
01946 {
01947 fprintf (out, " %s();", entry_name);
01948 }
01949 col += name_len + 4;
01950
01951 }
01952
01953 putc ('\n', out);
01954 putc ('}', out);
01955 putc ('\n', out);
01956 }
01957
01958
01959
01960 }
01961
01962
01963 void MD_print_md_template (FILE *out, MD *md)
01964 {
01965 MD_Section *section;
01966 MD_Symbol *symbol;
01967 int first_section;
01968
01969
01970 fprintf (out, "/*\n * %s template\n */\n", md->name);
01971
01972
01973 first_section = 1;
01974
01975
01976 for (symbol = md->section_table->head_symbol; symbol != NULL;
01977 symbol = symbol->next_symbol)
01978 {
01979
01980 section = (MD_Section *) symbol->data;
01981
01982
01983 if (!first_section)
01984 putc ('\n', out);
01985
01986
01987 else
01988 first_section = 0;
01989
01990
01991 MD_print_section_template (out, section);
01992 }
01993 }
01994
01995
01996
01997
01998
01999
02000
02001 MD_Section *MD_new_section (MD *md, char *name, int num_entries,
02002 int num_fields)
02003 {
02004 MD_Section *section;
02005 char *field_decl_desc, *entry_desc;
02006
02007
02008 section = (MD_Section *) L_alloc (MD_Section_pool);
02009
02010
02011 section->md = md;
02012 section->name = strdup (name);
02013
02014
02015 section->user_ext = NULL;
02016
02017
02018
02019
02020
02021 entry_desc = MD_concat_strings (name, "'s entry table");
02022 section->entry_table = MD_new_symbol_table (md, entry_desc, num_entries);
02023 free (entry_desc);
02024
02025
02026
02027
02028
02029
02030 field_decl_desc = MD_concat_strings (name, "'s field declaration table");
02031 section->field_decl_table = MD_new_symbol_table (md, field_decl_desc,
02032 num_fields);
02033 free (field_decl_desc);
02034
02035
02036
02037
02038 section->max_field_index = -1;
02039 section->field_decl = NULL;
02040 section->field_array_size = 0;
02041
02042
02043
02044
02045 if (num_fields != 0)
02046 {
02047 MD_resize_field_arrays (section, num_fields);
02048 }
02049
02050
02051
02052
02053
02054 section->symbol = MD_add_symbol (md->section_table, section->name,
02055 (void *) section);
02056
02057
02058 return (section);
02059 }
02060
02061
02062
02063
02064
02065
02066
02067 int _MD_num_sections (MD *md)
02068 {
02069
02070 return (md->section_table->symbol_count);
02071 }
02072
02073
02074
02075
02076
02077
02078
02079 MD_Section *_MD_find_section (MD *md, char *name)
02080 {
02081
02082 return ((MD_Section *) _MD_find_symbol_data(md->section_table, name));
02083 }
02084
02085
02086
02087
02088 MD_Section *MD_first_section (MD *md)
02089 {
02090 MD_Symbol *symbol;
02091
02092 symbol = md->section_table->head_symbol;
02093
02094 if (symbol != NULL)
02095 return ((MD_Section *) symbol->data);
02096 else
02097 return (NULL);
02098 }
02099
02100
02101
02102
02103 MD_Section *MD_last_section (MD *md)
02104 {
02105 MD_Symbol *symbol;
02106
02107 symbol = md->section_table->tail_symbol;
02108
02109 if (symbol != NULL)
02110 return ((MD_Section *) symbol->data);
02111 else
02112 return (NULL);
02113 }
02114
02115
02116
02117
02118
02119 MD_Section *MD_next_section (MD_Section *section)
02120 {
02121 MD_Symbol *symbol;
02122
02123 symbol = section->symbol->next_symbol;
02124
02125 if (symbol != NULL)
02126 return ((MD_Section *) symbol->data);
02127 else
02128 return (NULL);
02129 }
02130
02131
02132
02133
02134
02135 MD_Section *MD_prev_section (MD_Section *section)
02136 {
02137 MD_Symbol *symbol;
02138
02139 symbol = section->symbol->prev_symbol;
02140
02141 if (symbol != NULL)
02142 return ((MD_Section *) symbol->data);
02143 else
02144 return (NULL);
02145 }
02146
02147
02148
02149
02150
02151
02152
02153 void *_MD_set_section_ext(MD_Section *section, void *ext)
02154 {
02155 section->user_ext = ext;
02156
02157
02158 return (ext);
02159 }
02160
02161
02162
02163
02164
02165
02166
02167 void *_MD_get_section_ext(MD_Section *section)
02168 {
02169 return (section->user_ext);
02170 }
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180 void _MD_free_section (MD_Section *section)
02181 {
02182 char *name;
02183
02184
02185 name = section->name;
02186
02187
02188 MD_delete_symbol_table (section->entry_table,
02189 (void (*)(void *))_MD_free_entry);
02190
02191
02192
02193
02194
02195 MD_delete_symbol_table (section->field_decl_table,
02196 (void (*)(void *))_MD_free_field_decl);
02197
02198
02199 if (section->field_decl != NULL)
02200 free (section->field_decl);
02201
02202
02203 L_free (MD_Section_pool, section);
02204
02205
02206 free (name);
02207 }
02208
02209
02210
02211
02212
02213
02214
02215 void _MD_delete_section (MD_Section *section)
02216 {
02217
02218 MD_delete_symbol (section->symbol, (void(*)(void *))_MD_free_section);
02219 }
02220
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230
02231
02232
02233
02234
02235
02236
02237 int _MD_check_section (FILE *out, MD_Section *section, char *caller_name)
02238 {
02239 MD_Symbol *symbol;
02240 MD_Entry *entry;
02241 int error_count;
02242
02243
02244 error_count = 0;
02245
02246
02247 for (symbol = section->entry_table->head_symbol; symbol != NULL;
02248 symbol = symbol->next_symbol)
02249 {
02250
02251 entry = (MD_Entry *) symbol->data;
02252
02253
02254 error_count += _MD_check_entry (out, entry, caller_name);
02255 }
02256
02257
02258
02259 return (error_count);
02260 }
02261
02262
02263 void MD_print_section (FILE *out, MD_Section *section, int page_width)
02264 {
02265 MD_Field_Decl *field_decl;
02266 MD_Symbol *symbol;
02267 MD_Entry *entry;
02268
02269 fprintf (out, "SECTION %s\n", section->name);
02270
02271 for (symbol = section->field_decl_table->head_symbol; symbol != NULL;
02272 symbol = symbol->next_symbol)
02273 {
02274
02275 field_decl = (MD_Field_Decl *) symbol->data;
02276
02277
02278 MD_print_field_decl (out, field_decl, page_width);
02279 }
02280 fprintf (out, "{\n");
02281
02282
02283 for (symbol = section->entry_table->head_symbol; symbol != NULL;
02284 symbol = symbol->next_symbol)
02285 {
02286
02287 entry = (MD_Entry *) symbol->data;
02288
02289
02290 MD_print_entry (out, entry, page_width);
02291 }
02292
02293 fprintf (out, "}\n");
02294 }
02295
02296
02297 void MD_print_section_template (FILE *out, MD_Section *section)
02298 {
02299 MD_Symbol *symbol;
02300 MD_Entry *entry;
02301
02302 fprintf (out, "SECTION %s\n{\n", section->name);
02303
02304
02305 for (symbol = section->entry_table->head_symbol; symbol != NULL;
02306 symbol = symbol->next_symbol)
02307 {
02308
02309 entry = (MD_Entry *) symbol->data;
02310
02311
02312 MD_print_entry_template (out, entry);
02313 }
02314
02315 fprintf (out, "}\n");
02316 }
02317
02318
02319
02320
02321 MD_Entry *MD_new_entry (MD_Section *section, char *name)
02322 {
02323 MD_Entry *entry;
02324 int field_array_size;
02325 MD_Field **field_array;
02326 int i;
02327
02328
02329 entry = (MD_Entry *) L_alloc (MD_Entry_pool);
02330
02331
02332 entry->section = section;
02333 entry->name = strdup (name);
02334
02335
02336 entry->user_ext = NULL;
02337
02338
02339 field_array_size = section->field_array_size;
02340
02341
02342 if (field_array_size > 0)
02343 {
02344 field_array = (MD_Field **) malloc (sizeof(MD_Field *) *
02345 field_array_size);
02346 if (field_array == NULL)
02347 {
02348 MD_punt (section->md, "MD_new_entry: Out of memory (size %i)",
02349 field_array_size);
02350 }
02351
02352
02353 for (i=0; i < field_array_size; i++)
02354 field_array[i] = NULL;
02355
02356
02357 entry->field = field_array;
02358 }
02359
02360
02361 else
02362 {
02363 entry->field = NULL;
02364 }
02365
02366
02367
02368
02369 entry->symbol = MD_add_symbol (section->entry_table, entry->name,
02370 (void *) entry);
02371
02372
02373 return (entry);
02374 }
02375
02376
02377 void MD_rename_entry (MD_Entry *entry, char *new_name)
02378 {
02379 char *old_name;
02380
02381
02382
02383
02384
02385 old_name = entry->name;
02386 entry->name = strdup (new_name);
02387
02388
02389 MD_rename_symbol (entry->symbol, entry->name);
02390
02391
02392 free (old_name);
02393 }
02394
02395
02396
02397
02398
02399
02400
02401 int _MD_num_entries (MD_Section *section)
02402 {
02403
02404 return (section->entry_table->symbol_count);
02405 }
02406
02407
02408
02409
02410
02411
02412
02413 MD_Entry *_MD_find_entry (MD_Section *section, char *name)
02414 {
02415
02416 return ((MD_Entry *) _MD_find_symbol_data(section->entry_table, name));
02417 }
02418
02419
02420
02421
02422
02423 MD_Entry *MD_first_entry (MD_Section *section)
02424 {
02425 MD_Symbol *symbol;
02426
02427 symbol = section->entry_table->head_symbol;
02428
02429 if (symbol != NULL)
02430 return ((MD_Entry *) symbol->data);
02431 else
02432 return (NULL);
02433 }
02434
02435
02436
02437
02438
02439 MD_Entry *MD_last_entry (MD_Section *section)
02440 {
02441 MD_Symbol *symbol;
02442
02443 symbol = section->entry_table->tail_symbol;
02444
02445 if (symbol != NULL)
02446 return ((MD_Entry *) symbol->data);
02447 else
02448 return (NULL);
02449 }
02450
02451
02452
02453
02454
02455 MD_Entry *MD_next_entry (MD_Entry *entry)
02456 {
02457 MD_Symbol *symbol;
02458
02459 symbol = entry->symbol->next_symbol;
02460
02461 if (symbol != NULL)
02462 return ((MD_Entry *) symbol->data);
02463 else
02464 return (NULL);
02465 }
02466
02467
02468
02469
02470
02471 MD_Entry *MD_prev_entry (MD_Entry *entry)
02472 {
02473 MD_Symbol *symbol;
02474
02475 symbol = entry->symbol->prev_symbol;
02476
02477 if (symbol != NULL)
02478 return ((MD_Entry *) symbol->data);
02479 else
02480 return (NULL);
02481 }
02482
02483
02484
02485
02486
02487
02488
02489 void *_MD_set_entry_ext(MD_Entry *entry, void *ext)
02490 {
02491 entry->user_ext = ext;
02492
02493
02494 return (ext);
02495 }
02496
02497
02498
02499
02500
02501
02502
02503 void *_MD_get_entry_ext(MD_Entry *entry)
02504 {
02505 return (entry->user_ext);
02506 }
02507
02508
02509
02510
02511
02512
02513
02514
02515
02516 void _MD_free_entry (MD_Entry *entry)
02517 {
02518 char *name;
02519 int field_index, max_field_index;
02520 MD_Field **field_array, *field;
02521
02522
02523 name = entry->name;
02524
02525
02526 max_field_index = entry->section->max_field_index;
02527 field_array = entry->field;
02528
02529
02530
02531
02532 for (field_index=0; field_index <= max_field_index; field_index++)
02533 {
02534 field = field_array[field_index];
02535 if (field != NULL)
02536 MD_delete_field (field);
02537 }
02538
02539
02540 if (field_array != NULL)
02541 free (field_array);
02542
02543
02544 L_free (MD_Entry_pool, entry);
02545
02546
02547 free (name);
02548 }
02549
02550
02551
02552
02553
02554
02555
02556 void _MD_delete_entry (MD_Entry *entry)
02557 {
02558
02559 MD_delete_symbol (entry->symbol, (void(*)(void *))_MD_free_entry);
02560 }
02561
02562
02563
02564
02565
02566
02567
02568
02569
02570
02571
02572
02573
02574
02575
02576
02577 int _MD_check_entry (FILE *out, MD_Entry *entry, char *caller_name)
02578 {
02579 MD_Section *section;
02580 MD_Field_Decl *field_decl, **field_decl_array;
02581 MD_Field *field;
02582 int max_field_index, field_index;
02583 int error_count;
02584
02585
02586 error_count = 0;
02587
02588
02589 section = entry->section;
02590 field_decl_array = section->field_decl;
02591 max_field_index = section->max_field_index;
02592
02593
02594 for (field_index = 0; field_index <= max_field_index; field_index ++)
02595 {
02596
02597 field_decl = field_decl_array[field_index];
02598
02599
02600 if (field_decl == NULL)
02601 continue;
02602
02603
02604 field = entry->field[field_index];
02605
02606
02607 if (field != NULL)
02608 {
02609
02610 error_count += _MD_check_field (out, field, caller_name);
02611 }
02612
02613
02614 else if (field_decl->type == MD_REQUIRED_FIELD)
02615 {
02616 error_count++;
02617 if (out != NULL)
02618 {
02619 MD_warn (out,
02620 "%s(%s->%s->%s):\n Warning, required field '%s' unspecified for entry '%s'.",
02621 caller_name, section->name, entry->name,
02622 field_decl->name, field_decl->name, entry->name);
02623 }
02624 }
02625 }
02626
02627
02628 return (error_count);
02629 }
02630
02631
02632 static int MD_legal_ident (char *ident)
02633 {
02634
02635 char *ptr;
02636
02637
02638 if ((ident[0] != '_') && !isalpha (ident[0]))
02639 return (0);
02640
02641
02642 for (ptr = &ident[1]; *ptr != 0; ptr++)
02643 {
02644 if ((*ptr != '_') && !isalnum (*ptr))
02645 return (0);
02646 }
02647
02648
02649 return (1);
02650 }
02651
02652
02653
02654
02655 void MD_print_entry (FILE *out, MD_Entry *entry, int page_width)
02656 {
02657 MD_Field **field_array, *field;
02658 MD_Field_Decl *field_decl;
02659 MD_Symbol *symbol;
02660 MD_Section *section;
02661 MD_Element **element_array, *element;
02662 char *entry_name, *field_name, *link_name;
02663 int effective_name_len, field_name_indent, first_field;
02664 int element_value_indent, value_len, print_column;
02665 int element_index, first_element;
02666 int max_assigned_index, link_valid_ident;
02667 char value_buf[500];
02668 int i;
02669
02670
02671
02672
02673
02674 field_name_indent = 17;
02675
02676
02677 entry_name = entry->name;
02678 field_array = entry->field;
02679 section = entry->section;
02680
02681
02682 if (!MD_legal_ident(entry_name))
02683 {
02684 fprintf (out, " '%s'", entry_name);
02685
02686
02687
02688
02689 effective_name_len = strlen (entry_name) + 4;
02690 }
02691 else
02692 {
02693 fprintf (out, " %s", entry_name);
02694
02695
02696
02697
02698 effective_name_len = strlen (entry_name) + 2;
02699 }
02700
02701
02702
02703
02704 if ((effective_name_len + 1) > field_name_indent)
02705 {
02706
02707 putc ('\n', out);
02708
02709
02710 for (i=1; i < field_name_indent; i++)
02711 putc (' ', out);
02712 }
02713 else
02714 {
02715
02716 for (i=effective_name_len + 1; i < field_name_indent; i++)
02717 putc (' ', out);
02718 }
02719
02720
02721 putc ('(', out);
02722
02723
02724 first_field = 1;
02725
02726
02727
02728
02729 for (symbol = section->field_decl_table->head_symbol; symbol != NULL;
02730 symbol = symbol->next_symbol)
02731 {
02732
02733 field_decl = (MD_Field_Decl *) symbol->data;
02734
02735
02736 field = field_array[field_decl->field_index];
02737
02738
02739 if (field == NULL)
02740 continue;
02741
02742
02743 if (!first_field)
02744 {
02745
02746 putc ('\n', out);
02747
02748
02749 for (i=0; i < field_name_indent; i++)
02750 putc (' ', out);
02751 }
02752
02753 else
02754 {
02755 first_field = 0;
02756 }
02757
02758
02759 field_name = field_decl->name;
02760
02761
02762 element_value_indent = field_name_indent + strlen(field_name) + 1;
02763
02764
02765 fprintf (out, "%s(", field_name);
02766
02767
02768 print_column = element_value_indent;
02769
02770
02771 element_array = field->element;
02772
02773
02774 max_assigned_index = field->max_element_index;
02775 while ((max_assigned_index >= 0) &&
02776 (element_array[max_assigned_index] == NULL))
02777 max_assigned_index--;
02778
02779
02780
02781
02782 first_element = 1;
02783
02784
02785 for (element_index = 0; element_index <= max_assigned_index;
02786 element_index ++)
02787 {
02788
02789 element = element_array[element_index];
02790
02791
02792
02793
02794 if (element == NULL)
02795 value_len = 2;
02796 else
02797 {
02798 switch (element->type)
02799 {
02800 case MD_INT:
02801
02802 sprintf (value_buf, "%i", element->value.i);
02803 value_len = strlen (value_buf);
02804 break;
02805
02806 case MD_DOUBLE:
02807
02808
02809
02810
02811 sprintf (value_buf, "%.10f", element->value.d);
02812 value_len = strlen (value_buf);
02813 while (value_len >= 2)
02814 {
02815
02816
02817
02818 if ((value_buf[value_len-1] != '0') ||
02819 (value_buf[value_len-2] == '.'))
02820 break;
02821
02822
02823 value_len--;
02824 value_buf[value_len] = 0;
02825 }
02826 break;
02827
02828 case MD_STRING:
02829
02830 value_len = strlen(element->value.s) + 2;
02831 break;
02832
02833 case MD_LINK:
02834
02835 link_name = element->value.l->name;
02836 link_valid_ident = MD_legal_ident (link_name);
02837 if (link_valid_ident)
02838 value_len = strlen(link_name);
02839 else
02840 value_len = strlen(link_name) + 2;
02841 break;
02842
02843 default:
02844 MD_punt (entry->section->md,
02845 "MD_print_entry: Unknown element type '%i'",
02846 element->type);
02847 }
02848 }
02849
02850
02851
02852
02853
02854
02855 if (!first_element)
02856 {
02857
02858
02859
02860 if ((print_column + value_len) >= (page_width - 4))
02861 {
02862
02863 putc ('\n', out);
02864
02865
02866 for (i=0; i < element_value_indent; i++)
02867 putc (' ', out);
02868
02869
02870 print_column = element_value_indent;
02871 }
02872
02873
02874 else
02875 {
02876 putc (' ', out);
02877
02878
02879 print_column++;
02880 }
02881 }
02882
02883
02884
02885 else
02886 {
02887 first_element = 0;
02888 }
02889
02890
02891 print_column += value_len;
02892
02893
02894
02895
02896
02897
02898 if (element == NULL)
02899 {
02900 fprintf (out, "()");
02901 continue;
02902 }
02903
02904 switch (element->type)
02905 {
02906
02907 case MD_INT:
02908 case MD_DOUBLE:
02909 fprintf (out, "%s", value_buf);
02910 break;
02911
02912 case MD_STRING:
02913
02914 fprintf (out, "\"%s\"", element->value.s);
02915 break;
02916
02917 case MD_LINK:
02918
02919
02920
02921 link_name = element->value.l->name;
02922 if (link_valid_ident)
02923 fprintf (out, "%s", link_name);
02924 else
02925 fprintf (out, "'%s'", link_name);
02926 break;
02927
02928 default:
02929 MD_punt (entry->section->md,
02930 "MD_print_entry: Unknown element type '%i'",
02931 element->type);
02932 }
02933 }
02934
02935 fprintf (out, ")");
02936 }
02937
02938
02939 fprintf (out, ");\n");
02940 }
02941
02942
02943
02944
02945
02946
02947
02948 void MD_print_entry_template (FILE *out, MD_Entry *entry)
02949 {
02950 char *entry_name;
02951 int effective_name_len, field_name_indent;
02952 int i;
02953
02954
02955
02956
02957
02958 field_name_indent = 17;
02959
02960
02961 entry_name = entry->name;
02962
02963
02964 if (!MD_legal_ident(entry_name))
02965 {
02966 fprintf (out, " '%s'", entry_name);
02967
02968
02969
02970
02971 effective_name_len = strlen (entry_name) + 4;
02972 }
02973 else
02974 {
02975 fprintf (out, " %s", entry_name);
02976
02977
02978
02979
02980 effective_name_len = strlen (entry_name) + 2;
02981 }
02982
02983
02984
02985 for (i=effective_name_len + 1; i < field_name_indent; i++)
02986 putc (' ', out);
02987
02988
02989
02990 putc ('(', out);
02991 putc (')', out);
02992 putc (';', out);
02993 putc ('\n', out);
02994 }
02995
02996
02997 MD_Field_Decl *MD_new_field_decl (MD_Section *section, char *name,
02998 MD_FIELD_TYPE field_type)
02999 {
03000 MD_Field_Decl *field_decl, **decl_array;
03001 int new_index, max_index;
03002
03003
03004 field_decl = (MD_Field_Decl *) L_alloc (MD_Field_Decl_pool);
03005
03006
03007 field_decl->section = section;
03008 field_decl->name = strdup (name);
03009 field_decl->type = field_type;
03010
03011 field_decl->max_require_index = -1;
03012 field_decl->require = NULL;
03013 field_decl->require_array_size = 0;
03014 field_decl->kleene_starred_req= NULL;
03015
03016
03017 max_index = section->max_field_index;
03018 decl_array = section->field_decl;
03019 for (new_index=0; new_index <= max_index; new_index ++)
03020 {
03021
03022 if (decl_array[new_index] == NULL)
03023 break;
03024 }
03025
03026
03027 if (new_index >= section->field_array_size)
03028 MD_resize_field_arrays (section, new_index);
03029
03030
03031
03032
03033
03034 section->field_decl[new_index] = field_decl;
03035 field_decl->field_index = new_index;
03036
03037
03038 if (section->max_field_index < new_index)
03039 section->max_field_index = new_index;
03040
03041
03042
03043
03044 field_decl->symbol = MD_add_symbol (section->field_decl_table,
03045 field_decl->name, (void *) field_decl);
03046
03047
03048 return (field_decl);
03049 }
03050
03051
03052
03053
03054
03055
03056
03057
03058
03059 static void MD_resize_field_arrays (MD_Section *section, int max_index)
03060 {
03061 MD_Field_Decl **new_decl_array, **old_decl_array;
03062 MD_Symbol *symbol;
03063 MD_Entry *entry;
03064 MD_Field **new_field_array, **old_field_array;
03065 int max_field_index, new_array_size, i;
03066
03067
03068
03069
03070
03071 new_array_size = (max_index | 1) + 3;
03072
03073
03074 if (new_array_size <= section->field_array_size)
03075 {
03076 MD_punt (section->md,
03077 "MD_resize_field_arrays: new_array_size (%i) must be > current size (%i)",
03078 new_array_size, section->field_array_size);
03079 }
03080
03081
03082 max_field_index = section->max_field_index;
03083
03084
03085
03086
03087
03088
03089 new_decl_array = (MD_Field_Decl **) malloc (sizeof (MD_Field_Decl *) *
03090 new_array_size);
03091 if (new_decl_array == NULL)
03092 {
03093 MD_punt (section->md,
03094 "MD_resize_field_arrays: Out of memory (size %i)",
03095 new_array_size);
03096 }
03097
03098
03099 old_decl_array = section->field_decl;
03100
03101
03102
03103
03104 for (i=0; i <= max_field_index; i++)
03105 new_decl_array[i] = old_decl_array[i];
03106
03107
03108 for (i=max_field_index + 1; i < new_array_size; i++)
03109 new_decl_array[i] = NULL;
03110
03111
03112 if (old_decl_array != NULL)
03113 free (old_decl_array);
03114
03115
03116 section->field_decl = new_decl_array;
03117 section->field_array_size = new_array_size;
03118
03119
03120
03121
03122
03123
03124 for (symbol = section->entry_table->head_symbol; symbol != NULL;
03125 symbol = symbol->next_symbol)
03126 {
03127
03128 entry = (MD_Entry *) symbol->data;
03129
03130
03131 new_field_array = (MD_Field **) malloc (sizeof (MD_Field *) *
03132 new_array_size);
03133 if (new_field_array == NULL)
03134 {
03135 MD_punt (section->md,
03136 "MD_resize_field_arrays: Out of memory (size %i)",
03137 new_array_size);
03138 }
03139
03140
03141 old_field_array = entry->field;
03142
03143
03144
03145
03146 for (i=0; i <= max_field_index; i++)
03147 new_field_array[i] = old_field_array[i];
03148
03149
03150 for (i=max_field_index + 1; i < new_array_size; i++)
03151 new_field_array[i] = NULL;
03152
03153
03154 if (old_field_array != NULL)
03155 free (old_field_array);
03156
03157
03158 entry->field = new_field_array;
03159 }
03160 }
03161
03162
03163
03164
03165
03166
03167
03168 int _MD_num_field_decls (MD_Section *section)
03169 {
03170
03171 return (section->field_decl_table->symbol_count);
03172 }
03173
03174
03175
03176
03177
03178
03179
03180 int _MD_max_field_index (MD_Section *section)
03181 {
03182
03183 return (section->max_field_index);
03184 }
03185
03186
03187
03188
03189
03190
03191
03192 MD_Field_Decl *_MD_find_field_decl (MD_Section *section, char *name)
03193 {
03194
03195 return ((MD_Field_Decl *) _MD_find_symbol_data(section->field_decl_table,
03196 name));
03197 }
03198
03199
03200
03201
03202
03203 MD_Field_Decl *MD_first_field_decl (MD_Section *section)
03204 {
03205 MD_Symbol *symbol;
03206
03207 symbol = section->field_decl_table->head_symbol;
03208
03209 if (symbol != NULL)
03210 return ((MD_Field_Decl *) symbol->data);
03211 else
03212 return (NULL);
03213 }
03214
03215
03216
03217
03218
03219 MD_Field_Decl *MD_last_field_decl (MD_Section *section)
03220 {
03221 MD_Symbol *symbol;
03222
03223 symbol = section->field_decl_table->tail_symbol;
03224
03225 if (symbol != NULL)
03226 return ((MD_Field_Decl *) symbol->data);
03227 else
03228 return (NULL);
03229 }
03230
03231
03232
03233
03234
03235 MD_Field_Decl *MD_next_field_decl (MD_Field_Decl *field_decl)
03236 {
03237 MD_Symbol *symbol;
03238
03239 symbol = field_decl->symbol->next_symbol;
03240
03241 if (symbol != NULL)
03242 return ((MD_Field_Decl *) symbol->data);
03243 else
03244 return (NULL);
03245 }
03246
03247
03248
03249
03250
03251 MD_Field_Decl *MD_prev_field_decl (MD_Field_Decl *field_decl)
03252 {
03253 MD_Symbol *symbol;
03254
03255 symbol = field_decl->symbol->prev_symbol;
03256
03257 if (symbol != NULL)
03258 return ((MD_Field_Decl *) symbol->data);
03259 else
03260 return (NULL);
03261 }
03262
03263
03264
03265
03266
03267
03268
03269
03270
03271
03272
03273
03274
03275
03276 void _MD_free_field_decl (MD_Field_Decl *field_decl)
03277 {
03278 char *name;
03279 MD_Element_Req **require, *element_req;
03280 int i, max_require_index;
03281
03282
03283 name = field_decl->name;
03284
03285
03286 field_decl->section->field_decl[field_decl->field_index] = NULL;
03287
03288
03289 require = field_decl->require;
03290 max_require_index = field_decl->max_require_index;
03291
03292
03293
03294 for (i=0; i <= max_require_index; i++)
03295 {
03296
03297 element_req = require[i];
03298
03299
03300 free (element_req->desc);
03301
03302
03303 if (element_req->type == MD_LINK)
03304 free (element_req->link);
03305
03306
03307 L_free (MD_Element_Req_pool, element_req);
03308 }
03309
03310
03311 if (require != NULL)
03312 free (require);
03313
03314
03315 L_free (MD_Field_Decl_pool, field_decl);
03316
03317
03318 free (name);
03319 }
03320
03321
03322
03323
03324 void MD_delete_field_decl (MD_Field_Decl *field_decl)
03325 {
03326 MD_Section *section;
03327 MD_Symbol *symbol;
03328 MD_Entry *entry;
03329 MD_Field *field;
03330 int field_index;
03331
03332
03333 section = field_decl->section;
03334
03335
03336 field_index = field_decl->field_index;
03337
03338
03339
03340
03341
03342 for (symbol = section->entry_table->head_symbol; symbol != NULL;
03343 symbol = symbol->next_symbol)
03344 {
03345
03346 entry = (MD_Entry *) symbol->data;
03347
03348
03349 field = entry->field[field_index];
03350
03351 if (field != NULL)
03352 {
03353 MD_delete_field (field);
03354 }
03355 }
03356
03357
03358 MD_delete_symbol (field_decl->symbol,
03359 (void(*)(void *))_MD_free_field_decl);
03360 }
03361
03362
03363
03364
03365 void MD_print_field_decl (FILE *out, MD_Field_Decl *field_decl, int page_width)
03366 {
03367 MD_Element_Req **require_array, *require;
03368 MD_FIELD_TYPE type;
03369 char *field_name;
03370 int decl_len;
03371 int max_require_index, require_index, first_requirement;
03372 int require_indent, print_column, i;
03373
03374
03375 type = field_decl->type;
03376 require_array = field_decl->require;
03377 max_require_index = field_decl->max_require_index;
03378 field_name = field_decl->name;
03379
03380
03381 if (type == MD_REQUIRED_FIELD)
03382 {
03383 fprintf (out, " REQUIRED ");
03384 }
03385 else if (type == MD_OPTIONAL_FIELD)
03386 {
03387 fprintf (out, " OPTIONAL ");
03388 }
03389 else
03390 {
03391 MD_punt (field_decl->section->md,
03392 "MD_print_field_decl: Unknown field decl type '%i'",type);
03393 }
03394
03395
03396 fprintf (out, "%s(", field_name);
03397
03398
03399 require_indent = strlen (field_name) + 12;
03400
03401
03402 print_column = require_indent;
03403
03404
03405 first_requirement = 1;
03406
03407
03408 for (require_index = 0; require_index <= max_require_index;
03409 require_index++)
03410 {
03411
03412 require = require_array[require_index];
03413
03414
03415 decl_len = strlen (require->desc);
03416
03417
03418
03419
03420
03421
03422
03423 if (!first_requirement)
03424 {
03425
03426
03427
03428 if ((print_column + decl_len) >= (page_width - 3))
03429 {
03430
03431 putc ('\n', out);
03432
03433
03434 for (i=0; i < require_indent; i++)
03435 putc (' ', out);
03436
03437
03438 print_column = require_indent;
03439 }
03440
03441
03442 else
03443 {
03444 putc (' ', out);
03445 print_column ++;
03446 }
03447 }
03448
03449
03450
03451
03452 else
03453 {
03454 first_requirement = 0;
03455 }
03456
03457
03458 print_column += decl_len;
03459
03460
03461 fprintf (out, "%s", require->desc);
03462 }
03463
03464
03465 fprintf (out, ");\n");
03466 }
03467
03468
03469
03470
03471
03472
03473
03474
03475
03476
03477
03478
03479
03480
03481
03482
03483
03484 static MD_Element_Req *MD_new_element_req (MD_Field_Decl *field_decl,
03485 int index, char *caller_name)
03486 {
03487 MD_Element_Req *element_req, **old_require_array, **new_require_array;
03488 int i, new_array_size, max_require_index;
03489
03490
03491 max_require_index = field_decl->max_require_index;
03492
03493
03494
03495
03496 if (index != (max_require_index + 1))
03497 {
03498
03499 if (index <= max_require_index)
03500 {
03501 MD_punt (field_decl->section->md,
03502 "%s(%s->*->%s[%i]):\n Element %i already required to be '%s'!",
03503 caller_name, field_decl->section->name, field_decl->name,
03504 index, index, field_decl->require[index]->desc);
03505 }
03506
03507 else
03508 {
03509 MD_punt (field_decl->section->md,
03510 "%s(%s->*->%s[%i]):\n Specify requirements for elements before %i first!",
03511 caller_name, field_decl->section->name, field_decl->name,
03512 index, index);
03513 }
03514 }
03515
03516
03517
03518
03519 if (field_decl->kleene_starred_req != NULL)
03520 {
03521 MD_punt (field_decl->section->md,
03522 "%s(%s->*->%s[%i]):\n Cannot specify requirements after a kleene starred requirement!",
03523 caller_name, field_decl->section->name, field_decl->name,
03524 index);
03525 }
03526
03527
03528 if (index >= field_decl->require_array_size)
03529 {
03530
03531
03532
03533
03534 new_array_size = (index | 1) + 3;
03535
03536
03537 new_require_array =(MD_Element_Req **)malloc(sizeof(MD_Element_Req *) *
03538 new_array_size);
03539 if (new_require_array == NULL)
03540 {
03541 MD_punt (field_decl->section->md,
03542 "Out of memory resizing require array (size %i).",
03543 new_array_size);
03544 }
03545
03546
03547 old_require_array = field_decl->require;
03548
03549
03550
03551
03552 for (i=0; i <= max_require_index; i++)
03553 new_require_array[i] = old_require_array[i];
03554
03555
03556 for (i=max_require_index + 1; i < new_array_size; i++)
03557 new_require_array[i] = NULL;
03558
03559
03560 if (old_require_array != NULL)
03561 free (old_require_array);
03562
03563
03564 field_decl->require = new_require_array;
03565 field_decl->require_array_size = new_array_size;
03566 }
03567
03568
03569 element_req = (MD_Element_Req *) L_alloc (MD_Element_Req_pool);
03570
03571
03572
03573
03574 element_req->field_decl = field_decl;
03575 element_req->require_index = index;
03576 element_req->kleene_starred = 0;
03577 element_req->link = NULL;
03578 element_req->link_array_size = 0;
03579
03580
03581 field_decl->require[index] = element_req;
03582
03583
03584
03585
03586 field_decl->max_require_index = index;
03587
03588
03589 return (element_req);
03590 }
03591
03592
03593
03594
03595
03596
03597 void MD_require_int (MD_Field_Decl *field_decl, int element_index)
03598 {
03599 MD_Element_Req *element_req;
03600
03601
03602
03603
03604
03605
03606
03607
03608 element_req = MD_new_element_req (field_decl, element_index,
03609 "MD_require_int");
03610
03611
03612
03613
03614 element_req->type = MD_INT;
03615 element_req->desc = strdup ("INT");
03616 }
03617
03618
03619
03620
03621
03622
03623 void MD_require_double (MD_Field_Decl *field_decl, int element_index)
03624 {
03625 MD_Element_Req *element_req;
03626
03627
03628
03629
03630
03631
03632
03633
03634 element_req = MD_new_element_req (field_decl, element_index,
03635 "MD_require_double");
03636
03637
03638
03639
03640 element_req->type = MD_DOUBLE;
03641 element_req->desc = strdup ("DOUBLE");
03642 }
03643
03644
03645
03646
03647
03648
03649 void MD_require_string (MD_Field_Decl *field_decl, int element_index)
03650 {
03651 MD_Element_Req *element_req;
03652
03653
03654
03655
03656
03657
03658
03659
03660 element_req = MD_new_element_req (field_decl, element_index,
03661 "MD_require_string");
03662
03663
03664
03665
03666 element_req->type = MD_STRING;
03667 element_req->desc = strdup ("STRING");
03668 }
03669
03670
03671
03672
03673
03674
03675
03676
03677 void MD_require_link (MD_Field_Decl *field_decl, int element_index,
03678 MD_Section *section)
03679 {
03680 MD_Element_Req *element_req;
03681 MD_Section **link;
03682 int desc_length;
03683 char *desc;
03684
03685
03686
03687
03688
03689
03690
03691
03692
03693 element_req = MD_new_element_req (field_decl, element_index,
03694 "MD_require_link");
03695
03696
03697
03698 link = (MD_Section **)malloc (sizeof(MD_Section *));
03699 if (link == NULL)
03700 {
03701 MD_punt (field_decl->section->md,
03702 "Out of memory allocating link array (size 1)");
03703 }
03704
03705
03706 link[0] = section;
03707
03708
03709 desc_length = strlen(section->name) + strlen("LINK()") + 1;
03710
03711
03712 desc = (char *) malloc (sizeof(char) * desc_length);
03713 if (desc == NULL)
03714 {
03715 MD_punt (field_decl->section->md,
03716 "Out of memory allocating link desc (size %i)",
03717 desc_length);
03718 }
03719
03720
03721 desc[desc_length-1] = 1;
03722
03723
03724 sprintf (desc,"LINK(%s)", section->name);
03725
03726
03727 if (desc[desc_length-1] != 0)
03728 {
03729 MD_punt (field_decl->section->md,
03730 "link->desc incorrect length (%i)", desc_length);
03731 }
03732
03733
03734
03735
03736 element_req->type = MD_LINK;
03737 element_req->desc = desc;
03738 element_req->link = link;
03739 element_req->link_array_size = 1;
03740 }
03741
03742
03743
03744
03745
03746
03747
03748 void MD_require_multi_target_link (MD_Field_Decl *field_decl,
03749 int element_index, int section_array_size,
03750 MD_Section **section_array)
03751 {
03752 MD_Element_Req *element_req;
03753 MD_Section **link, *section;
03754 int desc_length;
03755 char *desc, *desc_ptr, *name_ptr;
03756 int i;
03757
03758
03759
03760
03761
03762
03763
03764
03765
03766 element_req = MD_new_element_req (field_decl, element_index,
03767 "MD_require_multi_target_link");
03768
03769
03770 if (section_array_size <= 0)
03771 {
03772 MD_punt (field_decl->section->md,
03773 "MD_require_multi_target_link: invalid array size (%i).",
03774 section_array_size);
03775 }
03776
03777
03778 link = (MD_Section **)malloc (sizeof(MD_Section *) * section_array_size);
03779 if (link == NULL)
03780 {
03781 MD_punt (field_decl->section->md,
03782 "Out of memory allocating link array (size %i)",
03783 section_array_size);
03784 }
03785
03786
03787 desc_length = 0;
03788 for (i=0; i < section_array_size; i++)
03789 {
03790 section = section_array[i];
03791 link[i] = section;
03792
03793
03794 desc_length += strlen (section->name);
03795 }
03796
03797
03798 desc_length += strlen ("LINK()");
03799
03800
03801 desc_length += section_array_size;
03802
03803
03804 desc = (char *) malloc (sizeof(char) * desc_length);
03805 if (desc == NULL)
03806 MD_punt (field_decl->section->md,
03807 "Out of memory allocating link desc (size %i)",
03808 desc_length);
03809
03810
03811 desc[desc_length-1] = 1;
03812
03813
03814 strcpy (desc, "LINK(");
03815 desc_ptr = &desc[5];
03816
03817 for (i=0; i < section_array_size; i++)
03818 {
03819
03820 for (name_ptr = link[i]->name; *name_ptr != 0; name_ptr++)
03821 {
03822 *desc_ptr = *name_ptr;
03823 desc_ptr++;
03824 }
03825
03826 if ((i+1) < section_array_size)
03827 {
03828 *desc_ptr = '|';
03829 desc_ptr++;
03830 }
03831 }
03832
03833
03834 *desc_ptr = ')';
03835 desc_ptr++;
03836 *desc_ptr = 0;
03837
03838
03839 if (desc[desc_length-1] != 0)
03840 {
03841 MD_punt (field_decl->section->md,
03842 "link->desc incorrect length (%i)", desc_length);
03843 }
03844
03845
03846
03847
03848 element_req->type = MD_LINK;
03849 element_req->desc = desc;
03850 element_req->link = link;
03851 element_req->link_array_size = section_array_size;
03852 }
03853
03854
03855
03856
03857
03858
03859
03860 void MD_kleene_star_requirement (MD_Field_Decl *field_decl, int element_index)
03861 {
03862 MD_Element_Req *element_req;
03863 char *new_desc;
03864 int max_require_index;
03865
03866 max_require_index = field_decl->max_require_index;
03867
03868
03869 if ((element_index < 0) || (element_index > max_require_index))
03870 {
03871 MD_punt (field_decl->section->md,
03872 "MD_kleene_star_requirement(%s->*->%s[%i]:\n Invalid element index %i (the max valid index is %i).",
03873 field_decl->section->name, field_decl->name,
03874 element_index, element_index, max_require_index);
03875 }
03876
03877
03878 if (element_index != max_require_index)
03879 {
03880 MD_punt (field_decl->section->md,
03881 "MD_kleene_star_requirement(%s->*->%s[%i]:\n Only the last requirment (%i) may be kleene starred.",
03882 field_decl->section->name, field_decl->name,
03883 element_index, max_require_index);
03884 }
03885
03886
03887 element_req = field_decl->require[element_index];
03888
03889
03890 if (element_req->kleene_starred)
03891 {
03892 MD_punt (field_decl->section->md,
03893 "MD_kleene_star_requirement(%s->*->%s[%i]:\n Requirement already kleene starred.",
03894 field_decl->section->name, field_decl->name,
03895 element_index);
03896
03897 }
03898
03899
03900 if (field_decl->kleene_starred_req != NULL)
03901 {
03902 MD_punt (field_decl->section->md,
03903 "MD_kleene_star_requirement(%s->*->%s[%i]:\n Algorithm error, %i marked kleene starred... why?.",
03904 field_decl->section->name, field_decl->name,
03905 element_index, field_decl->kleene_starred_req->require_index);
03906 }
03907
03908
03909 element_req->kleene_starred = 1;
03910 field_decl->kleene_starred_req = element_req;
03911
03912
03913 new_desc = MD_concat_strings (element_req->desc, "*");
03914
03915
03916 free (element_req->desc);
03917
03918
03919 element_req->desc = new_desc;
03920 }
03921
03922
03923
03924
03925
03926
03927 MD_Field *MD_new_field (MD_Entry *entry, MD_Field_Decl *decl,
03928 int num_elements)
03929 {
03930 MD_Field *field, **field_slot;
03931
03932
03933 if (MD_Field_pool == NULL)
03934 {
03935 MD_punt (NULL,
03936 "MD routines not initialized (call MD_new_md() first)!");
03937 }
03938 field = (MD_Field *) L_alloc (MD_Field_pool);
03939
03940
03941 field->entry = entry;
03942 field->decl = decl;
03943 field->max_element_index = -1;
03944
03945
03946 field_slot = &entry->field[decl->field_index];
03947
03948
03949 if (*field_slot != NULL)
03950 {
03951 MD_punt (entry->section->md,
03952 "%s, entry %s: Cannot create field '%s', already exists!",
03953 entry->section->name, entry->name, decl->name);
03954 }
03955
03956
03957 *field_slot = field;
03958
03959
03960 if (num_elements < 0)
03961 {
03962 MD_punt (entry->section->md,
03963 "%s, entry %s, creating field %i: num_elements (%i) must be >= 0",
03964 entry->section->name, entry->name, decl->name, num_elements);
03965 }
03966
03967
03968 field->element = NULL;
03969 field->element_array_size = 0;
03970
03971
03972 if (num_elements > 0)
03973 {
03974 MD_resize_element_array (field, num_elements - 1);
03975 }
03976
03977 return (field);
03978 }
03979
03980
03981 static void MD_resize_element_array (MD_Field *field, int max_index)
03982 {
03983 MD_Element **old_array, **new_array;
03984 int new_size;
03985 int i;
03986
03987
03988
03989
03990
03991 new_size = (max_index | 3) + 1;
03992
03993
03994 if (new_size <= field->element_array_size)
03995 {
03996 MD_punt (field->entry->section->md,
03997 "MD_resize_element_array: new_size (%i) must be > current size (%i)",
03998 new_size, field->element_array_size);
03999 }
04000
04001
04002 new_array = (MD_Element **) malloc (sizeof(MD_Element *) * new_size);
04003 if (new_array == NULL)
04004 {
04005 MD_punt (field->entry->section->md,
04006 "MD_resize_element_array: Out of memory");
04007 }
04008
04009
04010 old_array = field->element;
04011
04012
04013
04014
04015 for (i=field->max_element_index; i >= 0; i--)
04016 new_array[i] = old_array[i];
04017
04018
04019 for (i=field->max_element_index + 1; i < new_size; i++)
04020 new_array[i] = NULL;
04021
04022
04023 if (old_array != NULL)
04024 free (old_array);
04025
04026
04027 field->element = new_array;
04028 field->element_array_size = new_size;
04029 }
04030
04031
04032
04033
04034
04035
04036 MD_Field *_MD_find_field (MD_Entry *entry, MD_Field_Decl *field_decl)
04037 {
04038 MD_Field *field;
04039
04040
04041 if (entry->section != field_decl->section)
04042 {
04043 MD_punt (entry->section->md,
04044 "MD_find_field: entry (%s) from section %s and field decl (%s) from %s!",
04045 entry->name, entry->section->name, field_decl->name,
04046 field_decl->section->name);
04047 }
04048
04049
04050 field = entry->field[field_decl->field_index];
04051
04052 return (field);
04053 }
04054
04055
04056 void MD_delete_field (MD_Field *field)
04057 {
04058 MD_Element *element, **element_array;
04059 int index, max_element_index;
04060
04061
04062 max_element_index = field->max_element_index;
04063 element_array = field->element;
04064
04065
04066
04067
04068 for (index = 0; index <= max_element_index; index++)
04069 {
04070
04071 element = element_array[index];
04072
04073
04074 if (element != NULL)
04075 {
04076
04077 if (element->type == MD_STRING)
04078 free (element->value.s);
04079
04080 L_free (MD_Element_pool, element);
04081 }
04082 }
04083
04084
04085 if (element_array != NULL)
04086 free (element_array);
04087
04088
04089 field->entry->field[field->decl->field_index] = NULL;
04090
04091
04092 L_free (MD_Field_pool, field);
04093 }
04094
04095
04096
04097
04098
04099
04100
04101
04102
04103
04104
04105
04106
04107
04108
04109 int _MD_check_field (FILE *out, MD_Field *field, char *caller_name)
04110 {
04111 MD_Field_Decl *field_decl;
04112 MD_Element_Req **require_array, *requirement, *kleene_starred_req;
04113 MD_Element **element_array, *element;
04114 MD_Section *section, **link_array, *target_section;
04115 MD_Entry *entry;
04116 int max_element_index, max_require_index;
04117 int max_non_kleene_index, max_assigned_index, max_check_index;
04118 int link_array_size, valid_link;
04119 int i, j;
04120 int error_count;
04121
04122
04123 error_count = 0;
04124
04125
04126 field_decl = field->decl;
04127 element_array = field->element;
04128 max_element_index = field->max_element_index;
04129 require_array = field_decl->require;
04130 max_require_index = field_decl->max_require_index;
04131 kleene_starred_req = field_decl->kleene_starred_req;
04132 entry = field->entry;
04133 section = entry->section;
04134
04135
04136 max_assigned_index = max_element_index;
04137 while ((max_assigned_index >= 0) &&
04138 (element_array[max_assigned_index] == NULL))
04139 max_assigned_index--;
04140
04141
04142 if (kleene_starred_req != NULL)
04143 max_non_kleene_index = max_require_index -1;
04144 else
04145 max_non_kleene_index = max_require_index;
04146
04147
04148
04149
04150
04151 if (max_assigned_index > max_non_kleene_index)
04152 max_check_index = max_assigned_index;
04153 else
04154 max_check_index = max_non_kleene_index;
04155
04156
04157
04158 for (i=0; (i <= max_check_index); i++)
04159 {
04160 if (i <= max_assigned_index)
04161 element = element_array[i];
04162 else
04163 element = NULL;
04164
04165 if (i <= max_non_kleene_index)
04166 requirement = require_array[i];
04167 else
04168 requirement = kleene_starred_req;
04169
04170
04171
04172
04173 if ((element == NULL) && (requirement == NULL))
04174 continue;
04175
04176
04177 if (element == NULL)
04178 {
04179 error_count++;
04180 if (out != NULL)
04181 {
04182 MD_warn (out,
04183 "%s(%s->%s->%s[%i]):\n Warning, %s required not NULL.",
04184 caller_name, section->name, entry->name,
04185 field_decl->name, i, requirement->desc);
04186 }
04187 }
04188
04189
04190 else if (requirement == NULL)
04191 {
04192 error_count++;
04193 if (out != NULL)
04194 {
04195 MD_warn (out,
04196 "%s(%s->%s->%s[%i]):\n Warning, NULL required not %s.",
04197 caller_name, section->name, entry->name,
04198 field_decl->name, i, MD_type_name[element->type]);
04199 }
04200 }
04201
04202 else if (element->type != requirement->type)
04203 {
04204 error_count++;
04205 if (out != NULL)
04206 {
04207 MD_warn (out,
04208 "%s(%s->%s->%s[%i]):\n Warning, %s required not %s.",
04209 caller_name, section->name, entry->name,
04210 field_decl->name, i, requirement->desc,
04211 MD_type_name[element->type]);
04212 }
04213 }
04214 else if (element->type == MD_LINK)
04215 {
04216 link_array = requirement->link;
04217 link_array_size = requirement->link_array_size;
04218 target_section = element->value.l->section;
04219 valid_link = 0;
04220
04221 for (j=0; j < link_array_size; j++)
04222 {
04223 if (link_array[j] == target_section)
04224 {
04225 valid_link = 1;
04226 break;
04227 }
04228 }
04229
04230 if (!valid_link)
04231 {
04232 error_count++;
04233 if (out != NULL)
04234 {
04235 MD_warn (out,
04236 "%s(%s->%s->%s[%i]):\n Warning, %s required not link to %s->%s.",
04237 caller_name, section->name, entry->name,
04238 field_decl->name, i, requirement->desc,
04239 target_section->name, element->value.l->name);
04240 }
04241 }
04242 }
04243 }
04244
04245
04246 return (error_count);
04247 }
04248
04249
04250
04251 static int MD_check_setting (FILE *out, MD_Field *field, int index, char *caller_name)
04252 {
04253 MD_Field_Decl *field_decl;
04254 MD_Element_Req *requirement;
04255 MD_Element *element;
04256 MD_Section **link_array, *target_section;
04257 int link_array_size, valid_link;
04258 int j;
04259
04260
04261 field_decl = field->decl;
04262
04263 if (index <= field->max_element_index)
04264 element = field->element[index];
04265 else
04266 element = NULL;
04267
04268 if (index <= field_decl->max_require_index)
04269 requirement = field_decl->require[index];
04270 else
04271 requirement = field_decl->kleene_starred_req;
04272
04273
04274
04275
04276 if ((element == NULL) && (requirement == NULL))
04277 {
04278
04279 return (0);
04280 }
04281
04282
04283 if (element == NULL)
04284 {
04285 if (out != NULL)
04286 {
04287 MD_warn (out,
04288 "%s(%s->%s->%s[%i]):\n Warning, %s required not NULL.",
04289 caller_name, field->entry->section->name,
04290 field->entry->name, field_decl->name, index,
04291 requirement->desc);
04292 }
04293
04294 return (1);
04295 }
04296
04297
04298 else if (requirement == NULL)
04299 {
04300 if (out != NULL)
04301 {
04302 MD_warn (out,
04303 "%s(%s->%s->%s[%i]):\n Warning, NULL required not %s.",
04304 caller_name, field->entry->section->name,
04305 field->entry->name, field_decl->name, index,
04306 MD_type_name[element->type]);
04307 }
04308
04309 return (1);
04310 }
04311 else if (element->type != requirement->type)
04312 {
04313 if (out != NULL)
04314 {
04315 MD_warn (out,
04316 "%s(%s->%s->%s[%i]):\n Warning, %s required not %s.",
04317 caller_name, field->entry->section->name,
04318 field->entry->name, field_decl->name, index,
04319 requirement->desc, MD_type_name[element->type]);
04320 }
04321
04322 return (1);
04323 }
04324 else if (element->type == MD_LINK)
04325 {
04326 link_array = requirement->link;
04327 link_array_size = requirement->link_array_size;
04328 target_section = element->value.l->section;
04329 valid_link = 0;
04330
04331 for (j=0; j < link_array_size; j++)
04332 {
04333 if (link_array[j] == target_section)
04334 {
04335 valid_link = 1;
04336 break;
04337 }
04338 }
04339
04340 if (!valid_link)
04341 {
04342 if (out != NULL)
04343 {
04344 MD_warn (out,
04345 "%s(%s->%s->%s[%i]):\n Warning, %s required not link to %s->%s.",
04346 caller_name, field->entry->section->name,
04347 field->entry->name, field_decl->name, index,
04348 requirement->desc, target_section->name,
04349 element->value.l->name);
04350 }
04351
04352 return (1);
04353 }
04354 }
04355
04356
04357 return (0);
04358 }
04359
04360
04361
04362
04363
04364
04365
04366 int _MD_num_elements (MD_Field *field)
04367 {
04368
04369
04370
04371 return (field->max_element_index + 1);
04372 }
04373
04374
04375
04376
04377
04378
04379
04380 int _MD_max_element_index (MD_Field *field)
04381 {
04382
04383 return (field->max_element_index);
04384 }
04385
04386
04387
04388
04389
04390
04391
04392
04393
04394 void _MD_set_int (MD_Field *field, int index, int value)
04395 {
04396 MD_Element *element;
04397
04398
04399 if (index < 0)
04400 {
04401 MD_punt (field->entry->section->md,
04402 "MD_set_int (%s->%s->%s[%d]): Invalid index (%d)\n",
04403 field->entry->section->name, field->entry->name,
04404 field->decl->name, index, index);
04405 }
04406
04407
04408 if (index > field->max_element_index)
04409 {
04410
04411 if (index >= field->element_array_size)
04412 {
04413
04414 MD_resize_element_array (field, index);
04415 }
04416
04417
04418 field->max_element_index = index;
04419 }
04420
04421
04422 element = field->element[index];
04423
04424
04425 if (element == NULL)
04426 {
04427 element = (MD_Element *) L_alloc (MD_Element_pool);
04428 field->element[index] = element;
04429 }
04430
04431
04432 else if (element->type == MD_STRING)
04433 {
04434 free (element->value.s);
04435 }
04436
04437
04438 element->field = field;
04439 element->element_index = (unsigned short) index;
04440 element->type = MD_INT;
04441 element->value.i = value;
04442 }
04443
04444
04445
04446
04447
04448
04449
04450
04451 void _MD_set_int_type_checking (MD_Field *field, int index, int value)
04452 {
04453
04454 _MD_set_int (field, index, value);
04455
04456
04457 MD_check_setting (stderr, field, index, "MD_set_int");
04458 }
04459
04460
04461
04462
04463
04464
04465
04466
04467
04468
04469
04470 int _MD_get_int (MD_Field *field, int index)
04471 {
04472 MD_Element *element;
04473
04474
04475 element = field->element[index];
04476
04477
04478 if (element->type != MD_INT)
04479 {
04480 MD_punt (field->entry->section->md,
04481 "MD_get_int(%s->%s->%s[%i]):\n Accessing %s element as an INT!",
04482 field->entry->section->name,
04483 field->entry->name, field->decl->name,
04484 index, MD_type_name[(int) element->type]);
04485 }
04486
04487
04488 return (element->value.i);
04489 }
04490
04491
04492
04493
04494
04495
04496
04497
04498 void _MD_set_double (MD_Field *field, int index, double value)
04499 {
04500 MD_Element *element;
04501
04502
04503 if (index < 0)
04504 {
04505 MD_punt (field->entry->section->md,
04506 "MD_set_double (%s->%s->%s[%d]): Invalid index (%d)\n",
04507 field->entry->section->name, field->entry->name,
04508 field->decl->name, index, index);
04509 }
04510
04511
04512 if (index > field->max_element_index)
04513 {
04514
04515 if (index >= field->element_array_size)
04516 {
04517
04518 MD_resize_element_array (field, index);
04519 }
04520
04521
04522 field->max_element_index = index;
04523 }
04524
04525
04526 element = field->element[index];
04527
04528
04529 if (element == NULL)
04530 {
04531 element = (MD_Element *) L_alloc (MD_Element_pool);
04532 field->element[index] = element;
04533 }
04534
04535 else if (element->type == MD_STRING)
04536 {
04537 free (element->value.s);
04538 }
04539
04540
04541 element->field = field;
04542 element->element_index = (unsigned short) index;
04543 element->type = MD_DOUBLE;
04544 element->value.d = value;
04545 }
04546
04547
04548
04549
04550
04551
04552
04553
04554 void _MD_set_double_type_checking (MD_Field *field, int index, double value)
04555 {
04556
04557 _MD_set_double (field, index, value);
04558
04559
04560 MD_check_setting (stderr, field, index, "MD_set_double");
04561 }
04562
04563
04564
04565
04566
04567
04568
04569
04570
04571
04572
04573 double _MD_get_double (MD_Field *field, int index)
04574 {
04575 MD_Element *element;
04576
04577
04578 element = field->element[index];
04579
04580
04581 if (element->type != MD_DOUBLE)
04582 {
04583 MD_punt (field->entry->section->md,
04584 "MD_get_double(%s->%s->%s[%i]):\n Accessing %s element as a DOUBLE!",
04585 field->entry->section->name,
04586 field->entry->name, field->decl->name,
04587 index, MD_type_name[(int) element->type]);
04588 }
04589
04590
04591 return (element->value.d);
04592 }
04593
04594
04595
04596
04597
04598
04599
04600
04601 void _MD_set_string (MD_Field *field, int index, char *value)
04602 {
04603 MD_Element *element;
04604
04605
04606 if (index < 0)
04607 {
04608 MD_punt (field->entry->section->md,
04609 "MD_set_string (%s->%s->%s[%d]): Invalid index (%d)\n",
04610 field->entry->section->name, field->entry->name,
04611 field->decl->name, index, index);
04612 }
04613
04614
04615 if (index > field->max_element_index)
04616 {
04617
04618 if (index >= field->element_array_size)
04619 {
04620
04621 MD_resize_element_array (field, index);
04622 }
04623
04624
04625 field->max_element_index = index;
04626 }
04627
04628
04629 element = field->element[index];
04630
04631
04632 if (element == NULL)
04633 {
04634 element = (MD_Element *) L_alloc (MD_Element_pool);
04635 field->element[index] = element;
04636 }
04637
04638 else if (element->type == MD_STRING)
04639 {
04640 free (element->value.s);
04641 }
04642
04643
04644 element->field = field;
04645 element->element_index = (unsigned short) index;
04646 element->type = MD_STRING;
04647 element->value.s = strdup(value);
04648 }
04649
04650
04651
04652
04653
04654
04655
04656
04657 void _MD_set_string_type_checking (MD_Field *field, int index, char *value)
04658 {
04659
04660 _MD_set_string (field, index, value);
04661
04662
04663 MD_check_setting (stderr, field, index, "MD_set_string");
04664 }
04665
04666
04667
04668
04669
04670
04671
04672
04673
04674
04675
04676 char *_MD_get_string (MD_Field *field, int index)
04677 {
04678 MD_Element *element;
04679
04680
04681 element = field->element[index];
04682
04683
04684 if (element->type != MD_STRING)
04685 {
04686 MD_punt (field->entry->section->md,
04687 "MD_get_string(%s->%s->%s[%i]):\n Accessing %s element as a STRING!",
04688 field->entry->section->name,
04689 field->entry->name, field->decl->name,
04690 index, MD_type_name[(int) element->type]);
04691 }
04692
04693
04694 return (element->value.s);
04695 }
04696
04697
04698
04699
04700
04701
04702
04703
04704 void _MD_set_link (MD_Field *field, int index, MD_Entry *value)
04705 {
04706 MD_Element *element;
04707
04708
04709 if (index < 0)
04710 {
04711 MD_punt (field->entry->section->md,
04712 "MD_set_link (%s->%s->%s[%d]):\n Invalid index (%d)\n",
04713 field->entry->section->name, field->entry->name,
04714 field->decl->name, index, index);
04715 }
04716
04717
04718 if (value == NULL)
04719 {
04720 MD_punt (field->entry->section->md,
04721 "MD_set_link (%s->%s->%s[%d]):\n Invalid value (pointer to NULL entry)\n",
04722 field->entry->section->name, field->entry->name,
04723 field->decl->name, index);
04724 }
04725
04726
04727 if (index > field->max_element_index)
04728 {
04729
04730 if (index >= field->element_array_size)
04731 {
04732
04733 MD_resize_element_array (field, index);
04734 }
04735
04736
04737 field->max_element_index = index;
04738 }
04739
04740
04741 element = field->element[index];
04742
04743
04744 if (element == NULL)
04745 {
04746 element = (MD_Element *) L_alloc (MD_Element_pool);
04747 field->element[index] = element;
04748 }
04749
04750 else if (element->type == MD_STRING)
04751 {
04752 free (element->value.s);
04753 }
04754
04755
04756 element->field = field;
04757 element->element_index = (unsigned short) index;
04758 element->type = MD_LINK;
04759 element->value.l = value;
04760 }
04761
04762
04763
04764
04765
04766
04767
04768
04769 void _MD_set_link_type_checking (MD_Field *field, int index, MD_Entry *value)
04770 {
04771
04772 _MD_set_link (field, index, value);
04773
04774
04775 MD_check_setting (stderr, field, index, "MD_set_link");
04776 }
04777
04778
04779
04780
04781
04782
04783
04784
04785
04786
04787
04788 MD_Entry *_MD_get_link (MD_Field *field, int index)
04789 {
04790 MD_Element *element;
04791
04792
04793 element = field->element[index];
04794
04795
04796 if (element->type != MD_LINK)
04797 {
04798 MD_punt (field->entry->section->md,
04799 "MD_get_link(%s->%s->%s[%i]):\n Accessing %s element as a LINK!",
04800 field->entry->section->name,
04801 field->entry->name, field->decl->name,
04802 index, MD_type_name[(int) element->type]);
04803 }
04804
04805
04806 return (element->value.l);
04807 }
04808
04809
04810
04811
04812 void MD_delete_element (MD_Field *field, int index)
04813 {
04814 MD_Element *element, **element_array;
04815 int max_index;
04816
04817
04818 element_array = field->element;
04819
04820
04821 element = element_array[index];
04822
04823
04824 if (element == NULL)
04825 return;
04826
04827
04828 element_array[index] = NULL;
04829
04830
04831 if (element->type == MD_STRING)
04832 {
04833 free (element->value.s);
04834 }
04835
04836
04837 L_free (MD_Element_pool, element);
04838
04839
04840
04841
04842
04843 max_index = field->max_element_index;
04844 while ((max_index > -1) && (element_array[max_index] == NULL))
04845 max_index--;
04846 field->max_element_index = max_index;
04847 }
04848
04849
04850 #if 0
04851
04852 int main()
04853 {
04854 MD *md;
04855 MD_Section *section, *section2, *section_array[10];
04856 MD_Entry *entry;
04857 MD_Symbol_Table *table;
04858 MD_Symbol *symbol;
04859 MD_Field *field1, *field2;
04860 MD_Field_Decl *field_decl1, *field_decl2, *field_decl3, *field_decl4;
04861 MD_Field_Decl *decl[10];
04862 MD_Element *element;
04863 int i, found, j, error_count;
04864 char buf[100], *string;
04865
04866
04867 printf ("Testing md routines.\n");
04868
04869
04870 md = MD_new_md ("Test_md", 1);
04871
04872
04873 section = MD_new_section (md, "Test_section", 1, 0);
04874 printf ("%s max_field_index %i field_array_size %i\n",
04875 section->name, section->max_field_index,
04876 section->field_array_size);
04877
04878 section2 = MD_new_section (md, "Section2", 0, 0);
04879
04880 section_array[0] = section;
04881 section_array[1] = section2;
04882
04883
04884 field_decl1 = MD_new_field_decl (section, "field1", MD_REQUIRED_FIELD);
04885 printf ("%s max_field_index %i field_array_size %i %s index %i\n",
04886 section->name, section->max_field_index, section->field_array_size,
04887 field_decl1->name, field_decl1->field_index);
04888 field_decl2 = MD_new_field_decl (section, "field2", MD_REQUIRED_FIELD);
04889 printf ("%s max_field_index %i field_array_size %i %s index %i\n",
04890 section->name, section->max_field_index, section->field_array_size,
04891 field_decl2->name, field_decl2->field_index);
04892
04893
04894 MD_require_double (field_decl1, 0);
04895 MD_require_int (field_decl1, 1);
04896 MD_require_string (field_decl1, 2);
04897 MD_require_link (field_decl1, 3, section2);
04898 MD_require_multi_target_link (field_decl1, 4, 2, section_array);
04899 MD_require_double (field_decl1, 5);
04900 MD_require_int (field_decl1, 6);
04901 MD_require_string (field_decl1, 7);
04902 MD_require_link (field_decl1, 8, section2);
04903 MD_require_multi_target_link (field_decl1, 9, 2, section_array);
04904
04905 MD_require_double (field_decl1, 10);
04906 MD_require_int (field_decl1, 11);
04907 MD_require_string (field_decl1, 12);
04908 MD_require_link (field_decl1, 13, section2);
04909 MD_require_multi_target_link (field_decl1, 14, 2, section_array);
04910
04911
04912 table = section->entry_table;
04913 MD_print_symbol_table_hash (stdout, table);
04914
04915 for (i=0; i < 10; i+= 3)
04916 {
04917 if (i == 3)
04918 sprintf (buf, "long_name_%i", i);
04919 else
04920 sprintf (buf, "d%i", i);
04921 entry = MD_new_entry (section, buf);
04922
04923
04924 field1 = MD_new_field (entry, field_decl1, 0);
04925 MD_set_double (field1, 0, ((double)i) * ((double) 1.001));
04926 MD_set_int (field1, 1, i);
04927 sprintf (buf, "string%i", i);
04928 MD_set_string (field1, 2, buf);
04929 MD_set_link (field1, 4, entry);
04930
04931 MD_set_double (field1, 5, (double)i);
04932 MD_set_int (field1, 6, i);
04933 sprintf (buf, "string%i", i);
04934 MD_set_string (field1, 7, buf);
04935 MD_set_link (field1, 9, entry);
04936
04937 MD_set_double (field1, 10, (double)i);
04938 MD_set_int (field1, 11, i);
04939 sprintf (buf, "string%i", i);
04940 MD_set_string (field1, 12, buf);
04941 MD_set_link (field1, 14, entry);
04942
04943 MD_get_int (field1, 1);
04944 field2 = MD_new_field (entry, field_decl2, 0);
04945 if (table->symbol_count == table->resize_size)
04946 {
04947 MD_print_symbol_table_hash (stdout, table);
04948 }
04949 }
04950
04951 fprintf (stderr, "Sizeof MD_Element = %i\n", sizeof(MD_Element));
04952
04953 field_decl3 = MD_new_field_decl (section, "field3", MD_REQUIRED_FIELD);
04954
04955
04956
04957
04958
04959
04960
04961
04962
04963
04964
04965
04966
04967
04968 MD_print_md (stdout, md, 80);
04969
04970
04971
04972
04973
04974 MD_print_symbol_table_hash (stdout, table);
04975 printf ("\n");
04976 printf ("%s max_field_index %i field_array_size %i %s index %i\n",
04977 section->name, section->max_field_index, section->field_array_size,
04978 field_decl3->name, field_decl3->field_index);
04979 MD_delete_field_decl (field_decl2);
04980 field_decl4 = MD_new_field_decl (section, "field4", MD_OPTIONAL_FIELD);
04981 printf ("%s max_field_index %i field_array_size %i %s index %i\n",
04982 section->name, section->max_field_index, section->field_array_size,
04983 field_decl4->name, field_decl4->field_index);
04984
04985 for (j=5; j < 10; j++)
04986 {
04987 sprintf (buf, "field%i", j);
04988 decl[j] = MD_new_field_decl (section, buf, MD_OPTIONAL_FIELD);
04989 printf ("%s max_field_index %i field_array_size %i %s index %i\n",
04990 section->name, section->max_field_index,
04991 section->field_array_size, decl[j]->name,
04992 decl[j]->field_index);
04993
04994 }
04995 found = 0;
04996 for (i=0; i < 1000; i+= 1)
04997 {
04998 sprintf (buf, "d%i", i);
04999 if ((entry = MD_find_entry (section, buf)) != NULL)
05000 {
05001 found ++;
05002 MD_delete_entry (entry);
05003 }
05004 if (i == 500)
05005 MD_print_symbol_table_hash (stdout, table);
05006 }
05007 printf ("\n Found = %i\n", found);
05008
05009
05010
05011
05012 MD_print_symbol_table_hash (stdout, table);
05013
05014 section = MD_find_section(md, "Test_section");
05015 MD_delete_section(section);
05016
05017
05018 MD_delete_md (md);
05019 md = NULL;
05020 #if 0
05021 field = MD_new_field (NULL, NULL, 0);
05022 printf ("size %i max %i\n", field->array_size, field->max_element_index);
05023
05024 for (i=0; i < 20; i ++)
05025 {
05026 MD_set_int (field, i, i);
05027 printf ("size %i max %i\n", field->array_size,
05028 field->max_element_index);
05029 }
05030 for (i=0; i < 20; i ++)
05031 {
05032 element = field->element[i];
05033 if (element != NULL)
05034 {
05035 printf ("%2i: %i type %i value\n", i, element->type, element->value.i);
05036 }
05037 }
05038
05039 #endif
05040 printf ("End md test.\n");
05041 return (0);
05042 }
05043
05044 #endif