root/src/editor/etags.c

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

DEFINITIONS

This source file includes following definitions.
  1. parse_define
  2. etags_set_definition_hash

   1 /*
   2    Editor C-code navigation via tags.
   3    make TAGS file via command:
   4    $ find . -type f -name "*.[ch]" | etags -l c --declarations -
   5 
   6    or, if etags utility not installed:
   7    $ find . -type f -name "*.[ch]" | ctags --c-kinds=+p --fields=+iaS --extra=+q -e -L-
   8 
   9    Copyright (C) 2009-2019
  10    Free Software Foundation, Inc.
  11 
  12    Written by:
  13    Ilia Maslakov <il.smind@gmail.com>, 2009
  14    Slava Zanko <slavazanko@gmail.com>, 2009
  15 
  16    This file is part of the Midnight Commander.
  17 
  18    The Midnight Commander is free software: you can redistribute it
  19    and/or modify it under the terms of the GNU General Public License as
  20    published by the Free Software Foundation, either version 3 of the License,
  21    or (at your option) any later version.
  22 
  23    The Midnight Commander is distributed in the hope that it will be useful,
  24    but WITHOUT ANY WARRANTY; without even the implied warranty of
  25    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  26    GNU General Public License for more details.
  27 
  28    You should have received a copy of the GNU General Public License
  29    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  30  */
  31 
  32 #include <config.h>
  33 
  34 #include <stdlib.h>
  35 #include <stdio.h>
  36 #include <inttypes.h>
  37 #include <string.h>
  38 #include <ctype.h>
  39 
  40 #include "lib/global.h"
  41 #include "lib/util.h"           /* canonicalize_pathname() */
  42 
  43 #include "etags.h"
  44 
  45 /*** global variables ****************************************************************************/
  46 
  47 /*** file scope macro definitions ****************************************************************/
  48 
  49 /*** file scope type declarations ****************************************************************/
  50 
  51 /*** file scope variables ************************************************************************/
  52 
  53 /*** file scope functions ************************************************************************/
  54 /* --------------------------------------------------------------------------------------------- */
  55 
  56 static gboolean
  57 parse_define (const char *buf, char **long_name, char **short_name, long *line)
     /* [previous][next][first][last][top][bottom][index][help]  */
  58 {
  59     /* *INDENT-OFF* */
  60     enum
  61     {
  62         in_longname,
  63         in_shortname,
  64         in_shortname_first_char,
  65         in_line, finish
  66     } def_state = in_longname;
  67     /* *INDENT-ON* */
  68 
  69     static char longdef[LONG_DEF_LEN];
  70     static char shortdef[SHORT_DEF_LEN];
  71     static char linedef[LINE_DEF_LEN];
  72     int nlong = 0;
  73     int nshort = 0;
  74     int nline = 0;
  75     char c = *buf;
  76 
  77     while (!(c == '\0' || c == '\n'))
  78     {
  79         switch (def_state)
  80         {
  81         case in_longname:
  82             if (c == 0x01)
  83             {
  84                 def_state = in_line;
  85             }
  86             else if (c == 0x7F)
  87             {
  88                 def_state = in_shortname;
  89             }
  90             else
  91             {
  92                 if (nlong < LONG_DEF_LEN - 1)
  93                 {
  94                     longdef[nlong++] = c;
  95                 }
  96             }
  97             break;
  98         case in_shortname_first_char:
  99             if (isdigit (c))
 100             {
 101                 nshort = 0;
 102                 buf--;
 103                 def_state = in_line;
 104             }
 105             else if (c == 0x01)
 106             {
 107                 def_state = in_line;
 108             }
 109             else
 110             {
 111                 if (nshort < SHORT_DEF_LEN - 1)
 112                 {
 113                     shortdef[nshort++] = c;
 114                     def_state = in_shortname;
 115                 }
 116             }
 117             break;
 118         case in_shortname:
 119             if (c == 0x01)
 120             {
 121                 def_state = in_line;
 122             }
 123             else if (c == '\n')
 124             {
 125                 def_state = finish;
 126             }
 127             else
 128             {
 129                 if (nshort < SHORT_DEF_LEN - 1)
 130                 {
 131                     shortdef[nshort++] = c;
 132                 }
 133             }
 134             break;
 135         case in_line:
 136             if (c == ',' || c == '\n')
 137             {
 138                 def_state = finish;
 139             }
 140             else if (isdigit (c))
 141             {
 142                 if (nline < LINE_DEF_LEN - 1)
 143                 {
 144                     linedef[nline++] = c;
 145                 }
 146             }
 147             break;
 148         case finish:
 149             longdef[nlong] = '\0';
 150             shortdef[nshort] = '\0';
 151             linedef[nline] = '\0';
 152             *long_name = longdef;
 153             *short_name = shortdef;
 154             *line = atol (linedef);
 155             return TRUE;
 156         default:
 157             break;
 158         }
 159         buf++;
 160         c = *buf;
 161     }
 162     *long_name = NULL;
 163     *short_name = NULL;
 164     *line = 0;
 165     return FALSE;
 166 }
 167 
 168 /* --------------------------------------------------------------------------------------------- */
 169 /*** public functions ****************************************************************************/
 170 /* --------------------------------------------------------------------------------------------- */
 171 
 172 int
 173 etags_set_definition_hash (const char *tagfile, const char *start_path,
     /* [previous][next][first][last][top][bottom][index][help]  */
 174                            const char *match_func, etags_hash_t * def_hash)
 175 {
 176     /* *INDENT-OFF* */
 177     enum
 178     {
 179         start,
 180         in_filename,
 181         in_define
 182     } state = start;
 183     /* *INDENT-ON* */
 184 
 185     FILE *f;
 186     char buf[BUF_LARGE];
 187 
 188     char *chekedstr = NULL;
 189 
 190     int num = 0;                /* returned value */
 191     char *filename = NULL;
 192 
 193     if (!match_func || !tagfile)
 194         return 0;
 195 
 196     /* open file with positions */
 197     f = fopen (tagfile, "r");
 198     if (f == NULL)
 199         return 0;
 200 
 201     while (fgets (buf, sizeof (buf), f))
 202     {
 203         switch (state)
 204         {
 205         case start:
 206             if (buf[0] == 0x0C)
 207             {
 208                 state = in_filename;
 209             }
 210             break;
 211         case in_filename:
 212             {
 213                 size_t pos;
 214 
 215                 pos = strcspn (buf, ",");
 216                 g_free (filename);
 217                 filename = g_strndup (buf, pos);
 218                 state = in_define;
 219                 break;
 220             }
 221         case in_define:
 222             if (buf[0] == 0x0C)
 223             {
 224                 state = in_filename;
 225                 break;
 226             }
 227             /* check if the filename matches the define pos */
 228             chekedstr = strstr (buf, match_func);
 229             if (chekedstr)
 230             {
 231                 char *longname = NULL;
 232                 char *shortname = NULL;
 233                 long line = 0;
 234 
 235                 parse_define (chekedstr, &longname, &shortname, &line);
 236                 if (num < MAX_DEFINITIONS - 1)
 237                 {
 238                     def_hash[num].filename_len = strlen (filename);
 239                     def_hash[num].fullpath =
 240                         mc_build_filename (start_path, filename, (char *) NULL);
 241 
 242                     canonicalize_pathname (def_hash[num].fullpath);
 243                     def_hash[num].filename = g_strdup (filename);
 244                     def_hash[num].short_define = g_strdup (shortname ? shortname : longname);
 245                     def_hash[num].line = line;
 246                     num++;
 247                 }
 248             }
 249             break;
 250         default:
 251             break;
 252         }
 253     }
 254 
 255     g_free (filename);
 256     fclose (f);
 257     return num;
 258 }
 259 
 260 /* --------------------------------------------------------------------------------------------- */

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