~ubuntu-branches/ubuntu/warty/aqsis/warty

« back to all changes in this revision

Viewing changes to slpp/pp1.c

  • Committer: Bazaar Package Importer
  • Author(s): LaMont Jones
  • Date: 2004-08-24 07:25:04 UTC
  • Revision ID: james.westby@ubuntu.com-20040824072504-zf993vnevvisdsvb
Tags: upstream-0.9.1
ImportĀ upstreamĀ versionĀ 0.9.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/************************************************************************/
 
2
/*                                                                      */
 
3
/*      File:   pp1.c                                                   */
 
4
/*                                                                      */
 
5
/*      Main program module.                                            */
 
6
/*                                                                      */
 
7
/*      Written by:                                                     */
 
8
/*                      Gary Oliver                                     */
 
9
/*                      3420 NW Elmwood Dr.                             */
 
10
/*                      PO Box 826                                      */
 
11
/*                      Corvallis, Oregon 97339                         */
 
12
/*                      (503)758-5549                                   */
 
13
/*      Maintained by:                                                  */
 
14
/*                      Kirk Bailey                                     */
 
15
/*                      Logical Systems                                 */
 
16
/*                      P.O. Box 1702                                   */
 
17
/*                      Corvallis, OR 97339                             */
 
18
/*                      (503)753-9051                                   */
 
19
/*                                                                      */
 
20
/*      This program is hereby placed in the public domain.  In         */
 
21
/*      contrast to other claims of "public domain", this means no      */
 
22
/*      copyright is claimed and you may do anything you like with PP,  */
 
23
/*      including selling it!  As a gesture of courtesy, please retain  */
 
24
/*      the authorship information in the source code and               */
 
25
/*      documentation.                                                  */
 
26
/*                                                                      */
 
27
/*      Synopsis:                                                       */
 
28
/*              PP [inputfile] -[cdeilostuvz?]                          */
 
29
/*                      -c 0|1|2|3|4|5|6 Enable desired option:         */
 
30
/*                              0 -> Replace arguments in strings.      */
 
31
/*                              1 -> Expand macros inside #pragma asm.  */
 
32
/*                              2 -> Allow recursive comments.          */
 
33
/*                              3 -> Rescan macro expansions for        */
 
34
/*                                      directives.                     */
 
35
/*                              4 -> Allow macro definitions and undefs */
 
36
/*                                      to stack.                       */
 
37
/*                              5 -> Perform Trigraph translation.      */
 
38
/*                              6 -> Allow C++ style "//" eol comments  */
 
39
/*                      -d: define symbols (-d symbol[=value].)         */
 
40
/*                      -e: Don't abort on errors.                      */
 
41
/*                      -i <list>: Specify path for #include searches.  */
 
42
/*                      -l <t>: Control line # emission to the Output   */
 
43
/*                              file.  If <t> == 'n' don't emit any     */
 
44
/*                              explicit line # info.  If <t> == 'a',   */
 
45
/*                              then use the abbreviated form:          */
 
46
/*                                      "#<n> |filename|"               */
 
47
/*                              If <t> == 'l' then use the "long" form: */
 
48
/*                                      "#line <n> |filename|"          */
 
49
/*                              The "long" form is the default.         */
 
50
/*                      -o: Specify output file name (def: <infile>.pp) */
 
51
/*                      -s: Product statistics info at end (DEBUG only.)*/
 
52
/*                      -t: Specify add/remove token characters.        */
 
53
/*                      -u: Undefine an initial symbol (e.g. CPM)       */
 
54
/*                      -v: Invert VERBOSE toggle.                      */
 
55
/*                      -z: Output DEBUG messages (DEBUG only.)         */
 
56
/*                      -?: Print usage information.                    */
 
57
/*                                                                      */
 
58
/*      If [inputfile] is absent, standard input is assumed.            */
 
59
/*                                                                      */
 
60
/*      Description:                                                    */
 
61
/*              PP is a general purpose preprocessor that handles       */
 
62
/*              ANSI C style preprocessor directives.                   */
 
63
/*                                                                      */
 
64
/*      Example:                                                        */
 
65
/*              PP test.c                                               */
 
66
/*                                                                      */
 
67
/*      History:                                                        */
 
68
/*              Inspired by the PP.C program by:                        */
 
69
/*                                                                      */
 
70
/*                      Robert T. Pasky                                 */
 
71
/*                      36 Wiswall Rd                                   */
 
72
/*                      Newton Centre, MA 02159                         */
 
