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

📄 compile.c

📁 Boost provides free peer-reviewed portable C++ source libraries. We emphasize libraries that work
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright 1993, 2000 Christopher Seiwald. * * This file is part of Jam - see jam.c for Copyright information. *//*  This file is ALSO: *  Copyright 2001-2004 David Abrahams. *  Distributed under the Boost Software License, Version 1.0. *  (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) */# include "jam.h"# include "lists.h"# include "parse.h"# include "compile.h"# include "variable.h"# include "expand.h"# include "rules.h"# include "newstr.h"# include "make.h"# include "search.h"# include "hdrmacro.h"# include "hash.h"# include "modules.h"# include "strings.h"# include "builtins.h"# include "class.h"# include <assert.h># include <string.h># include <stdarg.h>/* * compile.c - compile parsed jam statements * * External routines: * *  compile_append() - append list results of two statements *	compile_eval() - evaluate if to determine which leg to compile *  compile_foreach() - compile the "for x in y" statement *  compile_if() - compile 'if' rule *  compile_while() - compile 'while' rule *  compile_include() - support for 'include' - call include() on file *  compile_list() - expand and return a list  *  compile_local() - declare (and set) local variables *  compile_null() - do nothing -- a stub for parsing *  compile_on() - run rule under influence of on-target variables *  compile_rule() - compile a single user defined rule *  compile_rules() - compile a chain of rules *  compile_set() - compile the "set variable" statement *  compile_setcomp() - support for `rule` - save parse tree  *  compile_setexec() - support for `actions` - save execution string  *  compile_settings() - compile the "on =" (set variable on exec) statement *  compile_switch() - compile 'switch' rule * * Internal routines: * *  debug_compile() - printf with indent to show rule expansion. *  evaluate_rule() - execute a rule invocation * *  builtin_depends() - DEPENDS/INCLUDES rule *  builtin_echo() - ECHO rule *  builtin_exit() - EXIT rule *  builtin_flags() - NOCARE, NOTFILE, TEMPORARY rule * * 02/03/94 (seiwald) - Changed trace output to read "setting" instead of  *          the awkward sounding "settings". * 04/12/94 (seiwald) - Combined build_depends() with build_includes(). * 04/12/94 (seiwald) - actionlist() now just appends a single action. * 04/13/94 (seiwald) - added shorthand L0 for null list pointer * 05/13/94 (seiwald) - include files are now bound as targets, and thus *          can make use of $(SEARCH) * 06/01/94 (seiwald) - new 'actions existing' does existing sources * 08/23/94 (seiwald) - Support for '+=' (append to variable) * 12/20/94 (seiwald) - NOTIME renamed NOTFILE. * 01/22/95 (seiwald) - Exit rule. * 02/02/95 (seiwald) - Always rule; LEAVES rule. * 02/14/95 (seiwald) - NoUpdate rule. * 09/11/00 (seiwald) - new evaluate_rule() for headers(). * 09/11/00 (seiwald) - compile_xxx() now return LIST *. *          New compile_append() and compile_list() in *          support of building lists here, rather than *          in jamgram.yy. * 01/10/00 (seiwald) - built-ins split out to builtin.c. */static void debug_compile( int which, char *s, FRAME* frame );int glob( char *s, char *c );/* Internal functions from builtins.c */void backtrace( FRAME *frame );void backtrace_line( FRAME *frame );void print_source_line( PARSE* p );struct frame *frame_before_python_call;void frame_init( FRAME* frame ){    frame->prev = 0;    frame->prev_user = 0;    lol_init(frame->args);    frame->module = root_module();    frame->rulename = "module scope";    frame->procedure = 0;}void frame_free( FRAME* frame ){    lol_free( frame->args );}/* * compile_append() - append list results of two statements * *  parse->left more compile_append() by left-recursion *  parse->right    single rule */LIST *compile_append(    PARSE   *parse,    FRAME *frame ){    /* Append right to left. */    return list_append(         parse_evaluate( parse->left, frame ),        parse_evaluate( parse->right, frame ) );}/* * compile_eval() - evaluate if to determine which leg to compile * * Returns: *	list 	if expression true - compile 'then' clause *	L0	if expression false - compile 'else' clause */static intlcmp( LIST *t, LIST *s ){	int status = 0;	while( !status && ( t || s ) )	{	    char *st = t ? t->string : "";	    char *ss = s ? s->string : "";	    status = strcmp( st, ss );	    t = t ? list_next( t ) : t;	    s = s ? list_next( s ) : s;	}	return status;}LIST *compile_eval(	PARSE	*parse,	FRAME	*frame ){	LIST *ll, *lr, *s, *t;	int status = 0;	/* Short circuit lr eval for &&, ||, and 'in' */	ll = parse_evaluate( parse->left, frame );	lr = 0;	switch( parse->num )	{	case EXPR_AND: 	case EXPR_IN: 	if( ll ) goto eval; break;	case EXPR_OR: 	if( !ll ) goto eval; break;	default: eval: 	lr = parse_evaluate( parse->right, frame );	}	/* Now eval */	switch( parse->num )	{	case EXPR_NOT:			if( !ll ) status = 1;		break;	case EXPR_AND:		if( ll && lr ) status = 1;		break;	case EXPR_OR:		if( ll || lr ) status = 1;		break;	case EXPR_IN:		/* "a in b": make sure each of */		/* ll is equal to something in lr. */		for( t = ll; t; t = list_next( t ) )		{		    for( s = lr; s; s = list_next( s ) )			if( !strcmp( t->string, s->string ) )			    break;		    if( !s ) break;		}		/* No more ll? Success */		if( !t ) status = 1;		break;	case EXPR_EXISTS:       if( lcmp( ll, L0 ) != 0 ) status = 1; break;	case EXPR_EQUALS:	if( lcmp( ll, lr ) == 0 ) status = 1; break;	case EXPR_NOTEQ:	if( lcmp( ll, lr ) != 0 ) status = 1; break;	case EXPR_LESS:		if( lcmp( ll, lr ) < 0  ) status = 1; break;	case EXPR_LESSEQ:	if( lcmp( ll, lr ) <= 0 ) status = 1; break;	case EXPR_MORE:		if( lcmp( ll, lr ) > 0  ) status = 1; break;	case EXPR_MOREEQ:	if( lcmp( ll, lr ) >= 0 ) status = 1; break;	}	if( DEBUG_IF )	{	    debug_compile( 0, "if", frame );	    list_print( ll );	    printf( "(%d) ", status );	    list_print( lr );	    printf( "\n" );	}	/* Find something to return. */	/* In odd circumstances (like "" = "") */	/* we'll have to return a new string. */	if( !status ) t = 0;	else if( ll ) t = ll, ll = 0;	else if( lr ) t = lr, lr = 0;	else t = list_new( L0, newstr( "1" ) );	if( ll ) list_free( ll );	if( lr ) list_free( lr );	return t;}/* * compile_foreach() - compile the "for x in y" statement * * Compile_foreach() resets the given variable name to each specified * value, executing the commands enclosed in braces for each iteration. * *  parse->string   index variable *  parse->left variable values *  parse->right    rule to compile */LIST *compile_foreach(    PARSE   *parse,    FRAME *frame ){    LIST    *nv = parse_evaluate( parse->left, frame );    LIST    *l;    SETTINGS *s = 0;                if ( parse->num )        {            s = addsettings( s, VAR_SET, parse->string, L0 );            pushsettings( s );        }    /* Call var_set to reset $(parse->string) for each val. */    for( l = nv; l; l = list_next( l ) )    {        LIST *val = list_new( L0, copystr( l->string ) );        var_set( parse->string, val, VAR_SET );        list_free( parse_evaluate( parse->right, frame ) );    }        if ( parse->num )        {            popsettings( s );            freesettings( s );        }    list_free( nv );    return L0;}/* * compile_if() - compile 'if' rule * *  parse->left     condition tree *  parse->right        then tree *  parse->third        else tree */LIST *compile_if(    PARSE   *p,    FRAME *frame ){    LIST *l = parse_evaluate( p->left, frame );    if( l )    {        list_free( l );        return parse_evaluate( p->right, frame );    }    else    {        return parse_evaluate( p->third, frame );    }}LIST *compile_while(    PARSE   *p,    FRAME *frame ){    LIST *r = 0;    LIST *l;    while ( l = parse_evaluate( p->left, frame ) )    {        list_free( l );        if( r ) list_free( r );        r = parse_evaluate( p->right, frame );    }    return r;}/* * compile_include() - support for 'include' - call include() on file * *  parse->left list of files to include (can only do 1) */LIST *compile_include(    PARSE   *parse,    FRAME *frame ){    LIST    *nt = parse_evaluate( parse->left, frame );    if( DEBUG_COMPILE )    {        debug_compile( 0, "include", frame);        list_print( nt );        printf( "\n" );    }    if( nt )    {        TARGET *t = bindtarget( nt->string );            /* DWA 2001/10/22 - Perforce Jam clears the arguments here, which             * prevents an included file from being treated as part of the body             * of a rule. I didn't see any reason to do that, so I lifted the             * restriction.             */                       /* Bind the include file under the influence of */        /* "on-target" variables.  Though they are targets, */        /* include files are not built with make(). */        pushsettings( t->settings );        /* We don't expect that file to be included is generated by some           action. Therefore, pass 0 as third argument. */        t->boundname = search( t->name, &t->time, 0 );        popsettings( t->settings );        parse_file( t->boundname, frame );    }    list_free( nt );    return L0;}static LIST* evaluate_in_module ( char* module_name, PARSE * p, FRAME* frame){    LIST* result;    module_t* outer_module = frame->module;    frame->module = module_name ? bindmodule( module_name ) : root_module();    if ( outer_module != frame->module )    {        exit_module( outer_module );        enter_module( frame->module );    }        result = parse_evaluate( p, frame );        if ( outer_module != frame->module )    {        exit_module( frame->module );        enter_module( outer_module );        frame->module = outer_module;    }    return result;}LIST *compile_module(    PARSE   *p,    FRAME *frame ){    /* Here we are entering a module declaration block.      */    LIST* module_name = parse_evaluate( p->left, frame );    LIST* result = evaluate_in_module( module_name ? module_name->string : 0,                                        p->right, frame );        list_free( module_name );    return result;}LIST *compile_class(     PARSE *p,     FRAME *frame ){    /** Todo: check for empty class name.        Check for class redeclaration. */    char* class_module = 0;    LIST* name = parse_evaluate( p->left->right, frame );    LIST* bases = 0;    if (p->left->left)        bases = parse_evaluate( p->left->left->right, frame );    class_module = make_class_module(name, bases, frame);        evaluate_in_module( class_module, p->right, frame );    return L0;    }/* * compile_list() - expand and return a list  * *  parse->string - character string to expand */LIST *compile_list(    PARSE   *parse,    FRAME *frame ){    /* voodoo 1 means: s is a copyable string */    char *s = parse->string;    return var_expand( L0, s, s + strlen( s ), frame->args, 1 );}/* * compile_local() - declare (and set) local variables * *  parse->left list of variables *  parse->right    list of values *  parse->third    rules to execute */

⌨️ 快捷键说明

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