widl #7: optional and defaultvalue parameters

Huw D M Davies h.davies1 at physics.ox.ac.uk
Mon Jan 10 05:49:17 CST 2005


I've belatedly started numbering these patches.  This one comes after
'widl: typeinfo attributes' 

        Huw Davies <huw at codeweavers.com>
        Add support for optional arguments and some suppport for the
        defaultvalue attributes.
        Better calculation of the typeinfo's res3 member (at least for
        interfaces).

-- 
Huw Davies
huw at codeweavers.com
--- wine/tools/widl/parser.y	2005-01-10 10:34:52.000000000 +0000
+++ wine/tools/widl/parser.y	2005-01-10 11:29:00.451006263 +0000
@@ -350,8 +350,8 @@
 	| tCONTEXTHANDLESERIALIZE		{ $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_SERIALIZE */ }
 	| tCONTROL				{ $$ = make_attr(ATTR_CONTROL); }
 	| tDEFAULT				{ $$ = make_attr(ATTR_DEFAULT); }
-	| tDEFAULTVALUE '(' expr_const ')'	{ $$ = make_attrp(ATTR_DEFAULTVALUE, $3); }
-	| tDEFAULTVALUE '(' aSTRING ')'		{ $$ = make_attrp(ATTR_DEFAULTVALUE, $3); }
+	| tDEFAULTVALUE '(' expr_const ')'	{ $$ = make_attrp(ATTR_DEFAULTVALUE_EXPR, $3); }
+	| tDEFAULTVALUE '(' aSTRING ')'		{ $$ = make_attrp(ATTR_DEFAULTVALUE_STRING, $3); }
 	| tDLLNAME '(' aSTRING ')'		{ $$ = make_attrp(ATTR_DLLNAME, $3); }
 	| tDUAL					{ $$ = make_attr(ATTR_DUAL); }
 	| tENDPOINT '(' aSTRING ')'		{ $$ = make_attrp(ATTR_ENDPOINT, $3); }
--- wine/tools/widl/widltypes.h	2005-01-10 10:34:52.000000000 +0000
+++ wine/tools/widl/widltypes.h	2005-01-10 11:30:52.183708149 +0000
@@ -62,7 +62,8 @@
     ATTR_CONTEXTHANDLE,
     ATTR_CONTROL,
     ATTR_DEFAULT,
-    ATTR_DEFAULTVALUE,
+    ATTR_DEFAULTVALUE_EXPR,
+    ATTR_DEFAULTVALUE_STRING,
     ATTR_DLLNAME,
     ATTR_DUAL,
     ATTR_ENDPOINT,
--- wine/tools/widl/write_msft.c	2005-01-10 11:17:54.622748000 +0000
+++ wine/tools/widl/write_msft.c	2005-01-10 11:27:14.784875566 +0000
@@ -648,9 +648,9 @@
 
 
 /****************************************************************************
- *	ctl2_encode_typedesc
+ *	ctl2_encode_type
  *
- *  Encodes a type description, storing information in the TYPEDESC and ARRAYDESC
+ *  Encodes a type, storing information in the TYPEDESC and ARRAYDESC
  *  segments as needed.
  *
  * RETURNS
@@ -927,13 +927,53 @@
 }
 
 
+static void write_value(msft_typeinfo_t* typeinfo, int *out, var_t *arg, int type, void *value)
+{
+    int vt = (type >> 16) & 0x1ff;
+    switch(vt) {
+    case VT_I2:
+    case VT_I4:
+    case VT_R4:
+    case VT_BOOL:
+    case VT_I1:
+    case VT_UI1:
+    case VT_UI2:
+    case VT_UI4:
+    case VT_INT:
+    case VT_UINT:
+    case VT_HRESULT:
+      {
+        unsigned long *lv = value;
+        if((*lv & 0x3ffffff) == *lv) {
+            *out = 0x80000000;
+            *out |= vt << 26;
+            *out |= *lv;
+        } else {
+            int offset = ctl2_alloc_segment(typeinfo->typelib, MSFT_SEG_CUSTDATA, 8, 0);
+            *((unsigned short *)&typeinfo->typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset]) = vt;
+            memcpy(&typeinfo->typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+2], value, 4);
+            *((unsigned short *)&typeinfo->typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+6]) = 0x5757;
+            *out = offset;
+        }
+        return;
+      }
+    case VT_BSTR:
+        warning("default value BSTR %s\n", (char*)value);
+        break;
+
+      default:
+          warning("can't write value of type %d yet\n", vt);
+    }
+    return;
+}
+
 static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, func_t *func)
 {
     int offset;
     int *typedata;
     int i, index = func->idx, id;
     int decoded_size;
-    int num_params = 0;
+    int num_params = 0, num_defaults = 0;
     var_t *arg, *last_arg = NULL;
     char *namedata;
     attr_t *attr;
@@ -951,6 +991,12 @@
     for(arg = func->args; arg; arg = NEXT_LINK(arg)) {
         last_arg = arg;
         num_params++;
+        for(attr = arg->attrs; attr; attr = NEXT_LINK(attr)) {
+            if(attr->type == ATTR_DEFAULTVALUE_EXPR || attr->type == ATTR_DEFAULTVALUE_STRING) {
+                num_defaults++;
+                break;
+            }
+        }
     }
 
     chat("num of params %d\n", num_params);
@@ -973,30 +1019,56 @@
     }
     /* allocate type data space for us */
     offset = typeinfo->typedata[0];
