## root/htags/defineindex.c

/* [<][>][^][v][top][bottom][index][help] */

## DEFINITIONS

This source file includes following definitions.

1. makedefineindex

    /*
     * Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005
     *      Tama Communications Corporation
     *
     * This file is part of GNU GLOBAL.
     *
     * This program is free software: you can redistribute it and/or modify
     * it under the terms of the GNU General Public License as published by
     * the Free Software Foundation, either version 3 of the License, or
     * (at your option) any later version.
     *
     * This program is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     * GNU General Public License for more details.
     *
     * You should have received a copy of the GNU General Public License
     * along with this program.  If not, see <http://www.gnu.org/licenses/>.
     */
    #ifdef HAVE_CONFIG_H
    #include <config.h>
    #endif
    #include <ctype.h>
    #include <stdio.h>
    #ifdef HAVE_STRING_H
    #include <string.h>
    #else
    #include <strings.h>
    #endif
    #include "queue.h"
    #include "global.h"
    #include "cache.h"
    #include "htags.h"
    #include "path2url.h"
    #include "common.h"

    /*
     * makedefineindex: make definition index (including alphabetic index)
     *
     *      i)      file            definition index file
     *      i)      total           definitions total
     *      o)      @defines
     *      gi)     tag cache
     */
    int
    makedefineindex(const char *file, int total, STRBUF *defines)
    {
            int count = 0;
            int alpha_count = 0;
            FILEOP *fileop_MAP = NULL, *fileop_DEFINES, *fileop_ALPHA = NULL;
            FILE *MAP = NULL;
            FILE *DEFINES, *STDOUT, *TAGS, *ALPHA = NULL;
            STRBUF *sb = strbuf_open(0);
            STRBUF *url = strbuf_open(0);
            /* Index link */
            const char *target = (Fflag) ? "mains" : "_top";
            const char *indexlink;
            const char *index_string = "Index Page";
            char command[1024], buf[1024], alpha[32], alpha_f[32], *_;

            if (!aflag && !Fflag)
                    indexlink = "mains";
            else if (Fflag)
                    indexlink = "../defines";
            else
                    indexlink = "../mains";

            if (map_file) {
                    fileop_MAP = open_output_file(makepath(distpath, "MAP", NULL), 0);
                    MAP = get_descripter(fileop_MAP);
            }
            fileop_DEFINES = open_output_file(makepath(distpath, file, NULL), 0);
            DEFINES = get_descripter(fileop_DEFINES);
            fputs_nl(gen_page_begin(title_define_index, TOPDIR), DEFINES);
            fputs_nl(body_begin, DEFINES);
            fputs(header_begin, DEFINES);
            if (Fflag)
                    fputs(gen_href_begin(NULL, "defines", normal_suffix, NULL), DEFINES);
            fputs(title_define_index, DEFINES);
            if (Fflag)
                    fputs(gen_href_end(), DEFINES);
            fputs_nl(header_end, DEFINES);
            if (!aflag && !Fflag) {
                    fputs(gen_href_begin_with_title(NULL, indexlink, normal_suffix, NULL, index_string), DEFINES);
                    if (Iflag)
                            fputs(gen_image(CURRENT, back_icon, ".."), DEFINES);
                    else
                            fputs("[..]", DEFINES);
                    fputs_nl(gen_href_end(), DEFINES);
            }
            if (!aflag) {
                    if (!no_order_list)
                            fputs_nl(list_begin, DEFINES);
            }
            /*
             * map DEFINES to STDOUT.
             */
            STDOUT = DEFINES;
            snprintf(command, sizeof(command), "%s -c", global_path);
            if ((TAGS = popen(command, "r")) == NULL)
                    die("cannot fork.");
            alpha[0] = '\0';
            while ((_ = strbuf_fgets(sb, TAGS, STRBUF_NOCRLF)) != NULL) {
                    const char *tag, *line;
                    char guide[1024], url_for_map[1024];

                    count++;
                    tag = _;
                    message(" [%d/%d] adding %s", count, total, tag);
                    if (aflag && (alpha[0] == '\0' || !locatestring(tag, alpha, MATCH_AT_FIRST))) {
                            const char *msg = (alpha_count == 1) ? "definition" : "definitions";
                            int c;

                            if (alpha[0]) {
                                    char tmp[128];
                                    snprintf(tmp, sizeof(tmp), "%d %s", alpha_count, msg);
                                    strbuf_puts(defines, gen_href_begin_with_title("defines", alpha_f, HTML, NULL, tmp));
                                    strbuf_sprintf(defines, "[%s]", alpha);
                                    strbuf_puts_nl(defines, gen_href_end());
                                    alpha_count = 0;
                                    if (!no_order_list)
                                            fputs_nl(list_end, ALPHA);
                                    else
                                            fputs_nl(br, ALPHA);
                                    fputs(gen_href_begin_with_title(NULL, indexlink, normal_suffix, NULL, index_string), ALPHA);
                                    if (Iflag)
                                            fputs(gen_image(PARENT, back_icon, ".."), ALPHA);
                                    else
                                            fputs("[..]", ALPHA);
                                    fputs_nl(gen_href_end(), ALPHA);
                                    fputs_nl(body_end, ALPHA);
                                    fputs_nl(gen_page_end(), ALPHA);
                                    close_file(fileop_ALPHA);
                                    html_count++;
                            }
                            /*
                             * setup index char (for example, 'a' of '[a]').
                             * alpha is used for display.
                             * alpha_f is used for part of path.
                             */
                            c = (unsigned char)*tag;
                            if (c > 127) {
                                    int i2 = *(tag + 1) & 0xff;
                                    /*
                                     * for multi-byte(EUC) code.
                                     */
                                    alpha[0] = *tag;
                                    alpha[1] = *(tag + 1);
                                    alpha[2] = '\0';
                                    snprintf(alpha_f, sizeof(alpha_f), "%03d%03d", c, i2);
                            } else if (isalpha(c) || c == '_') {
                                    alpha[0] = *tag;
                                    alpha[1] = '\0';
                                    /*
                                     * for CD9660 or FAT file system
                                     */
                                    if (islower(c)) {
                                            alpha_f[0] = 'l';
                                            alpha_f[1] = *tag;
                                            alpha_f[2] = '\0';
                                    } else {
                                            alpha_f[0] = *tag;
                                            alpha_f[1] = '\0';
                                    }
                            } else {
                                    alpha[0] = *tag;
                                    alpha[1] = '\0';
                                    snprintf(alpha_f, sizeof(alpha_f), "%03d", c);
                            }
                            snprintf(buf, sizeof(buf), "%s/defines/%s.%s", distpath, alpha_f, HTML);
                            fileop_ALPHA = open_output_file(buf, cflag);
                            ALPHA = get_descripter(fileop_ALPHA);
                            snprintf(buf, sizeof(buf), "[%s]", alpha);
                            fputs_nl(gen_page_begin(buf, SUBDIR), ALPHA);
                            fputs_nl(body_begin, ALPHA);
                            fprintf(ALPHA, "%s[%s]%s\n", header_begin, alpha, header_end);
                            fputs(gen_href_begin_with_title(NULL, indexlink, normal_suffix, NULL, index_string), ALPHA);
                            if (Iflag)
                                    fputs(gen_image(PARENT, back_icon, ".."), ALPHA);
                            else
                                    fputs("[..]", ALPHA);
                            fputs_nl(gen_href_end(), ALPHA);
                            if (!no_order_list)
                                    fputs_nl(list_begin, ALPHA);
                            else
                                    fprintf(ALPHA, "%s%s\n", br, br);
                            STDOUT = ALPHA;
                    }
                    alpha_count++;
                    /*
                     * generating url for function definition.
                     */
                    line = cache_get(GTAGS, tag);
                    strbuf_reset(url);

                    if (line == NULL)
                            die("internal error in makedefineindex().");
                    if (*line == ' ') {
                            SPLIT ptable;
                            const char *fid, *enumber;

                            if (split((char *)line + 1, 2, &ptable) < 2) {
                                    recover(&ptable);
                                    die("too small number of parts in makedefineindex().\n'%s'", line);
                            }
                            fid     = ptable.part[0].start;
                            enumber = ptable.part[1].start;
                            snprintf(url_for_map, sizeof(url_for_map), "%s/%s.%s",
                                    DEFS, fid, HTML);
                            /*
                             * cache record: " <file id> <entry number>"
                             */
                            if (dynamic) {
                                    if (*action != '/' && aflag)
                                            strbuf_puts(url, "../");
                                    strbuf_puts(url, action);
                                    strbuf_sprintf(url, "?pattern=%s%stype=definitions", tag, quote_amp);
                            } else {
                                    if (aflag)
                                            strbuf_puts(url, "../");
                                    strbuf_sprintf(url, "%s/%s.%s", DEFS, fid, HTML);
                            }
                            snprintf(guide, sizeof(guide), "Multiple defined in %s places.", enumber);
                            recover(&ptable);
                    } else {
                            SPLIT ptable;
                            const char *lno, *fid, *path;

                            if (split((char *)line, 2, &ptable) < 2) {
                                    recover(&ptable);
                                    die("too small number of parts in makedefineindex().\n'%s'", line);
                            }
                            lno = ptable.part[0].start;
                            path = ptable.part[1].start;
                            path += 2;              /* remove './' */

                            fid = path2fid(path);
                            snprintf(url_for_map, sizeof(url_for_map), "%s/%s.%s#L%s",
                                    SRCS, fid, HTML, lno);
                            if (aflag)
                                    strbuf_puts(url, "../");
                            strbuf_sprintf(url, "%s/%s.%s#L%s", SRCS, fid, HTML, lno);
                            snprintf(guide, sizeof(guide), "Defined at %s in %s.", lno, path);
                            recover(&ptable);
                    }
                    if (!no_order_list)
                            fputs(item_begin, STDOUT);
                    fputs(gen_href_begin_with_title_target(NULL, strbuf_value(url), NULL, NULL, guide, target), STDOUT);
                    fputs(tag, STDOUT);
                    fputs(gen_href_end(), STDOUT);
                    if (!no_order_list)
                            fputs(item_end, STDOUT);
                    else
                            fputs(br, STDOUT);
                    fputc('\n', STDOUT);
                    if (map_file)
                            fprintf(MAP, "%s\t%s\n", tag, url_for_map);
            }
            if (pclose(TAGS) != 0)
                    die("'%s' failed.", command);
            if (aflag && alpha[0]) {
                    char tmp[128];
                    const char *msg = (alpha_count == 1) ? "definition" : "definitions";

                    snprintf(tmp, sizeof(tmp), "%d %s", alpha_count, msg);
                    strbuf_puts(defines, gen_href_begin_with_title("defines", alpha_f, HTML, NULL, tmp));
                    strbuf_sprintf(defines, "[%s]", alpha);
                    strbuf_puts_nl(defines, gen_href_end());
                    if (!no_order_list)
                            fputs_nl(list_end, ALPHA);
                    else
                            fputs_nl(br, ALPHA);
                    fputs(gen_href_begin_with_title(NULL, indexlink, normal_suffix, NULL, index_string), ALPHA);
                    if (Iflag)
                            fputs(gen_image(PARENT, back_icon, ".."), ALPHA);
                    else
                            fputs("[..]", ALPHA);
                    fputs_nl(gen_href_end(), ALPHA);
                    fputs_nl(body_end, ALPHA);
                    fputs_nl(gen_page_end(), ALPHA);
                    close_file(fileop_ALPHA);
                    html_count++;

                    fputs(strbuf_value(defines), DEFINES);
            }
            if (!no_order_list && !aflag)
                    fputs_nl(list_end, DEFINES);
            if (!aflag && !Fflag) {
                    fputs(gen_href_begin_with_title(NULL, "mains", normal_suffix, NULL, index_string), DEFINES);
                    if (Iflag)
                            fputs(gen_image(CURRENT, back_icon, ".."), DEFINES);
                    else
                            fputs("[..]", DEFINES);
                    fputs_nl(gen_href_end(), DEFINES);
            }
            fputs_nl(body_end, DEFINES);
            fputs_nl(gen_page_end(), DEFINES);
            close_file(fileop_DEFINES);
            html_count++;
            if (map_file)
                    close_file(fileop_MAP);
            strbuf_close(sb);
            strbuf_close(url);
            return count;
    }

/* [<][>][^][v][top][bottom][index][help] */