⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 its about compiler for LL1 and LR
💻 C
📖 第 1 页 / 共 2 页
字号:
/*@A (C) 1992 Allen I. Holub                                                */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdarg.h>
#include <signal.h>
#include <malloc.h>
#include <errno.h>
#include <time.h>
#include <sys/types.h>
#include <sys/timeb.h>
#include <process.h>
#include <tools/debug.h>
#include <tools/set.h>
#include <tools/hash.h>
#include <tools/compiler.h>
#include <tools/l.h>

#ifdef LLAMA
#	define  ALLOCATE
#	include "parser.h"
#	undef   ALLOCATE
#else
#	define  ALLOCATE
#	include "parser.h"
#	undef   ALLOCATE
#endif

#if (0 MSC(+1) )
    #pragma comment(exestr, "(C)" __DATE__ "Allen Holub. All rights reserved.")
#endif

PRIVATE   int   Warn_exit     = 0;	/* Set to 1 if -W on command line  */
PRIVATE   int	Num_warnings  = 0;	/* Total warnings printed	   */
PRIVATE	  char  *Output_fname = "????"; /* Name of the output file	   */
PRIVATE   FILE *Doc_file      = NULL;   /* Error log & machine description */

#ifdef MAP_MALLOC
  PRIVATE int	Malloc_chk     = 1;	/* Run-time malloc() checking      */
  PRIVATE int	Malloc_verbose = 0;	/*     " use verbose diagnostics   */
#endif

#define VERBOSE(str)  if(Verbose){  printf( "%s:\n", (str));  }else
/*----------------------------------------------------------------------*/
void onintr	  P(( void 			));		/* local */
void parse_args	  P(( int argc,  char **argv	));
int  do_file	  P(( void			));
void symbols	  P(( void			));
void statistics	  P(( FILE *fp			));
void tail	  P(( void			));

void output	  P(( char *fmt, ...		));		/* public */
void lerror	  P(( int fatal, char *fmt, ...	));
void error	  P(( int fatal, char *fmt, ...	));
char *open_errmsg P(( void 			));
char *do_dollar	  P(( int num, int rhs_size, int lineno, PRODUCTION *prod, \
								char *fname));
/*----------------------------------------------------------------------
 * There are two versions of the following subroutines--used in do_file(),
 * depending on whether this is llama or occs.

 *
 * subroutine:		llama version in:	occs version in:
 *
 * file_header()	lldriver.c		yydriver.c
 * code_header()	lldriver.c		yydriver.c
 * driver()		lldriver.c		yydriver.c
 * tables()		llcode.c		yycode.c
 * patch()		-----			yypatch.c
 * select()		llselect.c		------
 * do_dollar()		lldollar.c		yydollar.c
 *
 * Also, several part of this file are compiled only for llama, others only for
 * occs. The llama-specific parts are arguments to LL() macros, the occs-
 * specific parts are in OX() macros. We'll look at what the occs-specific
 * parts actually do in the next Chapter.
 *----------------------------------------------------------------------
 */
