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

📄 builtins.c

📁 C++的一个好库。。。现在很流行
💻 C
📖 第 1 页 / 共 3 页
字号:
{
	if ( !frame ) return;
    while ( frame = frame->prev )
    {
        backtrace_line( frame );
    }
}

/*  A Jam version of the backtrace function, taking no arguments and
 *  returning a list of quadruples: FILENAME LINE MODULE. RULENAME
 *  describing each frame. Note that the module-name is always
 *  followed by a period.
 */
LIST *builtin_backtrace( PARSE *parse, FRAME *frame )
{
    LIST* levels_arg = lol_get( frame->args, 0 );
    int levels = levels_arg ? atoi( levels_arg->string ) : ((unsigned int)(-1) >> 1) ;

    LIST* result = L0;
    for(; (frame = frame->prev) && levels ; --levels )
    {
        char* file;
        int line;
        char buf[32];
        get_source_line( frame->procedure, &file, &line );
        sprintf( buf, "%d", line );
        result = list_new( result, newstr( file ) );
        result = list_new( result, newstr( buf ) );
        result = list_new( result, newstr( frame->module->name ) );
        result = list_new( result, newstr( frame->rulename ) );
    }
    return result;
}

/*
 * builtin_caller_module() - CALLER_MODULE ( levels ? )
 *
 * If levels is not supplied, returns the name of the module of the rule which
 * called the one calling this one. If levels is supplied, it is interpreted as
 * an integer specifying a number of additional levels of call stack to traverse
 * in order to locate the module in question. If no such module exists,
 * returns the empty list. Also returns the empty list when the module in
 * question is the global module. This rule is needed for implementing module
 * import behavior.
 */
LIST *builtin_caller_module( PARSE *parse, FRAME *frame )
{
    LIST* levels_arg = lol_get( frame->args, 0 );
    int levels = levels_arg ? atoi( levels_arg->string ) : 0 ;

    int i;
    for (i = 0; i < levels + 2 && frame->prev; ++i)
        frame = frame->prev;

    if ( frame->module == root_module() )
    {
        return L0;
    }
    else
    {
        LIST* result;
        
        string name;
        string_copy( &name, frame->module->name );
        string_pop_back( &name );

        result = list_new( L0, newstr(name.value) );
        
        string_free( &name );
        
        return result;
    }
}

/*
 * Return the current working directory.
 *
 * Usage: pwd = [ PWD ] ;
 */
LIST*
builtin_pwd( PARSE *parse, FRAME *frame )
{
    return pwd();
}

/*
 * Adds targets to the list of target that jam will attempt to update.
 */
LIST* 
builtin_update( PARSE *parse, FRAME *frame)
{
    LIST* result = list_copy( L0, targets_to_update() );
    LIST* arg1 = lol_get( frame->args, 0 );
    clear_targets_to_update();
    for ( ; arg1; arg1 = list_next( arg1 ) )
        mark_target_for_updating( newstr(arg1->string) );
    return result;
}

LIST*
builtin_search_for_target( PARSE *parse, FRAME *frame )
{
    LIST* arg1 = lol_get( frame->args, 0 );
    LIST* arg2 = lol_get( frame->args, 1 );

    TARGET* t = search_for_target( arg1->string, arg2 );
    return list_new( L0, t->name );
}

LIST *builtin_import_module( PARSE *parse, FRAME *frame )
{
    LIST* arg1 = lol_get( frame->args, 0 );
    LIST* arg2 = lol_get( frame->args, 1 );

    module_t* m = arg2 ? bindmodule(arg2->string) : root_module();

    import_module(arg1, m);

    return L0;
}


LIST *builtin_imported_modules( PARSE *parse, FRAME *frame )
{
    LIST *arg0 = lol_get( frame->args, 0 );
    module_t* source_module = bindmodule( arg0 ? arg0->string : 0 );

    return imported_modules(source_module);
}

LIST *builtin_instance( PARSE *parse, FRAME *frame )
{
    LIST* arg1 = lol_get( frame->args, 0 );
    LIST* arg2 = lol_get( frame->args, 1 );

    module_t* instance = bindmodule( arg1->string );
    module_t* class_module = bindmodule( arg2->string );
    instance->class_module = class_module;

    return L0;
}

LIST*
builtin_sort( PARSE *parse, FRAME *frame )
{
    LIST* arg1 = lol_get( frame->args, 0 );

    return list_sort(arg1);
}

