Changeset 108342 in vbox
- Timestamp:
- Feb 24, 2025 10:21:58 AM (3 weeks ago)
- svn:sync-xref-src-repo-rev:
- 167701
- Location:
- trunk/src/libs/xpcom18a4/xpcom/typelib/xpidl
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl.h
r108340 r108342 395 395 396 396 /* 397 * Verifies the interface declaration398 */399 DECLHIDDEN(bool) verify_interface_declaration(PCXPIDLNODE pNd);400 401 /*402 397 * Find the underlying type of an identifier typedef. Returns NULL 403 398 * (and doesn't complain) on failure. … … 405 400 DECLHIDDEN(PCXPIDLNODE) find_underlying_type(PCXPIDLNODE pNd); 406 401 407 #if 0 402 /* 403 * Verifies the interface declaration 404 */ 405 DECLHIDDEN(int) verify_interface_declaration(PCXPIDLNODE pNd, PRTERRINFO pErrInfo); 406 408 407 /* 409 408 * Check that const declarations match their stated sign and are of the 410 409 * appropriate types. 411 410 */ 412 gboolean 413 verify_const_declaration(IDL_tree const_tree); 411 DECLHIDDEN(int) verify_const_declaration(PCXPIDLNODE pNd, PRTERRINFO pErrInfo); 414 412 415 413 /* 416 414 * Check that scriptable attributes in scriptable interfaces actually are. 417 415 */ 418 gboolean 419 verify_attribute_declaration(IDL_tree method_tree); 416 DECLHIDDEN(int) verify_attribute_declaration(PCXPIDLNODE pNd, PRTERRINFO pErrInfo); 420 417 421 418 /* 422 419 * Perform various validation checks on methods. 423 420 */ 424 gboolean 425 verify_method_declaration(IDL_tree method_tree); 426 #endif 421 DECLHIDDEN(int) verify_method_declaration(PCXPIDLNODE pNd, PRTERRINFO pErrInfo); 427 422 428 423 /* … … 430 425 * it's of the form native <idl-name>(<c++-name>) 431 426 */ 432 DECLHIDDEN( bool) check_native(PCXPIDLNODE pNd);427 DECLHIDDEN(int) check_native(PCXPIDLNODE pNd, PRTERRINFO pErrInfo); 433 428 434 429 #endif /* __xpidl_h */ -
trunk/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_header.c
r108340 r108342 393 393 394 394 395 static int xpidlHdrWriteMethod(PCXPIDLNODE pNd, FILE *pFile) 396 { 397 #if 0 /** @todo */ 395 static int xpidlHdrWriteMethod(PCXPIDLNODE pNd, FILE *pFile, PRTERRINFO pErrInfo) 396 { 398 397 /* 399 398 * Verify that e.g. non-scriptable methods in [scriptable] interfaces 400 399 * are declared so. Do this in a separate verification pass? 401 400 */ 402 i f (!verify_method_declaration(state->tree))403 return FALSE;404 #endif 401 int rc = verify_method_declaration(pNd, pErrInfo); 402 if (RT_FAILURE(rc)) 403 return rc; 405 404 406 405 /* Dump the signature as a comment. */ … … 430 429 431 430 write_indent(pFile); 432 intrc = write_method_signature(pNd, pFile, true /*fDecl*/);431 rc = write_method_signature(pNd, pFile, true /*fDecl*/); 433 432 if (RT_FAILURE(rc)) 434 433 return rc; … … 475 474 } 476 475 477 static int xpidlHdrWriteAttribute(PCXPIDLNODE pNd, FILE *pFile) 478 { 479 #if 0 /** @todo */ 480 if (!verify_attribute_declaration(state->tree)) 481 return FALSE; 482 #endif 476 static int xpidlHdrWriteAttribute(PCXPIDLNODE pNd, FILE *pFile, PRTERRINFO pErrInfo) 477 { 478 int rc = verify_attribute_declaration(pNd, pErrInfo); 479 if (RT_FAILURE(rc)) 480 return rc; 483 481 484 482 /* Write the attribute as a comment. */ … … 492 490 493 491 write_indent(pFile); 494 intrc = xpidlHdrWriteAttrAccessor(pNd, pFile, true, true /*fDecl*/);492 rc = xpidlHdrWriteAttrAccessor(pNd, pFile, true, true /*fDecl*/); 495 493 if (RT_FAILURE(rc)) 496 494 return rc; … … 510 508 511 509 512 static int xpidlHdrWriteConst(PCXPIDLNODE pNd, FILE *pFile) 513 { 514 #if 0 /** @todo We only allow unsigned numbers for now. */ 515 if (!verify_const_declaration(pNd)) 516 return FALSE; 517 #endif 510 static int xpidlHdrWriteConst(PCXPIDLNODE pNd, FILE *pFile, PRTERRINFO pErrInfo) 511 { 512 int rc = verify_const_declaration(pNd, pErrInfo); 513 if (RT_FAILURE(rc)) 514 return rc; 518 515 519 516 write_indent(pFile); … … 536 533 struct nsID id; 537 534 char iid_parsed[UUID_LENGTH]; 538 int rc = VINF_SUCCESS; 539 540 if ( !verify_interface_declaration(pNd))541 return VERR_INVALID_PARAMETER;542 543 #define FAIL do { AssertFailed();rc = VERR_INVALID_PARAMETER; goto out;} while(0)535 536 int rc = verify_interface_declaration(pNd, pErrInfo); 537 if (RT_FAILURE(rc)) 538 return rc; 539 540 #define FAIL do {/*AssertFailed();*/ rc = VERR_INVALID_PARAMETER; goto out;} while(0) 544 541 545 542 fprintf(pFile, "\n/* starting interface: %s */\n", pNd->u.If.pszIfName); … … 643 640 { 644 641 case kXpidlNdType_Const: 645 rc = xpidlHdrWriteConst(pIt, pFile );642 rc = xpidlHdrWriteConst(pIt, pFile, pErrInfo); 646 643 if (RT_FAILURE(rc)) 647 644 FAIL; 648 645 break; 649 646 case kXpidlNdType_Attribute: 650 rc = xpidlHdrWriteAttribute(pIt, pFile );647 rc = xpidlHdrWriteAttribute(pIt, pFile, pErrInfo); 651 648 if (RT_FAILURE(rc)) 652 649 FAIL; 653 650 break; 654 651 case kXpidlNdType_Method: 655 rc = xpidlHdrWriteMethod(pIt, pFile );652 rc = xpidlHdrWriteMethod(pIt, pFile, pErrInfo); 656 653 if (RT_FAILURE(rc)) 657 654 FAIL; -
trunk/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_idl.c
r108340 r108342 607 607 static PCXPIDLNODE xpidlParseFindType(PXPIDLPARSE pThis, const char *pszName) 608 608 { 609 PCXPIDLNODE pIfFwd = NULL; 609 610 PCXPIDLNODE pIt; 610 611 RTListForEach(&pThis->LstNodes, pIt, XPIDLNODE, NdLst) … … 622 623 case kXpidlNdType_Interface_Forward_Decl: 623 624 if (!strcmp(pszName, pIt->u.pszIfFwdName)) 624 return pIt;625 pIfFwd = pIt; /* We will try finding the real definition before returning the forward declaration. */ 625 626 break; 626 627 case kXpidlNdType_Interface_Def: … … 633 634 } 634 635 635 return NULL;636 return pIfFwd; 636 637 } 637 638 … … 1379 1380 free(outname); 1380 1381 } 1381 else 1382 1383 if (RT_FAILURE(rc)) 1382 1384 RTMsgError(ParseState.ErrInfo.Core.pszMsg); 1383 1385 -
trunk/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_typelib.c
r108340 r108342 979 979 bool hidden = (xpidlNodeAttrFind(pNd, "noscript") != NULL); 980 980 981 //if (!verify_attribute_declaration(state->tree)) 982 // return VERR_NO_MEMORY; 981 int rc = verify_attribute_declaration(pNd, pThis->pErrInfo); 982 if (RT_FAILURE(rc)) 983 return rc; 983 984 984 985 if (!XPT_InterfaceDescriptorAddMethods(ARENA(pThis), id, … … 988 989 meth = &id->method_descriptors[NEXT_METH(pThis)]; 989 990 990 intrc = typelib_attr_accessor(pThis, pNd, meth, true, hidden);991 rc = typelib_attr_accessor(pThis, pNd, meth, true, hidden); 991 992 if (RT_FAILURE(rc)) 992 993 return rc; … … 1012 1013 bool op_noscript = (xpidlNodeAttrFind(pNd, "noscript") != NULL); 1013 1014 1014 //if (!verify_method_declaration(pNd)) 1015 // return FALSE; 1015 int rc = verify_method_declaration(pNd, pThis->pErrInfo); 1016 if (RT_FAILURE(rc)) 1017 return rc; 1016 1018 1017 1019 if (!XPT_InterfaceDescriptorAddMethods(ARENA(pThis), id, 1)) … … 1094 1096 XPTConstDescriptor *cd; 1095 1097 1096 //if (!verify_const_declaration(state->tree)) 1097 // return FALSE; 1098 int rc = verify_const_declaration(pNd, pThis->pErrInfo); 1099 if (RT_FAILURE(rc)) 1100 return rc; 1098 1101 1099 1102 /* Could be a typedef; try to map it to the real type. */ … … 1117 1120 fprintf(stderr, "DBG: adding const %s\n", cd->name); 1118 1121 #endif 1119 intrc = fill_td_from_type(pThis, &cd->type, pNd->u.Const.pNdTypeSpec);1122 rc = fill_td_from_type(pThis, &cd->type, pNd->u.Const.pNdTypeSpec); 1120 1123 if (RT_FAILURE(rc)) 1121 1124 return rc; … … 1218 1221 This.pErrInfo = pErrInfo; 1219 1222 int rc = typelib_prolog(&This, pInput, pParse); 1220 AssertRC(rc);1221 1222 1223 if (RT_SUCCESS(rc)) 1223 1224 { … … 1231 1232 { 1232 1233 case kXpidlNdType_Native: 1233 if (!check_native(pIt)) 1234 rc = VERR_INVALID_PARAMETER; 1234 rc = check_native(pIt, pErrInfo); 1235 1235 break; 1236 1236 case kXpidlNdType_Interface_Def: … … 1245 1245 break; 1246 1246 } 1247 AssertRC(rc);1248 1247 if (RT_FAILURE(rc)) 1249 1248 break; … … 1254 1253 } 1255 1254 1256 AssertRC(rc);1257 1255 return rc; 1258 1256 } -
trunk/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_util.c
r108340 r108342 146 146 } 147 147 148 #if 0 149 gboolean 150 verify_const_declaration(IDL_tree const_tree) { 151 struct _IDL_CONST_DCL *dcl = &IDL_CONST_DCL(const_tree); 152 const char *name = IDL_IDENT(dcl->ident).str; 153 IDL_tree real_type; 154 155 /* const -> list -> interface */ 156 if (!IDL_NODE_UP(IDL_NODE_UP(const_tree)) || 157 IDL_NODE_TYPE(IDL_NODE_UP(IDL_NODE_UP(const_tree))) 158 != IDLN_INTERFACE) { 159 IDL_tree_error(const_tree, 160 "const declaration \'%s\' outside interface", 161 name); 162 return FALSE; 163 } 148 DECLHIDDEN(int) verify_const_declaration(PCXPIDLNODE pNd, PRTERRINFO pErrInfo) 149 { 150 /* const must be inside an interface definition. */ 151 if ( !pNd->pParent 152 || pNd->pParent->enmType != kXpidlNdType_Interface_Def) 153 return xpidlIdlError(pErrInfo, pNd, VERR_INVALID_STATE, 154 "const declaration \'%s\' outside interface", 155 pNd->u.Const.pszName); 164 156 165 157 /* Could be a typedef; try to map it to the real type. */ 166 real_type = find_underlying_type(dcl->const_type); 167 real_type = real_type ? real_type : dcl->const_type; 168 if (IDL_NODE_TYPE(real_type) == IDLN_TYPE_INTEGER && 169 (IDL_TYPE_INTEGER(real_type).f_type == IDL_INTEGER_TYPE_SHORT || 170 IDL_TYPE_INTEGER(real_type).f_type == IDL_INTEGER_TYPE_LONG)) 171 { 172 if (!IDL_TYPE_INTEGER(real_type).f_signed && 173 IDL_INTEGER(dcl->const_exp).value < 0) 174 { 175 #ifndef G_HAVE_GINT64 176 /* 177 * For platforms without longlong support turned on we can get 178 * confused by the high bit of the long value and think that it 179 * represents a negative value in an unsigned declaration. 180 * In that case we don't know if it is the programmer who is 181 * confused or the compiler. So we issue a warning instead of 182 * an error. 183 */ 184 if (IDL_TYPE_INTEGER(real_type).f_type == IDL_INTEGER_TYPE_LONG) 185 { 186 XPIDL_WARNING((const_tree, IDL_WARNING1, 187 "unsigned const declaration \'%s\' " 188 "initialized with (possibly) negative constant", 189 name)); 190 return TRUE; 191 } 192 #endif 193 IDL_tree_error(const_tree, 194 "unsigned const declaration \'%s\' initialized with " 195 "negative constant", 196 name); 197 return FALSE; 198 } 199 } else { 200 IDL_tree_error(const_tree, 201 "const declaration \'%s\' must be of type short or long", 202 name); 203 return FALSE; 204 } 205 206 return TRUE; 207 } 208 209 210 211 /* 212 * This method consolidates error checking needed when coercing the XPIDL compiler 213 * via the -t flag to generate output for a specific version of XPConnect. 214 */ 215 static gboolean 216 verify_type_fits_version(IDL_tree in_tree, IDL_tree error_tree) 217 { 218 if (major_version == 1 && minor_version == 1) 219 { 220 /* XPIDL Version 1.1 checks */ 221 222 /* utf8string, cstring, and astring types are not supported */ 223 if (IDL_tree_property_get(in_tree, "utf8string") != NULL || 224 IDL_tree_property_get(in_tree, "cstring") != NULL || 225 IDL_tree_property_get(in_tree, "astring") != NULL) 226 { 227 IDL_tree_error(error_tree, 228 "Cannot use [utf8string], [cstring] and [astring] " 229 "types when generating version 1.1 typelibs\n"); 230 return FALSE; 231 } 232 } 233 return TRUE; 234 } 235 236 gboolean 237 verify_attribute_declaration(IDL_tree attr_tree) 238 { 239 IDL_tree iface; 240 IDL_tree ident; 241 IDL_tree attr_type; 242 gboolean scriptable_interface; 243 244 /* We don't support attributes named IID, conflicts with static GetIID 158 PCXPIDLNODE pNdType = find_underlying_type(pNd->u.Const.pNdTypeSpec); 159 pNdType = pNdType ? pNdType : pNd->u.Const.pNdTypeSpec; 160 if ( pNdType->enmType != kXpidlNdType_BaseType 161 || ( pNdType->u.enmBaseType != kXpidlType_Short 162 && pNdType->u.enmBaseType != kXpidlType_Long 163 && pNdType->u.enmBaseType != kXpidlType_Unsigned_Short 164 && pNdType->u.enmBaseType != kXpidlType_Unsigned_Long)) 165 return xpidlIdlError(pErrInfo, pNd, VERR_INVALID_STATE, 166 "const declaration \'%s\' must be of type short or long", 167 pNd->u.Const.pszName); 168 169 return VINF_SUCCESS; 170 } 171 172 173 DECLHIDDEN(int) verify_attribute_declaration(PCXPIDLNODE pNd, PRTERRINFO pErrInfo) 174 { 175 Assert(pNd->enmType == kXpidlNdType_Attribute); 176 177 /* 178 * We don't support attributes named IID, conflicts with static GetIID 245 179 * member. The conflict is due to certain compilers (VC++) choosing a 246 180 * different vtable order, placing GetIID at the beginning regardless 247 181 * of it's placement 248 182 */ 249 if (strcmp( 250 IDL_IDENT( 251 IDL_LIST(IDL_ATTR_DCL(attr_tree).simple_declarations).data).str, 252 "IID") == 0) { 253 IDL_tree_error(attr_tree, 254 "Attributes named IID not supported, causes vtable " 255 "ordering problems"); 256 return FALSE; 257 } 183 if (!strcmp(pNd->u.Attribute.pszName, "IID")) 184 return xpidlIdlError(pErrInfo, pNd, VERR_INVALID_STATE, 185 "Attributes named IID not supported, causes vtable ordering problems"); 186 258 187 /* 259 188 * Verify that we've been called on an interface, and decide if the 260 189 * interface was marked [scriptable]. 261 190 */ 262 if (IDL_NODE_UP(attr_tree) && IDL_NODE_UP(IDL_NODE_UP(attr_tree)) && 263 IDL_NODE_TYPE(iface = IDL_NODE_UP(IDL_NODE_UP(attr_tree))) 264 == IDLN_INTERFACE) 265 { 266 scriptable_interface = 267 (IDL_tree_property_get(IDL_INTERFACE(iface).ident, "scriptable") 268 != NULL); 269 } else { 270 IDL_tree_error(attr_tree, 271 "verify_attribute_declaration called on a non-interface?"); 272 return FALSE; 273 } 274 275 /* 276 * Grab the first of the list of idents and hope that it'll 277 * say scriptable or no. 278 */ 279 ident = IDL_LIST(IDL_ATTR_DCL(attr_tree).simple_declarations).data; 191 bool fScriptable; 192 if ( pNd->pParent 193 && pNd->pParent->enmType == kXpidlNdType_Interface_Def) 194 fScriptable = (xpidlNodeAttrFind(pNd->pParent, "scriptable") != NULL); 195 else 196 return xpidlIdlError(pErrInfo, pNd, VERR_INVALID_STATE, 197 "verify_attribute_declaration called on a non-interface?"); 280 198 281 199 /* … … 283 201 * there's no need to check. 284 202 */ 285 if (!scriptable_interface || 286 IDL_tree_property_get(ident, "noscript") != NULL) 287 return TRUE; 203 if (!fScriptable || !xpidlNodeAttrFind(pNd, "scriptable")) 204 return VINF_SUCCESS; 288 205 289 206 /* … … 291 208 * domstring, utf8string, cstring, astring are exempted. 292 209 */ 293 attr_type = IDL_ATTR_DCL(attr_tree).param_type_spec;294 295 if ( attr_type != NULL)210 PCXPIDLNODE pNdType = find_underlying_type(pNd->u.Attribute.pNdTypeSpec); 211 pNdType = pNdType ? pNdType : pNd->u.Attribute.pNdTypeSpec; 212 if (pNdType) 296 213 { 297 if (UP_IS_NATIVE(attr_type) && 298 IDL_tree_property_get(attr_type, "nsid") == NULL && 299 IDL_tree_property_get(attr_type, "domstring") == NULL && 300 IDL_tree_property_get(attr_type, "utf8string") == NULL && 301 IDL_tree_property_get(attr_type, "cstring") == NULL && 302 IDL_tree_property_get(attr_type, "astring") == NULL) 303 { 304 IDL_tree_error(attr_tree, 305 "attributes in [scriptable] interfaces that are " 306 "non-scriptable because they refer to native " 307 "types must be marked [noscript]\n"); 308 return FALSE; 309 } 214 if (pNdType->enmType == kXpidlNdType_Native && 215 xpidlNodeAttrFind(pNdType, "nsid") == NULL && 216 xpidlNodeAttrFind(pNdType, "domstring") == NULL && 217 xpidlNodeAttrFind(pNdType, "utf8string") == NULL && 218 xpidlNodeAttrFind(pNdType, "cstring") == NULL && 219 xpidlNodeAttrFind(pNdType, "astring") == NULL) 220 return xpidlIdlError(pErrInfo, pNd, VERR_INVALID_STATE, 221 "attributes in [scriptable] interfaces that are " 222 "non-scriptable because they refer to native " 223 "types must be marked [noscript]"); 224 310 225 /* 311 226 * We currently don't support properties of type nsid that aren't … … 313 228 * must be read-only 314 229 */ 315 316 if ((IDL_tree_property_get(ident, "notxpcom") == NULL || !(IDL_ATTR_DCL(attr_tree).f_readonly)) && 317 IDL_tree_property_get(attr_type,"nsid") != NULL && 318 IDL_tree_property_get(attr_type,"ptr") == NULL && 319 IDL_tree_property_get(attr_type,"ref") == NULL) 320 { 321 IDL_tree_error(attr_tree, 322 "Feature not currently supported: " 323 "attributes with a type of nsid must be marked " 324 "either [ptr] or [ref], or " 325 "else must be marked [notxpcom] " 326 "and must be read-only\n"); 327 return FALSE; 328 } 329 330 /* 331 * Run additional error checks on the attribute type if targetting an 332 * older version of XPConnect. 333 */ 334 335 if (!verify_type_fits_version(attr_type, attr_tree)) 336 return FALSE; 337 } 338 339 if (IDL_LIST(IDL_ATTR_DCL(attr_tree).simple_declarations).next != NULL) 340 { 341 IDL_tree_error(attr_tree, 342 "multiple attributes in a single declaration is not supported\n"); 343 return FALSE; 344 } 345 return TRUE; 346 } 347 #endif 230 if ( ( xpidlNodeAttrFind(pNd, "notxpcom") == NULL 231 || pNd->u.Attribute.fReadonly) 232 && xpidlNodeAttrFind(pNdType,"nsid") != NULL 233 && xpidlNodeAttrFind(pNdType,"ptr") == NULL 234 && xpidlNodeAttrFind(pNdType,"ref") == NULL) 235 return xpidlIdlError(pErrInfo, pNd, VERR_INVALID_STATE, 236 "Feature not currently supported: " 237 "attributes with a type of nsid must be marked either [ptr] or [ref], or " 238 "else must be marked [notxpcom] and must be read-only\n"); 239 } 240 241 return VINF_SUCCESS; 242 } 243 348 244 349 245 /* … … 365 261 366 262 367 #if 0 368 static IDL_tree /* IDL_PARAM_DCL */ 369 find_named_parameter(IDL_tree method_tree, const char *param_name) 370 { 371 IDL_tree iter; 372 for (iter = IDL_OP_DCL(method_tree).parameter_dcls; iter; 373 iter = IDL_LIST(iter).next) 263 static PCXPIDLNODE find_named_parameter(PCXPIDLNODE pNdMethod, const char *param_name) 264 { 265 PCXPIDLNODE pIt; 266 RTListForEach(&pNdMethod->u.Method.LstParams, pIt, XPIDLNODE, NdLst) 374 267 { 375 IDL_tree param = IDL_LIST(iter).data; 376 IDL_tree simple_decl = IDL_PARAM_DCL(param).simple_declarator; 377 const char *current_name = IDL_IDENT(simple_decl).str; 378 if (strcmp(current_name, param_name) == 0) 379 return param; 268 Assert(pIt->enmType == kXpidlNdType_Parameter); 269 if (!strcmp(pIt->u.Param.pszName, param_name)) 270 return pIt; 380 271 } 381 272 return NULL; … … 392 283 * refer to parameters of the appropriate type. 393 284 */ 394 static gboolean 395 check_param_attribute(IDL_tree method_tree, IDL_tree param, 396 ParamAttrType whattocheck) 397 { 398 const char *referred_name = NULL; 399 IDL_tree simple_decl = IDL_PARAM_DCL(param).simple_declarator; 285 static int check_param_attribute(PCXPIDLNODE pNdMethod, PCXPIDLNODE pNdParam, 286 ParamAttrType whattocheck, PRTERRINFO pErrInfo) 287 { 400 288 const char *attr_name; 401 289 const char *needed_type; … … 411 299 needed_type = "unsigned long (or PRUint32)"; 412 300 } else { 413 XPT_ASSERT("asked to check an unknown attribute type!");414 return TRUE;301 AssertMsgFailed(("asked to check an unknown attribute type!")); 302 return VINF_SUCCESS; 415 303 } 416 304 417 referred_name = IDL_tree_property_get(simple_decl, attr_name); 418 if (referred_name != NULL) { 419 IDL_tree referred_param = find_named_parameter(method_tree, 305 PCXPIDLATTR pAttr = xpidlNodeAttrFind(pNdParam, attr_name); 306 if (pAttr != NULL) 307 { 308 const char *referred_name = pAttr->pszVal; 309 310 PCXPIDLNODE pNdParamRef = find_named_parameter(pNdMethod, 420 311 referred_name); 421 IDL_tree referred_param_type; 422 if (referred_param == NULL) { 423 IDL_tree_error(method_tree, 424 "attribute [%s(%s)] refers to missing " 425 "parameter \"%s\"", 426 attr_name, referred_name, referred_name); 427 return FALSE; 428 } 429 if (referred_param == param) { 430 IDL_tree_error(method_tree, 431 "attribute [%s(%s)] refers to it's own parameter", 432 attr_name, referred_name); 433 return FALSE; 434 } 312 if (!pNdParamRef) 313 return xpidlIdlError(pErrInfo, pNdParam, VERR_INVALID_STATE, 314 "attribute [%s(%s)] refers to missing parameter \"%s\"", 315 attr_name, referred_name, referred_name); 316 317 if (pNdParamRef == pNdParam) 318 return xpidlIdlError(pErrInfo, pNdParam, VERR_INVALID_STATE, 319 "attribute [%s(%s)] refers to it's own parameter", 320 attr_name, referred_name); 435 321 436 referred_param_type = IDL_PARAM_DCL(referred_param).param_type_spec; 437 if (whattocheck == IID_IS) { 322 PCXPIDLNODE pNdTypeSpec = find_underlying_type(pNdParamRef->u.Param.pNdTypeSpec); 323 pNdTypeSpec = pNdTypeSpec ? pNdTypeSpec : pNdParamRef->u.Param.pNdTypeSpec; 324 if (whattocheck == IID_IS) 325 { 438 326 /* require IID type */ 439 if ( IDL_tree_property_get(referred_param_type, "nsid") == NULL) {440 IDL_tree_error(method_tree,327 if (!xpidlNodeAttrFind(pNdTypeSpec, "nsid")) 328 return xpidlIdlError(pErrInfo, pNdParamRef, VERR_INVALID_STATE, 441 329 "target \"%s\" of [%s(%s)] attribute " 442 330 "must be of %s type", 443 331 referred_name, attr_name, referred_name, 444 332 needed_type); 445 return FALSE;446 }447 } else if (whattocheck == LENGTH_IS || whattocheck == SIZE_IS) {448 /* require PRUint32 type */449 IDL_tree real_type;450 451 /* Could be a typedef; try to map it to the real type. */452 real_type = find_underlying_type(referred_param_type);453 real_type = real_type ? real_type : referred_param_type;454 455 if (IDL_NODE_TYPE(real_type) != IDLN_TYPE_INTEGER ||456 IDL_TYPE_INTEGER(real_type).f_signed != FALSE ||457 IDL_TYPE_INTEGER(real_type).f_type != IDL_INTEGER_TYPE_LONG)458 {459 IDL_tree_error(method_tree,460 "target \"%s\" of [%s(%s)] attribute "461 "must be of %s type",462 referred_name, attr_name, referred_name,463 needed_type);464 465 return FALSE;466 }467 333 } 468 } 469 470 return TRUE; 334 else if (whattocheck == LENGTH_IS || whattocheck == SIZE_IS) 335 { 336 PCXPIDLNODE pNdType = find_underlying_type(pNdTypeSpec); 337 pNdType = pNdType ? pNdType : pNdTypeSpec; 338 339 if ( pNdType->enmType != kXpidlNdType_BaseType 340 || pNdType->u.enmBaseType != kXpidlType_Unsigned_Long) 341 return xpidlIdlError(pErrInfo, pNdParamRef, VERR_INVALID_STATE, 342 "target \"%s\" of [%s(%s)] attribute " 343 "must be of %s type", 344 referred_name, attr_name, referred_name, 345 needed_type); 346 } 347 } 348 349 return VINF_SUCCESS; 471 350 } 472 351 … … 475 354 * Common method verification code, called by *op_dcl in the various backends. 476 355 */ 477 gboolean 478 verify_method_declaration(IDL_tree method_tree) 479 { 480 struct _IDL_OP_DCL *op = &IDL_OP_DCL(method_tree); 481 IDL_tree iface; 482 IDL_tree iter; 483 gboolean notxpcom; 484 gboolean scriptable_interface; 485 gboolean scriptable_method; 486 gboolean seen_retval = FALSE; 487 const char *method_name = IDL_IDENT(IDL_OP_DCL(method_tree).ident).str; 488 489 /* We don't support attributes named IID, conflicts with static GetIID 356 DECLHIDDEN(int) verify_method_declaration(PCXPIDLNODE pNd, PRTERRINFO pErrInfo) 357 { 358 Assert(pNd->enmType == kXpidlNdType_Method); 359 bool notxpcom; 360 bool scriptable_interface; 361 bool scriptable_method; 362 bool seen_retval = false; 363 364 /* 365 * We don't support attributes named IID, conflicts with static GetIID 490 366 * member. The conflict is due to certain compilers (VC++) choosing a 491 367 * different vtable order, placing GetIID at the beginning regardless 492 368 * of it's placement 493 369 */ 494 if (strcmp(method_name, "GetIID") == 0) { 495 IDL_tree_error(method_tree, 496 "Methods named GetIID not supported, causes vtable " 497 "ordering problems"); 498 return FALSE; 499 } 500 if (op->f_varargs) { 501 /* We don't currently support varargs. */ 502 IDL_tree_error(method_tree, "varargs are not currently supported"); 503 return FALSE; 504 } 370 if (!strcmp(pNd->u.Method.pszName, "GetIID")) 371 return xpidlIdlError(pErrInfo, pNd, VERR_INVALID_STATE, 372 "Methods named GetIID not supported, causes vtable " 373 "ordering problems"); 505 374 506 375 /* … … 508 377 * interface was marked [scriptable]. 509 378 */ 510 if (IDL_NODE_UP(method_tree) && IDL_NODE_UP(IDL_NODE_UP(method_tree)) && 511 IDL_NODE_TYPE(iface = IDL_NODE_UP(IDL_NODE_UP(method_tree))) 512 == IDLN_INTERFACE) 513 { 514 scriptable_interface = 515 (IDL_tree_property_get(IDL_INTERFACE(iface).ident, "scriptable") 516 != NULL); 517 } else { 518 IDL_tree_error(method_tree, 519 "verify_method_declaration called on a non-interface?"); 520 return FALSE; 521 } 379 if ( pNd->pParent 380 && pNd->pParent->enmType == kXpidlNdType_Interface_Def) 381 scriptable_interface = (xpidlNodeAttrFind(pNd->pParent, "scriptable") != NULL); 382 else 383 return xpidlIdlError(pErrInfo, pNd, VERR_INVALID_STATE, 384 "verify_method_declaration called on a non-interface?"); 522 385 523 386 /* … … 529 392 * to unsigned long. 530 393 */ 531 notxpcom = IDL_tree_property_get(op->ident, "notxpcom") != NULL;532 533 scriptable_method = scriptable_interface &&534 !notxpcom &&535 IDL_tree_property_get(op->ident, "noscript") == NULL;394 notxpcom = xpidlNodeAttrFind(pNd, "notxpcom") != NULL; 395 396 scriptable_method = scriptable_interface 397 && !notxpcom 398 && xpidlNodeAttrFind(pNd, "noscript") == NULL; 536 399 537 400 /* Loop through the parameters and check. */ 538 for (iter = op->parameter_dcls; iter; iter = IDL_LIST(iter).next) {539 IDL_tree param = IDL_LIST(iter).data;540 IDL_tree param_type =541 IDL_PARAM_DCL(param).param_type_spec;542 IDL_tree simple_decl = 543 IDL_PARAM_DCL(param).simple_declarator;544 const char *param_name = IDL_IDENT(simple_decl).str;401 PCXPIDLNODE pIt; 402 RTListForEach(&pNd->u.Method.LstParams, pIt, XPIDLNODE, NdLst) 403 { 404 int rc; 405 406 PCXPIDLNODE pNdTypeSpec = find_underlying_type(pIt->u.Param.pNdTypeSpec); 407 pNdTypeSpec = pNdTypeSpec ? pNdTypeSpec : pIt->u.Param.pNdTypeSpec; 545 408 546 409 /* … … 549 412 * cstring, astring or iid_is. 550 413 */ 551 if (scriptable_method && 552 UP_IS_NATIVE(param_type) && 553 IDL_tree_property_get(param_type, "nsid") == NULL && 554 IDL_tree_property_get(simple_decl, "iid_is") == NULL && 555 IDL_tree_property_get(param_type, "domstring") == NULL && 556 IDL_tree_property_get(param_type, "utf8string") == NULL && 557 IDL_tree_property_get(param_type, "cstring") == NULL && 558 IDL_tree_property_get(param_type, "astring") == NULL) 559 { 560 IDL_tree_error(method_tree, 414 if ( scriptable_method 415 && pNdTypeSpec->enmType == kXpidlNdType_Native 416 && xpidlNodeAttrFind(pNdTypeSpec, "nsid") == NULL 417 && xpidlNodeAttrFind(pIt, "iid_is") == NULL 418 && xpidlNodeAttrFind(pNdTypeSpec, "domstring") == NULL 419 && xpidlNodeAttrFind(pNdTypeSpec, "utf8string") == NULL 420 && xpidlNodeAttrFind(pNdTypeSpec, "cstring") == NULL 421 && xpidlNodeAttrFind(pNdTypeSpec, "astring") == NULL) 422 return xpidlIdlError(pErrInfo, pIt, VERR_INVALID_STATE, 561 423 "methods in [scriptable] interfaces that are " 562 424 "non-scriptable because they refer to native " 563 425 "types (parameter \"%s\") must be marked " 564 "[noscript]", param_name); 565 return FALSE; 566 } 426 "[noscript]", pIt->u.Param.pszName); 567 427 568 428 /* … … 571 431 * as input parameters 572 432 */ 573 if (!(notxpcom && IDL_PARAM_DCL(param).attr != IDL_PARAM_IN) && 574 IDL_tree_property_get(param_type, "nsid") != NULL && 575 IDL_tree_property_get(param_type, "ptr") == NULL && 576 IDL_tree_property_get(param_type, "ref") == NULL) 577 { 578 IDL_tree_error(method_tree, 579 "Feature currently not supported: " 580 "parameter \"%s\" is of type nsid and " 581 "must be marked either [ptr] or [ref] " 582 "or method \"%s\" must be marked [notxpcom] " 583 "and must not be an input parameter", 584 param_name, 585 method_name); 586 return FALSE; 587 } 433 if ( !( notxpcom 434 && pIt->u.Param.enmDir != kXpidlDirection_In) 435 && xpidlNodeAttrFind(pNdTypeSpec, "nsid") != NULL 436 && xpidlNodeAttrFind(pNdTypeSpec, "ptr") == NULL 437 && xpidlNodeAttrFind(pNdTypeSpec, "ref") == NULL) 438 return xpidlIdlError(pErrInfo, pNd, VERR_INVALID_STATE, 439 "Feature currently not supported: " 440 "parameter \"%s\" is of type nsid and " 441 "must be marked either [ptr] or [ref] " 442 "or method \"%s\" must be marked [notxpcom] " 443 "and must not be an input parameter", 444 pIt->u.Param.pszName, pNd->u.Method.pszName); 445 588 446 /* 589 447 * Sanity checks on return values. 590 448 */ 591 if ( IDL_tree_property_get(simple_decl, "retval") != NULL) {592 if (IDL_LIST(iter).next != NULL){593 IDL_tree_error(method_tree,594 "only the last parameter can be marked [retval]");595 return FALSE;596 } 597 if ( op->op_type_spec) {598 IDL_tree_error(method_tree,599 "can't have [retval] with non-void return type");600 return FALSE;601 } 449 if (xpidlNodeAttrFind(pIt, "retval") != NULL) 450 { 451 if (!RTListNodeIsLast(&pNd->u.Method.LstParams, &pIt->NdLst)) 452 return xpidlIdlError(pErrInfo, pNd, VERR_INVALID_STATE, 453 "only the last parameter can be marked [retval]"); 454 455 if ( pNd->u.Method.pNdTypeSpecRet->enmType != kXpidlNdType_BaseType 456 || pNd->u.Method.pNdTypeSpecRet->u.enmBaseType != kXpidlType_Void) 457 return xpidlIdlError(pErrInfo, pNd, VERR_INVALID_STATE, 458 "can't have [retval] with non-void return type"); 459 602 460 /* In case XPConnect relaxes the retval-is-last restriction. */ 603 if (seen_retval) { 604 IDL_tree_error(method_tree, 605 "can't have more than one [retval] parameter"); 606 return FALSE; 607 } 608 seen_retval = TRUE; 461 if (seen_retval) 462 return xpidlIdlError(pErrInfo, pNd, VERR_INVALID_STATE, 463 "can't have more than one [retval] parameter"); 464 465 seen_retval = true; 609 466 } 610 467 … … 614 471 * and can't be used with [array]. 615 472 */ 616 if (IDL_tree_property_get(simple_decl, "shared") != NULL) { 617 IDL_tree real_type; 618 real_type = find_underlying_type(param_type); 619 real_type = real_type ? real_type : param_type; 620 621 if (IDL_tree_property_get(simple_decl, "array") != NULL) { 622 IDL_tree_error(method_tree, 623 "[shared] parameter \"%s\" cannot " 624 "be of array type", param_name); 625 return FALSE; 626 } 627 628 if (!(IDL_NODE_TYPE(real_type) == IDLN_TYPE_STRING || 629 IDL_NODE_TYPE(real_type) == IDLN_TYPE_WIDE_STRING || 630 (UP_IS_NATIVE(real_type) && 631 !IDL_tree_property_get(real_type, "nsid") && 632 !IDL_tree_property_get(real_type, "domstring") && 633 !IDL_tree_property_get(real_type, "utf8string") && 634 !IDL_tree_property_get(real_type, "cstring") && 635 !IDL_tree_property_get(real_type, "astring")))) 636 { 637 IDL_tree_error(method_tree, 638 "[shared] parameter \"%s\" must be of type " 639 "string, wstring or native", param_name); 640 return FALSE; 641 } 473 if (xpidlNodeAttrFind(pIt, "shared") != NULL) 474 { 475 if (xpidlNodeAttrFind(pIt, "array") != NULL) 476 return xpidlIdlError(pErrInfo, pIt, VERR_INVALID_STATE, 477 "[shared] parameter \"%s\" cannot be of array type", 478 pIt->u.Param.pszName); 479 480 if ( !( pNdTypeSpec->enmType == kXpidlNdType_BaseType 481 && ( pNdTypeSpec->u.enmBaseType == kXpidlType_String 482 || pNdTypeSpec->u.enmBaseType == kXpidlType_Wide_String)) 483 && !( pNdTypeSpec->enmType == kXpidlNdType_Native 484 && ( !xpidlNodeAttrFind(pNdTypeSpec, "nsid") 485 && !xpidlNodeAttrFind(pNdTypeSpec, "domstring") 486 && !xpidlNodeAttrFind(pNdTypeSpec, "utf8string") 487 && !xpidlNodeAttrFind(pNdTypeSpec, "cstring") 488 && !xpidlNodeAttrFind(pNdTypeSpec, "astring")))) 489 return xpidlIdlError(pErrInfo, pIt, VERR_INVALID_STATE, 490 "[shared] parameter \"%s\" must be of type " 491 "string, wstring or native", pIt->u.Param.pszName); 642 492 } 643 493 … … 646 496 * and "AString" types 647 497 */ 648 if (IDL_PARAM_DCL(param).attr == IDL_PARAM_INOUT && 649 UP_IS_NATIVE(param_type) && 650 (IDL_tree_property_get(param_type, "domstring") != NULL || 651 IDL_tree_property_get(param_type, "utf8string") != NULL || 652 IDL_tree_property_get(param_type, "cstring") != NULL || 653 IDL_tree_property_get(param_type, "astring") != NULL )) { 654 IDL_tree_error(method_tree, 655 "[domstring], [utf8string], [cstring], [astring] " 656 "types cannot be used as inout parameters"); 657 return FALSE; 658 } 659 498 if ( pIt->u.Param.enmDir == kXpidlDirection_InOut 499 && pNdTypeSpec->enmType == kXpidlNdType_Native 500 && ( xpidlNodeAttrFind(pNdTypeSpec, "domstring") != NULL 501 || xpidlNodeAttrFind(pNdTypeSpec, "utf8string") != NULL 502 || xpidlNodeAttrFind(pNdTypeSpec, "cstring") != NULL 503 || xpidlNodeAttrFind(pNdTypeSpec, "astring") != NULL)) 504 return xpidlIdlError(pErrInfo, pIt, VERR_INVALID_STATE, 505 "[domstring], [utf8string], [cstring], [astring] " 506 "types cannot be used as inout parameters"); 660 507 661 508 /* 662 509 * arrays of domstring, utf8string, cstring, astring types not allowed 663 510 */ 664 if ( IDL_tree_property_get(simple_decl, "array") != NULL &&665 UP_IS_NATIVE(param_type) &&666 (IDL_tree_property_get(param_type, "domstring") != NULL ||667 IDL_tree_property_get(param_type, "utf8string") != NULL ||668 IDL_tree_property_get(param_type, "cstring") != NULL ||669 IDL_tree_property_get(param_type, "astring") != NULL)) {670 IDL_tree_error(method_tree,511 if ( xpidlNodeAttrFind(pIt, "array") 512 && pNdTypeSpec->enmType == kXpidlNdType_Native 513 && ( xpidlNodeAttrFind(pNdTypeSpec, "domstring") != NULL 514 || xpidlNodeAttrFind(pNdTypeSpec, "utf8string") != NULL 515 || xpidlNodeAttrFind(pNdTypeSpec, "cstring") != NULL 516 || xpidlNodeAttrFind(pNdTypeSpec, "astring") != NULL)) 517 return xpidlIdlError(pErrInfo, pIt, VERR_INVALID_STATE, 671 518 "[domstring], [utf8string], [cstring], [astring] " 672 519 "types cannot be used in array parameters"); 673 return FALSE; 674 } 675 676 if (!check_param_attribute(method_tree, param, IID_IS) || 677 !check_param_attribute(method_tree, param, LENGTH_IS) || 678 !check_param_attribute(method_tree, param, SIZE_IS)) 679 return FALSE; 680 681 /* 682 * Run additional error checks on the parameter type if targetting an 683 * older version of XPConnect. 684 */ 685 686 if (!verify_type_fits_version(param_type, method_tree)) 687 return FALSE; 688 689 } 690 520 521 rc = check_param_attribute(pNd, pIt, IID_IS, pErrInfo); 522 if (RT_FAILURE(rc)) 523 return rc; 524 rc = check_param_attribute(pNd, pIt, LENGTH_IS, pErrInfo); 525 if (RT_FAILURE(rc)) 526 return rc; 527 rc = check_param_attribute(pNd, pIt, SIZE_IS, pErrInfo); 528 if (RT_FAILURE(rc)) 529 return rc; 530 } 531 532 PCXPIDLNODE pNdTypeSpec = find_underlying_type(pNd->u.Method.pNdTypeSpecRet); 533 pNdTypeSpec = pNdTypeSpec ? pNdTypeSpec : pIt->u.Method.pNdTypeSpecRet; 534 691 535 /* XXX q: can return type be nsid? */ 692 536 /* Native return type? */ 693 if (scriptable_method && 694 op->op_type_spec != NULL && UP_IS_NATIVE(op->op_type_spec) && 695 IDL_tree_property_get(op->op_type_spec, "nsid") == NULL && 696 IDL_tree_property_get(op->op_type_spec, "domstring") == NULL && 697 IDL_tree_property_get(op->op_type_spec, "utf8string") == NULL && 698 IDL_tree_property_get(op->op_type_spec, "cstring") == NULL && 699 IDL_tree_property_get(op->op_type_spec, "astring") == NULL) 700 { 701 IDL_tree_error(method_tree, 702 "methods in [scriptable] interfaces that are " 703 "non-scriptable because they return native " 704 "types must be marked [noscript]"); 705 return FALSE; 706 } 707 537 if ( scriptable_method 538 && pNdTypeSpec->enmType == kXpidlNdType_Native 539 && xpidlNodeAttrFind(pNdTypeSpec, "nsid") == NULL 540 && xpidlNodeAttrFind(pNdTypeSpec, "domstring") == NULL 541 && xpidlNodeAttrFind(pNdTypeSpec, "utf8string") == NULL 542 && xpidlNodeAttrFind(pNdTypeSpec, "cstring") == NULL 543 && xpidlNodeAttrFind(pNdTypeSpec, "astring") == NULL) 544 return xpidlIdlError(pErrInfo, pIt, VERR_INVALID_STATE, 545 "methods in [scriptable] interfaces that are " 546 "non-scriptable because they return native " 547 "types must be marked [noscript]"); 708 548 709 549 /* … … 711 551 * supported in xpcom 712 552 */ 713 if (!notxpcom && 714 op->op_type_spec != NULL && 715 IDL_tree_property_get(op->op_type_spec, "nsid") != NULL && 716 IDL_tree_property_get(op->op_type_spec, "ptr") == NULL && 717 IDL_tree_property_get(op->op_type_spec, "ref") == NULL) 718 { 719 IDL_tree_error(method_tree, 720 "Feature currently not supported: " 721 "return value is of type nsid and " 722 "must be marked either [ptr] or [ref], " 723 "or else method \"%s\" must be marked [notxpcom] ", 724 method_name); 725 return FALSE; 726 } 727 728 /* 729 * Run additional error checks on the return type if targetting an 730 * older version of XPConnect. 731 */ 732 733 if (op->op_type_spec != NULL && 734 !verify_type_fits_version(op->op_type_spec, method_tree)) 735 { 736 return FALSE; 737 } 738 739 return TRUE; 740 } 741 #endif 553 if ( !notxpcom 554 && pNdTypeSpec->enmType == kXpidlNdType_Native 555 && xpidlNodeAttrFind(pNdTypeSpec, "nsid") != NULL 556 && xpidlNodeAttrFind(pNdTypeSpec, "ptr") == NULL 557 && xpidlNodeAttrFind(pNdTypeSpec, "ref") == NULL) 558 return xpidlIdlError(pErrInfo, pIt, VERR_INVALID_STATE, 559 "Feature currently not supported: " 560 "return value is of type nsid and " 561 "must be marked either [ptr] or [ref], " 562 "or else method \"%s\" must be marked [notxpcom] ", 563 pNd->u.Method.pszName); 564 565 return VINF_SUCCESS; 566 } 567 742 568 743 569 /* … … 745 571 * it's of the form native <idl-name>(<c++-name>) 746 572 */ 747 DECLHIDDEN( bool) check_native(PCXPIDLNODE pNd)573 DECLHIDDEN(int) check_native(PCXPIDLNODE pNd, PRTERRINFO pErrInfo) 748 574 { 749 575 Assert(pNd->enmType == kXpidlNdType_Native); … … 751 577 /* require that native declarations give a native type */ 752 578 if (pNd->u.Native.pszNative) 753 return true; 754 755 //IDL_tree_error(state->tree, 756 // "``native %s;'' needs C++ type: ``native %s(<C++ type>);''", 757 // pNd->u.Native.pszName, pNd->u.Native.pszName); 758 return false; 579 return VINF_SUCCESS; 580 581 return xpidlIdlError(pErrInfo, pNd, VERR_INVALID_STATE, 582 "``native %s;'' needs C++ type: ``native %s(<C++ type>);''", 583 pNd->u.Native.pszName, pNd->u.Native.pszName); 759 584 } 760 585 … … 763 588 * Verify that the interface declaration is correct 764 589 */ 765 DECLHIDDEN( bool) verify_interface_declaration(PCXPIDLNODE pNd)590 DECLHIDDEN(int) verify_interface_declaration(PCXPIDLNODE pNd, PRTERRINFO pErrInfo) 766 591 { 767 592 /* … … 770 595 * NOTE: We don't recurse since all interfaces will fall through here 771 596 */ 772 if (xpidlNodeAttrFind(pNd, 597 if (xpidlNodeAttrFind(pNd, "scriptable")) 773 598 { 774 #if 0 775 for (iter = IDL_INTERFACE(interface_tree).inheritance_spec; iter; 776 iter = IDL_LIST(iter).next) { 777 if (IDL_tree_property_get( 778 IDL_INTERFACE(iter).ident, "scriptable") == 0) { 779 XPIDL_WARNING((interface_tree,IDL_WARNING1, 780 "%s is scriptable but inherits from the non-scriptable interface %s\n", 781 IDL_IDENT(IDL_INTERFACE(interface_tree).ident).str, 782 IDL_IDENT(IDL_INTERFACE(iter).ident).str)); 783 } 599 Assert(pNd->enmType == kXpidlNdType_Interface_Def); 600 while (pNd->pNdTypeRef) 601 { 602 if (!xpidlNodeAttrFind(pNd->pNdTypeRef, "scriptable")) 603 return xpidlIdlError(pErrInfo, pNd, VERR_INVALID_STATE, 604 "%s is scriptable but inherits from the non-scriptable interface %s", 605 pNd->u.If.pszIfName, pNd->u.If.pszIfInherit); 606 607 pNd = pNd->pNdTypeRef; 784 608 } 785 #endif 786 } 787 return true; 609 } 610 return VINF_SUCCESS; 788 611 } 789 612
Note:
See TracChangeset
for help on using the changeset viewer.