VirtualBox

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

Last change on this file since 4837 was 4837, checked in by vboxsync, 17 years ago

Solaris

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

© 2023 Oracle
ContactPrivacy policyTerms of Use