73
/*                      (617) 964-3641                                  */
 
74
/*                                                                      */
 
75
/*              which, in turn, was based upon the Ratfor               */
 
76
/*              version found in K&P's Software Tools.                  */
 
77
/*                                                                      */
 
78
/*              30-Mar-85 GO    First entered.                          */
 
79
/*                                                                      */
 
80
/*      Conventions:                                                    */
 
81
/*              The convention used within this program is to           */
 
82
/*              capitalize global variable names.  Function             */
 
83
/*              names, per the C convention, are not capitalized.       */
 
84
/*                                                                      */
 
85
/*      Future features:                                                */
 
86
/*              Generalize on a means for generating the output         */
 
87
/*              name.  Currently ".pp" is appended to the input         */
 
88
/*              file name, after the input file extension (if any)      */
 
89
/*              is removed.  Dave Regan suggests prepending a '$'       */
 
90
/*              to the input file name and using that as the output     */
 
91
/*              name, retaining the input file's extension (if any).    */
 
92
/*              (e.g. ABC.XYZ becomes $ABC.XYZ)  Must think on this.    */
 
93
/*                                                                      */
 
94
/*              Some performance enhancement may be gained by using     */
 
95
/*              a better symbol table allocation or simply a better     */
 
96
/*              hashing function.  I will have to check some            */
 
97
/*              reference materials...                                  */
 
98
/*                                                                      */
 
99
/*      Functions contained in this module:                             */
 
100
/*                                                                      */
 
101
/*              main            Main module.                            */
 
102
/*              getnext         Get next parameter from argv/argc.      */
 
103
/*              init            Initialize the preprocessor.            */
 
104
/*              usage           Print usage information.                */
 
105
/*                                                                      */
 
106
/*      * Unix is a trademark/footnote of Bell Laboratories.            */
 
107
/*      * CP/M is a trademark of Digital Resarch, Inc.                  */
 
108
/*      * Q/C is a trademark of Quality Computer Systems.               */
 
109
/*      * VMS is a trademark of Digital Equipment Corporation.          */
 
110
/*                                                                      */
 
111
/************************************************************************/
 
112
 
 
113
#define         MAIN                    /* This is the main() module */
 
114
 
 
115
#include        "pp.h"
 
116
#include        "ppext.h"
 
117
 
 
118
#ifdef  __TURBOC__
 
119
extern  unsigned        _stklen = 32767;
 
120
#endif  /* __TURBOC__ */
 
121
 
 
122
/************************************************************************/
 
123
/*                                                                      */
 
124
/*      main                                                            */
 
125
/*                                                                      */
 
126
/*      The main program.                                               */
 
127
/*                                                                      */
 
128
/************************************************************************/
 
129
 
 
130
#ifdef  MSC_OPT
 
131
#pragma optimize("e",off)               /* Disable global reg optimizing */
 
132
#pragma optimize("g",off)               /* Disable global common subs */
 
133
#pragma optimize("l",off)               /* Disable loop optimizations */
 
134
#endif  /* MSC_OPT */
 
135
 
 
136
void
 
137
#ifdef  SLPP_LIBRARY
 
138
PreProcess(argc,argv)
 
139
#else
 
140
main(argc,argv)
 
141
#endif
 
142
        int                     argc;
 
143
        char                    **argv;
 
