home *** CD-ROM | disk | FTP | other *** search
- /*=========================================================================
-
- ATOC proprocessor module
-
- =========================================================================*/
-
- #include <stdio.h>
- #include <ctype.h>
- #include "atoc.h"
-
-
- #define STACKSIZE 32
- #define INCLUDE_ENVNAME "INCLUDE"
-
-
- /*-------------------------------------------------------------------------
- local global variables
- -------------------------------------------------------------------------*/
- PRIVATE int ecstack[ STACKSIZE ]; /* stack for endifcount nesting */
- PRIVATE int csi = 0; /* current stack index */
-
-
- /*-------------------------------------------------------------------------
- preprocessor( fo, s ) alters new ANSI preprocessor statements into those
- commonly supported by older compilers. Also notes a few things we don't
- handle yet.
- -------------------------------------------------------------------------*/
- preprocessor( fo, s )
- FILE *fo;
- char *s;
- {
- char *p1, *p2, *p3, *strstr();
-
- /* find first non-white char */
- for ( p1 = s; *p1 && isspace( *p1 ); ++p1 )
- ;
-
- if ( *p1 == '#' )
- {
- /* remove leading white space */
- /* and any white space between # and command */
- for ( ++p1; *p1 && isspace( *p1 ); ++p1 )
- ;
- s[ 0 ] = '#';
- if ( p1 > &s[ 1 ] )
- strcpy( &s[ 1 ], p1 );
-
- /* check for #if, handle nesting of endifcount */
- if ( ( p1 = strstr( s, "#if" ) ) != NULL )
- {
- if ( csi < STACKSIZE )
- {
- ecstack[ csi++ ] = endifcount;
- endifcount = 0;
- }
- else
- {
- error( "#if stack overflow" );
- return;
- }
- }
-
- /* check for #elif, convert to #else #if and add extra #endif */
- if ( ( p1 = strstr( s, "#elif" ) ) != NULL )
- {
- fprintf( fo, "#else\n" );
- strcpy( p1 + 1, p1 + 3 );
- ++endifcount;
- }
-
- /* check for "#if defined" or "#if ! defined" */
- if ( ( p1 = strstr( s, "#if" ) ) != NULL )
- {
- p2 = strstr( p1, "!" );
- if ( ( p3 = strstr( p1, "defined" ) ) != NULL )
- {
- strcpy( p1, p3 + 7 );
- if ( p2 && p2 > p1 && p2 < p3 )
- strins( p1, "#ifndef" );
- else strins( p1, "#ifdef" );
- }
- }
-
- /* output any accumulated #endifs */
- if ( ( p1 = strstr( s, "#endif" ) ) != NULL )
- {
- for ( ; endifcount; --endifcount )
- fprintf( fo, "#endif\n" );
- if ( csi > 0 )
- {
- endifcount = ecstack[ --csi ];
- }
- else
- {
- error( "Too many #endifs" );
- return;
- }
- }
-
- /* handle include files if option selected */
- if ( ( p1 = strstr( s, "#include" ) ) != NULL )
- {
- if ( includeflag )
- include( fo, s );
- /* else just output the include line */
- }
-
- /* check for new # and ## operators that we don't convert */
- if ( ( p1 = strstr( s, "#define" ) ) != NULL )
- {
- if ( strstr( p1 + 7, "##" ) != NULL )
- warning( "'##' Token paste operator not converted" );
- else if ( strstr( p1 + 7, "#" ) != NULL )
- warning( "'#' String literal operator not converted" );
- }
- }
- }
- /*-------------------------------------------------------------------------
- endif_stack_empty() checks to see if the stack is empty, which it should
- be at the time we call.
- -------------------------------------------------------------------------*/
- int endif_stack_empty()
- {
- if ( csi == 0 )
- return( TRUE );
- else return( FALSE );
- }
- /*-------------------------------------------------------------------------
- include( fo, s ) handles an include file line. This is only done if the
- -i option was specified on the command line. -il causes us to only handle
- local includes (those delimited with " ").
- -------------------------------------------------------------------------*/
- PRIVATE include( fo, s )
- FILE *fo;
- char *s;
- {
- FILE *fi;
- char basename[ 80 ], fullname[ 80 ], old_filename[ 80 ];
- char *cp, dc, *path, *getenv(), *strchr();
- int old_linenumber;
-
- /* find include filename and delimiter type */
- if ( ( cp = strchr( s, '\"' ) ) == NULL )
- cp = strchr( s, '<' );
- if ( cp != NULL )
- {
- dc = *cp++;
- /* if local includes only and this is a <>, forget it... */
- if ( localonlyflag && dc == '<' )
- return;
- }
- else
- {
- error( "Can't find include filename delimiter" );
- return;
- }
-
- /* copy include filename to basename, delete trailing end of line */
- strcpy( basename, cp );
- if ( dc == '<' )
- dc = '>';
- if ( ( cp = strchr( basename, dc ) ) != NULL )
- *cp = '\0';
- else
- {
- error( "No trailing delimiter on include filename" );
- return;
- }
-
- /* open include file, either locally... */
- if ( dc == '\"' )
- fi = fopen( basename, "r" );
- else fi = NULL;
- /* or on the INCLUDE path */
- if ( fi == NULL )
- if ( path = getenv( INCLUDE_ENVNAME ) )
- for ( cp = path; path; path = cp )
- {
- if ( ( cp = strchr( cp, ';' ) ) != NULL )
- *cp++ = '\0';
- strcpy( fullname, path );
- strcat( fullname, "\\" );
- strcat( fullname, basename );
- if ( ( fi = fopen( fullname, "r" ) ) != NULL )
- break;
- }
-
- /* set up global variables and recursively call atoc() for include file */
- if ( fi != NULL )
- {
- strcpy( old_filename, filename );
- strcpy( filename, basename );
- old_linenumber = linenumber;
- linenumber = 1;
- fprintf( fo, "/* %s */\n", s );
- atoc( fi, fo );
- fclose( fi );
- s[ 0 ] = '\0';
- strcpy( filename, old_filename );
- linenumber = old_linenumber;
- }
- else error( "Can't open include file" );
- }
- /*=======================================================================*/