root/htags/fileindex.c

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

DEFINITIONS

This source file includes following definitions.
  1. getpath
  2. ungetpath
  3. extract_lastname
  4. lastpart
  5. dirpart
  6. localpath
  7. appendslash
  8. removedotslash
  9. insert_comma
  10. print_directory
  11. print_directory_header
  12. print_directory_footer
  13. print_file_name
  14. print_directory_name
  15. makefileindex
  16. makeincludeindex

   1 /*
   2  * Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
   3  *              2006, 2010
   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 #ifdef HAVE_CONFIG_H
  22 #include "config.h"
  23 #endif
  24 #include <ctype.h>
  25 #include <stdio.h>
  26 #ifdef STDC_HEADERS
  27 #include <stdlib.h>
  28 #endif
  29 #ifdef HAVE_STRING_H
  30 #include <string.h>
  31 #else
  32 #include <strings.h>
  33 #endif
  34 
  35 #include "global.h"
  36 #include "incop.h"
  37 #include "htags.h"
  38 #include "path2url.h"
  39 #include "common.h"
  40 
  41 /*----------------------------------------------------------------------*/
  42 /* Find list procedures                                                 */
  43 /*----------------------------------------------------------------------*/
  44 static const char *getpath(void);
  45 static void ungetpath(void);
  46 static GFIND *gp;
  47 static int retry;
  48 /**
  49  * get a path from input stream.
  50  *
  51  * @note Each path name must start with @CODE{"./"}.
  52  */
  53 static const char *
  54 getpath(void)
  55 {
  56         static const char *buff;
  57 
  58         if (!retry) {
  59                 /* skip README or ChangeLog unless the -o option specified. */
  60                 do {
  61                         buff = gfind_read(gp);
  62                 } while (buff && gp->type == GPATH_OTHER && !other_files);
  63         }
  64         retry = 0;
  65         return buff;
  66 }
  67 /**
  68  * push back a path name.
  69  */
  70 static void
  71 ungetpath(void)
  72 {
  73         retry = 1;
  74 }
  75 /*----------------------------------------------------------------------*/
  76 /* Path name operation procedures                                       */
  77 /*----------------------------------------------------------------------*/
  78 static const char *extract_lastname(const char *, int);
  79 static const char *lastpart(const char *);
  80 static const char *dirpart(const char *, char *);
  81 static const char *localpath(const char *, char *);
  82 static const char *appendslash(const char *);
  83 static const char *insert_comma(unsigned int);
  84 
  85 /**
  86  * extract_lastname: extract the last name of include line.
  87  *
  88  *      @param[in]      image   source image of include
  89  *      @param[in]      is_php  1: is @NAME{PHP} source
  90  *      @return         last name or @VAR{NULL} on error.
  91  */
  92 static const char *
  93 extract_lastname(const char *image, int is_php)
  94 {
  95         static char buf[MAXBUFLEN];
  96         const char *p;
  97         char *q;
  98         int sep;
  99 
 100         /*
 101          * C:   #include <xxx/yyy/zzz.h>
 102          *      #include "xxx/yyy/zzz.h"
 103          * PHP: include('xxx/yyy/zzz');
 104          */
 105         p = image;
 106         while (*p && isspace((unsigned char)*p))                /* skip space */
 107                 p++;
 108         if (!*p)
 109                 return NULL;
 110         if (*p == '#') {
 111                 if (is_php)
 112                         return NULL;
 113                 p++;
 114                 while (*p && isspace((unsigned char)*p))        /* skip space */
 115                         p++;
 116                 if (!*p)
 117                         return NULL;
 118         }
 119         /*
 120          * If match to one of the include keywords then points
 121          * the following character of the keyword.
 122          *            p
 123          *            v
 124          * ... include ....
 125          */
 126         if (is_php) {
 127                 if ((p = locatestring(p, "include", MATCH_AT_FIRST)) == NULL)
 128                         return NULL;
 129         } else {
 130                 char *q;
 131 
 132                 if (((q = locatestring(p, "include_next", MATCH_AT_FIRST)) == NULL) &&
 133                     ((q = locatestring(p, "import", MATCH_AT_FIRST)) == NULL) &&
 134                     ((q = locatestring(p, "include", MATCH_AT_FIRST)) == NULL))
 135                         return NULL;
 136                 p = q;
 137         }
 138         while (*p && isspace((unsigned char)*p))                /* skip space */
 139                 p++;
 140         if (is_php && *p == '(') {
 141                 p++;
 142                 while (*p && isspace((unsigned char)*p))        /* skip space */
 143                         p++;
 144         }
 145         sep = *p;
 146         if (is_php) {
 147                 if (sep != '\'' && sep != '"')
 148                         return NULL;
 149         } else {
 150                 if (sep != '<' && sep != '"')
 151                         return NULL;
 152         }
 153         if (sep == '<')
 154                 sep = '>';
 155         p++;
 156         if (!*p)
 157                 return NULL;
 158         q = buf; 
 159         while (*p && *p != '\n' && *p != sep)
 160                 *q++ = *p++;
 161         *q = '\0';
 162         if (*p == sep) {
 163                 q = locatestring(buf, "/", MATCH_LAST);
 164                 if (q)
 165                         q++;
 166                 else
 167                         q = buf;
 168                 return q;
 169         }
 170         return NULL;
 171 }
 172 /**
 173  * get the last part of the @a path.
 174  *
 175  *      @param[in]      path    path name
 176  *      @return         last part
 177  *
 178  * @par Examples:
 179  * @code
 180  * lastpart("a/b")      => "b"
 181  * lastpart("a")        => "a"
 182  * @endcode
 183  */
 184 static const char *
 185 lastpart(const char *path)
 186 {
 187         const char *p = strrchr(path, '/');
 188 
 189         return p ? p + 1 : path;
 190 }
 191 /**
 192  * get the directory part of the @a path.
 193  *
 194  *      @param[in]      path    path name
 195  *      @param[out]     result  result buffer
 196  *      @return         directory part
 197  *
 198  * @par Examples:
 199  * @code
 200  * dirpart("a/b/c")     => "a/b"
 201  * @endcode
 202  */
 203 static const char *
 204 dirpart(const char *path, char *result)
 205 {
 206         char *p = result;
 207         const char *q = path, *limit = strrchr(path, '/');
 208 
 209         while (q < limit)
 210                 *p++ = *q++; 
 211         *p = '\0';
 212         return result;
 213 }
 214 /**
 215  * get the local path name if the path is under the @a dir.
 216  *
 217  *      @param[in]      path    path name
 218  *      @param[in]      dir     directory name
 219  *      @return         local path name or @VAR{NULL}
 220  *
 221  * @par Examples:
 222  * @code
 223  * localpath("a/b/c", "a/b")    => "c"
 224  * localpath("a/b/c/d", "a/b")  => "c/d"
 225  * localpath("a/b/c", "a/d")    => NULL
 226  * @endcode
 227  */
 228 static const char *
 229 localpath(const char *path, char *dir)
 230 {
 231         int length = strlen(dir);
 232 
 233         if (!strncmp(path, dir, length) && *(path + length) == '/')
 234                 return path + length + 1;
 235         return NULL;
 236 }
 237 /**
 238  * append @CODE{'/'} after the path name
 239  *
 240  *      @param[in]      path    path name
 241  *      @return         appended path name
 242  *
 243  *      @note Doesn't check if ends with a @CODE{'/'} already.
 244  *
 245  * @par Examples:
 246  * @code
 247  * appendslash("a")     => "a/"
 248  * @endcode
 249  */
 250 static const char *
 251 appendslash(const char *path)
 252 {
 253         STATIC_STRBUF(sb);
 254 
 255         strbuf_clear(sb);
 256         strbuf_puts(sb, path);
 257         strbuf_putc(sb, '/');
 258         return strbuf_value(sb);
 259 }
 260 /**
 261  * remove @CODE{"./"} at the head of the path name
 262  *
 263  *      @param[in]      path    path name
 264  *      @return         removed path name
 265  *
 266  * @par Examples:
 267  * @code
 268  * removedotslash("./a") => "a"
 269  * @endcode
 270  */
 271 static const char *
 272 removedotslash(const char *path)
 273 {
 274         return (*path == '.' && *(path + 1) == '/') ? path + 2 : path;
 275 }
 276 /**
 277  * insert_comma: insert comma to the number.
 278  *
 279  *      @param[in]      n       number
 280  *      @return         edited string
 281  *
 282  * @par Examples:
 283  * @code
 284  * 10000 => 10,000
 285  * @endcode
 286  */
 287 static const char *
 288 insert_comma(unsigned int n)
 289 {
 290 #define RESULTSIZE 15
 291 #define INTERVAL 3
 292         static char result[RESULTSIZE];
 293         int i = RESULTSIZE;
 294         int count = 0;
 295 
 296         if (n == 0)
 297                 return (const char *)"0";
 298         if (n > 1000000000)
 299                 goto giveup;
 300         result[--i] = '\0';
 301         for (; n > 0; n = n / 10) {
 302                 /*
 303                  * Buffer overflow. This is not important even if occurring.
 304                  */
 305                 if (i <= 0)
 306                         goto giveup;
 307                 if (count && count % INTERVAL == 0)
 308                         result[--i] = ',';
 309                 result[--i] = n % 10 + '0';
 310                 count++;
 311         }
 312         return (const char *)&result[i];
 313 giveup:
 314         snprintf(result, sizeof(result), "*****");
 315         return (const char *)result;
 316 }
 317 /*----------------------------------------------------------------------*/
 318 /* Generating file index                                                */
 319 /*----------------------------------------------------------------------*/
 320 static int print_directory(int, char *);
 321 static void print_directory_header(FILE *, int, const char *);
 322 static void print_directory_footer(FILE *, int, const char *);
 323 static const char *print_file_name(int, const char *);
 324 static const char *print_directory_name(int, const char *, int);
 325 
 326 FILE *FILEMAP;
 327 STRBUF *files;
 328 const char *indexlink;
 329 regex_t is_include_file;
 330 int src_count;
 331 
 332 /**
 333  * @fn static int print_directory(int level, char *basedir)
 334  *
 335  * print contents of one directory and the descendant. (@STRONG{recursively called})
 336  *
 337  *      @param[in]      level   directory nest level
 338  *      @param[in,out]  basedir current directory
 339  *
 340  * This function read find style records, and print directory tree.
 341  */
 342 /**
 343  * File list of the top level directory (when @CODE{level == 0}) is not written
 344  * to a file directly. Instead, it is written to string buffer, because
 345  * it appears in some places.
 346  */
 347 #define PUT(s) do {                                             \
 348                 if (level == 0) {                               \
 349                         if (tree_view == 0)                     \
 350                                 strbuf_puts(files, s);          \
 351                 } else                                          \
 352                          fputs(s, op);                          \
 353 } while (0)
 354 
 355 static int
 356 print_directory(int level, char *basedir)
 357 {
 358         const char *path;
 359         FILEOP *fileop = NULL;
 360         FILE *op = NULL;
 361         int flist_items = 0;
 362         int count = 0;
 363 
 364         if (level > 0) {
 365                 char name[MAXPATHLEN];
 366 
 367                 snprintf(name, sizeof(name), "%s/files/%s.%s", distpath, path2fid(basedir), HTML);
 368                 fileop = open_output_file(name, cflag);
 369                 op = get_descripter(fileop);
 370                 print_directory_header(op, level, basedir);
 371                 if (tree_view) {
 372                         char *target = (Fflag) ? "mains" : "_top";
 373 
 374                         strbuf_puts(files, dir_begin);
 375                         strbuf_puts(files, gen_href_begin_with_title_target("files", path2fid(basedir), HTML, NULL, NULL, target));
 376                         strbuf_puts(files, full_path ? removedotslash(basedir) : lastpart(basedir));
 377                         strbuf_puts(files, gen_href_end());
 378                         strbuf_puts(files, dir_end);
 379                         strbuf_puts(files, "\n<ul>\n");
 380                 }
 381         }
 382         while ((path = getpath()) != NULL) {
 383                 const char *p, *local = localpath(path, basedir);
 384 
 385                 /*
 386                  * Path is outside of basedir.
 387                  */
 388                 if (local == NULL) {
 389                         ungetpath();    /* read again by upper level print_directory(). */
 390                         break;
 391                 }
 392                 /*
 393                  * Path is inside of basedir.
 394                  */
 395                 else {
 396                         char *slash = strchr(local, '/');
 397 
 398                         if (table_flist && flist_items++ % flist_fields == 0)
 399                                 PUT(fline_begin);
 400                         /*
 401                          * Print directory.
 402                          */
 403                         if (slash) {
 404                                 int baselen = strlen(basedir);
 405                                 char *q, *last = basedir + baselen;
 406                                 int subcount;
 407 
 408                                 if (baselen + 1 + (slash - local)  > MAXPATHLEN) {
 409                                         fprintf(stderr, "Too long path name.\n");
 410                                         exit(1);
 411                                 }
 412                                 /*
 413                                  * Append new directory to the basedir.
 414                                  */
 415                                 p = local;
 416                                 q = last;
 417                                 *q++ = '/';
 418                                 while (p < slash)
 419                                         *q++ = *p++;
 420                                 *q = '\0';
 421                                 /*
 422                                  * print tree for this directory.
 423                                  */
 424                                 ungetpath();    /* read again by lower level print_directory(). */
 425                                 subcount = print_directory(level + 1, basedir);
 426                                 PUT(print_directory_name(level, basedir, subcount));
 427                                 count += subcount;
 428                                 /*
 429                                  * Shrink the basedir.
 430                                  */
 431                                 *last = '\0';
 432                         }
 433                         /*
 434                          * Print file.
 435                          */
 436                         else {
 437                                 const char *file_name = print_file_name(level, path);
 438 
 439                                 if (tree_view) {
 440                                         int size = filesize(path);
 441                                         char *target = (Fflag) ? "mains" : "_top";
 442                                         char tips[80];
 443 
 444                                         if (size > 1)
 445                                                 snprintf(tips, sizeof(tips), "%s bytes", insert_comma(size));
 446                                         else
 447                                                 snprintf(tips, sizeof(tips), "%s byte", insert_comma(size));
 448                                         strbuf_sprintf(files, "%s%s%s%s%s\n",
 449                                                 file_begin,
 450                                                 gen_href_begin_with_title_target(SRCS, path2fid(path), HTML, NULL, tips, target),
 451                                                 full_path ? removedotslash(path) : lastpart(path),
 452                                                 gen_href_end(),
 453                                                 file_end);
 454                                 }
 455                                 PUT(file_name);
 456                                 if (filemap_file)
 457                                         fprintf(FILEMAP, "%s\t%s/%s.%s\n", removedotslash(path), SRCS, path2fid(path), HTML);
 458                                 count++;
 459                         }
 460                         if (table_flist && flist_items % flist_fields == 0)
 461                                 PUT(fline_end);
 462                 }
 463         }
 464         if (flist_items % flist_fields != 0)
 465                 PUT(fline_end);
 466         if (level > 0) {
 467                 print_directory_footer(op, level, basedir);
 468                 close_file(fileop);
 469                 if (tree_view)
 470                         strbuf_puts(files, "</ul>\n");
 471         }
 472         html_count++;
 473         return count;
 474 }
 475 /**
 476  * print directory header.
 477  *
 478  *      @param[in]      op      file index
 479  *      @param[in]      level   1,2...
 480  *      @param[in]      dir     directory name
 481  */
 482 static void
 483 print_directory_header(FILE *op, int level, const char *dir)
 484 {
 485         STATIC_STRBUF(sb);
 486         const char *top = (Fflag && !tree_view) ? "../files" : "../mains";
 487 
 488         if (level == 0)
 489                 die("print_directory_header: internal error.");
 490         strbuf_clear(sb);
 491         strbuf_puts(sb, removedotslash(dir));
 492         strbuf_putc(sb, '/');
 493         fputs_nl(gen_page_begin(strbuf_value(sb), SUBDIR), op);
 494         fputs_nl(body_begin, op);
 495 
 496         strbuf_clear(sb);
 497         strbuf_sprintf(sb, "%s%sroot%s/", header_begin, gen_href_begin(NULL, top, normal_suffix, NULL), gen_href_end());
 498         fputs(strbuf_value(sb), op);
 499         {
 500                 char path[MAXPATHLEN];
 501                 char *p, *q;
 502 
 503                 strlimcpy(path, dir, sizeof(path));
 504                 for (p = path + 1; p != NULL; p = strchr(p, '/')) {
 505                         int save = 0;
 506 
 507                         q = ++p;
 508                         while (*q && *q != '/')
 509                                 q++;
 510                         save = *q;
 511                         if (*q == '/')
 512                                 *q = '\0';
 513                         if (save == '/')
 514                                 fputs(gen_href_begin(NULL, path2fid(path), HTML, NULL), op);
 515                         fputs(p, op);
 516                         if (save == '/')
 517                                 fputs(gen_href_end(), op);
 518                         *q = save;
 519                         fputc('/', op);
 520                 }
 521         }
 522         fputs_nl(header_end, op);
 523         {
 524                 char parentdir[MAXPATHLEN];
 525                 const char *suffix, *parent;
 526 
 527                 (void)dirpart(dir, parentdir);
 528                 if (level == 1) {
 529                         parent = top;
 530                         suffix = normal_suffix;
 531                 } else {
 532                         parent = path2fid(parentdir);
 533                         suffix = HTML;
 534                 }
 535                 fputs(gen_href_begin_with_title(NULL, parent, suffix, NULL, "Parent Directory"), op);
 536         }
 537         if (Iflag)
 538                 fputs(gen_image(PARENT, back_icon, ".."), op);
 539         else
 540                 fputs("[..]", op);
 541         fputs_nl(gen_href_end(), op);
 542         if (table_flist)
 543                 fputs_nl(flist_begin, op);
 544         else if (!no_order_list)
 545                 fputs_nl(list_begin, op);
 546         else {
 547                 fputs(br, op);
 548                 fputs_nl(br, op);
 549         }
 550 }
 551 /**
 552  * print directory footer.
 553  *
 554  *      @param[in]      op      file index
 555  *      @param[in]      level   1,2...
 556  *      @param[in]      dir     directory name
 557  */
 558 static void
 559 print_directory_footer(FILE *op, int level, const char *dir)
 560 {
 561         const char *parent, *suffix;
 562         char parentdir[MAXPATHLEN];
 563         const char *top = (Fflag && !tree_view) ? "../files" : "../mains";
 564 
 565         if (level == 0)
 566                 die("print_directory_footer: internal error.");
 567         (void)dirpart(dir, parentdir);
 568         if (level == 1) {
 569                 parent = top;
 570                 suffix = normal_suffix;
 571         } else {
 572                 parent = path2fid(parentdir);
 573                 suffix = HTML;
 574         }
 575         if (table_flist)
 576                 fputs_nl(flist_end, op);
 577         else if (!no_order_list)
 578                 fputs_nl(list_end, op);
 579         else
 580                 fputs_nl(br, op);
 581         fputs(gen_href_begin_with_title(NULL, parent, suffix, NULL, "Parent Directory"), op);
 582         if (Iflag)
 583                 fputs(gen_image(PARENT, back_icon, ".."), op);
 584         else
 585                 fputs("[..]", op);
 586         fputs_nl(gen_href_end(), op);
 587         fputs_nl(body_end, op);
 588         fputs_nl(gen_page_end(), op);
 589 }
 590 /**
 591  * print file name.
 592  *
 593  *      @param[in]      level   0,1,2...
 594  *      @param[in]      path    path of the file
 595  */
 596 static const char *
 597 print_file_name(int level, const char *path)
 598 {
 599         STATIC_STRBUF(sb);
 600         char *target = (Fflag) ? "mains" : "_top";
 601         int size = filesize(path);
 602         char tips[80];
 603 
 604         message(" [%d] adding %s", ++src_count, removedotslash(path));
 605         /*
 606          * We assume the file which has one of the following suffixes
 607          * as a candidate of include file.
 608          *
 609          * C: .h
 610          * C++: .hxx, .hpp, .H, .hh
 611          * PHP: .inc.php
 612          */
 613         if (regexec(&is_include_file, path, 0, 0, 0) == 0)
 614                 put_inc(lastpart(path), path, src_count);
 615         strbuf_clear(sb);
 616         if (table_flist)
 617                 strbuf_puts(sb, fitem_begin);
 618         else if (!no_order_list)
 619                 strbuf_puts(sb, item_begin);
 620         if (size > 1)
 621                 snprintf(tips, sizeof(tips), "%s bytes", insert_comma(size));
 622         else
 623                 snprintf(tips, sizeof(tips), "%s byte", insert_comma(size));
 624         strbuf_puts(sb, gen_href_begin_with_title_target(level == 0 ? SRCS: upperdir(SRCS),
 625                         path2fid(path), HTML, NULL, tips, target));
 626         if (Iflag) {
 627                 const char *lang, *suffix, *text_icon;
 628 
 629                 if ((suffix = locatestring(path, ".", MATCH_LAST)) != NULL
 630                     && (lang = decide_lang(suffix)) != NULL
 631                     && (strcmp(lang, "c") == 0 || strcmp(lang, "cpp") == 0
 632                        || strcmp(lang, "yacc") == 0))
 633                         text_icon = c_icon;
 634                 else
 635                         text_icon = file_icon;
 636                 strbuf_puts(sb, gen_image(level == 0 ? CURRENT : PARENT, text_icon, removedotslash(path)));
 637                 strbuf_puts(sb, quote_space);
 638         }
 639         strbuf_puts(sb, full_path ? removedotslash(path) : lastpart(path));
 640         strbuf_puts(sb, gen_href_end());
 641         if (table_flist)
 642                 strbuf_puts(sb, fitem_end);
 643         else if (!no_order_list)
 644                 strbuf_puts(sb, item_end);
 645         else
 646                 strbuf_puts(sb, br);
 647         strbuf_putc(sb, '\n');
 648         return (const char *)strbuf_value(sb);
 649 }
 650 /**
 651  * print directory name.
 652  *
 653  *      @param[in]      level   0,1,2...
 654  *      @param[in]      path    path of the directory
 655  *      @param[in]      count   number of files in this directory
 656  */
 657 static const char *
 658 print_directory_name(int level, const char *path, int count)
 659 {
 660         STATIC_STRBUF(sb);
 661         char tips[80];
 662 
 663         if (count > 1)
 664                 snprintf(tips, sizeof(tips), "%d files", count);
 665         else
 666                 snprintf(tips, sizeof(tips), "%d file", count);
 667         path = removedotslash(path);
 668         strbuf_clear(sb);
 669         if (table_flist)
 670                 strbuf_puts(sb, fitem_begin);
 671         else if (!no_order_list)
 672                 strbuf_puts(sb, item_begin);
 673         strbuf_puts(sb, gen_href_begin_with_title(level == 0 ? "files" : NULL,
 674                         path2fid(path), HTML, NULL, tips));
 675         if (Iflag) {
 676                 strbuf_puts(sb, gen_image(level == 0 ? CURRENT : PARENT, dir_icon, appendslash(path)));
 677                 strbuf_puts(sb, quote_space);
 678         }
 679         strbuf_sprintf(sb, "%s/%s", lastpart(path), gen_href_end());
 680         if (table_flist)
 681                 strbuf_puts(sb, fitem_end);
 682         else if (!no_order_list)
 683                 strbuf_puts(sb, item_end);
 684         else
 685                 strbuf_puts(sb, br);
 686         strbuf_putc(sb, '\n');
 687         return (const char *)strbuf_value(sb);
 688 }
 689 /**
 690  * makefileindex: make file index.
 691  *
 692  *      @param[in]      file            output file name
 693  *      @param[out]     a_files         top level file index
 694  */
 695 int
 696 makefileindex(const char *file, STRBUF *a_files)
 697 {
 698         STATIC_STRBUF(sb);
 699         FILE *filesop;
 700         int flags = REG_EXTENDED;
 701         /*
 702          * Basedir is a directory to which we are paying attention on each
 703          * occasion. It starts with ".", grows and shrink according to the
 704          * progress of processing. It isn't copied each every recursive call
 705          * not to waste the stack.
 706          */
 707         char basedir[MAXPATHLEN];
 708 
 709         /*
 710          * Initialize data.
 711          */
 712         indexlink = (Fflag) ? "../files" : "../mains";
 713         src_count = 0;
 714 
 715         gp = gfind_open(dbpath, NULL, other_files ? GPATH_BOTH : GPATH_SOURCE);
 716         /*
 717          * for collecting include files.
 718          */
 719         if (w32)
 720                 flags |= REG_ICASE;
 721         strbuf_clear(sb);
 722         strbuf_puts(sb, "\\.(");
 723         {
 724                 const char *p = include_file_suffixes;
 725                 int c;
 726 
 727                 while ((c = (unsigned char)*p++) != '\0') {
 728                         if (isregexchar(c))
 729                                 strbuf_putc(sb, '\\');
 730                         else if (c == ',')
 731                                 c = '|';
 732                         strbuf_putc(sb, c);
 733                 }
 734         }
 735         strbuf_puts(sb, ")$");
 736         if (regcomp(&is_include_file, strbuf_value(sb), flags) != 0)
 737                 die("cannot compile regular expression '%s'.", strbuf_value(sb));
 738 
 739         /*
 740          * Write to files.html.
 741          */
 742         if ((filesop = fopen(makepath(distpath, file, NULL), "w")) == NULL)
 743                 die("cannot open file '%s'.", file);
 744         fputs_nl(gen_page_index_begin(title_file_index, jscode), filesop);
 745         fputs_nl(body_begin, filesop);
 746         fputs(header_begin, filesop);
 747         fputs(gen_href_begin(NULL, "files", normal_suffix, NULL), filesop);
 748         fputs(title_file_index, filesop);
 749         fputs(gen_href_end(), filesop);
 750         fputs_nl(header_end, filesop);
 751         if (tree_view) {
 752                 fputs_nl(tree_control, filesop);
 753                 if (tree_view_type) {
 754                         fprintf(filesop, tree_begin_using, tree_view_type);
 755                         fputc('\n', filesop);
 756                 } else {
 757                         fputs_nl(tree_begin, filesop);
 758                 }
 759         } else if (table_flist)
 760                 fputs_nl(flist_begin, filesop);
 761         else if (!no_order_list)
 762                 fputs_nl(list_begin, filesop);
 763         FILEMAP = NULL;
 764         if (filemap_file) {
 765                 if (!(FILEMAP = fopen(makepath(distpath, "FILEMAP", NULL), "w")))
 766                         die("cannot open '%s'.", makepath(distpath, "FILEMAP", NULL));
 767         }
 768         /*
 769          * print whole directory tree.
 770          */
 771         files = a_files;
 772         strcpy(basedir, ".");
 773 
 774         (void)print_directory(0, basedir);
 775         if (tree_view)
 776                 strbuf_puts(files, tree_end);
 777 
 778         if (filemap_file)
 779                 fclose(FILEMAP);
 780         gfind_close(gp);
 781         regfree(&is_include_file);
 782 
 783         fputs(strbuf_value(files), filesop);
 784         if (tree_view)
 785                 fputs_nl(tree_end, filesop);
 786         else if (table_flist)
 787                 fputs_nl(flist_end, filesop);
 788         else if (!no_order_list)
 789                 fputs_nl(list_end, filesop);
 790         fputs_nl(body_end, filesop);
 791         fputs_nl(gen_page_end(), filesop);
 792         fclose(filesop);
 793         html_count++;
 794         return src_count;
 795 }
 796 /*----------------------------------------------------------------------*/
 797 /* Main body of generating include file index                           */
 798 /*----------------------------------------------------------------------*/
 799 void
 800 makeincludeindex(void)
 801 {
 802         FILE *PIPE;
 803         STRBUF *input = strbuf_open(0);
 804         char *ctags_x;
 805         struct data *inc;
 806         char *target = (Fflag) ? "mains" : "_top";
 807         char command[MAXFILLEN];
 808 
 809         /*
 810          * Pick up include pattern.
 811          *
 812          * C: #include "xxx.h"
 813          * PHP: include("xxx.inc.php");
 814          */
 815         /*
 816          * Unlike Perl regular expression, POSIX regular expression doesn't support C-style escape sequence.
 817          * Therefore, we can not use "\\t" here.
 818          */
 819         snprintf(command, sizeof(command), PQUOTE "%s -gnx --encode-path=\" \t\" \"^[ \t]*(#[ \t]*(import|include)|include[ \t]*\\()\"" PQUOTE, quote_shell(global_path));
 820         if ((PIPE = popen(command, "r")) == NULL)
 821                 die("cannot fork.");
 822         strbuf_reset(input);
 823         while ((ctags_x = strbuf_fgets(input, PIPE, STRBUF_NOCRLF)) != NULL) {
 824                 SPLIT ptable;
 825                 char buf[MAXBUFLEN];
 826                 int is_php = 0;
 827                 const char *last, *lang, *suffix;
 828 
 829                 if (split(ctags_x, 4, &ptable) < 4) {
 830                         recover(&ptable);
 831                         die("too small number of parts in makefileindex().");
 832                 }
 833                 if ((suffix = locatestring(ptable.part[PART_PATH].start, ".", MATCH_LAST)) != NULL
 834                     && (lang = decide_lang(suffix)) != NULL
 835                     && strcmp(lang, "php") == 0)
 836                         is_php = 1;
 837                 last = extract_lastname(ptable.part[PART_LINE].start, is_php);
 838                 if (last == NULL || (inc = get_inc(last)) == NULL)
 839                         continue;
 840                 recover(&ptable);
 841                 /*
 842                  * s/^[^ \t]+/$last/;
 843                  */
 844                 {
 845                         const char *p;
 846                         char *q = buf;
 847 
 848                         for (p = last; *p; p++)
 849                                 *q++ = *p;
 850                         for (p = ctags_x; *p && *p != ' ' && *p != '\t'; p++)
 851                                 ;
 852                         for (; *p; p++)
 853                                 *q++ = *p;
 854                         *q = '\0';
 855                 }
 856                 put_included(inc, buf);
 857         }
 858         if (pclose(PIPE) != 0)
 859                 die("terminated abnormally.");
 860 
 861         for (inc = first_inc(); inc; inc = next_inc()) {
 862                 const char *last = inc->name;
 863                 int no = inc->id;
 864                 FILEOP *fileop_INCLUDE;
 865                 FILE *INCLUDE;
 866 
 867                 if (inc->count > 1) {
 868                         char path[MAXPATHLEN];
 869 
 870                         snprintf(path, sizeof(path), "%s/%s/%d.%s", distpath, INCS, no, HTML);
 871                         fileop_INCLUDE = open_output_file(path, cflag);
 872                         INCLUDE = get_descripter(fileop_INCLUDE);
 873                         fputs_nl(gen_page_begin(last, SUBDIR), INCLUDE);
 874                         fputs_nl(body_begin, INCLUDE);
 875                         fputs_nl(verbatim_begin, INCLUDE);
 876                         {
 877                                 const char *filename = strbuf_value(inc->contents);
 878                                 int count = inc->count;
 879 
 880                                 for (; count; filename += strlen(filename) + 1, count--) {
 881                                         fputs(gen_href_begin_with_title_target(upperdir(SRCS), path2fid(filename), HTML, NULL, NULL, target), INCLUDE);
 882                                         fputs(removedotslash(filename), INCLUDE);
 883                                         fputs_nl(gen_href_end(), INCLUDE);
 884                                 }
 885                         }
 886                         fputs_nl(verbatim_end, INCLUDE);
 887                         fputs_nl(body_end, INCLUDE);
 888                         fputs_nl(gen_page_end(), INCLUDE);
 889                         close_file(fileop_INCLUDE);
 890                         html_count++;
 891                         /*
 892                          * inc->contents == NULL means that information already
 893                          * written to file.
 894                          */
 895                         strbuf_close(inc->contents);
 896                         inc->contents = NULL;
 897                 }
 898                 if (!inc->ref_count)
 899                         continue;
 900                 if (inc->ref_count == 1) {
 901                         SPLIT ptable;
 902                         char buf[1024];
 903 
 904                         if (split(strbuf_value(inc->ref_contents), 4, &ptable) < 4) {
 905                                 recover(&ptable);
 906                                 die("too small number of parts in makefileindex().");
 907                         }
 908                         snprintf(buf, sizeof(buf), "%s %s", ptable.part[PART_LNO].start, decode_path(ptable.part[PART_PATH].start));
 909                         recover(&ptable);
 910                         strbuf_reset(inc->ref_contents);
 911                         strbuf_puts(inc->ref_contents, buf);
 912                 } else {
 913                         char path[MAXPATHLEN];
 914 
 915                         snprintf(path, sizeof(path), "%s/%s/%d.%s", distpath, INCREFS, no, HTML);
 916                         fileop_INCLUDE = open_output_file(path, cflag);
 917                         INCLUDE = get_descripter(fileop_INCLUDE);
 918                         fputs_nl(gen_page_begin(last, SUBDIR), INCLUDE);
 919                         fputs_nl(body_begin, INCLUDE);
 920                         fputs_nl(gen_list_begin(), INCLUDE);
 921                         {
 922                                 const char *line = strbuf_value(inc->ref_contents);
 923                                 int count = inc->ref_count;
 924 
 925                                 for (; count; line += strlen(line) + 1, count--)
 926                                         fputs_nl(gen_list_body(upperdir(SRCS), line, NULL), INCLUDE);
 927                         }
 928                         fputs_nl(gen_list_end(), INCLUDE);
 929                         fputs_nl(body_end, INCLUDE);
 930                         fputs_nl(gen_page_end(), INCLUDE);
 931                         close_file(fileop_INCLUDE);
 932                         html_count++;
 933                         /*
 934                          * inc->ref_contents == NULL means that information already
 935                          * written to file.
 936                          */
 937                         strbuf_close(inc->ref_contents);
 938                         inc->ref_contents = NULL;
 939                 }
 940         }
 941         strbuf_close(input);
 942 }

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