144
        {
 
145
        static  char            *one_string = "1";
 
146
 
 
147
        register int            t;      /* General holder for token     */
 
148
        register struct symtab  *p;     /* Ptr into symbol table        */
 
149
        register struct ppdir   *sp;    /* Ptr to predefined symbol     */
 
150
        int                     ifile;
 
151
        int                     ofile;
 
152
        char                    *s;
 
153
        char                    *s2;
 
154
        int                     i;
 
155
#if     DEBUG
 
156
        int                     n;
 
157
#endif  /* DEBUG */
 
158
        int                     skip;   /* Boolean for option loop      */
 
159
 
 
160
        init();                         /* Initialize preprocessor      */
 
161
 
 
162
        ifile   =                       /* No input file specified      */
 
163
        ofile   = FALSE;                /* No output file specified     */
 
164
 
 
165
        while(--argc != 0)
 
166
                {
 
167
                s = *++argv;
 
168
                if(s[0] == '-')
 
169
                        {
 
170
                        skip = FALSE;
 
171
                        while((! skip) && (*++s != '\0'))
 
172
                                {
 
173
                                switch((int) *s)
 
174
                                        {
 
175
                                        /* -[c 0|1|2|3|4|5|6] */
 
176
                                        case 'C':
 
177
                                        case 'c':
 
178
                                s2 = getnext(s,&argc,&argv,NO);
 
179
                                switch((int) *s2)
 
180
                                        {
 
181
                                        case '0':
 
182
                                                s2 = "arg_string";
 
183
                                                break;
 
184
 
 
185
                                        case '1':
 
186
                                                s2 = "asm_expand";
 
187
                                                break;
 
188
 
 
189
                                        case '2':
 
190
                                                s2 = "comment_recurse";
 
191
                                                break;
 
192
 
 
193
                                        case '3':
 
194
                                                s2 = "macro_rescan";
 
195
                                                break;
 
196
 
 
197
                                        case '4':
 
198
                                                s2 = "macro_stack";
 
199
                                                break;
 
200
 
 
201
                                        case '5':
 
202
                                                s2 = "trigraph";
 
203
                                                break;
 
204
 
 
205
                                        case '6':
 
206
                                                s2 = "eol_comment";
 
207
                                                break;
 
208
 
 
209
                                        default:
 
210
                                                usage(TRUE);
 
211
                                        }
 
212
                                pragopt(EMPTY,FALSE,s2);
 
213
                                skip = TRUE;
 
214
                                break;
 
215
 
 
216
                                        /* -[d symbol [= value]] */
 
217
                                        case 'D':
 
218
                                        case 'd':
 
219
                                s = getnext(s,&argc,&argv,NO);
 
220
                                s2 = strchr(s,'=');     /* Location of val */
 
221
                                if(s2)
 
222
                                        *s2++ = '\0';   /* Terminate string */
 
223
                                else
 
224
                                        s2 = one_string;        /* Default */
 
225
                                
 
226
                                if(lookup(s,NULL) != NULL)
 
227
                                        warning("Symbol already defined: ",s);
 
228
                                else
 
229
                                        sbind(s,s2,NO_PARAMS);
 
230
 
 
231
                                skip = TRUE;    /* Skip to next param */
 
232
                                break;
 
233
 
 
234
                                        /* -[e] don't abort on errors */
 
235
                                        case 'E':
 
236
                                        case 'e':
 
237
                                Eflag = TRUE;
 
238
                                break;
 
239
 
 
240
                                        /* -iI <#include search path> */
 
241
                                        case 'I':
 
242
                                        case 'i':
 
243
                                if(Ipcnt > NIPATHS)
 
244
                                        fatal("Too many pathnames","");
 
245
                                Ipath[Ipcnt++] = getnext(s,&argc,&argv,NO);
 
246
                                skip = TRUE;    /* Skip to next param */
 
247
                                break;
 
248
 
 
249
                                        /* -[l a|l|n] Spec #line output mode */
 
250
                                        case 'L':
 
251
                                        case 'l':
 
252
                                s2 = getnext(s,&argc,&argv,NO);
 
253
                                switch((int) *s2)
 
254
                                        {
 
255
                                        case 'A':
 
256
                                        case 'a':
 
257
                                                Lineopt = LINE_ABR;
 
258
                                                break;
 
259
 
 
260
                                        case 'L':
 
261
                                        case 'l':
 
262
                                                Lineopt = LINE_EXP;
 
263
                                                break;
 
264
 
 
265
                                        case 'N':
 
266
                                        case 'n':
 
267
                                                Lineopt = FALSE;
 
268
                                                break;
 
269
 
 
270
                                        default:
 
271
                                                usage(TRUE);
 
272
                                        }
 
273
                                skip = TRUE;    /* Skip to next param */
 
274
                                break;
 
275
 
 
276
                                        /* -[o file] spec output file name */
 
277
                                        case 'O':
 
278
                                        case 'o':
 
279
                                s2 = getnext(s,&argc,&argv,NO);
 
280
                                strcpy(Outfile,s2);     /* Copy filename */
 
281
                                ofile = TRUE;
 
282
                                skip = TRUE;    /* Skip to next param */
 
283
                                break;
 
284
 
 
285
#if     DEBUG
 
286
                                        /* -[s] give statistics at end */
 
287
                                        case 'S':
 
288
                                        case 's':
 
289
                                Stats = Verbose = TRUE; /* Implies Verbose */
 
290
                                break;
 
291
#endif  /* DEBUG */
 
292
                /* -[t Astr|Rstr] Add or delete chars from LETTER class */
 
293
                                        case 'T':
 
294
                                        case 't':
 
295
                                s2 = getnext(s,&argc,&argv,NO);
 
296
                                switch((int) *s2++)
 
297
                                        {
 
298
                                        case 'a':
 
299
                                        case 'A':
 
300
                                                i = TRUE;
 
301
                                                break;
 
302
 
 
303
                                        case 'r':
 
304
                                        case 'R':
 
305
                                                i = FALSE;
 
306
                                                break;
 
307
 
 
308
                                        default:
 
309
                                                usage(TRUE);
 
310
                                        }
 
311
 
 
312
                                for(; *s2 != '\0'; s2++)
 
313
                                        {
 
314
                                        if(i)
 
315
                                                typetab[*s2 + 1] |= C_L;
 
316
                                        else
 
317
                                                typetab[*s2 + 1] &= ~C_L;
 
318
                                        }
 
319
 
 
320
                                skip = TRUE;    /* Skip to next param */
 
321
                                break;
 
322
 
 
323
                                        /* -[u symbol] */
 
324
                                        case 'U':
 
325
                                        case 'u':
 
326
                                s = getnext(s,&argc,&argv,NO);
 
327
 
 
328
                                if(lookup(s,NULL) == NULL)
 
329
                                        warning("Symbol not defined: ",s);
 
330
                                else
 
331
                                        unsbind(s);
 
332
                                skip = TRUE;    /* Skip to next param */
 
333
                                break;
 
334
 
 
335
                                        /* -[v] verbose mode toggle */
 
336
                                        case 'V':
 
337
                                        case 'v':
 
338
                                Verbose = !Verbose;
 
339
                                break;
 
340
 
 
341
#if     DEBUG
 
342
                                        /* -[z] enable debug */
 
343
                                        case 'Z':
 
344
                                        case 'z':
 
345
                                Debug = TRUE;
 
346
                                printf("Debug is on\n");
 
347
                                break;
 
348
#endif  /* DEBUG */
 
349
                                        case '?':
 
350
                                usage(FALSE);   /* Give usage info and quit */
 
351
 
 
352
                                        default:
 
353
                                fprintf(STDERR,"FATAL: Bad option: %s\n",s);
 
354
                                usage(TRUE);
 
355
                                        }
 
356
                                }
 
357
                        }
 
358
                else if(! ifile)
 
359
                        {
 
360
                        /* Try to get input file */
 
361
#if     HOST == H_CPM
 
362
                        if(! inc_open(s,-1,0))  /* Open file here */
 
363
#else   /* HOST != H_CPM */
 
364
                        if(! inc_open(s))       /* Open input file */
 
365
#endif  /* HOST == H_CPM */
 
366
                                {
 
367
                                fatal("Unable to open input file: ",s);
 
368
                                }
 
369
                        ifile = TRUE;   /* Got an input file */
 
370
                        }
 
371
                else
 
372
                        {
 
373
                        /* Too many file names given */
 
374
                        usage(TRUE);
 
375
                        }
 
376
                }
 
377
 
 
378
        Nextch = A_trigraph ? trigraph : gchbuf;        /* Next char source */
 
379
 
 
380
        if(! ifile)
 
381
                {
 
382
                /* Must have at least an input file name */
 
383
                usage(TRUE);
 
384
                }
 
385
 
 
386
        if(! ofile)
 
387
                {
 
388
                /* No output name given; use input name and modify it */
 
389
                strcpy (Outfile,Filestack[0]->f_name);
 
390
                /* terminate the file name before any extension */
 
391
                if((s = strrchr(Outfile,'.')) != NULL)
 
392
                        *s = '\0';
 
393
                strcat(Outfile,".pp");
 
394
                }
 
395
        else
 
396
                {
 
397
                if(strcmp(Outfile,Filestack[0]->f_name) == EQUAL)
 
398
                        fatal("Input and output filenames are the same: ",Outfile);
 
399
                else if((Output = fopen(Outfile,"w")) == NULL)
 
400
                        fatal("Unable to create output file: ",Outfile);
 
401
                }
 
402
 
 
403
#if     HOST == H_CPM
 
404
        /* Create a bigger than average buffer */
 
405
        if((s = malloc(OUTBUFSIZE)) == NULL)
 
406
                out_of_memory();
 
407
        setbuf(Output,s);
 
408
        setbsize(Output,OUTBUFSIZE);
 
409
#endif  /* HOST == H_CPM */
 
410
 
 
411
        if(Verbose)
 
412
                {
 
413
                printf("%s%s\n\n","PP Preprocessor, ",VERSION);
 
414
                printf("Output will be on <%s>\n",Outfile);
 
415
                printf("*** Read    %s\n",Filestack[Filelevel]->f_name);
 
416
                }
 
417
 
 
418
        Do_name = TRUE;                 /* Force name output on #line */
 
419
 
 
420
        init_path();                    /* Initialize search path */
 
421
        Ipath[Ipcnt] = NULL;            /* Terminate last include path */
 
422
 
 
423
        for(Lastnl = TRUE, t = gettoken(GT_STR); t != EOF;
 
424
                t = gettoken(GT_STR))
 
425
                {
 
426
                if((Ifstate != IFTRUE) && (t != '\n') && istype(t,C_W))
 
427
                        {
 
428
                        }
 
429
                else if(Lastnl && (t == DIRECTIVE_CHAR))
 
430
                        {
 
431
                        t = getnstoken(GT_STR);
 
432
                        if(t == LETTER)
 
433
                                {
 
434
                                if((sp = predef(Token,pptab)) != NULL)
 
435
                                        {
 
436
/*
 
437
 *      If unconditionally do it or if emitting code...
 
438
 */
 
439
                                        if(sp->pp_ifif || (Ifstate == IFTRUE))
 
440
                                                {
 
441
/* Do #func */                                  (void) (*(sp->pp_func))
 
442
                                                        (sp->pp_arg);
 
443
                                                }
 
444
                                        }
 
445
                                else if(Ifstate == IFTRUE)
 
446
                                        non_fatal("Illegal directive","");
 
447
 
 
448
                                scaneol();      /* Suck till EOL ('\n' next) */
 
449
                                }
 
450
                        else if(t != '\n')
 
451
                                {
 
452
                                non_fatal("Bad directive","");
 
453
                                scaneol();
 
454
                                }
 
455
                        else
 
456
                                pushback('\n'); /* Leave for fetch to get */
 
457
                        }
 
458
                else if((t != EOF) && (Ifstate == IFTRUE))
 
459
                        {
 
460
#if     (TARGET == T_QC) OR (TARGET == T_QCX) OR (TARGET == T_TCX)
 
461
                        if(t == LETTER && Macexpand)
 
462
#else   /* !((TARGET == T_QC) OR (TARGET == T_QCX) OR (TARGET == T_TCX)) */
 
463
                        if(t == LETTER)
 
464
#endif  /* (TARGET == T_QC) OR (TARGET == T_QCX) OR (TARGET == T_TCX) */
 
465
                                {
 
466
                                if((p = lookup(Token,NULL)) != NULL)
 
467
                                        {
 
468
/* Call macro */                        (void) docall(p,NULL,NULL);
 
469
                                        }
 
470
                                else
 
471
/* Just output token if nothing */      puttoken(Token);
 
472
                                }
 
473
                        else
 
474
                                {
 
475
                                puttoken(Token);
 
476
                                if(t == '\n')
 
477
                                        Lastnl = TRUE;  /* Turn on if '\n' */
 
478
                                else if(! istype(t,C_W))
 
479
                                        Lastnl = FALSE; /* Turn off if !ws */
 
480
                                }
 
481
                        }
 
482
                else
 
483
                        {
 
484
                        while((t != '\n') && (t != EOF))
 
485
                                {
 
486
                                /* Absorb to EOL if False #ifxx */
 
487
                                t = gettoken(GT_STR);
 
488
                                }
 
489
                        Lastnl = TRUE;
 
490
                        }
 
491
                }
 
492
 
 
493
        if(Iflevel != 0)
 
494
                {
 
495
                /* Unterminated #if */
 
496
                non_fatal("Unterminated conditional","");
 
497
                }
 
498
 
 
499
        if(Verbose)
 
500
                {
 
501
        printf("\nActive symbols at end:\t%d\tMaximum symbols used:\t%d\n",
 
502
                        Nsyms,Maxsyms);
 
503
#if     HOST == H_CPM
 
504
                printf("Free memory: %5u\n",maxsbrk());
 
505
#endif  /* HOST == H_CPM */
 
506
                }
 
507
 
 
508
        if(Verbose || Errors)
 
509
                {
 
510
                if(Errors)
 
511
                        printf("\n%d errors detected\n",Errors);
 
512
                else
 
513
                        printf("\nNo errors detected\n");
 
514
                }
 
515
 
 
516
#if     DEBUG
 
517
        if(Stats)
 
518
                {
 
519
                printf("\nSymbol table bucket statistics:");
 
520
                for(i = 0; i < NUMBUCKETS; i++)
 
521
                        {
 
522
                        if((i % 8) == 0)
 
523
                                printf("\n");   /* New line */
 
524
                        for(n = 0, p = Macros[i]; p != 0; p = p->s_link, n++)
 
525
                                ;       /* Count items in list */
 
526
                        printf("  %3d:%-3d",i,n);
 
527
                        }
 
528
                printf("\n\n");
 
529
                }
 
530
#endif  /* DEBUG */
 
531
 
 
532
        if((Output != stdout) && (fclose(Output) == EOF))
 
533
                fatal("Unable to close output file: ",Outfile);
 
534
#ifdef  SLPP_LIBRARY
 
535
        return;
 
536
#else
 
537
        exit(Eflag ? 0 : Errors);
 
538
#endif  /* SLPP_LIBRARY */
 
539
        }
 
