root/htags-refkit/htags_path2url.c

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

DEFINITIONS

This source file includes following definitions.
  1. load_filemap_contents
  2. cmp
  3. create_filemap_index
  4. unload_filemap
  5. htags_load_filemap
  6. htags_unload_filemap
  7. htags_path2url
  8. main

   1 /*
   2  * Htags Hyper-text Reference Kit.
   3  *
   4  * This file is placed into the public domain by the author,
   5  * 2005, 2006 Tama Communications Corporation.
   6  *
   7  * Two library function, qsort(3) and bsearch(3), are required.
   8  */
   9 #include <fcntl.h>
  10 #include <stdio.h>
  11 #include <stdlib.h>
  12 #include <string.h>
  13 #include <sys/param.h>
  14 #include <sys/stat.h>
  15 
  16 #if defined(_WIN32) || defined(__DJGPP__)
  17 # define OPENMODE O_BINARY
  18 #else
  19 # define OPENMODE 0
  20 #endif
  21 
  22 int htags_load_filemap(const char *);
  23 void htags_unload_filemap(void);
  24 int htags_path2url(const char *, int, char *, int);
  25 
  26 /** @file
  27  * @NAME{htags} Hyper-text Reference Kit.
  28  *
  29  * Usage by example.
  30  *
  31  * Getting the URL of @FILE{i386/i386/identcpu.c} at 120, in variable url.
  32  *
  33  * @code
  34  *      char url[MAXPATHLEN];
  35  *      -- Load filemap generated by htags(1).
  36  *      ret = htags_load_filemap("HTML/FILEMAP");
  37  *      if (ret != 0)
  38  *              ERROR;
  39  *      -- Get URL of the specified file name and line number.
  40  *      ret = htags_path2url("i386/i386/identcpu.c", 120, url, sizeof(url));
  41  *      if (ret != 0)
  42  *              ERROR;
  43  *      url == 'S/1238.html#L120'
  44  *      -- release resource
  45  *      htags_unload_filemap();
  46  * @endcode
  47  *
  48  * Since the URL is a relative path from the HTML directory, you should
  49  * modify it so that your application program works well.
  50  */
  51 /**
  52  * in memory FILEMAP
  53  *
  54  * Alphabetical sorted table.
  55  */
  56 struct map
  57 {
  58         const char *name;
  59         const char *path;
  60 };
  61 /**
  62  * @name Global variables.
  63  *
  64  * These variables are set by htags_load_filemap(), and referred by <br>
  65  * htags_path2url() and htags_unload_filemap().
  66  */
  67 /** @{ */
  68 static char *global_contents;           /**< filemap contents           */
  69 static struct map *global_map;          /**< file -\> url mapping table */
  70 static int global_maplines;             /**< the lines of #global_map   */
  71 /** @} */
  72 
  73 /*----------------------------------------------------------------------*/
  74 /* Local functions                                                      */
  75 /*----------------------------------------------------------------------*/
  76 /**
  77  * load contents of FILEMAP into the memory.
  78  *
  79  *      @param[in]      file    path of FILEMAP
  80  *      @param[out]     area    file contents (malloced)
  81  *      @param[out]     size    size of @a area
  82  *      @return 0 succesful <br>
  83  *              -1: out of memory. <br>
  84  *              -2: FILEMAP not found. <br>
  85  *              -3: cannot fstat FILEMAP. <br>
  86  *              -4: cannot read FILEMAP.
  87  */
  88 static int
  89 load_filemap_contents(const char *file, char **area, int *size)
  90 {
  91         struct stat st;
  92         char *p = NULL;
  93         int status = 0;
  94         int fd = -1;
  95 
  96         /* Load FILEMAP contents */
  97         status = -2;
  98         if ((fd = open(file, OPENMODE)) < 0)
  99                 goto err;
 100         status = -3;
 101         if (fstat(fd, &st) < 0)
 102                 goto err;
 103         status = -1;
 104         if ((p = (char *)malloc(st.st_size)) == NULL)
 105                 goto err;
 106         status = -4;
 107         if (read(fd, p, st.st_size) != st.st_size)
 108                 goto err;
 109         close(fd);
 110         *area = p;
 111         *size = st.st_size;
 112         return 0;
 113 err:
 114         if (fd != -1)
 115                 close(fd);
 116         if (p != NULL)
 117                 free(p);
 118         return status;
 119 }
 120 
 121 /**
 122  * comparison function for @CODE{bsearch()}.
 123  */
 124 static int
 125 cmp(const void *s1, const void *s2)
 126 {
 127         return strcmp(((struct map *)s1)->name, ((struct map *)s2)->name);
 128 }
 129 /**
 130  * creates index for in core FILEMAP.
 131  *
 132  *      @param[in]      area    filemap contents
 133  *      @param[in]      size    size of @a area
 134  *      @param[out]     map     map structure
 135  *      @param[out]     lines   @a map lines
 136  *      @return  0: succesful <br>
 137  *              -1: out of memory. <br>
 138  *              -5: illegal format.
 139  */
 140 static int
 141 create_filemap_index(char *area, int size, struct map **map, int *lines)
 142 {
 143         char *p, *endp = area + size;
 144         struct map *m;
 145         int n = 0;
 146         int status;
 147         int i;
 148 
 149         /* Count line number */
 150         for (p = area; p < endp; p++)
 151                 if (*p == '\n')
 152                         n++; 
 153         status = -1;
 154         if ((m = (struct map *)malloc(sizeof(struct map) * n)) == NULL)
 155                 return -1;
 156         /*
 157          * FILEMAP format:
 158          * <NAME>\t<PATH>\n
 159          */
 160         p = area;
 161         for (i = 0; i < n; i++) {
 162                 m[i].name = p;
 163                 while (*p && *p != '\t')
 164                         p++;
 165                 if (*p == '\0')
 166                         goto ferr;
 167                 *p++ = '\0';
 168                 m[i].path = p;
 169                 while (*p && *p != '\r' && *p != '\n')
 170                         p++;
 171                 if (*p == '\0')
 172                         goto ferr;
 173                 if (*p == '\r')
 174                         *p++ = '\0';
 175                 if (*p == '\n')
 176                         *p++ = '\0';
 177         }
 178         qsort(m, n, sizeof(struct map), cmp);
 179         *map = m;
 180         *lines = n;
 181         return 0;
 182 ferr:
 183         free(m);
 184         return -5;
 185 }
 186 
 187 /**
 188  * unloads FILEMAP.
 189  */
 190 static void
 191 unload_filemap(void)
 192 {
 193         (void)free(global_map);
 194         global_map = NULL;
 195         (void)free(global_contents);
 196         global_contents = NULL;
 197 }
 198 /*----------------------------------------------------------------------*/
 199 /* Global functions                                                     */
 200 /*----------------------------------------------------------------------*/
 201 /**
 202  * loads FILEMAP.
 203  *
 204  *      @param[in]      filemap FILEMAP file
 205  *      @par Globals used (output):
 206  *              #global_contents        filemap contents (for free) <br>
 207  *              #global_map     filemap index. <br>
 208  *              #global_maplines        lines of filemap index.
 209  *
 210  *      @return          0: succesful <br>
 211  *                      -1: out of memory. <br>
 212  *                      -2: FILEMAP not found. <br>
 213  *                      -3: cannot fstat FILEMAP. <br>
 214  *                      -4: cannot read FILEMAP. <br>
 215  *                      -5: format error.
 216  */
 217 int
 218 htags_load_filemap(const char *filemap)
 219 {
 220         int status = 0;
 221         char *area;
 222         int size, lines;
 223         struct map *map;
 224 
 225         status = load_filemap_contents(filemap, &area, &size);
 226         if (status < 0)
 227                 return status;
 228         status = create_filemap_index(area, size, &map, &lines);
 229         if (status < 0) {
 230                 (void)free(area);
 231                 return status;
 232         }
 233         global_contents = area;
 234         global_map = map;
 235         global_maplines = lines;
 236         return 0;
 237 }
 238 /**
 239  * unloads FILEMAP.
 240  */
 241 void
 242 htags_unload_filemap(void)
 243 {
 244         unload_filemap();
 245 }
 246 
 247 /**
 248  * convert file path name into the URL in the hypertext.
 249  *
 250  *      @param[in]      path    path name in the filesystem.
 251  *      @param[in]      line    0: ignored, !=0: line number in @a path.
 252  *      @param[out]     url     result url
 253  *      @param[in]      size    size of @a url
 254  *      @par Globals used (input):
 255  *              #global_contents        filemap contents (for free) <br>
 256  *              #global_map     filemap index. <br>
 257  *              #global_maplines        lines of filemap index.
 258  *
 259  *      @return         0: succesful <br>
 260  *                      1: path not found <br>
 261  *                      -1: filemap not loaded yet
 262  *
 263  * URL: @CODE{S/\<file id\>.html\#\<line number\>}
 264  */
 265 int
 266 htags_path2url(const char *path, int line, char *url, int size)
 267 {
 268         struct map tmp;
 269         struct map *result;
 270 
 271         if (global_contents == NULL || global_map == NULL)
 272                 return -1;
 273         tmp.name = path;
 274         result = (struct map *)bsearch(&tmp, global_map, global_maplines, sizeof(struct map), cmp);
 275         if (result == NULL)
 276                 return 1;
 277         if (line > 0)
 278                 snprintf(url, size, "%s#L%d", result->path, line);
 279         else
 280                 snprintf(url, size, "%s", result->path);
 281         return 0;
 282 }
 283 
 284 #ifdef TEST
 285 
 286 /**
 287  * @par Usage:
 288  * @NAME{htags_path2url} @ARG{filemap} @ARG{path} [@ARG{line}]
 289  *
 290  * @par Examples:
 291  * @code
 292  * $ htags_path2url HTML/FILEMAP i386/i386/identcpu.c 120
 293  * i386/i386/identcpu.c, line 120 => S/1238.html#L120
 294  * $ _
 295  * @endcode
 296  */
 297 int
 298 main(int argc, char **argv)
 299 {
 300         char url[MAXPATHLEN];
 301         char *path, *html;
 302         int line = 0;
 303         int ret;
 304 
 305         if (argc < 3) {
 306                 fprintf(stderr, "Usage: htags_path2url filemap path [line]\n");
 307                 exit(1);
 308         }
 309         html = argv[1];
 310         path = argv[2];
 311         if (argc > 3)
 312                 line = atoi(argv[3]);
 313         ret = htags_load_filemap(html);
 314         if (ret != 0) {
 315                 fprintf(stderr, "htags_load_filemap failed.(");
 316                 switch (ret) {
 317                 case -1: fprintf(stderr, "out of memory"); break;
 318                 case -2: fprintf(stderr, "FILEMAP not found."); break;
 319                 case -3: fprintf(stderr, "cannot fstat FILEMAP."); break;
 320                 case -4: fprintf(stderr, "cannot read FILEMAP."); break;
 321                 case -5: fprintf(stderr, "format error."); break;
 322                 default: fprintf(stderr, "unknown error."); break;
 323                 }
 324                 fprintf(stderr, ")\n");
 325                 exit(1);
 326         }
 327         ret = htags_path2url(path, line, url, sizeof(url));
 328         if (ret != 0) {
 329                 fprintf(stderr, "htags_path2url failed.(");
 330                 switch (ret) {
 331                 case  1: fprintf(stderr, "path not found."); break;
 332                 case -1: fprintf(stderr, "out of memory."); break;
 333                 }
 334                 fprintf(stderr, ")\n");
 335                 exit(1);
 336         }
 337         fprintf(stdout, "%s, line %d => %s\n", path, line, url);
 338         htags_unload_filemap();
 339         return 0;
 340 }
 341 #endif

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