-    typeinfo->typedata[0] += 0x18 + (num_params * 12);
+    typeinfo->typedata[0] += 0x18 + (num_params * (num_defaults ? 16 : 12));
     typedata = typeinfo->typedata + (offset >> 2) + 1;
 
     /* fill out the basic type information */
-    typedata[0] = (0x18 + (num_params * 12)) | (index << 16);
+    typedata[0] = (0x18 + (num_params * (num_defaults ? 16 : 12))) | (index << 16);
     ctl2_encode_type(typeinfo->typelib, func->def->type, func->def->ptr_level, func->def->array, &typedata[1], NULL, NULL, &decoded_size);
     typedata[2] = funcflags;
     typedata[3] = ((52 /*sizeof(FUNCDESC)*/ + decoded_size) << 16) | typeinfo->typeinfo->cbSizeVft;
     typedata[4] = (index << 16) | (callconv << 8) | 9;
+    if(num_defaults) typedata[4] |= 0x10;
     typedata[5] = num_params;
 
     /* NOTE: High word of typedata[3] is total size of FUNCDESC + size of all ELEMDESCs for params + TYPEDESCs for pointer params and return types. */
     /* That is, total memory allocation required to reconstitute the FUNCDESC in its entirety. */
     typedata[3] += (16 /*sizeof(ELEMDESC)*/ * num_params) << 16;
+    typedata[3] += (24 /*sizeof(PARAMDESCEX)*/ * num_defaults) << 16;
 
     for (arg = last_arg, i = 0; arg; arg = PREV_LINK(arg), i++) {
         attr_t *attr;
         int paramflags = 0;
+        int *paramdata = typedata + 6 + (num_defaults ? num_params : 0) + i * 3;
+        int *defaultdata = num_defaults ? typedata + 6 + i : NULL;
+
+        if(defaultdata) *defaultdata = -1;
 
+	ctl2_encode_type(typeinfo->typelib, arg->type, arg->ptr_level, arg->array, paramdata, NULL, NULL, &decoded_size);
         for(attr = arg->attrs; attr; attr = NEXT_LINK(attr)) {
             switch(attr->type) {
+            case ATTR_DEFAULTVALUE_EXPR:
+              {
+                expr_t *expr = (expr_t *)attr->u.pval;
+                paramflags |= 0x30; /* PARAMFLAG_FHASDEFAULT | PARAMFLAG_FOPT */
+                chat("default value %ld\n", expr->cval);
+                write_value(typeinfo, defaultdata, arg, *paramdata, &expr->cval);
+                break;
+              }
+            case ATTR_DEFAULTVALUE_STRING:
+              {
+                char *s = (char *)attr->u.pval;
+                paramflags |= 0x30; /* PARAMFLAG_FHASDEFAULT | PARAMFLAG_FOPT */
+                chat("default value '%s'\n", s);
+                write_value(typeinfo, defaultdata, arg, *paramdata, s);
+                break;
+              }
             case ATTR_IN:
                 paramflags |= 0x01; /* PARAMFLAG_FIN */
                 break;
+            case ATTR_OPTIONAL:
+                paramflags |= 0x10; /* PARAMFLAG_FOPT */
+                break;
             case ATTR_OUT:
                 paramflags |= 0x02; /* PARAMFLAG_FOUT */
                 break;
@@ -1008,17 +1080,9 @@
                 break;
             }
         }
-	ctl2_encode_type(typeinfo->typelib, arg->type, arg->ptr_level, arg->array, &typedata[6+(i*3)], NULL, NULL, &decoded_size);
-	typedata[7+(i*3)] = -1;
-	typedata[8+(i*3)] = paramflags;
+	paramdata[1] = -1;
+	paramdata[2] = paramflags;
 	typedata[3] += decoded_size << 16;
-
-#if 0
-	/* FIXME: Doesn't work. Doesn't even come up with usable VTs for varDefaultValue. */
-	if (pFuncDesc->lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) {
-	    ctl2_alloc_custdata(This->typelib, &pFuncDesc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
-	}
-#endif
     }
 
     /* update the index data */
@@ -1029,14 +1093,12 @@
     /* ??? */
     if (!typeinfo->typeinfo->res2) typeinfo->typeinfo->res2 = 0x20;
     typeinfo->typeinfo->res2 <<= 1;
-
-    /* ??? */
-    if (typeinfo->typeinfo->res3 == -1) typeinfo->typeinfo->res3 = 0;
-    typeinfo->typeinfo->res3 += 0x38;
-
     /* ??? */
     if (index < 2) typeinfo->typeinfo->res2 += num_params << 4;
-    typeinfo->typeinfo->res3 += num_params << 4;
+
+    if (typeinfo->typeinfo->res3 == -1) typeinfo->typeinfo->res3 = 0;
+    typeinfo->typeinfo->res3 += 0x38 + num_params * 0x10;
+    if(num_defaults) typeinfo->typeinfo->res3 += num_params * 0x4;
 
     /* adjust size of VTBL */
     typeinfo->typeinfo->cbSizeVft += 4;
@@ -1058,9 +1120,9 @@
     for (arg = last_arg, i = 0; arg; arg = PREV_LINK(arg), i++) {
 	/* FIXME: Almost certainly easy to break */
 	int *paramdata = &typeinfo->typedata[typeinfo->offsets[index] >> 2];
-        
+        paramdata += 7 + (num_defaults ? num_params : 0) + i * 3;
 	offset = ctl2_alloc_name(typeinfo->typelib, arg->name);
-	paramdata[(i * 3) + 8] = offset;
+	paramdata[1] = offset;
         chat("param %d name %s offset %d\n", i, arg->name, offset);
     }
     return S_OK;



More information about the wine-patches mailing list