Files correlati : Commento : Aggiunto il preprocessore c++ mcpp per sostituire il compilatore nella compilazione delle maschere.
		
			
				
	
	
		
			292 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			292 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * ins_once.c
 | |
|  *  Quick and dirty program to insert '#pragma once' into the header files.
 | |
|  *  1998/08     kmatsui
 | |
|  *  2002/08     kmatsui
 | |
|  *      Added -p, -o, -g option, removed -s option.
 | |
|  *      Compile with -DPATH_DELIM='x' option, if the path-delimiter is any
 | |
|  *          other than '/'.
 | |
|  *  2004/11     kmatsui
 | |
|  *      Changed '#pragma __once' to '#pragma once'.
 | |
|  *  2006/07     kmatsui
 | |
|  *      Removed -o option.
 | |
|  *      Changed non-prototype declarations to prototype ones.
 | |
|  */
 | |
| 
 | |
| #include    "stdio.h"
 | |
| #include    "stdlib.h"
 | |
| #include    "string.h"
 | |
| #include    "ctype.h"
 | |
| #include    "errno.h"
 | |
| 
 | |
| #ifndef PATH_DELIM
 | |
| #define PATH_DELIM  '/'
 | |
| #endif
 | |
| 
 | |
| #define TRUE    1
 | |
| #define FALSE   0
 | |
| 
 | |
| #define IFNDEF      0x100
 | |
| #define IF          0x101
 | |
| #define PRAGMA      0x102
 | |
| #define DEFINED     0x103
 | |
| #define _ONCE       0x111
 | |
| 
 | |
| void    usage( void);
 | |
| void    test_a_file( char *);
 | |
| void    conv_a_file( char *);
 | |
| void    insert_once( FILE *, FILE *, char *);
 | |
| void    prepend_once( FILE *, FILE *);
 | |
| int     look_directive( FILE *);
 | |
| int     get_token( char **);
 | |
| void    ins_once( FILE *);
 | |
| 
 | |
| int     test;
 | |
|     /* Only test files whether beginning with #ifndef or #if !defined.  */
 | |
| int     prepend;
 | |
| /*
 | |
|  * If TRUE, prepend '#pragma once' line to the file.
 | |
|  * If FALSE, insert the line after the first #ifndef line.
 | |
|  */
 | |
| int     gcc;
 | |
| /*
 | |
|  * If TRUE, do not insert '#pragma once' line to "stddef.h".
 | |
|  * This is the option for GCC family.
 | |
|  */
 | |
| 
 | |
