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
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103 #ifndef lint
00104 #define lint
00105 static char copyright[] =
00106 "@(#) Copyright (c) 1994 The Board of Trustees of the University of Illinois.\
00107 \nAll rights reserved.\n";
00108 #endif
00109
00110 #include "md_preprocessor.h"
00111
00112
00113 FILE *out;
00114
00115
00116 Mfile *current_file;
00117
00118
00119 Psymbol_Table *Pdef_table = NULL;
00120 Psymbol_Table *Mfile_table = NULL;
00121
00122
00123
00124
00125 int allow_text_replacement = 1;
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136 int disable_implicit_text_replacement = 0;
00137
00138
00139 Mbuf *temp_mbuf = NULL;
00140 Mbuf *pptr_mbuf = NULL;
00141
00142
00143 Pptr *temp_placemark = NULL;
00144 Mptr *expand_placemark = NULL;
00145
00146
00147 L_Alloc_Pool *Pptr_pool = NULL;
00148 L_Alloc_Pool *Pdef_pool = NULL;
00149 L_Alloc_Pool *String_Node_pool = NULL;
00150 L_Alloc_Pool *Value_List_pool = NULL;
00151
00152 char *program_name = NULL;
00153
00154
00155 char *input_file_name = NULL;
00156 char *output_file_name = NULL;
00157 int using_stdin = 0;
00158 int print_line_directives = 1;
00159 int print_alloc_usage = 0;
00160
00161
00162 void print_usage (char *fmt, ...)
00163 {
00164 va_list args;
00165
00166
00167 if (fmt != NULL)
00168 {
00169 fprintf (stderr, "\nError: ");
00170 va_start (args, fmt);
00171 vfprintf (stderr, fmt, args);
00172 va_end (args);
00173 fprintf (stderr, "\n");
00174 }
00175
00176 fprintf (stderr, "\n");
00177 fprintf(stderr, "usage: %s [options] [input_file]\n\n",
00178 program_name);
00179 fprintf (stderr, "options:\n");
00180 fprintf (stderr, " -o output_file outputs to output_file instead of to standard output.\n");
00181 fprintf (stderr, " -stdin reads input from standard input instead of input_file.\n");
00182 fprintf (stderr, " -no_directives suppresses output of line directives.\n");
00183 fprintf (stderr, "\n");
00184 fprintf (stderr, " -Ddef_name=value overrides $def directives in input (until hit $undef.).\n");
00185 fprintf (stderr, "\n");
00186 fprintf (stderr, "debug options:\n");
00187 fprintf (stderr, " -bypass_alloc use malloc instead of alloc routines.\n");
00188 fprintf (stderr, " -print_usage prints alloc routine stats.\n");
00189 fprintf (stderr, "\n");
00190 exit (1);
00191 }
00192
00193 void read_command_line_parameters (int argc, char **arg_ptr)
00194 {
00195 char *name, *value;
00196
00197
00198 program_name = strdup (*arg_ptr);
00199
00200
00201 arg_ptr++;
00202 for (;*arg_ptr != NULL; arg_ptr++)
00203 {
00204
00205 if ((*arg_ptr)[0] == '-')
00206 {
00207
00208 if (strcmp (*arg_ptr, "-o") == 0)
00209 {
00210
00211 if (output_file_name != NULL)
00212 {
00213 print_usage("-o option specified twice.");
00214 }
00215
00216
00217 arg_ptr++;
00218 if (*arg_ptr == NULL)
00219 {
00220 print_usage("expected '-o output_file'.\n");
00221 }
00222 output_file_name = strdup (*arg_ptr);
00223 }
00224
00225 else if ((*arg_ptr)[1] == 'D')
00226 {
00227
00228 name = strdup (&(*arg_ptr)[2]);
00229
00230
00231 if ((name[0] != '_') && !isalpha (name[0]))
00232 {
00233 print_usage ("invalid def_name in '%s'.\n",
00234 *arg_ptr);
00235 }
00236
00237
00238 for (value = name; *value != 0; value ++)
00239 {
00240
00241 if (*value == '=')
00242 {
00243 break;
00244 }
00245
00246
00247 if ((*value != '_') && !isalnum (*value))
00248 {
00249 print_usage ("invalid def_name in '%s'.\n",
00250 *arg_ptr);
00251 }
00252 }
00253
00254 if (*value == 0)
00255 {
00256 value = "";
00257 }
00258 else
00259 {
00260
00261 *value = 0;
00262
00263
00264 value++;
00265 }
00266
00267
00268
00269
00270 add_Pdef (name, value, 0, 2);
00271
00272
00273 free (name);
00274 }
00275
00276
00277 else if (strcmp (*arg_ptr, "-stdin") == 0)
00278 {
00279 using_stdin = 1;
00280 }
00281
00282
00283 else if (strcmp (*arg_ptr, "-no_directives") == 0)
00284 {
00285 print_line_directives = 0;
00286 }
00287
00288
00289 else if (strcmp (*arg_ptr, "-bypass_alloc") == 0)
00290 {
00291 bypass_alloc_routines = 1;
00292 }
00293
00294
00295 else if (strcmp (*arg_ptr, "-print_usage") == 0)
00296 {
00297 print_alloc_usage = 1;
00298 }
00299 else
00300 {
00301 print_usage("unknown command line option '%s'.\n", *arg_ptr);
00302 }
00303 }
00304
00305
00306 else
00307 {
00308 if (input_file_name != NULL)
00309 {
00310 print_usage("only one input file may be specified.\n");
00311
00312 }
00313
00314
00315 input_file_name = strdup (*arg_ptr);
00316 }
00317 }
00318
00319
00320 if ((input_file_name == NULL) && !using_stdin)
00321 {
00322
00323 if (argc > 1)
00324 {
00325 print_usage("input_file or -stdin must be specified.\n");
00326 }
00327 else
00328 {
00329 print_usage(NULL);
00330 }
00331 }
00332
00333
00334 if ((input_file_name != NULL) && using_stdin)
00335 {
00336 print_usage("may not specify both input_file and -stdin.\n");
00337 }
00338
00339
00340 if ((input_file_name != NULL) && (output_file_name != NULL) &&
00341 (strcmp (input_file_name, output_file_name) == 0))
00342 {
00343 print_usage("may not specify input file (%s) that is the same as output file.",
00344 input_file_name);
00345 }
00346
00347 }
00348
00349
00350
00351
00352
00353 void L_punt (char *fmt, ...)
00354 {
00355 va_list args;
00356
00357 va_start (args, fmt);
00358 vfprintf (stderr, fmt, args);
00359 va_end(args);
00360 fprintf (stderr,"\n");
00361
00362 exit (-1);
00363 }
00364
00365
00366
00367
00368
00369
00370
00371
00372 void Perror (Pptr *pptr, char *fmt, ...)
00373 {
00374 va_list args;
00375 Mptr *mptr;
00376 int i;
00377 int text_replaced;
00378 int error_pos;
00379
00380
00381
00382 mptr = pptr->mptr;
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393 if ((mptr->mline == NULL) || (mptr->pos != 0) ||
00394 (mptr->mline->line_no != 0))
00395 Mbackupc (mptr);
00396
00397
00398
00399
00400
00401
00402 fprintf (stderr, "\n");
00403
00404 if (mptr->mline != NULL)
00405 {
00406 fprintf (stderr,
00407 "Error during preprocessing (line %i char %i of %s):\n",
00408 mptr->mline->line_no,
00409 mptr->pos+1, mptr->mfile->name);
00410 }
00411
00412
00413 else
00414 {
00415 fprintf (stderr,
00416 "Error during preprocessing (%s at EOF):\n",
00417 mptr->mfile->name);
00418
00419 }
00420
00421
00422 va_start (args, fmt);
00423 vfprintf (stderr, fmt, args);
00424 va_end(args);
00425 fprintf (stderr,"\n");
00426 fprintf (stderr, "\n");
00427
00428
00429
00430 if (mptr->mline != NULL)
00431 {
00432
00433 text_replaced = 0;
00434 for (i=0; i <pptr->expanded->cur_len; i++)
00435 {
00436 if (mptr->mline->buf[i] != pptr->expanded->buf[i])
00437 {
00438 text_replaced = 1;
00439 break;
00440 }
00441 }
00442
00443 }
00444
00445
00446 else
00447 {
00448 if (pptr->expanded_pos > 0)
00449 text_replaced = 1;
00450 else
00451 text_replaced = 0;
00452 }
00453
00454
00455
00456
00457 if (text_replaced)
00458 {
00459
00460 fprintf (stderr, "File text where error occurred:\n");
00461 if (mptr->mline != NULL)
00462 {
00463 print_buf_with_arrow (stderr, mptr->mline->buf, mptr->pos);
00464 }
00465 else
00466 {
00467 fprintf(stderr, "At EOF.\n\n");
00468 }
00469
00470
00471 fprintf (stderr, "After incremental text replacement:\n");
00472 print_buf_with_arrow (stderr, pptr->expanded->buf, pptr->expanded_pos);
00473 }
00474
00475
00476
00477
00478
00479
00480 else
00481 {
00482
00483 fprintf (stderr, "File text where error occurred:\n");
00484
00485
00486
00487
00488 if (pptr->expanded_pos == (mptr->pos -1))
00489 error_pos = pptr->expanded_pos;
00490 else
00491 error_pos = mptr->pos;
00492 print_buf_with_arrow (stderr, mptr->mline->buf, error_pos);
00493 }
00494
00495 fprintf (stderr,"Fatal error, cannot continue.\n");
00496 fprintf (stderr,"\n");
00497
00498 exit (-1);
00499 }
00500
00501
00502 void Pputc (Pptr *pptr, int ch)
00503 {
00504 static char *file_name = NULL;
00505 static int file_line = -1, file_pos = 0;
00506 char *input_name;
00507 int input_line;
00508 int name_changed, line_changed;
00509
00510
00511
00512 if (file_pos == 0)
00513 {
00514
00515 line_changed = 0;
00516 name_changed = 0;
00517
00518
00519 input_name = pptr->mptr->mfile->name;
00520
00521
00522
00523
00524
00525
00526 if (pptr->mptr->mline == NULL)
00527 {
00528 input_line = file_line;
00529 }
00530 else
00531 {
00532 input_line = pptr->mptr->mline->line_no;
00533 if (ch == '\n')
00534 input_line --;
00535 }
00536
00537 if ((file_name == NULL) ||
00538 (strcmp (file_name, input_name) != 0))
00539 {
00540 if (file_name != NULL)
00541 free (file_name);
00542 file_name = strdup (input_name);
00543
00544
00545 name_changed = 1;
00546 }
00547
00548 if ((pptr->mptr->mline != NULL) &&
00549 (file_line != input_line))
00550 {
00551 file_line = input_line;
00552
00553
00554 line_changed = 1;
00555 }
00556
00557
00558 if (print_line_directives)
00559 {
00560 if (name_changed && line_changed)
00561 fprintf (out, "$line %i \"%s\"\n",file_line, file_name);
00562
00563 else if (name_changed)
00564 fprintf (out, "$line \"%s\"\n", file_name);
00565
00566 else if (line_changed)
00567 fprintf (out, "$line %i\n", file_line);
00568 }
00569 }
00570
00571
00572 putc (ch, out);
00573
00574
00575 if (ch == '\n')
00576 {
00577 file_line++;
00578 file_pos = 0;
00579 }
00580 else
00581 {
00582 file_pos ++;
00583 }
00584 }
00585
00586 main (int argc, char **argv, char **envp)
00587 {
00588 FILE *in;
00589 Pptr *pptr;
00590 char ch;
00591 int i;
00592 char *name, *value;
00593
00594
00595 Pptr_pool = L_create_alloc_pool ("Pptr", sizeof (Pptr), 16);
00596 Pdef_pool = L_create_alloc_pool ("Pdef", sizeof (Pdef), 16);
00597 String_Node_pool = L_create_alloc_pool ("String_Node",
00598 sizeof (String_Node), 16);
00599 Value_List_pool = L_create_alloc_pool ("Value_List",
00600 sizeof (Value_List), 16);
00601
00602
00603 temp_mbuf = create_Mbuf();
00604 pptr_mbuf = create_Mbuf();
00605
00606
00607
00608 Pdef_table = create_Psymbol_Table ("def");
00609 Mfile_table = create_Psymbol_Table ("open file");
00610
00611
00612
00613 read_command_line_parameters(argc, argv);
00614
00615
00616 for (i = 0; envp[i] != NULL; i++)
00617 {
00618
00619 name = strdup (envp[i]);
00620
00621
00622 for (value = name; *value != 0; value++)
00623 {
00624
00625
00626
00627 if (*value == '=')
00628 {
00629
00630 *value = 0;
00631
00632
00633 value++;
00634 break;
00635 }
00636 }
00637
00638
00639
00640
00641 add_Pdef (name, value, 0, 0);
00642
00643
00644 free (name);
00645 }
00646
00647
00648 if (using_stdin)
00649 {
00650 input_file_name = strdup ("(stdin)");
00651 in = stdin;
00652 }
00653 else
00654 {
00655 if ((in = fopen (input_file_name, "r")) == NULL)
00656 L_punt ("Unable to open input file '%s'.", input_file_name);
00657 }
00658
00659
00660 if (output_file_name == NULL)
00661 {
00662 output_file_name = strdup ("(stdout)");
00663 out = stdout;
00664 }
00665 else
00666 {
00667 if ((out = fopen (output_file_name, "w")) == NULL)
00668 L_punt ("Unable to open output file '%s'.", output_file_name);
00669 }
00670
00671
00672
00673 current_file = create_Mfile (in, input_file_name, "preprocessing");
00674 add_Psymbol (Mfile_table, current_file->name, current_file);
00675
00676
00677 pptr = create_Pptr (current_file);
00678
00679
00680 temp_placemark = create_Pptr (current_file);
00681 expand_placemark = create_Mptr (current_file);
00682
00683 while ((ch = Ppeekc (pptr)) != EOF)
00684 {
00685
00686
00687
00688 if (ch == '}')
00689 {
00690 ch = Pgetc (pptr);
00691 Pputc (pptr, ch);
00692 }
00693 else
00694 {
00695 pptr = process_body (pptr);
00696 }
00697 }
00698
00699
00700 free_Pptr (temp_placemark);
00701 free_Mptr (expand_placemark);
00702
00703
00704 free_Pptr (pptr);
00705
00706
00707 free_Psymbol_Table (Pdef_table, free_Pdef);
00708 free_Psymbol_Table (Mfile_table, (void (*)(void *))free_Mfile);
00709
00710
00711 free_Mbuf (temp_mbuf);
00712 free_Mbuf (pptr_mbuf);
00713
00714
00715 if (print_alloc_usage)
00716 {
00717 if (Mfile_pool != NULL)
00718 L_print_alloc_info (stdout, Mfile_pool, 1);
00719 if (Mline_pool != NULL)
00720 L_print_alloc_info (stdout, Mline_pool, 1);
00721 if (Mbuf_pool != NULL)
00722 L_print_alloc_info (stdout, Mbuf_pool, 1);
00723 if (Mptr_pool != NULL)
00724 L_print_alloc_info (stdout, Mptr_pool, 1);
00725 if (Psymbol_Table_pool != NULL)
00726 L_print_alloc_info (stdout, Psymbol_Table_pool, 1);
00727 if (Psymbol_pool != NULL)
00728 L_print_alloc_info (stdout, Psymbol_pool, 1);
00729 L_print_alloc_info (stdout, Pptr_pool, 1);
00730 L_print_alloc_info (stdout, Pdef_pool, 1);
00731 L_print_alloc_info (stdout, String_Node_pool, 1);
00732 L_print_alloc_info (stdout, Value_List_pool, 1);
00733 }
00734
00735
00736 if (Mfile_pool != NULL)
00737 L_free_alloc_pool (Mfile_pool);
00738 if (Mline_pool != NULL)
00739 L_free_alloc_pool (Mline_pool);
00740 if (Mbuf_pool != NULL)
00741 L_free_alloc_pool (Mbuf_pool);
00742 if (Mptr_pool != NULL)
00743 L_free_alloc_pool (Mptr_pool);
00744 if (Psymbol_Table_pool != NULL)
00745 L_free_alloc_pool (Psymbol_Table_pool);
00746 if (Psymbol_pool != NULL)
00747 L_free_alloc_pool (Psymbol_pool);
00748 L_free_alloc_pool (Pptr_pool);
00749 L_free_alloc_pool (Pdef_pool);
00750 L_free_alloc_pool (String_Node_pool);
00751 L_free_alloc_pool (Value_List_pool);
00752
00753
00754 fclose(in);
00755 fclose(out);
00756
00757 return (0);
00758 }
00759
00760
00761
00762 Pptr *process_body (Pptr *pptr)
00763 {
00764 int ch;
00765 int depth;
00766
00767
00768 depth = 0;
00769
00770
00771 while ((ch = Ppeekc (pptr)) != EOF)
00772 {
00773
00774 if (ch == '$')
00775 {
00776 pptr = process_directive (pptr);
00777 }
00778
00779 else if (ch == '{')
00780 {
00781
00782 ch = Pgetc (pptr);
00783 Pputc (pptr, ch);
00784
00785 depth++;
00786
00787 }
00788
00789 else if (ch == '}')
00790 {
00791
00792
00793
00794 if (depth <= 0)
00795 break;
00796
00797
00798 ch = Pgetc (pptr);
00799 Pputc (pptr, ch);
00800
00801 depth--;
00802 }
00803
00804
00805
00806 else
00807 {
00808
00809 ch = Pgetc (pptr);
00810 Pputc (pptr, ch);
00811
00812
00813 if (ch == '\\')
00814 {
00815 if ((ch = Pgetc (pptr)) != EOF)
00816 Pputc (pptr, ch);
00817 }
00818
00819
00820
00821
00822 else if (ch == '\'')
00823 {
00824 while ((ch = Pgetc (pptr)) != EOF)
00825 {
00826 Pputc (pptr, ch);
00827
00828
00829 if ((ch == '\'') || (ch == '\n'))
00830 break;
00831
00832
00833
00834
00835 if (ch == '\\')
00836 {
00837 if ((ch = Ppeekc (pptr)) != EOF)
00838 {
00839 if (ch != '\n')
00840 {
00841 ch = Pgetc (pptr);
00842 Pputc (pptr, ch);
00843 }
00844
00845 }
00846 }
00847 }
00848 }
00849 }
00850 }
00851
00852 return (pptr);
00853 }
00854
00855
00856 Pptr *skip_body (Pptr *pptr)
00857 {
00858 int ch;
00859 int depth;
00860
00861
00862 allow_text_replacement = 0;
00863
00864
00865 depth = 0;
00866
00867
00868 while ((ch = Ppeekc (pptr)) != EOF)
00869 {
00870
00871 if (ch == '{')
00872 {
00873
00874 ch = Pgetc (pptr);
00875
00876 depth++;
00877
00878 }
00879
00880 else if (ch == '}')
00881 {
00882
00883
00884 if (depth <= 0)
00885 break;
00886
00887
00888 ch = Pgetc (pptr);
00889
00890 depth--;
00891 }
00892
00893
00894
00895 else
00896 {
00897
00898 ch = Pgetc (pptr);
00899
00900
00901 if (ch == '\\')
00902 {
00903 ch = Pgetc (pptr);
00904 }
00905
00906
00907
00908
00909 else if (ch == '\'')
00910 {
00911 while ((ch = Pgetc (pptr)) != EOF)
00912 {
00913
00914 if ((ch == '\'') || (ch == '\n'))
00915 break;
00916
00917
00918
00919
00920 if (ch == '\\')
00921 {
00922 if ((ch = Ppeekc (pptr)) != EOF)
00923 {
00924 if (ch != '\n')
00925 {
00926 ch = Pgetc (pptr);
00927 }
00928 }
00929 }
00930 }
00931 }
00932 }
00933 }
00934
00935
00936 allow_text_replacement = 1;
00937
00938 return (pptr);
00939 }
00940
00941 Pptr *process_def_directive (Pptr *pptr)
00942 {
00943 char *name, *val, ch, *ptr;
00944 int allow_implicit_replacement;
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954 disable_implicit_text_replacement++;
00955
00956 Pskip_whitespace_no_nl (pptr);
00957
00958
00959 if (Ppeekc (pptr) == '!')
00960 {
00961
00962 Pgetc (pptr);
00963
00964
00965 allow_implicit_replacement = 1;
00966 }
00967
00968 else
00969 {
00970 allow_implicit_replacement = 0;
00971 }
00972 name = Pget_identifier (pptr);
00973
00974
00975 disable_implicit_text_replacement--;
00976
00977 Pskip_whitespace_no_nl (pptr);
00978
00979 ch = Ppeekc (pptr);
00980
00981
00982 if ((ch == EOF) || (ch == '\n'))
00983 {
00984 val = strdup ("");
00985 }
00986
00987
00988 else if (ch == '{')
00989 {
00990 val = Pget_bounded_string (pptr);
00991 }
00992
00993
00994
00995
00996
00997
00998 else
00999 {
01000
01001 move_Pptr (temp_placemark, pptr);
01002 val = Pget_stripped_line (pptr);
01003
01004
01005 for (ptr = val; *ptr != NULL; ptr++)
01006 {
01007
01008 if (*ptr == '\\')
01009 {
01010
01011 ptr++;
01012
01013
01014 if (*ptr == NULL)
01015 {
01016 Perror (temp_placemark,
01017 "Character missing after backslash in "
01018 "$def of '%s' to '%s'.\n\n",
01019 name, val);
01020 }
01021 }
01022 else if ((*ptr == '{') || (*ptr == '}'))
01023 {
01024 Perror (temp_placemark,
01025 "Unexpected '%c' in $def of '%s' to '%s'.\n"
01026 " Braces are not allowed in this form of $def.\n\n"
01027 "Possible solutions:\n"
01028 " 1) Place '%c' on next line to exclude from $def\n"
01029 " 2) Place a backslash before '%c'\n"
01030 " 3) Use '$def def_name {bounded_def_value}' form.\n",
01031 *ptr, name, val, *ptr, *ptr);
01032 }
01033
01034
01035 else if (*ptr == '$' )
01036 {
01037 Perror (temp_placemark,
01038 "Expecting a backslash before '$' in "
01039 "$def of '%s' to '%s'.\n\n"
01040 "Note: $def, $undef, $for, $if, and $include directives may not\n"
01041 " be embedded in replacement value strings.",
01042 name, val);
01043 }
01044 }
01045 }
01046
01047
01048 add_Pdef (name, val, allow_implicit_replacement, 1);
01049
01050
01051 free (name);
01052 free (val);
01053
01054
01055 return (pptr);
01056 }
01057
01058 Pptr *process_undef_directive (Pptr *pptr)
01059 {
01060 char *name;
01061
01062
01063
01064
01065
01066
01067
01068
01069 disable_implicit_text_replacement++;
01070
01071 Pskip_whitespace_no_nl (pptr);
01072 name = Pget_identifier (pptr);
01073
01074
01075 disable_implicit_text_replacement--;
01076
01077
01078 delete_Pdef (name);
01079
01080
01081 free (name);
01082
01083 return (pptr);
01084 }
01085
01086 Value_List *get_for_value_list (Pptr *pptr, Pptr *placemark)
01087 {
01088 Value_List *value_list;
01089 String_Node *value_node;
01090 char *val;
01091 int ch;
01092
01093
01094 value_list = (Value_List *) L_alloc (Value_List_pool);
01095
01096
01097 Pskip_whitespace (pptr);
01098
01099
01100 move_Pptr (placemark, pptr);
01101
01102
01103 if ((ch = Ppeekc (pptr)) != '(')
01104 Perror (pptr,
01105 "Error parsing $for directive, '(' expected not '%c'.",
01106 ch);
01107 Pgetc (pptr);
01108
01109
01110
01111
01112
01113
01114
01115 disable_implicit_text_replacement++;
01116
01117 Pskip_whitespace (pptr);
01118
01119
01120
01121
01122 if (Ppeekc (pptr) == '!')
01123 {
01124
01125
01126
01127 Pgetc (pptr);
01128 value_list->allow_implicit_replacement = 1;
01129 }
01130 else
01131 {
01132
01133 value_list->allow_implicit_replacement = 0;
01134
01135 }
01136 value_list->name = Pget_identifier (pptr);
01137
01138
01139 disable_implicit_text_replacement--;
01140
01141 Pskip_whitespace (pptr);
01142
01143
01144 if (Ppeekc (pptr) != 'i')
01145 Perror (pptr, "Error parsing $for directive, 'in' expected.");
01146 Pgetc (pptr);
01147 if (Ppeekc (pptr) != 'n')
01148 Perror (pptr, "Error parsing $for directive, 'in' expected.");
01149 Pgetc (pptr);
01150 if (!isspace(Ppeekc (pptr)))
01151 Perror (pptr, "Error parsing $for directive, 'in' expected.");
01152 Pgetc (pptr);
01153 Pskip_whitespace (pptr);
01154
01155
01156
01157 value_list->first_value = NULL;
01158 value_list->last_value = NULL;
01159 value_list->value_count = 0;
01160 while ((ch = Ppeekc (pptr)) != ')')
01161 {
01162
01163 if (ch == EOF)
01164 {
01165 Perror (placemark,
01166 "Expect matching ')' to terminate $for directive's value list.");
01167 }
01168
01169
01170 val = Pget_for_string (pptr);
01171 Pskip_whitespace (pptr);
01172
01173
01174 value_node = (String_Node *) L_alloc (String_Node_pool);
01175
01176 value_node->string = val;
01177 value_node->next = NULL;
01178
01179 if (value_list->last_value != NULL)
01180 value_list->last_value->next = value_node;
01181 else
01182 value_list->first_value = value_node;
01183 value_list->last_value = value_node;
01184
01185
01186 value_list->value_count ++;
01187 }
01188
01189
01190 ch = Pgetc (pptr);
01191
01192
01193 if (value_list->value_count == 0)
01194 Perror (pptr, "Values expected in $for.");
01195
01196
01197 return (value_list);
01198 }
01199
01200 Pptr *process_for_directive (Pptr *pptr, Pptr *placemark)
01201 {
01202 Value_List *first_list, *last_list, *list, *next_list;
01203 String_Node *value_node, *next_value_node;
01204 Pptr *loop_start;
01205 int ch, multi_list;
01206
01207
01208 first_list = NULL;
01209 last_list = NULL;
01210
01211 Pskip_whitespace (pptr);
01212
01213
01214 move_Pptr (placemark, pptr);
01215
01216
01217 if ((ch = Ppeekc (pptr)) != '(')
01218 {
01219 Perror (pptr,
01220 "Error parsing $for directive, '(' expected not '%c'.",
01221 ch);
01222 }
01223
01224
01225 Pgetc (pptr);
01226 Pskip_whitespace (pptr);
01227
01228
01229 if (Ppeekc (pptr) != '(')
01230 {
01231
01232 move_Pptr (pptr, placemark);
01233
01234
01235 list = get_for_value_list (pptr, placemark);
01236
01237
01238 first_list = list;
01239 last_list = list;
01240 list->next_list = NULL;
01241 }
01242 else
01243 {
01244
01245 while ((ch = Ppeekc (pptr)) != ')')
01246 {
01247
01248 if (ch != '(')
01249 {
01250 Perror (pptr,
01251 "Error parsing $for directive of the form:\n"
01252 " $for ((name1 in ...) (name2 in ...) ...) {body}\n\n"
01253 "Expecting '(' or ')', not '%c' at this point.",
01254 ch);
01255 }
01256
01257
01258 list = get_for_value_list (pptr, placemark);
01259
01260
01261 if (last_list == NULL)
01262 first_list = list;
01263 else
01264 last_list->next_list = list;
01265 last_list = list;
01266 list->next_list = NULL;
01267
01268
01269
01270
01271 if (list->value_count != first_list->value_count)
01272 {
01273 Perror (placemark,
01274 "Value lists must be the same length for $for directive of this form:\n"
01275 " $for ((name1 in ...) (name2 in ...) ...) {body}\n\n"
01276 "List for '%s' has length %i but list of '%s' has length %i!",
01277 first_list->name, first_list->value_count,
01278 list->name, list->value_count);
01279 }
01280
01281
01282 for (list = first_list; list != last_list; list = list->next_list)
01283 {
01284 if (strcmp (list->name, last_list->name) == 0)
01285 {
01286 Perror (placemark,
01287 "A list for '%s' has already been defined in $for directive of form:\n"
01288 " $for ((name1 in ...) (name2 in ...) ...) {body}\n",
01289 last_list->name);
01290 }
01291 }
01292
01293
01294 Pskip_whitespace (pptr);
01295 }
01296
01297
01298 Pgetc (pptr);
01299
01300 }
01301
01302
01303 Pskip_whitespace (pptr);
01304
01305
01306 move_Pptr (placemark, pptr);
01307
01308
01309 if ((ch = Ppeekc (pptr)) != '{')
01310 Perror (pptr, "Expect '{' before $for's body.");
01311 Pgetc(pptr);
01312
01313
01314
01315 loop_start = copy_Pptr (pptr);
01316
01317
01318
01319
01320 while (first_list->value_count > 0)
01321 {
01322
01323 move_Pptr (pptr, loop_start);
01324
01325
01326 for (list = first_list; list != NULL; list = list->next_list)
01327 {
01328
01329
01330
01331 add_Pdef (list->name, list->first_value->string,
01332 list->allow_implicit_replacement, 3);
01333 }
01334
01335
01336 pptr = process_body (pptr);
01337
01338
01339 for (list = first_list; list != NULL; list = list->next_list)
01340 {
01341 delete_Pdef (list->name);
01342 }
01343
01344
01345 if ((ch = Pgetc (pptr)) != '}')
01346 {
01347 Perror (placemark,
01348 "Matching '}' for $for's body expected before EOF.");
01349 }
01350
01351
01352 for (list = first_list; list != NULL; list = list->next_list)
01353 {
01354
01355 value_node = list->first_value;
01356
01357
01358 list->first_value = value_node->next;
01359 if (list->first_value == NULL)
01360 list->last_value = NULL;
01361 list->value_count--;
01362
01363
01364 free (value_node->string);
01365 L_free (String_Node_pool, value_node);
01366 }
01367 }
01368
01369
01370 for (list = first_list; list != NULL; list = next_list)
01371 {
01372
01373 next_list = list->next_list;
01374
01375 free (list->name);
01376 L_free (Value_List_pool, list);
01377 }
01378
01379
01380 free_Pptr (loop_start);
01381
01382
01383 return (pptr);
01384 }
01385
01386 Pptr *process_if_directive (Pptr *pptr, Pptr *placemark)
01387 {
01388 int ch;
01389 int condition, skip_elses;
01390 char *directive_type;
01391
01392 Pskip_whitespace (pptr);
01393
01394
01395 if ((ch = Ppeekc (pptr)) != '(')
01396 Perror (pptr,
01397 "Error parsing $if directive, '(' expected not '%c'.",
01398 ch);
01399 Pgetc (pptr);
01400
01401
01402 condition = Pcalc_C_int_expr (pptr, 0);
01403
01404 Pskip_whitespace (pptr);
01405
01406
01407 if ((ch = Ppeekc (pptr)) != ')')
01408 Perror (pptr,
01409 "Error parsing $if directive, ')' expected not '%c'.",
01410 ch);
01411 Pgetc (pptr);
01412
01413
01414 Pskip_whitespace (pptr);
01415
01416
01417 if ((ch = Ppeekc (pptr)) != '{')
01418 Perror (pptr, "Expect '{' before $if's body.");
01419 Pgetc(pptr);
01420
01421
01422 if (condition)
01423 {
01424
01425 pptr = process_body (pptr);
01426
01427
01428 skip_elses = 1;
01429 }
01430 else
01431 {
01432 pptr = skip_body (pptr);
01433
01434
01435 skip_elses = 0;
01436 }
01437
01438
01439 if ((ch = Pgetc (pptr)) != '}')
01440 Perror (placemark, "End '}' of $if expected before EOF.");
01441
01442
01443
01444 while (1)
01445 {
01446
01447 move_Pptr (placemark, pptr);
01448
01449
01450 Pskip_whitespace (pptr);
01451
01452 if (Pgetc (pptr) != '$')
01453 break;
01454
01455
01456 directive_type = Pget_alnum_string (pptr);
01457
01458 if (strcmp (directive_type, "else") == 0)
01459 {
01460
01461 Pskip_whitespace (pptr);
01462
01463
01464 if ((ch = Ppeekc (pptr)) != '{')
01465 Perror (pptr, "Expect '{' before $else's body.");
01466 Pgetc(pptr);
01467
01468 if (!skip_elses)
01469 {
01470
01471 pptr = process_body (pptr);
01472 }
01473 else
01474 {
01475 pptr = skip_body (pptr);
01476 }
01477
01478
01479 if ((ch = Pgetc (pptr)) != '}')
01480 Perror (placemark, "End '}' of $else expected before EOF.");
01481
01482
01483 move_Pptr (placemark, pptr);
01484
01485
01486 free (directive_type);
01487 break;
01488 }
01489 else if (strcmp (directive_type, "elif") == 0)
01490 {
01491 Pskip_whitespace (pptr);
01492
01493
01494 if ((ch = Ppeekc (pptr)) != '(')
01495 Perror (pptr,
01496 "Error parsing $elif directive, '(' expected not '%c'.",
01497 ch);
01498 Pgetc (pptr);
01499
01500
01501 condition = Pcalc_C_int_expr (pptr, 0);
01502
01503 Pskip_whitespace (pptr);
01504
01505
01506 if ((ch = Ppeekc (pptr)) != ')')
01507 Perror (pptr,
01508 "Error parsing $elif directive, ')' expected not '%c'.",
01509 ch);
01510 Pgetc (pptr);
01511
01512
01513 Pskip_whitespace (pptr);
01514
01515
01516 if ((ch = Ppeekc (pptr)) != '{')
01517 Perror (pptr, "Expect '{' before $elif's body.");
01518 Pgetc(pptr);
01519
01520
01521
01522
01523 if (condition && !skip_elses)
01524 {
01525
01526 pptr = process_body (pptr);
01527
01528
01529 skip_elses = 1;
01530 }
01531 else
01532 {
01533 pptr = skip_body (pptr);
01534 }
01535
01536
01537 if ((ch = Pgetc (pptr)) != '}')
01538 Perror (placemark, "End '}' of $elif expected before EOF.");
01539 }
01540 else
01541 {
01542
01543 free (directive_type);
01544 break;
01545 }
01546
01547
01548 free (directive_type);
01549 }
01550
01551
01552 move_Pptr (pptr, placemark);
01553
01554 return (pptr);
01555 }
01556 Pptr *process_include_directive (Pptr *pptr, Pptr *placemark)
01557 {
01558 char *file_name;
01559 Psymbol *psymbol;
01560 Mfile *include_file;
01561 Pptr *include_pptr;
01562 int ch;
01563 FILE *in;
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574 if (placemark->mptr->pos != 1)
01575 {
01576 Perror (placemark,
01577 "$include directive must be the first and only thing on the line.");
01578 }
01579
01580
01581 file_name = Pget_quoted_string (pptr, 1);
01582
01583
01584 Pskip_whitespace_no_nl (pptr);
01585 ch = Pgetc (pptr);
01586 if ((ch != '\n') && (ch != EOF))
01587 {
01588 Perror (placemark,
01589 "$include directive must be the first and only thing on the line.");
01590 }
01591
01592
01593
01594
01595
01596 if ((psymbol = find_Psymbol (Mfile_table, file_name)) != NULL)
01597 {
01598 include_file = (Mfile *) psymbol->data;
01599 }
01600 else
01601 {
01602 if ((in = fopen (file_name, "r")) == NULL)
01603 {
01604 Perror (placemark, "Unable to open include file %s.",
01605 file_name);
01606 }
01607
01608 include_file = create_Mfile (in, file_name, "preprocessing");
01609 add_Psymbol (Mfile_table, include_file->name, include_file);
01610 }
01611
01612
01613 include_pptr = create_Pptr (include_file);
01614
01615
01616 while ((ch = Ppeekc (include_pptr)) != EOF)
01617 {
01618
01619
01620
01621 if (ch == '}')
01622 {
01623 ch = Pgetc (include_pptr);
01624 Pputc (include_pptr, ch);
01625 }
01626 else
01627 {
01628 include_pptr = process_body (include_pptr);
01629 }
01630 }
01631
01632
01633 free_Pptr (include_pptr);
01634
01635
01636 free (file_name);
01637
01638 return (pptr);
01639 }
01640
01641
01642 Pptr *process_directive(Pptr *pptr)
01643 {
01644 int ch;
01645 char *directive_type;
01646 Pptr *placemark;
01647
01648
01649 placemark = copy_Pptr (pptr);
01650
01651
01652 if ((ch = Pgetc (pptr)) != '$')
01653 L_punt ("process_directive: $ expected.");
01654
01655
01656 directive_type = Pget_alnum_string (pptr);
01657
01658
01659 if (directive_type[0] == 0)
01660 {
01661 Perror (placemark,
01662 "Poorly formed preprocessor directive, expecting either:\n"
01663 " 1) A backslash before the '$' or\n"
01664 " 2) one of the currently supported directives:\n"
01665 " $include \"name_of_file_to_include\"\n"
01666 " $def def_name def_value /* Note: def_value ends at newline */\n"
01667 " $def def_name {bounded_def_value}\n"
01668 " ${name} /* Forces replacement of name */\n"
01669 " $\\name /* Prevents replacement of name */\n"
01670 " $?{name} /* Replaced with 1 if name defined, 0 otherwise */\n"
01671 " $={integer C expression}\n"
01672 " $.={floating-point C expression}\n"
01673 " $if (cond) {body} $elif (cond) {body} $else {body}\n"
01674 " $x..y or $(int C expr)..(int C expr)\n"
01675 " $for (def_name in value1 value2 ... value N) {for_body}\n"
01676 " $for ((def_name1 in ...)(def_name2 in...)...){for_body}");
01677 }
01678
01679
01680 if (strcmp (directive_type, "def") == 0)
01681 {
01682 pptr = process_def_directive (pptr);
01683 }
01684
01685 else if (strcmp (directive_type, "undef") == 0)
01686 {
01687 pptr = process_undef_directive (pptr);
01688 }
01689
01690 else if (strcmp (directive_type, "for") == 0)
01691 {
01692 pptr = process_for_directive (pptr, placemark);
01693 }
01694
01695 else if (strcmp (directive_type, "if") == 0)
01696 {
01697 pptr = process_if_directive (pptr, placemark);
01698 }
01699
01700 else if (strcmp (directive_type, "else") == 0)
01701 {
01702 Perror (placemark, "$else without associated $if.");
01703 }
01704
01705 else if (strcmp (directive_type, "elif") == 0)
01706 {
01707 Perror (placemark, "$elif without associated $if.");
01708 }
01709
01710 else if (strcmp (directive_type, "include") == 0)
01711 {
01712 pptr = process_include_directive (pptr, placemark);
01713 }
01714
01715
01716
01717 else
01718 {
01719 Perror (placemark,
01720 "Unsupported preprocessing directive '%s'.\n"
01721 "The currently supported directives are:\n"
01722 " $include \"name_of_file_to_include\"\n"
01723 " $def def_name def_value /* Note: def_value ends at newline */\n"
01724 " $def def_name {bounded_def_value}\n"
01725 " ${name} /* Forces replacement of name */\n"
01726 " $\\name /* Prevents replacement of name */\n"
01727 " $?{name} /* Replaced with 1 if name defined, 0 otherwise */\n"
01728 " $={integer C expression}\n"
01729 " $.={floating-point C expression}\n"
01730 " $if (cond) {body} $elif (cond) {body} $else {body}\n"
01731 " $x..y or $(int C expr)..(int C expr)\n"
01732 " $for (def_name in value1 value2 ... value N) {for_body}\n"
01733 " $for ((def_name1 in ...)(def_name2 in...)...){for_body}",
01734 directive_type);
01735 }
01736
01737
01738
01739 free (directive_type);
01740
01741
01742 free_Pptr (placemark);
01743
01744 return (pptr);
01745 }
01746
01747 char *Pget_alnum_string (Pptr *pptr)
01748 {
01749 int ch;
01750 char *string;
01751
01752
01753 clear_Mbuf (temp_mbuf);
01754
01755 while ((ch = Ppeekc (pptr)) != EOF)
01756 {
01757 if ((ch == '_') || isalnum (ch))
01758 {
01759 ch = Pgetc (pptr);
01760 addc_to_Mbuf (temp_mbuf, ch);
01761 }
01762 else
01763 break;
01764 }
01765
01766
01767 string = copy_Mbuf_buf (temp_mbuf);
01768
01769 return (string);
01770 }
01771
01772 char *Pget_identifier (Pptr *pptr)
01773 {
01774 int ch;
01775 char *string;
01776
01777
01778 clear_Mbuf (temp_mbuf);
01779
01780
01781 ch = Ppeekc (pptr);
01782
01783 if ((ch != '_') && !isalpha(ch))
01784 Perror (pptr, "Error in identifier at '%c'.", ch);
01785
01786 while ((ch = Ppeekc (pptr)) != EOF)
01787 {
01788
01789 if (isspace (ch))
01790 break;
01791
01792 if ((ch == '_') || isalnum (ch))
01793 {
01794 ch = Pgetc (pptr);
01795 addc_to_Mbuf (temp_mbuf, ch);
01796 }
01797 else
01798 Perror (pptr, "Error in identifier at '%c'.", ch);
01799 }
01800
01801
01802 string = copy_Mbuf_buf (temp_mbuf);
01803
01804 return (string);
01805 }
01806
01807
01808 char *Pget_stripped_line (Pptr *pptr)
01809 {
01810 int ch;
01811 char *string;
01812
01813
01814 clear_Mbuf (temp_mbuf);
01815
01816
01817 Pskip_whitespace_no_nl (pptr);
01818
01819
01820 while ((ch = Ppeekc (pptr)) != EOF)
01821 {
01822 if (ch == '\n')
01823 break;
01824
01825 ch = Pgetc (pptr);
01826 addc_to_Mbuf (temp_mbuf, ch);
01827 }
01828
01829
01830 strip_Mbuf (temp_mbuf);
01831
01832
01833 string = copy_Mbuf_buf (temp_mbuf);
01834
01835 return (string);
01836 }
01837
01838 char *Pget_quoted_string (Pptr *pptr, int strip_quotes)
01839 {
01840 int ch, quote_ch;
01841 char *string;
01842
01843
01844 clear_Mbuf (temp_mbuf);
01845
01846
01847 Pskip_whitespace_no_nl (pptr);
01848
01849
01850 move_Pptr (temp_placemark, pptr);
01851
01852
01853 ch = Ppeekc (pptr);
01854 if ((ch != '\'') && (ch != '\"'))
01855 {
01856 Perror (pptr, "Open quote (\' or \") expected.");
01857 }
01858
01859 ch = Pgetc (pptr);
01860 quote_ch = ch;
01861
01862
01863 if (!strip_quotes)
01864 addc_to_Mbuf (temp_mbuf, ch);
01865
01866 while (1)
01867 {
01868
01869 ch = Ppeekc (pptr);
01870 if (ch == '$' )
01871 {
01872 Perror (pptr,
01873 "Expecting a backslash before '$' in quoted string.\n"
01874 "Note: $def, $undef, $for, $if, and $include directives may not\n"
01875 " be embedded in replacement value strings.");
01876 }
01877
01878
01879 ch = Pgetc (pptr);
01880
01881
01882 if ((ch == EOF) || (ch == '\n'))
01883 {
01884 Perror (temp_placemark,
01885 "Expecting close quote (%c) before end of line.",
01886 quote_ch);
01887 }
01888
01889
01890 if (ch == quote_ch)
01891 {
01892
01893 if (!strip_quotes)
01894 addc_to_Mbuf (temp_mbuf, ch);
01895 break;
01896 }
01897
01898
01899 addc_to_Mbuf (temp_mbuf, ch);
01900
01901
01902 if (ch == '\\')
01903 {
01904 ch = Ppeekc (pptr);
01905
01906 if ((ch != EOF) && (ch != '\n'))
01907 {
01908 ch = Pgetc (pptr);
01909 addc_to_Mbuf (temp_mbuf, ch);
01910 }
01911
01912 }
01913 }
01914
01915 string = copy_Mbuf_buf (temp_mbuf);
01916
01917 return (string);
01918 }
01919
01920
01921
01922 char *Pget_for_string (Pptr *pptr)
01923 {
01924 int ch, next_ch;
01925 char *string;
01926
01927
01928 clear_Mbuf (temp_mbuf);
01929
01930
01931 Pskip_whitespace_no_nl (pptr);
01932
01933
01934 move_Pptr (temp_placemark, pptr);
01935
01936
01937 if ((ch = Ppeekc (pptr)) == EOF)
01938 Perror (temp_placemark, "String expected, not EOF.");
01939 if (ch == '{')
01940 {
01941 string = Pget_bounded_string (pptr);
01942 }
01943
01944
01945 else if ((ch == '"') || (ch == '\''))
01946 {
01947 string = Pget_quoted_string (pptr, 0);
01948 }
01949
01950
01951
01952
01953 else
01954 {
01955 while (1)
01956 {
01957 ch = Ppeekc (pptr);
01958
01959 if ((ch == EOF) || (ch == ')') || isspace (ch))
01960 break;
01961
01962 if (ch == '\\')
01963 {
01964
01965 ch = Pgetc (pptr);
01966 next_ch = Ppeekc (pptr);
01967
01968 if ((next_ch == EOF) || (next_ch == '\n'))
01969 Perror (pptr, "Character missing after backslash.");
01970
01971 next_ch = Pgetc (pptr);
01972
01973 addc_to_Mbuf (temp_mbuf, ch);
01974 addc_to_Mbuf (temp_mbuf, next_ch);
01975
01976
01977 }
01978
01979
01980 else if ((ch == '"' ) || (ch == '\''))
01981 {
01982 Perror (pptr,
01983 "Unexpected quote. Expecting one of the following:\n 1) Whitespace before the quote\n 2) or a backslash before the quote.");
01984
01985 }
01986
01987
01988 else if (ch == '(' )
01989 {
01990 Perror (pptr, "Unexpected '(' in unquoted string.");
01991 }
01992
01993
01994 else if (ch == '$' )
01995 {
01996 Perror (pptr,
01997 "Expecting a backslash before '$' in unquoted string.\n"
01998 "Note: $def, $undef, $for, $if, and $include directives may not\n"
01999 " be embedded in replacement value strings.");
02000 }
02001
02002 else
02003 {
02004 ch = Pgetc (pptr);
02005 addc_to_Mbuf (temp_mbuf, ch);
02006 }
02007 }
02008
02009
02010 string = copy_Mbuf_buf (temp_mbuf);
02011 }
02012
02013 return (string);
02014 }
02015
02016
02017 char *Pget_bounded_string (Pptr *pptr)
02018 {
02019 int ch;
02020 char *string;
02021 int nesting_level;
02022
02023
02024 clear_Mbuf (temp_mbuf);
02025
02026
02027 Pskip_whitespace_no_nl (pptr);
02028
02029
02030 move_Pptr (temp_placemark, pptr);
02031
02032
02033 if ((ch = Ppeekc (pptr)) == EOF)
02034 Perror (temp_placemark, "String expected, not EOF.");
02035
02036 if (ch != '{')
02037 L_punt ("Pget_bounded_string: '{' expected not '%c'.", ch);
02038
02039
02040 Pgetc (pptr);
02041
02042
02043 nesting_level = 1;
02044
02045 while (1)
02046 {
02047
02048 ch = Ppeekc (pptr);
02049 if (ch == '$' )
02050 {
02051 Perror (pptr,
02052 "Expecting a backslash before '$' in bounded string.\n"
02053 "Note: $def, $undef, $for, $if, and $include directives may not\n"
02054 " be embedded in replacement value strings.");
02055 }
02056
02057 if ((ch = Pgetc (pptr)) == EOF)
02058 Perror (temp_placemark,
02059 "End '}' of bounded string not found.");
02060
02061
02062
02063
02064 if (ch == '\\')
02065 {
02066 addc_to_Mbuf (temp_mbuf, ch);
02067
02068 if ((ch = Pgetc (pptr)) == EOF)
02069 Perror (temp_placemark,
02070 "End '}' of bounded string not found.");
02071 addc_to_Mbuf (temp_mbuf, ch);
02072
02073 continue;
02074 }
02075
02076
02077 if (ch == '{')
02078 nesting_level ++;
02079 else if (ch == '}')
02080 nesting_level --;
02081
02082
02083 if (nesting_level <= 0)
02084 break;
02085
02086 addc_to_Mbuf (temp_mbuf, ch);
02087 }
02088
02089
02090 string = copy_Mbuf_buf (temp_mbuf);
02091
02092 return (string);
02093 }
02094
02095 void Pskip_whitespace (Pptr *pptr)
02096 {
02097 int ch;
02098
02099 while ((ch = Ppeekc (pptr)) != EOF)
02100 {
02101 if (isspace (ch))
02102 Pgetc (pptr);
02103 else
02104 break;
02105 }
02106 }
02107
02108 void Pskip_whitespace_no_nl (Pptr *pptr)
02109 {
02110 int ch;
02111
02112 while ((ch = Ppeekc (pptr)) != EOF)
02113 {
02114 if ((ch != '\n') && isspace (ch))
02115 Pgetc (pptr);
02116 else
02117 break;
02118 }
02119 }
02120
02121
02122
02123 Pptr *create_Pptr (Mfile *mfile)
02124 {
02125 Pptr *pptr;
02126
02127 pptr = (Pptr *) L_alloc (Pptr_pool);
02128
02129 pptr->mptr = create_Mptr (mfile);
02130 pptr->expanded = create_Mbuf();
02131 pptr->expanded_pos = 0;
02132 pptr->quoted = 0;
02133 pptr->scanned = 0;
02134
02135 return (pptr);
02136 }
02137
02138
02139
02140
02141 Pptr *copy_Pptr (Pptr *orig_pptr)
02142 {
02143 Pptr *new_pptr;
02144 char *orig_expanded;
02145
02146
02147 new_pptr = (Pptr *) L_alloc (Pptr_pool);
02148
02149 new_pptr->mptr = copy_Mptr(orig_pptr->mptr);
02150
02151
02152 new_pptr->expanded = create_Mbuf();
02153 orig_expanded = get_Mbuf_buf (orig_pptr->expanded);
02154 adds_to_Mbuf (new_pptr->expanded, orig_expanded);
02155 new_pptr->expanded_pos = orig_pptr->expanded_pos;
02156 new_pptr->quoted = orig_pptr->quoted;
02157 new_pptr->scanned = orig_pptr->scanned;
02158
02159 return (new_pptr);
02160 }
02161
02162
02163
02164
02165
02166 void move_Pptr (Pptr *old_pptr, Pptr *new_pptr)
02167 {
02168 char *new_expanded;
02169
02170
02171 if (old_pptr == new_pptr)
02172 L_punt ("move_Pptr: old_pptr and new_pptr the same.");
02173
02174 move_Mptr (old_pptr->mptr, new_pptr->mptr);
02175
02176
02177 clear_Mbuf (old_pptr->expanded);
02178 new_expanded = get_Mbuf_buf (new_pptr->expanded);
02179 adds_to_Mbuf (old_pptr->expanded, new_expanded);
02180
02181
02182 old_pptr->expanded_pos = new_pptr->expanded_pos;
02183 old_pptr->quoted = new_pptr->quoted;
02184 old_pptr->scanned = new_pptr->scanned;
02185 }
02186
02187 void free_Pptr (Pptr *pptr)
02188 {
02189
02190 free_Mptr (pptr->mptr);
02191
02192
02193 free_Mbuf (pptr->expanded);
02194
02195
02196 L_free (Pptr_pool, pptr);
02197 }
02198
02199
02200
02201
02202 void Pexpand_directive (Pptr *source_pptr)
02203 {
02204 int ch, next_ch, end_ch;
02205 Pptr *expand_pptr;
02206 Mbuf *expand_mbuf;
02207 int range_start, range_end;
02208 int int_result;
02209 double double_result;
02210 char rbuf[100];
02211 char *recurse_buf;
02212 char *ident, *replacement;
02213 int i;
02214
02215
02216 expand_pptr = copy_Pptr (source_pptr);
02217
02218
02219 addc_to_Mbuf (expand_pptr->expanded, '$');
02220 expand_pptr->expanded_pos += 1;
02221
02222
02223
02224
02225
02226 if ((next_ch = Mpeekc (expand_pptr->mptr)) != '\\')
02227 {
02228 next_ch = Ppeekc (expand_pptr);
02229 }
02230
02231
02232 if ((next_ch == '=') && allow_text_replacement)
02233
02234 {
02235
02236 Pgetc (expand_pptr);
02237
02238
02239 if (Ppeekc (expand_pptr) != '{')
02240 {
02241 Perror (expand_pptr,
02242 "Expecting '{' after '$=' in 'evaluate integer expression' directive.\nForm expected: $={integer expression}.");
02243 }
02244
02245 Pgetc (expand_pptr);
02246
02247
02248 int_result = Pcalc_C_int_expr (expand_pptr, 0);
02249
02250
02251 Pskip_whitespace (expand_pptr);
02252
02253 if ((end_ch = Ppeekc (expand_pptr)) != '}')
02254 {
02255 if ((end_ch == 'e') || (end_ch == 'E') || (end_ch == '.'))
02256 {
02257 Perror (expand_pptr,
02258 "Expression error or missing '}' in 'evaulate int expression' directive.\n"
02259 "Form expected: $={integer expression}.\n\n"
02260 "For floating-point expressions use: "
02261 "$.={floating-point expression}.");
02262 }
02263 else
02264 {
02265 Perror (expand_pptr,
02266 "Expression error or missing '}' in 'evaulate int expression' directive.\n"
02267 "Form expected: $={integer expression}.");
02268 }
02269 }
02270
02271 Pgetc (expand_pptr);
02272
02273
02274 move_Mptr (source_pptr->mptr, expand_pptr->mptr);
02275
02276
02277 sprintf (rbuf, "%i", int_result);
02278
02279 adds_to_Mbuf (source_pptr->expanded, rbuf);
02280
02281
02282 recurse_buf = get_Mbuf_buf (expand_pptr->expanded);
02283 adds_to_Mbuf (source_pptr->expanded,
02284 &recurse_buf[expand_pptr->expanded_pos]);
02285
02286 }
02287
02288
02289 else if ((next_ch == '.') && allow_text_replacement)
02290
02291 {
02292
02293 Pgetc (expand_pptr);
02294
02295
02296 if (Ppeekc (expand_pptr) != '=')
02297 {
02298 Perror (expand_pptr,
02299 "Expecting '=' after '$.' in 'evaluate float expression' directive.\nForm expected: $.={floating-point expression}.");
02300 }
02301
02302 Pgetc (expand_pptr);
02303
02304
02305 if (Ppeekc (expand_pptr) != '{')
02306 {
02307 Perror (expand_pptr,
02308 "Expecting '{' after '$.=' in 'evaluate float expression' directive.\nForm expected: $.={floating-point expression}.");
02309 }
02310
02311 Pgetc (expand_pptr);
02312
02313
02314 double_result = Pcalc_C_float_expr (expand_pptr, 0);
02315
02316
02317 Pskip_whitespace (expand_pptr);
02318
02319 if (Ppeekc (expand_pptr) != '}')
02320 {
02321 Perror (expand_pptr,
02322 "Expression error or missing '}' in 'evaulate float expression' directive.\nForm expected: $.={floating-point expression}.");
02323 }
02324
02325 Pgetc (expand_pptr);
02326
02327
02328 move_Mptr (source_pptr->mptr, expand_pptr->mptr);
02329
02330
02331 sprintf (rbuf, "%.16g", double_result);
02332
02333 adds_to_Mbuf (source_pptr->expanded, rbuf);
02334
02335
02336 recurse_buf = get_Mbuf_buf (expand_pptr->expanded);
02337 adds_to_Mbuf (source_pptr->expanded,
02338 &recurse_buf[expand_pptr->expanded_pos]);
02339
02340 }
02341
02342
02343 else if ((next_ch == '?') && allow_text_replacement)
02344
02345 {
02346
02347
02348
02349
02350 disable_implicit_text_replacement++;
02351
02352
02353 Pgetc (expand_pptr);
02354
02355
02356 if (Ppeekc (expand_pptr) != '{')
02357 {
02358 Perror (expand_pptr,
02359 "Expecting '{' after '$?' in 'is defined?' directive.\nForm expected: $?{name}.");
02360 }
02361
02362
02363 Pgetc (expand_pptr);
02364
02365
02366 expand_mbuf = create_Mbuf();
02367
02368
02369 while ((ch = Ppeekc (expand_pptr)) != '}')
02370 {
02371 if ((ch == EOF) || (ch == '\n'))
02372 Merror (source_pptr->mptr,
02373 "Text replacement directive's end '}' not found.");
02374
02375
02376 if ((ch == '_') || isalnum (ch))
02377 {
02378
02379 ch = Pgetc (expand_pptr);
02380 addc_to_Mbuf (expand_mbuf, ch);
02381 }
02382 else
02383 {
02384 Perror (expand_pptr,
02385 "Invalid character '%c' in 'is defined?' directive.",
02386 ch);
02387 }
02388 }
02389
02390
02391 ident = get_Mbuf_buf (expand_mbuf);
02392
02393
02394 if ((replacement = Plookup (ident, 0)) != NULL)
02395 addc_to_Mbuf (source_pptr->expanded, '1');
02396
02397
02398 else
02399 {
02400 addc_to_Mbuf (source_pptr->expanded, '0');
02401 }
02402
02403
02404 free_Mbuf (expand_mbuf);
02405
02406
02407 disable_implicit_text_replacement--;
02408
02409
02410 Pgetc (expand_pptr);
02411
02412
02413 move_Mptr (source_pptr->mptr, expand_pptr->mptr);
02414 }
02415
02416
02417 else if ((isdigit (next_ch) || (next_ch == '-') || (next_ch == '+')
02418 || (next_ch == '(')) && allow_text_replacement)
02419 {
02420
02421
02422
02423
02424
02425
02426 range_start = Pcalc_C_int_factor (expand_pptr);
02427
02428
02429 Pskip_whitespace (expand_pptr);
02430
02431
02432
02433
02434 if ((Ppeekc (expand_pptr) != '.') || (Pgetc (expand_pptr) != '.') ||
02435 (Ppeekc (expand_pptr) != '.') || (Pgetc (expand_pptr) != '.'))
02436 Perror (expand_pptr,
02437 "Error in range expression: '..' expected between start and end range.");
02438
02439
02440 Pskip_whitespace (expand_pptr);
02441
02442
02443
02444
02445
02446
02447 range_end = Pcalc_C_int_factor (expand_pptr);
02448
02449
02450 if (range_start <= range_end)
02451 {
02452 for (i = range_start; i <= range_end; i++)
02453 {
02454 sprintf (rbuf, "%i", i);
02455 adds_to_Mbuf (source_pptr->expanded, rbuf);
02456
02457 if (i < range_end)
02458 addc_to_Mbuf (source_pptr->expanded, ' ');
02459 }
02460 }
02461 else
02462 {
02463 for (i = range_start; i >= range_end; i--)
02464 {
02465 sprintf (rbuf, "%i", i);
02466 adds_to_Mbuf (source_pptr->expanded, rbuf);
02467
02468 if (i > range_end)
02469 addc_to_Mbuf (source_pptr->expanded, ' ');
02470 }
02471 }
02472
02473
02474 move_Mptr (source_pptr->mptr, expand_pptr->mptr);
02475
02476
02477 recurse_buf = get_Mbuf_buf (expand_pptr->expanded);
02478 adds_to_Mbuf (source_pptr->expanded,
02479 &recurse_buf[expand_pptr->expanded_pos]);
02480 }
02481
02482
02483 else if ((next_ch == '{') && allow_text_replacement)
02484 {
02485
02486
02487
02488
02489 disable_implicit_text_replacement++;
02490
02491
02492 Pgetc (expand_pptr);
02493
02494
02495 expand_mbuf = create_Mbuf();
02496
02497
02498 while ((ch = Ppeekc (expand_pptr)) != '}')
02499 {
02500 if ((ch == EOF) || (ch == '\n'))
02501 Merror (source_pptr->mptr,
02502 "Text replacement directive's end '}' not found.");
02503
02504
02505 if ((ch == '_') || isalnum (ch))
02506 {
02507
02508 ch = Pgetc (expand_pptr);
02509 addc_to_Mbuf (expand_mbuf, ch);
02510 }
02511
02512 else
02513 {
02514 Perror (expand_pptr,
02515 "Invalid character '%c' in text replacement directive.",
02516 ch);
02517 }
02518 }
02519
02520
02521
02522 ident = get_Mbuf_buf (expand_mbuf);
02523
02524
02525
02526
02527 if ((replacement = Plookup (ident, 0)) != NULL)
02528 adds_to_Mbuf (source_pptr->expanded, replacement);
02529 else
02530 {
02531 Perror (expand_pptr,
02532 "Undefined name '%s' in text replacement directive.",
02533 ident);
02534 }
02535
02536
02537 free_Mbuf (expand_mbuf);
02538
02539
02540 disable_implicit_text_replacement--;
02541
02542
02543 Pgetc (expand_pptr);
02544
02545
02546 move_Mptr (source_pptr->mptr, expand_pptr->mptr);
02547 }
02548
02549
02550
02551
02552
02553 else if (next_ch == '\\')
02554 {
02555
02556 Mgetc (source_pptr->mptr);
02557
02558
02559
02560
02561
02562 if (Mpeekc (source_pptr->mptr) == '\n')
02563 Mgetc (source_pptr->mptr);
02564 else
02565 {
02566
02567 source_pptr->scanned = 1;
02568 }
02569 }
02570
02571 else
02572 {
02573 addc_to_Mbuf (source_pptr->expanded, '$');
02574 }
02575
02576
02577 free_Pptr (expand_pptr);
02578
02579 }
02580
02581
02582
02583
02584
02585
02586 int Pexpand_text (Pptr *pptr)
02587 {
02588 char ch, next_ch, first_ch;
02589 Mptr *mptr;
02590 char *ident, *replacement;
02591 char nesting_level;
02592
02593
02594
02595 mptr = pptr->mptr;
02596
02597
02598
02599
02600
02601 while (pptr->expanded->cur_len <= pptr->expanded_pos)
02602 {
02603
02604
02605 if (Mptr_pos(mptr) == 0)
02606 {
02607
02608 clear_Mbuf (pptr->expanded);
02609 pptr->expanded_pos = 0;
02610
02611
02612 pptr->quoted = 0;
02613 }
02614
02615
02616 if ((ch = Mgetc (mptr)) == NULL)
02617 return (0);
02618
02619
02620 if ((ch != '_') && !isalnum(ch))
02621 {
02622 pptr->scanned = 0;
02623 }
02624
02625
02626
02627
02628
02629 if ((!pptr->quoted) && (!pptr->scanned) &&
02630 ((ch == '_') || isalpha(ch)))
02631 {
02632
02633 move_Mptr (expand_placemark, mptr);
02634 first_ch = ch;
02635
02636
02637 clear_Mbuf (pptr_mbuf);
02638 addc_to_Mbuf (pptr_mbuf, ch);
02639
02640
02641 while ((ch = Mpeekc (mptr)) != EOF)
02642 {
02643 if ((ch == '_') || isalnum(ch))
02644 {
02645 ch = Mgetc (mptr);
02646 addc_to_Mbuf (pptr_mbuf, ch);
02647 }
02648 else
02649 break;
02650 }
02651
02652
02653 ident = get_Mbuf_buf (pptr_mbuf);
02654
02655
02656
02657
02658
02659 if (allow_text_replacement &&
02660 (disable_implicit_text_replacement == 0) &&
02661 (replacement = Plookup (ident, 1)) != NULL)
02662 adds_to_Mbuf (pptr->expanded, replacement);
02663 else
02664 {
02665 move_Mptr (mptr, expand_placemark);
02666 pptr->scanned = 1;
02667 addc_to_Mbuf (pptr->expanded, first_ch);
02668 }
02669 }
02670
02671
02672
02673
02674
02675 else if ((!pptr->quoted) && (ch == '$'))
02676 {
02677 Pexpand_directive (pptr);
02678 }
02679
02680
02681 else if (ch == '/')
02682 {
02683
02684
02685
02686 ch = Mpeekc (mptr);
02687
02688
02689 if (ch == '/')
02690 {
02691
02692
02693
02694 while ((ch = Mpeekc (mptr)) != EOF)
02695 {
02696 if (ch == '\n')
02697 break;
02698 Mgetc (mptr);
02699 }
02700 }
02701
02702 else if (ch == '*')
02703 {
02704
02705 move_Mptr (expand_placemark, mptr);
02706
02707
02708 Mgetc(mptr);
02709
02710
02711 nesting_level = 1;
02712
02713 while (nesting_level > 0)
02714 {
02715 if ((ch = Mgetc (mptr)) == EOF)
02716 Merror (expand_placemark,
02717 "End of comment not found.");
02718
02719
02720
02721
02722 next_ch = Mpeekc (mptr);
02723
02724
02725 if (ch == '\\')
02726 {
02727
02728 Mgetc (mptr);
02729 }
02730
02731
02732
02733 if ((ch == '/') && (next_ch == '*'))
02734 {
02735
02736 Mgetc (mptr);
02737
02738 nesting_level++;
02739 }
02740
02741
02742 if ((ch == '*') && (next_ch == '/'))
02743 {
02744
02745 Mgetc (mptr);
02746
02747 nesting_level--;
02748 }
02749 }
02750 }
02751
02752
02753 else
02754 {
02755 addc_to_Mbuf (pptr->expanded, '/');
02756 }
02757 }
02758
02759
02760 else
02761 {
02762 addc_to_Mbuf (pptr->expanded, ch);
02763
02764
02765
02766
02767 if (ch == '\'')
02768 {
02769 if (pptr->quoted)
02770 pptr->quoted = 0;
02771 else
02772 pptr->quoted = 1;
02773 }
02774
02775
02776 else if (ch == '\\')
02777 {
02778 ch = Mpeekc (mptr);
02779 if ((ch != '\n') && (ch != EOF))
02780 {
02781 ch = Mgetc(mptr);
02782 addc_to_Mbuf (pptr->expanded, ch);
02783 }
02784 }
02785 }
02786 }
02787
02788
02789 return (1);
02790 }
02791
02792
02793 int Pgetc (Pptr *pptr)
02794 {
02795 int ch;
02796 char *expanded_buf;
02797
02798
02799 if (Pexpand_text (pptr))
02800 {
02801
02802 expanded_buf = get_Mbuf_buf (pptr->expanded);
02803 ch = expanded_buf[pptr->expanded_pos];
02804 pptr->expanded_pos++;
02805 }
02806
02807
02808 else
02809 {
02810 ch = EOF;
02811 }
02812 return (ch);
02813 }
02814
02815
02816 int Ppeekc (Pptr *pptr)
02817 {
02818 int ch;
02819 char *expanded_buf;
02820
02821
02822 if (Pexpand_text (pptr))
02823 {
02824
02825 expanded_buf = get_Mbuf_buf (pptr->expanded);
02826 ch = expanded_buf[pptr->expanded_pos];
02827 }
02828
02829
02830 else
02831 ch = EOF;
02832
02833 return (ch);
02834 }
02835
02836
02837
02838
02839 int Pcalc_C_int_expr (Pptr *pptr, int current_precedence)
02840 {
02841 int result;
02842 int ch, ch2;
02843 int unary_operator;
02844 int temp_result;
02845 Pptr *placemark;
02846
02847
02848 Pskip_whitespace (pptr);
02849 ch = Ppeekc (pptr);
02850
02851 if ((ch == '!') || (ch == '~'))
02852 {
02853
02854 unary_operator = ch;
02855 Pgetc(pptr);
02856 Pskip_whitespace (pptr);
02857 ch = Ppeekc (pptr);
02858 }
02859 else
02860 unary_operator = 0;
02861
02862
02863 result = Pcalc_C_int_factor (pptr);
02864
02865
02866 if (unary_operator != 0)
02867 {
02868 switch (unary_operator)
02869 {
02870 case '!':
02871 result = !result;
02872 break;
02873
02874 case '~':
02875 result = ~result;
02876 break;
02877
02878 default:
02879 Perror (pptr, "Algorithm error: undefined unary operator '%c'.",
02880 unary_operator);
02881 }
02882 }
02883
02884
02885
02886
02887 placemark = copy_Pptr (pptr);
02888
02889
02890 while (1)
02891 {
02892
02893 move_Pptr (placemark, pptr);
02894 Pskip_whitespace (pptr);
02895
02896
02897
02898
02899 ch = Pgetc (pptr);
02900 ch2 = Ppeekc (pptr);
02901
02902
02903
02904
02905
02906
02907
02908
02909
02910
02911 if ((ch == '<') && (ch2 == '<') && (current_precedence < 11))
02912 {
02913
02914 Pgetc(pptr);
02915 result = result << Pcalc_C_int_expr (pptr, 11);
02916 }
02917
02918 else if ((ch == '>') && (ch2 == '>') && (current_precedence < 11))
02919 {
02920
02921 Pgetc(pptr);
02922 result = result >> Pcalc_C_int_expr (pptr, 11);
02923 }
02924
02925 else if ((ch == '<') && (ch2 == '=') && (current_precedence < 10))
02926 {
02927
02928 Pgetc(pptr);
02929 result = result <= Pcalc_C_int_expr (pptr, 10);
02930 }
02931
02932 else if ((ch == '>') && (ch2 == '=') && (current_precedence < 10))
02933 {
02934
02935 Pgetc(pptr);
02936 result = result >= Pcalc_C_int_expr (pptr, 10);
02937 }
02938
02939 else if ((ch == '=') && (ch2 == '=') && (current_precedence < 9))
02940 {
02941
02942 Pgetc(pptr);
02943 result = result == Pcalc_C_int_expr (pptr, 9);
02944 }
02945
02946 else if ((ch == '!') && (ch2 == '=') && (current_precedence < 9))
02947 {
02948
02949 Pgetc(pptr);
02950 result = result != Pcalc_C_int_expr (pptr, 9);
02951 }
02952
02953 else if ((ch == '&') && (ch2 == '&') && (current_precedence < 5))
02954 {
02955
02956 Pgetc(pptr);
02957
02958
02959 temp_result = Pcalc_C_int_expr (pptr, 5);
02960 result = result && temp_result;
02961 }
02962
02963 else if ((ch == '|') && (ch2 == '|') && (current_precedence < 4))
02964 {
02965
02966 Pgetc(pptr);
02967
02968
02969 temp_result = Pcalc_C_int_expr (pptr, 4);
02970 result = result || temp_result;
02971 }
02972
02973
02974
02975
02976
02977 else if ((ch == '*') && (current_precedence < 13))
02978 result = result * Pcalc_C_int_expr (pptr, 13);
02979
02980 else if ((ch == '/') && (current_precedence < 13))
02981 {
02982
02983 temp_result = Pcalc_C_int_expr (pptr, 13);
02984
02985 if (temp_result == 0)
02986 Perror (pptr, "Expression attempts to divide by zero.");
02987
02988 result = result / temp_result;
02989 }
02990
02991 else if ((ch == '%') && (current_precedence < 13))
02992 result = result % Pcalc_C_int_expr (pptr, 13);
02993
02994 else if ((ch == '+') && (current_precedence < 12))
02995 result = result + Pcalc_C_int_expr (pptr, 12);
02996
02997 else if ((ch == '-') && (current_precedence < 12))
02998 result = result - Pcalc_C_int_expr (pptr, 12);
02999
03000 else if ((ch == '<') && (current_precedence < 10))
03001 result = result < Pcalc_C_int_expr (pptr, 10);
03002
03003 else if ((ch == '>') && (current_precedence < 10))
03004 result = result > Pcalc_C_int_expr (pptr, 10);
03005
03006
03007
03008
03009 else if ((ch == '&') && (ch2 != '&') && (current_precedence < 8))
03010 result = result & Pcalc_C_int_expr (pptr, 8);
03011
03012 else if ((ch == '^') && (current_precedence < 7))
03013 result = result ^ Pcalc_C_int_expr (pptr, 7);
03014
03015
03016
03017
03018 else if ((ch == '|') && (ch2 != '|') && (current_precedence < 6))
03019 result = result | Pcalc_C_int_expr (pptr, 6);
03020
03021 else
03022 {
03023
03024 move_Pptr (pptr, placemark);
03025 break;
03026 }
03027 }
03028
03029
03030 free_Pptr (placemark);
03031
03032 return (result);
03033 }
03034
03035 int Pcalc_C_int_factor (Pptr *pptr)
03036 {
03037 int result;
03038 int ch, sign_operator;
03039 Pptr *placemark;
03040
03041 Pskip_whitespace (pptr);
03042 ch = Ppeekc (pptr);
03043
03044
03045 if ((ch == '-') || (ch == '+'))
03046 {
03047
03048 sign_operator = ch;
03049 Pgetc(pptr);
03050 Pskip_whitespace (pptr);
03051 ch = Ppeekc (pptr);
03052 }
03053 else
03054 sign_operator = 0;
03055
03056
03057 if (isdigit (ch))
03058 {
03059
03060 ch = Pgetc (pptr);
03061 result = ch - '0';
03062
03063
03064
03065 if (ch == '0')
03066 {
03067 ch = Ppeekc (pptr);
03068 if (isdigit (ch))
03069 {
03070 Perror (pptr, "Octal representation (numbers with 0 prefix) not supported in expressions.");
03071 }
03072 else if ((ch == 'x') || (ch == 'X'))
03073 {
03074 Perror (pptr, "Hex representation (numbers with 0x prefix) not supported in expressions.");
03075 }
03076 }
03077
03078
03079
03080
03081 placemark = copy_Pptr (pptr);
03082
03083
03084 while (1)
03085 {
03086
03087 move_Pptr (placemark, pptr);
03088
03089
03090 ch = Ppeekc (pptr);
03091
03092 if (isdigit (ch))
03093 {
03094 ch = Pgetc (pptr);
03095 result = (result * 10) + (ch - '0');
03096 }
03097 else
03098 {
03099
03100 move_Pptr (pptr, placemark);
03101 break;
03102 }
03103 }
03104
03105 free_Pptr (placemark);
03106 }
03107
03108
03109 else if (ch == '(')
03110 {
03111
03112 Pgetc (pptr);
03113 result = Pcalc_C_int_expr (pptr, 0);
03114 Pskip_whitespace (pptr);
03115 if ((ch = Ppeekc (pptr)) == ')')
03116 Pgetc (pptr);
03117 else
03118 {
03119 if ((ch == 'e') || (ch == 'E') || (ch == '.'))
03120 {
03121 Perror (pptr,
03122 "Integer expression error: ')' expected.\n\n"
03123 "For floating-point expressions use: "
03124 "$.={floating-point expression}.");
03125 }
03126 else
03127 {
03128 Perror (pptr, "Integer expression error: ')' expected.");
03129 }
03130 }
03131 }
03132
03133 else
03134 {
03135 if (sign_operator != 0)
03136 {
03137 if (ch == '.')
03138 {
03139 Perror (pptr,
03140 "Integer expression error:\n"
03141 " integer or '(' expected.\n\n"
03142 "For floating-point expressions use the following form:\n"
03143 " $.={floating-point expression}.");
03144 }
03145 else
03146 {
03147 Perror (pptr,
03148 "Integer expression error:\n"
03149 " integer or '(' expected.");
03150 }
03151 }
03152 else
03153 {
03154 if (ch == '.')
03155 {
03156 Perror (pptr,
03157 "Integer expression error:\n"
03158 " integer , '(', or sign (-, +) expected.\n\n"
03159 "For floating-point expressions use the following form:\n"
03160 " $.={floating-point expression}.");
03161 }
03162 else
03163 {
03164 Perror (pptr,
03165 "Integer expression error:\n"
03166 " integer , '(', or sign (-, +) expected.");
03167 }
03168 }
03169
03170 }
03171
03172 if (sign_operator != 0)
03173 {
03174 switch (sign_operator)
03175 {
03176 case '-':
03177 result = -result;
03178 break;
03179
03180 case '+':
03181 break;
03182
03183
03184 default:
03185 Perror (pptr, "Algorithm error: undefined sign operator '%c'.",
03186 sign_operator);
03187 }
03188 }
03189
03190
03191 return (result);
03192 }
03193
03194
03195
03196
03197
03198
03199 double Pcalc_C_float_expr (Pptr *pptr, int current_precedence)
03200 {
03201 double result;
03202 int ch, ch2;
03203 int unary_operator;
03204 double temp_result;
03205 Pptr *placemark;
03206
03207
03208 Pskip_whitespace (pptr);
03209 ch = Ppeekc (pptr);
03210
03211 if (ch == '!')
03212 {
03213
03214 unary_operator = ch;
03215 Pgetc(pptr);
03216 Pskip_whitespace (pptr);
03217 ch = Ppeekc (pptr);
03218 }
03219 else if (ch == '~')
03220 {
03221 Perror (pptr, "'~' not supported in floating point expressions.");
03222 }
03223 else
03224 unary_operator = 0;
03225
03226
03227 result = Pcalc_C_float_factor (pptr);
03228
03229
03230 if (unary_operator != 0)
03231 {
03232 switch (unary_operator)
03233 {
03234 case '!':
03235 result = !result;
03236 break;
03237
03238 default:
03239 Perror (pptr, "Algorithm error: undefined unary operator '%c'.",
03240 unary_operator);
03241 }
03242 }
03243
03244
03245
03246
03247 placemark = copy_Pptr (pptr);
03248
03249
03250 while (1)
03251 {
03252
03253 move_Pptr (placemark, pptr);
03254 Pskip_whitespace (pptr);
03255
03256
03257
03258
03259 ch = Pgetc (pptr);
03260 ch2 = Ppeekc (pptr);
03261
03262
03263
03264
03265
03266
03267
03268
03269
03270
03271 if ((ch == '<') && (ch2 == '<') && (current_precedence < 11))
03272 {
03273 Perror (pptr, "'<<' not supported in floating point expressions.");
03274 }
03275
03276 else if ((ch == '>') && (ch2 == '>') && (current_precedence < 11))
03277 {
03278 Perror (pptr, "'>>' not supported in floating point expressions.");
03279 }
03280
03281 else if ((ch == '<') && (ch2 == '=') && (current_precedence < 10))
03282 {
03283
03284 Pgetc(pptr);
03285 result = result <= Pcalc_C_float_expr (pptr, 10);
03286 }
03287
03288 else if ((ch == '>') && (ch2 == '=') && (current_precedence < 10))
03289 {
03290
03291 Pgetc(pptr);
03292 result = result >= Pcalc_C_float_expr (pptr, 10);
03293 }
03294
03295 else if ((ch == '=') && (ch2 == '=') && (current_precedence < 9))
03296 {
03297
03298 Pgetc(pptr);
03299 result = result == Pcalc_C_float_expr (pptr, 9);
03300 }
03301
03302 else if ((ch == '!') && (ch2 == '=') && (current_precedence < 9))
03303 {
03304
03305 Pgetc(pptr);
03306 result = result != Pcalc_C_float_expr (pptr, 9);
03307 }
03308
03309 else if ((ch == '&') && (ch2 == '&') && (current_precedence < 5))
03310 {
03311
03312 Pgetc(pptr);
03313
03314
03315 temp_result = Pcalc_C_float_expr (pptr, 5);
03316 result = result && temp_result;
03317 }
03318
03319 else if ((ch == '|') && (ch2 == '|') && (current_precedence < 4))
03320 {
03321
03322 Pgetc(pptr);
03323
03324
03325 temp_result = Pcalc_C_float_expr (pptr, 4);
03326 result = result || temp_result;
03327 }
03328
03329
03330
03331
03332
03333 else if ((ch == '*') && (current_precedence < 13))
03334 result = result * Pcalc_C_float_expr (pptr, 13);
03335
03336 else if ((ch == '/') && (current_precedence < 13))
03337 {
03338
03339 temp_result = Pcalc_C_float_expr (pptr, 13);
03340
03341 if (temp_result == 0.0)
03342 Perror (pptr, "Float expression attempts to divide by zero.");
03343
03344 result = result / temp_result;
03345 }
03346
03347 else if ((ch == '%') && (current_precedence < 13))
03348 Perror (pptr, "'%' not supported in floating point expressions.");
03349
03350 else if ((ch == '+') && (current_precedence < 12))
03351 result = result + Pcalc_C_float_expr (pptr, 12);
03352
03353 else if ((ch == '-') && (current_precedence < 12))
03354 result = result - Pcalc_C_float_expr (pptr, 12);
03355
03356 else if ((ch == '<') && (current_precedence < 10))
03357 result = result < Pcalc_C_float_expr (pptr, 10);
03358
03359 else if ((ch == '>') && (current_precedence < 10))
03360 result = result > Pcalc_C_float_expr (pptr, 10);
03361
03362
03363
03364
03365 else if ((ch == '&') && (ch2 != '&') && (current_precedence < 8))
03366 Perror (pptr, "'&' not supported in floating point expressions.");
03367
03368 else if ((ch == '^') && (current_precedence < 7))
03369 Perror (pptr, "'^' not supported in floating point expressions.");
03370
03371
03372
03373
03374 else if ((ch == '|') && (ch2 != '|') && (current_precedence < 6))
03375 Perror (pptr, "'|' not supported in floating point expressions.");
03376
03377 else
03378 {
03379
03380 move_Pptr (pptr, placemark);
03381 break;
03382 }
03383 }
03384
03385
03386 free_Pptr (placemark);
03387
03388 return (result);
03389 }
03390
03391 double Pcalc_C_float_factor (Pptr *pptr)
03392 {
03393 double result;
03394 int ch, sign_operator;
03395 Pptr *placemark;
03396 Mbuf *double_mbuf;
03397 int after_decimal_point, in_exponent;
03398 char *double_string, *end_ptr;
03399
03400 Pskip_whitespace (pptr);
03401 ch = Ppeekc (pptr);
03402
03403
03404 if ((ch == '-') || (ch == '+'))
03405 {
03406
03407 sign_operator = ch;
03408 Pgetc(pptr);
03409 Pskip_whitespace (pptr);
03410 ch = Ppeekc (pptr);
03411 }
03412 else
03413 sign_operator = 0;
03414
03415
03416 if (isdigit (ch) || (ch == '.'))
03417 {
03418
03419
03420
03421 after_decimal_point = 0;
03422 in_exponent = 0;
03423
03424
03425 double_mbuf = create_Mbuf();
03426
03427
03428 ch = Pgetc (pptr);
03429 addc_to_Mbuf (double_mbuf, ch);
03430
03431
03432
03433
03434 if (ch == '.')
03435 {
03436 ch = Ppeekc (pptr);
03437 if (!isdigit(ch))
03438 {
03439 Perror (pptr,
03440 "Digit required after '.' in floating-point expression.");
03441 }
03442
03443
03444 after_decimal_point = 1;
03445 }
03446
03447
03448
03449
03450 placemark = copy_Pptr (pptr);
03451
03452
03453 while (1)
03454 {
03455
03456 move_Pptr (placemark, pptr);
03457
03458
03459 ch = Ppeekc (pptr);
03460
03461
03462 if (isdigit (ch))
03463 {
03464 ch = Pgetc (pptr);
03465 addc_to_Mbuf (double_mbuf, ch);
03466 }
03467
03468
03469 else if (ch == '.')
03470 {
03471
03472 if (after_decimal_point)
03473 {
03474 Perror (pptr,
03475 "Unexpected second decimal point in floating-point number.");
03476 }
03477
03478
03479 if (in_exponent)
03480 {
03481 Perror (pptr,
03482 "Unexpected decimal point in exponent.");
03483 }
03484
03485
03486 ch = Pgetc (pptr);
03487 addc_to_Mbuf (double_mbuf, ch);
03488
03489
03490 after_decimal_point = 1;
03491 }
03492
03493
03494 else if ((ch == 'e') || (ch == 'E'))
03495 {
03496
03497 if (in_exponent)
03498 {
03499 Perror (pptr, "Unexpected second exponent specified.");
03500 }
03501
03502
03503 in_exponent = 1;
03504
03505
03506 ch = Pgetc (pptr);
03507 addc_to_Mbuf (double_mbuf, ch);
03508
03509
03510 ch = Ppeekc (pptr);
03511 if ((ch == '+') || (ch == '-'))
03512 {
03513 ch = Pgetc (pptr);
03514 addc_to_Mbuf (double_mbuf, ch);
03515 }
03516
03517
03518 ch = Ppeekc (pptr);
03519 if (!isdigit (ch))
03520 {
03521 Perror (pptr, "Exponent expected not '%c'.", ch);
03522 }
03523 }
03524 else
03525 {
03526
03527 move_Pptr (pptr, placemark);
03528 break;
03529 }
03530 }
03531
03532
03533 double_string = get_Mbuf_buf (double_mbuf);
03534 result = strtod (double_string, &end_ptr);
03535
03536
03537
03538 if (*end_ptr != 0)
03539 {
03540 Perror (pptr, "Invalid float number '%s' in expression.",
03541 double_string);
03542 }
03543
03544
03545 free_Mbuf (double_mbuf);
03546
03547 free_Pptr (placemark);
03548 }
03549
03550
03551 else if (ch == '(')
03552 {
03553
03554 Pgetc (pptr);
03555 result = Pcalc_C_float_expr (pptr, 0);
03556 Pskip_whitespace (pptr);
03557 if ((ch = Ppeekc (pptr)) == ')')
03558 Pgetc (pptr);
03559 else
03560 {
03561 Perror (pptr, "Floating-point expression error: ')' expected.");
03562
03563 }
03564 }
03565
03566 else
03567 {
03568 if (sign_operator != 0)
03569 {
03570 Perror (pptr,
03571 "Floating-point expression error: integer, '.', or '(' expected.");
03572 }
03573 else
03574 {
03575 Perror (pptr,
03576 "Floating-point expression error: integer , '(', '.', or sign (-, +) expected.");
03577 }
03578
03579 }
03580
03581 if (sign_operator != 0)
03582 {
03583 switch (sign_operator)
03584 {
03585 case '-':
03586 result = -result;
03587 break;
03588
03589 case '+':
03590 break;
03591
03592
03593 default:
03594 Perror (pptr, "Algorithm error: undefined sign operator '%c'.",
03595 sign_operator);
03596 }
03597 }
03598
03599
03600 return (result);
03601 }
03602
03603
03604
03605
03606 Pdef *create_Pdef (char *name, char *val, int allow_implicit_replacement,
03607 int level)
03608 {
03609 Pdef *def;
03610
03611 def = (Pdef *) L_alloc (Pdef_pool);
03612
03613 def->name = strdup (name);
03614 def->val = strdup (val);
03615 def->allow_implicit_replacement = allow_implicit_replacement;
03616 def->level = level;
03617
03618 return (def);
03619 }
03620
03621 void free_Pdef (void *def_v)
03622 {
03623 Pdef *def;
03624
03625 def = (Pdef *) def_v;
03626
03627 free (def->name);
03628 free (def->val);
03629
03630 L_free (Pdef_pool, def);
03631 }
03632
03633 void add_Pdef (char *name, char *val, int allow_implicit_replacement,
03634 int level)
03635 {
03636 Psymbol *psymbol;
03637 Pdef *pdef;
03638
03639
03640
03641
03642 psymbol = find_Psymbol (Pdef_table, name);
03643
03644 if (psymbol == NULL)
03645 {
03646 pdef = create_Pdef (name, val, allow_implicit_replacement, level);
03647 add_Psymbol (Pdef_table, name, (void *)pdef);
03648 }
03649 else
03650 {
03651 pdef = (Pdef *) psymbol->data;
03652
03653
03654
03655 if (pdef->level > level)
03656 return;
03657
03658 free (pdef->val);
03659 pdef->val = strdup (val);
03660 pdef->allow_implicit_replacement = allow_implicit_replacement;
03661 pdef->level = level;
03662 }
03663 }
03664
03665 void delete_Pdef (char *name)
03666 {
03667 Psymbol *psymbol;
03668
03669
03670 psymbol = find_Psymbol (Pdef_table, name);
03671
03672 if (psymbol != NULL)
03673 delete_Psymbol (psymbol, free_Pdef);
03674 }
03675
03676
03677
03678
03679
03680 char *Plookup (char *name, int implicit_replacement)
03681 {
03682 Psymbol *symbol;
03683 Pdef *def;
03684
03685 if ((symbol = find_Psymbol (Pdef_table, name)) != NULL)
03686 {
03687 def = (Pdef *) symbol->data;
03688
03689
03690
03691
03692 if (implicit_replacement && !def->allow_implicit_replacement)
03693 return (NULL);
03694
03695 return (def->val);
03696 }
03697
03698 return (NULL);
03699 }