540
 
 
541
#ifdef  MSC_OPT
 
542
#pragma optimize("e",on)                /* Enable global reg optimizing */
 
543
#pragma optimize("g",on)                /* Enable global common subs */
 
544
#pragma optimize("l",on)                /* Enable loop optimizing */
 
545
#endif  /* MSC_OPT */
 
546
 
 
547
/************************************************************************/
 
548
/*                                                                      */
 
549
/*      getnext                                                         */
 
550
/*                                                                      */
 
551
/*      Get next parameter from parameter line and return its address.  */
 
552
/*      If the character following the current parameter (cp) is non-   */
 
553
/*      null, then return that parameter, otherwise look ahead in the   */
 
554
/*      argv list to fetch the next one.  Give a usage() error if the   */
 
555
/*      parameter list is empty or if the fetched parameter's first     */
 
556
/*      character is a '-' and the <swvalid> parameter is NO.           */
 
557
/*                                                                      */
 
558
/************************************************************************/
 
559
 
 
560
char    *
 
561
getnext(cp,argc,argv,swvalid)
 
562
        char                    *cp;
 
563
        int                     *argc;
 
564
        char                    ***argv;
 
565
        int                     swvalid;        /* True if -x token valid */
 
566
        {
 
567
        if(*++cp == '\0')
 
568
                {
 
569
                if(*argc != 0)
 
570
                        {
 
571
                        /* Parameters remain -- use next one */
 
572
                        --*argc;        /* Count it down */
 
573
                        cp = *++*argv;  /* Return its address */
 
574
                        }
 
575
                else
 
576
                        usage(TRUE);    /* Otherwise give usage error */
 
577
                }
 
578
 
 
579
        if(!swvalid && (*cp == '-'))
 
580
                usage(TRUE);            /* Complain if switch starts w/'-' */
 
581
 
 
582
        return (cp);
 
583
        }
 
