root/htags/src2html.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_lang_entry
  2. echoc
  3. echos
  4. HTML_quoting
  5. fill_anchor
  6. link_format
  7. fixed_guide_link_format
  8. generate_guide
  9. tooltip
  10. put_anchor
  11. put_anchor_force
  12. put_include_anchor
  13. put_include_anchor_direct
  14. put_reserved_word
  15. put_macro
  16. unknown_preprocessing_directive
  17. unexpected_eof
  18. unknown_yacc_directive
  19. missing_left
  20. put_char
  21. put_string
  22. put_brace
  23. put_begin_of_line
  24. put_end_of_line
  25. encode
  26. get_cvs_module
  27. src2html

   1 /*
   2  * Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
   3  *              2006, 2008, 2010, 2011
   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 
  22 #ifdef HAVE_CONFIG_H
  23 #include <config.h>
  24 #endif
  25 #include <stdio.h>
  26 #ifdef STDC_HEADERS
  27 #include <stdlib.h>
  28 #endif
  29 #include <ctype.h>
  30 
  31 #include "global.h"
  32 #include "anchor.h"
  33 #include "cache.h"
  34 #include "common.h"
  35 #include "incop.h"
  36 #include "path2url.h"
  37 #include "htags.h"
  38 
  39 /*----------------------------------------------------------------------*/
  40 /* Parser switch                                                        */
  41 /*----------------------------------------------------------------------*/
  42 /**
  43  * @details
  44  * This is the linkage section of each parsers. <br>
  45  * If you want to support new language, you must define two procedures: <br>
  46  *      -# Initializing procedure (#init_proc).
  47  *              Called once first with an input file descripter.
  48  *      -# Executing procedure (#exec_proc).
  49  *              Called repeatedly until returning @NAME{EOF}. <br>
  50  *              It should read from above descripter and write @NAME{HTML}
  51  *              using output procedures in this module.
  52  */
  53 struct lang_entry {
  54         const char *lang_name;
  55         void (*init_proc)(FILE *);              /**< initializing procedure */
  56         int (*exec_proc)(void);                 /**< executing procedure */
  57 };
  58 
  59 /**
  60  * @name initializing procedures
  61  * For lang_entry::init_proc
  62  */
  63 /** @{ */
  64 void c_parser_init(FILE *);
  65 void yacc_parser_init(FILE *);
  66 void cpp_parser_init(FILE *);
  67 void java_parser_init(FILE *);
  68 void php_parser_init(FILE *);
  69 void asm_parser_init(FILE *);
  70 /** @} */
  71 
  72 /**
  73  * @name executing procedures
  74  * For lang_entry::exec_proc
  75  */
  76 /** @{ */
  77 int c_lex(void);
  78 int cpp_lex(void);
  79 int java_lex(void);
  80 int php_lex(void);
  81 int asm_lex(void);
  82 /** @} */
  83 
  84 /**
  85  * The first entry is default language.
  86  */
  87 struct lang_entry lang_switch[] = {
  88         /* lang_name    init_proc               exec_proc */
  89         {"c",           c_parser_init,          c_lex},         /* DEFAULT */
  90         {"yacc",        yacc_parser_init,       c_lex},
  91         {"cpp",         cpp_parser_init,        cpp_lex},
  92         {"java",        java_parser_init,       java_lex},
  93         {"php",         php_parser_init,        php_lex},
  94         {"asm",         asm_parser_init,        asm_lex}
  95 };
  96 #define DEFAULT_ENTRY &lang_switch[0]
  97 
  98 /**
  99  * get language entry.
 100  *
 101  * If the specified language (@a lang) is not found, it assumes the
 102  * default language, which is @NAME{C}.
 103  *
 104  *      @param[in]      lang    language name (@VAR{NULL} means 'not specified'.)
 105  *      @return         language entry
 106  */
 107 static struct lang_entry *
 108 get_lang_entry(const char *lang)
 109 {
 110         int i, size = sizeof(lang_switch) / sizeof(struct lang_entry);
 111 
 112         /*
 113          * if language not specified, it assumes default language.
 114          */
 115         if (lang == NULL)
 116                 return DEFAULT_ENTRY;
 117         for (i = 0; i < size; i++)
 118                 if (!strcmp(lang, lang_switch[i].lang_name))
 119                         return &lang_switch[i];
 120         /*
 121          * if specified language not found, it assumes default language.
 122          */
 123         return DEFAULT_ENTRY;
 124 }
 125 /*----------------------------------------------------------------------*/
 126 /* Input/Output                                                         */
 127 /*----------------------------------------------------------------------*/
 128 /*
 129  * Input/Output descriptor.
 130  */
 131 static FILEOP *fileop_out;
 132 static FILEOP *fileop_in;
 133 static FILE *out;
 134 static FILE *in;
 135 
 136 STATIC_STRBUF(outbuf);
 137 static const char *curpfile;
 138 static int warned;
 139 static int last_lineno;
 140 
 141 /**
 142  * Put a character to HTML as is.
 143  *
 144  * @note You should use this function to put a control character. <br>
 145  *
 146  * @attention
 147  * No escaping of @CODE{'\<'}, @CODE{'\>'} and @CODE{'\&'} is performed.
 148  *
 149  * @see put_char()
 150  */
 151 void
 152 echoc(int c)
 153 {
 154         strbuf_putc(outbuf, c);
 155 }
 156 /**
 157  * Put a string to HTML as is.
 158  *
 159  * @note You should use this function to put a control sequence.
 160  *
 161  * @attention
 162  * No escaping of @CODE{'\<'}, @CODE{'\>'} and @CODE{'\&'} is performed.
 163  *
 164  * @see put_string()
 165  */
 166 void
 167 echos(const char *s)
 168 {
 169         strbuf_puts(outbuf, s);
 170 }
 171 /*----------------------------------------------------------------------*/
 172 /* HTML output                                                          */
 173 /*----------------------------------------------------------------------*/
 174 /**
 175  * Quote character with HTML's way.
 176  *
 177  * (Fixes @CODE{'\<'}, @CODE{'\>'} and @CODE{'\&'} for HTML).
 178  */
 179 static const char *
 180 HTML_quoting(int c)
 181 {
 182         if (c == '<')
 183                 return quote_little;
 184         else if (c == '>')
 185                 return quote_great;
 186         else if (c == '&')
 187                 return quote_amp;
 188         return NULL;
 189 }
 190 /**
 191  * fill_anchor: fill anchor into file name
 192  *
 193  *       @param[in]      root   \$root or index page
 194  *       @param[in]      path   \$path name
 195  *       @return              hypertext file name string
 196  */
 197 const char *
 198 fill_anchor(const char *root, const char *path)
 199 {
 200         STATIC_STRBUF(sb);
 201         char buf[MAXBUFLEN], *limit, *p;
 202 
 203         strbuf_clear(sb);
 204         strlimcpy(buf, path, sizeof(buf));
 205         for (p = buf; *p; p++)
 206                 if (*p == sep)
 207                         *p = '\0';
 208         limit = p;
 209 
 210         if (root != NULL)
 211                 strbuf_sprintf(sb, "%sroot%s/", gen_href_begin_simple(root), gen_href_end());
 212         for (p = buf; p < limit; p += strlen(p) + 1) {
 213                 const char *path = buf;
 214                 const char *unit = p;
 215                 const char *next = p + strlen(p) + 1;
 216 
 217                 if (next > limit) {
 218                         strbuf_puts(sb, unit);
 219                         break;
 220                 }
 221                 if (p > buf)
 222                         *(p - 1) = sep;
 223                 strbuf_puts(sb, gen_href_begin("../files", path2fid(path), HTML, NULL));
 224                 strbuf_puts(sb, unit);
 225                 strbuf_puts(sb, gen_href_end());
 226                 strbuf_putc(sb, '/');
 227         }
 228         return strbuf_value(sb);
 229 }
 230 
 231 /**
 232  * link_format: make hypertext from anchor array.
 233  *
 234  *      @param[in]      ref     (previous, next, first, last, top, bottom) <br>
 235  *              -1: top, -2: bottom, other: line number
 236  *      @return HTML
 237  */
 238 const char *
 239 link_format(int ref[A_SIZE])
 240 {
 241         STATIC_STRBUF(sb);
 242         const char **label = Iflag ? anchor_comment : anchor_label;
 243         const char **icons = anchor_icons;
 244         int i;
 245 
 246         strbuf_clear(sb);
 247         for (i = 0; i < A_LIMIT; i++) {
 248                 if (i == A_INDEX) {
 249                         strbuf_puts(sb, gen_href_begin("..", "mains", normal_suffix, NULL));
 250                 } else if (i == A_HELP) {
 251                         strbuf_puts(sb, gen_href_begin("..", "help", normal_suffix, NULL));
 252                 } else if (ref[i]) {
 253                         char tmp[32], *key = tmp;
 254 
 255                         if (ref[i] == -1)
 256                                 key = "TOP";
 257                         else if (ref[i] == -2)
 258                                 key = "BOTTOM";
 259                         else
 260                                 snprintf(tmp, sizeof(tmp), "%d", ref[i]);
 261                         strbuf_puts(sb, gen_href_begin(NULL, NULL, NULL, key));
 262                 }
 263                 if (Iflag) {
 264                         char tmp[MAXPATHLEN];
 265                         snprintf(tmp, sizeof(tmp), "%s%s", (i != A_INDEX && i != A_HELP && ref[i] == 0) ? "n_" : "", icons[i]);
 266                         strbuf_puts(sb, gen_image(PARENT, tmp, label[i]));
 267                 } else {
 268                         strbuf_sprintf(sb, "[%s]", label[i]);
 269                 }
 270                 if (i == A_INDEX || i == A_HELP || ref[i] != 0)
 271                         strbuf_puts(sb, gen_href_end());
 272         }
 273         return strbuf_value(sb);
 274 }
 275 /**
 276  * fixed_guide_link_format: make fixed guide
 277  *
 278  *      @param[in]      ref     (previous, next, first, last, top, bottom) <br>
 279  *              -1: top, -2: bottom, other: line number
 280  *      @param[in]      anchors
 281  *      @return HTML
 282  */
 283 const char *
 284 fixed_guide_link_format(int ref[A_LIMIT], const char *anchors)
 285 {
 286         int i = 0;
 287         STATIC_STRBUF(sb);
 288 
 289         strbuf_clear(sb);
 290         strbuf_puts(sb, "<!-- beginning of fixed guide -->\n");
 291         strbuf_puts(sb, guide_begin);
 292         strbuf_putc(sb, '\n');
 293         for (i = 0; i < A_LIMIT; i++) {
 294                 if (i == A_PREV || i == A_NEXT)
 295                         continue;
 296                 strbuf_puts(sb, guide_unit_begin);
 297                 switch (i) {
 298                 case A_FIRST:
 299                 case A_LAST:
 300                         if (ref[i] == 0)
 301                                 strbuf_puts(sb, gen_href_begin(NULL, NULL, NULL, (i == A_FIRST) ? "TOP" : "BOTTOM"));
 302                         else {
 303                                 char lineno[32];
 304                                 snprintf(lineno, sizeof(lineno), "%d", ref[i]);
 305                                 strbuf_puts(sb, gen_href_begin(NULL, NULL, NULL, lineno));
 306                         }
 307                         break;
 308                 case A_TOP:
 309                         strbuf_puts(sb, gen_href_begin(NULL, NULL, NULL, "TOP"));
 310                         break;
 311                 case A_BOTTOM:
 312                         strbuf_puts(sb, gen_href_begin(NULL, NULL, NULL, "BOTTOM"));
 313                         break;
 314                 case A_INDEX:
 315                         strbuf_puts(sb, gen_href_begin("..", "mains", normal_suffix, NULL));
 316                         break;
 317                 case A_HELP:
 318                         strbuf_puts(sb, gen_href_begin("..", "help", normal_suffix, NULL));
 319                         break;
 320                 default:
 321                         die("fixed_guide_link_format: something is wrong.(%d)", i);
 322                         break;
 323                 }
 324                 if (Iflag)
 325                         strbuf_puts(sb, gen_image(PARENT, anchor_icons[i], anchor_label[i]));
 326                 else
 327                         strbuf_sprintf(sb, "[%s]", anchor_label[i]);
 328                 strbuf_puts(sb, gen_href_end());
 329                 strbuf_puts(sb, guide_unit_end);
 330                 strbuf_putc(sb, '\n');
 331         }
 332         strbuf_puts(sb, guide_path_begin);
 333         strbuf_puts(sb, anchors);
 334         strbuf_puts(sb, guide_path_end);
 335         strbuf_putc(sb, '\n');
 336         strbuf_puts(sb, guide_end);
 337         strbuf_putc(sb, '\n');
 338         strbuf_puts(sb, "<!-- end of fixed guide -->\n");
 339 
 340         return strbuf_value(sb);
 341 }
 342 /**
 343  * generate_guide: generate guide string for definition line.
 344  *
 345  *      @param[in]      lineno  line number
 346  *      @return         guide string
 347  */
 348 const char *
 349 generate_guide(int lineno)
 350 {
 351         STATIC_STRBUF(sb);
 352         int i = 0;
 353 
 354         strbuf_clear(sb);
 355         if (definition_header == RIGHT_HEADER)
 356                 i = 4;
 357         else if (nflag)
 358                 i = ncol + 1;
 359         if (i > 0)
 360                 for (; i > 0; i--)
 361                         strbuf_putc(sb, ' ');
 362         strbuf_sprintf(sb, "%s/* ", comment_begin);
 363         strbuf_puts(sb, link_format(anchor_getlinks(lineno)));
 364         if (show_position)
 365                 strbuf_sprintf(sb, "%s%s[+%d %s]%s",
 366                         quote_space, position_begin, lineno, curpfile, position_end);
 367         strbuf_sprintf(sb, " */%s", comment_end);
 368 
 369         return strbuf_value(sb);
 370 }
 371 /**
 372  * tooltip: generate tooltip string
 373  *
 374  *      @param[in]      type    @CODE{'I'}: 'Included from' <br>
 375  *                      @CODE{'R'}: 'Defined at' <br>
 376  *                      @CODE{'Y'}: 'Used at' <br>
 377  *                      @CODE{'D'}, @CODE{'M'}: 'Referred from'
 378  *      @param[in]      lno     line number
 379  *      @param[in]      opt     
 380  *      @return         tooltip string
 381  */
 382 const char *
 383 tooltip(int type, int lno, const char *opt)
 384 {
 385         STATIC_STRBUF(sb);
 386 
 387         strbuf_clear(sb);
 388         if (lno > 0) {
 389                 if (type == 'I')
 390                         strbuf_puts(sb, "Included from");
 391                 else if (type == 'R')
 392                         strbuf_puts(sb, "Defined at");
 393                 else if (type == 'Y')
 394                         strbuf_puts(sb, "Used at");
 395                 else
 396                         strbuf_puts(sb, "Referred from");
 397                 strbuf_putc(sb, ' ');
 398                 strbuf_putn(sb, lno);
 399                 if (opt) {
 400                         strbuf_puts(sb, " in ");
 401                         strbuf_puts(sb, opt);
 402                 }
 403         } else {
 404                 strbuf_puts(sb, "Multiple ");
 405                 if (type == 'I')
 406                         strbuf_puts(sb, "included from");
 407                 else if (type == 'R')
 408                         strbuf_puts(sb, "defined in");
 409                 else if (type == 'Y')
 410                         strbuf_puts(sb, "used in");
 411                 else
 412                         strbuf_puts(sb, "referred from");
 413                 strbuf_putc(sb, ' ');
 414                 strbuf_puts(sb, opt);
 415                 strbuf_putc(sb, ' ');
 416                 strbuf_puts(sb, "places");
 417         }
 418         strbuf_putc(sb, '.');
 419         return strbuf_value(sb);
 420 }
 421 /**
 422  * put_anchor: output HTML anchor.
 423  *
 424  *      @param[in]      name    tag
 425  *      @param[in]      type    tag type. @CODE{'R'}: @NAME{GTAGS} <br>
 426  *                      @CODE{'Y'}: @NAME{GSYMS} <br>
 427  *                      @CODE{'D'}, @CODE{'M'}, @CODE{'T'}: @NAME{GRTAGS}
 428  *      @param[in]      lineno  current line no
 429  */
 430 void
 431 put_anchor(char *name, int type, int lineno)
 432 {
 433         const char *line;
 434         int db;
 435 
 436         if (type == 'R')
 437                 db = GTAGS;
 438         else if (type == 'Y')
 439                 db = GSYMS;
 440         else    /* 'D', 'M' or 'T' */
 441                 db = GRTAGS;
 442         line = cache_get(db, name);
 443         if (line == NULL) {
 444                 if ((type == 'R' || type == 'Y') && wflag) {
 445                         warning("%s %d %s(%c) found but not defined.",
 446                                 curpfile, lineno, name, type);
 447                         if (colorize_warned_line)
 448                                 warned = 1;
 449                 }
 450                 strbuf_puts(outbuf, name);
 451         } else {
 452                 /*
 453                  * About the format of 'line', please see the head comment of cache.c.
 454                  */
 455                 if (*line == ' ') {
 456                         const char *fid = line + 1;
 457                         const char *count = nextstring(fid);
 458                         const char *dir, *file, *suffix = NULL;
 459 
 460                         if (dynamic) {
 461                                 STATIC_STRBUF(sb);
 462 
 463                                 strbuf_clear(sb);
 464                                 strbuf_puts(sb, action);
 465                                 strbuf_putc(sb, '?');
 466                                 strbuf_puts(sb, "pattern=");
 467                                 strbuf_puts(sb, name);
 468                                 strbuf_puts(sb, quote_amp);
 469                                 if (Sflag) {
 470                                         strbuf_puts(sb, "id=");
 471                                         strbuf_puts(sb, sitekey);
 472                                         strbuf_puts(sb, quote_amp);
 473                                 }
 474                                 strbuf_puts(sb, "type=");
 475                                 if (db == GTAGS)
 476                                         strbuf_puts(sb, "definitions");
 477                                 else if (db == GRTAGS)
 478                                         strbuf_puts(sb, "reference");
 479                                 else
 480                                         strbuf_puts(sb, "symbol");
 481                                 file = strbuf_value(sb);
 482                                 dir = (*action == '/') ? NULL : "..";
 483                         } else {
 484                                 if (type == 'R')
 485                                         dir = upperdir(DEFS);
 486                                 else if (type == 'Y')
 487                                         dir = upperdir(SYMS);
 488                                 else    /* 'D', 'M' or 'T' */
 489                                         dir = upperdir(REFS);
 490                                 file = fid;
 491                                 suffix = HTML;
 492                         }
 493                         strbuf_puts(outbuf, gen_href_begin_with_title(dir, file, suffix, NULL, tooltip(type, -1, count)));
 494                         strbuf_puts(outbuf, name);
 495                         strbuf_puts(outbuf, gen_href_end());
 496                 } else {
 497                         const char *lno = line;
 498                         const char *fid = nextstring(line);
 499                         const char *path = gpath_fid2path(fid, NULL);
 500 
 501                         path += 2;              /* remove './' */
 502                         /*
 503                          * Don't make a link which refers to itself.
 504                          * Being used only once means that it is a self link.
 505                          */
 506                         if (db == GSYMS) {
 507                                 strbuf_puts(outbuf, name);
 508                                 return;
 509                         }
 510                         strbuf_puts(outbuf, gen_href_begin_with_title(upperdir(SRCS), fid, HTML, lno, tooltip(type, atoi(lno), path)));
 511                         strbuf_puts(outbuf, name);
 512                         strbuf_puts(outbuf, gen_href_end());
 513                 }
 514         }
 515 }
 516 /**
 517  * put_anchor_force: output HTML anchor without warning.
 518  *
 519  *      @param[in]      name    tag
 520  *      @param[in]      length
 521  *      @param[in]      lineno  current line no
 522  *
 523  * @remark The tag type is fixed at 'R' (@NAME{GTAGS})
 524  */
 525 void
 526 put_anchor_force(char *name, int length, int lineno)
 527 {
 528         STATIC_STRBUF(sb);
 529         int saveflag = wflag;
 530 
 531         strbuf_clear(sb);
 532         strbuf_nputs(sb, name, length);
 533         wflag = 0;
 534         put_anchor(strbuf_value(sb), 'R', lineno);
 535         wflag = saveflag;
 536 }
 537 /**
 538  * put_include_anchor: output HTML anchor.
 539  *
 540  *      @param[in]      inc     inc structure
 541  *      @param[in]      path    path name for display
 542  */
 543 void
 544 put_include_anchor(struct data *inc, const char *path)
 545 {
 546         if (inc->count == 1)
 547                 strbuf_puts(outbuf, gen_href_begin(NULL, path2fid(strbuf_value(inc->contents)), HTML, NULL));
 548         else {
 549                 char id[32];
 550                 snprintf(id, sizeof(id), "%d", inc->id);
 551                 strbuf_puts(outbuf, gen_href_begin(upperdir(INCS), id, HTML, NULL));
 552         }
 553         strbuf_puts(outbuf, path);
 554         strbuf_puts(outbuf, gen_href_end());
 555 }
 556 /**
 557  * put_include_anchor_direct: output HTML anchor.
 558  *
 559  *      @param[in]      file    normalized path
 560  *      @param[in]      path    path name for display
 561  */
 562 void
 563 put_include_anchor_direct(const char *file, const char *path)
 564 {
 565         strbuf_puts(outbuf, gen_href_begin(NULL, path2fid(file), HTML, NULL));
 566         strbuf_puts(outbuf, path);
 567         strbuf_puts(outbuf, gen_href_end());
 568 }
 569 /**
 570  * Put a reserved word (@CODE{if}, @CODE{while}, ...)
 571  */
 572 void
 573 put_reserved_word(const char *word)
 574 {
 575         strbuf_puts(outbuf, reserved_begin);
 576         strbuf_puts(outbuf, word);
 577         strbuf_puts(outbuf, reserved_end);
 578 }
 579 /**
 580  * Put a macro (@CODE{\#define}, @CODE{\#undef}, ...) 
 581  */
 582 void
 583 put_macro(const char *word)
 584 {
 585         strbuf_puts(outbuf, sharp_begin);
 586         strbuf_puts(outbuf, word);
 587         strbuf_puts(outbuf, sharp_end);
 588 }
 589 /**
 590  * Print warning message when unknown preprocessing directive is found.
 591  */
 592 void
 593 unknown_preprocessing_directive(const char *word, int lineno)
 594 {
 595         word = strtrim(word, TRIM_ALL, NULL);
 596         warning("unknown preprocessing directive '%s'. [+%d %s]", word, lineno, curpfile);
 597         if (colorize_warned_line)
 598                 warned = 1;
 599 }
 600 /**
 601  * Print warning message when unexpected eof.
 602  */
 603 void
 604 unexpected_eof(int lineno)
 605 {
 606         warning("unexpected eof. [+%d %s]", lineno, curpfile);
 607         if (colorize_warned_line)
 608                 warned = 1;
 609 }
 610 /**
 611  * Print warning message when unknown @NAME{yacc} directive is found.
 612  */
 613 void
 614 unknown_yacc_directive(const char *word, int lineno)
 615 {
 616         warning("unknown yacc directive '%s'. [+%d %s]", word, lineno, curpfile);
 617         if (colorize_warned_line)
 618                 warned = 1;
 619 }
 620 /**
 621  * Print warning message when unmatched brace is found.
 622  */
 623 void
 624 missing_left(const char *word, int lineno)
 625 {
 626         warning("missing left '%s'. [+%d %s]", word, lineno, curpfile);
 627         if (colorize_warned_line)
 628                 warned = 1;
 629 }
 630 /**
 631  * Put a character with HTML quoting.
 632  *
 633  * @note If you want to put @CODE{'\<'}, @CODE{'\>'} or @CODE{'\&'}, you
 634  *              should echoc() instead, as this function escapes (fixes) those
 635  *              characters for HTML.
 636  */
 637 void
 638 put_char(int c)
 639 {
 640         const char *quoted = HTML_quoting(c);
 641 
 642         if (quoted)
 643                 strbuf_puts(outbuf, quoted);
 644         else
 645                 strbuf_putc(outbuf, c);
 646 }
 647 /**
 648  * Put a string with HTML quoting.
 649  *
 650  * @note If you want to put HTML tag itself, you should echos() instead,
 651  *              as this function escapes (fixes) the characters @CODE{'\<'},
 652  *              @CODE{'\>'} and @CODE{'\&'} for HTML.
 653  */
 654 void
 655 put_string(const char *s)
 656 {
 657         for (; *s; s++)
 658                 put_char(*s);
 659 }
 660 /**
 661  * Put brace (@c '{', @c '}')
 662  */
 663 void
 664 put_brace(const char *text)
 665 {
 666         strbuf_puts(outbuf, brace_begin);
 667         strbuf_puts(outbuf, text);
 668         strbuf_puts(outbuf, brace_end);
 669 }
 670 
 671 /**
 672  * @name common procedure for line control.
 673  */
 674 /** @{ */
 675 static char lineno_format[32];
 676 static const char *guide = NULL;
 677 /** @} */
 678 
 679 /**
 680  * Begin of line processing.
 681  */
 682 void
 683 put_begin_of_line(int lineno)
 684 {
 685         if (definition_header != NO_HEADER) {
 686                 if (define_line(lineno))
 687                         guide = generate_guide(lineno);
 688                 else
 689                         guide = NULL;
 690         }
 691         if (guide && definition_header == BEFORE_HEADER) {
 692                 fputs_nl(guide, out);
 693                 guide = NULL;
 694         }
 695 }
 696 /**
 697  * End of line processing.
 698  *
 699  *      @param[in]      lineno  current line number
 700  *      @par Globals used (input):
 701  *              @NAME{outbuf}, HTML line image
 702  *
 703  * The @EMPH{outbuf} (string buffer) has HTML image of the line. <br>
 704  * This function flush and clear it.
 705  */
 706 void
 707 put_end_of_line(int lineno)
 708 {
 709         fputs(gen_name_number(lineno), out);
 710         if (nflag)
 711                 fprintf(out, lineno_format, lineno);
 712         if (warned)
 713                 fputs(warned_line_begin, out);
 714 
 715         /* flush output buffer */
 716         fputs(strbuf_value(outbuf), out);
 717         strbuf_reset(outbuf);
 718 
 719         if (warned)
 720                 fputs(warned_line_end, out);
 721         if (guide == NULL)
 722                 fputc('\n', out);
 723         else {
 724                 if (definition_header == RIGHT_HEADER)
 725                         fputs(guide, out);
 726                 fputc('\n', out);
 727                 if (definition_header == AFTER_HEADER) {
 728                         fputs_nl(guide, out);
 729                 }
 730                 guide = NULL;
 731         }
 732         warned = 0;
 733 
 734         /* save for the other job in this module */
 735         last_lineno = lineno;
 736 }
 737 /**
 738  * Encode URL.
 739  *
 740  *      @param[out]     sb      encoded URL
 741  *      @param[in]      url     URL
 742  */
 743 static void
 744 encode(STRBUF *sb, const char *url)
 745 {
 746         int c;
 747 
 748         while ((c = (unsigned char)*url++) != '\0') {
 749                 if (isurlchar(c)) {
 750                         strbuf_putc(sb, c);
 751                 } else {
 752                         strbuf_putc(sb, '%');
 753                         strbuf_putc(sb, "0123456789abcdef"[c >> 4]);
 754                         strbuf_putc(sb, "0123456789abcdef"[c & 0x0f]);
 755                 }
 756         }
 757 }
 758 /**
 759  * get_cvs_module: return @NAME{CVS} module of source file.
 760  *
 761  *      @param[in]      file            source path
 762  *      @param[out]     basename        If @a basename is not @CODE{NULL}, store pointer to <br>
 763  *                              the last component of source path.
 764  *      @return         !=NULL : relative path from repository top <br>
 765  *                      ==NULL : CVS/Repository is not readable.
 766  */
 767 static const char *
 768 get_cvs_module(const char *file, const char **basename)
 769 {
 770         const char *p;
 771         STATIC_STRBUF(dir);
 772         static char prev_dir[MAXPATHLEN];
 773         STATIC_STRBUF(module);
 774         FILE *ip;
 775 
 776         strbuf_clear(dir);
 777         p = locatestring(file, "/", MATCH_LAST);
 778         if (p != NULL) {
 779                 strbuf_nputs(dir, file, p - file);
 780                 p++;
 781         } else {
 782                 strbuf_putc(dir, '.');
 783                 p = file;
 784         }
 785         if (basename != NULL)
 786                 *basename = p;
 787         if (strcmp(strbuf_value(dir), prev_dir) != 0) {
 788                 strlimcpy(prev_dir, strbuf_value(dir), sizeof(prev_dir));
 789                 strbuf_clear(module);
 790                 strbuf_puts(dir, "/CVS/Repository");
 791                 ip = fopen(strbuf_value(dir), "r");
 792                 if (ip != NULL) {
 793                         strbuf_fgets(module, ip, STRBUF_NOCRLF);
 794                         fclose(ip);
 795                 }
 796         }
 797         if (strbuf_getlen(module) > 0)
 798                 return strbuf_value(module);
 799         return NULL;
 800 }
 801 /**
 802  *
 803  * src2html: convert source code into HTML
 804  *
 805  *       @param[in]      src   source file     - Read from
 806  *       @param[in]      html  HTML file       - Write to
 807  *       @param[in]      notsource 1: isn't source, 0: source.
 808  */
 809 void
 810 src2html(const char *src, const char *html, int notsource)
 811 {
 812         char indexlink[128];
 813 
 814         /*
 815          * setup lineno format.
 816          */
 817         snprintf(lineno_format, sizeof(lineno_format), "%%%dd ", ncol);
 818 
 819         fileop_in  = open_input_file(src);
 820         in = get_descripter(fileop_in);
 821         curpfile = src;
 822         warned = 0;
 823 
 824         fileop_out = open_output_file(html, cflag);
 825         out = get_descripter(fileop_out);
 826         strbuf_clear(outbuf);
 827 
 828         snprintf(indexlink, sizeof(indexlink), "../mains.%s", normal_suffix);
 829         fputs_nl(gen_page_begin(src, SUBDIR), out);
 830         fputs_nl(body_begin, out);
 831         /*
 832          * print fixed guide
 833          */
 834         if (fixed_guide)
 835                 fputs(fixed_guide_link_format(anchor_getlinks(0), fill_anchor(NULL, src)), out);
 836         /*
 837          * print the header
 838          */
 839         if (insert_header)
 840                 fputs(gen_insert_header(SUBDIR), out);
 841         fputs(gen_name_string("TOP"), out);
 842         fputs(header_begin, out);
 843         fputs(fill_anchor(indexlink, src), out);
 844         if (cvsweb_url) {
 845                 STATIC_STRBUF(sb);
 846                 const char *module, *basename;
 847 
 848                 strbuf_clear(sb);
 849                 strbuf_puts(sb, cvsweb_url);
 850                 if (use_cvs_module
 851                  && (module = get_cvs_module(src, &basename)) != NULL) {
 852                         encode(sb, module);
 853                         strbuf_putc(sb, '/');
 854                         encode(sb, basename);
 855                 } else {
 856                         encode(sb, src);
 857                 }
 858                 if (cvsweb_cvsroot) {
 859                         strbuf_puts(sb, "?cvsroot=");
 860                         strbuf_puts(sb, cvsweb_cvsroot);
 861                 }
 862                 fputs(quote_space, out);
 863                 fputs(gen_href_begin_simple(strbuf_value(sb)), out);
 864                 fputs(cvslink_begin, out);
 865                 fputs("[CVS]", out);
 866                 fputs(cvslink_end, out);
 867                 fputs_nl(gen_href_end(), out);
 868                 /* doesn't close string buffer */
 869         }
 870         fputs_nl(header_end, out);
 871         fputs(comment_begin, out);
 872         fputs("/* ", out);
 873 
 874         fputs(link_format(anchor_getlinks(0)), out);
 875         if (show_position)
 876                 fprintf(out, "%s%s[+1 %s]%s", quote_space, position_begin, src, position_end);
 877         fputs(" */", out);
 878         fputs_nl(comment_end, out);
 879         fputs_nl(hr, out);
 880         /*
 881          * It is not source file.
 882          */
 883         if (notsource) {
 884                 STRBUF *sb = strbuf_open(0);
 885                 const char *_;
 886 
 887                 fputs_nl(verbatim_begin, out);
 888                 last_lineno = 0;
 889                 while ((_ = strbuf_fgets(sb, in, STRBUF_NOCRLF)) != NULL) {
 890                         fputs(gen_name_number(++last_lineno), out);
 891                         detab_replacing(out, _, HTML_quoting);
 892                 }
 893                 fputs_nl(verbatim_end, out);
 894                 strbuf_close(sb);
 895         }
 896         /*
 897          * It's source code.
 898          */
 899         else {
 900                 const char *basename;
 901                 struct data *incref;
 902                 struct anchor *ancref;
 903                 STATIC_STRBUF(define_index);
 904 
 905                 /*
 906                  * INCLUDED FROM index.
 907                  */
 908                 basename = locatestring(src, "/", MATCH_LAST);
 909                 if (basename)
 910                         basename++;
 911                 else
 912                         basename = src;
 913                 incref = get_included(basename);
 914                 if (incref) {
 915                         char s_id[32];
 916                         const char *dir, *file, *suffix, *key, *title;
 917 
 918                         fputs(header_begin, out);
 919                         if (incref->ref_count > 1) {
 920                                 char s_count[32];
 921 
 922                                 snprintf(s_count, sizeof(s_count), "%d", incref->ref_count);
 923                                 snprintf(s_id, sizeof(s_id), "%d", incref->id);
 924                                 dir = upperdir(INCREFS);
 925                                 file = s_id;
 926                                 suffix = HTML;
 927                                 key = NULL;
 928                                 title = tooltip('I', -1, s_count);
 929                         } else {
 930                                 const char *p = strbuf_value(incref->ref_contents);
 931                                 const char *lno = strmake(p, " ");
 932                                 const char *filename;
 933 
 934                                 p = locatestring(p, " ", MATCH_FIRST);
 935                                 if (p == NULL)
 936                                         die("internal error.(incref->ref_contents)");
 937                                 filename = p + 1;
 938                                 if (filename[0] == '.' && filename[1] == '/')
 939                                         filename += 2;
 940                                 dir = NULL;
 941                                 file = path2fid(filename);
 942                                 suffix = HTML;
 943                                 key = lno;
 944                                 title = tooltip('I', atoi(lno), filename);
 945                         }
 946                         fputs(gen_href_begin_with_title(dir, file, suffix, key, title), out);
 947                         fputs(title_included_from, out);
 948                         fputs(gen_href_end(), out);
 949                         fputs_nl(header_end, out);
 950                         fputs_nl(hr, out);
 951                 }
 952                 /*
 953                  * DEFINITIONS index.
 954                  */
 955                 strbuf_clear(define_index);
 956                 for (ancref = anchor_first(); ancref; ancref = anchor_next()) {
 957                         if (ancref->type == 'D') {
 958                                 char tmp[32];
 959                                 snprintf(tmp, sizeof(tmp), "%d", ancref->lineno);
 960                                 strbuf_puts(define_index, item_begin);
 961                                 strbuf_puts(define_index, gen_href_begin_with_title(NULL, NULL, NULL, tmp, tooltip('R', ancref->lineno, NULL)));
 962                                 strbuf_puts(define_index, gettag(ancref));
 963                                 strbuf_puts(define_index, gen_href_end());
 964                                 strbuf_puts_nl(define_index, item_end);
 965                         }
 966                 }
 967                 if (strbuf_getlen(define_index) > 0) {
 968                         fputs(header_begin, out);
 969                         fputs(title_define_index, out);
 970                         fputs_nl(header_end, out);
 971                         fputs_nl("This source file includes following definitions.", out);
 972                         fputs_nl(list_begin, out);
 973                         fputs(strbuf_value(define_index), out);
 974                         fputs_nl(list_end, out);
 975                         fputs_nl(hr, out);
 976                 }
 977                 /*
 978                  * print source code
 979                  */
 980                 fputs_nl(verbatim_begin, out);
 981                 {
 982                         const char *suffix = locatestring(src, ".", MATCH_LAST);
 983                         const char *lang = NULL;
 984                         struct lang_entry *ent;
 985 
 986                         /*
 987                          * Decide language.
 988                          */
 989                         if (suffix)
 990                                 lang = decide_lang(suffix);
 991                         /*
 992                          * Select parser.
 993                          * If lang == NULL then default parser is selected.
 994                          */
 995                         ent = get_lang_entry(lang);
 996                         /*
 997                          * Initialize parser.
 998                          */
 999                         ent->init_proc(in);
1000                         /*
1001                          * Execute parser.
1002                          * Exec_proc() is called repeatedly until returning EOF.
1003                          */
1004                         while (ent->exec_proc())
1005                                 ;
1006                 }
1007                 fputs_nl(verbatim_end, out);
1008         }
1009         fputs_nl(hr, out);
1010         fputs_nl(gen_name_string("BOTTOM"), out);
1011         fputs(comment_begin, out);
1012         fputs("/* ", out);
1013         fputs(link_format(anchor_getlinks(-1)), out);
1014         if (show_position)
1015                 fprintf(out, "%s%s[+%d %s]%s", quote_space, position_begin, last_lineno, src, position_end);
1016         fputs(" */", out);
1017         fputs_nl(comment_end, out);
1018         if (insert_footer) {
1019                 fputs(br, out);
1020                 fputs(gen_insert_footer(SUBDIR), out);
1021         }
1022         fputs_nl(body_end, out);
1023         fputs_nl(gen_page_end(), out);
1024         if (!notsource)
1025                 anchor_unload();
1026         close_file(fileop_out);
1027         close_file(fileop_in);
1028 }

/* [previous][next][first][last][top][bottom][index][help] */