widl [2/2]: Add error checking and more accurate handling to [string] attrs

Dan Hipschman dsh at linux.ucla.edu
Fri Sep 1 18:35:49 CDT 2006


This does some sanity checking to make sure the [string] attributes only
get applied to char, wchar_t or byte types, and pointer type attributes
only get applied to pointers.  MIDL also enforces these restrictions.

More importantly, we can't set the type field of type_t to FC_C_[CW]STRING
because it may also need to hold a valid pointer type.  E.g., this should work:

typedef [string, ptr] char *str_t;

When the format string is written, the [string] attribute actually affects
the pointed to type (i.e., pointer to FC_C_CSTRING instead of FC_CHAR), not
the pointer, so the above should generate

0x14, 0x8, /* FC_FP */
0x22       /* FC_C_CSTRING */

We'll just need to deal with [string] attributes in the functions that
later process the types.

ChangeLog:
* Sanity check string and pointer attrs.  Don't assign string as type.
---
 tools/widl/parser.y  |   54 ++++++++++++++++++++++++++------------------------
 tools/widl/proxy.c   |   24 +++++++++++++++++-----
 tools/widl/typelib.c |    4 +---
 3 files changed, 47 insertions(+), 35 deletions(-)

diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index 12767c7..63e4c6d 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -1285,29 +1285,26 @@ static type_t *reg_type(type_t *type, co
   return type;
 }
 
