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