584
 
 
585
/************************************************************************/
 
586
/*                                                                      */
 
587
/*      init                                                            */
 
588
/*                                                                      */
 
589
/*      Initialize the preprocessor.                                    */
 
590
/*                                                                      */
 
591
/************************************************************************/
 
592
 
 
593
void
 
594
init()
 
595
        {
 
596
        static  char            *one_string = "1";
 
597
 
 
598
        char                    *fromptr;
 
599
        int                     i;
 
600
#if     (HOST != H_CPM) AND (HOST != H_MPW)
 
601
        time_t                  long_time;      /* time_t def'd in "time.h" */
 
602
#endif  /* (HOST != H_CPM) AND (HOST != H_MPW) */
 
603
        char                    str[TOKENSIZE + 1];
 
604
        char                    *toptr;
 
605
 
 
606
#if     DEBUG
 
607
        Debug = FALSE;
 
608
#endif  /* DEBUG */
 
609
 
 
610
        Verbose = FALSE;                /* Set verbose state */
 
611
 
 
612
        Eflag = FALSE;                  /* Say to abort on errors */
 
613
        Lineopt = LINE_EXP;             /* Default to "long" #line form */
 
614
 
 
615
#if     (TARGET == T_QC) OR (TARGET == T_QCX) OR (TARGET == T_TCX)
 
616
        Do_asm = FALSE;                 /* Not inside #pragma asm/endasm */
 
617
        Macexpand = TRUE;               /* Macro expansion enabled */
 
618
        Asmexpand = FALSE;              /* Disabled inside asm/endasm */
 
619
#endif  /* (TARGET == T_QC) OR (TARGET == T_QCX) OR (TARGET == T_TCX) */
 
620
 
 
621
        Outline = 1;                    /* Line number of next output line */
 
622
 
 
623
        Filelevel = -1;                 /* Current file level */
 
624
 
 
625
        Pbbuf = Pbbufp =
 
626
                (struct pbbuf *) malloc(sizeof(struct pbbuf) * PUSHBACKSIZE);
 
627
 
 
628
        if(Pbbufp == NULL)
 
629
                out_of_memory();
 
630
 
 
631
        Pbbufp->pb_type = PB_TOS;       /* Top of stack marker */
 
632
 
 
633
        A_astring       =               /* Replace args within strings  */
 
634
        A_crecurse      =               /* No recursive comments        */
 
635
        A_eolcomment    =               /* No eol comments              */
 
636
        A_rescan        =               /* No macro gen'd directives    */
 
637
        A_stack         =               /* No stacking of macro def's   */
 
638
        A_trigraph      = FALSE;        /* No Trigraph translation      */
 
639
 
 
640
        Nsyms           =               /* Number of symbols generated  */
 
641
        Errors          =               /* Zero the error counter       */
 
642
        Iflevel         =               /* #if stack pointer            */
 
643
        Ipcnt           =               /* Number of -i paths           */
 
644
        Unique          = 0;            /* Zero unique # counter        */
 
645
 
 
646
        Ifstack[0].i_state = Ifstate =
 
647
                IFTRUE;                 /* Currently TRUE #ifxxx assumed */
 
648
 
 
649
#if     HOST == H_CPM
 
650
        Orig_user = bdos1(BDOS_USER,0xFF);      /* Save user and disk */
 
651
        Orig_disk = bdos1(BDOS_GETDISK,0);
 
652
#endif  /* HOST == H_CPM */
 
653
 
 
654
/*
 
655
 *      Initialize the Time and Date variables to hold the ANSI strings that
 
656
 *      each will print out in response to __TIME__ and __DATE__ respectively.
 
657
 */
 
658
#if     (HOST == H_CPM) OR (HOST == H_MPW)
 
659
        strcpy(_Time,"HH:MM:SS");       /* Fake a time */
 
660
        strcpy(Date,"Mmm DD YYYY");
 
661
#else   /* !((HOST == H_CPM) OR (HOST == H_MPW)) */
 
662
        (void) time(&long_time);        /* Seconds since whenever... */
 
663
        strncpy(str,asctime(localtime(&long_time)),26); /* Get time/date */
 
664
 
 
665
        strncpy(_Time,&str[11],8);      /* Pull time portion out of string */
 
666
        _Time[8] = '\0';
 
667
 
 
668
        strncpy(Date,&str[4],7);        /* Pull month and day out of string */
 
669
        strncpy(&Date[7],&str[20],4);   /* Pull year out of string */
 
670
        Date[11] = '\0';
 
671
#endif  /* (HOST == H_CPM) OR (HOST == H_MPW) */
 
672
 
 
673
    /************************************/
 
674
    /* Define the automatic definitions */
 
675
    /************************************/
 
676
 
 
677
#if     TARGET == T_UNIX
 
678
        sbind("unix",one_string,NO_PARAMS);     /* #define unix 1 */
 
679
#endif  /* TARGET == T_UNIX */
 
680
 
 
681
#if     TARGET == T_BSD
 
682
        sbind("unix",one_string,NO_PARAMS);     /* #define unix 1 */
 
683
        sbind("BSD",one_string,NO_PARAMS);      /* #define BSD 1 */
 
684
#endif  /* TARGET == T_BSD */
 
685
 
 
686
#if     TARGET == T_VMS
 
687
        sbind("VMS",one_string,NO_PARAMS);      /* #define VMS 1 */
 
688
#endif  /* TARGET == T_VMS */
 
689
 
 
690
#if     (TARGET == T_QC) OR (TARGET == T_QCX)
 
691
        sbind("CPM",one_string,NO_PARAMS);      /* #define CPM 1 */
 
692
        sbind("QC",one_string,NO_PARAMS);       /* #define QC 1 */
 
693
        /* Generate asm() macro */
 
694
        sbind("asm",";\n#pragma asm\n_PARAM_\n#pragma endasm\n",
 
695
                makeparam("_PARAM_",PF_RQUOTES));
 
696
#endif  /* (TARGET == T_QC) OR (TARGET == T_QCX) */
 
697
 
 
698
#if     TARGET == T_TCX
 
699
        sbind("TC",one_string,NO_PARAMS);       /* #define TC 1 */
 
700
        /* Generate asm() macro */
 
701
        sbind("asm",";\n#pragma asm\n_PARAM_\n#pragma endasm\n",
 
702
                makeparam("_PARAM_",PF_RQUOTES));
 
703
#endif  /* TARGET == T_TCX */
 
704
 
 
705
/*      Now bind the automatic line/file generators, etc.       */
 
706
 
 
707
        str[1] = '\0';
 
708
        str[0] = (char) LINE_TOKEN;     sbind("__LINE__",str,NO_PARAMS);
 
709
        str[0] = (char) FILE_TOKEN;     sbind("__FILE__",str,NO_PARAMS);
 
710
        str[0] = (char) TIME_TOKEN;     sbind("__TIME__",str,NO_PARAMS);
 
711
        str[0] = (char) DATE_TOKEN;     sbind("__DATE__",str,NO_PARAMS);
 
712
        str[0] = (char) NOW_TOKEN;      sbind("__NOW__",str,NO_PARAMS);
 
713
        str[0] = (char) NEXT_TOKEN;     sbind("__NEXT__",str,NO_PARAMS);
 
714
        str[0] = (char) PREV_TOKEN;     sbind("__PREV__",str,NO_PARAMS);
 
715
 
 
716
/*      Bind macro symbols for the configuration setting variables      */
 
717
 
 
718
        for(i = 0; pragtab[i].pp_name != NULL; i++)
 
719
                {
 
720
                if(pragtab[i].pp_func == pragopt)
 
721
                        {
 
722
                        strcpy(str,"__");
 
723
                        for(toptr = &str[2], fromptr = pragtab[i].pp_name;
 
724
                                *fromptr; fromptr++)
 
725
                                {
 
726
                                *toptr++ = (islower(*fromptr) ?
 
727
                                        toupper(*fromptr) : *fromptr);
 
728
                                }
 
729
                        *toptr = '\0';
 
730
                        strcat(str,"__");
 
731
                        sbind(str,"0",NO_PARAMS);
 
732
                        }
 
733
                }
 
734
        }
 
