etags.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. /* editor C-code navigation via tags.
  2. make TAGS file via command:
  3. $ find . -type f -name "*.[ch]" | etags -l c --declarations -
  4. or, if etags utility not installed:
  5. $ find . -type f -name "*.[ch]" | ctags --c-kinds=+p --fields=+iaS --extra=+q -e -L-
  6. Copyright (C) 2009 Free Software Foundation, Inc.
  7. Authors:
  8. Ilia Maslakov <il.smind@gmail.com>, 2009
  9. Slava Zanko <slavazanko@gmail.com>, 2009
  10. This file is part of the Midnight Commander.
  11. The Midnight Commander is free software; you can redistribute it
  12. and/or modify it under the terms of the GNU General Public License as
  13. published by the Free Software Foundation; either version 2 of the
  14. License, or (at your option) any later version.
  15. The Midnight Commander is distributed in the hope that it will be
  16. useful, but WITHOUT ANY WARRANTY; without even the implied warranty
  17. of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18. General Public License for more details.
  19. You should have received a copy of the GNU General Public License
  20. along with this program; if not, write to the Free Software
  21. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  22. MA 02110-1301, USA.
  23. */
  24. #include <config.h>
  25. #include <stdlib.h>
  26. #include <stdio.h>
  27. #include <inttypes.h>
  28. #include <string.h>
  29. #include <ctype.h>
  30. #include "../src/global.h"
  31. #include "../src/util.h" /* canonicalize_pathname() */
  32. #include "../edit/etags.h"
  33. /*** file scope functions **********************************************/
  34. static gboolean parse_define(char *buf, char **long_name, char **short_name, long *line)
  35. {
  36. enum {in_longname, in_shortname, in_line, finish} def_state = in_longname;
  37. static char longdef[LONG_DEF_LEN];
  38. static char shortdef[SHORT_DEF_LEN];
  39. static char linedef[LINE_DEF_LEN];
  40. int nlong = 0;
  41. int nshort = 0;
  42. int nline = 0;
  43. char c = *buf;
  44. while ( !(c =='\0' || c =='\n') ) {
  45. switch ( def_state ) {
  46. case in_longname:
  47. if ( c == 0x01 ) {
  48. def_state = in_line;
  49. } else if ( c == 0x7F ) {
  50. def_state = in_shortname;
  51. } else {
  52. if ( nlong < LONG_DEF_LEN - 1 ) {
  53. longdef[nlong++] = c;
  54. }
  55. }
  56. break;
  57. case in_shortname:
  58. if ( isdigit(c) ) {
  59. nshort = 0;
  60. buf--;
  61. def_state = in_line;
  62. } else if ( c == 0x01 ) {
  63. def_state = in_line;
  64. } else {
  65. if ( nshort < SHORT_DEF_LEN - 1 ) {
  66. shortdef[nshort++] = c;
  67. }
  68. }
  69. break;
  70. case in_line:
  71. if ( c == ',' ) {
  72. def_state = finish;
  73. } else if ( isdigit(c) ) {
  74. if ( nline < LINE_DEF_LEN - 1 ) {
  75. linedef[nline++] = c;
  76. }
  77. }
  78. break;
  79. case finish:
  80. longdef[nlong] = '\0';
  81. shortdef[nshort] = '\0';
  82. linedef[nline] = '\0';
  83. *long_name = g_strdup (longdef);
  84. *short_name = g_strdup (shortdef);
  85. *line = atol (linedef);
  86. return TRUE;
  87. break;
  88. }
  89. buf++;
  90. c = *buf;
  91. }
  92. *long_name = NULL;
  93. *short_name = NULL;
  94. *line = 0;
  95. return FALSE;
  96. }
  97. /*** public functions **************************************************/
  98. int etags_set_definition_hash(const char *tagfile, const char *start_path,
  99. const char *match_func,
  100. etags_hash_t *def_hash)
  101. {
  102. enum {start, in_filename, in_define} state = start;
  103. FILE *f;
  104. static char buf[BUF_LARGE];
  105. char *longname = NULL;
  106. char *shortname = NULL;
  107. long line;
  108. char *chekedstr = NULL;
  109. int num = 0; /* returned value */
  110. int pos;
  111. char *filename = NULL;
  112. /* open file with positions */
  113. f = fopen (tagfile, "r");
  114. if (!f)
  115. return 0;
  116. while (fgets (buf, sizeof (buf), f)) {
  117. switch ( state ) {
  118. case start:
  119. if ( buf[0] == 0x0C ) {
  120. state = in_filename;
  121. }
  122. break;
  123. case in_filename:
  124. pos = strcspn(buf, ",");
  125. g_free(filename);
  126. filename = g_malloc (pos + 2);
  127. g_strlcpy(filename, (char *)buf, pos + 1);
  128. state = in_define;
  129. break;
  130. case in_define:
  131. if ( buf[0] == 0x0C ) {
  132. state = in_filename;
  133. break;
  134. }
  135. /* check if the filename matches the define pos */
  136. chekedstr = strstr (buf, match_func);
  137. if ( chekedstr ) {
  138. parse_define (chekedstr, &longname, &shortname, &line);
  139. if ( num < MAX_DEFINITIONS - 1 ) {
  140. def_hash[num].filename_len = strlen (filename);
  141. def_hash[num].fullpath = g_build_filename ( start_path, filename, (char *) NULL);
  142. canonicalize_pathname (def_hash[num].fullpath);
  143. def_hash[num].filename = g_strdup (filename);
  144. if ( shortname ) {
  145. def_hash[num].short_define = g_strdup (shortname);
  146. } else {
  147. def_hash[num].short_define = g_strdup (longname);
  148. }
  149. def_hash[num].line = line;
  150. g_free(shortname);
  151. g_free(longname);
  152. num++;
  153. }
  154. }
  155. break;
  156. }
  157. }
  158. g_free(filename);
  159. return num;
  160. }