1 /******************************************************************************
2 Copyright (c) 1999 Daniel Stenberg
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 SOFTWARE.
21 ******************************************************************************/
22 /******************************************************************************
23 * FREXXWARE
24 * ----------------------------------------------------------------------------
25 *
26 * Project: Frexx C Preprocessor
27 * $Source: /home/user/start/cpp/RCS/usecpp.c,v $
28 * $Revision: 1.6 $
29 * $Date: 1994/06/02 09:11:01 $
30 * $Author: start $
31 * $State: Exp $
32 * $Locker: start $
33 *
34 * ----------------------------------------------------------------------------
35 * $Log: usecpp.c,v $
36 * Revision 1.6 1994/06/02 09:11:01 start
37 * Added the '-n' option!
38 *
39 * Revision 1.5 1994/06/02 08:51:49 start
40 * Added three more command line parameters
41 * Made -h invokes exit nice
42 *
43 * Revision 1.4 1994/01/24 09:37:17 start
44 * Major difference.
45 *
46 * Revision 1.3 1993/12/06 13:51:20 start
47 * A lot of new stuff (too much to mention)
48 *
49 * Revision 1.2 1993/11/11 07:16:39 start
50 * New stuff
51 *
52 * Revision 1.1 1993/11/03 09:13:08 start
53 * Initial revision
54 *
55 *
56 *****************************************************************************/
57 /**********************************************************************
58 *
59 * usecpp.c
60 *
61 * This is a routine that is should be used to call functions in the
62 * fpp.library. We supply the own_input() and own_output() functions to
63 * the preprocessor to remain flexible.
64 */
65
66 #include <stdlib.h>
67
68 #ifdef AMIGA
69 #include <proto/exec.h>
70 #include <exec/types.h>
71
72 #if defined(SHARED)
73 #include <exec/libraries.h>
74 #include <libraries/dos.h>
75
76 #include "fpp_pragmas.h"
77 #include "fpp_protos.h"
78 #include "FPPBase.h"
79 struct Library *FPPBase=NULL;
80 #define PREFIX __saveds
81 #define REG(x) register __ ## x
82 #else
83 #define PREFIX
84 #define REG(x)
85 #endif
86
87 #elif defined(UNIX)
88 #if defined(OS9)
89 #include <types.h>
90 #else
91 #include <sys/types.h>
92 #ifdef BSD
93 #include <sys/unistd.h> /* for BSD systems (SUN OS at least) */
94 #endif
95 #endif
96 #define PREFIX
97 #define REG(x)
98 #endif
99 #include <stdio.h>
100 #include <string.h>
101 #include <stdlib.h>
102 #include <ctype.h>
103 #ifndef OS9
104 #include <stdarg.h>
105 #else
106 #define va_list void *
107 #endif
108
109 #include "fpp.h"
110 #define MAX_TAGS 40 /* maximum number of tags allowed! */
111 #define FILE_LOCAL static
112
113 #define CPP_PREFS_FILE "cpp.prefs"
114 #ifdef AMIGA
115 #define DEFAULT_CPP_PREFS_FILE "s:cpp.prefs"
116 #else
117 #define DEFAULT_CPP_PREFS_FILE "$HOME/cpp.prefs"
118 #endif
119
120 FILE_LOCAL char PREFIX *own_input(char *, int, void *);
121 FILE_LOCAL void PREFIX own_output(int, void *);
122 FILE_LOCAL void PREFIX own_error(void *, char *, va_list);
123 FILE_LOCAL int SetOptions(int, char **, struct fppTag **);
124 FILE_LOCAL char GetPrefs(struct fppTag **, char **);
125 FILE_LOCAL char DoString(struct fppTag **, char *);
126
127 #ifdef AMIGA
128 extern long __stack=8000;
129 #endif
130
131 FILE_LOCAL char ignore=FPP_FALSE; /* if we should ignore strange flags! */
132 FILE_LOCAL char display=FPP_FALSE; /* display all options in use! */
133
134 FILE_LOCAL char dontreadprefs; /* set if only the command line is valid */
135
main(int argc,char ** argv)136 int main(int argc, char **argv)
137 {
138 struct fppTag tags[MAX_TAGS];
139 int i;
140 struct fppTag *tagptr = tags;
141 char *dealloc;
142
143 /*
144 * Append system-specific directories to the include directory list.
145 * The include directories will be searched through in the same order
146 * as you add them in the taglist!
147 * The directory _must_ end with a proper directory speparator!
148 */
149
150 tagptr->tag=FPPTAG_INCLUDE_DIR;
151 #if defined (AMIGA)
152 tagptr->data = "INCLUDE:";
153 #elif defined (OS9)
154 tagptr->data = "/dd/defs/";
155 #else
156 tagptr->data = "/usr/include/";
157 #endif
158 tagptr++;
159
160 if(GetPrefs(&tagptr, &dealloc))
161 return(0);
162
163 if( !(i = SetOptions(argc, argv, &tagptr)))
164 return(0);
165
166 if (argc - i >2) {
167 printf("Too many file arguments. Usage: cpp [options] [input [output]]\n");
168 return(-1);
169 }
170
171 tagptr->tag=FPPTAG_INPUT;
172 tagptr->data=(void *)own_input;
173 tagptr++;
174
175 if(i<argc) {
176 /*
177 * Open input file, "-" means use stdin.
178 */
179 if (strcmp(argv[i], "-")) {
180 if (freopen(argv[i], "r", stdin) == NULL) {
181 perror(argv[i]);
182 fprintf(stderr, "Can't open input file \"%s\"", argv[i]);
183 return(-2);
184 }
185 tagptr->tag=FPPTAG_INPUT_NAME;
186 tagptr->data=argv[i];
187 tagptr++;
188 if(display)
189 fprintf(stderr, "cpp: input: %s\n", argv[i]);
190 } else /* Else, just get stdin */
191 if(display)
192 fprintf(stderr, "cpp: input: [stdin]\n");
193 i++;
194 } else
195 if(display)
196 fprintf(stderr, "cpp: input: [stdin]\n");
197
198 if(i<argc) {
199 /*
200 * Get output file, "-" means use stdout.
201 */
202 if (strcmp(argv[i], "-")) {
203 if (freopen(argv[i], "w", stdout) == NULL) {
204 perror(argv[i]);
205 fprintf(stderr, "Can't open output file \"%s\"", argv[i]);
206 return(-1);
207 }
208 if(display)
209 fprintf(stderr, "cpp: output: %s\n", argv[i]);
210 } else
211 if(display)
212 fprintf(stderr, "cpp: output: [stdout]\n");
213 } else
214 if(display)
215 fprintf(stderr, "cpp: output: [stdout]\n");
216
217 tagptr->tag=FPPTAG_OUTPUT;
218 tagptr->data=(void *)own_output;
219 tagptr++;
220
221 tagptr->tag=FPPTAG_ERROR;
222 tagptr->data=(void *)own_error;
223 tagptr++;
224
225 /* The LAST tag: */
226
227 tagptr->tag=FPPTAG_END;
228 tagptr->data=0;
229 tagptr++;
230
231 #if defined(SHARED) && defined(AMIGA)
232 if(!(FPPBase=OpenLibrary(FPPNAME, 1))) {
233 printf("Error opening %s!\n", FPPNAME);
234 return(-1);
235 }
236 #endif
237 fppPreProcess(tags);
238
239 #if defined(SHARED) && defined(AMIGA)
240 CloseLibrary((struct Library *)FPPBase);
241 #endif
242 /*
243 * Preprocess ready!
244 */
245
246 if( dealloc )
247 free( dealloc );
248
249 return(0);
250 }
251
252
253 FILE_LOCAL
own_input(char * buffer,int size,void * userdata)254 char PREFIX *own_input(char *buffer, int size, void *userdata)
255 {
256 return(fgets(buffer, size, stdin));
257 }
258
259 FILE_LOCAL
own_output(int c,void * userdata)260 void PREFIX own_output(int c, void *userdata)
261 {
262 putchar(c);
263 }
264
265 FILE_LOCAL
own_error(void * userdata,char * format,va_list arg)266 void PREFIX own_error(void *userdata, char *format, va_list arg)
267 {
268 vfprintf(stderr, format, arg);
269 }
270
271 FILE_LOCAL
GetPrefs(struct fppTag ** tagptr,char ** string)272 char GetPrefs(struct fppTag **tagptr, char **string)
273 {
274
275 FILE *PrefsFile_PF;
276 unsigned Length_U;
277 char *PrefsBuffer_PC;
278 char ret= 0;
279 char *env;
280
281 *string = NULL;
282
283 /* Open prefs file for read */
284 if ( (PrefsFile_PF = fopen(CPP_PREFS_FILE, "r")) ||
285 (PrefsFile_PF = fopen(DEFAULT_CPP_PREFS_FILE, "r"))) {
286
287 fseek(PrefsFile_PF, 0 , SEEK_END);
288 Length_U = ftell(PrefsFile_PF);
289 fseek(PrefsFile_PF, 0, SEEK_SET);
290
291 if (*string = (char *)malloc(Length_U+1)) {
292 fread(*string, 1, Length_U, PrefsFile_PF);
293 (*string)[Length_U] = '\0';
294
295 ret = !DoString(tagptr, *string);
296 }
297 fclose(PrefsFile_PF);
298 if(ret) {
299 free( *string );
300 return ret;
301 }
302 }
303
304 if((env = getenv("CPP_PREFS"))) {
305 ret= !DoString(tagptr, env);
306 if(ret && *string)
307 free( *string );
308 }
309 return ret;
310 }
311
312 FILE_LOCAL
DoString(struct fppTag ** tagptr,char * string)313 char DoString(struct fppTag **tagptr, char *string)
314 {
315 char *argv[MAX_TAGS];
316 int argc=1;
317 do {
318 while(*string && *string != '-')
319 string++;
320
321 if(!*string)
322 break;
323
324 argv[argc]=string;
325
326 do {
327 string++;
328 if(*string=='\"') {
329 do
330 string++;
331 while(*string != '\"');
332 string++;
333 }
334 } while(*string && *string!=' ' && *string != '\n' && *string != '\t');
335 argc++;
336 if(*string) {
337 *string='\0';
338 string++;
339 } else
340 break;
341 } while(1);
342
343 return (SetOptions(argc, argv, tagptr));
344 }
345
346 FILE_LOCAL
SetOptions(int argc,char ** argv,struct fppTag ** tagptr)347 int SetOptions(int argc, char **argv, struct fppTag **tagptr)
348 {
349 int i;
350 char *ap;
351 for (i = 1; i < argc; i++) {
352 ap = argv[i];
353 if (*ap++ != '-' || *ap == '\0')
354 break;
355 else {
356 char c = *ap++;
357
358 if(display)
359 fprintf(stderr, "cpp: option: %s\n", ap-2);
360
361 switch (c) { /* Command character */
362 case 'Q': /* ignore unknown flags but */
363 ignore=1; /* output them on stderr */
364 break;
365
366 case 'q': /* ignore unknown flags */
367 ignore=2;
368 break;
369
370 case 'H': /* display all whitespaces */
371 (*tagptr)->tag = FPPTAG_OUTPUTSPACE;
372 (*tagptr)->data= (void *)FPP_TRUE;
373 (*tagptr)++;
374 break;
375
376 case 'b': /* display unbalance */
377 (*tagptr)->tag = FPPTAG_OUTPUTBALANCE;
378 (*tagptr)->data= (void *)FPP_TRUE;
379 (*tagptr)++;
380 break;
381
382 case 'f': /* output all defined functions! */
383 (*tagptr)->tag = FPPTAG_DISPLAYFUNCTIONS;
384 (*tagptr)->data= (void *)FPP_TRUE;
385 (*tagptr)++;
386 break;
387
388 case 'F': /* output all included files! */
389 (*tagptr)->tag = FPPTAG_OUTPUTINCLUDES;
390 (*tagptr)->data= (void *)FPP_TRUE;
391 (*tagptr)++;
392 break;
393
394 case 'V': /* do not output version */
395 (*tagptr)->tag = FPPTAG_SHOWVERSION;
396 (*tagptr)->data= (void *)FPP_FALSE;
397 (*tagptr)++;
398 break;
399
400 case 'C': /* Keep comments */
401 (*tagptr)->tag = FPPTAG_KEEPCOMMENTS;
402 (*tagptr)->data= (void *)FPP_TRUE;
403 (*tagptr)++;
404 break;
405
406 case 'D': /* Define symbol */
407 (*tagptr)->tag=FPPTAG_DEFINE;
408 (*tagptr)->data=argv[i]+2;
409 (*tagptr)++;
410 break;
411
412 case 'd': /* Display all options */
413 fprintf(stderr, "FOUND -d flag!\n");
414 display = FPP_TRUE;
415 break;
416
417 case 'E': /* Ignore non-fatal errors */
418 (*tagptr)->tag=FPPTAG_IGNORE_NONFATAL;
419 (*tagptr)->data=(void *)FPP_TRUE;
420 (*tagptr)++;
421 break;
422
423 case 'I': /* Include directory */
424 (*tagptr)->tag=FPPTAG_INCLUDE_DIR;
425 (*tagptr)->data=ap;
426 (*tagptr)++;
427 break;
428
429 case 'J': /* Allow nested comments */
430 (*tagptr)->tag=FPPTAG_NESTED_COMMENTS;
431 (*tagptr)->data=ap;
432 (*tagptr)++;
433 break;
434
435 case 'j': /* Warn at nested comments */
436 (*tagptr)->tag=FPPTAG_WARN_NESTED_COMMENTS;
437 (*tagptr)->data=ap;
438 (*tagptr)++;
439 break;
440
441 case 'L':
442 if(*ap == 'L') { /* Do not output #line */
443 (*tagptr)->tag=FPPTAG_LINE;
444 } else {
445 /* Do not output the 'line' keyword */
446 (*tagptr)->tag=FPPTAG_OUTPUTLINE;
447 }
448 (*tagptr)->data=(void *)FPP_FALSE;
449 (*tagptr)++;
450 break;
451
452 case 'M': /* Do not warn at missing includes */
453 (*tagptr)->tag=FPPTAG_WARNMISSINCLUDE;
454 (*tagptr)->data=(void *)FPP_FALSE;
455 (*tagptr)++;
456 break;
457
458 case 'n':
459 dontreadprefs^=1; /* toggle prefsreading, default is read prefs */
460
461 /*
462 * This flag should reset all previously added tags!
463 */
464
465 break;
466
467 case 'N': /* No machine specific built-ins */
468 (*tagptr)->tag=FPPTAG_BUILTINS;
469 (*tagptr)->data=(void *)FPP_FALSE;
470 (*tagptr)++;
471 break;
472
473 case 'B': /* No predefines like __LINE__, etc. */
474 (*tagptr)->tag=FPPTAG_PREDEFINES;
475 (*tagptr)->data=(void *)FPP_FALSE;
476 (*tagptr)++;
477 break;
478
479 case 'P': /* No C++ comments */
480 (*tagptr)->tag=FPPTAG_IGNORE_CPLUSPLUS;
481 (*tagptr)->data=(void *)FPP_TRUE;
482 (*tagptr)++;
483 break;
484
485 case 'p': /* warn about illegal # - instructions */
486 (*tagptr)->tag = FPPTAG_WARNILLEGALCPP;
487 (*tagptr)->data= (void *)FPP_TRUE;
488 (*tagptr)++;
489 break;
490
491 case 'R':
492 (*tagptr)->tag = FPPTAG_RIGHTCONCAT;
493 (*tagptr)->data= (void *)FPP_TRUE;
494 (*tagptr)++;
495 break;
496
497 case 's': /* sizeof table */
498 (*tagptr)->tag=FPPTAG_INITFUNC;
499 (*tagptr)->data=ap;
500 (*tagptr)++;
501 break;
502
503 case 't': /* excluded functions */
504 (*tagptr)->tag=FPPTAG_EXCLFUNC;
505 (*tagptr)->data=ap;
506 (*tagptr)++;
507 break;
508
509 case 'S': /* sizeof table */
510 (*tagptr)->tag=FPPTAG_SIZEOF_TABLE;
511 (*tagptr)->data=ap;
512 (*tagptr)++;
513 break;
514
515 case 'U': /* Undefine symbol */
516 (*tagptr)->tag=FPPTAG_UNDEFINE;
517 (*tagptr)->data=ap;
518 (*tagptr)++;
519 break;
520
521 case 'w': /* Output all #defines but not the
522 main file */
523 (*tagptr)->tag=FPPTAG_OUTPUTMAIN;
524 (*tagptr)->data=(void *)FPP_FALSE;
525 (*tagptr)++;
526
527 case 'W': /* Output all #defines */
528 if(!strncmp(ap, "WW", 2)) {
529 (*tagptr)->tag=FPPTAG_WEBMODE;
530 (*tagptr)->data=(void *)FPP_TRUE;
531 (*tagptr)++;
532 }
533 else {
534 (*tagptr)->tag=FPPTAG_OUTPUT_DEFINES;
535 (*tagptr)->data=(void *)FPP_TRUE;
536 (*tagptr)++;
537 }
538 break;
539
540 case 'X':
541 (*tagptr)->tag=FPPTAG_INCLUDE_FILE;
542 (*tagptr)->data=ap;
543 (*tagptr)++;
544 break;
545
546 /*
547 case 'x':
548 tags[tag]->tag=FPPTAG_INCLUDE_MACRO_FILE;
549 tags[tag++]->data=ap;
550 break;
551 */
552 case 'h':
553 case '?': /* if a question mark is possible to specify! */
554 default: /* What is this one? */
555 if( ignore < 2 && c != 'h') {
556 fprintf(stderr, "cpp: unknown option: -%s\n", ap-1);
557 }
558 if(!ignore || c == 'h') {
559 fprintf(stderr,
560 "Usage: cpp [options] [infile [outfile] ]\n\n"
561 "The following options are valid:\n"
562 " -B\tNo machine specific built-in symbols\n"
563 " -b\tOutput any parentheses, brace or bracket unbalance\n"
564 " -C\tWrite source file comments to output\n"
565 " -D\tDefine a symbol with the given (optional) value \"symbol[=value]\"\n"
566 " -d\tDisplay all specified options\n"
567 " -E\tIgnore non-fatal errors\n"
568 " -F\tOutput all included file names on stderr\n"
569 " -f\tOutput all defined functions' names on stderr\n"
570 " -H\tOutput all whitespaces from the source file\n"
571 " -h\tOutput this help text\n"
572 " -I\tAdd directory to the #include search list\n"
573 " -J\tAllow nested comments\n"
574 " -j\tEnable warnings for nested comments\n"
575 " -LL\tDon't output #line instructions\n"
576 " -L\tDon't output the 'line' keyword in \"#line\" instructions\n"
577 " -M\tDon't warn for missing include files\n"
578 " -N\tDon't predefine target-specific names\n"
579 " -n\tToggle prefs usage\n"
580 " -P\tDon't recognize C++ comment style\n"
581 " -p\tEnable warnings on non ANSI preprocessor instructions\n"
582 " -Q\tIgnore but visualize undefined flags\n"
583 " -q\tIgnore all undefined flags\n"
584 " -R\tEvaluate the right part first in symbol concatenations\n"
585 " -s\tInclude the following string at the top of each function\n"
586 " -S\tSpecify sizes for #if sizeof\n"
587 " -t\tThis function should not get an initial function\n"
588 " -U\tUndefine symbol\n"
589 " -V\tDon't output version information\n"
590 " -W\tOutput all #defines\n"
591 " -WWW\tWeb mode preprocessing\n"
592 " -w\tOnly output #defines\n"
593 " -X\tInclude file\n");
594 return(0);
595 } /* if (!ignore) */
596 } /* Switch on all options */
597 } /* If it's a -option */
598 } /* For all arguments */
599
600 return i;
601
602 } /* end of function */
603