rv = NextIsInclude(stack, &start, &len);
rv = NextIsInclude(stack, &start, (int *)&len);
input_callback(IDL_input_reason reason, union IDL_input_data *cb_data,               gpointer user_data){ struct input_callback_stack *stack = user_data;    struct input_callback_data *data = stack->top, *new_data = NULL;    unsigned int len, copy, avail, rv;    char *start;    switch(reason) {      case IDL_INPUT_REASON_INIT:        if (data == NULL || data->next == NULL) {            /*             * This is the first file being processed.  As it's the target             * file, we only look for it in the first entry in the include             * path, which we assume to be the current directory.             */            IncludePathEntry first_entry;            first_entry.directory = stack->include_path->directory;            first_entry.next = NULL;            new_data = new_input_callback_data(cb_data->init.filename,                                               &first_entry);        } else {            new_data = new_input_callback_data(cb_data->init.filename,                                               stack->include_path);        }        if (!new_data)            return -1;        IDL_file_set(new_data->filename, (int)new_data->lineno);        stack->top = new_data;        return 0;      case IDL_INPUT_REASON_FILL:        /* get data into the buffer */        data->start = 0;        start = NULL;        len = 0;        while (!(avail = data->buf + data->len - data->point)) {            data->point = data->buf;            /* fill the buffer */            data->len = fread(data->buf, 1, data->max, data->input);            /* if we've got data in the buffer, no need for the tricks below */            if (data->len) {                data->start = 1;                break;            }            if (ferror(data->input))                return -1;            /* pop include */            /* beard: what about closing the file? */            fclose(data->input);            data->input = NULL; /* prevent double close */            if (!data->next)                return 0;            data->input = NULL;#ifdef DEBUG_shaver_includes            fprintf(stderr, "leaving %s, returning to %s\n",                    data->filename, data->next->filename);#endif            stack->top = data->next;            /* shaver: what about freeing the input structure? */            free(data);            data = stack->top;            IDL_file_set(data->filename, (int)data->lineno);            IDL_inhibit_pop();            data->f_include = INPUT_IN_NONE;        }        /* force NUL-termination on the buffer */        data->buf[data->len] = 0;                /*         * Now we scan for sequences which require special attention:         *   \n#include                   begins an include statement         *   \n%{                         begins a raw-source block         *   /*                           begins a comment         *          * We used to be fancier here, so make sure that we sent the most         * data possible at any given time.  To that end, we skipped over         * \n%{ raw \n%} blocks and then _continued_ the search for special         * sequences like \n#include or /* comments .         *          * It was really ugly, though -- liberal use of goto!  lots of implicit         * state!  what fun! -- so now we just do this:         *         * if (special at start) {         *     process that special;         *     send next chunk of data to libIDL;         * } else {         *     scan for next special;         *     send data up to that special to libIDL;         * }         *         * Easy as pie.  Except that libIDL takes a return of zero to mean         * ``all done'', so whenever we would want to do that, we send a single         * space in the buffer.  Nobody'll notice, promise.  (For the curious,         * we would want to send zero bytes but be called again when we start         * include processing or when a comment/raw follows another         * immediately, etc.)         *         * XXX we don't handle the case where the \n#include or /* or \n%{         * sequence straddles a block boundary.  We should really fix that.         *         * XXX we don't handle doc-comments correctly (correct would be sending         * them to through to libIDL where they will get tokenized and made         * available to backends that want to generate docs).  When we next         * upgrade libIDL versions, it'll handle comments for us, which will         * help a lot.         *         * XXX our line counts are pretty much always wrong (bugzilla #5872)         *         * XXX const string foo = "/*" will just screw us horribly.         */        /*         * Order is important, so that you can have /* comments and         * #includes within raw sections, and so that you can comment out         * #includes.         */        /* XXX should check for errors here, too */        rv = NextIsRaw(data, &start, &len);        if (rv == -1) return -1;        if (!rv) {            rv = NextIsComment(data, &start, &len);            if (rv == -1) return -1;            if (!rv) {                /* includes might need to push a new file */                rv = NextIsInclude(stack, &start, &len);                if (rv == -1) return -1;                if (!rv)                    /* FindSpecial can't fail? */                    FindSpecial(data, &start, &len);            }        }        assert(start);        copy = MIN(len, (int) cb_data->fill.max_size);        if (copy) {            memcpy(cb_data->fill.buffer, start, copy);            data->point = start + copy;        } else {            cb_data->fill.buffer[0] = ' ';            copy = 1;        }#ifdef DEBUG_shaver_input        fprintf(stderr, "COPYING %d->%.*s<-COPYING\n", copy, (int)copy,                cb_data->fill.buffer);#endif        if (tracefile)            fwrite(cb_data->fill.buffer, copy, 1, tracefile);        return copy;      case IDL_INPUT_REASON_ABORT:      case IDL_INPUT_REASON_FINISH:        if (data->input && data->input != stdin)            fclose(data->input);        data->input = NULL;        free(data->buf);        data->buf = data->point = NULL;        data->len = data->max = 0;        return 0;      default:        g_error("unknown input reason %d!", reason);        return -1;    }}