VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_util.c@ 40504

Last change on this file since 40504 was 40504, checked in by vboxsync, 12 years ago

Solaris 11 build fixes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 29.2 KB
Line 
1/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/* ***** BEGIN LICENSE BLOCK *****
3 * Version: NPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Netscape Public License
6 * Version 1.1 (the "License"); you may not use this file except in
7 * compliance with the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/NPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is mozilla.org code.
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 *
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the NPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the NPL, the GPL or the LGPL.
35 *
36 * ***** END LICENSE BLOCK ***** */
37
38/*
39 * Utility functions called by various backends.
40 */
41
42#include "xpidl.h"
43
44/* XXXbe static */ char OOM[] = "ERROR: out of memory\n";
45
46void *
47xpidl_malloc(size_t nbytes)
48{
49 void *p = malloc(nbytes);
50 if (!p) {
51 fputs(OOM, stderr);
52 exit(1);
53 }
54 return p;
55}
56
57char *
58xpidl_strdup(const char *s)
59{
60#if defined(XP_MAC) || defined(XP_SOLARIS) /* bird: dunno why this is required, but whatever*/
61 size_t len = strlen(s);
62 char *ns = malloc(len + 1);
63 if (ns)
64 memcpy(ns, s, len + 1);
65#else
66 char *ns = strdup(s);
67#endif
68 if (!ns) {
69 fputs(OOM, stderr);
70 exit(1);
71 }
72 return ns;
73}
74
75void
76xpidl_write_comment(TreeState *state, int indent)
77{
78 fprintf(state->file, "%*s/* ", indent, "");
79 IDL_tree_to_IDL(state->tree, state->ns, state->file,
80 IDLF_OUTPUT_NO_NEWLINES |
81 IDLF_OUTPUT_NO_QUALIFY_IDENTS |
82 IDLF_OUTPUT_PROPERTIES);
83 fputs(" */\n", state->file);
84}
85
86/*
87 * Print an iid to into a supplied buffer; the buffer should be at least
88 * UUID_LENGTH bytes.
89 */
90gboolean
91xpidl_sprint_iid(nsID *id, char iidbuf[])
92{
93 int printed;
94
95 printed = sprintf(iidbuf,
96 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
97 (PRUint32) id->m0, (PRUint32) id->m1,(PRUint32) id->m2,
98 (PRUint32) id->m3[0], (PRUint32) id->m3[1],
99 (PRUint32) id->m3[2], (PRUint32) id->m3[3],
100 (PRUint32) id->m3[4], (PRUint32) id->m3[5],
101 (PRUint32) id->m3[6], (PRUint32) id->m3[7]);
102
103#ifdef SPRINTF_RETURNS_STRING
104 return (printed && strlen((char *)printed) == 36);
105#else
106 return (printed == 36);
107#endif
108}
109
110/* We only parse the {}-less format. */
111static const char nsIDFmt2[] =
112 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
113
114/*
115 * Parse a uuid string into an nsID struct. We cannot link against libxpcom,
116 * so we re-implement nsID::Parse here.
117 */
118gboolean
119xpidl_parse_iid(nsID *id, const char *str)
120{
121 PRInt32 count = 0;
122 PRInt32 n1, n2, n3[8];
123 PRInt32 n0, i;
124
125 XPT_ASSERT(str != NULL);
126
127 if (strlen(str) != 36) {
128 return FALSE;
129 }
130
131#ifdef DEBUG_shaver_iid
132 fprintf(stderr, "parsing iid %s\n", str);
133#endif
134
135 count = sscanf(str, nsIDFmt2,
136 &n0, &n1, &n2,
137 &n3[0],&n3[1],&n3[2],&n3[3],
138 &n3[4],&n3[5],&n3[6],&n3[7]);
139
140 id->m0 = (PRInt32) n0;
141 id->m1 = (PRInt16) n1;
142 id->m2 = (PRInt16) n2;
143 for (i = 0; i < 8; i++) {
144 id->m3[i] = (PRInt8) n3[i];
145 }
146
147#ifdef DEBUG_shaver_iid
148 if (count == 11) {
149 fprintf(stderr, "IID parsed to ");
150 print_IID(id, stderr);
151 fputs("\n", stderr);
152 }
153#endif
154 return (gboolean)(count == 11);
155}
156
157gboolean
158verify_const_declaration(IDL_tree const_tree) {
159 struct _IDL_CONST_DCL *dcl = &IDL_CONST_DCL(const_tree);
160 const char *name = IDL_IDENT(dcl->ident).str;
161 IDL_tree real_type;
162
163 /* const -> list -> interface */
164 if (!IDL_NODE_UP(IDL_NODE_UP(const_tree)) ||
165 IDL_NODE_TYPE(IDL_NODE_UP(IDL_NODE_UP(const_tree)))
166 != IDLN_INTERFACE) {
167 IDL_tree_error(const_tree,
168 "const declaration \'%s\' outside interface",
169 name);
170 return FALSE;
171 }
172
173 /* Could be a typedef; try to map it to the real type. */
174 real_type = find_underlying_type(dcl->const_type);
175 real_type = real_type ? real_type : dcl->const_type;
176 if (IDL_NODE_TYPE(real_type) == IDLN_TYPE_INTEGER &&
177 (IDL_TYPE_INTEGER(real_type).f_type == IDL_INTEGER_TYPE_SHORT ||
178 IDL_TYPE_INTEGER(real_type).f_type == IDL_INTEGER_TYPE_LONG))
179 {
180 if (!IDL_TYPE_INTEGER(real_type).f_signed &&
181 IDL_INTEGER(dcl->const_exp).value < 0)
182 {
183#ifndef G_HAVE_GINT64
184 /*
185 * For platforms without longlong support turned on we can get
186 * confused by the high bit of the long value and think that it
187 * represents a negative value in an unsigned declaration.
188 * In that case we don't know if it is the programmer who is
189 * confused or the compiler. So we issue a warning instead of
190 * an error.
191 */
192 if (IDL_TYPE_INTEGER(real_type).f_type == IDL_INTEGER_TYPE_LONG)
193 {
194 XPIDL_WARNING((const_tree, IDL_WARNING1,
195 "unsigned const declaration \'%s\' "
196 "initialized with (possibly) negative constant",
197 name));
198 return TRUE;
199 }
200#endif
201 IDL_tree_error(const_tree,
202 "unsigned const declaration \'%s\' initialized with "
203 "negative constant",
204 name);
205 return FALSE;
206 }
207 } else {
208 IDL_tree_error(const_tree,
209 "const declaration \'%s\' must be of type short or long",
210 name);
211 return FALSE;
212 }
213
214 return TRUE;
215}
216
217
218
219/*
220 * This method consolidates error checking needed when coercing the XPIDL compiler
221 * via the -t flag to generate output for a specific version of XPConnect.
222 */
223static gboolean
224verify_type_fits_version(IDL_tree in_tree, IDL_tree error_tree)
225{
226 if (major_version == 1 && minor_version == 1)
227 {
228 /* XPIDL Version 1.1 checks */
229
230 /* utf8string, cstring, and astring types are not supported */
231 if (IDL_tree_property_get(in_tree, "utf8string") != NULL ||
232 IDL_tree_property_get(in_tree, "cstring") != NULL ||
233 IDL_tree_property_get(in_tree, "astring") != NULL)
234 {
235 IDL_tree_error(error_tree,
236 "Cannot use [utf8string], [cstring] and [astring] "
237 "types when generating version 1.1 typelibs\n");
238 return FALSE;
239 }
240 }
241 return TRUE;
242}
243
244gboolean
245verify_attribute_declaration(IDL_tree attr_tree)
246{
247 IDL_tree iface;
248 IDL_tree ident;
249 IDL_tree attr_type;
250 gboolean scriptable_interface;
251
252 /* We don't support attributes named IID, conflicts with static GetIID
253 * member. The conflict is due to certain compilers (VC++) choosing a
254 * different vtable order, placing GetIID at the beginning regardless
255 * of it's placement
256 */
257 if (strcmp(
258 IDL_IDENT(
259 IDL_LIST(IDL_ATTR_DCL(attr_tree).simple_declarations).data).str,
260 "IID") == 0) {
261 IDL_tree_error(attr_tree,
262 "Attributes named IID not supported, causes vtable "
263 "ordering problems");
264 return FALSE;
265 }
266 /*
267 * Verify that we've been called on an interface, and decide if the
268 * interface was marked [scriptable].
269 */
270 if (IDL_NODE_UP(attr_tree) && IDL_NODE_UP(IDL_NODE_UP(attr_tree)) &&
271 IDL_NODE_TYPE(iface = IDL_NODE_UP(IDL_NODE_UP(attr_tree)))
272 == IDLN_INTERFACE)
273 {
274 scriptable_interface =
275 (IDL_tree_property_get(IDL_INTERFACE(iface).ident, "scriptable")
276 != NULL);
277 } else {
278 IDL_tree_error(attr_tree,
279 "verify_attribute_declaration called on a non-interface?");
280 return FALSE;
281 }
282
283 /*
284 * Grab the first of the list of idents and hope that it'll
285 * say scriptable or no.
286 */
287 ident = IDL_LIST(IDL_ATTR_DCL(attr_tree).simple_declarations).data;
288
289 /*
290 * If the interface isn't scriptable, or the attribute is marked noscript,
291 * there's no need to check.
292 */
293 if (!scriptable_interface ||
294 IDL_tree_property_get(ident, "noscript") != NULL)
295 return TRUE;
296
297 /*
298 * If it should be scriptable, check that the type is non-native. nsid,
299 * domstring, utf8string, cstring, astring are exempted.
300 */
301 attr_type = IDL_ATTR_DCL(attr_tree).param_type_spec;
302
303 if (attr_type != NULL)
304 {
305 if (UP_IS_NATIVE(attr_type) &&
306 IDL_tree_property_get(attr_type, "nsid") == NULL &&
307 IDL_tree_property_get(attr_type, "domstring") == NULL &&
308 IDL_tree_property_get(attr_type, "utf8string") == NULL &&
309 IDL_tree_property_get(attr_type, "cstring") == NULL &&
310 IDL_tree_property_get(attr_type, "astring") == NULL)
311 {
312 IDL_tree_error(attr_tree,
313 "attributes in [scriptable] interfaces that are "
314 "non-scriptable because they refer to native "
315 "types must be marked [noscript]\n");
316 return FALSE;
317 }
318 /*
319 * We currently don't support properties of type nsid that aren't
320 * pointers or references, unless they are marked [notxpcom} and
321 * must be read-only
322 */
323
324 if ((IDL_tree_property_get(ident, "notxpcom") == NULL || !(IDL_ATTR_DCL(attr_tree).f_readonly)) &&
325 IDL_tree_property_get(attr_type,"nsid") != NULL &&
326 IDL_tree_property_get(attr_type,"ptr") == NULL &&
327 IDL_tree_property_get(attr_type,"ref") == NULL)
328 {
329 IDL_tree_error(attr_tree,
330 "Feature not currently supported: "
331 "attributes with a type of nsid must be marked "
332 "either [ptr] or [ref], or "
333 "else must be marked [notxpcom] "
334 "and must be read-only\n");
335 return FALSE;
336 }
337
338 /*
339 * Run additional error checks on the attribute type if targetting an
340 * older version of XPConnect.
341 */
342
343 if (!verify_type_fits_version(attr_type, attr_tree))
344 return FALSE;
345 }
346
347 if (IDL_LIST(IDL_ATTR_DCL(attr_tree).simple_declarations).next != NULL)
348 {
349 IDL_tree_error(attr_tree,
350 "multiple attributes in a single declaration is not supported\n");
351 return FALSE;
352 }
353 return TRUE;
354}
355
356/*
357 * Find the underlying type of an identifier typedef.
358 *
359 * All the needed tree-walking seems pretty shaky; isn't there something in
360 * libIDL to automate this?
361 */
362IDL_tree /* IDL_TYPE_DCL */
363find_underlying_type(IDL_tree typedef_ident)
364{
365 IDL_tree up;
366
367 if (typedef_ident == NULL || IDL_NODE_TYPE(typedef_ident) != IDLN_IDENT)
368 return NULL;
369
370 up = IDL_NODE_UP(typedef_ident);
371 if (up == NULL || IDL_NODE_TYPE(up) != IDLN_LIST)
372 return NULL;
373 up = IDL_NODE_UP(up);
374 if (up == NULL || IDL_NODE_TYPE(up) != IDLN_TYPE_DCL)
375 return NULL;
376
377 return IDL_TYPE_DCL(up).type_spec;
378}
379
380static IDL_tree /* IDL_PARAM_DCL */
381find_named_parameter(IDL_tree method_tree, const char *param_name)
382{
383 IDL_tree iter;
384 for (iter = IDL_OP_DCL(method_tree).parameter_dcls; iter;
385 iter = IDL_LIST(iter).next)
386 {
387 IDL_tree param = IDL_LIST(iter).data;
388 IDL_tree simple_decl = IDL_PARAM_DCL(param).simple_declarator;
389 const char *current_name = IDL_IDENT(simple_decl).str;
390 if (strcmp(current_name, param_name) == 0)
391 return param;
392 }
393 return NULL;
394}
395
396typedef enum ParamAttrType {
397 IID_IS,
398 LENGTH_IS,
399 SIZE_IS
400} ParamAttrType;
401
402/*
403 * Check that parameters referred to by attributes such as size_is exist and
404 * refer to parameters of the appropriate type.
405 */
406static gboolean
407check_param_attribute(IDL_tree method_tree, IDL_tree param,
408 ParamAttrType whattocheck)
409{
410 const char *method_name = IDL_IDENT(IDL_OP_DCL(method_tree).ident).str;
411 const char *referred_name = NULL;
412 IDL_tree param_type = IDL_PARAM_DCL(param).param_type_spec;
413 IDL_tree simple_decl = IDL_PARAM_DCL(param).simple_declarator;
414 const char *param_name = IDL_IDENT(simple_decl).str;
415 const char *attr_name;
416 const char *needed_type;
417
418 if (whattocheck == IID_IS) {
419 attr_name = "iid_is";
420 needed_type = "IID";
421 } else if (whattocheck == LENGTH_IS) {
422 attr_name = "length_is";
423 needed_type = "unsigned long (or PRUint32)";
424 } else if (whattocheck == SIZE_IS) {
425 attr_name = "size_is";
426 needed_type = "unsigned long (or PRUint32)";
427 } else {
428 XPT_ASSERT("asked to check an unknown attribute type!");
429 return TRUE;
430 }
431
432 referred_name = IDL_tree_property_get(simple_decl, attr_name);
433 if (referred_name != NULL) {
434 IDL_tree referred_param = find_named_parameter(method_tree,
435 referred_name);
436 IDL_tree referred_param_type;
437 if (referred_param == NULL) {
438 IDL_tree_error(method_tree,
439 "attribute [%s(%s)] refers to missing "
440 "parameter \"%s\"",
441 attr_name, referred_name, referred_name);
442 return FALSE;
443 }
444 if (referred_param == param) {
445 IDL_tree_error(method_tree,
446 "attribute [%s(%s)] refers to it's own parameter",
447 attr_name, referred_name);
448 return FALSE;
449 }
450
451 referred_param_type = IDL_PARAM_DCL(referred_param).param_type_spec;
452 if (whattocheck == IID_IS) {
453 /* require IID type */
454 if (IDL_tree_property_get(referred_param_type, "nsid") == NULL) {
455 IDL_tree_error(method_tree,
456 "target \"%s\" of [%s(%s)] attribute "
457 "must be of %s type",
458 referred_name, attr_name, referred_name,
459 needed_type);
460 return FALSE;
461 }
462 } else if (whattocheck == LENGTH_IS || whattocheck == SIZE_IS) {
463 /* require PRUint32 type */
464 IDL_tree real_type;
465
466 /* Could be a typedef; try to map it to the real type. */
467 real_type = find_underlying_type(referred_param_type);
468 real_type = real_type ? real_type : referred_param_type;
469
470 if (IDL_NODE_TYPE(real_type) != IDLN_TYPE_INTEGER ||
471 IDL_TYPE_INTEGER(real_type).f_signed != FALSE ||
472 IDL_TYPE_INTEGER(real_type).f_type != IDL_INTEGER_TYPE_LONG)
473 {
474 IDL_tree_error(method_tree,
475 "target \"%s\" of [%s(%s)] attribute "
476 "must be of %s type",
477 referred_name, attr_name, referred_name,
478 needed_type);
479
480 return FALSE;
481 }
482 }
483 }
484
485 return TRUE;
486}
487
488
489/*
490 * Common method verification code, called by *op_dcl in the various backends.
491 */
492gboolean
493verify_method_declaration(IDL_tree method_tree)
494{
495 struct _IDL_OP_DCL *op = &IDL_OP_DCL(method_tree);
496 IDL_tree iface;
497 IDL_tree iter;
498 gboolean notxpcom;
499 gboolean scriptable_interface;
500 gboolean scriptable_method;
501 gboolean seen_retval = FALSE;
502 const char *method_name = IDL_IDENT(IDL_OP_DCL(method_tree).ident).str;
503
504 /* We don't support attributes named IID, conflicts with static GetIID
505 * member. The conflict is due to certain compilers (VC++) choosing a
506 * different vtable order, placing GetIID at the beginning regardless
507 * of it's placement
508 */
509 if (strcmp(method_name, "GetIID") == 0) {
510 IDL_tree_error(method_tree,
511 "Methods named GetIID not supported, causes vtable "
512 "ordering problems");
513 return FALSE;
514 }
515 if (op->f_varargs) {
516 /* We don't currently support varargs. */
517 IDL_tree_error(method_tree, "varargs are not currently supported");
518 return FALSE;
519 }
520
521 /*
522 * Verify that we've been called on an interface, and decide if the
523 * interface was marked [scriptable].
524 */
525 if (IDL_NODE_UP(method_tree) && IDL_NODE_UP(IDL_NODE_UP(method_tree)) &&
526 IDL_NODE_TYPE(iface = IDL_NODE_UP(IDL_NODE_UP(method_tree)))
527 == IDLN_INTERFACE)
528 {
529 scriptable_interface =
530 (IDL_tree_property_get(IDL_INTERFACE(iface).ident, "scriptable")
531 != NULL);
532 } else {
533 IDL_tree_error(method_tree,
534 "verify_method_declaration called on a non-interface?");
535 return FALSE;
536 }
537
538 /*
539 * Require that any method in an interface marked as [scriptable], that
540 * *isn't* scriptable because it refers to some native type, be marked
541 * [noscript] or [notxpcom].
542 *
543 * Also check that iid_is points to nsid, and length_is, size_is points
544 * to unsigned long.
545 */
546 notxpcom = IDL_tree_property_get(op->ident, "notxpcom") != NULL;
547
548 scriptable_method = scriptable_interface &&
549 !notxpcom &&
550 IDL_tree_property_get(op->ident, "noscript") == NULL;
551
552 /* Loop through the parameters and check. */
553 for (iter = op->parameter_dcls; iter; iter = IDL_LIST(iter).next) {
554 IDL_tree param = IDL_LIST(iter).data;
555 IDL_tree param_type =
556 IDL_PARAM_DCL(param).param_type_spec;
557 IDL_tree simple_decl =
558 IDL_PARAM_DCL(param).simple_declarator;
559 const char *param_name = IDL_IDENT(simple_decl).str;
560
561 /*
562 * Reject this method if it should be scriptable and some parameter is
563 * native that isn't marked with either nsid, domstring, utf8string,
564 * cstring, astring or iid_is.
565 */
566 if (scriptable_method &&
567 UP_IS_NATIVE(param_type) &&
568 IDL_tree_property_get(param_type, "nsid") == NULL &&
569 IDL_tree_property_get(simple_decl, "iid_is") == NULL &&
570 IDL_tree_property_get(param_type, "domstring") == NULL &&
571 IDL_tree_property_get(param_type, "utf8string") == NULL &&
572 IDL_tree_property_get(param_type, "cstring") == NULL &&
573 IDL_tree_property_get(param_type, "astring") == NULL)
574 {
575 IDL_tree_error(method_tree,
576 "methods in [scriptable] interfaces that are "
577 "non-scriptable because they refer to native "
578 "types (parameter \"%s\") must be marked "
579 "[noscript]", param_name);
580 return FALSE;
581 }
582
583 /*
584 * nsid's parameters that aren't ptr's or ref's are not currently
585 * supported in xpcom or non-xpcom (marked with [notxpcom]) methods
586 * as input parameters
587 */
588 if (!(notxpcom && IDL_PARAM_DCL(param).attr != IDL_PARAM_IN) &&
589 IDL_tree_property_get(param_type, "nsid") != NULL &&
590 IDL_tree_property_get(param_type, "ptr") == NULL &&
591 IDL_tree_property_get(param_type, "ref") == NULL)
592 {
593 IDL_tree_error(method_tree,
594 "Feature currently not supported: "
595 "parameter \"%s\" is of type nsid and "
596 "must be marked either [ptr] or [ref] "
597 "or method \"%s\" must be marked [notxpcom] "
598 "and must not be an input parameter",
599 param_name,
600 method_name);
601 return FALSE;
602 }
603 /*
604 * Sanity checks on return values.
605 */
606 if (IDL_tree_property_get(simple_decl, "retval") != NULL) {
607 if (IDL_LIST(iter).next != NULL) {
608 IDL_tree_error(method_tree,
609 "only the last parameter can be marked [retval]");
610 return FALSE;
611 }
612 if (op->op_type_spec) {
613 IDL_tree_error(method_tree,
614 "can't have [retval] with non-void return type");
615 return FALSE;
616 }
617 /* In case XPConnect relaxes the retval-is-last restriction. */
618 if (seen_retval) {
619 IDL_tree_error(method_tree,
620 "can't have more than one [retval] parameter");
621 return FALSE;
622 }
623 seen_retval = TRUE;
624 }
625
626 /*
627 * Confirm that [shared] attributes are only used with string, wstring,
628 * or native (but not nsid, domstring, utf8string, cstring or astring)
629 * and can't be used with [array].
630 */
631 if (IDL_tree_property_get(simple_decl, "shared") != NULL) {
632 IDL_tree real_type;
633 real_type = find_underlying_type(param_type);
634 real_type = real_type ? real_type : param_type;
635
636 if (IDL_tree_property_get(simple_decl, "array") != NULL) {
637 IDL_tree_error(method_tree,
638 "[shared] parameter \"%s\" cannot "
639 "be of array type", param_name);
640 return FALSE;
641 }
642
643 if (!(IDL_NODE_TYPE(real_type) == IDLN_TYPE_STRING ||
644 IDL_NODE_TYPE(real_type) == IDLN_TYPE_WIDE_STRING ||
645 (UP_IS_NATIVE(real_type) &&
646 !IDL_tree_property_get(real_type, "nsid") &&
647 !IDL_tree_property_get(real_type, "domstring") &&
648 !IDL_tree_property_get(real_type, "utf8string") &&
649 !IDL_tree_property_get(real_type, "cstring") &&
650 !IDL_tree_property_get(real_type, "astring"))))
651 {
652 IDL_tree_error(method_tree,
653 "[shared] parameter \"%s\" must be of type "
654 "string, wstring or native", param_name);
655 return FALSE;
656 }
657 }
658
659 /*
660 * inout is not allowed with "domstring", "UTF8String", "CString"
661 * and "AString" types
662 */
663 if (IDL_PARAM_DCL(param).attr == IDL_PARAM_INOUT &&
664 UP_IS_NATIVE(param_type) &&
665 (IDL_tree_property_get(param_type, "domstring") != NULL ||
666 IDL_tree_property_get(param_type, "utf8string") != NULL ||
667 IDL_tree_property_get(param_type, "cstring") != NULL ||
668 IDL_tree_property_get(param_type, "astring") != NULL )) {
669 IDL_tree_error(method_tree,
670 "[domstring], [utf8string], [cstring], [astring] "
671 "types cannot be used as inout parameters");
672 return FALSE;
673 }
674
675
676 /*
677 * arrays of domstring, utf8string, cstring, astring types not allowed
678 */
679 if (IDL_tree_property_get(simple_decl, "array") != NULL &&
680 UP_IS_NATIVE(param_type) &&
681 (IDL_tree_property_get(param_type, "domstring") != NULL ||
682 IDL_tree_property_get(param_type, "utf8string") != NULL ||
683 IDL_tree_property_get(param_type, "cstring") != NULL ||
684 IDL_tree_property_get(param_type, "astring") != NULL)) {
685 IDL_tree_error(method_tree,
686 "[domstring], [utf8string], [cstring], [astring] "
687 "types cannot be used in array parameters");
688 return FALSE;
689 }
690
691 if (!check_param_attribute(method_tree, param, IID_IS) ||
692 !check_param_attribute(method_tree, param, LENGTH_IS) ||
693 !check_param_attribute(method_tree, param, SIZE_IS))
694 return FALSE;
695
696 /*
697 * Run additional error checks on the parameter type if targetting an
698 * older version of XPConnect.
699 */
700
701 if (!verify_type_fits_version(param_type, method_tree))
702 return FALSE;
703
704 }
705
706 /* XXX q: can return type be nsid? */
707 /* Native return type? */
708 if (scriptable_method &&
709 op->op_type_spec != NULL && UP_IS_NATIVE(op->op_type_spec) &&
710 IDL_tree_property_get(op->op_type_spec, "nsid") == NULL &&
711 IDL_tree_property_get(op->op_type_spec, "domstring") == NULL &&
712 IDL_tree_property_get(op->op_type_spec, "utf8string") == NULL &&
713 IDL_tree_property_get(op->op_type_spec, "cstring") == NULL &&
714 IDL_tree_property_get(op->op_type_spec, "astring") == NULL)
715 {
716 IDL_tree_error(method_tree,
717 "methods in [scriptable] interfaces that are "
718 "non-scriptable because they return native "
719 "types must be marked [noscript]");
720 return FALSE;
721 }
722
723
724 /*
725 * nsid's parameters that aren't ptr's or ref's are not currently
726 * supported in xpcom
727 */
728 if (!notxpcom &&
729 op->op_type_spec != NULL &&
730 IDL_tree_property_get(op->op_type_spec, "nsid") != NULL &&
731 IDL_tree_property_get(op->op_type_spec, "ptr") == NULL &&
732 IDL_tree_property_get(op->op_type_spec, "ref") == NULL)
733 {
734 IDL_tree_error(method_tree,
735 "Feature currently not supported: "
736 "return value is of type nsid and "
737 "must be marked either [ptr] or [ref], "
738 "or else method \"%s\" must be marked [notxpcom] ",
739 method_name);
740 return FALSE;
741 }
742
743 /*
744 * Run additional error checks on the return type if targetting an
745 * older version of XPConnect.
746 */
747
748 if (op->op_type_spec != NULL &&
749 !verify_type_fits_version(op->op_type_spec, method_tree))
750 {
751 return FALSE;
752 }
753
754 return TRUE;
755}
756
757/*
758 * Verify that a native declaration has an associated C++ expression, i.e. that
759 * it's of the form native <idl-name>(<c++-name>)
760 */
761gboolean
762check_native(TreeState *state)
763{
764 char *native_name;
765 /* require that native declarations give a native type */
766 if (IDL_NATIVE(state->tree).user_type)
767 return TRUE;
768 native_name = IDL_IDENT(IDL_NATIVE(state->tree).ident).str;
769 IDL_tree_error(state->tree,
770 "``native %s;'' needs C++ type: ``native %s(<C++ type>);''",
771 native_name, native_name);
772 return FALSE;
773}
774
775/*
776 * Print a GSList as char strings to a file.
777 */
778void
779printlist(FILE *outfile, GSList *slist)
780{
781 guint i;
782 guint len = g_slist_length(slist);
783
784 for(i = 0; i < len; i++) {
785 fprintf(outfile,
786 "%s\n", (char *)g_slist_nth_data(slist, i));
787 }
788}
789
790void
791xpidl_list_foreach(IDL_tree p, IDL_tree_func foreach, gpointer user_data)
792{
793 IDL_tree_func_data tfd;
794
795 while (p) {
796 struct _IDL_LIST *list = &IDL_LIST(p);
797 tfd.tree = list->data;
798 if (!foreach(&tfd, user_data))
799 return;
800 p = list->next;
801 }
802}
803
804/*
805 * Verify that the interface declaration is correct
806 */
807gboolean
808verify_interface_declaration(IDL_tree interface_tree)
809{
810 IDL_tree iter;
811 /*
812 * If we have the scriptable attribute then make sure all of our direct
813 * parents have it as well.
814 * NOTE: We don't recurse since all interfaces will fall through here
815 */
816 if (IDL_tree_property_get(IDL_INTERFACE(interface_tree).ident,
817 "scriptable")) {
818 for (iter = IDL_INTERFACE(interface_tree).inheritance_spec; iter;
819 iter = IDL_LIST(iter).next) {
820 if (IDL_tree_property_get(
821 IDL_INTERFACE(iter).ident, "scriptable") == 0) {
822 XPIDL_WARNING((interface_tree,IDL_WARNING1,
823 "%s is scriptable but inherits from the non-scriptable interface %s\n",
824 IDL_IDENT(IDL_INTERFACE(interface_tree).ident).str,
825 IDL_IDENT(IDL_INTERFACE(iter).ident).str));
826 }
827 }
828 }
829 return TRUE;
830}
831
832/*
833 * Return a pointer to the start of the base filename of path
834 */
835const char *
836xpidl_basename(const char * path)
837{
838 const char * result = g_basename(path);
839 /*
840 *If this is windows then we'll handle either / or \ as a separator
841 * g_basename only handles \ for windows
842 */
843#if defined(XP_WIN32)
844 const char * slash = strrchr(path, '/');
845 /* If we found a slash and its after the current default OS separator */
846 if (slash != NULL && (slash > result))
847 result = slash + 1;
848#endif
849 return result;
850}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use