-/* determine pointer type from attrs */
-static unsigned char get_pointer_type( type_t *type )
-{
-  int t;
-  if (is_attr( type->attrs, ATTR_STRING ))
-  {
-    switch( type->ref->type )
-    {
-    case RPC_FC_CHAR:
-      return RPC_FC_C_CSTRING;
-    case RPC_FC_WCHAR:
-      return RPC_FC_C_WSTRING;
-    }
-  }
-  t = get_attrv( type->attrs, ATTR_POINTERTYPE );
-  if (t) return t;
-  return RPC_FC_FP;
-}
-
 static type_t *reg_typedefs(type_t *type, var_t *names, attr_t *attrs)
 {
   type_t *ptr = type;
   int ptrc = 0;
+  int is_str = is_attr(attrs, ATTR_STRING);
+  unsigned char ptr_type = get_attrv(attrs, ATTR_POINTERTYPE);
+
+  if (is_str)
+  {
+    type_t *t = type;
+    unsigned char c;
+
+    while (is_ptr(t))
+      t = t->ref;
+
+    c = t->type;
+    if (c != RPC_FC_CHAR && c != RPC_FC_BYTE && c != RPC_FC_WCHAR)
+      yyerror("'%s': [string] attribute is only valid on 'char', 'byte', or 'wchar_t' pointers and arrays",
+              names->name);
+  }
 
   /* We must generate names for tagless enum, struct or union.
      Typedef-ing a tagless enum, struct or union means we want the typedef
@@ -1343,8 +1340,18 @@ static type_t *reg_typedefs(type_t *type
       }
       cur = alias(cur, names->name);
       cur->attrs = attrs;
-      if (is_ptr(cur))
-        cur->type = get_pointer_type(cur);
+      if (ptr_type)
+      {
+        if (is_ptr(cur))
+          cur->type = ptr_type;
+        else
+          yyerror("'%s': pointer attribute applied to non-pointer type",
+                  cur->name);
+      }
+      else if (is_str && ! is_ptr(cur))
+        yyerror("'%s': [string] attribute applied to non-pointer type",
+                cur->name);
+
       reg_type(cur, cur->name, 0);
     }
     names = next;
@@ -1485,11 +1492,6 @@ static int get_struct_type(var_t *field)
           yyerror("field '%s' deriving from a conformant array must be the last field in the structure",
                   field->name);
       break;
-    case RPC_FC_C_CSTRING:
-    case RPC_FC_C_WSTRING:
-      has_conformance = 1;
-      has_variance = 1;
-      break;
 
     /*
      * Propagate member attributes
diff --git a/tools/widl/proxy.c b/tools/widl/proxy.c
index 2022663..8d4d467 100644
--- a/tools/widl/proxy.c
+++ b/tools/widl/proxy.c
@@ -224,6 +224,12 @@ static void marshall_size_arg( var_t *ar
     return;
   }
 
+  if (is_string_type(arg->attrs, arg->ptr_level, arg->array))
+  {
+    print_proxy("NdrConformantStringBufferSize( &_StubMsg, (unsigned char*)s, ", arg->name);
+    fprintf(proxy, "&__MIDL_TypeFormatString.Format[%d] );\n", index);
+  }
+
   switch( type->type )
   {
   case RPC_FC_BYTE:
@@ -249,8 +255,6 @@ static void marshall_size_arg( var_t *ar
     fprintf(proxy, "&__MIDL_TypeFormatString.Format[%d] );\n", index );
     break;
 
-  case RPC_FC_C_CSTRING:
-  case RPC_FC_C_WSTRING:
   case RPC_FC_CARRAY:
     print_proxy( "NdrConformantArrayBufferSize( &_StubMsg, (unsigned char*)%s, ", arg->name );
     fprintf(proxy, "&__MIDL_TypeFormatString.Format[%d]);\n", index );
@@ -323,6 +327,12 @@ static void marshall_copy_arg( var_t *ar
     return;
   }
 
+  if (is_string_type(arg->attrs, arg->ptr_level, arg->array))
+  {
+    print_proxy("NdrConformantStringMarshall( &_StubMsg, (unsigned char*)s, ", arg->name);
+    fprintf(proxy, "&__MIDL_TypeFormatString.Format[%d] );\n", index);
+  }
+
   switch( type->type )
   {
   case RPC_FC_BYTE:
@@ -348,8 +358,6 @@ static void marshall_copy_arg( var_t *ar
     fprintf(proxy, "&__MIDL_TypeFormatString.Format[%d]);\n", index );
     break;
 
-  case RPC_FC_C_CSTRING:
-  case RPC_FC_C_WSTRING:
   case RPC_FC_CARRAY:
     break;
 
@@ -429,6 +437,12 @@ static void unmarshall_copy_arg( var_t *
     return;
   }
 
+  if (is_string_type(arg->attrs, arg->ptr_level, arg->array))
+  {
+    print_proxy("NdrConformantStringUnmarshall( &_StubMsg, (unsigned char**)&s, ", arg->name);
+    fprintf(proxy, "&__MIDL_TypeFormatString.Format[%d], 0 );\n", index);
+  }
+
   switch( type->type )
   {
   case RPC_FC_BYTE:
@@ -453,8 +467,6 @@ static void unmarshall_copy_arg( var_t *
     fprintf(proxy, "&__MIDL_TypeFormatString.Format[%d], 0);\n", index );
     break;
 
-  case RPC_FC_C_CSTRING:
-  case RPC_FC_C_WSTRING:
   case RPC_FC_CARRAY:
     print_proxy( "NdrConformantArrayUnmarshall( &_StubMsg, (unsigned char**)&%s, ", arg->name );
     fprintf(proxy, "&__MIDL_TypeFormatString.Format[%d], 0);\n", index );
diff --git a/tools/widl/typelib.c b/tools/widl/typelib.c
index adf9870..ae5cca8 100644
--- a/tools/widl/typelib.c
+++ b/tools/widl/typelib.c
@@ -79,9 +79,7 @@ int is_ptr(type_t *t)
   return c == RPC_FC_RP
       || c == RPC_FC_UP
       || c == RPC_FC_FP
-      || c == RPC_FC_OP
-      || c == RPC_FC_C_CSTRING
-      || c == RPC_FC_C_WSTRING;
+      || c == RPC_FC_OP;
 }
 
 /* List of oleauto types that should be recognized by name.



More information about the wine-patches mailing list