1 /*
2 * Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005,
3 * 2010
4 * Tama Communications Corporation
5 *
6 * This file is part of GNU GLOBAL.
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 #include <ctype.h>
25 #include <stdio.h>
26 #include <errno.h>
27 #ifdef HAVE_STRING_H
28 #include <string.h>
29 #else
30 #include <strings.h>
31 #endif
32 #include "queue.h"
33 #include "global.h"
34 #include "cache.h"
35 #include "htags.h"
36 #include "path2url.h"
37 #include "common.h"
38
39 /*
40 * makedefineindex: make definition index (including alphabetic index)
41 *
42 * @param[in] file definition index file
43 * @param[in] total definitions total
44 * @param[out] defines @defines
45 * Globals used (input):
46 * tag cache XXX: should this be global output, not input?
47 */
48 int
makedefineindex(const char * file,int total,STRBUF * defines)49 makedefineindex(const char *file, int total, STRBUF *defines)
50 {
51 int count = 0;
52 int alpha_count = 0;
53 FILEOP *fileop_MAP = NULL, *fileop_DEFINES, *fileop_ALPHA = NULL;
54 FILE *MAP = NULL;
55 FILE *DEFINES, *STDOUT, *TAGS, *ALPHA = NULL;
56 STRBUF *sb = strbuf_open(0);
57 STRBUF *url = strbuf_open(0);
58 /* Index link */
59 const char *target = (Fflag) ? "mains" : "_top";
60 const char *indexlink;
61 const char *index_string = "Index Page";
62 char command[1024], buf[1024], alpha[32], alpha_f[32], *_;
63
64 if (!aflag && !Fflag)
65 indexlink = "mains";
66 else if (Fflag)
67 indexlink = "../defines";
68 else
69 indexlink = "../mains";
70
71 if (map_file) {
72 fileop_MAP = open_output_file(makepath(distpath, "MAP", NULL), 0);
73 MAP = get_descripter(fileop_MAP);
74 }
75 fileop_DEFINES = open_output_file(makepath(distpath, file, NULL), 0);
76 DEFINES = get_descripter(fileop_DEFINES);
77 fputs_nl(gen_page_begin(title_define_index, TOPDIR), DEFINES);
78 fputs_nl(body_begin, DEFINES);
79 fputs(header_begin, DEFINES);
80 if (Fflag)
81 fputs(gen_href_begin(NULL, "defines", normal_suffix, NULL), DEFINES);
82 fputs(title_define_index, DEFINES);
83 if (Fflag)
84 fputs(gen_href_end(), DEFINES);
85 fputs_nl(header_end, DEFINES);
86 if (!aflag && !Fflag) {
87 fputs(gen_href_begin_with_title(NULL, indexlink, normal_suffix, NULL, index_string), DEFINES);
88 if (Iflag)
89 fputs(gen_image(CURRENT, back_icon, ".."), DEFINES);
90 else
91 fputs("[..]", DEFINES);
92 fputs_nl(gen_href_end(), DEFINES);
93 }
94 if (!aflag) {
95 if (!no_order_list)
96 fputs_nl(list_begin, DEFINES);
97 }
98 /*
99 * map DEFINES to STDOUT.
100 */
101 STDOUT = DEFINES;
102 snprintf(command, sizeof(command), PQUOTE "%s -c" PQUOTE, quote_shell(global_path));
103 if ((TAGS = popen(command, "r")) == NULL)
104 die("cannot execute '%s'.", command);
105 alpha[0] = '\0';
106 while ((_ = strbuf_fgets(sb, TAGS, STRBUF_NOCRLF)) != NULL) {
107 const char *tag, *line;
108 char guide[1024], url_for_map[1024];
109
110 count++;
111 tag = _;
112 message(" [%d/%d] adding %s", count, total, tag);
113 if (aflag && (alpha[0] == '\0' || !locatestring(tag, alpha, MATCH_AT_FIRST))) {
114 const char *msg = (alpha_count == 1) ? "definition" : "definitions";
115 int c;
116
117 if (alpha[0]) {
118 char tmp[128];
119 snprintf(tmp, sizeof(tmp), "%d %s", alpha_count, msg);
120 strbuf_puts(defines, gen_href_begin_with_title("defines", alpha_f, HTML, NULL, tmp));
121 strbuf_sprintf(defines, "[%s]", alpha);
122 strbuf_puts_nl(defines, gen_href_end());
123 alpha_count = 0;
124 if (!no_order_list)
125 fputs_nl(list_end, ALPHA);
126 else
127 fputs_nl(br, ALPHA);
128 fputs(gen_href_begin_with_title(NULL, indexlink, normal_suffix, NULL, index_string), ALPHA);
129 if (Iflag)
130 fputs(gen_image(PARENT, back_icon, ".."), ALPHA);
131 else
132 fputs("[..]", ALPHA);
133 fputs_nl(gen_href_end(), ALPHA);
134 fputs_nl(body_end, ALPHA);
135 fputs_nl(gen_page_end(), ALPHA);
136 close_file(fileop_ALPHA);
137 html_count++;
138 }
139 /*
140 * setup index char (for example, 'a' of '[a]').
141 * alpha is used for display.
142 * alpha_f is used for part of path.
143 */
144 c = (unsigned char)*tag;
145 if (c > 127) {
146 int i2 = *(tag + 1) & 0xff;
147 /*
148 * for multi-byte(EUC) code.
149 */
150 alpha[0] = *tag;
151 alpha[1] = *(tag + 1);
152 alpha[2] = '\0';
153 snprintf(alpha_f, sizeof(alpha_f), "%03d%03d", c, i2);
154 } else if (isalpha(c) || c == '_') {
155 alpha[0] = *tag;
156 alpha[1] = '\0';
157 /*
158 * for CD9660 or FAT file system
159 */
160 if (islower(c)) {
161 alpha_f[0] = 'l';
162 alpha_f[1] = *tag;
163 alpha_f[2] = '\0';
164 } else {
165 alpha_f[0] = *tag;
166 alpha_f[1] = '\0';
167 }
168 } else {
169 alpha[0] = *tag;
170 alpha[1] = '\0';
171 snprintf(alpha_f, sizeof(alpha_f), "%03d", c);
172 }
173 snprintf(buf, sizeof(buf), "%s/defines/%s.%s", distpath, alpha_f, HTML);
174 fileop_ALPHA = open_output_file(buf, 0);
175 ALPHA = get_descripter(fileop_ALPHA);
176 snprintf(buf, sizeof(buf), "[%s]", alpha);
177 fputs_nl(gen_page_begin(buf, SUBDIR), ALPHA);
178 fputs_nl(body_begin, ALPHA);
179 fprintf(ALPHA, "%s[%s]%s\n", header_begin, alpha, header_end);
180 fputs(gen_href_begin_with_title(NULL, indexlink, normal_suffix, NULL, index_string), ALPHA);
181 if (Iflag)
182 fputs(gen_image(PARENT, back_icon, ".."), ALPHA);
183 else
184 fputs("[..]", ALPHA);
185 fputs_nl(gen_href_end(), ALPHA);
186 if (!no_order_list)
187 fputs_nl(list_begin, ALPHA);
188 else
189 fprintf(ALPHA, "%s%s\n", br, br);
190 STDOUT = ALPHA;
191 }
192 alpha_count++;
193 /*
194 * generating url for function definition.
195 */
196 line = cache_get(GTAGS, tag);
197 strbuf_reset(url);
198
199 if (line == NULL)
200 die("internal error in makedefineindex().");
201 /*
202 * About the format of 'line', please see the head comment of cache.c.
203 */
204 if (*line == ' ') {
205 const char *fid = line + 1;
206 const char *enumber = nextstring(fid);
207
208 snprintf(url_for_map, sizeof(url_for_map), "%s/%s.%s",
209 DEFS, fid, HTML);
210 if (dynamic) {
211 if (*action != '/' && aflag)
212 strbuf_puts(url, "../");
213 strbuf_puts(url, action);
214 strbuf_sprintf(url, "?pattern=%s%stype=definitions", tag, quote_amp);
215 } else {
216 if (aflag)
217 strbuf_puts(url, "../");
218 strbuf_sprintf(url, "%s/%s.%s", DEFS, fid, HTML);
219 }
220 snprintf(guide, sizeof(guide), "Multiple defined in %s places.", enumber);
221 } else {
222 const char *lno = line;
223 const char *fid = nextstring(line);
224 const char *path = gpath_fid2path(fid, NULL);
225
226 path += 2; /* remove './' */
227 snprintf(url_for_map, sizeof(url_for_map), "%s/%s.%s#L%s",
228 SRCS, fid, HTML, lno);
229 if (aflag)
230 strbuf_puts(url, "../");
231 strbuf_sprintf(url, "%s/%s.%s#L%s", SRCS, fid, HTML, lno);
232 snprintf(guide, sizeof(guide), "Defined at %s in %s.", lno, path);
233 }
234 if (!no_order_list)
235 fputs(item_begin, STDOUT);
236 fputs(gen_href_begin_with_title_target(NULL, strbuf_value(url), NULL, NULL, guide, target), STDOUT);
237 fputs(tag, STDOUT);
238 fputs(gen_href_end(), STDOUT);
239 if (!no_order_list)
240 fputs(item_end, STDOUT);
241 else
242 fputs(br, STDOUT);
243 fputc('\n', STDOUT);
244 if (map_file)
245 fprintf(MAP, "%s\t%s\n", tag, url_for_map);
246 }
247 if (pclose(TAGS) != 0)
248 die("terminated abnormally '%s' (errno = %d).", command, errno);
249 if (aflag && alpha[0]) {
250 char tmp[128];
251 const char *msg = (alpha_count == 1) ? "definition" : "definitions";
252
253 snprintf(tmp, sizeof(tmp), "%d %s", alpha_count, msg);
254 strbuf_puts(defines, gen_href_begin_with_title("defines", alpha_f, HTML, NULL, tmp));
255 strbuf_sprintf(defines, "[%s]", alpha);
256 strbuf_puts_nl(defines, gen_href_end());
257 if (!no_order_list)
258 fputs_nl(list_end, ALPHA);
259 else
260 fputs_nl(br, ALPHA);
261 fputs(gen_href_begin_with_title(NULL, indexlink, normal_suffix, NULL, index_string), ALPHA);
262 if (Iflag)
263 fputs(gen_image(PARENT, back_icon, ".."), ALPHA);
264 else
265 fputs("[..]", ALPHA);
266 fputs_nl(gen_href_end(), ALPHA);
267 fputs_nl(body_end, ALPHA);
268 fputs_nl(gen_page_end(), ALPHA);
269 close_file(fileop_ALPHA);
270 html_count++;
271
272 fputs(strbuf_value(defines), DEFINES);
273 }
274 if (!no_order_list && !aflag)
275 fputs_nl(list_end, DEFINES);
276 if (!aflag && !Fflag) {
277 fputs(gen_href_begin_with_title(NULL, "mains", normal_suffix, NULL, index_string), DEFINES);
278 if (Iflag)
279 fputs(gen_image(CURRENT, back_icon, ".."), DEFINES);
280 else
281 fputs("[..]", DEFINES);
282 fputs_nl(gen_href_end(), DEFINES);
283 }
284 fputs_nl(body_end, DEFINES);
285 fputs_nl(gen_page_end(), DEFINES);
286 close_file(fileop_DEFINES);
287 html_count++;
288 if (map_file)
289 close_file(fileop_MAP);
290 strbuf_close(sb);
291 strbuf_close(url);
292 return count;
293 }
294