1
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/* ***** BEGIN LICENSE BLOCK *****
3
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
5
* The contents of this file are subject to the Mozilla Public License Version
6
* 1.1 (the "License"); you may not use this file except in compliance with
7
* the License. You may obtain a copy of the License at
8
* http://www.mozilla.org/MPL/
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
15
* The Original Code is mozilla.org code.
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.
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 MPL, 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 MPL, the GPL or the LGPL.
36
* ***** END LICENSE BLOCK ***** */
39
* Generate typelib files for use with InterfaceInfo.
40
* http://www.mozilla.org/scriptable/typelib_file.html
45
#include <xpt_struct.h>
46
#include <time.h> /* XXX XP? */
51
GHashTable *interface_map;
52
XPTInterfaceDescriptor *current;
56
uint16 next_type; /* used for 'additional_types' for idl arrays */
59
#define HEADER(state) (((struct priv_data *)state->priv)->header)
60
#define IFACES(state) (((struct priv_data *)state->priv)->ifaces)
61
#define IFACE_MAP(state) (((struct priv_data *)state->priv)->interface_map)
62
#define CURRENT(state) (((struct priv_data *)state->priv)->current)
63
#define ARENA(state) (((struct priv_data *)state->priv)->arena)
64
#define NEXT_METH(state) (((struct priv_data *)state->priv)->next_method)
65
#define NEXT_CONST(state) (((struct priv_data *)state->priv)->next_const)
66
#define NEXT_TYPE(state) (((struct priv_data *)state->priv)->next_type)
69
/* #define DEBUG_shaver_sort */
77
gboolean is_forward_dcl;
80
static NewInterfaceHolder*
81
CreateNewInterfaceHolder(char *name, char *name_space, char *iid,
82
gboolean is_forward_dcl)
84
NewInterfaceHolder *holder = calloc(1, sizeof(NewInterfaceHolder));
86
holder->is_forward_dcl = is_forward_dcl;
88
holder->name = xpidl_strdup(name);
90
holder->name_space = xpidl_strdup(name_space);
91
if (holder->name && holder->name_space) {
92
holder->full_name = calloc(1, strlen(holder->name) +
93
strlen(holder->name_space) + 2);
95
if (holder->full_name) {
96
strcpy(holder->full_name, holder->name_space);
97
strcat(holder->full_name, ".");
98
strcat(holder->full_name, holder->name);
101
holder->full_name = holder->name;
103
holder->iid = xpidl_strdup(iid);
109
DeleteNewInterfaceHolder(NewInterfaceHolder *holder)
112
if (holder->full_name && holder->full_name != holder->name)
113
free(holder->full_name);
116
if (holder->name_space)
117
free(holder->name_space);
125
* If p is an ident for an interface, and we don't have an entry in the
126
* interface map yet, add one.
129
add_interface_maybe(IDL_tree_func_data *tfd, gpointer user_data)
131
TreeState *state = user_data;
133
if (IDL_NODE_TYPE(tfd->tree) == IDLN_IDENT) {
134
IDL_tree_type node_type = IDL_NODE_TYPE((up = IDL_NODE_UP(tfd->tree)));
135
if (node_type == IDLN_INTERFACE || node_type == IDLN_FORWARD_DCL) {
137
/* We only want to add a new entry if there is no entry by this
138
* name or if the previously found entry was just a forward
139
* declaration and the new entry is not.
142
char *iface = IDL_IDENT(tfd->tree).str;
143
NewInterfaceHolder *old_holder = (NewInterfaceHolder *)
144
g_hash_table_lookup(IFACE_MAP(state), iface);
145
if (old_holder && old_holder->is_forward_dcl &&
146
node_type != IDLN_FORWARD_DCL)
148
g_hash_table_remove(IFACE_MAP(state), iface);
149
DeleteNewInterfaceHolder(old_holder);
153
/* XXX should we parse here and store a struct nsID *? */
154
char *iid = (char *)IDL_tree_property_get(tfd->tree, "uuid");
155
char *name_space = (char *)
156
IDL_tree_property_get(tfd->tree, "namespace");
157
NewInterfaceHolder *holder =
158
CreateNewInterfaceHolder(iface, name_space, iid,
159
(gboolean) node_type == IDLN_FORWARD_DCL);
162
g_hash_table_insert(IFACE_MAP(state),
163
holder->full_name, holder);
165
#ifdef DEBUG_shaver_ifaces
166
fprintf(stderr, "adding interface #%d: %s/%s\n", IFACES(state),
167
iface, iid[0] ? iid : "<unresolved>");
171
#ifdef DEBUG_shaver_ifaces
172
fprintf(stderr, "ident %s isn't an interface (%s)\n",
173
IDL_IDENT(tfd->tree).str, IDL_NODE_TYPE_NAME(up));
181
/* Find all the interfaces referenced in the tree (uses add_interface_maybe) */
183
find_interfaces(IDL_tree_func_data *tfd, gpointer user_data)
185
IDL_tree node = NULL;
187
switch (IDL_NODE_TYPE(tfd->tree)) {
189
node = IDL_ATTR_DCL(tfd->tree).param_type_spec;
192
IDL_tree_walk_in_order(IDL_OP_DCL(tfd->tree).parameter_dcls, find_interfaces,
194
node = IDL_OP_DCL(tfd->tree).op_type_spec;
197
node = IDL_PARAM_DCL(tfd->tree).param_type_spec;
200
node = IDL_INTERFACE(tfd->tree).inheritance_spec;
202
xpidl_list_foreach(node, add_interface_maybe, user_data);
203
node = IDL_INTERFACE(tfd->tree).ident;
205
case IDLN_FORWARD_DCL:
206
node = IDL_FORWARD_DCL(tfd->tree).ident;
212
if (node && IDL_NODE_TYPE(node) == IDLN_IDENT) {
213
IDL_tree_func_data new_tfd;
215
add_interface_maybe(&new_tfd, user_data);
222
/* for calling from gdb */
224
print_IID(struct nsID *iid, FILE *file)
226
char iid_buf[UUID_LENGTH];
228
xpidl_sprint_iid(iid, iid_buf);
229
fprintf(file, "%s\n", iid_buf);
233
/* fill the interface_directory IDE table from the interface_map */
235
fill_ide_table(gpointer key, gpointer value, gpointer user_data)
237
TreeState *state = user_data;
238
NewInterfaceHolder *holder = (NewInterfaceHolder *) value;
240
XPTInterfaceDirectoryEntry *ide;
244
#ifdef DEBUG_shaver_ifaces
245
fprintf(stderr, "filling %s\n", holder->full_name);
249
if (strlen(holder->iid) != 36) {
250
IDL_tree_error(state->tree, "IID %s is the wrong length\n",
254
if (!xpidl_parse_iid(&id, holder->iid)) {
255
IDL_tree_error(state->tree, "cannot parse IID %s\n", holder->iid);
259
memset(&id, 0, sizeof(id));
262
ide = &(HEADER(state)->interface_directory[IFACES(state)]);
263
if (!XPT_FillInterfaceDirectoryEntry(ARENA(state), ide, &id, holder->name,
264
holder->name_space, NULL)) {
265
IDL_tree_error(state->tree, "INTERNAL: XPT_FillIDE failed for %s\n",
271
DeleteNewInterfaceHolder(holder);
276
compare_IDEs(const void *ap, const void *bp)
278
const XPTInterfaceDirectoryEntry *a = ap, *b = bp;
279
const nsID *aid = &a->iid, *bid = &b->iid;
280
const char *ans, *bns;
283
#define COMPARE(field) if (aid->field > bid->field) return 1; \
284
if (bid->field > aid->field) return -1;
288
for (i = 0; i < 8; i++) {
292
/* defend against NULL name_space by using empty string. */
293
ans = a->name_space ? a->name_space : "";
294
bns = b->name_space ? b->name_space : "";
296
if (a->name_space && b->name_space) {
297
if ((i = strcmp(a->name_space, b->name_space)))
300
if (a->name_space || b->name_space) {
306
/* these had better not be NULL... */
307
return strcmp(a->name, b->name);
311
/* sort the IDE block as per the typelib spec: IID order, unresolved first */
313
sort_ide_block(TreeState *state)
315
XPTInterfaceDirectoryEntry *ide;
318
/* boy, I sure hope qsort works correctly everywhere */
319
#ifdef DEBUG_shaver_sort
320
fputs("before sort:\n", stderr);
321
for (i = 0; i < IFACES(state); i++) {
323
print_IID(&HEADER(state)->interface_directory[i].iid, stderr);
327
qsort(HEADER(state)->interface_directory, IFACES(state),
328
sizeof(*ide), compare_IDEs);
329
#ifdef DEBUG_shaver_sort
330
fputs("after sort:\n", stderr);
331
for (i = 0; i < IFACES(state); i++) {
333
print_IID(&HEADER(state)->interface_directory[i].iid, stderr);
338
for (i = 0; i < IFACES(state); i++) {
339
ide = HEADER(state)->interface_directory + i;
340
g_hash_table_insert(IFACE_MAP(state), ide->name, (void *)(i + 1));
347
typelib_list(TreeState *state)
350
for (iter = state->tree; iter; iter = IDL_LIST(iter).next) {
351
state->tree = IDL_LIST(iter).data;
352
if (!xpidl_process_node(state))
359
typelib_prolog(TreeState *state)
361
state->priv = calloc(1, sizeof(struct priv_data));
365
IFACE_MAP(state) = g_hash_table_new(g_str_hash, g_str_equal);
366
if (!IFACE_MAP(state)) {
367
/* XXX report error */
371
/* find all interfaces, top-level and referenced by others */
372
IDL_tree_walk_in_order(state->tree, find_interfaces, state);
373
ARENA(state) = XPT_NewArena(1024, sizeof(double), "main xpidl arena");
374
HEADER(state) = XPT_NewHeader(ARENA(state), IFACES(state),
375
major_version, minor_version);
377
/* fill IDEs from hash table */
379
g_hash_table_foreach_remove(IFACE_MAP(state), fill_ide_table, state);
381
/* if any are left then we must have failed in fill_ide_table */
382
if (g_hash_table_size(IFACE_MAP(state)))
385
/* sort the IDEs by IID order and store indices in the interface map */
386
sort_ide_block(state);
392
typelib_epilog(TreeState *state)
394
XPTState *xstate = XPT_NewXDRState(XPT_ENCODE, NULL, 0);
395
XPTCursor curs, *cursor = &curs;
396
PRUint32 i, len, header_sz;
401
/* Write any annotations */
402
if (emit_typelib_annotations) {
403
PRUint32 annotation_len, written_so_far;
404
char *annotate_val, *timestr;
406
static char *annotation_format =
407
"Created from %s.idl\nCreation date: %sInterfaces:";
409
/* fill in the annotations, listing resolved interfaces in order */
412
timestr = ctime(&now);
414
/* Avoid dependence on nspr; no PR_smprintf and friends. */
416
/* How large should the annotation string be? */
417
annotation_len = strlen(annotation_format) + strlen(state->basename) +
419
for (i = 0; i < HEADER(state)->num_interfaces; i++) {
420
XPTInterfaceDirectoryEntry *ide;
421
ide = &HEADER(state)->interface_directory[i];
422
if (ide->interface_descriptor) {
423
annotation_len += strlen(ide->name) + 1;
427
annotate_val = (char *) malloc(annotation_len);
428
written_so_far = sprintf(annotate_val, annotation_format,
429
state->basename, timestr);
431
for (i = 0; i < HEADER(state)->num_interfaces; i++) {
432
XPTInterfaceDirectoryEntry *ide;
433
ide = &HEADER(state)->interface_directory[i];
434
if (ide->interface_descriptor) {
435
written_so_far += sprintf(annotate_val + written_so_far, " %s",
440
HEADER(state)->annotations =
441
XPT_NewAnnotation(ARENA(state),
442
XPT_ANN_LAST | XPT_ANN_PRIVATE,
443
XPT_NewStringZ(ARENA(state), "xpidl 0.99.9"),
444
XPT_NewStringZ(ARENA(state), annotate_val));
447
HEADER(state)->annotations =
448
XPT_NewAnnotation(ARENA(state), XPT_ANN_LAST, NULL, NULL);
451
if (!HEADER(state)->annotations) {
452
/* XXX report out of memory error */
456
/* Write the typelib */
457
header_sz = XPT_SizeOfHeaderBlock(HEADER(state));
460
!XPT_MakeCursor(xstate, XPT_HEADER, header_sz, cursor))
462
oldOffset = cursor->offset;
463
if (!XPT_DoHeader(ARENA(state), cursor, &HEADER(state)))
465
newOffset = cursor->offset;
466
XPT_GetXDRDataLength(xstate, XPT_HEADER, &len);
467
HEADER(state)->file_length = len;
468
XPT_GetXDRDataLength(xstate, XPT_DATA, &len);
469
HEADER(state)->file_length += len;
470
XPT_SeekTo(cursor, oldOffset);
471
if (!XPT_DoHeaderPrologue(ARENA(state), cursor, &HEADER(state), NULL))
473
XPT_SeekTo(cursor, newOffset);
474
XPT_GetXDRData(xstate, XPT_HEADER, &data, &len);
475
fwrite(data, len, 1, state->file);
476
XPT_GetXDRData(xstate, XPT_DATA, &data, &len);
477
fwrite(data, len, 1, state->file);
480
XPT_DestroyXDRState(xstate);
482
/* XXX XPT_DestroyHeader(HEADER(state)) */
484
XPT_FreeHeader(ARENA(state), HEADER(state));
485
XPT_DestroyArena(ARENA(state));
487
/* XXX should destroy priv_data here */
492
static XPTInterfaceDirectoryEntry *
493
FindInterfaceByName(XPTInterfaceDirectoryEntry *ides, uint16 num_interfaces,
497
for (i = 0; i < num_interfaces; i++) {
498
if (!strcmp(ides[i].name, name))
505
typelib_interface(TreeState *state)
507
IDL_tree iface = state->tree, iter;
508
char *name = IDL_IDENT(IDL_INTERFACE(iface).ident).str;
509
XPTInterfaceDirectoryEntry *ide;
510
XPTInterfaceDescriptor *id;
511
uint16 parent_id = 0;
512
PRUint8 interface_flags = 0;
514
if (!verify_interface_declaration(iface))
517
if (IDL_tree_property_get(IDL_INTERFACE(iface).ident, "scriptable"))
518
interface_flags |= XPT_ID_SCRIPTABLE;
520
if (IDL_tree_property_get(IDL_INTERFACE(iface).ident, "function"))
521
interface_flags |= XPT_ID_FUNCTION;
523
ide = FindInterfaceByName(HEADER(state)->interface_directory,
524
HEADER(state)->num_interfaces, name);
526
IDL_tree_error(iface, "ERROR: didn't find interface %s in "
527
"IDE block. Giving up.\n", name);
531
if ((iter = IDL_INTERFACE(iface).inheritance_spec)) {
533
if (IDL_LIST(iter).next) {
534
IDL_tree_error(iface,
535
"ERROR: more than one parent interface for %s\n",
539
parent = IDL_IDENT(IDL_LIST(iter).data).str;
540
parent_id = (uint16)(uint32)g_hash_table_lookup(IFACE_MAP(state),
543
IDL_tree_error(iface,
544
"ERROR: no index found for %s. Giving up.\n",
550
id = XPT_NewInterfaceDescriptor(ARENA(state), parent_id, 0, 0,
555
CURRENT(state) = ide->interface_descriptor = id;
556
#ifdef DEBUG_shaver_ifaces
557
fprintf(stderr, "DBG: starting interface %s @ %p\n", name, id);
560
NEXT_METH(state) = 0;
561
NEXT_CONST(state) = 0;
562
NEXT_TYPE(state) = 0;
564
state->tree = IDL_INTERFACE(iface).body;
565
if (state->tree && !xpidl_process_node(state))
567
#ifdef DEBUG_shaver_ifaces
568
fprintf(stderr, "DBG: ending interface %s\n", name);
574
find_arg_with_name(TreeState *state, const char *name, int16 *argnum)
583
params = IDL_OP_DCL(IDL_NODE_UP(IDL_NODE_UP(state->tree))).parameter_dcls;
585
params != NULL && IDL_LIST(params).data != NULL;
586
params = IDL_LIST(params).next, count++)
588
const char *cur_name = IDL_IDENT(
589
IDL_PARAM_DCL(IDL_LIST(params).data).simple_declarator).str;
590
if (!strcmp(cur_name, name)) {
591
/* XXX ought to verify that this is the right type here */
592
/* XXX for iid_is this must be an iid */
593
/* XXX for size_is and length_is this must be a uint32 */
601
/* return value is for success or failure */
603
get_size_and_length(TreeState *state, IDL_tree type,
604
int16 *size_is_argnum, int16 *length_is_argnum,
605
gboolean *has_size_is, gboolean *has_length_is)
607
*has_size_is = FALSE;
608
*has_length_is = FALSE;
610
if (IDL_NODE_TYPE(state->tree) == IDLN_PARAM_DCL) {
611
IDL_tree sd = IDL_PARAM_DCL(state->tree).simple_declarator;
613
const char *length_is;
615
/* only if size_is is found does any of this matter */
616
size_is = IDL_tree_property_get(sd, "size_is");
620
if (!find_arg_with_name(state, size_is, size_is_argnum)) {
621
IDL_tree_error(state->tree, "can't find matching argument for "
622
"[size_is(%s)]\n", size_is);
627
/* length_is is optional */
628
length_is = IDL_tree_property_get(sd, "length_is");
630
*has_length_is = TRUE;
631
if (!find_arg_with_name(state, length_is, length_is_argnum)) {
632
IDL_tree_error(state->tree, "can't find matching argument for "
633
"[length_is(%s)]\n", length_is);
642
fill_td_from_type(TreeState *state, XPTTypeDescriptor *td, IDL_tree type)
645
int16 size_is_argnum;
646
int16 length_is_argnum;
647
gboolean has_size_is;
648
gboolean has_length_is;
649
gboolean is_array = FALSE;
653
/* deal with array */
655
if (IDL_NODE_TYPE(state->tree) == IDLN_PARAM_DCL) {
656
IDL_tree sd = IDL_PARAM_DCL(state->tree).simple_declarator;
657
if (IDL_tree_property_get(sd, "array")) {
661
/* size_is is required! */
662
if (!get_size_and_length(state, type,
663
&size_is_argnum, &length_is_argnum,
664
&has_size_is, &has_length_is)) {
665
/* error was reported by helper function */
670
IDL_tree_error(state->tree, "[array] requires [size_is()]\n");
674
td->prefix.flags = TD_ARRAY | XPT_TDP_POINTER;
675
td->argnum = size_is_argnum;
678
td->argnum2 = length_is_argnum;
680
td->argnum2 = size_is_argnum;
683
* XXX - NOTE - this will be broken for multidimensional
684
* arrays because of the realloc XPT_InterfaceDescriptorAddTypes
685
* uses. The underlying 'td' can change as we recurse in to get
686
* additional dimensions. Luckily, we don't yet support more
687
* than on dimension in the arrays
689
/* setup the additional_type */
690
if (!XPT_InterfaceDescriptorAddTypes(ARENA(state),
691
CURRENT(state), 1)) {
692
g_error("out of memory\n");
695
td->type.additional_type = NEXT_TYPE(state);
696
td = &CURRENT(state)->additional_types[NEXT_TYPE(state)];
702
switch (IDL_NODE_TYPE(type)) {
703
case IDLN_TYPE_INTEGER: {
704
gboolean sign = IDL_TYPE_INTEGER(type).f_signed;
705
switch(IDL_TYPE_INTEGER(type).f_type) {
706
case IDL_INTEGER_TYPE_SHORT:
707
td->prefix.flags = sign ? TD_INT16 : TD_UINT16;
709
case IDL_INTEGER_TYPE_LONG:
710
td->prefix.flags = sign ? TD_INT32 : TD_UINT32;
712
case IDL_INTEGER_TYPE_LONGLONG:
713
td->prefix.flags = sign ? TD_INT64 : TD_UINT64;
719
td->prefix.flags = TD_CHAR;
721
case IDLN_TYPE_WIDE_CHAR:
722
td->prefix.flags = TD_WCHAR;
724
case IDLN_TYPE_STRING:
726
td->prefix.flags = TD_PSTRING | XPT_TDP_POINTER;
728
if (!get_size_and_length(state, type,
729
&size_is_argnum, &length_is_argnum,
730
&has_size_is, &has_length_is)) {
731
/* error was reported by helper function */
735
td->prefix.flags = TD_PSTRING_SIZE_IS | XPT_TDP_POINTER;
736
td->argnum = size_is_argnum;
738
td->argnum2 = length_is_argnum;
740
td->argnum2 = size_is_argnum;
742
td->prefix.flags = TD_PSTRING | XPT_TDP_POINTER;
746
case IDLN_TYPE_WIDE_STRING:
748
td->prefix.flags = TD_PWSTRING | XPT_TDP_POINTER;
750
if (!get_size_and_length(state, type,
751
&size_is_argnum, &length_is_argnum,
752
&has_size_is, &has_length_is)) {
753
/* error was reported by helper function */
757
td->prefix.flags = TD_PWSTRING_SIZE_IS | XPT_TDP_POINTER;
758
td->argnum = size_is_argnum;
760
td->argnum2 = length_is_argnum;
762
td->argnum2 = size_is_argnum;
764
td->prefix.flags = TD_PWSTRING | XPT_TDP_POINTER;
768
case IDLN_TYPE_BOOLEAN:
769
td->prefix.flags = TD_BOOL;
771
case IDLN_TYPE_OCTET:
772
td->prefix.flags = TD_UINT8;
774
case IDLN_TYPE_FLOAT:
775
switch (IDL_TYPE_FLOAT (type).f_type) {
776
case IDL_FLOAT_TYPE_FLOAT:
777
td->prefix.flags = TD_FLOAT;
779
case IDL_FLOAT_TYPE_DOUBLE:
780
td->prefix.flags = TD_DOUBLE;
782
/* XXX 'long double' just ignored, or what? */
787
if (!(up = IDL_NODE_UP(type))) {
788
IDL_tree_error(state->tree,
789
"ERROR: orphan ident %s in param list\n",
790
IDL_IDENT(type).str);
793
switch (IDL_NODE_TYPE(up)) {
794
/* This whole section is abominably ugly */
795
case IDLN_FORWARD_DCL:
796
case IDLN_INTERFACE: {
797
XPTInterfaceDirectoryEntry *ide, *ides;
802
ides = HEADER(state)->interface_directory;
803
num_ifaces = HEADER(state)->num_interfaces;
804
/* might get here via the goto, so re-check type */
805
if (IDL_NODE_TYPE(up) == IDLN_INTERFACE)
806
className = IDL_IDENT(IDL_INTERFACE(up).ident).str;
807
else if (IDL_NODE_TYPE(up) == IDLN_FORWARD_DCL)
808
className = IDL_IDENT(IDL_FORWARD_DCL(up).ident).str;
810
className = IDL_IDENT(IDL_NATIVE(up).ident).str;
813
if (IDL_NODE_TYPE(state->tree) == IDLN_PARAM_DCL) {
815
IDL_tree_property_get(IDL_PARAM_DCL(state->tree).simple_declarator,
820
if (!find_arg_with_name(state, iid_is, &argnum)) {
821
IDL_tree_error(state->tree,
822
"can't find matching argument for "
823
"[iid_is(%s)]\n", iid_is);
826
td->prefix.flags = TD_INTERFACE_IS_TYPE | XPT_TDP_POINTER;
829
td->prefix.flags = TD_INTERFACE_TYPE | XPT_TDP_POINTER;
830
ide = FindInterfaceByName(ides, num_ifaces, className);
831
if (!ide || ide < ides || ide > ides + num_ifaces) {
832
IDL_tree_error(state->tree,
833
"unknown iface %s in param\n",
837
td->type.iface = ide - ides + 1;
838
#ifdef DEBUG_shaver_index
839
fprintf(stderr, "DBG: index %d for %s\n",
840
td->type.iface, className);
848
/* jband - adding goto for iid_is when type is native */
849
if (IDL_NODE_TYPE(state->tree) == IDLN_PARAM_DCL &&
850
IDL_tree_property_get(IDL_PARAM_DCL(state->tree).simple_declarator,
854
ident = IDL_IDENT(type).str;
855
if (IDL_tree_property_get(type, "nsid")) {
856
td->prefix.flags = TD_PNSIID;
857
if (IDL_tree_property_get(type, "ref"))
858
td->prefix.flags |= XPT_TDP_POINTER | XPT_TDP_REFERENCE;
859
else if (IDL_tree_property_get(type,"ptr"))
860
td->prefix.flags |= XPT_TDP_POINTER;
861
} else if (IDL_tree_property_get(type, "domstring")) {
862
td->prefix.flags = TD_DOMSTRING | XPT_TDP_POINTER;
863
if (IDL_tree_property_get(type, "ref"))
864
td->prefix.flags |= XPT_TDP_REFERENCE;
865
} else if (IDL_tree_property_get(type, "astring")) {
866
td->prefix.flags = TD_ASTRING | XPT_TDP_POINTER;
867
if (IDL_tree_property_get(type, "ref"))
868
td->prefix.flags |= XPT_TDP_REFERENCE;
869
} else if (IDL_tree_property_get(type, "utf8string")) {
870
td->prefix.flags = TD_UTF8STRING | XPT_TDP_POINTER;
871
if (IDL_tree_property_get(type, "ref"))
872
td->prefix.flags |= XPT_TDP_REFERENCE;
873
} else if (IDL_tree_property_get(type, "cstring")) {
874
td->prefix.flags = TD_CSTRING | XPT_TDP_POINTER;
875
if (IDL_tree_property_get(type, "ref"))
876
td->prefix.flags |= XPT_TDP_REFERENCE;
878
td->prefix.flags = TD_VOID | XPT_TDP_POINTER;
883
if (IDL_NODE_TYPE(IDL_NODE_UP(up)) == IDLN_TYPE_DCL) {
884
/* restart with the underlying type */
886
new_type = IDL_TYPE_DCL(IDL_NODE_UP(up)).type_spec;
887
#ifdef DEBUG_shaver_misc
888
fprintf(stderr, "following %s typedef to %s\n",
889
IDL_IDENT(type).str, IDL_NODE_TYPE_NAME(new_type));
892
* Do a nice messy goto rather than recursion so that
893
* we can avoid screwing up the *array* information.
895
/* return fill_td_from_type(state, td, new_type); */
900
/* do what we would do in recursion if !type */
901
td->prefix.flags = TD_VOID;
905
IDL_tree_error(state->tree,
906
"can't handle %s ident in param list\n",
908
/* XXX is this safe to use on Win now? */
909
IDL_NODE_TYPE_NAME(IDL_NODE_UP(type))
921
IDL_tree_error(state->tree, "can't handle %s in param list\n",
923
/* XXX is this safe to use on Win now? */
924
IDL_NODE_TYPE_NAME(IDL_NODE_UP(type))
932
td->prefix.flags = TD_VOID;
939
fill_pd_from_type(TreeState *state, XPTParamDescriptor *pd, uint8 flags,
943
return fill_td_from_type(state, &pd->type, type);
947
fill_pd_from_param(TreeState *state, XPTParamDescriptor *pd, IDL_tree tree)
950
gboolean is_dipper_type = DIPPER_TYPE(IDL_PARAM_DCL(tree).param_type_spec);
952
switch (IDL_PARAM_DCL(tree).attr) {
959
case IDL_PARAM_INOUT:
960
flags = XPT_PD_IN | XPT_PD_OUT;
964
if (IDL_tree_property_get(IDL_PARAM_DCL(tree).simple_declarator,
966
if (flags != XPT_PD_OUT) {
967
IDL_tree_error(tree, "can't have [retval] with in%s param "
969
flags & XPT_PD_OUT ? "out" : "");
972
flags |= XPT_PD_RETVAL;
975
if (is_dipper_type && (flags & XPT_PD_OUT)) {
976
flags &= ~XPT_PD_OUT;
977
flags |= XPT_PD_IN | XPT_PD_DIPPER;
980
if (IDL_tree_property_get(IDL_PARAM_DCL(tree).simple_declarator,
982
if (flags & XPT_PD_IN) {
983
IDL_tree_error(tree, "can't have [shared] with in%s param "
985
flags & XPT_PD_OUT ? "out" : "");
988
flags |= XPT_PD_SHARED;
991
if (IDL_tree_property_get(IDL_PARAM_DCL(tree).simple_declarator,
993
flags |= XPT_PD_OPTIONAL;
996
/* stick param where we can see it later */
998
return fill_pd_from_type(state, pd, flags,
999
IDL_PARAM_DCL(tree).param_type_spec);
1002
/* XXXshaver common with xpidl_header.c */
1003
#define ATTR_IDENT(tree) (IDL_IDENT(IDL_LIST(IDL_ATTR_DCL(tree).simple_declarations).data))
1004
#define ATTR_TYPE_DECL(tree) (IDL_ATTR_DCL(tree).param_type_spec)
1005
#define ATTR_TYPE(tree) (IDL_NODE_TYPE(ATTR_TYPE_DECL(tree)))
1008
fill_pd_as_nsresult(XPTParamDescriptor *pd)
1010
pd->type.prefix.flags = TD_UINT32; /* TD_NSRESULT */
1015
typelib_attr_accessor(TreeState *state, XPTMethodDescriptor *meth,
1016
gboolean getter, gboolean hidden)
1018
uint8 methflags = 0;
1021
methflags |= getter ? XPT_MD_GETTER : XPT_MD_SETTER;
1022
methflags |= hidden ? XPT_MD_HIDDEN : 0;
1023
if (!XPT_FillMethodDescriptor(ARENA(state), meth, methflags,
1024
ATTR_IDENT(state->tree).str, 1))
1028
if (DIPPER_TYPE(ATTR_TYPE_DECL(state->tree))) {
1029
pdflags |= (XPT_PD_RETVAL | XPT_PD_IN | XPT_PD_DIPPER);
1031
pdflags |= (XPT_PD_RETVAL | XPT_PD_OUT);
1034
pdflags |= XPT_PD_IN;
1037
if (!fill_pd_from_type(state, meth->params, pdflags,
1038
ATTR_TYPE_DECL(state->tree)))
1041
fill_pd_as_nsresult(meth->result);
1047
typelib_attr_dcl(TreeState *state)
1049
XPTInterfaceDescriptor *id = CURRENT(state);
1050
XPTMethodDescriptor *meth;
1051
gboolean read_only = IDL_ATTR_DCL(state->tree).f_readonly;
1053
/* XXX this only handles the first ident; elsewhere too... */
1055
IDL_LIST(IDL_ATTR_DCL(state->tree).simple_declarations).data;
1057
/* If it's marked [noscript], mark it as hidden in the typelib. */
1058
gboolean hidden = (IDL_tree_property_get(ident, "noscript") != NULL);
1060
if (!verify_attribute_declaration(state->tree))
1063
if (!XPT_InterfaceDescriptorAddMethods(ARENA(state), id,
1064
(PRUint16) (read_only ? 1 : 2)))
1067
meth = &id->method_descriptors[NEXT_METH(state)];
1069
return typelib_attr_accessor(state, meth, TRUE, hidden) &&
1070
(read_only || typelib_attr_accessor(state, meth + 1, FALSE, hidden));
1074
typelib_op_dcl(TreeState *state)
1076
XPTInterfaceDescriptor *id = CURRENT(state);
1077
XPTMethodDescriptor *meth;
1078
struct _IDL_OP_DCL *op = &IDL_OP_DCL(state->tree);
1080
uint16 num_args = 0;
1082
gboolean op_notxpcom = (IDL_tree_property_get(op->ident, "notxpcom")
1084
gboolean op_noscript = (IDL_tree_property_get(op->ident, "noscript")
1087
if (!verify_method_declaration(state->tree))
1090
if (!XPT_InterfaceDescriptorAddMethods(ARENA(state), id, 1))
1093
meth = &id->method_descriptors[NEXT_METH(state)];
1095
for (iter = op->parameter_dcls; iter; iter = IDL_LIST(iter).next)
1096
num_args++; /* count params */
1097
if (op->op_type_spec && !op_notxpcom)
1098
num_args++; /* fake param for _retval */
1101
op_flags |= XPT_MD_HIDDEN;
1103
op_flags |= XPT_MD_NOTXPCOM;
1105
/* XXXshaver constructor? */
1107
#ifdef DEBUG_shaver_method
1108
fprintf(stdout, "DBG: adding method %s (nargs %d)\n",
1109
IDL_IDENT(op->ident).str, num_args);
1111
if (!XPT_FillMethodDescriptor(ARENA(state), meth, op_flags,
1112
IDL_IDENT(op->ident).str,
1116
for (num_args = 0, iter = op->parameter_dcls; iter;
1117
iter = IDL_LIST(iter).next, num_args++) {
1118
XPTParamDescriptor *pd = &meth->params[num_args];
1119
if (!fill_pd_from_param(state, pd, IDL_LIST(iter).data))
1123
/* stick retval param where we can see it later */
1124
state->tree = op->op_type_spec;
1126
/* XXX unless [notxpcom] */
1128
if (op->op_type_spec) {
1129
uint8 pdflags = DIPPER_TYPE(op->op_type_spec) ?
1130
(XPT_PD_RETVAL | XPT_PD_IN | XPT_PD_DIPPER) :
1131
(XPT_PD_RETVAL | XPT_PD_OUT);
1133
if (!fill_pd_from_type(state, &meth->params[num_args],
1134
pdflags, op->op_type_spec))
1138
if (!fill_pd_as_nsresult(meth->result))
1141
#ifdef DEBUG_shaver_notxpcom
1142
fprintf(stderr, "%s is notxpcom\n", IDL_IDENT(op->ident).str);
1144
if (!fill_pd_from_type(state, meth->result, XPT_PD_RETVAL,
1153
typelib_const_dcl(TreeState *state)
1155
struct _IDL_CONST_DCL *dcl = &IDL_CONST_DCL(state->tree);
1156
const char *name = IDL_IDENT(dcl->ident).str;
1160
XPTInterfaceDescriptor *id;
1161
XPTConstDescriptor *cd;
1162
IDL_longlong_t value;
1164
if (!verify_const_declaration(state->tree))
1167
/* Could be a typedef; try to map it to the real type. */
1168
real_type = find_underlying_type(dcl->const_type);
1169
real_type = real_type ? real_type : dcl->const_type;
1170
is_long = (IDL_TYPE_INTEGER(real_type).f_type == IDL_INTEGER_TYPE_LONG);
1172
id = CURRENT(state);
1173
if (!XPT_InterfaceDescriptorAddConsts(ARENA(state), id, 1))
1175
cd = &id->const_descriptors[NEXT_CONST(state)];
1177
cd->name = IDL_IDENT(dcl->ident).str;
1178
#ifdef DEBUG_shaver_const
1179
fprintf(stderr, "DBG: adding const %s\n", cd->name);
1181
if (!fill_td_from_type(state, &cd->type, dcl->const_type))
1184
value = IDL_INTEGER(dcl->const_exp).value;
1185
sign = IDL_TYPE_INTEGER(dcl->const_type).f_signed;
1188
cd->value.i32 = value;
1190
cd->value.ui32 = value;
1193
cd->value.i16 = value;
1195
cd->value.ui16 = value;
1197
NEXT_CONST(state)++;
1202
typelib_enum(TreeState *state)
1204
XPIDL_WARNING((state->tree, IDL_WARNING1,
1205
"enums not supported, enum \'%s\' ignored",
1206
IDL_IDENT(IDL_TYPE_ENUM(state->tree).ident).str));
1211
xpidl_typelib_dispatch(void)
1213
static backend result;
1214
static nodeHandler table[IDLN_LAST];
1215
static gboolean initialized = FALSE;
1217
result.emit_prolog = typelib_prolog;
1218
result.emit_epilog = typelib_epilog;
1221
/* Initialize non-NULL elements */
1222
table[IDLN_LIST] = typelib_list;
1223
table[IDLN_ATTR_DCL] = typelib_attr_dcl;
1224
table[IDLN_OP_DCL] = typelib_op_dcl;
1225
table[IDLN_INTERFACE] = typelib_interface;
1226
table[IDLN_CONST_DCL] = typelib_const_dcl;
1227
table[IDLN_TYPE_ENUM] = typelib_enum;
1228
table[IDLN_NATIVE] = check_native;
1232
result.dispatch_table = table;