735
 
 
736
/************************************************************************/
 
737
/*                                                                      */
 
738
/*      usage                                                           */
 
739
/*                                                                      */
 
740
/*      Print usage information and exit with argument passed.          */
 
741
/*                                                                      */
 
742
/************************************************************************/
 
743
 
 
744
void
 
745
usage(v)
 
746
        int                     v;
 
747
        {
 
748
        printf(
 
749
#if     DEBUG
 
750
"Usage: pp <input> -[cdeilostuvz?]\n%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
 
751
#else   /* !DEBUG */
 
752
"Usage: pp <input> -[cdeilotuv?]\n%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
 
753
#endif  /* DEBUG */
 
754
        "   -c 0|1|2|3|4|5|6 Enable the desired configuration option:\n",
 
755
        "              0 -> Replace macro arguments in strings.\n",
 
756
        "              1 -> Expand macros inside #pragma asm.\n",
 
757
        "              2 -> Allow recursive comments.\n",
 
758
        "              3 -> Rescan macro expansions for directives.\n",
 
759
        "              4 -> Allow macro defs and undefs to stack/unstack.\n",
 
760
        "              5 -> Perform Trigraph input character translation.\n",
 
761
        "              6 -> Permit C++ style \"//\" eol comments.\n",
 
762
        "   -d s[=v] Define symbol <s> to have value <v> (default 1).\n",
 
763
        "   -e       Don't abort on error.\n",
 
764
        "   -i       Set path for #include files.\n",
 
765
        "   -l a|l|n Specify #line output mode (abbrev/long/none).\n",
 
766
        "   -o file  Specify output file name.\n",
 
767
#if     DEBUG
 
768
        "   -s       Generate statistics summary at end.\n",
 
769
#endif  /* DEBUG */
 
770
        "   -t str   Add/remove LETTER chars (Accc or Rccc).\n",
 
771
        "   -u s     Undefine an initial symbol.\n",
 
772
        "   -v       Verbose mode toggle.\n",
 
773
#if     DEBUG
 
774
        "   -z       Output debug messages.\n",
 
775
#endif  /* DEBUG */
 
776
        "   -?       Output this message.\n",
 
777
        " Output file, if not specified, is <input>.pp\n");
 
778
 
 
779
        exit(v);
 
780
        }