| int main( int argc, char **argv) {
 | |
|     extern int      getopt( int, char **, char *);
 | |
|     extern int      optind;
 | |
|     extern char     *optarg;
 | |
|     int     opt;
 | |
|     char    *except[] = { "assert.h", "cassert", "cassert.h", NULL};
 | |
|     char    *g_except[] = { "stddef.h", "stdio.h", "signal.h", "errno.h"
 | |
|                     , NULL};
 | |
|     char    *arg;
 | |
|     char    **ep;
 | |
| 
 | |
|     if (argc < 2)
 | |
|         usage();
 | |
|     while (optind < argc
 | |
|             && (opt = getopt( argc, argv, "gopt")) != EOF) {
 | |
|         switch (opt) {
 | |
|         case 't':
 | |
|             test = TRUE;
 | |
|             break;
 | |
|         case 'p':
 | |
|             prepend = TRUE;
 | |
|             break;
 | |
|         case 'g':
 | |
|             gcc = TRUE;
 | |
|             break;
 | |
|         default:
 | |
|             usage();
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
|     argv += (optind - 1);
 | |
|     while (*++argv) {
 | |
|         if ((arg = strrchr( *argv, PATH_DELIM)) != NULL)
 | |
|             arg++;
 | |
|         else
 | |
|             arg = *argv;
 | |
|         for (ep = except; *ep; ep++) {
 | |
|             if (strcmp( arg, *ep) == 0)
 | |
|                 goto skip;
 | |
|         }
 | |
|         if (gcc) {
 | |
|             for (ep = g_except; *ep; ep++) {
 | |
|                 if (strcmp( arg, *ep) == 0)
 | |
|                     goto skip;
 | |
|             }
 | |
|         }
 | |
|         if (test)
 | |
|             test_a_file( *argv);
 | |
|         else
 | |
|             conv_a_file( *argv);
 | |
|         continue;
 | |
| skip:   fprintf( stderr, "Skipped %s\n", *ep);
 | |
|     }
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| void    usage( void)
 | |
| {
 | |
|     static char     *mes[] = {
 | |
|    "ins_once: Insert '#pragma once' to header files except \"assert.h\"\n",
 | |
|    "            and \"stddef.h\" and some others (for GCC).\n",
 | |
|    "Usage: ins_once [-DPATH_DELIM=\\] [-t|-p|-g] [header1.h [header2.h [...]]]\n",
 | |
|    "    -t : Only test files whether beginning with #ifndef or #if !defined.\n",
 | |
|    "    -p : Prepend the line to the file\n",
 | |
|    "        (default: insert after the first #ifndef line -- for GCC).\n",
 | |
|    "    -g : Do not convert stddef.h, stdio.h, signal.h, errno.h.\n",
 | |
|         NULL,
 | |
|     };
 | |
|     char    **mesp = mes;
 | |
| 
 | |
|     while( *mesp)
 | |
|         fputs( *mesp++, stderr);
 | |
|     if (errno) {
 | |
|         fputs( strerror( errno), stderr);
 | |
|         fputc( '\n', stderr);
 | |
|     }
 | |
|     exit( errno);
 | |
| }
 | |
| 
 | |
| void    test_a_file( char *fname) {
 | |
| /*
 | |
|  * Only test the file whether it begins with #ifndef or #if !defined.
 | |
|  */
 | |
|     char    buf[ BUFSIZ];
 | |
|     FILE    *fp_in;
 | |
|     int     token;
 | |
|     char    *cp;
 | |
| 
 | |
|     fp_in = fopen( fname, "r");
 | |
|     if (fp_in == NULL)
 | |
|         usage();
 | |
| 
 | |
|     while (fgets( buf, BUFSIZ, fp_in) != NULL) {
 | |
|         cp = buf;
 | |
|         if (get_token( &cp) == '#') {       /* The first directive  */
 | |
|             if (((token = get_token( &cp)) != IFNDEF)   /* #ifndef  */
 | |
|                     && (token != IF || get_token( &cp) != '!'
 | |
|                         || get_token( &cp) != DEFINED)) {   /* #if ! defined*/
 | |
|                 fputs( fname, stderr);
 | |
|                 fputs( ": doesn't begin with #ifndef nor #if !defined\n",
 | |
|                         stderr);
 | |
|             }
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
|     fclose( fp_in);
 | |
| }
 | |
| 
 | |
| void    conv_a_file( char *fname) {
 | |
| /*
 | |
|  * Insert '#pragma once' line to seemingly apropriate place according
 | |
|  * the command-line options.
 | |
|  */
 | |
|     char    *tmp = "tmp_once";
 | |
|     FILE    *fp_in, *fp_out;
 | |
| 
 | |
|     if ((fp_in = fopen( fname, "r")) == NULL)
 | |
|         usage();
 | |
|     if ((fp_out = fopen( tmp, "w")) == NULL)
 | |
|         usage();
 | |
|     fprintf( stderr, "Converting %s\n", fname);
 | |
| 
 | |
|     if (prepend)
 | |
|         prepend_once( fp_in, fp_out);
 | |
|     else
 | |
|         insert_once( fp_in, fp_out, fname);
 | |
| 
 | |
|     fclose( fp_in);
 | |
|     fclose( fp_out);
 | |
|     if (remove( fname) != 0 || rename( tmp, fname) != 0)
 | |
|         usage();
 | |
| }
 | |
| 
 | |
| void    insert_once( FILE *fp_in, FILE *fp_out, char *fname) {
 | |
| /*
 | |
|  * Insert '#pragma once' line after the first directive line, if the
 | |
|  * directive is #ifndef or #if !defined, else append the line at the end
 | |
|  * of the file.
 | |
|  */
 | |
|     char    buf[ BUFSIZ];
 | |
|     int     token;
 | |
|     int     no_ifndef = TRUE;
 | |
|     char    *cp;
 | |
| 
 | |
|     while (fgets( buf, BUFSIZ, fp_in) != NULL) {
 | |
|         fputs( buf, fp_out);
 | |
|         cp = buf;
 | |
|         if (get_token( &cp) == '#') {       /* The first directive  */
 | |
|             if (((token = get_token( &cp)) == IFNDEF)   /* #ifndef  */
 | |
|                     || (token == IF && get_token( &cp) == '!'
 | |
|                         && get_token( &cp) == DEFINED)) {   /* #if ! defined*/
 | |
|                 no_ifndef = FALSE;
 | |
|                 if (! look_directive( fp_in))
 | |
|                     ins_once( fp_out);
 | |
|                 /* Else already written in   */
 | |
|             } else {                            /* Other directive  */
 | |
|                 fputs( fname, stderr);
 | |
|                 fputs( ": doesn't begin with #ifndef nor #if !defined\n",
 | |
|                         stderr);
 | |
|             }
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
|     while (fgets( buf, BUFSIZ, fp_in) != NULL)
 | |
|         fputs( buf, fp_out);
 | |
|     if (no_ifndef)
 | |
|         ins_once( fp_out);          /* Append the line to the file  */
 | |
| }
 | |
| 
 | |
| void    prepend_once( FILE *fp_in, FILE *fp_out) {
 | |
| /*
 | |
|  * Prepend the '#pragma once' line at the top of the file.
 | |
|  */
 | |
|     char    buf[ BUFSIZ];
 | |
| 
 | |
|     if (! look_directive( fp_in))
 | |
|         ins_once( fp_out);          /* Prepend the line to the file */
 | |
| 
 | |
|     while (fgets( buf, BUFSIZ, fp_in) != NULL)
 | |
|         fputs( buf, fp_out);
 | |
| }
 | |
| 
 | |
| int     look_directive( FILE *fp) {
 | |
| /*
 | |
|  * Look whether the next line is '#pragma once'.
 | |
|  */
 | |
|     char    buf[ BUFSIZ];
 | |
|     long    pos;
 | |
|     int     res = 0;
 | |
|     int     token;
 | |
|     char    *cp;
 | |
| 
 | |
|     pos = ftell( fp);
 | |
|     cp = buf;
 | |
|     if (fgets( buf, BUFSIZ, fp) && buf[ 0] == '\n'
 | |
|             && fgets( buf, BUFSIZ, fp) && get_token( &cp) == '#'
 | |
|             && get_token( &cp) == PRAGMA && get_token( &cp) == _ONCE)
 | |
|         res = 1;
 | |
|     fseek( fp, pos, SEEK_SET);
 | |
|     return res;
 | |
| }
 | |
| 
 | |
| int     get_token( char **cpp) {
 | |
| /* Get the next 'token', without parsing comments, literals, etc.   */
 | |
|     int     token;
 | |
|     char    *cp = *cpp;
 | |
| 
 | |
|     while (*cp != '\n' && isspace( *cp))
 | |
|         cp++;
 | |
|     if (memcmp( cp, "ifndef", 6) == 0) {
 | |
|         token = IFNDEF;
 | |
|         cp += 6;
 | |
|     } else if (memcmp( cp, "if", 2) == 0) {
 | |
|         token = IF;
 | |
|         cp += 2;
 | |
|     } else if (memcmp( cp, "pragma", 6) == 0) {
 | |
|         token = PRAGMA;
 | |
|         cp += 6;
 | |
|     } else if (memcmp( cp, "defined", 7) == 0) {
 | |
|         token = DEFINED;
 | |
|         cp += 7;
 | |
|     } else if (memcmp( cp, "once", 6) == 0) {
 | |
|         token = _ONCE;
 | |
|         cp += 6;
 | |
|     } else {
 | |
|         token = *cp++;
 | |
|     }
 | |
|     *cpp = cp;
 | |
|     return token;
 | |
| }
 | |
| 
 | |
| void    ins_once( FILE *fp) {
 | |
|     fputs( "\n#pragma once\n\n", fp);
 | |
| }
 | |
| 
 |