diff options
author | marha <marha@users.sourceforge.net> | 2012-10-08 09:06:44 +0200 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2012-10-08 09:06:44 +0200 |
commit | 9b15e1cfe4c6ca9862c2865c4adbc21a758e9734 (patch) | |
tree | 13452621f70604f08fd91b1bd46ed6341dbc2ea7 /xorg-server/hw/kdrive | |
parent | bd13c464f728719fceb8a4918b52727ec125ea6e (diff) | |
parent | de8397bc3d010bba24ec0c4d2e6249a769a86fc7 (diff) | |
download | vcxsrv-9b15e1cfe4c6ca9862c2865c4adbc21a758e9734.tar.gz vcxsrv-9b15e1cfe4c6ca9862c2865c4adbc21a758e9734.tar.bz2 vcxsrv-9b15e1cfe4c6ca9862c2865c4adbc21a758e9734.zip |
Merge remote-tracking branch 'origin/released'
* origin/released:
pixman libxcb mesa xserver xkeyboard-config git update 8 oct 2012
Conflicts:
xorg-server/Xext/xf86bigfont.c
xorg-server/dix/dispatch.c
xorg-server/include/dixstruct.h
xorg-server/os/connection.c
Diffstat (limited to 'xorg-server/hw/kdrive')
-rw-r--r-- | xorg-server/hw/kdrive/ephyr/ephyrdriext.c | 4 | ||||
-rw-r--r-- | xorg-server/hw/kdrive/ephyr/ephyrglxext.c | 179 | ||||
-rw-r--r-- | xorg-server/hw/kdrive/ephyr/ephyrhostglx.c | 121 | ||||
-rw-r--r-- | xorg-server/hw/kdrive/ephyr/ephyrhostglx.h | 9 | ||||
-rw-r--r-- | xorg-server/hw/kdrive/src/kinput.c | 2 |
5 files changed, 264 insertions, 51 deletions
diff --git a/xorg-server/hw/kdrive/ephyr/ephyrdriext.c b/xorg-server/hw/kdrive/ephyr/ephyrdriext.c index a42be07d5..1a98a2dff 100644 --- a/xorg-server/hw/kdrive/ephyr/ephyrdriext.c +++ b/xorg-server/hw/kdrive/ephyr/ephyrdriext.c @@ -561,7 +561,7 @@ ProcXF86DRIQueryDirectRenderingCapable(register ClientPtr client) return BadValue; } - if (!LocalClient(client) || client->swapped) + if (!client->local || client->swapped) isCapable = 0; rep = (xXF86DRIQueryDirectRenderingCapableReply) { @@ -1229,7 +1229,7 @@ ProcXF86DRIDispatch(register ClientPtr client) } } - if (!LocalClient(client)) + if (!client->local) return DRIErrorBase + XF86DRIClientNotLocal; switch (stuff->data) { diff --git a/xorg-server/hw/kdrive/ephyr/ephyrglxext.c b/xorg-server/hw/kdrive/ephyr/ephyrglxext.c index df285cfcb..22d510891 100644 --- a/xorg-server/hw/kdrive/ephyr/ephyrglxext.c +++ b/xorg-server/hw/kdrive/ephyr/ephyrglxext.c @@ -61,10 +61,16 @@ int ephyrGLXGetFBConfigsSGIX(__GLXclientState * a_cl, GLbyte * a_pc); int ephyrGLXGetFBConfigsSGIXSwap(__GLXclientState * a_cl, GLbyte * a_pc); int ephyrGLXCreateContext(__GLXclientState * a_cl, GLbyte * a_pc); int ephyrGLXCreateContextSwap(__GLXclientState * a_cl, GLbyte * a_pc); +int ephyrGLXCreateNewContext(__GLXclientState * a_cl, GLbyte * a_pc); +int ephyrGLXCreateNewContextSwap(__GLXclientState * a_cl, GLbyte * a_pc); int ephyrGLXDestroyContext(__GLXclientState * a_cl, GLbyte * a_pc); int ephyrGLXDestroyContextSwap(__GLXclientState * a_cl, GLbyte * a_pc); int ephyrGLXMakeCurrent(__GLXclientState * a_cl, GLbyte * a_pc); int ephyrGLXMakeCurrentSwap(__GLXclientState * a_cl, GLbyte * a_pc); +int ephyrGLXMakeCurrentReadSGI(__GLXclientState * a_cl, GLbyte * a_pc); +int ephyrGLXMakeCurrentReadSGISwap(__GLXclientState * a_cl, GLbyte * a_pc); +int ephyrGLXMakeContextCurrent(__GLXclientState * a_cl, GLbyte * a_pc); +int ephyrGLXMakeContextCurrentSwap(__GLXclientState * a_cl, GLbyte * a_pc); int ephyrGLXGetString(__GLXclientState * a_cl, GLbyte * a_pc); int ephyrGLXGetStringSwap(__GLXclientState * a_cl, GLbyte * a_pc); int ephyrGLXGetIntegerv(__GLXclientState * a_cl, GLbyte * a_pc); @@ -108,6 +114,9 @@ ephyrHijackGLXExtension(void) dispatch_functions[X_GLXCreateContext][0] = ephyrGLXCreateContext; dispatch_functions[X_GLXCreateContext][1] = ephyrGLXCreateContextSwap; + dispatch_functions[X_GLXCreateNewContext][0] = ephyrGLXCreateNewContext; + dispatch_functions[X_GLXCreateNewContext][1] = ephyrGLXCreateNewContextSwap; + dispatch_functions[X_GLXDestroyContext][0] = ephyrGLXDestroyContext; dispatch_functions[X_GLXDestroyContext][1] = ephyrGLXDestroyContextSwap; @@ -123,14 +132,24 @@ ephyrHijackGLXExtension(void) dispatch_functions[61][0] = ephyrGLXGetIntegerv; dispatch_functions[61][1] = ephyrGLXGetIntegervSwap; + dispatch_functions[X_GLXMakeContextCurrent][0] = + ephyrGLXMakeContextCurrent; + dispatch_functions[X_GLXMakeContextCurrent][1] = + ephyrGLXMakeContextCurrentSwap; + /* * hijack some vendor priv entry point dispatch functions */ dispatch_functions = VendorPriv_dispatch_info.dispatch_functions; dispatch_functions[92][0] = ephyrGLXGetFBConfigsSGIX; dispatch_functions[92][1] = ephyrGLXGetFBConfigsSGIXSwap; + + dispatch_functions[89][0] = ephyrGLXMakeCurrentReadSGI; + dispatch_functions[89][1] = ephyrGLXMakeCurrentReadSGISwap; + EPHYR_LOG("hijacked glx entry points to forward requests to host X\n"); + return TRUE; } @@ -445,7 +464,8 @@ ephyrGLXCreateContextReal(xGLXCreateContextReq * a_req, Bool a_do_swap) if (!ephyrHostGLXCreateContext(a_req->screen, host_w_attrs.visualid, a_req->context, - a_req->shareList, a_req->isDirect)) { + a_req->shareList, 0, + a_req->isDirect, X_GLXCreateContext)) { EPHYR_LOG_ERROR("ephyrHostGLXCreateContext() failed\n"); goto out; } @@ -455,6 +475,45 @@ ephyrGLXCreateContextReal(xGLXCreateContextReq * a_req, Bool a_do_swap) return res; } +static int +ephyrGLXCreateNewContextReal(xGLXCreateNewContextReq * a_req, Bool a_do_swap) +{ + int res = BadImplementation; + + __GLX_DECLARE_SWAP_VARIABLES; + + EPHYR_RETURN_VAL_IF_FAIL(a_req, BadValue); + EPHYR_LOG("enter\n"); + + if (a_do_swap) { + __GLX_SWAP_SHORT(&a_req->length); + __GLX_SWAP_INT(&a_req->context); + __GLX_SWAP_INT(&a_req->fbconfig); + __GLX_SWAP_INT(&a_req->screen); + __GLX_SWAP_INT(&a_req->renderType); + __GLX_SWAP_INT(&a_req->shareList); + } + + EPHYR_LOG("context creation requested. localid:%d, " + "screen:%d, fbconfig:%d, renderType:%d, direct:%d\n", + (int) a_req->context, (int) a_req->screen, + (int) a_req->fbconfig, (int) a_req->renderType, + (int) a_req->isDirect); + + if (!ephyrHostGLXCreateContext(a_req->screen, + a_req->fbconfig, + a_req->context, + a_req->shareList, a_req->renderType, + a_req->isDirect, X_GLXCreateNewContext)) { + EPHYR_LOG_ERROR("ephyrHostGLXCreateNewContext() failed\n"); + goto out; + } + res = Success; + out: + EPHYR_LOG("leave\n"); + return res; +} + int ephyrGLXCreateContext(__GLXclientState * cl, GLbyte * pc) { @@ -471,6 +530,22 @@ ephyrGLXCreateContextSwap(__GLXclientState * cl, GLbyte * pc) return ephyrGLXCreateContextReal(req, TRUE); } +int +ephyrGLXCreateNewContext(__GLXclientState * cl, GLbyte * pc) +{ + xGLXCreateNewContextReq *req = (xGLXCreateNewContextReq *) pc; + + return ephyrGLXCreateNewContextReal(req, FALSE); +} + +int +ephyrGLXCreateNewContextSwap(__GLXclientState * cl, GLbyte * pc) +{ + xGLXCreateNewContextReq *req = (xGLXCreateNewContextReq *) pc; + + return ephyrGLXCreateNewContextReal(req, TRUE); +} + static int ephyrGLXDestroyContextReal(__GLXclientState * a_cl, GLbyte * a_pc, Bool a_do_swap) @@ -505,26 +580,34 @@ ephyrGLXDestroyContextSwap(__GLXclientState * a_cl, GLbyte * a_pc) } static int -ephyrGLXMakeCurrentReal(__GLXclientState * a_cl, GLbyte * a_pc, Bool a_do_swap) +ephyrGLXMakeCurrentReal(__GLXclientState * a_cl, GLXDrawable write, + GLXDrawable read, GLXContextTag ctx, + GLXContextTag old_ctx, Bool a_do_swap) { int res = BadImplementation; - xGLXMakeCurrentReq *req = (xGLXMakeCurrentReq *) a_pc; xGLXMakeCurrentReply reply; - DrawablePtr drawable = NULL; - GLXContextTag contextTag = 0; - int rc = 0; + DrawablePtr drawableR = NULL, drawableW = NULL; + GLXContextTag new_ctx = 0; EPHYR_LOG("enter\n"); - rc = dixLookupDrawable(&drawable, - req->drawable, a_cl->client, 0, DixReadAccess); - EPHYR_RETURN_VAL_IF_FAIL(drawable, BadValue); - EPHYR_RETURN_VAL_IF_FAIL(drawable->pScreen, BadValue); - EPHYR_LOG("screen nummber requested:%d\n", drawable->pScreen->myNum); - - if (!ephyrHostGLXMakeCurrent(hostx_get_window(drawable->pScreen->myNum), - req->context, - req->oldContextTag, - (int *) &contextTag)) { + res = dixLookupDrawable(&drawableW, write, a_cl->client, 0, DixReadAccess); + EPHYR_RETURN_VAL_IF_FAIL(drawableW, BadValue); + EPHYR_RETURN_VAL_IF_FAIL(drawableW->pScreen, BadValue); + EPHYR_LOG("screen nummber requested:%d\n", drawableW->pScreen->myNum); + + if (read != write) { + res = dixLookupDrawable(&drawableR, read, a_cl->client, 0, + DixReadAccess); + EPHYR_RETURN_VAL_IF_FAIL(drawableR, BadValue); + EPHYR_RETURN_VAL_IF_FAIL(drawableR->pScreen, BadValue); + } + else { + drawableR = drawableW; + } + + if (!ephyrHostGLXMakeCurrent(hostx_get_window(drawableW->pScreen->myNum), + hostx_get_window(drawableR->pScreen->myNum), + ctx, old_ctx, (int *) &new_ctx)) { EPHYR_LOG_ERROR("ephyrHostGLXMakeCurrent() failed\n"); goto out; } @@ -532,7 +615,7 @@ ephyrGLXMakeCurrentReal(__GLXclientState * a_cl, GLbyte * a_pc, Bool a_do_swap) .type = X_Reply, .sequenceNumber = a_cl->client->sequence, .length = 0, - .contextTag = contextTag + .contextTag = new_ctx }; if (a_do_swap) { __GLX_DECLARE_SWAP_VARIABLES; @@ -551,13 +634,71 @@ ephyrGLXMakeCurrentReal(__GLXclientState * a_cl, GLbyte * a_pc, Bool a_do_swap) int ephyrGLXMakeCurrent(__GLXclientState * a_cl, GLbyte * a_pc) { - return ephyrGLXMakeCurrentReal(a_cl, a_pc, FALSE); + xGLXMakeCurrentReq *req = (xGLXMakeCurrentReq *) a_pc; + return ephyrGLXMakeCurrentReal(a_cl, req->drawable, req->drawable, + req->context, req->oldContextTag, FALSE); } int ephyrGLXMakeCurrentSwap(__GLXclientState * a_cl, GLbyte * a_pc) { - return ephyrGLXMakeCurrentReal(a_cl, a_pc, TRUE); + xGLXMakeCurrentReq *req = (xGLXMakeCurrentReq *) a_pc; + __GLX_DECLARE_SWAP_VARIABLES; + + __GLX_SWAP_INT(&req->drawable); + __GLX_SWAP_INT(&req->context); + __GLX_SWAP_INT(&req->oldContextTag); + + return ephyrGLXMakeCurrentReal(a_cl, req->drawable, req->drawable, + req->context, req->oldContextTag, TRUE); +} + +int +ephyrGLXMakeCurrentReadSGI(__GLXclientState * a_cl, GLbyte * a_pc) +{ + xGLXMakeCurrentReadSGIReq *req = (xGLXMakeCurrentReadSGIReq *) a_pc; + + return ephyrGLXMakeCurrentReal(a_cl, req->drawable, req->readable, + req->context, req->oldContextTag, FALSE); +} + +int +ephyrGLXMakeCurrentReadSGISwap(__GLXclientState * a_cl, GLbyte * a_pc) +{ + xGLXMakeCurrentReadSGIReq *req = (xGLXMakeCurrentReadSGIReq *) a_pc; + __GLX_DECLARE_SWAP_VARIABLES; + + __GLX_SWAP_INT(&req->drawable); + __GLX_SWAP_INT(&req->readable); + __GLX_SWAP_INT(&req->context); + __GLX_SWAP_INT(&req->oldContextTag); + + return ephyrGLXMakeCurrentReal(a_cl, req->drawable, req->readable, + req->context, req->oldContextTag, TRUE); +} + +int +ephyrGLXMakeContextCurrent(__GLXclientState * a_cl, GLbyte * a_pc) +{ + xGLXMakeContextCurrentReq *req = (xGLXMakeContextCurrentReq *) a_pc; + + return ephyrGLXMakeCurrentReal(a_cl, req->drawable, req->readdrawable, + req->context, req->oldContextTag, FALSE); +} + +int +ephyrGLXMakeContextCurrentSwap(__GLXclientState * a_cl, GLbyte * a_pc) +{ + xGLXMakeContextCurrentReq *req = (xGLXMakeContextCurrentReq *) a_pc; + __GLX_DECLARE_SWAP_VARIABLES; + + __GLX_SWAP_INT(&req->drawable); + __GLX_SWAP_INT(&req->readdrawable); + __GLX_SWAP_INT(&req->context); + __GLX_SWAP_INT(&req->oldContextTag); + + return ephyrGLXMakeCurrentReal(a_cl, req->drawable, req->readdrawable, + req->context, req->oldContextTag, TRUE); } static int diff --git a/xorg-server/hw/kdrive/ephyr/ephyrhostglx.c b/xorg-server/hw/kdrive/ephyr/ephyrhostglx.c index 6b9da6fb1..392489a00 100644 --- a/xorg-server/hw/kdrive/ephyr/ephyrhostglx.c +++ b/xorg-server/hw/kdrive/ephyr/ephyrhostglx.c @@ -52,6 +52,8 @@ #include "ephyrlog.h" #include "hostx.h" +static int glx_major, glx_minor; + enum VisualConfRequestType { EPHYR_GET_FB_CONFIG, EPHYR_VENDOR_PRIV_GET_FB_CONFIG_SGIX, @@ -99,6 +101,12 @@ ephyrHostGLXQueryVersion(int *a_major, int *a_minor) EPHYR_RETURN_VAL_IF_FAIL(a_major && a_minor, FALSE); EPHYR_LOG("enter\n"); + if (glx_major) { + *a_major = glx_major; + *a_minor = glx_minor; + return TRUE; + } + if (!ephyrHostGLXGetMajorOpcode(&major_opcode)) { EPHYR_LOG_ERROR("failed to get major opcode\n"); goto out; @@ -117,8 +125,8 @@ ephyrHostGLXQueryVersion(int *a_major, int *a_minor) UnlockDisplay(dpy); SyncHandle(); - *a_major = reply.majorVersion; - *a_minor = reply.minorVersion; + *a_major = glx_major = reply.majorVersion; + *a_minor = glx_minor = reply.minorVersion; EPHYR_LOG("major:%d, minor:%d\n", *a_major, *a_minor); @@ -431,17 +439,20 @@ ephyrHostGLXSendClientInfo(int32_t a_major, int32_t a_minor, Bool ephyrHostGLXCreateContext(int a_screen, - int a_visual_id, + int a_generic_id, int a_context_id, - int a_share_list_ctxt_id, Bool a_direct) + int a_share_list_ctxt_id, + int a_render_type, + Bool a_direct, + int code) { Bool is_ok = FALSE; Display *dpy = hostx_get_display(); int major_opcode = 0, remote_context_id = 0; - xGLXCreateContextReq *req; - EPHYR_LOG("enter. screen:%d, visual:%d, contextid:%d, direct:%d\n", - a_screen, a_visual_id, a_context_id, a_direct); + EPHYR_LOG("enter. screen:%d, generic_id:%d, contextid:%d, rendertype:%d, " + "direct:%d\n", a_screen, a_generic_id, a_context_id, + a_render_type, a_direct); if (!hostx_allocate_resource_id_peer(a_context_id, &remote_context_id)) { EPHYR_LOG_ERROR("failed to peer the context id %d host X", @@ -456,15 +467,38 @@ ephyrHostGLXCreateContext(int a_screen, LockDisplay(dpy); - /* Send the glXCreateContext request */ - GetReq(GLXCreateContext, req); - req->reqType = major_opcode; - req->glxCode = X_GLXCreateContext; - req->context = remote_context_id; - req->visual = a_visual_id; - req->screen = DefaultScreen(dpy); - req->shareList = a_share_list_ctxt_id; - req->isDirect = a_direct; + switch (code) { + case X_GLXCreateContext: { + /* Send the glXCreateContext request */ + xGLXCreateContextReq *req; + GetReq(GLXCreateContext, req); + req->reqType = major_opcode; + req->glxCode = X_GLXCreateContext; + req->context = remote_context_id; + req->visual = a_generic_id; + req->screen = DefaultScreen(dpy); + req->shareList = a_share_list_ctxt_id; + req->isDirect = a_direct; + } + + case X_GLXCreateNewContext: { + /* Send the glXCreateNewContext request */ + xGLXCreateNewContextReq *req; + GetReq(GLXCreateNewContext, req); + req->reqType = major_opcode; + req->glxCode = X_GLXCreateNewContext; + req->context = remote_context_id; + req->fbconfig = a_generic_id; + req->screen = DefaultScreen(dpy); + req->renderType = a_render_type; + req->shareList = a_share_list_ctxt_id; + req->isDirect = a_direct; + } + + default: + /* This should never be reached !*/ + EPHYR_LOG("Internal error! Invalid CreateContext code!\n"); + } UnlockDisplay(dpy); SyncHandle(); @@ -512,20 +546,19 @@ ephyrHostDestroyContext(int a_ctxt_id) } Bool -ephyrHostGLXMakeCurrent(int a_drawable, +ephyrHostGLXMakeCurrent(int a_drawable, int a_readable, int a_glx_ctxt_id, int a_old_ctxt_tag, int *a_ctxt_tag) { Bool is_ok = FALSE; Display *dpy = hostx_get_display(); int32_t major_opcode = 0; int remote_glx_ctxt_id = 0; - xGLXMakeCurrentReq *req; xGLXMakeCurrentReply reply; EPHYR_RETURN_VAL_IF_FAIL(a_ctxt_tag, FALSE); - EPHYR_LOG("enter. drawable:%d, context:%d, oldtag:%d\n", - a_drawable, a_glx_ctxt_id, a_old_ctxt_tag); + EPHYR_LOG("enter. drawable:%d, read:%d, context:%d, oldtag:%d\n", + a_drawable, a_readable, a_glx_ctxt_id, a_old_ctxt_tag); if (!ephyrHostGLXGetMajorOpcode(&major_opcode)) { EPHYR_LOG_ERROR("failed to get major opcode\n"); @@ -538,12 +571,48 @@ ephyrHostGLXMakeCurrent(int a_drawable, LockDisplay(dpy); - GetReq(GLXMakeCurrent, req); - req->reqType = major_opcode; - req->glxCode = X_GLXMakeCurrent; - req->drawable = a_drawable; - req->context = remote_glx_ctxt_id; - req->oldContextTag = a_old_ctxt_tag; + /* If both drawables are the same, use the old MakeCurrent request. + * Otherwise, if we have GLX 1.3 or higher, use the MakeContextCurrent + * request which supports separate read and draw targets. Failing that, + * try the SGI MakeCurrentRead extension. Logic cribbed from Mesa. */ + if (a_drawable == a_readable) { + xGLXMakeCurrentReq *req; + + GetReq(GLXMakeCurrent, req); + req->reqType = major_opcode; + req->glxCode = X_GLXMakeCurrent; + req->drawable = a_drawable; + req->context = remote_glx_ctxt_id; + req->oldContextTag = a_old_ctxt_tag; + } + else if (glx_major > 1 || glx_minor >= 3) { + xGLXMakeContextCurrentReq *req; + + GetReq(GLXMakeContextCurrent, req); + req->reqType = major_opcode; + req->glxCode = X_GLXMakeContextCurrent; + req->drawable = a_drawable; + req->readdrawable = a_readable; + req->context = remote_glx_ctxt_id; + req->oldContextTag = a_old_ctxt_tag; + } + else { + xGLXVendorPrivateWithReplyReq *vpreq; + xGLXMakeCurrentReadSGIReq *req; + + GetReqExtra(GLXVendorPrivateWithReply, + (sz_xGLXMakeCurrentReadSGIReq - + sz_xGLXVendorPrivateWithReplyReq), + vpreq); + req = (xGLXMakeCurrentReadSGIReq *) vpreq; + req->reqType = major_opcode; + req->glxCode = X_GLXVendorPrivateWithReply; + req->vendorCode = X_GLXvop_MakeCurrentReadSGI; + req->drawable = a_drawable; + req->readable = a_readable; + req->context = remote_glx_ctxt_id; + req->oldContextTag = a_old_ctxt_tag; + } memset(&reply, 0, sizeof(reply)); if (!_XReply(dpy, (xReply *) & reply, 0, False)) { diff --git a/xorg-server/hw/kdrive/ephyr/ephyrhostglx.h b/xorg-server/hw/kdrive/ephyr/ephyrhostglx.h index 9c6012070..7ff515dc2 100644 --- a/xorg-server/hw/kdrive/ephyr/ephyrhostglx.h +++ b/xorg-server/hw/kdrive/ephyr/ephyrhostglx.h @@ -55,13 +55,16 @@ Bool ephyrHostGLXGetMajorOpcode(int32_t * a_opcode); Bool ephyrHostGLXSendClientInfo(int32_t a_major, int32_t a_minor, const char *a_extension_list); Bool ephyrHostGLXCreateContext(int a_screen, - int a_visual_id, + int a_generic_id, int a_context_id, - int a_shared_list_ctx_id, Bool a_direct); + int a_share_list_ctxt_id, + int a_render_type, + Bool a_direct, + int code); Bool ephyrHostDestroyContext(int a_ctxt_id); -Bool ephyrHostGLXMakeCurrent(int a_drawable, int a_glx_ctxt_id, +Bool ephyrHostGLXMakeCurrent(int a_drawable, int a_readable, int a_glx_ctxt_id, int a_olg_ctxt_tag, int *a_ctxt_tag); Bool ephyrHostGetIntegerValue(int a_current_context_tag, int a_int, int *a_val); diff --git a/xorg-server/hw/kdrive/src/kinput.c b/xorg-server/hw/kdrive/src/kinput.c index 2a6fec9a7..76424c1c5 100644 --- a/xorg-server/hw/kdrive/src/kinput.c +++ b/xorg-server/hw/kdrive/src/kinput.c @@ -1057,7 +1057,7 @@ KdGetOptions(InputOption **options, char *string) if (strchr(string, '=')) { tam_key = (strchr(string, '=') - string); - key = strndup(string, tam_key + 1); + key = strndup(string, tam_key); if (!key) goto out; |