/* */
This source file includes following definitions.
- makecflowindex
1 /*
2 * Copyright (c) 2010
3 * Tama Communications Corporation
4 *
5 * This file is part of GNU GLOBAL.
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23 #include <ctype.h>
24 #include <stdio.h>
25 #ifdef STDC_HEADERS
26 #include <stdlib.h>
27 #endif
28 #include "global.h"
29 #include "htags.h"
30 #include "path2url.h"
31 #include "common.h"
32
33 /**
34 * makecflowindex: make call-tree based on @NAME{cflow}'s output
35 *
36 * @param[in] output output file name
37 * @param[in] cflow_file input file which is the output of @NAME{Cflow} with @OPTION{--format=posix}
38 */
39 int
40 makecflowindex(const char *output, const char *cflow_file)
41 {
42 STRBUF *input = strbuf_open(0);
43 FILE *ip, *op;
44 char *cflow_posix, *p;
45 const char *m0 = "Gave up making call-tree because of illegal POSIX cflow format.";
46 const char *m1 = "";
47 const char *title = locatestring(output, "callee", MATCH_AT_FIRST) ? title_callee_tree : title_call_tree;
48 int line = 0;
49 int status = 0;
50 #define ERROR do { warning("%s\n%s:%d %s.", m0, cflow_file, line, m1); status = -1; goto finish; } while(0)
51
52 /*
53 * If syntax error occured then stop the jobs and return error status.
54 * Don't die() because htags has already done a lot of work.
55 */
56 if ((ip = fopen(cflow_file, "r")) == NULL) {
57 warning("cannot open cflow file '%s'.", cflow_file);
58 return -1;
59 }
60 if ((op = fopen(makepath(distpath, output, NULL), "w")) == NULL) {
61 warning("cannot create file '%s'.", output);
62 fclose(ip);
63 return -1;
64 }
65 fputs_nl(gen_page_begin(title, TOPDIR), op);
66 fputs_nl(body_begin, op);
67 fputs(header_begin, op);
68 fputs(gen_href_begin_simple(output), op);
69 /* fputs(gen_href_begin(NULL, "cflow", normal_suffix, NULL), op);*/
70 fputs(title, op);
71 fputs(gen_href_end(), op);
72 fputs_nl(header_end, op);
73 fputs_nl(verbatim_begin, op);
74 /*
75 * Cflow's output format (with the --format=posix)
76 * +----------------------------------------------------------------
77 * | 25 isregex: int (const char *s), <libutil/char.c 54>...
78 * | 32 func: 10
79 * +----------------------------------------------------------------
80 * cflow_posix
81 * v
82 * 25 isregex: int ... , <libutil/char.c 54>...
83 * ^ ^ ^ ^
84 * anchor name path lineno
85 *
86 * cflow_posix
87 * v
88 * 32 func: 10
89 * ^ ^ ^
90 * anchor name lineno
91 */
92 while ((cflow_posix = strbuf_fgets(input, ip, STRBUF_NOCRLF)) != NULL) {
93 char *anchor, *name, *path, *lineno;
94 char *anchor_end, *name_end, *path_end, *lineno_end;
95
96 anchor = name = path = lineno = anchor_end = name_end = path_end = lineno_end = NULL;
97 line++;
98
99 for (p = cflow_posix; *p && isspace(*p); p++)
100 ;
101 m1 = "line number at the head not found";
102 if (!*p || !isdigit(*p))
103 ERROR;
104 anchor = p; /* anchor */
105 for (; *p && isdigit(*p); p++)
106 ;
107 if (!*p || !isspace(*p))
108 ERROR;
109 anchor_end = p;
110 /* seek to the function name */
111 for (; *p; p++) {
112 /* skip special characters of HTML like '├'*/
113 if (*p == '&') {
114 for (p++; *p && *p != ';'; p++)
115 ;
116 if (*p != ';')
117 ERROR;
118 } else if (isalpha(*p) || *p == '_')
119 break;
120 }
121 m1 = "function name not found";
122 if (!*p || !isalpha(*p))
123 ERROR;
124 name = p; /* name */
125 for (; *p && *p != ':'; p++)
126 ;
127 if (*p != ':')
128 ERROR;
129 name_end = p++;
130 if (*p++ != ' ')
131 ERROR;
132 if (isdigit(*p)) { /* (1) name: 999 */
133 lineno = p; /* lineno */
134 for (; *p && isdigit(*p); p++)
135 ;
136 lineno_end = p;
137 } else if (*p == '<' && *(p + 1) == '>') { /* (2) name: <> */
138 ;
139 } else { /* (3) name: ... <path lineno> */
140 m1 = "<path lineno> not found";
141 for (; *p && *p != '<'; p++)
142 ;
143 if (!*p++)
144 ERROR;
145 path = p;
146 m1 = "path not found";
147 for (; *p && !isspace(*p); p++)
148 if (*p == '>')
149 ERROR;
150 if (!*p || *p != ' ')
151 ERROR;
152 path_end = p++;
153 m1 = "lineno not found";
154 if (!isdigit(*p))
155 ERROR;
156 lineno = p;
157 for (; *p && isdigit(*p); p++)
158 ;
159 if (*p != '>')
160 ERROR;
161 lineno_end = p;
162 }
163 /*
164 * print anchor
165 */
166 fprintf(op, gen_name_number(atoi(anchor)));
167 /*
168 * print until name
169 */
170 fwrite(cflow_posix, name - cflow_posix, 1, op);
171 /*
172 * print name
173 */
174 if (path) {
175 const char *fid = NULL;
176 int path_save = *path_end;
177 int lineno_save = *lineno_end;
178
179 *path_end = *lineno_end = 0;
180 if (test("f", path) && (fid = path2fid_readonly(path)) != NULL)
181 fprintf(op, gen_href_begin(SRCS, fid, HTML, lineno));
182 else
183 path = lineno = NULL; /* not to print </a> */
184 *path_end = path_save;
185 *lineno_end = lineno_save;
186 } else if (lineno) {
187 int lineno_save = *lineno_end;
188
189 *lineno_end = 0;
190 fprintf(op, gen_href_begin(NULL, NULL, NULL, lineno));
191 *lineno_end = lineno_save;
192 }
193 fwrite(name, name_end - name, 1, op);
194 if (path || lineno)
195 fputs(gen_href_end(), op);
196 /*
197 * print the rest
198 */
199 for (p = name_end; *p; p++) {
200 if (*p == '<')
201 fputs(quote_little, op);
202 else if (*p == '>')
203 fputs(quote_great, op);
204 else
205 fputc(*p, op);
206 }
207 fputc('\n', op);
208 }
209 finish:
210 fputs_nl(verbatim_end, op);
211 fputs_nl(body_end, op);
212 fputs_nl(gen_page_end(), op);
213 strbuf_close(input);
214 fclose(ip);
215 fclose(op);
216 return status;
217 }
/* */