/* * Make duplicate object index. * * If referred tag is only one, direct link which points the tag is generated. * Else if two or more tag exists, indirect link which points the tag list * is generated. */ int makedupindex(void) { STRBUF *sb = strbuf_open(0); STRBUF *tmp = strbuf_open(0); STRBUF *command = strbuf_open(0); int definition_count = 0; char srcdir[MAXPATHLEN]; int db; FILEOP *fileop = NULL; FILE *op = NULL; FILE *ip = NULL; snprintf(srcdir, sizeof(srcdir), "../%s", SRCS); for (db = GTAGS; db < GTAGLIM; db++) { const char *kind = kinds[db]; const char *option = options[db]; int writing = 0; int count = 0; int entry_count = 0; const char *ctags_xid, *ctags_x; char tag[IDENTLEN], prev[IDENTLEN], first_line[MAXBUFLEN]; if (gtags_exist[db] == 0) continue; prev[0] = 0; first_line[0] = 0; /* * construct command line. */ strbuf_reset(command); strbuf_sprintf(command, "%s -x%s --result=ctags-xid --encode-path=\" \t\" --nofilter=path", quote_shell(global_path), option); /* * Optimization when the --dynamic option is specified. */ if (dynamic) { strbuf_puts(command, " --nosource"); if (db != GSYMS) strbuf_puts(command, " --nofilter=sort"); } strbuf_puts(command, " \".*\""); if ((ip = popen(strbuf_value(command), "r")) == NULL) die("cannot execute command '%s'.", strbuf_value(command)); while ((ctags_xid = strbuf_fgets(sb, ip, STRBUF_NOCRLF)) != NULL) { char fid[MAXFIDLEN]; ctags_x = parse_xid(ctags_xid, fid, NULL); /* tag name */ (void)strcpy_withterm(tag, ctags_x, sizeof(tag), ' '); if (strcmp(prev, tag)) { count++; if (vflag) fprintf(stderr, " [%d] adding %s %s\n", count, kind, tag); if (writing) { if (!dynamic) { fputs_nl(gen_list_end(), op); fputs_nl(body_end, op); fputs_nl(gen_page_end(), op); close_file(fileop); html_count++; } writing = 0; /* * cache record: " <fid>\0<entry number>\0" */ strbuf_reset(tmp); strbuf_putc(tmp, ' '); strbuf_putn(tmp, count - 1); strbuf_putc(tmp, '\0'); strbuf_putn(tmp, entry_count); cache_put(db, prev, strbuf_value(tmp), strbuf_getlen(tmp) + 1); } /* single entry */ if (first_line[0]) { char fid[MAXFIDLEN]; const char *ctags_x = parse_xid(first_line, fid, NULL); const char *lno = nextelement(ctags_x); strbuf_reset(tmp); strbuf_puts_withterm(tmp, lno, ' '); strbuf_putc(tmp, '\0'); strbuf_puts(tmp, fid); cache_put(db, prev, strbuf_value(tmp), strbuf_getlen(tmp) + 1); } /* * Chop the tail of the line. It is not important. * strlimcpy(first_line, ctags_x, sizeof(first_line)); */ strncpy(first_line, ctags_xid, sizeof(first_line)); first_line[sizeof(first_line) - 1] = '\0'; strlimcpy(prev, tag, sizeof(prev)); entry_count = 0; } else { /* duplicate entry */ if (first_line[0]) { char fid[MAXFIDLEN]; const char *ctags_x = parse_xid(first_line, fid, NULL); if (!dynamic) { char path[MAXPATHLEN]; snprintf(path, sizeof(path), "%s/%s/%d.%s", distpath, dirs[db], count, HTML); fileop = open_output_file(path, cflag); op = get_descripter(fileop); fputs_nl(gen_page_begin(tag, SUBDIR), op); fputs_nl(body_begin, op); fputs_nl(gen_list_begin(), op); fputs_nl(gen_list_body(srcdir, ctags_x, fid), op); } writing = 1; entry_count++; first_line[0] = 0; } if (!dynamic) { fputs_nl(gen_list_body(srcdir, ctags_x, fid), op); } entry_count++; } } if (db == GTAGS) definition_count = count; if (pclose(ip) != 0) die("'%s' failed.", strbuf_value(command)); if (writing) { if (!dynamic) { fputs_nl(gen_list_end(), op); fputs_nl(body_end, op); fputs_nl(gen_page_end(), op); close_file(fileop); html_count++; } /* * cache record: " <fid>\0<entry number>\0" */ strbuf_reset(tmp); strbuf_putc(tmp, ' '); strbuf_putn(tmp, count); strbuf_putc(tmp, '\0'); strbuf_putn(tmp, entry_count); cache_put(db, prev, strbuf_value(tmp), strbuf_getlen(tmp) + 1); } if (first_line[0]) { char fid[MAXFIDLEN]; const char *ctags_x = parse_xid(first_line, fid, NULL); const char *lno = nextelement(ctags_x); strbuf_reset(tmp); strbuf_puts_withterm(tmp, lno, ' '); strbuf_putc(tmp, '\0'); strbuf_puts(tmp, fid); cache_put(db, prev, strbuf_value(tmp), strbuf_getlen(tmp) + 1); } } strbuf_close(sb); strbuf_close(tmp); strbuf_close(command); return definition_count; }
/** * anchor_load: load anchor table * * @param[in] path path name */ void anchor_load(const char *path) { int db, current_fid; /* Get fid of the path */ { const char *p = path2fid(path); if (p == NULL) die("anchor_load: internal error. file '%s' not found in GPATH.", path); current_fid = atoi(p); } FIRST = LAST = 0; end = CURRENT = NULL; if (vb == NULL) vb = varray_open(sizeof(struct anchor), 1000); else varray_reset(vb); for (db = GTAGS; db < GTAGLIM; db++) { XARGS *xp; char *ctags_xid; if ((xp = anchor_input[db]) == NULL) continue; /* * Read from input stream until it reaches end of file * or the line of another file appears. */ while ((ctags_xid = xargs_read(xp)) != NULL) { SPLIT ptable; struct anchor *a; int type, fid; const char *ctags_x = parse_xid(ctags_xid, NULL, &fid); /* * It is the following file. */ if (current_fid != fid) { xargs_unread(xp); break; } if (split(ctags_x, 4, &ptable) < 4) { recover(&ptable); die("too small number of parts in anchor_load().\n'%s'", ctags_x); } if (db == GTAGS) { char *p = ptable.part[PART_LINE].start; for (; *p && isspace((unsigned char)*p); p++) ; if (!*p) { recover(&ptable); die("The output of parser is illegal.\n%s", ctags_x); } /* * Function header is applied only to the anchor whoes type is 'D'. * (D: function, M: macro, T: type) */ type = 'T'; if (*p == '#') type = 'M'; else if (locatestring(p, "typedef", MATCH_AT_FIRST)) type = 'T'; else if ((p = locatestring(p, ptable.part[PART_TAG].start, MATCH_FIRST)) != NULL) { /* skip a tag and the following blanks */ p += strlen(ptable.part[PART_TAG].start); for (; *p && isspace((unsigned char)*p); p++) ; if (*p == '(') type = 'D'; } } else if (db == GRTAGS) type = 'R'; else type = 'Y'; /* allocate an entry */ a = varray_append(vb); a->lineno = atoi(ptable.part[PART_LNO].start); a->type = type; a->done = 0; settag(a, ptable.part[PART_TAG].start); recover(&ptable); } if (ctags_xid == NULL) { xargs_close(anchor_input[db]); anchor_input[db] = NULL; } } if (vb->length == 0) { table = NULL; } else { int i, used = vb->length; /* * Sort by lineno. */ table = varray_assign(vb, 0, 0); qsort(table, used, sizeof(struct anchor), cmp); /* * Setup some lineno. */ for (i = 0; i < used; i++) if (table[i].type == 'D') break; if (i < used) FIRST = table[i].lineno; for (i = used - 1; i >= 0; i--) if (table[i].type == 'D') break; if (i >= 0) LAST = table[i].lineno; } /* * Setup loop range. */ start = table; curp = NULL; end = &table[vb->length]; /* anchor_dump(stderr, 0);*/ }
/** * 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 */ }