keymap files: unification of Fxx keys: move to lower case.
[midnight-commander.git] / src / editor / etags.c
blobd707c167bf9bd3756c827822a21844ccddaeaa18
1 /* editor C-code navigation via tags.
2 make TAGS file via command:
3 $ find . -type f -name "*.[ch]" | etags -l c --declarations -
5 or, if etags utility not installed:
6 $ find . -type f -name "*.[ch]" | ctags --c-kinds=+p --fields=+iaS --extra=+q -e -L-
8 Copyright (C) 2009 Free Software Foundation, Inc.
10 Authors:
11 Ilia Maslakov <il.smind@gmail.com>, 2009
12 Slava Zanko <slavazanko@gmail.com>, 2009
15 This file is part of the Midnight Commander.
17 The Midnight Commander is free software; you can redistribute it
18 and/or modify it under the terms of the GNU General Public License as
19 published by the Free Software Foundation; either version 2 of the
20 License, or (at your option) any later version.
22 The Midnight Commander is distributed in the hope that it will be
23 useful, but WITHOUT ANY WARRANTY; without even the implied warranty
24 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 General Public License for more details.
27 You should have received a copy of the GNU General Public License
28 along with this program; if not, write to the Free Software
29 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
30 MA 02110-1301, USA.
33 #include <config.h>
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <inttypes.h>
38 #include <string.h>
39 #include <ctype.h>
41 #include "lib/global.h"
42 #include "lib/util.h" /* canonicalize_pathname() */
44 #include "etags.h"
46 /*** global variables ****************************************************************************/
48 /*** file scope macro definitions ****************************************************************/
50 /*** file scope type declarations ****************************************************************/
52 /*** file scope variables ************************************************************************/
54 /*** file scope functions ************************************************************************/
55 /* --------------------------------------------------------------------------------------------- */
57 static gboolean
58 parse_define (char *buf, char **long_name, char **short_name, long *line)
60 /* *INDENT-OFF* */
61 enum
63 in_longname,
64 in_shortname,
65 in_shortname_first_char,
66 in_line, finish
67 } def_state = in_longname;
68 /* *INDENT-ON* */
70 static char longdef[LONG_DEF_LEN];
71 static char shortdef[SHORT_DEF_LEN];
72 static char linedef[LINE_DEF_LEN];
73 int nlong = 0;
74 int nshort = 0;
75 int nline = 0;
76 char c = *buf;
78 while (!(c == '\0' || c == '\n'))
80 switch (def_state)
82 case in_longname:
83 if (c == 0x01)
85 def_state = in_line;
87 else if (c == 0x7F)
89 def_state = in_shortname;
91 else
93 if (nlong < LONG_DEF_LEN - 1)
95 longdef[nlong++] = c;
98 break;
99 case in_shortname_first_char:
100 if (isdigit (c))
102 nshort = 0;
103 buf--;
104 def_state = in_line;
106 else if (c == 0x01)
108 def_state = in_line;
110 else
112 if (nshort < SHORT_DEF_LEN - 1)
114 shortdef[nshort++] = c;
115 def_state = in_shortname;
118 break;
119 case in_shortname:
120 if (c == 0x01)
122 def_state = in_line;
124 else if (c == '\n')
126 def_state = finish;
128 else
130 if (nshort < SHORT_DEF_LEN - 1)
132 shortdef[nshort++] = c;
135 break;
136 case in_line:
137 if (c == ',' || c == '\n')
139 def_state = finish;
141 else if (isdigit (c))
143 if (nline < LINE_DEF_LEN - 1)
145 linedef[nline++] = c;
148 break;
149 case finish:
150 longdef[nlong] = '\0';
151 shortdef[nshort] = '\0';
152 linedef[nline] = '\0';
153 *long_name = longdef;
154 *short_name = shortdef;
155 *line = atol (linedef);
156 return TRUE;
158 buf++;
159 c = *buf;
161 *long_name = NULL;
162 *short_name = NULL;
163 *line = 0;
164 return FALSE;
167 /* --------------------------------------------------------------------------------------------- */
168 /*** public functions ****************************************************************************/
169 /* --------------------------------------------------------------------------------------------- */
172 etags_set_definition_hash (const char *tagfile, const char *start_path,
173 const char *match_func, etags_hash_t * def_hash)
175 /* *INDENT-OFF* */
176 enum
178 start,
179 in_filename,
180 in_define
181 } state = start;
182 /* *INDENT-ON* */
184 FILE *f;
185 static char buf[BUF_LARGE];
187 char *chekedstr = NULL;
189 int num = 0; /* returned value */
190 int pos;
191 char *filename = NULL;
193 if (!match_func || !tagfile)
194 return 0;
196 /* open file with positions */
197 f = fopen (tagfile, "r");
198 if (f == NULL)
199 return 0;
201 while (fgets (buf, sizeof (buf), f))
203 switch (state)
205 case start:
206 if (buf[0] == 0x0C)
208 state = in_filename;
210 break;
211 case in_filename:
212 pos = strcspn (buf, ",");
213 g_free (filename);
214 filename = g_malloc (pos + 2);
215 g_strlcpy (filename, (char *) buf, pos + 1);
216 state = in_define;
217 break;
218 case in_define:
219 if (buf[0] == 0x0C)
221 state = in_filename;
222 break;
224 /* check if the filename matches the define pos */
225 chekedstr = strstr (buf, match_func);
226 if (chekedstr)
228 char *longname = NULL;
229 char *shortname = NULL;
230 long line = 0;
232 parse_define (chekedstr, &longname, &shortname, &line);
233 if (num < MAX_DEFINITIONS - 1)
235 def_hash[num].filename_len = strlen (filename);
236 def_hash[num].fullpath = mc_build_filename (start_path, filename, (char *) NULL);
238 canonicalize_pathname (def_hash[num].fullpath);
239 def_hash[num].filename = g_strdup (filename);
240 if (shortname)
242 def_hash[num].short_define = g_strdup (shortname);
244 else
246 def_hash[num].short_define = g_strdup (longname);
248 def_hash[num].line = line;
249 num++;
252 break;
256 g_free (filename);
257 fclose (f);
258 return num;
261 /* --------------------------------------------------------------------------------------------- */