root/htags/common.c(230.html)

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

DEFINITIONS

This source file includes following definitions.
  1. fputs_nl
  2. setup_xhtml
  3. upperdir
  4. sed
  5. gen_insert_header
  6. gen_insert_footer
  7. gen_page_generic_begin
  8. gen_page_begin
  9. gen_page_frameset_begin
  10. gen_page_end
  11. gen_image
  12. gen_name_number
  13. gen_name_string
  14. gen_href_begin_with_title_target
  15. gen_href_begin_simple
  16. gen_href_begin
  17. gen_href_begin_with_title
  18. gen_href_end
  19. gen_list_begin
  20. gen_list_body
  21. gen_list_end
  22. gen_div_begin
  23. gen_div_end
  24. gen_form_begin
  25. gen_form_end
  26. gen_input
  27. gen_input_radio
  28. gen_input_checkbox
  29. gen_input_with_title_checked
  30. gen_frameset_begin
  31. gen_frameset_end
  32. gen_frame

/*
 * Copyright (c) 2004, 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 <stdio.h> #ifdef STDC_HEADERS #include <stdlib.h> #endif #ifdef HAVE_STRING_H #include <string.h> #else #include <strings.h> #endif #include <ctype.h> #include <sys/types.h> #ifdef HAVE_UNISTD_H #include <unistd.h> #endif #ifdef HAVE_FCNTL_H #include <fcntl.h> #else #include <sys/file.h> #endif #include "global.h" #include "common.h" #include "htags.h" #include "path2url.h" /* * Tag definitions * * Htags generates HTML tag by default. */
