コード例 #1
0
SValue For::Evaluate(const sptr<BShell>& parent, const sptr<ICommand>& shell, bool* outExit)
{
	SVector<SValue> args;

	for (size_t i = 0 ; i < m_words.CountItems(); i++)
	{
		bool insert_args = false;
		//bout << "WORDS [" << i << "] " << m_words[i] << endl;
		SValue expanded = Expand(shell, m_words.ItemAt(i), &insert_args);
		
		if (insert_args)
		{
			collect_arguments(expanded.AsString(), &args);
		}
		else
		{
			//bout << "adding expanded " << expanded << endl;
			args.AddItem(expanded);
		}
	}
	
	*outExit = false;
	SValue returned = SValue::Status(B_OK);
	
	for (size_t i = 0 ; i < args.CountItems() && !*outExit; i++)
	{
		//bout << "setting m_condition to be " << args.ItemAt(i) << endl;
		shell->SetProperty(SValue::String(m_condition), args.ItemAt(i));
		returned = m_dolist->Evaluate(parent, shell, outExit);
	}
	
	return returned;
}
コード例 #2
0
SValue SimpleCommand::Evaluate(const sptr<BShell>& parent, const sptr<ICommand>& shell, bool* outExit)
{
//	bout << "SimpleCommand::Evaluate: " << m_command << endl;

	sptr<ICommand> command = NULL;
	bool doExit = false;
	*outExit = false;
	
	if (m_command != "" && m_command != "exit" && m_command != "return"
		&& m_command != "cd" && m_command != "." && m_command != "source")
	{
		SValue cmdName = Expand(shell, m_command);

		// If the command is actually an ICommand object,
		// run it in-place.
		// XXX This isn't quite right -- we really want
		// to spawn a copy, in which we can set our own
		// environment.
		command = ICommand::AsInterface(cmdName);

		// Not an object, try to execute by name.
		if (command == NULL) {
			command = shell->Spawn(cmdName.AsString());
		}
	
		if (command == NULL)
		{
			parent->TextError() << "bsh: " << m_command << ": command not found" << endl;
			return SValue::Status(B_NAME_NOT_FOUND);
		}
	}
	else
		command = shell;

	SValue result;

	if (m_prefix != NULL)
		result = m_prefix->Evaluate(parent, command, &doExit);
	
	if (m_suffix != NULL)
		m_suffix->Evaluate(parent, command, &doExit);
	
	SVector<SString> words;
	if (m_suffix != NULL)
		words = m_suffix->GetWords();

	// set redirects

	// build argument list
	
	ICommand::ArgList args;
	args.AddItem(SValue::String(m_command));
	
	for (size_t index = 0 ; index < words.CountItems(); index++)
	{
		bool expand = false;
		//bout << "WORDS [" << index << "] " << words[index] << endl;
		SValue expanded = Expand(shell, words.ItemAt(index), &expand);
		//bout << "WORDS [" << index << "] expaned to " << expanded << endl;
		if (expand)
		{
			collect_arguments(expanded.AsString(), &args);
		}
		else
		{
			args.AddItem(expanded);
		}
	}
		
	// only run this if we are a newly spawned command!
	if (command != shell)
	{
		result = command->Run(args);
		// This command may be a function, that could call "exit".
		*outExit = parent->ExitRequested();
	}
	else if (m_command == "exit" || m_command == "return")
	{
		result = args.CountItems() > 1 ? args[1] : SValue::Status(B_OK);
		*outExit = true;
		if (m_command == "exit") {
			parent->RequestExit();
		}
	}
	else if (m_command == "cd")
	{
		SString path;
		if (args.CountItems() > 1) {
			path = args[1].AsString();
		}
		if (path != "") {
			SString cd=shell->GetProperty(SValue::String("PWD")).AsString();
			cd.PathAppend(path, true);
			SNode node(parent->Context().Root());
			SValue dir(node.Walk(cd, (uint32_t)0));
			if (interface_cast<INode>(dir) != NULL) {
				shell->SetProperty(SValue::String("PWD"), SValue::String(cd));
				result = SValue::Status(B_OK);
			} else {
				parent->TextError() << "cd: '" << path << "' is not a directory." << endl;
				result = SValue::Status(B_BAD_VALUE);
			}
		} else {
			parent->TextError() << "cd: no directory specified." << endl;
			result = SValue::Status(B_BAD_VALUE);
		}
	}
	else if (m_command == "." || m_command == "source")
	{
		if (args.CountItems() > 1) {
			sptr<ITextInput> input;
			SString path;
			find_some_input(args[1], parent, &input, &path);
			if (input != NULL) {
				SValue oldFile = parent->GetProperty(kBSH_SCRIPT_FILE);
				SValue oldDir = parent->GetProperty(kBSH_SCRIPT_DIR);
				
				args.RemoveItemsAt(0, 2);
				args.AddItemAt(SValue::String(path), 0);
				parent->SetLastResult(SValue::String(path));
				parent->SetProperty(kBSH_SCRIPT_FILE, SValue::String(path));
				SString parentDir;
				path.PathGetParent(&parentDir);
				parent->SetProperty(kBSH_SCRIPT_DIR, SValue::String(parentDir));
				
				FunctionCommand::ArgumentHandler argHandler;
				argHandler.ApplyArgs(parent, args, true);
				sptr<Lexer> lexer = new Lexer(parent, input, parent->TextOutput(), false);
				SValue result;
				if (lexer != NULL) {
					Parser parser(parent);
					SValue result = parser.Parse(lexer);
				} else {
					parent->TextError() << m_command << ": out of memory." << endl;
					result = SValue::Status(B_NO_MEMORY);
				}
				
				argHandler.RestoreArgs(parent);
				parent->SetProperty(kBSH_SCRIPT_FILE, oldFile);
				parent->SetProperty(kBSH_SCRIPT_DIR, oldDir);
				return result;
			} else {
				parent->TextError() << m_command << ": '" << args[1] << "' is not a file." << endl;
				result = SValue::Status(B_BAD_VALUE);
			}
		} else {
			parent->TextError() << m_command << ": no file specified." << endl;
			result = SValue::Status(B_BAD_VALUE);
		}
		*outExit = parent->ExitRequested();
	}
	
	return result;
}
コード例 #3
0
ファイル: compile.c プロジェクト: 4ukuta/core
LIST *
evaluate_rule(
    char  * rulename,
    FRAME * frame )
{
    LIST          * result = L0;
    RULE          * rule;
    profile_frame   prof[1];
    module_t      * prev_module = frame->module;

    LIST * l;
    {
        LOL arg_context_, * arg_context = &arg_context_;
        if ( !frame->prev )
            lol_init(arg_context);
        else
            arg_context = frame->prev->args;
        l = var_expand( L0, rulename, rulename+strlen(rulename), arg_context, 0 );
    }

    if ( !l )
    {
        backtrace_line( frame->prev );
        printf( "warning: rulename %s expands to empty string\n", rulename );
        backtrace( frame->prev );
        return result;
    }

    rulename = l->string;
    rule = bindrule( l->string, frame->module );

#ifdef HAVE_PYTHON
    if ( rule->python_function )
    {
        /* The below messing with modules is due to the way modules are
         * implemented in Jam. Suppose we are in module M1 now. The global
         * variable map actually holds 'M1' variables, and M1->variables hold
         * global variables.
         *
         * If we call Python right away, Python calls back Jam and then Jam
         * does 'module M1 { }' then Jam will try to swap the current global
         * variables with M1->variables. The result will be that global
         * variables map will hold global variables, and any variable settings
         * we do will go to the global module, not M1.
         *
         * By restoring basic state, where the global variable map holds global
         * variable, we make sure any future 'module M1' entry will work OK.
         */

        LIST * result;
        module_t * m = python_module();

        frame->module = m;

        exit_module( prev_module );
        enter_module( m );

        result = call_python_function( rule, frame );

        exit_module( m );
        enter_module ( prev_module );

        return result;
    }
#endif

    /* Drop the rule name. */
    l = list_pop_front( l );

    /* Tack the rest of the expansion onto the front of the first argument. */
    frame->args->list[0] = list_append( l, lol_get( frame->args, 0 ) );

    if ( DEBUG_COMPILE )
    {
        /* Try hard to indicate in which module the rule is going to execute. */
        if ( rule->module != frame->module
             && rule->procedure != 0 && strcmp( rulename, rule->procedure->rulename ) )
        {
            char buf[256] = "";
            strncat( buf, rule->module->name, sizeof( buf ) - 1 );
            strncat( buf, rule->name, sizeof( buf ) - 1 );
            debug_compile( 1, buf, frame );
        }
        else
        {
            debug_compile( 1, rulename, frame );
        }

        lol_print( frame->args );
        printf( "\n" );
    }

    if ( rule->procedure && rule->module != prev_module )
    {
        /* Propagate current module to nested rule invocations. */
        frame->module = rule->module;

        /* Swap variables. */
        exit_module( prev_module );
        enter_module( rule->module );
    }

    /* Record current rule name in frame. */
    if ( rule->procedure )
    {
        frame->rulename = rulename;
        /* And enter record profile info. */
        if ( DEBUG_PROFILE )
            profile_enter( rule->procedure->rulename, prof );
    }

    /* Check traditional targets $(<) and sources $(>). */
    if ( !rule->actions && !rule->procedure )
    {
        backtrace_line( frame->prev );
        printf( "rule %s unknown in module %s\n", rule->name, frame->module->name );
        backtrace( frame->prev );
        exit( 1 );
    }

    /* If this rule will be executed for updating the targets then construct the
     * action for make().
     */
    if ( rule->actions )
    {
        TARGETS * t;
        ACTION  * action;

        /* The action is associated with this instance of this rule. */
        action = (ACTION *)BJAM_MALLOC( sizeof( ACTION ) );
        memset( (char *)action, '\0', sizeof( *action ) );

        action->rule = rule;
        action->targets = targetlist( (TARGETS *)0, lol_get( frame->args, 0 ) );
        action->sources = targetlist( (TARGETS *)0, lol_get( frame->args, 1 ) );

        /* If we have a group of targets all being built using the same action
         * then we must not allow any of them to be used as sources unless they
         * had all already been built in the first place or their joined action
         * has had a chance to finish its work and build all of them anew.
         *
         * Without this it might be possible, in case of a multi-process build,
         * for their action, triggered by buiding one of the targets, to still
         * be running when another target in the group reports as done in order
         * to avoid triggering the same action again and gets used prematurely.
         *
         * As a quick-fix to achieve this effect we make all the targets list
         * each other as 'included targets'. More precisely, we mark the first
         * listed target as including all the other targets in the list and vice
         * versa. This makes anyone depending on any of those targets implicitly
         * depend on all of them, thus making sure none of those targets can be
         * used as sources until all of them have been built. Note that direct
         * dependencies could not have been used due to the 'circular
         * dependency' issue.
         *
         * TODO: Although the current implementation solves the problem of one
         * of the targets getting used before its action completes its work it
         * also forces the action to run whenever any of the targets in the
         * group is not up to date even though some of them might not actually
         * be used by the targets being built. We should see how we can
         * correctly recognize such cases and use that to avoid running the
         * action if possible and not rebuild targets not actually depending on
         * targets that are not up to date.
         *
         * TODO: Using the 'include' feature might have side-effects due to
         * interaction with the actual 'inclusion scanning' system. This should
         * be checked.
         */
        if ( action->targets )
        {
            TARGET * t0 = action->targets->target;
            for ( t = action->targets->next; t; t = t->next )
            {
                target_include( t->target, t0 );
                target_include( t0, t->target );
            }
        }

        /* Append this action to the actions of each target. */
        for ( t = action->targets; t; t = t->next )
            t->target->actions = actionlist( t->target->actions, action );
    }

    /* Now recursively compile any parse tree associated with this rule.
     * parse_refer()/parse_free() call pair added to ensure rule not freed
     * during use.
     */
    if ( rule->procedure )
    {
        SETTINGS * local_args = collect_arguments( rule, frame );
        PARSE * parse = rule->procedure;
        parse_refer( parse );

        pushsettings( local_args );
        result = parse_evaluate( parse, frame );
        popsettings( local_args );
        freesettings( local_args );

        parse_free( parse );
    }

    if ( frame->module != prev_module )
    {
        exit_module( frame->module );
        enter_module( prev_module );
    }

    if ( DEBUG_PROFILE && rule->procedure )
        profile_exit( prof );

    if ( DEBUG_COMPILE )
        debug_compile( -1, 0, frame);

    return result;
}
コード例 #4
0
ファイル: compile.c プロジェクト: 4ukuta/core
static LIST*
call_python_function(RULE* r, FRAME* frame)
{
    LIST * result = 0;
    PyObject * arguments = 0;
    PyObject * kw = NULL;
    int i ;
    PyObject * py_result;

    if (r->arguments)
    {
        SETTINGS * args;

        arguments = PyTuple_New(0);
        kw = PyDict_New();

        for (args = collect_arguments(r, frame); args; args = args->next)
        {
            PyObject *key = PyString_FromString(args->symbol);
            PyObject *value = 0;
            if (args->multiple)
                value = list_to_python(args->value);
            else {
                if (args->value)
                    value = PyString_FromString(args->value->string);
            }

            if (value)
                PyDict_SetItem(kw, key, value);
            Py_DECREF(key);
            Py_XDECREF(value);
        }
    }
    else
    {
        arguments = PyTuple_New( frame->args->count );
        for ( i = 0; i < frame->args->count; ++i )
        {
            PyObject * arg = PyList_New(0);
            LIST* l = lol_get( frame->args, i);
            
            for ( ; l; l = l->next )
            {
                PyObject * v = PyString_FromString(l->string);
                PyList_Append( arg, v );
                Py_DECREF(v);
            }
            /* Steals reference to 'arg' */
            PyTuple_SetItem( arguments, i, arg );
        }
    }

    frame_before_python_call = frame;
    py_result = PyObject_Call( r->python_function, arguments, kw );
    Py_DECREF(arguments);
    Py_XDECREF(kw);
    if ( py_result != NULL )
    {
        if ( PyList_Check( py_result ) )
        {
            int size = PyList_Size( py_result );
            int i;
            for ( i = 0; i < size; ++i )
            {
                PyObject * item = PyList_GetItem( py_result, i );
                char *s = python_to_string (item);
                if (!s) {
                    fprintf( stderr, "Non-string object returned by Python call.\n" );
                } else {
                    result = list_new (result, s);
                }
            }
        }
        else if ( py_result == Py_None )
        {
            result = L0;
        }
        else 
        {
            char *s = python_to_string(py_result);
            if (s)
                result = list_new(0, s);
            else 
                /* We have tried all we could.  Return empty list. There are
                   cases, e.g.  feature.feature function that should return
                   value for the benefit of Python code and which also can be
                   called by Jam code, where no sensible value can be
                   returned. We cannot even emit a warning, since there will
                   be a pile of them.  */                
                result = L0;                    
        }

        Py_DECREF( py_result );
    }
    else
    {
        PyErr_Print();
        fprintf(stderr,"Call failed\n");
    }

    return result;
}
コード例 #5
0
ファイル: compile.c プロジェクト: Albermg7/boost
LIST *
evaluate_rule(
    char    *rulename,
    FRAME *frame )
{
    LIST      *result = L0;
    RULE          *rule;
    profile_frame prof[1];
    module_t    *prev_module = frame->module;
    
    LIST      *l;
    {
        LOL arg_context_, *arg_context = &arg_context_;
        if ( !frame->prev )
            lol_init(arg_context);
        else
            arg_context = frame->prev->args;
        
        l = var_expand( L0, rulename, rulename+strlen(rulename), arg_context, 0 );
    }

    if ( !l )
    {
        backtrace_line( frame->prev );
        printf( "warning: rulename %s expands to empty string\n", rulename );
        backtrace( frame->prev );
        return result;
    }

    rulename = l->string;
    rule = bindrule( l->string, frame->module );

#ifdef HAVE_PYTHON
    if (rule->python_function)
    {
        return call_python_function(rule, frame);
    }
#endif

    /* drop the rule name */
    l = list_pop_front( l );

    /* tack the rest of the expansion onto the front of the first argument */
    frame->args->list[0] = list_append( l, lol_get( frame->args, 0 ) );

    if ( DEBUG_COMPILE )
    {
        /* Try hard to indicate in which module the rule is going to execute */
        if ( rule->module != frame->module
             && rule->procedure != 0 && strcmp(rulename, rule->procedure->rulename) )
        {
            char buf[256] = "";
            strncat( buf, rule->module->name, sizeof(buf) - 1 );
            strncat( buf, rule->name, sizeof(buf) - 1 );
            debug_compile( 1, buf, frame);
        }
        else
        {
            debug_compile( 1, rulename, frame);
        }

        lol_print( frame->args );
        printf( "\n" );
    }
    
    if ( rule->procedure && rule->module != prev_module )
    {
        /* propagate current module to nested rule invocations */
        frame->module = rule->module;
        
        /* swap variables */
        exit_module( prev_module );
        enter_module( rule->module );
    }
        
    /* record current rule name in frame */
    if ( rule->procedure )
    {
        frame->rulename = rulename;
        /* and enter record profile info */
        if ( DEBUG_PROFILE )
            profile_enter( rule->procedure->rulename, prof );
    }

    /* Check traditional targets $(<) and sources $(>) */

    if( !rule->actions && !rule->procedure )
    {
        backtrace_line( frame->prev );
        printf( "rule %s unknown in module %s\n", rule->name, frame->module->name );
        backtrace( frame->prev );
        exit(1);
    }

    /* If this rule will be executed for updating the targets */
    /* then construct the action for make(). */

    if( rule->actions )
    {
        TARGETS *t;
        ACTION  *action;

        /* The action is associated with this instance of this rule */

        action = (ACTION *)malloc( sizeof( ACTION ) );
        memset( (char *)action, '\0', sizeof( *action ) );

        action->rule = rule;
        action->targets = targetlist( (TARGETS *)0, lol_get( frame->args, 0 ) );
        action->sources = targetlist( (TARGETS *)0, lol_get( frame->args, 1 ) );

        /* Append this action to the actions of each target */

        for( t = action->targets; t; t = t->next )
            t->target->actions = actionlist( t->target->actions, action );
    }

    /* Now recursively compile any parse tree associated with this rule */
    /* refer/free to ensure rule not freed during use */

    if( rule->procedure )
    {
        SETTINGS *local_args = collect_arguments( rule, frame );
        PARSE *parse = rule->procedure;
        parse_refer( parse );
        
        pushsettings( local_args );
        result = parse_evaluate( parse, frame );
        popsettings( local_args );
        freesettings( local_args );
        
        parse_free( parse );
    }

    if ( frame->module != prev_module )
    {
        exit_module( frame->module );
        enter_module( prev_module );
    }

    if ( DEBUG_PROFILE && rule->procedure )
        profile_exit( prof );

    if( DEBUG_COMPILE )
        debug_compile( -1, 0, frame);

    return result;
}
コード例 #6
0
ファイル: macro.c プロジェクト: 119/aircam-openwrt
static void
expand_macro (symbol *sym)
{
  struct obstack arguments;     /* Alternate obstack if argc_stack is busy.  */
  unsigned argv_base;           /* Size of argv_stack on entry.  */
  bool use_argc_stack = true;   /* Whether argc_stack is safe.  */
  token_data **argv;
  int argc;
  struct obstack *expansion;
  const char *expanded;
  bool traced;
  int my_call_id;

  /* Report errors at the location where the open parenthesis (if any)
     was found, but after expansion, restore global state back to the
     location of the close parenthesis.  This is safe since we
     guarantee that macro expansion does not alter the state of
     current_file/current_line (dnl, include, and sinclude are special
     cased in the input engine to ensure this fact).  */
  const char *loc_open_file = current_file;
  int loc_open_line = current_line;
  const char *loc_close_file;
  int loc_close_line;

  SYMBOL_PENDING_EXPANSIONS (sym)++;
  expansion_level++;
  if (nesting_limit > 0 && expansion_level > nesting_limit)
    M4ERROR ((EXIT_FAILURE, 0,
              "recursion limit of %d exceeded, use -L<N> to change it",
              nesting_limit));

  macro_call_id++;
  my_call_id = macro_call_id;

  traced = (debug_level & DEBUG_TRACE_ALL) || SYMBOL_TRACED (sym);

  argv_base = obstack_object_size (&argv_stack);
  if (obstack_object_size (&argc_stack) > 0)
    {
      /* We cannot use argc_stack if this is a nested invocation, and an
         outer invocation has an unfinished argument being
         collected.  */
      obstack_init (&arguments);
      use_argc_stack = false;
    }

  if (traced && (debug_level & DEBUG_TRACE_CALL))
    trace_prepre (SYMBOL_NAME (sym), my_call_id);

  collect_arguments (sym, &argv_stack,
                     use_argc_stack ? &argc_stack : &arguments);

  argc = ((obstack_object_size (&argv_stack) - argv_base)
          / sizeof (token_data *));
  argv = (token_data **) ((char *) obstack_base (&argv_stack) + argv_base);

  loc_close_file = current_file;
  loc_close_line = current_line;
  current_file = loc_open_file;
  current_line = loc_open_line;

  if (traced)
    trace_pre (SYMBOL_NAME (sym), my_call_id, argc, argv);

  expansion = push_string_init ();
  call_macro (sym, argc, argv, expansion);
  expanded = push_string_finish ();

  if (traced)
    trace_post (SYMBOL_NAME (sym), my_call_id, argc, expanded);

  current_file = loc_close_file;
  current_line = loc_close_line;

  --expansion_level;
  --SYMBOL_PENDING_EXPANSIONS (sym);

  if (SYMBOL_DELETED (sym))
    free_symbol (sym);

  if (use_argc_stack)
    obstack_free (&argc_stack, argv[0]);
  else
    obstack_free (&arguments, NULL);
  obstack_blank (&argv_stack, -argc * sizeof (token_data *));
}