root/gozilla/gozilla.c

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

DEFINITIONS

This source file includes following definitions.
  1. usage
  2. help
  3. load_alias
  4. alias
  5. locate_HTMLdir
  6. main
  7. getdefinitionURL
  8. getURL
  9. isprotocol
  10. convertpath
  11. makefileurl
  12. show_page_by_url
  13. show_page_by_url
  14. show_page_by_url

   1 /*
   2  * Copyright (c) 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2006, 2011
   3  *      Tama Communications Corporation
   4  *
   5  * This file is part of GNU GLOBAL.
   6  *
   7  * This program is free software: you can redistribute it and/or modify
   8  * it under the terms of the GNU General Public License as published by
   9  * the Free Software Foundation, either version 3 of the License, or
  10  * (at your option) any later version.
  11  * 
  12  * This program is distributed in the hope that it will be useful,
  13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15  * GNU General Public License for more details.
  16  * 
  17  * You should have received a copy of the GNU General Public License
  18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  19  */
  20 
  21 #ifdef HAVE_CONFIG_H
  22 #include <config.h>
  23 #endif
  24 #include <stdio.h>
  25 #include <stdlib.h>
  26 #include <string.h>
  27 #include <ctype.h>
  28 #ifdef _WIN32
  29 #define WIN32_LEAN_AND_MEAN
  30 #include <windows.h>
  31 #include <shellapi.h>
  32 /*
  33  * Don't remove the following code which seems meaningless.
  34  * Since WIN32 has another SLIST_ENTRY, we removed the definition
  35  * so as not to cause the conflict.
  36  */
  37 #ifdef SLIST_ENTRY
  38 #undef SLIST_ENTRY
  39 #endif
  40 #endif
  41 
  42 #include "global.h"
  43 #include "regex.h"
  44 #include "const.h"
  45 
  46 /**
  47  @file
  48  @NAME{gozilla} - force @NAME{mozilla} browser to display specified part of a source file.
  49 */
  50 
  51 static void usage(void);
  52 static void help(void);
  53 
  54 const char *gozillarc = ".gozillarc";
  55 #ifdef __DJGPP__
  56 const char *dos_gozillarc = "_gozillarc";
  57 #endif
  58 STRHASH *sh;
  59 
  60 static void load_alias(void);
  61 static const char *alias(const char *);
  62 int main(int, char **);
  63 void getdefinitionURL(const char *, const char *, STRBUF *);
  64 void getURL(const char *, const char *, STRBUF *);
  65 int isprotocol(const char *);
  66 int convertpath(const char *, const char *, const char *, STRBUF *);
  67 void makefileurl(const char *, int, STRBUF *);
  68 void show_page_by_url(const char *, const char *);
  69 #ifndef isblank
  70 #define isblank(c)      ((c) == ' ' || (c) == '\t')
  71 #endif
  72 
  73 const char *cwd, *root, *dbpath;
  74 
  75 int bflag;
  76 int pflag;
  77 int qflag;
  78 int Cflag;
  79 int vflag;
  80 int show_version;
  81 int linenumber = 0;
  82 int debug;
  83 
  84 static void
  85 usage(void)
  86 {
  87         if (!qflag)
  88                 fputs(usage_const, stderr);
  89         exit(2);
  90 }
  91 static void
  92 help(void)
  93 {
  94         fputs(usage_const, stdout);
  95         fputs(help_const, stdout);
  96         exit(0);
  97 }
  98 
  99 /**
 100  * load_alias: load alias value.
 101  *
 102  * @code{.txt}
 103  * [$HOME/.gozillarc]
 104  * +-----------------------
 105  * |a:http://www.gnu.org
 106  * |f = file:/usr/share/xxx.html
 107  * |www http://www.xxx.yyy/
 108  * @endcode
 109  */
 110 static void
 111 load_alias(void)
 112 {
 113         FILE *ip;
 114         STRBUF *sb = strbuf_open(0);
 115         char *p;
 116         int flag = STRBUF_NOCRLF;
 117         struct sh_entry *ent;
 118 
 119         sh = strhash_open(10);
 120         if (!(p = get_home_directory()))
 121                 goto end;
 122         if (!test("r", makepath(p, gozillarc, NULL)))
 123 #ifdef __DJGPP__
 124                 if (!test("r", makepath(p, dos_gozillarc, NULL)))
 125 #endif
 126                         goto end;
 127         if (!(ip = fopen(makepath(p, gozillarc, NULL), "r")))
 128 #ifdef __DJGPP__
 129                 if (!(ip = fopen(makepath(p, dos_gozillarc, NULL), "r")))
 130 #endif
 131                         goto end;
 132         while ((p = strbuf_fgets(sb, ip, flag)) != NULL) {
 133                 char *name, *value;
 134 
 135                 flag &= ~STRBUF_APPEND;
 136                 if (*p == '#')
 137                         continue;
 138                 if (strbuf_unputc(sb, '\\')) {
 139                         flag |= STRBUF_APPEND;
 140                         continue;
 141                 }
 142                 while (*p && isblank(*p))                               /* skip spaces */
 143                         p++;
 144                 name = p;
 145                 while (*p && !isblank(*p) && *p != '=' && *p != ':')    /* get name */
 146                         p++;
 147                 *p++ = 0;
 148                 while (*p && (isblank(*p) || *p == '=' || *p == ':'))
 149                         p++;
 150                 value = p;                                              /* get value */
 151                 ent = strhash_assign(sh, name, 1);
 152                 if (ent->value)
 153                         (void)free(ent->value);
 154                 ent->value = check_strdup(value);
 155         }
 156         fclose(ip);
 157 end:
 158         strbuf_close(sb);
 159 }
 160 /**
 161  * alias: get alias value.
 162  *
 163  *      @param[in]      alias_name      alias name
 164  *      @return                 its value
 165  */
 166 static const char *
 167 alias(const char *alias_name)
 168 {
 169         struct sh_entry *ent = strhash_assign(sh, alias_name, 0);
 170         return ent ? ent->value : NULL;
 171 }
 172 
 173 /**
 174  * locate_HTMLdir: locate HTML directory made by @XREF{htags,1}.
 175  *
 176  *      @return         HTML directory
 177  */
 178 static const char *
 179 locate_HTMLdir(void)
 180 {
 181         static char htmldir[MAXPATHLEN];
 182 
 183         if (test("d", makepath(dbpath, "HTML", NULL)))
 184                 strlimcpy(htmldir, makepath(dbpath, "HTML", NULL), sizeof(htmldir));
 185         else if (test("d", makepath(root, "HTML", NULL)))
 186                 strlimcpy(htmldir, makepath(root, "HTML", NULL), sizeof(htmldir));
 187         else if (test("d", makepath(root, "html/HTML", NULL)))
 188                 /* Doxygen makes HTML in doxygen's html directory. */
 189                 strlimcpy(htmldir, makepath(root, "html/HTML", NULL), sizeof(htmldir));
 190         else
 191                 return NULL;
 192         if (vflag)
 193                 fprintf(stdout, "HTML directory '%s'.\n", htmldir);
 194         return (const char *)htmldir;
 195 }
 196 int
 197 main(int argc, char **argv)
 198 {
 199         char c;
 200         const char *p, *browser = NULL, *definition = NULL;
 201         STRBUF *arg = strbuf_open(0);
 202         STRBUF *URL = strbuf_open(0);
 203 
 204         while (--argc > 0 && ((c = (++argv)[0][0]) == '-' || c == '+')) {
 205                 if (argv[0][1] == '-') {
 206                         if (!strcmp("--help", argv[0]))
 207                                 help();
 208                         else if (!strcmp("--version", argv[0]))
 209                                 show_version++;
 210                         else if (!strcmp("--quiet", argv[0])) {
 211                                 qflag++;
 212                                 vflag = 0;
 213                         } else if (!strcmp("--verbose", argv[0])) {
 214                                 vflag++;
 215                                 qflag = 0;
 216                         } else
 217                                 usage();
 218                         continue;
 219                 }
 220                 if (c == '+') {
 221                         linenumber = atoi(argv[0] + 1);
 222                         continue;
 223                 }
 224                 p = argv[0] + 1;
 225                 switch (*p) {
 226                 case 'b':
 227                         browser = argv[1];
 228                         --argc; ++argv;
 229                         break;
 230                 case 'd':
 231                         definition = argv[1];
 232                         --argc; ++argv;
 233                         break;
 234                 case 'p':
 235                         pflag++;
 236                         break;
 237                 case 'q':
 238                         qflag++;
 239                         setquiet();
 240                         break;
 241                 case 'v':
 242                         vflag++;
 243                         setverbose();
 244                         break;
 245                 default:
 246                         usage();
 247                 }
 248         }
 249         if (show_version)
 250                 version(progname, vflag);
 251         /*
 252          * Load aliases from .gozillarc.
 253          */
 254         load_alias();
 255 
 256         /*
 257          * Decide browser.
 258          */
 259         if (!browser && getenv("BROWSER"))
 260                 browser = getenv("BROWSER");
 261         if (!browser && alias("BROWSER"))
 262                 browser = alias("BROWSER");
 263         /*
 264          * In DOS & Windows, let the file: association handle it.
 265          */
 266 #if !(_WIN32 || __DJGPP__)
 267         if (!browser)
 268                 browser = "mozilla";
 269 #endif
 270 
 271         /*
 272          * Replace alias name.
 273          */
 274         if (definition == NULL) {
 275                 if (argc == 0)
 276                         usage();
 277                 strbuf_puts(arg, argv[0]);
 278                 /*
 279                  * Replace with alias value.
 280                  */
 281                 if ((p = alias(strbuf_value(arg))) != NULL) {
 282                         strbuf_reset(arg);
 283                         strbuf_puts(arg, p);
 284                 }
 285         }
 286         /*
 287          * Get URL.
 288          */
 289         {
 290                 char *argument = strbuf_value(arg);
 291 
 292                 /*
 293                  * Protocol (xxx://...)
 294                  */
 295                 if (!definition && isprotocol(argument)) {
 296                         strbuf_puts(URL, argument);
 297                 } else {
 298                         const char *HTMLdir = NULL;
 299 
 300                         if (setupdbpath(0) == 0) {
 301                                 cwd = get_cwd();
 302                                 root = get_root();
 303                                 dbpath = get_dbpath();
 304                                 HTMLdir = locate_HTMLdir();
 305                         } 
 306                         /*
 307                          * Make a URL of hypertext from the argument.
 308                          */
 309                         if (HTMLdir != NULL) {
 310                                 if (definition)
 311                                         getdefinitionURL(definition, HTMLdir, URL);
 312                                 else
 313                                         getURL(argument, HTMLdir, URL);
 314                         }
 315                         /*
 316                          * Make a file URL.
 317                          */
 318                         else if (test("fr", argument) || test("dr", argument)) {
 319                                 char cwd[MAXPATHLEN];
 320                                 char result[MAXPATHLEN];
 321 
 322                                 if (getcwd(cwd, sizeof(cwd)) == NULL)
 323                                         die("cannot get current directory.");
 324                                 if (rel2abs(argument, cwd, result, sizeof(result)) == NULL)
 325                                         die("rel2abs failed.");
 326                                 strbuf_puts(URL, "file://");
 327                                 strbuf_puts(URL, result);
 328                         } else {
 329                                 die_with_code(1, "file '%s' not found.", argument);
 330                         }
 331                 }
 332         }
 333         if (pflag) {
 334                 fprintf(stdout, "%s\n", strbuf_value(URL));
 335                 if (vflag)
 336                         fprintf(stdout, "using browser '%s'.\n", browser);
 337                 exit(0);
 338         }
 339         /*
 340          * Show URL's page.
 341          */
 342         show_page_by_url(browser, strbuf_value(URL));
 343         exit(0);
 344 }
 345 
 346 /**
 347  * getdefinitionURL: get URL includes specified definition.
 348  *
 349  *      @param[in]      arg     definition name
 350  *      @param[in]      htmldir HTML directory
 351  *      @param[out]     URL     URL begin with @CODE{'file:'}
 352  */
 353 void
 354 getdefinitionURL(const char *arg, const char *htmldir, STRBUF *URL)
 355 {
 356         FILE *fp;
 357         char *p;
 358         SPLIT ptable;
 359         int status = -1;
 360         STRBUF *sb = strbuf_open(0);
 361         const char *path = makepath(htmldir, "MAP", NULL);
 362 
 363         if (!test("f", path))
 364                 die("'%s' not found. Please invoke htags(1) with the --map-file option.", path);
 365         fp = fopen(path, "r");
 366         if (!fp)
 367                 die("cannot open '%s'.", path);
 368         while ((p = strbuf_fgets(sb, fp, STRBUF_NOCRLF)) != NULL) {
 369                 if (split(p, 2, &ptable) != 2)
 370                         die("illegal format.");
 371                 if (!strcmp(arg, ptable.part[0].start)) {
 372                         status = 0;
 373                         break;
 374                 }
 375         }
 376         fclose(fp);
 377         if (status == -1)
 378                 die("definition %s not found.", arg);
 379         strbuf_reset(URL);
 380         /*
 381          * convert path into URL.
 382          */
 383         makefileurl(makepath(htmldir, ptable.part[1].start, NULL), 0, URL);
 384         recover(&ptable);
 385         strbuf_close(sb);
 386 }
 387 /**
 388  * getURL: get URL of the specified @a file.
 389  *
 390  *      @param[in]      file    file name
 391  *      @param[in]      htmldir HTML directory
 392  *      @param[out]     URL     URL begin with @CODE{'file:'}
 393  */
 394 void
 395 getURL(const char *file, const char *htmldir, STRBUF *URL)
 396 {
 397         char *p;
 398         char buf[MAXPATHLEN];
 399         STRBUF *sb = strbuf_open(0);
 400 
 401         if (!test("f", file) && !test("d", file))
 402                 die("file '%s' not found.", file);
 403         p = normalize(file, get_root_with_slash(), cwd, buf, sizeof(buf));
 404         if (p != NULL && convertpath(dbpath, htmldir, p, sb) == 0)
 405                 makefileurl(strbuf_value(sb), linenumber, URL);
 406         else
 407                 makefileurl(realpath(file, buf), 0, URL);
 408         strbuf_close(sb);
 409 }
 410 /**
 411  * isprotocol: return 1 if @a url has a procotol.
 412  *
 413  *      @param[in]      url     URL
 414  *      @return         1: protocol, 0: file
 415  */
 416 int
 417 isprotocol(const char *url)
 418 {
 419         const char *p;
 420 
 421         if (locatestring(url, "file:", MATCH_AT_FIRST))
 422                 return 1;
 423         /*
 424          * protocol's style is like http://xxx.
 425          */
 426         for (p = url; *p && *p != ':'; p++)
 427                 if (!isalnum(*p))
 428                         return 0;
 429         if (!*p)
 430                 return 0;
 431         if (*p++ == ':' && *p++ == '/' && *p == '/')
 432                 return 1;
 433         return 0;
 434 }
 435 /**
 436  * convertpath: convert source file into hypertext path.
 437  *
 438  *      @param[in]      dbpath  dbpath
 439  *      @param[in]      htmldir HTML directory made by @XREF{htags,1}
 440  *      @param[in]      path    source file path
 441  *      @param[out]     sb      string buffer
 442  *      @return         0: normal, -1: error
 443  */
 444 int
 445 convertpath(const char *dbpath, const char *htmldir, const char *path, STRBUF *sb)
 446 {
 447         static const char *suffix[] = {".html", ".htm"};
 448         static const char *gz = ".gz";
 449         int i, lim = sizeof(suffix)/sizeof(char *);
 450         const char *p;
 451 
 452         strbuf_reset(sb);
 453         strbuf_puts(sb, htmldir);
 454         strbuf_puts(sb, "/S/");
 455         /*
 456          * new style.
 457          */
 458         if (gpath_open(dbpath, 0) == 0) {
 459                 int tag1 = strbuf_getlen(sb);
 460 
 461                 p = gpath_path2fid(path, NULL);
 462                 if (p == NULL) {
 463                         gpath_close();
 464                         return -1;
 465                 }
 466                 gpath_close();
 467                 strbuf_puts(sb, p);
 468                 for (i = 0; i < lim; i++) {
 469                         int tag2 = strbuf_getlen(sb);
 470                         strbuf_puts(sb, suffix[i]);
 471                         if (test("f", strbuf_value(sb)))
 472                                 return 0;
 473                         strbuf_puts(sb, gz);
 474                         if (test("f", strbuf_value(sb)))
 475                                 return 0;
 476                         strbuf_setlen(sb, tag2);
 477                 }
 478                 strbuf_setlen(sb, tag1);
 479         }
 480         /*
 481          * old style.
 482          */
 483         for (p = path + 1; *p; p++)
 484                 strbuf_putc(sb, (*p == '/') ? ' ' : *p);
 485         for (i = 0; i < lim; i++) {
 486                 int tag = strbuf_getlen(sb);
 487                 strbuf_puts(sb, suffix[i]);
 488                 if (test("f", strbuf_value(sb)))
 489                         return 0;
 490                 strbuf_puts(sb, gz);
 491                 if (test("f", strbuf_value(sb)))
 492                         return 0;
 493                 strbuf_setlen(sb, tag);
 494         }
 495         return -1;
 496 }
 497 /**
 498  * makefileurl: make url which start with @CODE{'file:'}.
 499  *
 500  *      @param[in]      path    path name (absolute)
 501  *      @param[in]      line    !=0: line number
 502  *      @param[out]     url     URL
 503  *
 504  * @par Examples:
 505  * @code
 506  * makefileurl('/dir/a.html', 10)   => 'file:///dir/a.html#L10'
 507  * @endcode
 508  *
 509  * @par
 510  * (Windows32 environment)
 511  * @code
 512  * makefileurl('c:/dir/a.html', 10) => 'file://c|/dir/a.html#L10'
 513  * @endcode
 514  */
 515 void
 516 makefileurl(const char *path, int line, STRBUF *url)
 517 {
 518         strbuf_puts(url, "file://");
 519 #if _WIN32 || __DJGPP__
 520         /*
 521          * copy drive name. (c: -> c|)
 522          */
 523         if (isalpha(*path) && *(path+1) == ':') {
 524                 strbuf_putc(url, *path);
 525                 strbuf_putc(url, '|');
 526                 path += 2;
 527         }
 528 #endif
 529         strbuf_puts(url, path);
 530         if (line) {
 531                 strbuf_puts(url, "#L");
 532                 strbuf_putn(url, line);
 533         }
 534 }
 535 /**
 536  * show_page_by_url: show page by @a url
 537  *
 538  *      @param[in]      browser browser name
 539  *      @param[in]      url     URL
 540  */
 541 #if defined(_WIN32)
 542 /* Windows32 version */
 543 void
 544 show_page_by_url(const char *browser, const char *url)
 545 {
 546         const char *lpFile, *lpParameters;
 547         if (browser) {
 548                 lpFile = browser;
 549                 lpParameters = url;
 550         } else {
 551                 lpFile = url;
 552                 lpParameters = NULL;
 553         }
 554         if (ShellExecute(NULL, NULL, lpFile, lpParameters, NULL, SW_SHOWNORMAL) <= (HINSTANCE)32)
 555                 die("Cannot load %s (error = 0x%04x).", lpFile, GetLastError());
 556 }
 557 #elif defined(__DJGPP__)
 558 /* DJGPP version */
 559 void
 560 show_page_by_url(const char *browser, const char *url)
 561 {
 562         char com[MAXFILLEN];
 563         char *path;
 564 
 565         if (!browser) {
 566                 browser = "";
 567         }
 568         /*
 569          * assume a Windows browser if it's not on the path.
 570          */
 571         if (!(path = usable(browser))) {
 572                 /*
 573                  * START is an internal command in XP, external in 9X.
 574                  */
 575                 if (!(path = usable("start")))
 576                         path = "cmd /c start \"\"";
 577                 snprintf(com, sizeof(com), "%s %s \"%s\"", path, browser, url);
 578         } else {
 579                 snprintf(com, sizeof(com), "%s \"%s\"", path, url);
 580         }
 581         system(com);
 582 }
 583 #else
 584 /* UNIX version */
 585 void
 586 show_page_by_url(const char *browser, const char *url)
 587 {
 588         char com[1024];
 589 
 590         /*
 591          * Browsers which have openURL() command.
 592          */
 593         if (locatestring(browser, "mozilla", MATCH_AT_LAST) ||
 594             locatestring(browser, "firefox", MATCH_AT_LAST) ||
 595             locatestring(browser, "netscape", MATCH_AT_LAST) ||
 596             locatestring(browser, "netscape-remote", MATCH_AT_LAST))
 597         {
 598                 snprintf(com, sizeof(com), "%s -remote \"openURL(%s)\"", browser, url);
 599         }
 600         /*
 601          * Generic browser.
 602          */
 603         else {
 604                 snprintf(com, sizeof(com), "%s \"%s\"", browser, url);
 605         }
 606         system(com);
 607 }
 608 #endif

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