1 : /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
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/
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 of the GNU General Public License Version 2 or later (the "GPL"),
26 : * or 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.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : /* Implementation of XDR routines for typelib structures. */
39 :
40 : #include "xpt_xdr.h"
41 : #include "xpt_struct.h"
42 : #include <string.h>
43 : #include <stdio.h>
44 :
45 : /***************************************************************************/
46 : /* Forward declarations. */
47 :
48 : static PRUint32
49 : SizeOfTypeDescriptor(XPTTypeDescriptor *td, XPTInterfaceDescriptor *id);
50 :
51 : static PRUint32
52 : SizeOfMethodDescriptor(XPTMethodDescriptor *md, XPTInterfaceDescriptor *id);
53 :
54 : static PRUint32
55 : SizeOfConstDescriptor(XPTConstDescriptor *cd, XPTInterfaceDescriptor *id);
56 :
57 : static PRUint32
58 : SizeOfInterfaceDescriptor(XPTInterfaceDescriptor *id);
59 :
60 : static PRBool
61 : DoInterfaceDirectoryEntry(XPTArena *arena, XPTCursor *cursor,
62 : XPTInterfaceDirectoryEntry *ide, PRUint16 entry_index);
63 :
64 : static PRBool
65 : DoConstDescriptor(XPTArena *arena, XPTCursor *cursor, XPTConstDescriptor *cd,
66 : XPTInterfaceDescriptor *id);
67 :
68 : static PRBool
69 : DoMethodDescriptor(XPTArena *arena, XPTCursor *cursor, XPTMethodDescriptor *md,
70 : XPTInterfaceDescriptor *id);
71 :
72 : static PRBool
73 : DoAnnotation(XPTArena *arena, XPTCursor *cursor, XPTAnnotation **annp);
74 :
75 : static PRBool
76 : DoInterfaceDescriptor(XPTArena *arena, XPTCursor *outer, XPTInterfaceDescriptor **idp);
77 :
78 : static PRBool
79 : DoTypeDescriptorPrefix(XPTArena *arena, XPTCursor *cursor, XPTTypeDescriptorPrefix *tdp);
80 :
81 : static PRBool
82 : DoTypeDescriptor(XPTArena *arena, XPTCursor *cursor, XPTTypeDescriptor *td,
83 : XPTInterfaceDescriptor *id);
84 :
85 : static PRBool
86 : DoParamDescriptor(XPTArena *arena, XPTCursor *cursor, XPTParamDescriptor *pd,
87 : XPTInterfaceDescriptor *id);
88 :
89 : /***************************************************************************/
90 :
91 : XPT_PUBLIC_API(PRUint32)
92 : XPT_SizeOfHeader(XPTHeader *header)
93 : {
94 : XPTAnnotation *ann, *last;
95 0 : PRUint32 size = 16 /* magic */ +
96 : 1 /* major */ + 1 /* minor */ +
97 : 2 /* num_interfaces */ + 4 /* file_length */ +
98 : 4 /* interface_directory */ + 4 /* data_pool */;
99 :
100 0 : ann = header->annotations;
101 : do {
102 0 : size += 1; /* Annotation prefix */
103 0 : if (XPT_ANN_IS_PRIVATE(ann->flags))
104 0 : size += 2 + ann->creator->length + 2 + ann->private_data->length;
105 0 : last = ann;
106 0 : ann = ann->next;
107 0 : } while (!XPT_ANN_IS_LAST(last->flags));
108 :
109 0 : return size;
110 : }
111 :
112 : XPT_PUBLIC_API(PRUint32)
113 : XPT_SizeOfHeaderBlock(XPTHeader *header)
114 : {
115 0 : PRUint32 ide_size = 16 /* IID */ + 4 /* name */ +
116 : 4 /* namespace */ + 4 /* descriptor */;
117 :
118 0 : return XPT_SizeOfHeader(header) + header->num_interfaces * ide_size;
119 : }
120 :
121 : XPT_PUBLIC_API(XPTHeader *)
122 : XPT_NewHeader(XPTArena *arena, PRUint16 num_interfaces, PRUint8 major_version, PRUint8 minor_version)
123 : {
124 0 : XPTHeader *header = XPT_NEWZAP(arena, XPTHeader);
125 0 : if (!header)
126 0 : return NULL;
127 0 : memcpy(header->magic, XPT_MAGIC, 16);
128 0 : header->major_version = major_version;
129 0 : header->minor_version = minor_version;
130 0 : header->num_interfaces = num_interfaces;
131 0 : if (num_interfaces) {
132 0 : header->interface_directory =
133 0 : XPT_CALLOC(arena,
134 : num_interfaces * sizeof(XPTInterfaceDirectoryEntry));
135 0 : if (!header->interface_directory) {
136 0 : XPT_DELETE(arena, header);
137 0 : return NULL;
138 : }
139 : }
140 0 : header->data_pool = 0; /* XXX do we even need this struct any more? */
141 :
142 0 : return header;
143 : }
144 :
145 : XPT_PUBLIC_API(void)
146 : XPT_FreeHeader(XPTArena *arena, XPTHeader* aHeader)
147 : {
148 0 : if (aHeader) {
149 : XPTAnnotation* ann;
150 0 : XPTInterfaceDirectoryEntry* entry = aHeader->interface_directory;
151 0 : XPTInterfaceDirectoryEntry* end = entry + aHeader->num_interfaces;
152 0 : for (; entry < end; entry++) {
153 0 : XPT_DestroyInterfaceDirectoryEntry(arena, entry);
154 : }
155 :
156 0 : ann = aHeader->annotations;
157 0 : while (ann) {
158 0 : XPTAnnotation* next = ann->next;
159 0 : if (XPT_ANN_IS_PRIVATE(ann->flags)) {
160 0 : XPT_FREEIF(arena, ann->creator);
161 0 : XPT_FREEIF(arena, ann->private_data);
162 : }
163 0 : XPT_DELETE(arena, ann);
164 0 : ann = next;
165 : }
166 :
167 0 : XPT_FREEIF(arena, aHeader->interface_directory);
168 0 : XPT_DELETE(arena, aHeader);
169 : }
170 0 : }
171 :
172 : XPT_PUBLIC_API(PRBool)
173 : XPT_DoHeaderPrologue(XPTArena *arena, XPTCursor *cursor, XPTHeader **headerp, PRUint32 * ide_offset)
174 : {
175 218497 : XPTMode mode = cursor->state->mode;
176 : unsigned int i;
177 : XPTHeader * header;
178 :
179 218497 : if (mode == XPT_DECODE) {
180 218497 : header = XPT_NEWZAP(arena, XPTHeader);
181 218497 : if (!header)
182 0 : return PR_FALSE;
183 218497 : *headerp = header;
184 : } else {
185 0 : header = *headerp;
186 : }
187 :
188 218497 : if (mode == XPT_ENCODE) {
189 : /* IDEs appear after header, including annotations */
190 0 : if (ide_offset != NULL)
191 : {
192 0 : *ide_offset = XPT_SizeOfHeader(*headerp) + 1; /* one-based offset */
193 : }
194 0 : header->data_pool = XPT_SizeOfHeaderBlock(*headerp);
195 0 : XPT_SetDataOffset(cursor->state, header->data_pool);
196 : }
197 :
198 3714449 : for (i = 0; i < sizeof(header->magic); i++) {
199 3495952 : if (!XPT_Do8(cursor, &header->magic[i]))
200 0 : goto error;
201 : }
202 :
203 436994 : if (mode == XPT_DECODE &&
204 218497 : strncmp((const char*)header->magic, XPT_MAGIC, 16) != 0)
205 : {
206 : /* Require that the header contain the proper magic */
207 0 : fprintf(stderr,
208 : "libxpt: bad magic header in input file; "
209 : "found '%s', expected '%s'\n",
210 : header->magic, XPT_MAGIC_STRING);
211 0 : goto error;
212 : }
213 :
214 436994 : if (!XPT_Do8(cursor, &header->major_version) ||
215 218497 : !XPT_Do8(cursor, &header->minor_version)) {
216 : goto error;
217 : }
218 :
219 436994 : if (mode == XPT_DECODE &&
220 218497 : header->major_version >= XPT_MAJOR_INCOMPATIBLE_VERSION) {
221 : /* This file is newer than we are and set to an incompatible version
222 : * number. We must set the header state thusly and return.
223 : */
224 0 : header->num_interfaces = 0;
225 0 : header->file_length = 0;
226 0 : return PR_TRUE;
227 : }
228 :
229 436994 : if (!XPT_Do16(cursor, &header->num_interfaces) ||
230 436994 : !XPT_Do32(cursor, &header->file_length) ||
231 218497 : (ide_offset != NULL && !XPT_Do32(cursor, ide_offset))) {
232 : goto error;
233 : }
234 218497 : return PR_TRUE;
235 : /* XXX need to free child data sometimes! */
236 0 : XPT_ERROR_HANDLE(arena, header);
237 : }
238 :
239 : XPT_PUBLIC_API(PRBool)
240 : XPT_DoHeader(XPTArena *arena, XPTCursor *cursor, XPTHeader **headerp)
241 : {
242 218497 : const int HEADER_SIZE = 24;
243 218497 : XPTMode mode = cursor->state->mode;
244 : XPTHeader * header;
245 : PRUint32 ide_offset;
246 : int i;
247 : XPTAnnotation *ann, *next, **annp;
248 :
249 218497 : if (!XPT_DoHeaderPrologue(arena, cursor, headerp, &ide_offset))
250 0 : return PR_FALSE;
251 218497 : header = *headerp;
252 : /*
253 : * Make sure the file length reported in the header is the same size as
254 : * as our buffer unless it is zero (not set)
255 : */
256 436994 : if (mode == XPT_DECODE && (header->file_length != 0 &&
257 218497 : cursor->state->pool->allocated < header->file_length)) {
258 0 : fputs("libxpt: File length in header does not match actual length. File may be corrupt\n",
259 : stderr);
260 0 : goto error;
261 : }
262 :
263 218497 : if (mode == XPT_ENCODE)
264 0 : XPT_DataOffset(cursor->state, &header->data_pool);
265 218497 : if (!XPT_Do32(cursor, &header->data_pool))
266 0 : goto error;
267 218497 : if (mode == XPT_DECODE)
268 218497 : XPT_DataOffset(cursor->state, &header->data_pool);
269 :
270 218497 : if (mode == XPT_DECODE && header->num_interfaces) {
271 218497 : header->interface_directory =
272 218497 : XPT_CALLOC(arena, header->num_interfaces *
273 : sizeof(XPTInterfaceDirectoryEntry));
274 218497 : if (!header->interface_directory)
275 0 : goto error;
276 : }
277 :
278 : /*
279 : * Iterate through the annotations rather than recurring, to avoid blowing
280 : * the stack on large xpt files.
281 : */
282 218497 : ann = next = header->annotations;
283 218497 : annp = &header->annotations;
284 : do {
285 218497 : ann = next;
286 218497 : if (!DoAnnotation(arena, cursor, &ann))
287 0 : goto error;
288 218497 : if (mode == XPT_DECODE) {
289 : /*
290 : * Make sure that we store the address of the newly allocated
291 : * annotation in the previous annotation's ``next'' slot, or
292 : * header->annotations for the first one.
293 : */
294 218497 : *annp = ann;
295 218497 : annp = &ann->next;
296 : }
297 218497 : next = ann->next;
298 218497 : } while (!XPT_ANN_IS_LAST(ann->flags));
299 :
300 : /* shouldn't be necessary now, but maybe later */
301 218497 : XPT_SeekTo(cursor, ide_offset);
302 :
303 3616498 : for (i = 0; i < header->num_interfaces; i++) {
304 10194003 : if (!DoInterfaceDirectoryEntry(arena, cursor,
305 6796002 : &header->interface_directory[i],
306 3398001 : (PRUint16)(i + 1)))
307 0 : goto error;
308 : }
309 :
310 218497 : return PR_TRUE;
311 :
312 : /* XXX need to free child data sometimes! */
313 0 : XPT_ERROR_HANDLE(arena, header);
314 : }
315 :
316 : XPT_PUBLIC_API(PRBool)
317 : XPT_FillInterfaceDirectoryEntry(XPTArena *arena,
318 : XPTInterfaceDirectoryEntry *ide,
319 : nsID *iid, char *name, char *name_space,
320 : XPTInterfaceDescriptor *descriptor)
321 : {
322 0 : XPT_COPY_IID(ide->iid, *iid);
323 0 : ide->name = name ? XPT_STRDUP(arena, name) : NULL; /* what good is it w/o a name? */
324 0 : ide->name_space = name_space ? XPT_STRDUP(arena, name_space) : NULL;
325 0 : ide->interface_descriptor = descriptor;
326 0 : return PR_TRUE;
327 : }
328 :
329 : XPT_PUBLIC_API(void)
330 : XPT_DestroyInterfaceDirectoryEntry(XPTArena *arena,
331 : XPTInterfaceDirectoryEntry* ide)
332 : {
333 0 : if (ide) {
334 0 : if (ide->name) XPT_FREE(arena, ide->name);
335 0 : if (ide->name_space) XPT_FREE(arena, ide->name_space);
336 0 : XPT_FreeInterfaceDescriptor(arena, ide->interface_descriptor);
337 : }
338 0 : }
339 :
340 : /* InterfaceDirectoryEntry records go in the header */
341 : PRBool
342 3398001 : DoInterfaceDirectoryEntry(XPTArena *arena, XPTCursor *cursor,
343 : XPTInterfaceDirectoryEntry *ide, PRUint16 entry_index)
344 : {
345 3398001 : XPTMode mode = cursor->state->mode;
346 :
347 : /* write the IID in our cursor space */
348 6796002 : if (!XPT_DoIID(cursor, &(ide->iid)) ||
349 :
350 : /* write the name string in the data pool, and the offset in our
351 : cursor space */
352 6796002 : !XPT_DoCString(arena, cursor, &(ide->name)) ||
353 :
354 : /* write the name_space string in the data pool, and the offset in our
355 : cursor space */
356 6796002 : !XPT_DoCString(arena, cursor, &(ide->name_space)) ||
357 :
358 : /* do InterfaceDescriptors -- later, only on encode (see below) */
359 3398001 : !DoInterfaceDescriptor(arena, cursor, &ide->interface_descriptor)) {
360 : goto error;
361 : }
362 :
363 3398001 : if (mode == XPT_DECODE)
364 3398001 : XPT_SetOffsetForAddr(cursor, ide, entry_index);
365 :
366 3398001 : return PR_TRUE;
367 :
368 0 : XPT_ERROR_HANDLE(arena, ide);
369 : }
370 :
371 : XPT_PUBLIC_API(XPTInterfaceDescriptor *)
372 : XPT_NewInterfaceDescriptor(XPTArena *arena,
373 : PRUint16 parent_interface, PRUint16 num_methods,
374 : PRUint16 num_constants, PRUint8 flags)
375 : {
376 :
377 0 : XPTInterfaceDescriptor *id = XPT_NEWZAP(arena, XPTInterfaceDescriptor);
378 0 : if (!id)
379 0 : return NULL;
380 :
381 0 : if (num_methods) {
382 0 : id->method_descriptors = XPT_CALLOC(arena, num_methods *
383 : sizeof(XPTMethodDescriptor));
384 0 : if (!id->method_descriptors)
385 0 : goto free_id;
386 0 : id->num_methods = num_methods;
387 : }
388 :
389 0 : if (num_constants) {
390 0 : id->const_descriptors = XPT_CALLOC(arena, num_constants *
391 : sizeof(XPTConstDescriptor));
392 0 : if (!id->const_descriptors)
393 0 : goto free_meth;
394 0 : id->num_constants = num_constants;
395 : }
396 :
397 0 : if (parent_interface) {
398 0 : id->parent_interface = parent_interface;
399 : } else {
400 0 : id->parent_interface = 0;
401 : }
402 :
403 0 : id->flags = flags;
404 :
405 0 : return id;
406 :
407 : free_meth:
408 0 : XPT_FREEIF(arena, id->method_descriptors);
409 : free_id:
410 0 : XPT_DELETE(arena, id);
411 0 : return NULL;
412 : }
413 :
414 : XPT_PUBLIC_API(void)
415 : XPT_FreeInterfaceDescriptor(XPTArena *arena, XPTInterfaceDescriptor* id)
416 : {
417 0 : if (id) {
418 : XPTMethodDescriptor *md, *mdend;
419 : XPTConstDescriptor *cd, *cdend;
420 :
421 : /* Free up method descriptors */
422 0 : md = id->method_descriptors;
423 0 : mdend = md + id->num_methods;
424 0 : for (; md < mdend; md++) {
425 0 : XPT_FREEIF(arena, md->name);
426 0 : XPT_FREEIF(arena, md->params);
427 0 : XPT_FREEIF(arena, md->result);
428 : }
429 0 : XPT_FREEIF(arena, id->method_descriptors);
430 :
431 : /* Free up const descriptors */
432 0 : cd = id->const_descriptors;
433 0 : cdend = cd + id->num_constants;
434 0 : for (; cd < cdend; cd++) {
435 0 : XPT_FREEIF(arena, cd->name);
436 : }
437 0 : XPT_FREEIF(arena, id->const_descriptors);
438 :
439 : /* Free up type descriptors */
440 0 : XPT_FREEIF(arena, id->additional_types);
441 :
442 0 : XPT_DELETE(arena, id);
443 : }
444 0 : }
445 :
446 : XPT_PUBLIC_API(PRBool)
447 : XPT_InterfaceDescriptorAddTypes(XPTArena *arena, XPTInterfaceDescriptor *id,
448 : PRUint16 num)
449 : {
450 252654 : XPTTypeDescriptor *old = id->additional_types;
451 : XPTTypeDescriptor *new;
452 252654 : size_t old_size = id->num_additional_types * sizeof(XPTTypeDescriptor);
453 252654 : size_t new_size = (num * sizeof(XPTTypeDescriptor)) + old_size;
454 :
455 : /* XXX should grow in chunks to minimize alloc overhead */
456 252654 : new = XPT_CALLOC(arena, new_size);
457 252654 : if (!new)
458 0 : return PR_FALSE;
459 252654 : if (old) {
460 119264 : if (old_size)
461 119264 : memcpy(new, old, old_size);
462 119264 : XPT_FREE(arena, old);
463 : }
464 252654 : id->additional_types = new;
465 252654 : id->num_additional_types += num;
466 252654 : return PR_TRUE;
467 : }
468 :
469 : XPT_PUBLIC_API(PRBool)
470 : XPT_InterfaceDescriptorAddMethods(XPTArena *arena, XPTInterfaceDescriptor *id,
471 : PRUint16 num)
472 : {
473 0 : XPTMethodDescriptor *old = id->method_descriptors;
474 : XPTMethodDescriptor *new;
475 0 : size_t old_size = id->num_methods * sizeof(XPTMethodDescriptor);
476 0 : size_t new_size = (num * sizeof(XPTMethodDescriptor)) + old_size;
477 :
478 : /* XXX should grow in chunks to minimize alloc overhead */
479 0 : new = XPT_CALLOC(arena, new_size);
480 0 : if (!new)
481 0 : return PR_FALSE;
482 0 : if (old) {
483 0 : if (old_size)
484 0 : memcpy(new, old, old_size);
485 0 : XPT_FREE(arena, old);
486 : }
487 0 : id->method_descriptors = new;
488 0 : id->num_methods += num;
489 0 : return PR_TRUE;
490 : }
491 :
492 : XPT_PUBLIC_API(PRBool)
493 : XPT_InterfaceDescriptorAddConsts(XPTArena *arena, XPTInterfaceDescriptor *id,
494 : PRUint16 num)
495 : {
496 0 : XPTConstDescriptor *old = id->const_descriptors;
497 : XPTConstDescriptor *new;
498 0 : size_t old_size = id->num_constants * sizeof(XPTConstDescriptor);
499 0 : size_t new_size = (num * sizeof(XPTConstDescriptor)) + old_size;
500 :
501 : /* XXX should grow in chunks to minimize alloc overhead */
502 0 : new = XPT_CALLOC(arena, new_size);
503 0 : if (!new)
504 0 : return PR_FALSE;
505 0 : if (old) {
506 0 : if (old_size)
507 0 : memcpy(new, old, old_size);
508 0 : XPT_FREE(arena, old);
509 : }
510 0 : id->const_descriptors = new;
511 0 : id->num_constants += num;
512 0 : return PR_TRUE;
513 : }
514 :
515 : PRUint32
516 0 : SizeOfTypeDescriptor(XPTTypeDescriptor *td, XPTInterfaceDescriptor *id)
517 : {
518 0 : PRUint32 size = 1; /* prefix */
519 :
520 0 : switch (XPT_TDP_TAG(td->prefix)) {
521 : case TD_INTERFACE_TYPE:
522 0 : size += 2; /* interface_index */
523 0 : break;
524 : case TD_INTERFACE_IS_TYPE:
525 0 : size += 1; /* argnum */
526 0 : break;
527 : case TD_ARRAY:
528 0 : size += 2 + SizeOfTypeDescriptor(
529 0 : &id->additional_types[td->type.additional_type], id);
530 0 : break;
531 : case TD_PSTRING_SIZE_IS:
532 0 : size += 2; /* argnum + argnum2 */
533 0 : break;
534 : case TD_PWSTRING_SIZE_IS:
535 0 : size += 2; /* argnum + argnum2 */
536 0 : break;
537 : default:
538 : /* nothing special */
539 0 : break;
540 : }
541 0 : return size;
542 : }
543 :
544 : PRUint32
545 0 : SizeOfMethodDescriptor(XPTMethodDescriptor *md, XPTInterfaceDescriptor *id)
546 : {
547 0 : PRUint32 i, size = 1 /* flags */ + 4 /* name */ + 1 /* num_args */;
548 :
549 0 : for (i = 0; i < md->num_args; i++)
550 0 : size += 1 + SizeOfTypeDescriptor(&md->params[i].type, id);
551 :
552 0 : size += 1 + SizeOfTypeDescriptor(&md->result->type, id);
553 0 : return size;
554 : }
555 :
556 : PRUint32
557 0 : SizeOfConstDescriptor(XPTConstDescriptor *cd, XPTInterfaceDescriptor *id)
558 : {
559 0 : PRUint32 size = 4 /* name */ + SizeOfTypeDescriptor(&cd->type, id);
560 :
561 0 : switch (XPT_TDP_TAG(cd->type.prefix)) {
562 : case TD_INT8:
563 : case TD_UINT8:
564 : case TD_CHAR:
565 0 : size ++;
566 0 : break;
567 : case TD_INT16:
568 : case TD_UINT16:
569 : case TD_WCHAR:
570 0 : size += 2;
571 0 : break;
572 : case TD_INT32:
573 : case TD_UINT32:
574 : case TD_PSTRING:
575 0 : size += 4;
576 0 : break;
577 : case TD_INT64:
578 : case TD_UINT64:
579 0 : size += 8;
580 0 : break;
581 : default:
582 0 : fprintf(stderr, "libxpt: illegal type in ConstDescriptor: 0x%02x\n",
583 0 : XPT_TDP_TAG(cd->type.prefix));
584 0 : return 0;
585 : }
586 :
587 0 : return size;
588 : }
589 :
590 : PRUint32
591 0 : SizeOfInterfaceDescriptor(XPTInterfaceDescriptor *id)
592 : {
593 0 : PRUint32 size = 2 /* parent interface */ + 2 /* num_methods */
594 : + 2 /* num_constants */ + 1 /* flags */, i;
595 0 : for (i = 0; i < id->num_methods; i++)
596 0 : size += SizeOfMethodDescriptor(&id->method_descriptors[i], id);
597 0 : for (i = 0; i < id->num_constants; i++)
598 0 : size += SizeOfConstDescriptor(&id->const_descriptors[i], id);
599 0 : return size;
600 : }
601 :
602 : PRBool
603 3398001 : DoInterfaceDescriptor(XPTArena *arena, XPTCursor *outer,
604 : XPTInterfaceDescriptor **idp)
605 : {
606 3398001 : XPTMode mode = outer->state->mode;
607 : XPTInterfaceDescriptor *id;
608 3398001 : XPTCursor curs, *cursor = &curs;
609 3398001 : PRUint32 i, id_sz = 0;
610 :
611 3398001 : if (mode == XPT_DECODE) {
612 3398001 : id = XPT_NEWZAP(arena, XPTInterfaceDescriptor);
613 3398001 : if (!id)
614 0 : return PR_FALSE;
615 3398001 : *idp = id;
616 : } else {
617 0 : id = *idp;
618 0 : if (!id) {
619 0 : id_sz = 0;
620 0 : return XPT_Do32(outer, &id_sz);
621 : }
622 0 : id_sz = SizeOfInterfaceDescriptor(id);
623 : }
624 :
625 3398001 : if (!XPT_MakeCursor(outer->state, XPT_DATA, id_sz, cursor))
626 0 : goto error;
627 :
628 3398001 : if (!XPT_Do32(outer, &cursor->offset))
629 0 : goto error;
630 3398001 : if (mode == XPT_DECODE && !cursor->offset) {
631 1229947 : XPT_DELETE(arena, *idp);
632 1229947 : return PR_TRUE;
633 : }
634 4336108 : if(!XPT_Do16(cursor, &id->parent_interface) ||
635 2168054 : !XPT_Do16(cursor, &id->num_methods)) {
636 : goto error;
637 : }
638 :
639 2168054 : if (mode == XPT_DECODE && id->num_methods) {
640 2064467 : id->method_descriptors = XPT_CALLOC(arena, id->num_methods *
641 : sizeof(XPTMethodDescriptor));
642 2064467 : if (!id->method_descriptors)
643 0 : goto error;
644 : }
645 :
646 17455141 : for (i = 0; i < id->num_methods; i++) {
647 15287087 : if (!DoMethodDescriptor(arena, cursor, &id->method_descriptors[i], id))
648 0 : goto error;
649 : }
650 :
651 2168054 : if (!XPT_Do16(cursor, &id->num_constants)) {
652 0 : goto error;
653 : }
654 :
655 2168054 : if (mode == XPT_DECODE && id->num_constants) {
656 401577 : id->const_descriptors = XPT_CALLOC(arena, id->num_constants *
657 : sizeof(XPTConstDescriptor));
658 401577 : if (!id->const_descriptors)
659 0 : goto error;
660 : }
661 :
662 6037667 : for (i = 0; i < id->num_constants; i++) {
663 3869613 : if (!DoConstDescriptor(arena, cursor, &id->const_descriptors[i], id)) {
664 0 : goto error;
665 : }
666 : }
667 :
668 2168054 : if (!XPT_Do8(cursor, &id->flags)) {
669 0 : goto error;
670 : }
671 :
672 2168054 : return PR_TRUE;
673 :
674 0 : XPT_ERROR_HANDLE(arena, id);
675 : }
676 :
677 : PRBool
678 3869613 : DoConstDescriptor(XPTArena *arena, XPTCursor *cursor, XPTConstDescriptor *cd,
679 : XPTInterfaceDescriptor *id)
680 : {
681 3869613 : PRBool ok = PR_FALSE;
682 :
683 7739226 : if (!XPT_DoCString(arena, cursor, &cd->name) ||
684 3869613 : !DoTypeDescriptor(arena, cursor, &cd->type, id)) {
685 :
686 0 : return PR_FALSE;
687 : }
688 :
689 3869613 : switch(XPT_TDP_TAG(cd->type.prefix)) {
690 : case TD_INT8:
691 0 : ok = XPT_Do8(cursor, (PRUint8*) &cd->value.i8);
692 0 : break;
693 : case TD_INT16:
694 272448 : ok = XPT_Do16(cursor, (PRUint16*) &cd->value.i16);
695 272448 : break;
696 : case TD_INT32:
697 625779 : ok = XPT_Do32(cursor, (PRUint32*) &cd->value.i32);
698 625779 : break;
699 : case TD_INT64:
700 0 : ok = XPT_Do64(cursor, &cd->value.i64);
701 0 : break;
702 : case TD_UINT8:
703 0 : ok = XPT_Do8(cursor, &cd->value.ui8);
704 0 : break;
705 : case TD_UINT16:
706 683958 : ok = XPT_Do16(cursor, &cd->value.ui16);
707 683958 : break;
708 : case TD_UINT32:
709 2287428 : ok = XPT_Do32(cursor, &cd->value.ui32);
710 2287428 : break;
711 : case TD_UINT64:
712 0 : ok = XPT_Do64(cursor, (PRInt64 *)&cd->value.ui64);
713 0 : break;
714 : case TD_CHAR:
715 0 : ok = XPT_Do8(cursor, (PRUint8*) &cd->value.ch);
716 0 : break;
717 : case TD_WCHAR:
718 0 : ok = XPT_Do16(cursor, &cd->value.wch);
719 0 : break;
720 : /* fall-through */
721 : default:
722 0 : fprintf(stderr, "illegal type!\n");
723 0 : break;
724 : }
725 :
726 3869613 : return ok;
727 :
728 : }
729 :
730 : XPT_PUBLIC_API(PRBool)
731 : XPT_FillMethodDescriptor(XPTArena *arena, XPTMethodDescriptor *meth,
732 : PRUint8 flags, char *name, PRUint8 num_args)
733 : {
734 0 : meth->flags = flags & XPT_MD_FLAGMASK;
735 0 : meth->name = XPT_STRDUP(arena, name);
736 0 : if (!meth->name)
737 0 : return PR_FALSE;
738 0 : meth->num_args = num_args;
739 0 : if (num_args) {
740 0 : meth->params = XPT_CALLOC(arena, num_args * sizeof(XPTParamDescriptor));
741 0 : if (!meth->params)
742 0 : goto free_name;
743 : } else {
744 0 : meth->params = NULL;
745 : }
746 0 : meth->result = XPT_NEWZAP(arena, XPTParamDescriptor);
747 0 : if (!meth->result)
748 0 : goto free_params;
749 0 : return PR_TRUE;
750 :
751 : free_params:
752 0 : XPT_DELETE(arena, meth->params);
753 : free_name:
754 0 : XPT_DELETE(arena, meth->name);
755 0 : return PR_FALSE;
756 : }
757 :
758 : PRBool
759 15287087 : DoMethodDescriptor(XPTArena *arena, XPTCursor *cursor, XPTMethodDescriptor *md,
760 : XPTInterfaceDescriptor *id)
761 : {
762 15287087 : XPTMode mode = cursor->state->mode;
763 : int i;
764 :
765 30574174 : if (!XPT_Do8(cursor, &md->flags) ||
766 30574174 : !XPT_DoCString(arena, cursor, &md->name) ||
767 15287087 : !XPT_Do8(cursor, &md->num_args))
768 0 : return PR_FALSE;
769 :
770 15287087 : if (mode == XPT_DECODE && md->num_args) {
771 14427305 : md->params = XPT_CALLOC(arena, md->num_args * sizeof(XPTParamDescriptor));
772 14427305 : if (!md->params)
773 0 : return PR_FALSE;
774 : }
775 :
776 38151054 : for(i = 0; i < md->num_args; i++) {
777 22863967 : if (!DoParamDescriptor(arena, cursor, &md->params[i], id))
778 0 : goto error;
779 : }
780 :
781 15287087 : if (mode == XPT_DECODE) {
782 15287087 : md->result = XPT_NEWZAP(arena, XPTParamDescriptor);
783 15287087 : if (!md->result)
784 0 : return PR_FALSE;
785 : }
786 :
787 30574174 : if (!md->result ||
788 15287087 : !DoParamDescriptor(arena, cursor, md->result, id))
789 : goto error;
790 :
791 15287087 : return PR_TRUE;
792 :
793 0 : XPT_ERROR_HANDLE(arena, md->params);
794 : }
795 :
796 : XPT_PUBLIC_API(PRBool)
797 : XPT_FillParamDescriptor(XPTArena *arena, XPTParamDescriptor *pd, PRUint8 flags,
798 : XPTTypeDescriptor *type)
799 : {
800 0 : pd->flags = flags & XPT_PD_FLAGMASK;
801 0 : XPT_COPY_TYPE(pd->type, *type);
802 0 : return PR_TRUE;
803 : }
804 :
805 : PRBool
806 38151054 : DoParamDescriptor(XPTArena *arena, XPTCursor *cursor, XPTParamDescriptor *pd,
807 : XPTInterfaceDescriptor *id)
808 : {
809 76302108 : if (!XPT_Do8(cursor, &pd->flags) ||
810 38151054 : !DoTypeDescriptor(arena, cursor, &pd->type, id))
811 0 : return PR_FALSE;
812 :
813 38151054 : return PR_TRUE;
814 : }
815 :
816 : PRBool
817 42273321 : DoTypeDescriptorPrefix(XPTArena *arena, XPTCursor *cursor, XPTTypeDescriptorPrefix *tdp)
818 : {
819 42273321 : return XPT_Do8(cursor, &tdp->flags);
820 : }
821 :
822 : PRBool
823 42273321 : DoTypeDescriptor(XPTArena *arena, XPTCursor *cursor, XPTTypeDescriptor *td,
824 : XPTInterfaceDescriptor *id)
825 : {
826 42273321 : if (!DoTypeDescriptorPrefix(arena, cursor, &td->prefix)) {
827 0 : goto error;
828 : }
829 :
830 42273321 : switch (XPT_TDP_TAG(td->prefix)) {
831 : case TD_INTERFACE_TYPE:
832 6403497 : if (!XPT_Do16(cursor, &td->type.iface))
833 0 : goto error;
834 6403497 : break;
835 : case TD_INTERFACE_IS_TYPE:
836 44013 : if (!XPT_Do8(cursor, &td->argnum))
837 0 : goto error;
838 44013 : break;
839 : case TD_ARRAY:
840 505308 : if (!XPT_Do8(cursor, &td->argnum) ||
841 252654 : !XPT_Do8(cursor, &td->argnum2))
842 : goto error;
843 :
844 252654 : if (cursor->state->mode == XPT_DECODE) {
845 252654 : if(!XPT_InterfaceDescriptorAddTypes(arena, id, 1))
846 0 : goto error;
847 252654 : td->type.additional_type = id->num_additional_types - 1;
848 : }
849 :
850 505308 : if (!DoTypeDescriptor(arena, cursor,
851 505308 : &id->additional_types[td->type.additional_type],
852 : id))
853 0 : goto error;
854 252654 : break;
855 : case TD_PSTRING_SIZE_IS:
856 : case TD_PWSTRING_SIZE_IS:
857 42618 : if (!XPT_Do8(cursor, &td->argnum) ||
858 21309 : !XPT_Do8(cursor, &td->argnum2))
859 : goto error;
860 21309 : break;
861 :
862 : default:
863 : /* nothing special */
864 35551848 : break;
865 : }
866 42273321 : return PR_TRUE;
867 :
868 0 : XPT_ERROR_HANDLE(arena, td);
869 : }
870 :
871 : XPT_PUBLIC_API(XPTAnnotation *)
872 : XPT_NewAnnotation(XPTArena *arena, PRUint8 flags, XPTString *creator,
873 : XPTString *private_data)
874 : {
875 0 : XPTAnnotation *ann = XPT_NEWZAP(arena, XPTAnnotation);
876 0 : if (!ann)
877 0 : return NULL;
878 0 : ann->flags = flags;
879 0 : if (XPT_ANN_IS_PRIVATE(flags)) {
880 0 : ann->creator = creator;
881 0 : ann->private_data = private_data;
882 : }
883 0 : return ann;
884 : }
885 :
886 : PRBool
887 218497 : DoAnnotation(XPTArena *arena, XPTCursor *cursor, XPTAnnotation **annp)
888 : {
889 218497 : XPTMode mode = cursor->state->mode;
890 : XPTAnnotation *ann;
891 :
892 218497 : if (mode == XPT_DECODE) {
893 218497 : ann = XPT_NEWZAP(arena, XPTAnnotation);
894 218497 : if (!ann)
895 0 : return PR_FALSE;
896 218497 : *annp = ann;
897 : } else {
898 0 : ann = *annp;
899 : }
900 :
901 218497 : if (!XPT_Do8(cursor, &ann->flags))
902 0 : goto error;
903 :
904 218497 : if (XPT_ANN_IS_PRIVATE(ann->flags)) {
905 0 : if (!XPT_DoStringInline(arena, cursor, &ann->creator) ||
906 0 : !XPT_DoStringInline(arena, cursor, &ann->private_data))
907 : goto error_2;
908 : }
909 :
910 218497 : return PR_TRUE;
911 :
912 : error_2:
913 0 : if (ann && XPT_ANN_IS_PRIVATE(ann->flags)) {
914 0 : XPT_FREEIF(arena, ann->creator);
915 0 : XPT_FREEIF(arena, ann->private_data);
916 : }
917 0 : XPT_ERROR_HANDLE(arena, ann);
918 : }
919 :
920 : PRBool
921 : XPT_GetInterfaceIndexByName(XPTInterfaceDirectoryEntry *ide_block,
922 : PRUint16 num_interfaces, char *name,
923 : PRUint16 *indexp)
924 : {
925 : int i;
926 :
927 0 : for (i=1; i<=num_interfaces; i++) {
928 0 : fprintf(stderr, "%s == %s ?\n", ide_block[i].name, name);
929 0 : if (strcmp(ide_block[i].name, name) == 0) {
930 0 : *indexp = i;
931 0 : return PR_TRUE;
932 : }
933 : }
934 0 : indexp = 0;
935 0 : return PR_FALSE;
936 : }
937 :
938 : static XPT_TYPELIB_VERSIONS_STRUCT versions[] = XPT_TYPELIB_VERSIONS;
939 : #define XPT_TYPELIB_VERSIONS_COUNT (sizeof(versions) / sizeof(versions[0]))
940 :
941 : XPT_PUBLIC_API(PRUint16)
942 : XPT_ParseVersionString(const char* str, PRUint8* major, PRUint8* minor)
943 : {
944 : unsigned int i;
945 0 : for (i = 0; i < XPT_TYPELIB_VERSIONS_COUNT; i++) {
946 0 : if (!strcmp(versions[i].str, str)) {
947 0 : *major = versions[i].major;
948 0 : *minor = versions[i].minor;
949 0 : return versions[i].code;
950 : }
951 : }
952 0 : return XPT_VERSION_UNKNOWN;
953 : }
954 :
955 :
|