PUBLIC	void main( argc, argv )
char	**argv;
{
    MSC( _amblksiz = 2048; )	/* Declared in Microsoft C's malloc.h.        */
    				/* Controls size of malloc() allocation unit. */
    signon();			/* Print sign on message		   */
    signal( SIGINT, 		/* Close output files on Ctrl-Break.	   */
	MSC((void(*)(int))) onintr );
    parse_args( argc, argv );

# ifdef MAP_MALLOC
       malloc_checking( Malloc_chk, Malloc_verbose );
# endif

    if( Debug && !Symbols )
	Symbols = 1;

    OX( if( Make_parser )						)
    OX( {								)
    OX(     if( Verbose == 1 )						)
    OX(     {								)
    OX(	        if( !(Doc_file = fopen( DOC_FILE, "w") ) )		)
    OX(	            ferr( "Can't open log file %s\n", DOC_FILE );	)
    OX(     }								)
    OX(     else if( Verbose > 1 )					)
    OX(		Doc_file = stderr;					)
    OX( }								)

    if( Use_stdout )
    {
	Output_fname = "/dev/tty" ;
	Output       = stdout;
    }
    else
    {
	OX( Output_fname = !Make_parser ? ACT_FILE : PARSE_FILE ; )
	LL( Output_fname = PARSE_FILE; 				  )

	if( (Output = fopen( Output_fname, "w")) == NULL )
	    error( FATAL, "Can't open output file %s: %s\n",
						Output_fname, open_errmsg() );
    }

    if( (yynerrs = do_file()) == 0)	/* Do all the work  */
    {
	if( Symbols )
	    symbols();			/* Print the symbol table	  */

	statistics( stdout );		/* And any closing-up statistics. */

	if( Verbose && Doc_file )
	{
	    OX(  statistics( Doc_file );   )

#ifdef MAP_MALLOC
  	    printf("\n%lu bytes (%luK) memory used by malloc\n",
  				    memory_used(), memory_used()/1024L );
#endif
	}
    }
    else
    {
	if( Output != stdout )
	{
	    fclose( Output );
	    if( unlink( Output_fname ) == -1 )
		perror( Output_fname );
	}
    }

    /* Exit with  the number of hard errors (or, if -W was specified, the sum
     * of the hard errors and warnings) as an exit status. Doc_file and Output
     * are closed implicitly by exit().
     */

    exit( yynerrs + (Warn_exit ? Num_warnings : 0) );
}
/*----------------------------------------------------------------------*/
PRIVATE void onintr()			/* SIGABRT (Ctrl-Break, ^C) Handler */
{
    if( Output != stdout )		/* Destroy parse file so that a */
    {					/* subsequent compile will fail */
	fclose( Output );
	unlink( Output_fname );
    }

    exit( EXIT_USR_ABRT );
}
/*----------------------------------------------------------------------*/
PRIVATE	void parse_args( argc, argv )
int	argc;
char	**argv;
{
    /* Parse the command line, setting global variables as appropriate */

    char	*p;
    static char name_buf[80];	       /* Use to assemble default file names */

    static char	*usage_msg[] =
    {
#ifdef LLAMA
        "Usage is: llama [-switch] file",
        "Create an LL(1) parser from the specification in the",
	"input file. Legal command-line switches are:",
	"",
        "-cN      use N as the pairs threshold when (C)ompressing",
	"-D       enable (D)ebug mode in yyparse.c (implies -s)",
        "-f       (F)ast, uncompressed, tables",
#else
        "Usage is:  occs [-switch] file",
	"",
        "\tCreate an LALR(1) parser from the specification in the",
	"\tinput file. Legal command-line switches are:",
	"",
        "-a       Output actions only (see -p)",
	"-D       enable (D)ebug mode in yyparse.c (implies -s)",
#endif
	"-g       make static symbols (G)lobal in yyparse.c",
	"-l       suppress #(L)ine directives",
	"-m<file> use <file> for parser te(M)plate",
	"-p       output parser only (can be used with -T also)",
	"-s       make (s)ymbol table",
	"-S       make more-complete (S)ymbol table",
	"-t       print all (T)ables (and the parser) to standard output",
	"-T	  move large tables from yyout.c to yyoutab.c",
	"-v       print (V)erbose diagnostics (including symbol table)",
	"-V       more verbose than -v. Implies -t, & yyout.doc goes to stderr",
	"-w       suppress all warning messages",
	"-W       warnings (as well as errors) generate nonzero exit status",
#ifdef MAP_MALLOC
  	"-M       Disable malloc checking at run time\n",
#endif
	NULL
    };

    /* Note that all global variables set by command-line switches are declared
     * in parser.h. Space is allocated because a #define ALLOC is present at
     * the top of the current file.
     */

    for( ++argv,--argc; argc && *(p = *argv) == '-'; ++argv, --argc )
    {
	while( *++p )
	{
	    switch( *p )
	    {
	OX(  case 'a':  Make_parser  = 0;		)
	OX(	        Template     = ACT_TEMPL;	)
	OX(	        break;				)

	    case 'D':  Debug 	    = 1;	break;
	    case 'g':  Public	    = 1;	break;
	LL( case 'f':  Uncompressed = 1; 	break;		)
	    case 'l':  No_lines	    = 1;	break;
	    case 'm':  Template     = p + 1;	goto out;

#ifdef MAP_MALLOC
  	    case 'M':  Malloc_chk   = 0;	break;
#endif

	OX( case 'p':  Make_actions = 0;	break;		)
	    case 's':  Symbols      = 1;	break;
	    case 'S':  Symbols      = 2;	break;
	    case 't':  Use_stdout   = 1; 	break;
	    case 'T':  Make_yyoutab = 1; 	break;
	    case 'v':  Verbose	    = 1;	break;
	    case 'V':  Verbose	    = 2;	break;
	    case 'w':  No_warnings  = 1;	break;
	    case 'W':  Warn_exit    = 1;	break;
	LL( case 'c':  Threshold = atoi( ++p );			)
	LL(	       while( *p && isdigit( p[1] ) )		)
	LL(		    ++p;				)
	LL(	       break;					)
	    default :
		       fprintf(stderr, "<-%c>: illegal argument\n", *p);
		       printv (stderr, usage_msg );
		       exit( EXIT_ILLEGAL_ARG );
	    }
	}
out: ;

    }

    if( Verbose > 1 )
	Use_stdout = 1;

    if( argc <= 0 )			/* Input from standard input	*/
	No_lines = 1;

    else if( argc > 1 )
    {
	fprintf( stderr, "Too many arguments.\n" );
	printv ( stderr, usage_msg );
	exit   ( EXIT_TOO_MANY );
    }
    else 				/* argc == 1, input from file   */
    {
	if( ii_newfile( Input_file_name = *argv ) < 0 )
	{
	    sprintf( name_buf, "%0.70s.%s", *argv, DEF_EXT );

	    if( ii_newfile( Input_file_name = name_buf ) < 0 )
		error( FATAL, "Can't open input file %s or %s: %s\n",
						*argv, name_buf, open_errmsg());
	}
    }
}
/*----------------------------------------------------------------------*/
PRIVATE	int	do_file()
{

    /* Process the input file. Return the number of errors.  */

    struct timeb start_time, end_time ;
    long	 time;
    void 	 nows P((void));	/* declared in parser.lex */

    ftime( &start_time );    /* Initialize times now so that the difference   */
    end_time = start_time;   /* between times will be 0 if we don't build the */
			     /* tables. Note that I'm using structure assign- */
			     /* ment here.			              */
    init_acts  ();	     /* Initialize the action code.		      */
    file_header();  	     /* Output #defines that you might want to change */

    VERBOSE( "parsing" );

    nows      ();         /* Make lex ignore white space until ws() is called */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -