XPTInterfaceDirectoryEntry *newIDE, *IDE_array;
XPTInterfaceDirectoryEntry *IDE_array = NULL;
main(int argc, char **argv){    XPTState *state;    XPTCursor curs, *cursor = &curs;    XPTHeader *header;    XPTInterfaceDirectoryEntry *newIDE, *IDE_array;    XPTInterfaceDescriptor *id;    XPTTypeDescriptor *td;    XPTAnnotation *ann, *first_ann;    PRUint32 header_sz, len;    size_t flen = 0;    char *head, *data, *whole;    FILE *in, *out;    fixElement *newFix, *fix_array;    int i,j;    int k = 0;    if (argc < 3) {        xpt_link_usage(argv);        return 1;    }            /* We're going to keep annotations now, so we'll start off with one     * that will let people know that the resultant type library file     * was generated by this tool (xpt_link).     */     first_ann = XPT_NewAnnotation(XPT_ANN_LAST | XPT_ANN_PRIVATE,                                   XPT_NewStringZ("xpt_link"),                                   XPT_NewStringZ("This is a linked type library file created by xpt_link."));    for (i=2; i<argc; i++) {        char *name = argv[i];        flen = get_file_length(name);        in = fopen(name, "rb");        if (!in) {            perror("FAILED: fopen");            return 1;        }        whole = malloc(flen);        if (!whole) {            perror("FAILED: malloc for whole");            return 1;        }                if (flen > 0) {            size_t rv = fread(whole, 1, flen, in);            if (rv < 0) {                perror("FAILED: reading typelib file");                return 1;            }            if (rv < flen) {                fprintf(stderr, "short read (%d vs %d)! 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(cursor, &header)) {                fprintf(stdout,                        "DoHeader failed for %s.  Is %s a valid .xpt file?\n",                        name, name);                return 1;            }                                                                totalNumberOfInterfaces += header->num_interfaces;            if (k == 0) {                IDE_array = XPT_CALLOC(totalNumberOfInterfaces * sizeof(XPTInterfaceDirectoryEntry));                fix_array = XPT_CALLOC(totalNumberOfInterfaces * sizeof(fixElement));            } else {                newIDE = XPT_REALLOC(IDE_array, totalNumberOfInterfaces * sizeof(XPTInterfaceDirectoryEntry));                newFix = XPT_REALLOC(fix_array, totalNumberOfInterfaces * sizeof(fixElement));                if (!newIDE) {                    perror("FAILED: XPT_REALLOC of IDE_array");                    return 1;                }                if (!newFix) {                    perror("FAILED: XPT_REALLOC of newFix");                    return 1;                }                IDE_array = newIDE;                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.             */            ann = first_ann;            while (ann->next != NULL) {                ann = ann->next;            }            if (header->annotations != NULL) {                ann->next = header->annotations;            }                        XPT_FREEIF(header);            if (state)                XPT_DestroyXDRState(state);            free(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_IDEs_by_name(&IDE_array[i-1], &IDE_array[i]) == 0 &&             compare_IDEs_by_name_space(&IDE_array[i-1], &IDE_array[i]) == 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(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(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;                    if (XPT_TDP_TAG(td->prefix) == TD_INTERFACE_TYPE) {                        td->type.interface =                             get_new_index(fix_array,                                           totalNumberOfInterfaces,                                          fix_array[i].file_num,                                           td->type.interface);                    }                                                                }                /* 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.interface =                         get_new_index(fix_array, totalNumberOfInterfaces,                                      fix_array[i].file_num,                                       td->type.interface);                }                            }        }     }        /* 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_IDEs_by_IID(&IDE_array[i-1], &IDE_array[i]) == 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((PRUint16)trueNumberOfInterfaces);    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;    }        if (!XPT_DoHeader(cursor, &header)) {        perror("FAILED: error doing Header");        return 1;    }        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, "Error writing file: %s\n", argv[1]);    } else {/*        fprintf(stderr, "File written: %s\n", argv[1]); */    }     if (state)        XPT_DestroyXDRState(state);        return 0;        }