const char *html_begin = "<html>"; const char *html_end = "</html>"; const char *html_head_begin = "<head>"; const char *html_head_end = "</head>"; const char *html_title_begin = "<title>"; const char *html_title_end = "</title>"; const char *body_begin = "<body text='#191970' bgcolor='#f5f5dc' vlink='gray'>"; const char *body_end = "</body>"; const char *title_begin = "<h1><font color='#cc0000'>"; const char *title_end = "</font></h1>"; const char *header_begin = "<h2>"; const char *header_end = "</h2>"; const char *cvslink_begin = "<font size='-1'>"; const char *cvslink_end = "</font>"; const char *caution_begin = "<center>\n<blockquote>"; const char *caution_end = "</blockquote>\n</center>"; const char *list_begin = "<ol>"; const char *list_end = "</ol>"; const char *item_begin = "<li>"; const char *item_end = ""; const char *flist_begin = "<table cellpadding='2' width='100%'>"; const char *flist_end = "</table>"; const char *fline_begin = "<tr>"; const char *fline_end = "</tr>"; const char *fitem_begin = "<td nowrap>"; const char *fitem_end = "</td>"; const char *define_list_begin = "<dl>"; const char *define_list_end = "</dl>"; const char *define_term_begin = "<dt>"; const char *define_term_end = ""; const char *define_desc_begin = "<dd>"; const char *define_desc_end = ""; const char *table_begin = "<table>"; const char *table_end = "</table>"; const char *comment_begin = "<i><font color='green'>"; const char *comment_end = "</font></i>"; const char *sharp_begin = "<font color='darkred'>"; const char *sharp_end = "</font>"; const char *brace_begin = "<font color='red'>"; const char *brace_end = "</font>"; const char *verbatim_begin = "<pre>"; const char *verbatim_end = "</pre>"; const char *reserved_begin = "<b>"; const char *reserved_end = "</b>"; const char *position_begin = "<font color='gray'>"; const char *position_end = "</font>"; const char *warned_line_begin = "<span style='background-color:yellow'>"; const char *warned_line_end = "</span>"; const char *error_begin = "<h1><font color='#cc0000'>"; const char *error_end = "</font></h1>"; const char *message_begin = "<h3>"; const char *message_end = "</h3>"; const char *string_begin = "<u>"; const char *string_end = "</u>"; const char *quote_great = "&gt;"; const char *quote_little = "&lt;"; const char *quote_amp = "&amp;"; const char *quote_space = "&nbsp;"; const char *hr = "<hr>"; const char *br = "<br>"; const char *empty_element = ""; const char *noframes_begin = "<noframes>"; const char *noframes_end = "</noframes>"; /* * 1: Enforce XHTML1.0 strict or XHTML1.1. */
static int strict_xhtml = 0; /* * print string and new line. * * This function is a replacement of fprintf(op, "%s\n", s) in htags. */
int fputs_nl(const char *s, FILE *op) { fputs(s, op); putc('\n', op); return 0; } /* * XHTML support. * * If the --xhtml option is specified, htags(1) generates XHTML output. * We define each style for the tags in 'style.css' in this directory. */
void setup_xhtml(void) { if (!strcmp(xhtml_version, "1.1") && !Fflag) strict_xhtml = 1; html_begin = "<html xmlns='http://www.w3.org/1999/xhtml'>"; html_end = "</html>"; html_head_begin = "<head>"; html_head_end = "</head>"; html_title_begin = "<title>"; html_title_end = "</title>"; body_begin = "<body>"; body_end = "</body>"; title_begin = "<h1 class='title'>"; title_end = "</h1>"; header_begin = "<h2 class='header'>"; header_end = "</h2>"; cvslink_begin = "<span class='cvs'>"; cvslink_end = "</span>"; caution_begin = "<div class='caution'>"; caution_end = "</div>"; list_begin = "<ol>"; list_end = "</ol>"; item_begin = "<li>"; item_end = "</li>"; flist_begin = "<table class='flist'>"; flist_end = "</table>"; fline_begin = "<tr class='flist'>"; fline_end = "</tr>"; fitem_begin = "<td class='flist'>"; fitem_end = "</td>"; define_list_begin = "<dl>"; define_list_end = "</dl>"; define_term_begin = "<dt>"; define_term_end = "</dt>"; define_desc_begin = "<dd>"; define_desc_end = "</dd>"; table_begin = "<table>"; table_end = "</table>"; comment_begin = "<em class='comment'>"; comment_end = "</em>"; sharp_begin = "<em class='sharp'>"; sharp_end = "</em>"; brace_begin = "<em class='brace'>"; brace_end = "</em>"; verbatim_begin = "<pre>"; verbatim_end = "</pre>"; reserved_begin = "<strong class='reserved'>"; reserved_end = "</strong>"; position_begin = "<em class='position'>"; position_end = "</em>"; warned_line_begin = "<em class='warned'>"; warned_line_end = "</em>"; error_begin = "<h2 class='error'>"; error_end = "</h2>"; message_begin = "<h3 class='message'>"; message_end = "</h3>"; string_begin = "<em class='string'>"; string_end = "</em>"; quote_great = "&gt;"; quote_little = "&lt;"; quote_amp = "&amp;"; quote_space = "&nbsp;"; hr = "<hr />"; br = "<br />"; empty_element = " /"; noframes_begin = "<noframes>"; noframes_end = "</noframes>"; } /* * Generate upper directory. */
const char * upperdir(const char *dir) { STATIC_STRBUF(sb); strbuf_clear(sb); strbuf_sprintf(sb, "../%s", dir); return strbuf_value(sb); } /* * Load text from file with replacing @PARENT_DIR@ macro. * Macro @PARENT_DIR@ is replaced with the parent directory * of the 'HTML' directory. */
static const char * sed(FILE *ip, int place) { STATIC_STRBUF(sb); const char *parent_dir = (place == SUBDIR) ? "../.." : ".."; int c, start_position = -1; strbuf_clear(sb); while ((c = fgetc(ip)) != EOF) { strbuf_putc(sb, c); if (c == '@') { int curpos = strbuf_getlen(sb); if (start_position == -1) { start_position = curpos - 1; } else { if (!strncmp("@PARENT_DIR@", strbuf_value(sb) + start_position, curpos - start_position)) { strbuf_setlen(sb, start_position); strbuf_puts(sb, parent_dir); start_position = -1; } else { start_position = curpos - 1; } } } else if (!isalpha(c) && c != '_') { if (start_position != -1) start_position = -1; } } return strbuf_value(sb); } /* * Generate custom header. */
const char * gen_insert_header(int place) { static FILE *ip; if (ip != NULL) { rewind(ip); } else { ip = fopen(insert_header, "r"); if (ip == NULL) die("cannot open include header file '%s'.", insert_header); } return sed(ip, place); } /* * Generate custom footer. */
const char * gen_insert_footer(int place) { static FILE *ip; if (ip != NULL) { rewind(ip); } else { ip = fopen(insert_footer, "r"); if (ip == NULL) die("cannot open include footer file '%s'.", insert_footer); } return sed(ip, place); } /* * Generate beginning of generic page * * i) title title of this page * i) place SUBDIR: this page is in sub directory * TOPDIR: this page is in the top directory * i) use_frameset * use frameset document type or not */
static const char * gen_page_generic_begin(const char *title, int place, int use_frameset) { STATIC_STRBUF(sb); const char *dir = (place == SUBDIR) ? "../" : ""; 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); /* Stingll adds */
strbuf_sprintf(sb, "<meta http-equiv='Content-Style-Type' content='text/css'%s charset='UTF-8'>\n", empty_element); if (enable_xhtml) { /* Stingll adds */
/*strbuf_sprintf(sb, "<meta http-equiv='Content-Style-Type' content='text/css'%s>\n", empty_element);*/
strbuf_sprintf(sb, "<meta http-equiv='Content-Style-Type' content='text/css'%s charset='UTF-8'>\n", empty_element); strbuf_sprintf(sb, "<link rel='stylesheet' type='text/css' href='%sstyle.css'%s>\n", dir, empty_element); } strbuf_puts(sb, html_head_end); return strbuf_value(sb); } /* * Generate beginning of normal page * * i) title title of this page * i) place SUBDIR: this page is in sub directory * TOPDIR: this page is in the top directory */
const char * gen_page_begin(const char *title, int place) { return gen_page_generic_begin(title, place, 0); } /* * Generate beginning of frameset page * * i) title title of this page */
const char * gen_page_frameset_begin(const char *title) { return gen_page_generic_begin(title, TOPDIR, 1); } /* * Generate end of page */
const char * gen_page_end(void) { return html_end; } /* * Generate image tag. * * i) where Where is the icon directory? * CURRENT: current directory * PARENT: parent directory * i) file icon file without suffix. * i) alt alt string */
const char * gen_image(int where, const char *file, const char *alt) { STATIC_STRBUF(sb); const char *dir = (where == PARENT) ? "../icons" : "icons"; strbuf_clear(sb); if (enable_xhtml) strbuf_sprintf(sb, "<img class='icon' src='%s/%s.%s' alt='[%s]'%s>", dir, file, icon_suffix, alt, empty_element); else strbuf_sprintf(sb, "<img src='%s/%s.%s' alt='[%s]' %s%s>", dir, file, icon_suffix, alt, icon_spec, empty_element); return strbuf_value(sb); } /* * Generate name tag. */
const char * gen_name_number(int number) { static char buf[32]; snprintf(buf, sizeof(buf), "L%d", number); return gen_name_string(buf); } /* * Generate name tag. */
const char * gen_name_string(const char *name) { STATIC_STRBUF(sb); strbuf_clear(sb); if (enable_xhtml) { /* * Since some browser cannot understand "<a id='xxx' />", * we put both of 'id=' and 'name=' as long as XHTML1.1 * is not required. XHTML1.1 prohibit 'name='. */
if (strict_xhtml) strbuf_sprintf(sb, "<a id='%s' />", name); else strbuf_sprintf(sb, "<a id='%s' name='%s' />", name, name); } else { strbuf_sprintf(sb, "<a name='%s'>", name); } return strbuf_value(sb); } /* * Generate anchor begin tag. * (complete format) * * i) dir directory * i) file file * i) suffix suffix * i) key key * i) title title='xxx' * i) target target='xxx' * r) generated anchor tag */
const char * gen_href_begin_with_title_target(const char *dir, const char *file, const char *suffix, const char *key, const char *title, const char *target) { STATIC_STRBUF(sb); strbuf_clear(sb); /* * Construct URL. * href='dir/file.suffix#key' */
strbuf_puts(sb, "<a href='"); if (file) { if (dir) { strbuf_puts(sb, dir); strbuf_putc(sb, '/'); } strbuf_puts(sb, file); if (suffix) { strbuf_putc(sb, '.'); strbuf_puts(sb, suffix); } } if (key) { strbuf_putc(sb, '#'); /* * If the key starts with a digit, it assumed line number. * XHTML 1.1 profibits number as an anchor. */
if (isdigit(*key)) strbuf_putc(sb, 'L'); strbuf_puts(sb, key); } strbuf_putc(sb, '\''); if (target) strbuf_sprintf(sb, " target='%s'", target); if (title) strbuf_sprintf(sb, " title='%s'", title); strbuf_putc(sb, '>'); return strbuf_value(sb); } /* * Generate simple anchor begin tag. */
const char * gen_href_begin_simple(const char *file) { return gen_href_begin_with_title_target(NULL, file, NULL, NULL, NULL, NULL); } /* * Generate anchor begin tag without title and target. */
const char * gen_href_begin(const char *dir, const char *file, const char *suffix, const char *key) { return gen_href_begin_with_title_target(dir, file, suffix, key, NULL, NULL); } /* * Generate anchor begin tag without target. */
const char * gen_href_begin_with_title(const char *dir, const char *file, const char *suffix, const char *key, const char *title) { return gen_href_begin_with_title_target(dir, file, suffix, key, title, NULL); } /* * Generate anchor end tag. */
const char * gen_href_end(void) { return "</a>"; } /* * Generate list begin tag. */
const char * gen_list_begin(void) { STATIC_STRBUF(sb); if (strbuf_empty(sb)) { strbuf_clear(sb); if (table_list) { if (enable_xhtml) { strbuf_sprintf(sb, "%s\n%s%s%s%s", table_begin, "<tr><th class='tag'>tag</th>", "<th class='line'>line</th>", "<th class='file'>file</th>", "<th class='code'>source code</th></tr>"); } else { strbuf_sprintf(sb, "%s\n%s%s%s%s", table_begin, "<tr><th nowrap align='left'>tag</th>", "<th nowrap align='right'>line</th>", "<th nowrap align='center'>file</th>", "<th nowrap align='left'>source code</th></tr>"); } } else { strbuf_puts(sb, verbatim_begin); } } return strbuf_value(sb); } /* * Generate list body. * * s must be choped. */
const char * gen_list_body(const char *srcdir, const char *ctags_x) /* virtually const */
{ STATIC_STRBUF(sb); const char *p, *filename, *fid; SPLIT ptable; strbuf_clear(sb); if (split((char *)ctags_x, 4, &ptable) < 4) { recover(&ptable); die("too small number of parts in list_body().\n'%s'", ctags_x); } filename = ptable.part[PART_PATH].start + 2; /* remove './' */
fid = path2fid(filename); if (table_list) { if (enable_xhtml) { strbuf_puts(sb, "<tr><td class='tag'>"); strbuf_puts(sb, gen_href_begin(srcdir, fid, HTML, ptable.part[PART_LNO].start)); strbuf_puts(sb, ptable.part[PART_TAG].start); strbuf_puts(sb, gen_href_end()); strbuf_sprintf(sb, "</td><td class='line'>%s</td><td class='file'>%s</td><td class='code'>", ptable.part[PART_LNO].start, filename); } else { strbuf_puts(sb, "<tr><td nowrap>"); strbuf_puts(sb, gen_href_begin(srcdir, fid, HTML, ptable.part[PART_LNO].start)); strbuf_puts(sb, ptable.part[PART_TAG].start); strbuf_puts(sb, gen_href_end()); strbuf_sprintf(sb, "</td><td nowrap align='right'>%s</td><td nowrap align='left'>%s</td><td nowrap>", ptable.part[PART_LNO].start, filename); } for (p = ptable.part[PART_LINE].start; *p; p++) { unsigned char c = *p; if (c == '&') strbuf_puts(sb, quote_amp); else if (c == '<') strbuf_puts(sb, quote_little); else if (c == '>') strbuf_puts(sb, quote_great); else if (c == ' ') strbuf_puts(sb, quote_space); else if (c == '\t') { strbuf_puts(sb, quote_space); strbuf_puts(sb, quote_space); } else strbuf_putc(sb, c); } strbuf_puts(sb, "</td></tr>"); recover(&ptable); } else { int done = 0; strbuf_puts(sb, gen_href_begin(srcdir, fid, HTML, ptable.part[PART_LNO].start)); strbuf_puts(sb, ptable.part[PART_TAG].start); strbuf_puts(sb, gen_href_end()); p = ctags_x + strlen(ptable.part[PART_TAG].start); recover(&ptable); for (; *p; p++) { unsigned char c = *p; /* ignore "./" in path name */
if (!done && c == '.' && *(p + 1) == '/') { p++; done = 1; } else if (c == '&') strbuf_puts(sb, quote_amp); else if (c == '<') strbuf_puts(sb, quote_little); else if (c == '>') strbuf_puts(sb, quote_great); else strbuf_putc(sb, c); } } return strbuf_value(sb); } /* * Generate list end tag. */
const char * gen_list_end(void) { return table_list ? table_end : verbatim_end; } /* * Generate div begin tag. * * i) align right,left,center */
const char * gen_div_begin(const char *align) { STATIC_STRBUF(sb); if (strbuf_empty(sb)) { strbuf_clear(sb); if (align) { /* * In XHTML, alignment is defined in the file 'style.css'. */
if (enable_xhtml) strbuf_sprintf(sb, "<div class='%s'>", align); else strbuf_sprintf(sb, "<div align='%s'>", align); } else { strbuf_puts(sb, "<div>"); } } return strbuf_value(sb); } /* * Generate div end tag. */
const char * gen_div_end(void) { return "</div>"; } /* * Generate beginning of form * * i) target target */
const char * gen_form_begin(const char *target) { STATIC_STRBUF(sb); strbuf_clear(sb); strbuf_sprintf(sb, "<form method='get' action='%s'", action); if (target) strbuf_sprintf(sb, " target='%s'", target); strbuf_puts(sb, ">"); return strbuf_value(sb); } /* * Generate end of form */
const char * gen_form_end(void) { return "</form>"; } /* * Generate input tag */
const char * gen_input(const char *name, const char *value, const char *type) { return gen_input_with_title_checked(name, value, type, 0, NULL); } /* * Generate input radiobox tag */
const char * gen_input_radio(const char *name, const char *value, int checked, const char *title) { return gen_input_with_title_checked(name, value, "radio", checked, title); } /* * Generate input checkbox tag */
const char * gen_input_checkbox(const char *name, const char *value, const char *title) { return gen_input_with_title_checked(name, value, "checkbox", 0, title); } /* * Generate input radio tag */
const char * gen_input_with_title_checked(const char *name, const char *value, const char *type, int checked, const char *title) { STATIC_STRBUF(sb); strbuf_clear(sb); strbuf_puts(sb, "<input"); if (type) strbuf_sprintf(sb, " type='%s'", type); if (name) strbuf_sprintf(sb, " name='%s'", name); if (value) strbuf_sprintf(sb, " value='%s'", value); if (checked) { if (enable_xhtml) strbuf_puts(sb, " checked='checked'"); else strbuf_puts(sb, " checked"); } if (title) strbuf_sprintf(sb, " title='%s'", title); strbuf_sprintf(sb, "%s>", empty_element); return strbuf_value(sb); } /* * Generate beginning of frameset * * i) target target */
const char * gen_frameset_begin(const char *contents) { STATIC_STRBUF(sb); strbuf_clear(sb); strbuf_sprintf(sb, "<frameset %s>", contents); return strbuf_value(sb); } /* * Generate end of frameset */
const char * gen_frameset_end(void) { return "</frameset>"; } /* * Generate beginning of frame * * i) target target */
const char * gen_frame(const char *name, const char *src) { STATIC_STRBUF(sb); strbuf_clear(sb); strbuf_sprintf(sb, "<frame name='%s' id='%s' src='%s'%s>", name, name, src, empty_element); return strbuf_value(sb); }

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