// [scriptable, uuid(00000000-0000-0000-0000-000000000000)] // interface axIFoo : axIBar void DumpXPCOMInterfaceXPT(FILE *f, ITypeInfo *tiInterface) { XPTArena *arena = XPT_NewArena(1024 * 10, sizeof(double), "main xpt_link arena"); // TODO. Maybe it would be better to just feed an IDL through the regular compiler // than try and generate some XPT here. XPT_DestroyArena(arena); }
XPT_DestroyXDRState(XPTState *state) { XPTArena *arena = state->arena; if (state->pool->offset_map) XPT_HashTableDestroy(state->pool->offset_map); if (state->mode == XPT_ENCODE) XPT_DELETE(arena, state->pool->data); XPT_DELETE(arena, state->pool); XPT_DELETE(arena, state); if (arena) XPT_DestroyArena(arena); }
XPT_NewXDRState(XPTMode mode, char *data, uint32_t len) { XPTState *state; XPTArena *arena; arena = XPT_NewArena(512, sizeof(double), "an XDRState"); if (!arena) return NULL; state = XPT_NEWZAP(arena, XPTState); if (!state) goto err_free_arena; state->arena = arena; state->mode = mode; state->pool = XPT_NEW(arena, XPTDatapool); state->next_cursor[0] = state->next_cursor[1] = 1; if (!state->pool) goto err_free_state; state->pool->count = 0; state->pool->offset_map = XPT_NewHashTable(arena); if (!state->pool->offset_map) goto err_free_pool; if (mode == XPT_DECODE) { state->pool->data = data; state->pool->allocated = len; } else { state->pool->data = (char*)XPT_MALLOC(arena, XPT_GROW_CHUNK); if (!state->pool->data) goto err_free_hash; state->pool->allocated = XPT_GROW_CHUNK; } return state; err_free_hash: XPT_HashTableDestroy(state->pool->offset_map); err_free_pool: XPT_DELETE(arena, state->pool); err_free_state: XPT_DELETE(arena, state); err_free_arena: if (arena) XPT_DestroyArena(arena); return NULL; }
static gboolean typelib_epilog(TreeState *state) { XPTState *xstate = XPT_NewXDRState(XPT_ENCODE, NULL, 0); XPTCursor curs, *cursor = &curs; PRUint32 i, len, header_sz; PRUint32 oldOffset; PRUint32 newOffset; char *data; /* Write any annotations */ if (emit_typelib_annotations) { PRUint32 annotation_len, written_so_far; char *annotate_val, *timestr; time_t now; static char *annotation_format = "Created from %s.idl\nCreation date: %sInterfaces:"; /* fill in the annotations, listing resolved interfaces in order */ (void)time(&now); timestr = ctime(&now); /* Avoid dependence on nspr; no PR_smprintf and friends. */ /* How large should the annotation string be? */ annotation_len = strlen(annotation_format) + strlen(state->basename) + strlen(timestr); for (i = 0; i < HEADER(state)->num_interfaces; i++) { XPTInterfaceDirectoryEntry *ide; ide = &HEADER(state)->interface_directory[i]; if (ide->interface_descriptor) { annotation_len += strlen(ide->name) + 1; } } annotate_val = (char *) malloc(annotation_len); written_so_far = sprintf(annotate_val, annotation_format, state->basename, timestr); for (i = 0; i < HEADER(state)->num_interfaces; i++) { XPTInterfaceDirectoryEntry *ide; ide = &HEADER(state)->interface_directory[i]; if (ide->interface_descriptor) { written_so_far += sprintf(annotate_val + written_so_far, " %s", ide->name); } } HEADER(state)->annotations = XPT_NewAnnotation(ARENA(state), XPT_ANN_LAST | XPT_ANN_PRIVATE, XPT_NewStringZ(ARENA(state), "xpidl 0.99.9"), XPT_NewStringZ(ARENA(state), annotate_val)); free(annotate_val); } else { HEADER(state)->annotations = XPT_NewAnnotation(ARENA(state), XPT_ANN_LAST, NULL, NULL); } if (!HEADER(state)->annotations) { /* XXX report out of memory error */ return FALSE; } /* Write the typelib */ header_sz = XPT_SizeOfHeaderBlock(HEADER(state)); if (!xstate || !XPT_MakeCursor(xstate, XPT_HEADER, header_sz, cursor)) goto destroy_header; oldOffset = cursor->offset; if (!XPT_DoHeader(ARENA(state), cursor, &HEADER(state))) goto destroy; newOffset = cursor->offset; XPT_GetXDRDataLength(xstate, XPT_HEADER, &len); HEADER(state)->file_length = len; XPT_GetXDRDataLength(xstate, XPT_DATA, &len); HEADER(state)->file_length += len; XPT_SeekTo(cursor, oldOffset); if (!XPT_DoHeaderPrologue(ARENA(state), cursor, &HEADER(state), NULL)) goto destroy; XPT_SeekTo(cursor, newOffset); XPT_GetXDRData(xstate, XPT_HEADER, &data, &len); fwrite(data, len, 1, state->file); XPT_GetXDRData(xstate, XPT_DATA, &data, &len); fwrite(data, len, 1, state->file); destroy: XPT_DestroyXDRState(xstate); destroy_header: /* XXX XPT_DestroyHeader(HEADER(state)) */ XPT_FreeHeader(ARENA(state), HEADER(state)); XPT_DestroyArena(ARENA(state)); /* XXX should destroy priv_data here */ return TRUE; }
int main(int argc, char **argv) { XPTArena *arena; XPTState *state; XPTCursor curs, *cursor = &curs; XPTHeader *header; XPTInterfaceDirectoryEntry *IDE_array = NULL; XPTInterfaceDescriptor *id; XPTTypeDescriptor *td; XPTAnnotation *ann, *first_ann; PRUint32 header_sz, len; PRUint32 oldOffset; PRUint32 newOffset; size_t flen = 0; char *head, *data, *whole; const char *outFileName; FILE *in, *out; fixElement *fix_array = NULL; int i,j; int k = 0; if (argc < 3) { xpt_link_usage(argv); return 1; } arena = XPT_NewArena(1024 * 10, sizeof(double), "main xpt_link arena"); if (!arena) { perror("FAILED: XPT_NewArena"); return 1; } first_ann = XPT_NewAnnotation(arena, XPT_ANN_LAST, NULL, NULL); /* Check if the "-t version numnber" cmd line arg is present */ i = 1; if (argv[i][0] == '-' && argv[i][1] == 't') { /* Parse for "-t version number" */ /* If -t is the last argument on the command line, we have a problem */ if (i + 1 == argc) { fprintf(stderr, "ERROR: missing version number after -t\n"); xpt_link_usage(argv); return 1; } /* * Assume that the argument after "-t" is the version number string * and search for it in our internal list of acceptable version * numbers. */ switch (XPT_ParseVersionString(argv[++i], &major_version, &minor_version)) { case XPT_VERSION_CURRENT: case XPT_VERSION_OLD: break; case XPT_VERSION_UNSUPPORTED: fprintf(stderr, "ERROR: version \"%s\" not supported.\n", argv[i]); xpt_link_usage(argv); return 1; case XPT_VERSION_UNKNOWN: default: fprintf(stderr, "ERROR: version \"%s\" not recognised.\n", argv[i]); xpt_link_usage(argv); return 1; } /* Hang onto the output file name. It's needed later. */ outFileName = argv[++i]; /* Increment i to the cmd line arg after outFileName */ i++; } else { outFileName = argv[1]; i = 2; } for ( /* use i from earlier */ ; i < argc; i++) { char *name = argv[i]; flen = get_file_length(name); if (!flen) { fprintf(stderr, "ERROR: file %s is zero length\n", name); return 1; } in = fopen(name, "rb"); if (!in) { perror("FAILED: fopen"); return 1; } whole = XPT_MALLOC(arena, flen); if (!whole) { perror("FAILED: XPT_MALLOC for whole"); return 1; } if (flen > 0) { size_t rv = fread(whole, 1, flen, in); if (rv < flen) { fprintf(stderr, "short read (%zd vs %zd)! ouch!\n", rv, flen); return 1; } if (ferror(in) != 0 || fclose(in) != 0) { perror("FAILED: Unable to read typelib file.\n"); return 1; } state = XPT_NewXDRState(XPT_DECODE, whole, flen); if (!XPT_MakeCursor(state, XPT_HEADER, 0, cursor)) { fprintf(stdout, "XPT_MakeCursor failed for %s\n", name); return 1; } if (!XPT_DoHeader(arena, cursor, &header)) { fprintf(stdout, "DoHeader failed for %s. Is %s a valid .xpt file?\n", name, name); return 1; } /* * Make sure that the version of the typelib file is less than or * equal to the version specified in the -t cmd line arg. */ if (header && (header->major_version > major_version || (header->major_version == major_version && header->minor_version > minor_version))) { fprintf(stderr, "FAILED: %s's version, %d.%d, is newer than " "the version (%d.%d) specified in the -t " "command line argument.\n", name, header->major_version, header->minor_version, major_version, minor_version); return 1; } oldTotalNumberOfInterfaces = totalNumberOfInterfaces; totalNumberOfInterfaces += header->num_interfaces; if (header->num_interfaces > 0) { XPTInterfaceDirectoryEntry *newIDE; fixElement *newFix; newIDE = (XPTInterfaceDirectoryEntry *) XPT_MALLOC(arena, totalNumberOfInterfaces * sizeof(XPTInterfaceDirectoryEntry)); if (!newIDE) { perror("FAILED: XPT_MALLOC of IDE_array"); return 1; } if (IDE_array) { if (oldTotalNumberOfInterfaces) memcpy(newIDE, IDE_array, oldTotalNumberOfInterfaces * sizeof(XPTInterfaceDirectoryEntry)); XPT_FREE(arena, IDE_array); } IDE_array = newIDE; newFix = (fixElement *) XPT_MALLOC(arena, totalNumberOfInterfaces * sizeof(fixElement)); if (!newFix) { perror("FAILED: XPT_MALLOC of fix_array"); return 1; } if (fix_array) { if (oldTotalNumberOfInterfaces) memcpy(newFix, fix_array, oldTotalNumberOfInterfaces * sizeof(fixElement)); XPT_FREE(arena, fix_array); } fix_array = newFix; for (j=0; j<header->num_interfaces; j++) { if (!copy_IDE(&header->interface_directory[j], &IDE_array[k])) { perror("FAILED: 1st copying of IDE"); return 1; } fix_array[k].iid = IDE_array[k].iid; fix_array[k].name = IDE_array[k].name; fix_array[k].file_num = i-2; fix_array[k].interface_num = j+1; fix_array[k].is_deleted = PR_FALSE; fix_array[k].maps_to_file_num = i-2; fix_array[k].maps_to_interface_num = j+1; k++; } } /* Copy the annotations if they are not 'empty' */ if (header->annotations != NULL && header->annotations->flags != XPT_ANN_LAST) { ann = first_ann; while (ann->next != NULL) { ann = ann->next; } ann->next = header->annotations; } XPT_FREEIF(arena, header); if (state) XPT_DestroyXDRState(state); XPT_FREE(arena, whole); flen = 0; } else { fclose(in); perror("FAILED: file length <= 0"); return 1; } } /* Make sure the last annotation is the only one marked as XP_ANN_LAST. */ ann = first_ann; while (ann->next != NULL) { ann->flags &= ~XPT_ANN_LAST; ann = ann->next; } ann->flags |= XPT_ANN_LAST; /* Sort both IDE_array and fix_array by name so we can check for * name_space::name collisions. */ qsort(IDE_array, totalNumberOfInterfaces, sizeof(XPTInterfaceDirectoryEntry), compare_IDEs_by_name); qsort(fix_array, totalNumberOfInterfaces, sizeof(fixElement), compare_fixElements_by_name); /* trueNumberOfInterfaces == number of interfaces left after deletions * are made. Initialize it here to be the same as the total number of * interfaces we'ce encountered thus far. */ trueNumberOfInterfaces = totalNumberOfInterfaces; /* Iterate through the sorted interfaces. Start at one so we don't * accidentally walk off the end of the array. */ i = 1; while (i != trueNumberOfInterfaces) { /* Check for name_space::name collision. */ if (compare_strings(IDE_array[i-1].name, IDE_array[i].name) == 0 && compare_strings(IDE_array[i-1].name_space, IDE_array[i].name_space) == 0) { /* If one of the interfaces is unresolved, delete that one * preferentailly. */ if (!IDE_array[i-1].interface_descriptor) { /* Shrink the IDE_array to delete the duplicate interface. */ if (!shrink_IDE_array(IDE_array, i-1, trueNumberOfInterfaces)) { perror("FAILED: shrink_IDE_array"); return 1; } /* Update the fix array. This involves moving the deleted * entry to the end of the array (rather than deleting it) * and mapping it to the "replacement" element so we can * update interface indices appropriately later. */ update_fix_array(arena, fix_array, i-1, totalNumberOfInterfaces, i); /* Decrement the true number of interfaces since we just * deleted one. There's more than one way to get out of * this loop. */ trueNumberOfInterfaces--; } else { if (!IDE_array[i].interface_descriptor || (compare_IIDs(&IDE_array[i-1].iid, &IDE_array[i].iid) == 0)) { /* Shrink the IDE_array to delete the duplicate interface. */ if (!shrink_IDE_array(IDE_array, i, trueNumberOfInterfaces)) { perror("FAILED: shrink_IDE_array"); return 1; } /* Update the fix array. This involves moving the deleted * entry to the end of the array (rather than deleting it) * and mapping it to the "replacement" element so we can * update interface indices appropriately later. */ update_fix_array(arena, fix_array, i, totalNumberOfInterfaces, i-1); /* Decrement the true number of interfaces since we just * deleted one. There's more than one way to get out of * this loop. */ trueNumberOfInterfaces--; } else { /* Found interfaces with duplicate names but different * iids! */ char *ns = IDE_array[i].name_space; fprintf(stderr, "ERROR: found duplicate definitions of interface " "%s%s%s with iids \n", ns ? ns : "", ns ? "::" : "", IDE_array[i].name); print_IID(&IDE_array[i].iid, stderr); fprintf(stderr, " and "); print_IID(&IDE_array[i-1].iid, stderr); fprintf(stderr, "\n"); return 1; } } } else { /* Only increment if there was no name_space::name collision. */ i++; } } /* Sort the IDE_array (put them in their final order) so that updating * of indices will be meaningful. */ qsort(IDE_array, trueNumberOfInterfaces, sizeof(XPTInterfaceDirectoryEntry), compare_IDEs_by_IID); /* Sort the fix_array to match the IDE_array. */ qsort(fix_array, trueNumberOfInterfaces, sizeof(fixElement), compare_fixElements_by_IID); /* Iterate through the remaining interfaces (those not deleted) * looking for references to interfaces (such as id->parent_interface) * which need an updated index number. */ for (i=0; i<trueNumberOfInterfaces; i++) { /* Define id to save some keystrokes. */ id = IDE_array[i].interface_descriptor; /* Check for unresolved interface. */ if (id) { /* Fix parent_interface first. */ if (id->parent_interface && id->parent_interface != 0) { id->parent_interface = get_new_index(fix_array, totalNumberOfInterfaces, fix_array[i].file_num, id->parent_interface); } /* Iterate through the method descriptors looking for params of * type TD_INTERFACE_TYPE. */ for (j=0; j<id->num_methods; j++) { /* Cycle through the params first. */ for (k=0; k<id->method_descriptors[j].num_args; k++) { /* Define td to save some keystrokes. */ td = &id->method_descriptors[j].params[k].type; while (XPT_TDP_TAG(td->prefix) == TD_ARRAY) { td = &id->additional_types[td->type.additional_type]; } if (XPT_TDP_TAG(td->prefix) == TD_INTERFACE_TYPE) { td->type.iface = get_new_index(fix_array, totalNumberOfInterfaces, fix_array[i].file_num, td->type.iface); } } /* Check the result param too. Define td again to save * some keystrokes. */ td = &id->method_descriptors[j].result->type; if (XPT_TDP_TAG(td->prefix) == TD_INTERFACE_TYPE) { td->type.iface = get_new_index(fix_array, totalNumberOfInterfaces, fix_array[i].file_num, td->type.iface); } } } } /* Iterate through the array quickly looking for duplicate IIDS. * This shouldn't happen, i.e. is a failure condition, so bail * if we find a duplicate. If we have more than one entry, start * at one so we don't accidentally grep the ether. */ if (trueNumberOfInterfaces>1) { for (i=1; i<trueNumberOfInterfaces; i++) { /* Only complain if the IIDs are identical and nonzero. */ if (compare_IIDs(&IDE_array[i-1].iid, &IDE_array[i].iid) == 0 && compare_IDE_with_zero(&IDE_array[i]) != 0) { fprintf(stderr, "FATAL ERROR:\n" "Duplicate IID detected ("); print_IID(&IDE_array[i-1].iid, stderr); fprintf(stderr, ") in\n" "interface %s::%s from %s\n" "and\n" "interface %s::%s from %s\n", IDE_array[i-1].name_space ? IDE_array[i-1].name_space : "", IDE_array[i-1].name, argv[fix_array[i-1].file_num+2], IDE_array[i].name_space ? IDE_array[i].name_space : "", IDE_array[i].name, argv[fix_array[i].file_num+2]); return 1; } } } header = XPT_NewHeader(arena, (PRUint16)trueNumberOfInterfaces, major_version, minor_version); header->annotations = first_ann; for (i=0; i<trueNumberOfInterfaces; i++) { if (!copy_IDE(&IDE_array[i], &header->interface_directory[i])) { perror("FAILED: 2nd copying of IDE"); return 1; } } header_sz = XPT_SizeOfHeaderBlock(header); state = XPT_NewXDRState(XPT_ENCODE, NULL, 0); if (!state) { perror("FAILED: error creating XDRState"); return 1; } XPT_SetDataOffset(state, header_sz); if (!XPT_MakeCursor(state, XPT_HEADER, header_sz, cursor)) { perror("FAILED: error making cursor"); return 1; } oldOffset = cursor->offset; if (!XPT_DoHeader(arena, cursor, &header)) { perror("FAILED: error doing Header"); return 1; } newOffset = cursor->offset; XPT_GetXDRDataLength(state, XPT_HEADER, &len); header->file_length = len; XPT_GetXDRDataLength(state, XPT_DATA, &len); header->file_length += len; XPT_SeekTo(cursor, oldOffset); if (!XPT_DoHeaderPrologue(arena, cursor, &header, NULL)) { perror("FAILED: error doing Header"); return 1; } XPT_SeekTo(cursor, newOffset); out = fopen(outFileName, "wb"); if (!out) { perror("FAILED: fopen"); return 1; } XPT_GetXDRData(state, XPT_HEADER, &head, &len); fwrite(head, len, 1, out); XPT_GetXDRData(state, XPT_DATA, &data, &len); fwrite(data, len, 1, out); if (ferror(out) != 0 || fclose(out) != 0) { fprintf(stderr, "Error writing file: %s\n", argv[1]); } else { /* fprintf(stderr, "File written: %s\n", argv[1]); */ } if (state) XPT_DestroyXDRState(state); XPT_DestroyArena(arena); return 0; }
int main(int argc, char **argv) { XPTArena *arena; XPTHeader *header; XPTAnnotation *ann; XPTInterfaceDescriptor *id; XPTMethodDescriptor *meth; XPTState *state; XPTCursor curs, *cursor = &curs; char *data, *head; FILE *out; uint32 len, header_sz; PRBool ok; td_void.prefix.flags = TD_VOID; if (argc != 2) { fprintf(stderr, "Usage: %s <filename.xpt>\n" " Creates a simple typelib file.\n", argv[0]); return 1; } arena = XPT_NewArena(1024, sizeof(double), "main"); TRY("XPT_NewArena", arena); /* construct a header */ header = XPT_NewHeader(arena, 1, XPT_MAJOR_VERSION, XPT_MINOR_VERSION); TRY("NewHeader", header); ann = XPT_NewAnnotation(arena, XPT_ANN_LAST | XPT_ANN_PRIVATE, XPT_NewStringZ(arena, "SimpleTypeLib 1.0"), XPT_NewStringZ(arena, "See You In Rome")); TRY("NewAnnotation", ann); header->annotations = ann; header_sz = XPT_SizeOfHeaderBlock(header); id = XPT_NewInterfaceDescriptor(arena, 0, 2, 2, 0); TRY("NewInterfaceDescriptor", id); ok = XPT_FillInterfaceDirectoryEntry(arena, header->interface_directory, &iid, "Interface", "NS", id); TRY("FillInterfaceDirectoryEntry", ok); /* void method1(void) */ meth = &id->method_descriptors[0]; ok = XPT_FillMethodDescriptor(arena, meth, 0, "method1", 0); TRY("FillMethodDescriptor", ok); meth->result->flags = 0; meth->result->type.prefix.flags = TD_VOID; /* wstring method2(in uint32, in bool) */ meth = &id->method_descriptors[1]; ok = XPT_FillMethodDescriptor(arena, meth, 0, "method2", 2); TRY("FillMethodDescriptor", ok); meth->result->flags = 0; meth->result->type.prefix.flags = TD_PSTRING | XPT_TDP_POINTER; meth->params[0].type.prefix.flags = TD_UINT32; meth->params[0].flags = XPT_PD_IN; meth->params[1].type.prefix.flags = TD_BOOL; meth->params[1].flags = XPT_PD_IN; #if 0 /* const one = 1; */ id->const_descriptors[0].name = "one"; id->const_descriptors[0].type.prefix.flags = TD_UINT16; id->const_descriptors[0].value.ui16 = 1; /* const squeamish = "ossifrage"; */ id->const_descriptors[1].name = "squeamish"; id->const_descriptors[1].type.prefix.flags = TD_PBSTR | XPT_TDP_POINTER; id->const_descriptors[1].value.string = XPT_NewStringZ(arena, "ossifrage"); #endif /* serialize it */ state = XPT_NewXDRState(XPT_ENCODE, NULL, 0); TRY("NewState (ENCODE)", state); ok = XPT_MakeCursor(state, XPT_HEADER, header_sz, cursor); TRY("MakeCursor", ok); ok = XPT_DoHeader(arena, cursor, &header); TRY("DoHeader", ok); out = fopen(argv[1], "wb"); if (!out) { perror("FAILED: fopen"); return 1; } XPT_GetXDRData(state, XPT_HEADER, &head, &len); fwrite(head, len, 1, out); XPT_GetXDRData(state, XPT_DATA, &data, &len); fwrite(data, len, 1, out); if (ferror(out) != 0 || fclose(out) != 0) { fprintf(stderr, "\nError writing file: %s\n\n", argv[1]); } else { fprintf(stderr, "\nFile written: %s\n\n", argv[1]); } XPT_DestroyXDRState(state); XPT_FreeHeader(arena, header); XPT_DestroyArena(arena); return 0; }
int main(int argc, char **argv) { XPTArena *arena; XPTState *state; XPTCursor curs, *cursor = &curs; char *header, *data, *whole; uint32_t hlen, dlen, i; TRY("XPT_NewArena", (arena = XPT_NewArena(1024, sizeof(double), "main"))); TRY("NewState (ENCODE)", (state = XPT_NewXDRState(XPT_ENCODE, NULL, 0))); XPT_SetDataOffset(state, sizeof input); TRY("MakeCursor", XPT_MakeCursor(state, XPT_HEADER, sizeof input, cursor)); dump_struct("before", &input); if (XDR(arena, cursor, &input)) return 1; fprintf(stderr, "ENCODE successful\n"); XPT_GetXDRData(state, XPT_HEADER, &header, &hlen); fprintf(stderr, "XDR header %d bytes at %p:", hlen, header); for (i = 0; i < hlen; i++) fprintf(stderr, "%c%02x", i ? ',' : ' ', (uint8_t)header[i]); fprintf(stderr, "\n"); XPT_GetXDRData(state, XPT_DATA, &data, &dlen); fprintf(stderr, "XDR data %d bytes at %p:", dlen, data); for (i = 0; i < dlen; i++) fprintf(stderr, "%c%02x/%c", i ? ',' : ' ', (uint8_t)data[i], (uint8_t)data[i]); fprintf(stderr, "\n"); whole = malloc(dlen + hlen); if (!whole) { fprintf(stderr, "malloc %d failed!\n", dlen + hlen); return 1; } /* TRY_Q("malloc", (data2 = malloc(len))); */ memcpy(whole, header, hlen); memcpy(whole + hlen, data, dlen); XPT_DestroyXDRState(state); TRY("NewState (DECODE)", (state = XPT_NewXDRState(XPT_DECODE, whole, hlen + dlen))); TRY("MakeCursor", XPT_MakeCursor(state, XPT_HEADER, sizeof input, cursor)); XPT_SetDataOffset(state, sizeof input); if (XDR(arena, cursor, &output)) return 1; dump_struct("after", &output); XPT_DestroyXDRState(state); XPT_DestroyArena(arena); free(whole); return 0; }