LIST *builtin_normalize_path( PARSE *parse, FRAME *frame )
{
    LIST* arg1 = lol_get( frame->args, 0 );

    /* First, we iterate over all '/'-separated elements, starting from
       the end of string. If we see '..', we remove previous path elements.
       If we see '.', we remove it.
       The removal is done by putting '\1' in the string. After all the string
       is processed, we do a second pass, removing '\1' characters.
    */
    
    string in[1], out[1], tmp[1];
    char* end;      /* Last character of the part of string still to be processed. */
    char* current;  /* Working pointer. */  
    int dotdots = 0; /* Number of '..' elements seen and not processed yet. */
    int rooted = arg1->string[0] == '/';
    char* result;

    /* Make a copy of input: we should not change it. */
    string_new(in);
    if (!rooted)
        string_push_back(in, '/');
    string_append(in, arg1->string);
    

    end = in->value + in->size - 1;
    current = end;
    
    for(;end >= in->value;) {
        /* Set 'current' to the next occurence of '/', which always exists. */
        for(current = end; *current != '/'; --current)
            ;
        
        if (current == end && current != in->value) {
            /* Found a trailing slash. Remove it. */
            *current = '\1';
        } else if (current == end && *(current+1) == '/') {
            /* Found duplicated slash. Remove it. */
            *current = '\1';
        } else if (end - current == 1 && strncmp(current, "/.", 2) == 0) {
            /* Found '/.'. Drop them all. */
            *current = '\1';
            *(current+1) = '\1';                   
        } else if (end - current == 2 && strncmp(current, "/..", 3) == 0) {
            /* Found '/..' */                
            *current = '\1';
            *(current+1) = '\1';                   
            *(current+2) = '\1';                   
            ++dotdots;
        } else if (dotdots) {
            char* p = current;
            memset(current, '\1', end-current+1);
            --dotdots;
        }                 
        end = current-1;
    }


    string_new(tmp);
    while(dotdots--)
        string_append(tmp, "/..");
    string_append(tmp, in->value);
    string_copy(in, tmp->value);
    string_free(tmp);
        
       
    string_new(out);
    /* The resulting path is either empty or has '/' as the first significant
       element. If the original path was not rooted, we need to drop first '/'. 
       If the original path was rooted, and we've got empty path, need to add '/'
    */
    if (!rooted) {
        current = strchr(in->value, '/');
        if (current)
            *current = '\1';
    } 
       
    for (current = in->value; *current; ++current)
        if (*current != '\1')
            string_push_back(out, *current);

    
    result = newstr(out->size ? out->value : (rooted ? "/" : "."));
    string_free(in);
    string_free(out);

    return list_new(0, result);

}

LIST *builtin_native_rule( PARSE *parse, FRAME *frame )
{
    LIST* module_name = lol_get( frame->args, 0 );    
    LIST* rule_name = lol_get( frame->args, 1 );    

    module_t* module = bindmodule(module_name->string);

    native_rule_t n, *np = &n;
    n.name = rule_name->string;
    if (module->native_rules && hashcheck(module->native_rules, (HASHDATA**)&np))
    {
        new_rule_body(module, np->name, np->arguments, np->procedure, 1);
    }
    else
    {
        backtrace_line( frame->prev );
        printf( "error: no native rule \"%s\" defined in module \"%s\"\n", 
                n.name, module->name);
        backtrace( frame->prev );
        exit(1);
    }
    return L0;    
}

LIST *builtin_user_module( PARSE *parse, FRAME *frame )
{
    LIST* module_name = lol_get( frame->args, 0 );    
    for(; module_name; module_name = module_name->next) 
    {
        module_t* m = bindmodule( module_name->string);
        m->user_module = 1;
    }
    return L0;
}

LIST *builtin_nearest_user_location( PARSE *parse, FRAME *frame )
{
    LIST* result = 0;
    FRAME* nearest_user_frame = 
        frame->module->user_module ? frame : frame->prev_user;

    if (nearest_user_frame)
    {
        char* file;
        int line;
        char buf[32];
        get_source_line( nearest_user_frame->procedure, &file, &line );
        sprintf( buf, "%d", line );
        result = list_new( result, newstr( file ) );
        result = list_new( result, newstr( buf ) );
        return result;
    }
    else
    {
        return L0;
    }
}

LIST *builtin_check_if_file( PARSE *parse, FRAME *frame )
{
    LIST* name = lol_get( frame->args, 0 );
    if (file_is_file(name->string) == 1) {
        return list_new(0, newstr("true"));
    } else {
        return L0;
    }
}


#ifdef HAVE_PYTHON

