/** * Generate beginning of generic page * * @param[in] title title of this page * @param[in] place #SUBDIR: this page is in sub directory <br> * #TOPDIR: this page is in the top directory * @param[in] use_frameset * use frameset document type or not * @param[in] header_item * item which should be inserted into the header */ static const char * gen_page_generic_begin(const char *title, int place, int use_frameset, const char *header_item) { STATIC_STRBUF(sb); const char *dir = NULL; switch (place) { case TOPDIR: dir = ""; break; case SUBDIR: dir = "../"; break; case CGIDIR: dir = "$basedir/"; /* decided by the CGI script */ break; } strbuf_clear(sb); if (enable_xhtml) { /* * Since some browser cannot treat "<?xml...>", we don't * write the declaration as long as XHTML1.1 is not required. */ if (strict_xhtml) { strbuf_puts_nl(sb, "<?xml version='1.0' encoding='ISO-8859-1'?>"); strbuf_sprintf(sb, "<?xml-stylesheet type='text/css' href='%sstyle.css'?>\n", dir); } /* * If the --frame option are specified then we take * 'XHTML 1.0 Frameset' for index.html * and 'XHTML 1.0 Transitional' for other files, * else if the config variable 'xhtml_version' is * set to '1.1' then we take 'XHTML 1.1', * else 'XHTML 1.0 Transitional'. */ if (use_frameset) strbuf_puts_nl(sb, "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Frameset//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd'>"); else if (!Fflag && strict_xhtml) strbuf_puts_nl(sb, "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.1//EN' 'http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd'>"); else strbuf_puts_nl(sb, "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>"); } strbuf_puts_nl(sb, html_begin); strbuf_puts_nl(sb, html_head_begin); strbuf_puts(sb, html_title_begin); strbuf_puts(sb, title); strbuf_puts_nl(sb, html_title_end); strbuf_sprintf(sb, "<meta name='robots' content='noindex,nofollow'%s>\n", empty_element); strbuf_sprintf(sb, "<meta name='generator' content='GLOBAL-%s'%s>\n", get_version(), empty_element); if (enable_xhtml) { strbuf_sprintf(sb, "<meta http-equiv='Content-Style-Type' content='text/css'%s>\n", empty_element); strbuf_sprintf(sb, "<link rel='stylesheet' type='text/css' href='%sstyle.css'%s>\n", dir, empty_element); } if (header_item) strbuf_puts(sb, header_item); /* internal use */ if (html_header) strbuf_puts(sb, html_header); /* --html-header=file */ strbuf_puts(sb, html_head_end); return strbuf_value(sb); }
/** * Load file. */ void loadfile(const char *file, STRBUF *result) { STRBUF *sb = strbuf_open(0); FILE *ip = fopen(file, "r"); if (!ip) die("file '%s' not found.", file); while (strbuf_fgets(sb, ip, STRBUF_NOCRLF) != NULL) strbuf_puts_nl(result, strbuf_value(sb)); fclose(ip); strbuf_close(sb); }
/* * makedefineindex: make definition index (including alphabetic index) * * @param[in] file definition index file * @param[in] total definitions total * @param[out] defines @defines * Globals used (input): * tag cache XXX: should this be global output, not input? */ 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), PQUOTE "%s -c" PQUOTE, quote_shell(global_path)); if ((TAGS = popen(command, "r")) == NULL) die("cannot execute '%s'.", command); 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, 0); 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()."); /* * About the format of 'line', please see the head comment of cache.c. */ if (*line == ' ') { const char *fid = line + 1; const char *enumber = nextstring(fid); snprintf(url_for_map, sizeof(url_for_map), "%s/%s.%s", DEFS, fid, HTML); 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); } else { const char *lno = line; const char *fid = nextstring(line); const char *path = gpath_fid2path(fid, NULL); path += 2; /* remove './' */ 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); } 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("terminated abnormally '%s' (errno = %d).", command, errno); 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; }
/** * makecommonpart: make a common part for "mains.html" and "index.html" * * @param[in] title * @param[in] defines * @param[in] files * @return index common part */ static char * makecommonpart(const char *title, const char *defines, const char *files) { FILE *ip; STRBUF *sb = strbuf_open(0); STRBUF *ib = strbuf_open(0); char buf[MAXFILLEN]; const char *tips = "Go to the GLOBAL project page."; const char *_, *item; strbuf_puts(sb, title_begin); strbuf_puts(sb, title); strbuf_puts_nl(sb, title_end); strbuf_puts_nl(sb, poweredby_begin); strbuf_sprintf(sb, "Last updated %s%s\n", now(), br); if (Iflag) { snprintf(buf, sizeof(buf), "Powered by GLOBAL-%s.", get_version()); strbuf_puts(sb, gen_href_begin_with_title_target(NULL, www, NULL, NULL, tips,"_top")); strbuf_puts(sb, gen_image(CURRENT, "pglobe", buf)); strbuf_puts(sb, gen_href_end()); strbuf_puts(sb, br); } else { strbuf_sprintf(sb, "Powered by %sGLOBAL-%s%s.%s\n", gen_href_begin_with_title_target(NULL, www, NULL, NULL, tips, "_top"), get_version(), gen_href_end(), br); } strbuf_puts_nl(sb, poweredby_end); strbuf_puts_nl(sb, hr); /* * Print items according to the value of variable 'item_order'. */ for (item = item_order; *item; item++) { switch (*item) { case 'c': if (caution) { strbuf_puts_nl(sb, caution_begin); strbuf_sprintf(sb, "<font size='+2' color='red'>CAUTION</font>%s\n", br); strbuf_sprintf(sb, "This hypertext consists of %d files.\n", html_count); strbuf_puts_nl(sb, "Please don't download the whole hypertext using a hypertext copy tool."); strbuf_puts_nl(sb, "Our network cannot afford such traffic."); strbuf_puts_nl(sb, "Instead, you can generate the same thing in your computer using"); strbuf_puts(sb, gen_href_begin_with_title_target(NULL, www, NULL, NULL, NULL, "_top")); strbuf_puts(sb, "GLOBAL source code tag system"); strbuf_puts_nl(sb, gen_href_end()); strbuf_puts_nl(sb, "Thank you."); strbuf_puts_nl(sb, caution_end); strbuf_sprintf(sb, "\n%s\n", hr); } break; case 's': if (fflag) { strbuf_puts(sb, makesearchpart(NULL)); strbuf_puts_nl(sb, hr); } break; case 't': if (call_file || callee_file) { strbuf_puts(sb, header_begin); if (call_file) { strbuf_puts(sb, gen_href_begin(NULL, "call", normal_suffix, NULL)); strbuf_puts(sb, title_call_tree); strbuf_puts(sb, gen_href_end()); } if (call_file && callee_file) strbuf_puts(sb, " / "); if (callee_file) { strbuf_puts(sb, gen_href_begin(NULL, "callee", normal_suffix, NULL)); strbuf_puts(sb, title_callee_tree); strbuf_puts(sb, gen_href_end()); } strbuf_puts_nl(sb, header_end); strbuf_puts_nl(sb, hr); } break; case 'm': strbuf_sprintf(sb, "%sMAINS%s\n", header_begin, header_end); snprintf(buf, sizeof(buf), PQUOTE "%s --result=ctags-xid --encode-path=\" \t\" --nofilter=path %s" PQUOTE, quote_shell(global_path), main_func); ip = popen(buf, "r"); if (!ip) die("cannot execute '%s'.", buf); strbuf_puts_nl(sb, gen_list_begin()); while ((_ = strbuf_fgets(ib, ip, STRBUF_NOCRLF)) != NULL) { char fid[MAXFIDLEN]; const char *ctags_x = parse_xid(_, fid, NULL); strbuf_puts_nl(sb, gen_list_body(SRCS, ctags_x, fid)); } strbuf_puts_nl(sb, gen_list_end()); if (pclose(ip) != 0) die("terminated abnormally '%s' (errno = %d).", buf, errno); strbuf_puts_nl(sb, hr); break; case 'd': if (aflag && !Fflag) { strbuf_puts(sb, header_begin); strbuf_puts(sb, title_define_index); strbuf_puts_nl(sb, header_end); strbuf_puts(sb, defines); } else { strbuf_puts(sb, header_begin); strbuf_puts(sb, gen_href_begin(NULL, "defines", normal_suffix, NULL)); strbuf_puts(sb, title_define_index); strbuf_puts(sb, gen_href_end()); strbuf_puts_nl(sb, header_end); } strbuf_puts_nl(sb, hr); break; case 'f': if (Fflag) { strbuf_puts(sb, header_begin); strbuf_puts(sb, gen_href_begin(NULL, "files", normal_suffix, NULL)); strbuf_puts(sb, title_file_index); strbuf_puts(sb, gen_href_end()); strbuf_puts_nl(sb, header_end); } else { strbuf_puts(sb, header_begin); strbuf_puts(sb, title_file_index); strbuf_puts_nl(sb, header_end); if (tree_view) { strbuf_puts_nl(sb, tree_control); strbuf_puts_nl(sb, tree_loading); if (tree_view_type) { strbuf_sprintf(sb, tree_begin_using, tree_view_type); strbuf_putc(sb, '\n'); } else { strbuf_puts_nl(sb, tree_begin); } } else if (table_flist) strbuf_puts_nl(sb, flist_begin); else if (!no_order_list) strbuf_puts_nl(sb, list_begin); strbuf_puts(sb, files); if (tree_view) strbuf_puts_nl(sb, tree_end); else if (table_flist) strbuf_puts_nl(sb, flist_end); else if (!no_order_list) strbuf_puts_nl(sb, list_end); else strbuf_puts_nl(sb, br); } strbuf_puts_nl(sb, hr); break; default: warning("unknown item '%c'. (Ignored)", *item); break; } } strbuf_close(ib); return strbuf_value(sb); /* doesn't close string buffer */ }
/* * makesearchpart: make search part * * @param[in] target $target * @return html */ static char * makesearchpart(const char *target) { STATIC_STRBUF(sb); strbuf_clear(sb); strbuf_puts(sb, header_begin); if (Fflag) strbuf_puts(sb, gen_href_begin(NULL, "search", normal_suffix, NULL)); strbuf_puts(sb, "SEARCH"); if (Fflag) strbuf_puts(sb, gen_href_end()); strbuf_puts_nl(sb, header_end); if (!target) { strbuf_puts(sb, "Please input object name and select [Search]. POSIX's regular expression is allowed."); strbuf_puts_nl(sb, br); } strbuf_puts_nl(sb, gen_form_begin(target)); strbuf_puts_nl(sb, gen_input("pattern", NULL, NULL)); strbuf_puts_nl(sb, gen_input(NULL, "Search", "submit")); strbuf_puts(sb, gen_input(NULL, "Reset", "reset")); strbuf_puts_nl(sb, br); strbuf_puts(sb, gen_input_radio("type", "definition", 1, "Retrieve the definition place of the specified symbol.")); strbuf_puts_nl(sb, target ? "Def" : "Definition"); strbuf_puts(sb, gen_input_radio("type", "reference", 0, "Retrieve the reference place of the specified symbol.")); strbuf_puts_nl(sb, target ? "Ref" : "Reference"); strbuf_puts(sb, gen_input_radio("type", "symbol", 0, "Retrieve the place of the specified symbol is used.")); strbuf_puts_nl(sb, target ? "Sym" : "Other symbol"); strbuf_puts(sb, gen_input_radio("type", "path", 0, "Look for path name which matches to the specified pattern.")); strbuf_puts_nl(sb, target ? "Path" : "Path name"); if (enable_grep) { strbuf_puts(sb, gen_input_radio("type", "grep", 0, "Retrieve lines which matches to the specified pattern.")); strbuf_puts_nl(sb, target ? "Grep" : "Grep pattern"); } if (enable_idutils && test("f", makepath(dbpath, "ID", NULL))) { strbuf_puts(sb, gen_input_radio("type", "idutils", 0, "Retrieve lines which matches to the specified pattern using idutils(1).")); strbuf_puts_nl(sb, target ? "Id" : "Id pattern"); } strbuf_puts_nl(sb, br); strbuf_puts(sb, gen_input_checkbox("icase", NULL, "Ignore case distinctions in the pattern.")); strbuf_puts_nl(sb, target ? "Icase" : "Ignore case"); if (other_files) { strbuf_puts(sb, gen_input_checkbox("other", NULL, "Files other than the source code are also retrieved.")); strbuf_puts_nl(sb, target ? "Other" : "Other files"); } if (other_files && !target) { strbuf_puts_nl(sb, br); strbuf_puts(sb, "('Other files' is effective only to 'Path name'"); if (enable_grep) strbuf_puts(sb, " and 'Grep pattern'"); strbuf_puts_nl(sb, ".)"); } strbuf_puts_nl(sb, gen_form_end()); return strbuf_value(sb); }
int main(int argc, char **argv) { const char *av = NULL; int func_total, file_total; char arg_dbpath[MAXPATHLEN]; const char *index = NULL; int optchar; int option_index = 0; STATISTICS_TIME *tim; arg_dbpath[0] = 0; basic_check(); /* * Setup GTAGSCONF and GTAGSLABEL environment variable * according to the --gtagsconf and --gtagslabel option. */ preparse_options(argc, argv); /* * Load configuration values. */ if (!vgetcwd(cwdpath, sizeof(cwdpath))) die("cannot get current directory."); openconf(cwdpath); configuration(); /* * setup_langmap() is needed to use decide_lang(). */ setup_langmap(langmap); save_environment(argc, argv); /* * insert htags_options at the head of argv. */ setenv_from_config(); { char *env = getenv("HTAGS_OPTIONS"); if (env && *env) argv = prepend_options(&argc, argv, env); } while ((optchar = getopt_long(argc, argv, "acd:DfFghIm:nNoqst:Tvwx", long_options, &option_index)) != EOF) { switch (optchar) { case 0: /* already flags set */ break; case OPT_AUTO_COMPLETION: auto_completion = 1; if (optarg) { if (atoi(optarg) > 0) auto_completion_limit = optarg; else die("The option value of --auto-completion must be numeric."); } break; case OPT_CFLOW: call_file = optarg; break; case OPT_CALL_TREE: call_file = optarg; break; case OPT_CALLEE_TREE: callee_file = optarg; break; case OPT_CVSWEB: cvsweb_url = optarg; break; case OPT_CVSWEB_CVSROOT: cvsweb_cvsroot = optarg; break; case OPT_GTAGSCONF: case OPT_GTAGSLABEL: /* These options are already parsed in preparse_options() */ break; case OPT_INSERT_FOOTER: insert_footer = optarg; break; case OPT_INSERT_HEADER: insert_header = optarg; break; case OPT_HTML_HEADER: { STATIC_STRBUF(sb); if (!test("r", optarg)) die("file '%s' not found.", optarg); strbuf_clear(sb); loadfile(optarg, sb); html_header = strbuf_value(sb); } break; case OPT_ITEM_ORDER: item_order = optarg; break; case OPT_TABS: if (atoi(optarg) > 0) tabs = atoi(optarg); else die("--tabs option requires numeric value."); break; case OPT_NCOL: if (atoi(optarg) > 0) ncol = atoi(optarg); else die("--ncol option requires numeric value."); break; case OPT_TREE_VIEW: tree_view = 1; if (optarg) tree_view_type = optarg; break; case 'a': aflag++; break; case 'd': strlimcpy(arg_dbpath, optarg, sizeof(arg_dbpath)); break; case 'D': dynamic = 1; break; case 'f': fflag++; break; case 'F': Fflag++; break; case 'g': gflag++; break; case 'h': definition_header = AFTER_HEADER; if (optarg) { if (!strcmp(optarg, "before")) definition_header = BEFORE_HEADER; else if (!strcmp(optarg, "right")) definition_header = RIGHT_HEADER; else if (!strcmp(optarg, "after")) definition_header = AFTER_HEADER; else die("The option value of --func-header must be one of 'before', 'right' and 'after'."); } break; case 'I': Iflag++; break; case 'm': main_func = optarg; break; case 'n': nflag++; if (optarg) { if (atoi(optarg) > 0) ncol = atoi(optarg); else die("The option value of --line-number must be numeric."); } break; case 'o': other_files = 1; break; case 's': symbol = 1; break; case 'T': table_flist = 1; if (optarg) { if (atoi(optarg) > 0) flist_fields = atoi(optarg); else die("The option value of the --table-flist must be numeric."); } break; case 't': title = optarg; break; case 'q': qflag++; setquiet(); break; case 'v': vflag++; setverbose(); break; case 'w': wflag++; break; default: usage(); break; } } /* * Leaving everything to htags. * Htags selects popular options for you. */ if (suggest2) suggest = 1; if (suggest) { int gtags_not_found = 0; char dbpath[MAXPATHLEN]; aflag = Iflag = nflag = vflag = 1; setverbose(); definition_header = AFTER_HEADER; other_files = symbol = show_position = table_flist = fixed_guide = 1; if (arg_dbpath[0]) { if (!test("f", makepath(arg_dbpath, dbname(GTAGS), NULL))) gtags_not_found = 1; } else if (gtagsexist(".", dbpath, sizeof(dbpath), 0) == 0) { gtags_not_found = 1; } if (gtags_not_found) gflag = 1; } if (suggest2) { Fflag = 1; /* uses frame */ fflag = dynamic = 1; /* needs a HTTP server */ auto_completion = tree_view = 1; /* needs javascript */ } if (call_file && !test("fr", call_file)) die("cflow file not found. '%s'", call_file); if (callee_file && !test("fr", callee_file)) die("cflow file not found. '%s'", callee_file); if (insert_header && !test("fr", insert_header)) die("page header file '%s' not found.", insert_header); if (insert_footer && !test("fr", insert_footer)) die("page footer file '%s' not found.", insert_footer); if (!fflag) auto_completion = 0; argc -= optind; argv += optind; if (!av) av = (argc > 0) ? *argv : NULL; if (debug) setdebug(); settabs(tabs); /* setup tab skip */ if (qflag) { setquiet(); vflag = 0; } if (show_version) version(av, vflag); if (show_help) help(); /* * Invokes gtags beforehand. */ if (gflag) { STRBUF *sb = strbuf_open(0); strbuf_puts(sb, gtags_path); if (vflag) strbuf_puts(sb, " -v"); if (wflag) strbuf_puts(sb, " -w"); if (suggest2 && enable_idutils && usable("mkid")) strbuf_puts(sb, " -I"); if (arg_dbpath[0]) { strbuf_putc(sb, ' '); strbuf_puts(sb, arg_dbpath); } if (system(strbuf_value(sb))) die("cannot execute gtags(1) command."); strbuf_close(sb); } /* * get dbpath. */ if (arg_dbpath[0]) { strlimcpy(dbpath, arg_dbpath, sizeof(dbpath)); } else { int status = setupdbpath(0); if (status < 0) die_with_code(-status, "%s", gtags_dbpath_error); strlimcpy(dbpath, get_dbpath(), sizeof(dbpath)); } if (!title) { char *p = strrchr(cwdpath, sep); title = p ? p + 1 : cwdpath; } if (cvsweb_url && test("d", "CVS")) use_cvs_module = 1; /* * decide directory in which we make hypertext. */ if (av) { char realpath[MAXPATHLEN]; if (!test("dw", av)) die("'%s' is not writable directory.", av); if (chdir(av) < 0) die("directory '%s' not found.", av); if (!vgetcwd(realpath, sizeof(realpath))) die("cannot get current directory"); if (chdir(cwdpath) < 0) die("cannot return to original directory."); snprintf(distpath, sizeof(distpath), "%s/HTML", realpath); } else { snprintf(distpath, sizeof(distpath), "%s/HTML", cwdpath); } /* * Existence check of tag files. */ { int i; const char *path; GTOP *gtop; for (i = GPATH; i < GTAGLIM; i++) { path = makepath(dbpath, dbname(i), NULL); gtags_exist[i] = test("fr", path); } /* * Real GRTAGS includes virtual GSYMS. */ gtags_exist[GSYMS] = symbol ? 1 : 0; if (!gtags_exist[GPATH] || !gtags_exist[GTAGS] || !gtags_exist[GRTAGS]) die("GPATH, GTAGS and/or GRTAGS not found. Please reexecute htags with the -g option."); /* * version check. * Do nothing, but the version of tag file will be checked. */ gtop = gtags_open(dbpath, cwdpath, GTAGS, GTAGS_READ, 0); gtags_close(gtop); /* * Check whether GRTAGS is empty. */ gtop = gtags_open(dbpath, cwdpath, GRTAGS, GTAGS_READ, 0); if (gtags_first(gtop, NULL, 0) == NULL) grtags_is_empty = 1; gtags_close(gtop); } /* * make dbpath absolute. */ { char buf[MAXPATHLEN]; if (realpath(dbpath, buf) == NULL) die("cannot get realpath of dbpath."); strlimcpy(dbpath, buf, sizeof(dbpath)); } /* * The older version (4.8.7 or former) of GPATH doesn't have files * other than source file. The oflag requires new version of GPATH. */ if (other_files) { GFIND *gp = gfind_open(dbpath, NULL, 0, 0); if (gp->version < 2) die("GPATH is old format. Please remake it by invoking gtags(1)."); gfind_close(gp); } /* * for global(1) and gtags(1). */ set_env("GTAGSROOT", cwdpath); set_env("GTAGSDBPATH", dbpath); set_env("GTAGSLIBPATH", ""); /*------------------------------------------------------------------ * MAKE FILES *------------------------------------------------------------------ * HTML/cgi-bin/global.cgi ... CGI program (1) * HTML/cgi-bin/ghtml.cgi ... unzip script (1) * HTML/.htaccess ... skeleton of .htaccess (1) * HTML/help.html ... help file (2) * HTML/R/ ... references (3) * HTML/D/ ... definitions (3) * HTML/search.html ... search index (4) * HTML/defines.html ... definitions index (5) * HTML/defines/ ... definitions index (5) * HTML/files/ ... file index (6) * HTML/index.html ... index file (7) * HTML/mains.html ... main index (8) * HTML/null.html ... main null html (8) * HTML/S/ ... source files (9) * HTML/I/ ... include file index (9) * HTML/rebuild.sh ... rebuild script (10) * HTML/style.css ... style sheet (11) *------------------------------------------------------------------ */ /* for clean up */ signal_setup(); sethandler(clean); HTML = normal_suffix; message("[%s] Htags started", now()); init_statistics(); /* * (#) check if GTAGS, GRTAGS is the latest. */ if (get_dbpath()) message(" Using %s/GTAGS.", get_dbpath()); if (grtags_is_empty) message(" GRTAGS is empty."); if (gpath_open(dbpath, 0) < 0) die("GPATH not found."); if (!w32) { /* UNDER CONSTRUCTION */ } if (auto_completion || tree_view) { STATIC_STRBUF(sb); strbuf_clear(sb); strbuf_puts_nl(sb, "<script type='text/javascript' src='js/jquery.js'></script>"); if (auto_completion) loadfile(makepath(datadir, "gtags/jscode_suggest", NULL), sb); if (tree_view) loadfile(makepath(datadir, "gtags/jscode_treeview", NULL), sb); jscode = strbuf_value(sb); } /* * (0) make directories */ message("[%s] (0) making directories ...", now()); if (!test("d", distpath)) if (mkdir(distpath, 0777) < 0) die("cannot make directory '%s'.", distpath); make_directory_in_distpath("files"); make_directory_in_distpath("defines"); make_directory_in_distpath(SRCS); make_directory_in_distpath(INCS); make_directory_in_distpath(INCREFS); if (!dynamic) { make_directory_in_distpath(DEFS); make_directory_in_distpath(REFS); if (symbol) make_directory_in_distpath(SYMS); } if (fflag || dynamic) make_directory_in_distpath("cgi-bin"); if (Iflag) make_directory_in_distpath("icons"); if (auto_completion || tree_view) make_directory_in_distpath("js"); /* * (1) make CGI program */ if (fflag || dynamic) { char cgidir[MAXPATHLEN]; snprintf(cgidir, sizeof(cgidir), "%s/cgi-bin", distpath); message("[%s] (1) making CGI program ...", now()); if (fflag || dynamic) makeprogram(cgidir, "global.cgi", 0755); if (auto_completion) makeprogram(cgidir, "completion.cgi", 0755); makehtaccess(cgidir, ".htaccess", 0644); } else { message("[%s] (1) making CGI program ...(skipped)", now()); } if (av) { const char *path = makepath(distpath, "GTAGSROOT", NULL); FILE *op = fopen(path, "w"); if (op == NULL) die("cannot make file '%s'.", path); fputs(cwdpath, op); fputc('\n', op); fclose(op); } /* * (2) make help file */ message("[%s] (2) making help.html ...", now()); makehelp("help.html"); /* * (#) load GPATH */ load_gpath(dbpath); /* * (3) make function entries (D/ and R/) * MAKING TAG CACHE */ message("[%s] (3) making tag lists ...", now()); cache_open(); tim = statistics_time_start("Time of making tag lists"); func_total = makedupindex(); statistics_time_end(tim); message("Total %d functions.", func_total); /* * (4) search index. (search.html) */ if (Fflag && fflag) { message("[%s] (4) making search index ...", now()); makesearchindex("search.html"); } { STRBUF *defines = strbuf_open(0); STRBUF *files = strbuf_open(0); /* * (5) make definition index (defines.html and defines/) * PRODUCE @defines */ message("[%s] (5) making definition index ...", now()); tim = statistics_time_start("Time of making definition index"); func_total = makedefineindex("defines.html", func_total, defines); statistics_time_end(tim); message("Total %d functions.", func_total); /* * (6) make file index (files.html and files/) * PRODUCE @files, %includes */ message("[%s] (6) making file index ...", now()); init_inc(); tim = statistics_time_start("Time of making file index"); file_total = makefileindex("files.html", files); statistics_time_end(tim); message("Total %d files.", file_total); html_count += file_total; /* * (7) make call tree using cflow(1)'s output (cflow.html) */ if (call_file || callee_file) { message("[%s] (7) making cflow index ...", now()); tim = statistics_time_start("Time of making cflow index"); if (call_file) if (makecflowindex("call.html", call_file) < 0) call_file = NULL; if (callee_file) if (makecflowindex("callee.html", callee_file) < 0) callee_file = NULL; statistics_time_end(tim); } /* * [#] make include file index. */ message("[%s] (#) making include file index ...", now()); tim = statistics_time_start("Time of making include file index"); makeincludeindex(); statistics_time_end(tim); /* * [#] make a common part for mains.html and index.html * USING @defines @files */ message("[%s] (#) making a common part ...", now()); index = makecommonpart(title, strbuf_value(defines), strbuf_value(files)); strbuf_close(defines); strbuf_close(files); } /* * (7)make index file (index.html) */ message("[%s] (7) making index file ...", now()); makeindex("index.html", title, index); /* * (8) make main index (mains.html) */ message("[%s] (8) making main index ...", now()); makemainindex("mains.html", index); /* * (9) make HTML files (SRCS/) * USING TAG CACHE, %includes and anchor database. */ message("[%s] (9) making hypertext from source code ...", now()); tim = statistics_time_start("Time of making hypertext"); makehtml(file_total); statistics_time_end(tim); /* * (10) rebuild script. (rebuild.sh) * * Don't grant execute permission to rebuild script. */ makerebuild("rebuild.sh"); if (chmod(makepath(distpath, "rebuild.sh", NULL), 0640) < 0) die("cannot chmod rebuild script."); /* * (11) style sheet file (style.css) */ if (enable_xhtml) { char src[MAXPATHLEN]; char dist[MAXPATHLEN]; snprintf(src, sizeof(src), "%s/gtags/style.css", datadir); snprintf(dist, sizeof(dist), "%s/style.css", distpath); copyfile(src, dist); } if (auto_completion || tree_view) { char src[MAXPATHLEN]; char dist[MAXPATHLEN]; snprintf(src, sizeof(src), "%s/gtags/jquery", datadir); snprintf(dist, sizeof(dist), "%s/js", distpath); copydirectory(src, dist); snprintf(src, sizeof(src), "%s/gtags/jquery/images", datadir); snprintf(dist, sizeof(dist), "%s/js/images", distpath); copydirectory(src, dist); } message("[%s] Done.", now()); if (vflag && (fflag || dynamic || auto_completion)) { message("\n[Information]\n"); message(" o Htags was invoked with the -f, -c, -D or --auto-completion option. You should"); message(" start http server so that cgi-bin/*.cgi is executed as a CGI script."); message("\n If you are using Apache, 'HTML/.htaccess' might be helpful for you.\n"); message(" Good luck!\n"); } if (Iflag) { char src[MAXPATHLEN]; char dist[MAXPATHLEN]; snprintf(src, sizeof(src), "%s/gtags/icons", datadir); snprintf(dist, sizeof(dist), "%s/icons", distpath); copydirectory(src, dist); } gpath_close(); /* * Print statistics information. */ print_statistics(statistics); clean(); return 0; }
static int print_directory(int level, char *basedir) { const char *path; FILEOP *fileop = NULL; FILE *op = NULL; int flist_items = 0; int count = 0; if (level > 0) { char name[MAXPATHLEN]; snprintf(name, sizeof(name), "%s/files/%s.%s", distpath, path2fid(basedir), HTML); fileop = open_output_file(name, 0); op = get_descripter(fileop); print_directory_header(op, level, basedir); if (tree_view) { char *target = (Fflag) ? "mains" : "_top"; strbuf_puts(files, dir_begin); strbuf_puts(files, gen_href_begin_with_title_target("files", path2fid(basedir), HTML, NULL, NULL, target)); strbuf_puts(files, full_path ? removedotslash(basedir) : lastpart(basedir)); strbuf_puts(files, gen_href_end()); strbuf_puts_nl(files, dir_title_end); strbuf_puts_nl(files, "<ul>"); } } while ((path = getpath()) != NULL) { const char *p, *local = localpath(path, basedir); /* * Path is outside of basedir. */ if (local == NULL) { ungetpath(); /* read again by upper level print_directory(). */ break; } /* * Path is inside of basedir. */ else { char *slash = strchr(local, '/'); if (table_flist && flist_items++ % flist_fields == 0) PUT(fline_begin); /* * Print directory. */ if (slash) { int baselen = strlen(basedir); char *q, *last = basedir + baselen; int subcount; if (baselen + 1 + (slash - local) > MAXPATHLEN) { fprintf(stderr, "Too long path name.\n"); exit(1); } /* * Append new directory to the basedir. */ p = local; q = last; *q++ = '/'; while (p < slash) *q++ = *p++; *q = '\0'; /* * print tree for this directory. */ ungetpath(); /* read again by lower level print_directory(). */ subcount = print_directory(level + 1, basedir); PUT(print_directory_name(level, basedir, subcount)); count += subcount; /* * Shrink the basedir. */ *last = '\0'; } /* * Print file. */ else { const char *file_name = print_file_name(level, path); if (tree_view) { int size = filesize(path); char *target = (Fflag) ? "mains" : "_top"; char tips[80]; if (size > 1) snprintf(tips, sizeof(tips), "%s bytes", insert_comma(size)); else snprintf(tips, sizeof(tips), "%s byte", insert_comma(size)); strbuf_sprintf(files, "%s%s%s%s%s\n", file_begin, gen_href_begin_with_title_target(SRCS, path2fid(path), HTML, NULL, tips, target), full_path ? removedotslash(path) : lastpart(path), gen_href_end(), file_end); } PUT(file_name); if (filemap_file) fprintf(FILEMAP, "%s\t%s/%s.%s\n", removedotslash(path), SRCS, path2fid(path), HTML); count++; } if (table_flist && flist_items % flist_fields == 0) PUT(fline_end); } } if (flist_items % flist_fields != 0) PUT(fline_end); if (level > 0) { print_directory_footer(op, level, basedir); close_file(fileop); if (tree_view) { strbuf_puts_nl(files, "</ul>"); strbuf_puts_nl(files, dir_end); } } html_count++; return count; }