コード例 #1
0
ファイル: complex.c プロジェクト: plicease/FFI-Platypus
void
ffi_pl_complex_float_to_perl(SV *sv, float *ptr)
{
  if(SvOK(sv) && sv_isobject(sv) && sv_derived_from(sv, "Math::Complex"))
  {
    /* the complex variable is a Math::Complex object */
    set(sv, sv_2mortal(newSVnv(ptr[0])), 0);
    set(sv, sv_2mortal(newSVnv(ptr[1])), 1);    
  }
  else if(SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVAV)
  {
    /* the compex variable is already an array */
    AV *av = (AV*) SvRV(sv);
    av_store(av, 0, newSVnv(ptr[0]));
    av_store(av, 1, newSVnv(ptr[1]));
  }
  else
  {
    /* the complex variable is something else and an array needs to be created */
    SV *values[2];
    AV *av;
    values[0] = newSVnv(ptr[0]);
    values[1] = newSVnv(ptr[1]);
    av = av_make(2, values);
    sv_setsv(sv, newRV_noinc((SV*)av));
  }
}
コード例 #2
0
ファイル: call.C プロジェクト: Gustra/libperl--
const Array::Temp Call_stack::unpack(const Raw_string pattern, const Raw_string value) {
    prepare_call();
    int count = unpackstring(const_cast<char*>(pattern.value), const_cast<char*>(pattern.value + pattern.length), const_cast<char*>(value.value), const_cast<char*>(value.value + value.length), value.utf8 && !IN_BYTES ? FLAG_UNPACK_DO_UTF8 : 0);
    finish_call();
    return Array::Temp(interp, av_make(count, SP - count + 1), true);
}
コード例 #3
0
ファイル: PJS_Call.c プロジェクト: gitpan/JSPL
PJS_EXTERN JSBool
PJS_Call_sv_with_jsvals_rsv(
    pTHX_
    JSContext *cx,
    JSObject *obj,
    SV *code,
    SV *caller, /* Will be disposed inside */
    uintN argc,
    jsval *argv,
    SV **rsv,
    I32 flag
) {
    dSP;
    JSBool ok = JS_TRUE;
    uintN arg;
    I32 rcount = caller ? 1 : 0;
    PJS_Context *pcx = PJS_GET_CONTEXT(cx);
    
    if(SvROK(code) && SvTYPE(SvRV(code)) == SVt_PVCV) {
        ENTER; SAVETMPS;
        PUSHMARK(SP) ;

	sv_setiv(save_scalar(PJS_Context_SV), PTR2IV(pcx));
	
	EXTEND(SP, argc + rcount);
	PUTBACK;
        
	/* From here we are working with the global stack,
	 * a) at PUSH time we can fail, so we need to abort the call
	 * b) Want to avoid copying local <=> global SP at every single PUSH
	 *
	 * Before 'call_sv', rcount is the number of SVs pushed so far
	 */
        if(caller) *++PL_stack_sp = sv_2mortal(caller);

	if(argv && !(flag & G_NOARGS)) {
	    /* HACK: We use G_NOARGS as a guard against use argv[-1] to get This.
	     * Needed for the use in PJS_invoke_perl_property_setter where given
	     * argc is faked
	     */
	    SV *This;
	    ok = PJS_ReflectJS2Perl(aTHX_ cx, argv[-1], &This, 0);
	    if(ok) sv_setsv(save_scalar(PJS_This), sv_2mortal(This));
	    else goto forget;
	}
	else flag &= ~G_NOARGS;

        for(arg = 0; arg < argc; arg++) {
            SV *sv;
            ok = PJS_ReflectJS2Perl(aTHX_ cx, argv[arg], &sv, 1);
            if(!ok) {
		rcount += arg;
                goto forget;
	    }
	    *++PL_stack_sp = sv_2mortal(sv);
        }
        
        rcount = call_sv(code, flag | G_EVAL);

	if(rsv) {
	    if(flag == G_SCALAR || rcount == 1)
		*rsv = SvREFCNT_inc_simple_NN(*PL_stack_sp);
	    else
		*rsv = newRV((SV *)av_make(rcount, PL_stack_sp-rcount+1));

	    SAVEMORTALIZESV(*rsv);
	}

	forget:
	PL_stack_sp -= rcount;
        FREETMPS; LEAVE;

        if(ok && SvTRUE(ERRSV)) {
	    propagate2JS(aTHX_ pcx, obj);
	    ok = JS_FALSE;
        }
    }
    else croak("Not a coderef");
    return ok;
}
コード例 #4
0
ファイル: call.C プロジェクト: Gustra/libperl--
AV* Call_stack::pop_array(int count) {
    AV* ret = av_make(count, SP - count + 1);
    SP -= count;
    return ret;
}
コード例 #5
0
SV *ngx_http_psgi_create_env(pTHX_ ngx_http_request_t *r, char *app)
{
    ngx_list_part_t        *part;
    ngx_table_elt_t        *h;
    ngx_uint_t              i, c, x;


    SV  *_version[2];
    AV  *version;

    HV* env = newHV();

    /* PSGI version 1.0, arrayref [1,0] */
    _version[0] = newSViv(1);
    _version[1] = newSViv(0);

    version = av_make(2, _version);
    SvREFCNT_dec(_version[0]);
    SvREFCNT_dec(_version[1]);

    hv_store(env, "psgi.version", sizeof("psgi.version")-1, newRV_noinc((SV*)version), 0);

    /* FIXME: after any of this two operations $! is set to 'Inappropriate ioctl for device' */
    SV *errors_h = PerlIONginxError_newhandle(aTHX_ r);
    if (errors_h == NULL)
        return NULL;
    hv_store(env, "psgi.errors", sizeof("psgi.errors")-1, errors_h, 0);

    SV *input_h = PerlIONginxInput_newhandle(aTHX_ r);
    if (input_h == NULL)
        return NULL;
    hv_store(env, "psgi.input", sizeof("psgi.input")-1, input_h, 0);

    /* Detect scheme.
     * TODO: Check if only http and https schemes allowed here. What about ws and others?
     * FIXME: mb nginx should parse scheme in safe way: [a-z][a-z0-9\=\0\.]* allowed to be valid scheme (rfc3986)
     * but nginx allows only [a-z]+
     */
#if (NGX_HTTP_SSL)
    char *scheme;
    if (r->connection->ssl) {
        scheme = "https";
    } else {
        scheme = "http";
    }
    hv_store(env, "psgi.url_scheme", sizeof("psgi.url_scheme")-1, newSVpv(scheme, 0), 0);
#else
    hv_store(env, "psgi.url_scheme", sizeof("psgi.url_scheme")-1, newSVpv("http", 0), 0);
#endif

    // Buffered body in file
    if (r->request_body != NULL && r->request_body->temp_file != NULL) {
        hv_store(env, "psgix.input.buffered", sizeof("psgix.input.buffered")-1, newSViv(1), 0);
    }

    /* port defined in first line of HTTP request and parsed by nginx */
    if (r->port_start) {
        STRLEN port_len = r->port_end - r->port_start;
        hv_store(env, "SERVER_PORT", sizeof("SERVER_PORT")-1, newSVpv((char *)r->port_start, port_len), 0);
    } else {
        /* copypasted from ngx_http_variables.c: get port from nginx conf  */
        /* TODO: Maybe reuse code from ngx_http_variables.c is a good idea? */
        ngx_uint_t            port;
        struct sockaddr_in   *sin;
#if (NGX_HAVE_INET6)
        struct sockaddr_in6  *sin6;
#endif
        u_char *strport;

        if (ngx_connection_local_sockaddr(r->connection, NULL, 0) != NGX_OK) {
            // TODO: Throw error
            return NULL;
        }

        strport = ngx_pnalloc(r->pool, sizeof("65535") - 1);
        if (strport == NULL) {
            return NULL;
        }

        switch (r->connection->local_sockaddr->sa_family) {

#if (NGX_HAVE_INET6)
            case AF_INET6:
                sin6 = (struct sockaddr_in6 *) r->connection->local_sockaddr;
                port = ntohs(sin6->sin6_port);
                break;
#endif

            default: /* AF_INET */
                sin = (struct sockaddr_in *) r->connection->local_sockaddr;
                port = ntohs(sin->sin_port);
                break;
        }

        if (port > 0 && port < 65536) {
            hv_store(env, "SERVER_PORT", sizeof("SERVER_PORT")-1, newSVuv(port), 0);
        } else {
            hv_store(env, "SERVER_PORT", sizeof("SERVER_PORT")-1, newSVpv("", 0), 0);
        }
    }
    hv_store(env, "SERVER_PROTOCOL", sizeof("SERVER_PROTOCOL")-1, newSVpv((char *)r->http_protocol.data, r->http_protocol.len), 0);

    if (r->headers_in.content_length_n != -1) {
        hv_store(env, "CONTENT_LENGTH", sizeof("CONTENT_LENGTH")-1, newSViv(r->headers_in.content_length_n), 0);
    }

    if (r->headers_in.content_type != NULL) {
        hv_store(env, "CONTENT_TYPE", sizeof("CONTENT_TYPE")-1, 
                newSVpv((char*)r->headers_in.content_type->value.data, r->headers_in.content_type->value.len), 0);
    }

    hv_store(env, "REQUEST_URI", sizeof("REQUEST_URI")-1, newSVpv((char *)r->unparsed_uri.data, r->unparsed_uri.len), 0);

    /* TODO: SCRIPT_NAME should be string matched by 'location' value in nginx.conf */
    hv_store(env, "SCRIPT_NAME", sizeof("SCRIPT_NAME")-1, newSVpv("", 0), 0);

    /* FIXME:
     * PATH_INFO should be relative to SCRIPT_NAME (current 'location') path in nginx.conf
     * How to achieve this? Should I allow psgi only in 'exact match' locations?
     * It would be hard to find PATH_INFO for locations like "location ~ /(foo|bar)/.* { }". Or it wouldn't?
     */
    hv_store(env, "PATH_INFO", sizeof("PATH_INFO")-1, newSVpv((char *)r->uri.data, r->uri.len), 0);
    hv_store(env, "REQUEST_METHOD", sizeof("REQUEST_METHOD")-1, newSVpv((char *)r->method_name.data, r->method_name.len), 0);
    if (r->args.len > 0) {
        hv_store(env, "QUERY_STRING", sizeof("QUERY_STRING")-1, newSVpv((char *)r->args.data, r->args.len), 0);
    } else {
        hv_store(env, "QUERY_STRING", sizeof("QUERY_STRING")-1, newSVpv("", 0), 0);
    }

    if (r->host_start && r->host_end) {
        hv_store(env, "SERVER_NAME", sizeof("SERVER_NAME")-1, newSVpv((char *)r->host_start, r->host_end - r->host_start), 0);
    } else {
        ngx_http_core_srv_conf_t  *cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
        hv_store(env, "SERVER_NAME", sizeof("SERVER_NAME")-1, newSVpv((char *)cscf->server_name.data, cscf->server_name.len), 0);
    }

    hv_store(env, "REMOTE_ADDR", sizeof("REMOTE_ADDR")-1, newSVpv((char *)r->connection->addr_text.data, r->connection->addr_text.len), 0);
    /* TODO
     *
     * psgi.multithread
     * psgi.multiprocess
     */

    part = &r->headers_in.headers.part;
    h = part->elts;

    c = 0;
    for (i = 0; /* void */ ; i++) {
        ngx_str_t  name;
        u_char *p;
        if (i >= part->nelts) {
            if (part->next == NULL) {
                break;
            }

            part = part->next;
            h = part->elts;
            i = 0;
        }

        /* The environment MUST NOT contain keys named HTTP_CONTENT_TYPE or HTTP_CONTENT_LENGTH.
         * PSGI 1.09_3
         */
        if (ngx_strncasecmp(h[i].key.data, (u_char*)"CONTENT-LENGTH", h[i].key.len) == 0) {
            continue;
        }

        if (ngx_strncasecmp(h[i].key.data, (u_char*)"CONTENT-TYPE", h[i].key.len) == 0) {
            continue;
        }

        p = ngx_pnalloc(r->pool, sizeof("HTTP_") - 1 + h[i].key.len);

        if (p == NULL) {
            return NULL;
        }

        name.data = p;
        name.len = sizeof("HTTP_") + h[i].key.len -1 ;

        p = ngx_copy(p, (u_char*)"HTTP_", sizeof("HTTP_")-1);
        p = ngx_copy(p, h[i].key.data, h[i].key.len );

        ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                "Set env header: '%s' => '%s'",
                h[i].key.data, h[i].value.data);

        x = h[i].key.len + sizeof("HTTP_");
        while (x > 0) {
            if (name.data[x] == '-') {
                name.data[x] = '_';
            } else {
                name.data[x] = ngx_toupper(name.data[x]);
            }
            x--;
        }
        SV **exists = hv_fetch(env, (char*)name.data, name.len, 0);
        if (exists == NULL) {
            hv_store(env, (char *)name.data, name.len, newSVpv((char *)h[i].value.data, h[i].value.len), 0);
        } else {
            /* join ',', @values;
             * FIXME: Can I do this better
             */
            SV *newval = newSVpvf("%s,%s", SvPV_nolen(*exists), h[i].value.data);
            hv_store(env, (char *)name.data, name.len, newval, 0);
        }
        c += 2;
    }

    return newRV_noinc((SV*)env);
}