LIST *builtin_python_import_rule( PARSE *parse, FRAME *frame )
{
    static int first_time = 1;
   char* python_module = lol_get( frame->args, 0 )->string;        
   char* python_function = lol_get( frame->args, 1 )->string;        
   char* jam_module = lol_get( frame->args, 2 )->string;        
   char* jam_rule = lol_get( frame->args, 3 )->string;        

   PyObject *pName, *pModule, *pDict, *pFunc;

   if (first_time)
   {
       /* At the first invocation, we add the value of the
          global EXTRA_PYTHONPATH to the sys.path Python
          variable.
       */
       LIST* extra = 0;
       module_t* outer_module = frame->module;

       first_time = 0;

       if ( outer_module != root_module())
       {
           exit_module( outer_module );
           enter_module( root_module());
       }
    
       extra = var_get("EXTRA_PYTHONPATH");
    
       if ( outer_module != root_module())
       {
            exit_module( root_module());
            enter_module( outer_module );
       }

       for(; extra; extra = extra->next)
       {
           string buf[1];
           string_new(buf);
           string_append(buf, "import sys\nsys.path.append(\"");
           string_append(buf, extra->string);
           string_append(buf, "\")\n");
           PyRun_SimpleString(buf->value);   
           string_free(buf);               
       }       
   }


   pName = PyString_FromString(python_module);
   
   pModule = PyImport_Import(pName);
   Py_DECREF(pName);

   if (pModule != NULL) {
        pDict = PyModule_GetDict(pModule);
        pFunc = PyDict_GetItemString(pDict, python_function);

        if (pFunc && PyCallable_Check(pFunc)) {

            module_t* m = bindmodule(jam_module);
            RULE* r = bindrule( jam_rule, m );

            /* Make pFunc owned */
            Py_INCREF(pFunc);

            r->python_function = pFunc;
        }
        else {
            if (PyErr_Occurred())
                PyErr_Print();
            fprintf(stderr, "Cannot find function \"%s\"\n", python_function);
        }
        Py_DECREF(pModule);
    }
    else {
        PyErr_Print();
        fprintf(stderr, "Failed to load \"%s\"\n", python_module);
    }
   return L0;

}

#endif

void lol_build( LOL* lol, char** elements )
{
    LIST* l = L0;
    lol_init( lol );
    
    while ( elements && *elements )
    {
        if ( !strcmp( *elements, ":" ) )
        {
            lol_add( lol, l );
            l = L0 ;
        }
        else
        {
            l = list_new( l, newstr( *elements ) );
        }
        ++elements;
    }
    
    if ( l != L0 )
        lol_add( lol, l );
}

#ifdef HAVE_PYTHON

/** Calls the bjam rule specified by name passed in 'args'.
    The name is looked up in context of bjam's 'python_interface'
    module. Returns the list of string retured by the rule.
*/
PyObject*
bjam_call(PyObject* self, PyObject* args)
{
    FRAME       inner[1];
    LIST    *result;
    PARSE   *p;
    char*  rulename;
    
    /* Build up the list of arg lists */

    frame_init( inner );
    inner->prev = 0;
    inner->prev_user = 0;
    inner->module = bindmodule("python_interface");
    inner->procedure = 0;

    /* Extract the rule name and arguments from 'args' */

    /* PyTuple_GetItem returns borrowed reference */
    rulename = PyString_AsString(PyTuple_GetItem(args, 0));
    {
        int i = 1;
        int size = PyTuple_Size(args);
        for( ; i < size; ++i) {
            PyObject* a = PyTuple_GetItem(args, i);
            if (PyString_Check(a))
            {
                lol_add(inner->args, 
                        list_new(0, newstr(PyString_AsString(a))));
            }
            else if (PySequence_Check(a))
            {
                LIST* l = 0;
                int s = PySequence_Size(a);
                int i = 0;
                for(; i < s; ++i)
                {
                    /* PySequence_GetItem returns new reference. */
                    PyObject* e = PySequence_GetItem(a, i);
                    l = list_new(l, newstr(PyString_AsString(e)));
                    Py_DECREF(e);
                }
                lol_add(inner->args, l);
            }                
        }
    }

    result = evaluate_rule( rulename, inner );

    frame_free( inner );
}

/** Accepts three arguments: module name, rule name and Python callable.

    Creates bjam rule with the specified name in the specified module,
    which will invoke the Python callable.
*/
PyObject*
bjam_import_rule(PyObject* self, PyObject* args)
{
    char* module;
    char* rule;
    PyObject* func;
    module_t* m;
    RULE* r;

    if (!PyArg_ParseTuple(args, "ssO:import_rule", &module, &rule, &func))
        return NULL;
    
    if (!PyCallable_Check(func))
        return NULL;
    
    m = bindmodule(module);
    r = bindrule(rule, m);

    /* Make pFunc owned */
    Py_INCREF(func);

    r->python_function = func;
    return Py_None;
}

#endif

#ifdef HAVE_POPEN
#if defined(_MSC_VER) || defined(__BORLANDC__)
    #define popen _popen
    #define pclose _pclose
#endif

LIST *builtin_shell( PARSE *parse, FRAME *frame )
{
    LIST* arg = lol_get( frame->args, 0 );
    LIST* result = 0; 
    string s;
    int ret;
    char buffer[1024];
    FILE *p = NULL;

    string_new( &s );

    fflush(NULL);

    p = popen(arg->string, "r");
    if ( p == NULL )
        return L0;

    while ( (ret = fread(buffer, sizeof(char), sizeof(buffer)-1, p)) > 0 )
    {
        buffer[ret+1] = 0;
        string_append( &s, buffer );
    }

    pclose(p);

    result = list_new( L0, newstr(s.value) );
    string_free(&s);
    return result;
}

#else

LIST *builtin_shell( PARSE *parse, FRAME *frame )
{
    return L0;
}

#endif

⌨️ 快捷键说明

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