include_start = data->buf;
include_start = data->point;
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;    int rv, avail, copy;    char *search, *check_point, *ptr, *end_copy, *raw_start, *comment_start,        *include_start;    switch(reason) {      case IDL_INPUT_REASON_INIT:        new_data = new_input_callback_data(cb_data->init.filename,                                           stack->include_path);        if (!new_data)            return -1;        /* XXX replace with IDL_set_file_position */        new_data->len = sprintf(new_data->buf, "# 1 \"%s\"\n",                                cb_data->init.filename);        stack->top = new_data;        return 0;	      case IDL_INPUT_REASON_FILL:    fill_start:        avail = data->buf + data->len - data->point;        assert(avail >= 0);        if (!avail) {            data->point = data->buf;            /* fill the buffer */        fill_buffer:            data->len = fread(data->buf, 1, data->max, data->input);            if (!data->len) {                if (ferror(data->input))                    return -1;                /* pop include */                if (data->next) {#ifdef DEBUG_shaver_includes                    fprintf(stderr, "leaving %s, returning to %s\n",                            data->filename, data->next->filename);#endif                    data = data->next;                    stack->top = data;                    IDL_file_set(data->filename, ++data->lineno);                    IDL_inhibit_pop();                    data->f_include = INPUT_IN_NONE;                    goto fill_start;                }                return 0;            }            data->buf[data->len] = 0;        }        check_point = data->point;        end_copy = data->buf + data->len;        /*         * When we're stripping comments and processing #includes,         * we need to be sure that we don't process anything inside         * \n%{ and \n%}.  In order to simplify things, we only process         * comment, include or raw-block stuff when they're at the         * beginning of the block we're about to send (data->point).         * This makes the processing much simpler, since we can skip         * data->point ahead for comments and #include, and skip         * check_point ahead for raw blocks.         */        if (!(data->f_raw || data->f_comment || data->f_include)) {            /* look for first raw/comment/include */            /* raw block */            if ((raw_start = strstr(check_point, "\n%{"))) {                end_copy = raw_start;            }            /* comment */            if ((comment_start = strstr(check_point, "/*")) &&                (!raw_start || comment_start < raw_start)) {                end_copy = comment_start;            }            /* include */            if ((include_start = strstr(check_point, "#include")) &&                (!raw_start || include_start < raw_start) &&                (!comment_start || include_start < comment_start)) {                end_copy = include_start;            }            if (end_copy == raw_start)                data->f_raw = INPUT_IN_START;            else if (end_copy == comment_start)                data->f_comment = INPUT_IN_START;            else if (end_copy == include_start)                data->f_include = INPUT_IN_START;        }                if ((end_copy == data->buf || /* just found one at the start */             end_copy == data->buf + data->len /* left over */) &&            (data->f_raw || data->f_comment || data->f_include)) {            if (data->f_raw) {                ptr = strstr(check_point, "\n%}");                if (ptr) {                    data->f_raw = INPUT_IN_NONE;                    end_copy = ptr + 3;#ifdef DEBUG_shaver_bufmgmt                    fprintf(stderr, "RAW->%.*s<-RAW\n", end_copy - data->point,                            data->point);#endif                }                assert(!data->f_comment && !data->f_include);            } else if (data->f_comment) {                /* XXX process doc comment */                ptr = strstr(check_point, "*/");                if (ptr) {                    data->point = ptr + 2; /* star-slash */#ifdef DEBUG_shaver_bufmgmt                    fprintf(stderr, "COMMENT->%.*s<-COMMENT\n",                            data->point - check_point, check_point);#endif                }                assert(!data->f_raw && !data->f_include);            } else if (data->f_include) {                /* process include */                const char *scratch;                char *filename;                include_start = data->buf;                assert(!strncmp(include_start, "#include \"", 10));                filename = include_start + 10; /* skip #include " */                assert(filename < data->buf + data->len);                ptr = strchr(filename, '\"');                if (!ptr) {                    /* XXX report error */                    return -1;                }                data->point = ptr+1;                                *ptr = 0;                ptr = strrchr(filename, '.');#ifdef DEBUG_shaver_bufmgmt                fprintf(stderr, "found #include %s\n", filename);#endif                if (!g_hash_table_lookup(stack->includes, filename)) {                    char *basename = filename;                    filename = strdup(filename);                    ptr = strrchr(basename, '.');                    if (ptr)                        *ptr = 0;                    basename = strdup(basename);                    g_hash_table_insert(stack->includes, filename, basename);                    new_data = new_input_callback_data(filename,                                                       stack->include_path);                    if (!new_data) {                        free(filename);                        return -1;                    }                    new_data->next = stack->top;                    IDL_inhibit_push();                    IDL_file_get(&scratch, &data->lineno);                    data = stack->top = new_data;                    IDL_file_set(data->filename, data->lineno);#ifdef DEBUG_shaver_bufmgmt                    fprintf(stderr, "processing #include %s\n", filename);#endif                    /* now continue getting data from new file */                    goto fill_start;                }            }        } else                avail = MIN(data->buf + data->len, end_copy) - data->point;        copy = MIN(avail, cb_data->fill.max_size);        memcpy(cb_data->fill.buffer, data->point, copy);        data->point += copy;        return copy;	      case IDL_INPUT_REASON_ABORT:      case IDL_INPUT_REASON_FINISH:        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;    }}