Create branch for 0.19.1 release (copied from 0.19).
[geany-mirror.git] / tagmanager / tm_tag.c
blob25249c01c44c11d797e377a68c2692c643fc40ea
1 /*
3 * Copyright (c) 2001-2002, Biswapesh Chattopadhyay
5 * This source code is released for free distribution under the terms of the
6 * GNU General Public License.
8 */
10 #include <stdlib.h>
11 #include <string.h>
13 #include "general.h"
14 #include "entry.h"
15 #include "parse.h"
16 #include "read.h"
17 #define LIBCTAGS_DEFINED
18 #include "tm_tag.h"
21 #if GLIB_CHECK_VERSION (2, 10, 0)
22 /* Use GSlices if present */
24 #define TAG_NEW(T) ((T) = g_slice_new0(TMTag))
25 #define TAG_FREE(T) g_slice_free(TMTag, (T))
27 #else /* GLib < 2.10 */
29 static GMemChunk *s_tag_mem_chunk = NULL;
31 #define TAG_NEW(T) {\
32 if (!s_tag_mem_chunk) \
33 s_tag_mem_chunk = g_mem_chunk_new("TMTag memChunk", sizeof(TMTag), 1024 \
34 , G_ALLOC_AND_FREE); \
35 (T) = g_chunk_new0(TMTag, s_tag_mem_chunk);}
37 #define TAG_FREE(T) g_mem_chunk_free(s_tag_mem_chunk, (T))
39 #endif /* GLib version check */
42 /* Note: To preserve binary compatibility, it is very important
43 that you only *append* to this list ! */
44 enum
46 TA_NAME = 200,
47 TA_LINE,
48 TA_LOCAL,
49 TA_POS, /* Obsolete */
50 TA_TYPE,
51 TA_ARGLIST,
52 TA_SCOPE,
53 TA_VARTYPE,
54 TA_INHERITS,
55 TA_TIME,
56 TA_ACCESS,
57 TA_IMPL,
58 TA_LANG,
59 TA_INACTIVE,
60 TA_POINTER
63 static guint *s_sort_attrs = NULL;
64 static gboolean s_partial = FALSE;
66 static const char *s_tag_type_names[] = {
67 "class", /* classes */
68 "enum", /* enumeration names */
69 "enumerator", /* enumerators (values inside an enumeration) */
70 "externvar", /* external variable declarations */
71 "field", /* fields */
72 "function", /* function definitions */
73 "interface", /* interfaces */
74 "macro", /* macro definitions */
75 "member", /* class, struct, and union members */
76 "method", /* methods */
77 "namespace", /* namespaces */
78 "package", /* packages */
79 "prototype", /* function prototypes */
80 "struct", /* structure names */
81 "typedef", /* typedefs */
82 "union", /* union names */
83 "variable", /* variable definitions */
84 "other" /* Other tag type (non C/C++/Java) */
87 static int s_tag_types[] = {
88 tm_tag_class_t,
89 tm_tag_enum_t,
90 tm_tag_enumerator_t,
91 tm_tag_externvar_t,
92 tm_tag_field_t,
93 tm_tag_function_t,
94 tm_tag_interface_t,
95 tm_tag_macro_t,
96 tm_tag_member_t,
97 tm_tag_method_t,
98 tm_tag_namespace_t,
99 tm_tag_package_t,
100 tm_tag_prototype_t,
101 tm_tag_struct_t,
102 tm_tag_typedef_t,
103 tm_tag_union_t,
104 tm_tag_variable_t,
105 tm_tag_other_t
108 static int get_tag_type(const char *tag_name)
110 unsigned int i;
111 int cmp;
112 g_return_val_if_fail(tag_name, 0);
113 for (i=0; i < sizeof(s_tag_type_names)/sizeof(char *); ++i)
115 cmp = strcmp(tag_name, s_tag_type_names[i]);
116 if (0 == cmp)
117 return s_tag_types[i];
118 else if (cmp < 0)
119 break;
121 /* other is not checked above as it is last, not sorted alphabetically */
122 if (strcmp(tag_name, "other") == 0)
123 return tm_tag_other_t;
124 #ifdef TM_DEBUG
125 fprintf(stderr, "Unknown tag type %s\n", tag_name);
126 #endif
127 return tm_tag_undef_t;
130 gboolean tm_tag_init(TMTag *tag, TMSourceFile *file, const tagEntryInfo *tag_entry)
132 if (NULL == tag_entry)
134 /* This is a file tag */
135 if (NULL == file)
136 return FALSE;
137 else
139 tag->name = g_strdup(file->work_object.file_name);
140 tag->type = tm_tag_file_t;
141 /* tag->atts.file.timestamp = file->work_object.analyze_time; */
142 tag->atts.file.lang = file->lang;
143 tag->atts.file.inactive = FALSE;
144 return TRUE;
147 else
149 /* This is a normal tag entry */
150 if (NULL == tag_entry->name)
151 return FALSE;
152 tag->name = g_strdup(tag_entry->name);
153 tag->type = get_tag_type(tag_entry->kindName);
154 tag->atts.entry.local = tag_entry->isFileScope;
155 tag->atts.entry.pointerOrder = 0; /* backward compatibility (use var_type instead) */
156 tag->atts.entry.line = tag_entry->lineNumber;
157 if (NULL != tag_entry->extensionFields.arglist)
158 tag->atts.entry.arglist = g_strdup(tag_entry->extensionFields.arglist);
159 if ((NULL != tag_entry->extensionFields.scope[1]) &&
160 (isalpha(tag_entry->extensionFields.scope[1][0]) ||
161 tag_entry->extensionFields.scope[1][0] == '_'))
162 tag->atts.entry.scope = g_strdup(tag_entry->extensionFields.scope[1]);
163 if (tag_entry->extensionFields.inheritance != NULL)
164 tag->atts.entry.inheritance = g_strdup(tag_entry->extensionFields.inheritance);
165 if (tag_entry->extensionFields.varType != NULL)
166 tag->atts.entry.var_type = g_strdup(tag_entry->extensionFields.varType);
167 if (tag_entry->extensionFields.access != NULL)
169 if (0 == strcmp("public", tag_entry->extensionFields.access))
170 tag->atts.entry.access = TAG_ACCESS_PUBLIC;
171 else if (0 == strcmp("protected", tag_entry->extensionFields.access))
172 tag->atts.entry.access = TAG_ACCESS_PROTECTED;
173 else if (0 == strcmp("private", tag_entry->extensionFields.access))
174 tag->atts.entry.access = TAG_ACCESS_PRIVATE;
175 else if (0 == strcmp("friend", tag_entry->extensionFields.access))
176 tag->atts.entry.access = TAG_ACCESS_FRIEND;
177 else if (0 == strcmp("default", tag_entry->extensionFields.access))
178 tag->atts.entry.access = TAG_ACCESS_DEFAULT;
179 else
181 #ifdef TM_DEBUG
182 g_warning("Unknown access type %s", tag_entry->extensionFields.access);
183 #endif
184 tag->atts.entry.access = TAG_ACCESS_UNKNOWN;
187 if (tag_entry->extensionFields.implementation != NULL)
189 if ((0 == strcmp("virtual", tag_entry->extensionFields.implementation))
190 || (0 == strcmp("pure virtual", tag_entry->extensionFields.implementation)))
191 tag->atts.entry.impl = TAG_IMPL_VIRTUAL;
192 else
194 #ifdef TM_DEBUG
195 g_warning("Unknown implementation %s", tag_entry->extensionFields.implementation);
196 #endif
197 tag->atts.entry.impl = TAG_IMPL_UNKNOWN;
200 if ((tm_tag_macro_t == tag->type) && (NULL != tag->atts.entry.arglist))
201 tag->type = tm_tag_macro_with_arg_t;
202 tag->atts.entry.file = file;
203 return TRUE;
207 TMTag *tm_tag_new(TMSourceFile *file, const tagEntryInfo *tag_entry)
209 TMTag *tag;
211 TAG_NEW(tag);
212 if (FALSE == tm_tag_init(tag, file, tag_entry))
214 TAG_FREE(tag);
215 return NULL;
217 return tag;
220 gboolean tm_tag_init_from_file(TMTag *tag, TMSourceFile *file, FILE *fp)
222 guchar buf[BUFSIZ];
223 guchar *start, *end;
224 gboolean status;
225 guchar changed_char = TA_NAME;
227 if ((NULL == fgets((gchar*)buf, BUFSIZ, fp)) || ('\0' == *buf))
228 return FALSE;
229 for (start = end = buf, status = TRUE; (TRUE == status); start = end, ++ end)
231 while ((*end < TA_NAME) && (*end != '\0') && (*end != '\n'))
232 ++ end;
233 if (('\0' == *end) || ('\n' == *end))
234 status = FALSE;
235 changed_char = *end;
236 *end = '\0';
237 if (NULL == tag->name)
239 if (!isprint(*start))
240 return FALSE;
241 else
242 tag->name = g_strdup((gchar*)start);
244 else
246 switch (*start)
248 case TA_LINE:
249 tag->atts.entry.line = atol((gchar*)start + 1);
250 break;
251 case TA_LOCAL:
252 tag->atts.entry.local = atoi((gchar*)start + 1);
253 break;
254 case TA_TYPE:
255 tag->type = (TMTagType) atoi((gchar*)start + 1);
256 break;
257 case TA_ARGLIST:
258 tag->atts.entry.arglist = g_strdup((gchar*)start + 1);
259 break;
260 case TA_SCOPE:
261 tag->atts.entry.scope = g_strdup((gchar*)start + 1);
262 break;
263 case TA_POINTER:
264 tag->atts.entry.pointerOrder = atoi((gchar*)start + 1);
265 break;
266 case TA_VARTYPE:
267 tag->atts.entry.var_type = g_strdup((gchar*)start + 1);
268 break;
269 case TA_INHERITS:
270 tag->atts.entry.inheritance = g_strdup((gchar*)start + 1);
271 break;
272 case TA_TIME:
273 if (tm_tag_file_t != tag->type)
275 g_warning("Got time attribute for non-file tag %s", tag->name);
276 return FALSE;
278 else
279 tag->atts.file.timestamp = atol((gchar*)start + 1);
280 break;
281 case TA_LANG:
282 if (tm_tag_file_t != tag->type)
284 g_warning("Got lang attribute for non-file tag %s", tag->name);
285 return FALSE;
287 else
288 tag->atts.file.lang = atoi((gchar*)start + 1);
289 break;
290 case TA_INACTIVE:
291 if (tm_tag_file_t != tag->type)
293 g_warning("Got inactive attribute for non-file tag %s", tag->name);
294 return FALSE;
296 else
297 tag->atts.file.inactive = (gboolean) atoi((gchar*)start + 1);
298 break;
299 case TA_ACCESS:
300 tag->atts.entry.access = *(start + 1);
301 break;
302 case TA_IMPL:
303 tag->atts.entry.impl = *(start + 1);
304 break;
305 default:
306 #ifdef GEANY_DEBUG
307 g_warning("Unknown attribute %s", start + 1);
308 #endif
309 break;
312 *end = changed_char;
314 if (NULL == tag->name)
315 return FALSE;
316 if (tm_tag_file_t != tag->type)
317 tag->atts.entry.file = file;
318 return TRUE;
321 /* alternative parser for Pascal and LaTeX global tags files with the following format
322 * tagname|return value|arglist|description\n */
323 gboolean tm_tag_init_from_file_alt(TMTag *tag, TMSourceFile *file, FILE *fp)
325 guchar buf[BUFSIZ];
326 guchar *start, *end;
327 gboolean status;
328 /*guchar changed_char = TA_NAME;*/
330 if ((NULL == fgets((gchar*)buf, BUFSIZ, fp)) || ('\0' == *buf))
331 return FALSE;
333 gchar **fields;
334 guint field_len;
335 for (start = end = buf, status = TRUE; (TRUE == status); start = end, ++ end)
337 while ((*end < TA_NAME) && (*end != '\0') && (*end != '\n'))
338 ++ end;
339 if (('\0' == *end) || ('\n' == *end))
340 status = FALSE;
341 /*changed_char = *end;*/
342 *end = '\0';
343 if (NULL == tag->name && !isprint(*start))
344 return FALSE;
346 fields = g_strsplit((gchar*)start, "|", -1);
347 field_len = g_strv_length(fields);
349 if (field_len >= 1) tag->name = g_strdup(fields[0]);
350 else tag->name = NULL;
351 if (field_len >= 2 && fields[1] != NULL) tag->atts.entry.var_type = g_strdup(fields[1]);
352 if (field_len >= 3 && fields[2] != NULL) tag->atts.entry.arglist = g_strdup(fields[2]);
353 tag->type = tm_tag_prototype_t;
354 g_strfreev(fields);
358 if (NULL == tag->name)
359 return FALSE;
360 if (tm_tag_file_t != tag->type)
361 tag->atts.entry.file = file;
362 return TRUE;
365 TMTag *tm_tag_new_from_file(TMSourceFile *file, FILE *fp, gint mode, gboolean format_pipe)
367 TMTag *tag;
368 gboolean result;
370 TAG_NEW(tag);
372 if (format_pipe)
373 result = tm_tag_init_from_file_alt(tag, file, fp);
374 else
375 result = tm_tag_init_from_file(tag, file, fp);
377 if (! result)
379 TAG_FREE(tag);
380 return NULL;
382 tag->atts.file.lang = mode;
383 return tag;
386 gboolean tm_tag_write(TMTag *tag, FILE *fp, guint attrs)
388 fprintf(fp, "%s", tag->name);
389 if (attrs & tm_tag_attr_type_t)
390 fprintf(fp, "%c%d", TA_TYPE, tag->type);
391 if (tag->type == tm_tag_file_t)
393 if (attrs & tm_tag_attr_time_t)
394 fprintf(fp, "%c%ld", TA_TIME, tag->atts.file.timestamp);
395 if (attrs & tm_tag_attr_lang_t)
396 fprintf(fp, "%c%d", TA_LANG, tag->atts.file.lang);
397 if ((attrs & tm_tag_attr_inactive_t) && tag->atts.file.inactive)
398 fprintf(fp, "%c%d", TA_INACTIVE, tag->atts.file.inactive);
400 else
402 if ((attrs & tm_tag_attr_arglist_t) && (NULL != tag->atts.entry.arglist))
403 fprintf(fp, "%c%s", TA_ARGLIST, tag->atts.entry.arglist);
404 if (attrs & tm_tag_attr_line_t)
405 fprintf(fp, "%c%ld", TA_LINE, tag->atts.entry.line);
406 if (attrs & tm_tag_attr_local_t)
407 fprintf(fp, "%c%d", TA_LOCAL, tag->atts.entry.local);
408 if ((attrs & tm_tag_attr_scope_t) && (NULL != tag->atts.entry.scope))
409 fprintf(fp, "%c%s", TA_SCOPE, tag->atts.entry.scope);
410 if ((attrs & tm_tag_attr_inheritance_t) && (NULL != tag->atts.entry.inheritance))
411 fprintf(fp, "%c%s", TA_INHERITS, tag->atts.entry.inheritance);
412 if (attrs & tm_tag_attr_pointer_t)
413 fprintf(fp, "%c%d", TA_POINTER, tag->atts.entry.pointerOrder);
414 if ((attrs & tm_tag_attr_vartype_t) && (NULL != tag->atts.entry.var_type))
415 fprintf(fp, "%c%s", TA_VARTYPE, tag->atts.entry.var_type);
416 if ((attrs & tm_tag_attr_access_t) && (TAG_ACCESS_UNKNOWN != tag->atts.entry.access))
417 fprintf(fp, "%c%c", TA_ACCESS, tag->atts.entry.access);
418 if ((attrs & tm_tag_attr_impl_t) && (TAG_IMPL_UNKNOWN != tag->atts.entry.impl))
419 fprintf(fp, "%c%c", TA_IMPL, tag->atts.entry.impl);
421 if (fprintf(fp, "\n"))
422 return TRUE;
423 else
424 return FALSE;
427 static void tm_tag_destroy(TMTag *tag)
429 g_free(tag->name);
430 if (tm_tag_file_t != tag->type)
432 g_free(tag->atts.entry.arglist);
433 g_free(tag->atts.entry.scope);
434 g_free(tag->atts.entry.inheritance);
435 g_free(tag->atts.entry.var_type);
439 void tm_tag_free(gpointer tag)
441 if (NULL != tag)
443 tm_tag_destroy((TMTag *) tag);
444 TAG_FREE(tag);
448 int tm_tag_compare(const void *ptr1, const void *ptr2)
450 unsigned int *sort_attr;
451 int returnval = 0;
452 TMTag *t1 = *((TMTag **) ptr1);
453 TMTag *t2 = *((TMTag **) ptr2);
455 if ((NULL == t1) || (NULL == t2))
457 g_warning("Found NULL tag");
458 return t2 - t1;
460 if (NULL == s_sort_attrs)
462 if (s_partial)
463 return strncmp(NVL(t1->name, ""), NVL(t2->name, ""), strlen(NVL(t1->name, "")));
464 else
465 return strcmp(NVL(t1->name, ""), NVL(t2->name, ""));
468 for (sort_attr = s_sort_attrs; *sort_attr != tm_tag_attr_none_t; ++ sort_attr)
470 switch (*sort_attr)
472 case tm_tag_attr_name_t:
473 if (s_partial)
474 returnval = strncmp(NVL(t1->name, ""), NVL(t2->name, ""), strlen(NVL(t1->name, "")));
475 else
476 returnval = strcmp(NVL(t1->name, ""), NVL(t2->name, ""));
477 if (0 != returnval)
478 return returnval;
479 break;
480 case tm_tag_attr_type_t:
481 if (0 != (returnval = (t1->type - t2->type)))
482 return returnval;
483 break;
484 case tm_tag_attr_file_t:
485 if (0 != (returnval = (t1->atts.entry.file - t2->atts.entry.file)))
486 return returnval;
487 break;
488 case tm_tag_attr_scope_t:
489 if (0 != (returnval = strcmp(NVL(t1->atts.entry.scope, ""), NVL(t2->atts.entry.scope, ""))))
490 return returnval;
491 break;
492 case tm_tag_attr_arglist_t:
493 if (0 != (returnval = strcmp(NVL(t1->atts.entry.arglist, ""), NVL(t2->atts.entry.arglist, ""))))
495 int line_diff = (t1->atts.entry.line - t2->atts.entry.line);
497 return line_diff ? line_diff : returnval;
499 break;
500 case tm_tag_attr_vartype_t:
501 if (0 != (returnval = strcmp(NVL(t1->atts.entry.var_type, ""), NVL(t2->atts.entry.var_type, ""))))
502 return returnval;
503 break;
504 case tm_tag_attr_line_t:
505 if (0 != (returnval = (t1->atts.entry.line - t2->atts.entry.line)))
506 return returnval;
507 break;
510 return returnval;
513 gboolean tm_tags_prune(GPtrArray *tags_array)
515 guint i, count;
516 for (i=0, count = 0; i < tags_array->len; ++i)
518 if (NULL != tags_array->pdata[i])
519 tags_array->pdata[count++] = tags_array->pdata[i];
521 tags_array->len = count;
522 return TRUE;
525 gboolean tm_tags_dedup(GPtrArray *tags_array, TMTagAttrType *sort_attributes)
527 guint i;
529 if ((!tags_array) || (!tags_array->len))
530 return TRUE;
531 s_sort_attrs = sort_attributes;
532 s_partial = FALSE;
533 for (i = 1; i < tags_array->len; ++i)
535 if (0 == tm_tag_compare(&(tags_array->pdata[i - 1]), &(tags_array->pdata[i])))
537 tags_array->pdata[i-1] = NULL;
540 tm_tags_prune(tags_array);
541 return TRUE;
544 gboolean tm_tags_custom_dedup(GPtrArray *tags_array, TMTagCompareFunc compare_func)
546 guint i;
548 if ((!tags_array) || (!tags_array->len))
549 return TRUE;
550 for (i = 1; i < tags_array->len; ++i)
552 if (0 == compare_func(&(tags_array->pdata[i - 1]), &(tags_array->pdata[i])))
553 tags_array->pdata[i-1] = NULL;
555 tm_tags_prune(tags_array);
556 return TRUE;
559 gboolean tm_tags_sort(GPtrArray *tags_array, TMTagAttrType *sort_attributes, gboolean dedup)
561 if ((!tags_array) || (!tags_array->len))
562 return TRUE;
563 s_sort_attrs = sort_attributes;
564 s_partial = FALSE;
565 qsort(tags_array->pdata, tags_array->len, sizeof(gpointer), tm_tag_compare);
566 s_sort_attrs = NULL;
567 if (dedup)
568 tm_tags_dedup(tags_array, sort_attributes);
569 return TRUE;
572 gboolean tm_tags_custom_sort(GPtrArray *tags_array, TMTagCompareFunc compare_func, gboolean dedup)
574 if ((!tags_array) || (!tags_array->len))
575 return TRUE;
576 qsort(tags_array->pdata, tags_array->len, sizeof(gpointer), compare_func);
577 if (dedup)
578 tm_tags_custom_dedup(tags_array, compare_func);
579 return TRUE;
582 GPtrArray *tm_tags_extract(GPtrArray *tags_array, guint tag_types)
584 GPtrArray *new_tags;
585 guint i;
586 if (NULL == tags_array)
587 return NULL;
588 new_tags = g_ptr_array_new();
589 for (i=0; i < tags_array->len; ++i)
591 if (NULL != tags_array->pdata[i])
593 if (tag_types & (((TMTag *) tags_array->pdata[i])->type))
594 g_ptr_array_add(new_tags, tags_array->pdata[i]);
597 return new_tags;
600 void tm_tags_array_free(GPtrArray *tags_array, gboolean free_all)
602 if (tags_array)
604 guint i;
605 for (i = 0; i < tags_array->len; ++i)
606 tm_tag_free(tags_array->pdata[i]);
607 if (free_all)
608 g_ptr_array_free(tags_array, TRUE);
609 else
610 g_ptr_array_set_size(tags_array, 0);
614 TMTag **tm_tags_find(const GPtrArray *sorted_tags_array, const char *name,
615 gboolean partial, int * tagCount)
617 static TMTag *tag = NULL;
618 TMTag **result;
619 int tagMatches=0;
621 if ((!sorted_tags_array) || (!sorted_tags_array->len))
622 return NULL;
624 if (NULL == tag)
625 tag = g_new0(TMTag, 1);
626 tag->name = (char *) name;
627 s_sort_attrs = NULL;
628 s_partial = partial;
629 result = (TMTag **) bsearch(&tag, sorted_tags_array->pdata, sorted_tags_array->len
630 , sizeof(gpointer), tm_tag_compare);
631 /* There can be matches on both sides of result */
632 if (result)
634 TMTag **last = (TMTag **) &sorted_tags_array->pdata[sorted_tags_array->len - 1];
635 TMTag **adv;
637 /* First look for any matches after result */
638 adv = result;
639 adv++;
640 for (; adv <= last && *adv; ++ adv)
642 if (0 != tm_tag_compare(&tag, adv))
643 break;
644 ++tagMatches;
646 /* Now look for matches from result and below */
647 for (; result >= (TMTag **) sorted_tags_array->pdata; -- result)
649 if (0 != tm_tag_compare(&tag, (TMTag **) result))
650 break;
651 ++tagMatches;
653 *tagCount=tagMatches;
654 ++ result; /* Correct address for the last successful match */
656 s_partial = FALSE;
657 return (TMTag **) result;
660 const char *tm_tag_type_name(const TMTag *tag)
662 g_return_val_if_fail(tag, NULL);
663 switch(tag->type)
665 case tm_tag_class_t: return "class";
666 case tm_tag_enum_t: return "enum";
667 case tm_tag_enumerator_t: return "enumval";
668 case tm_tag_field_t: return "field";
669 case tm_tag_function_t: return "function";
670 case tm_tag_interface_t: return "interface";
671 case tm_tag_member_t: return "member";
672 case tm_tag_method_t: return "method";
673 case tm_tag_namespace_t: return "namespace";
674 case tm_tag_package_t: return "package";
675 case tm_tag_prototype_t: return "prototype";
676 case tm_tag_struct_t: return "struct";
677 case tm_tag_typedef_t: return "typedef";
678 case tm_tag_union_t: return "union";
679 case tm_tag_variable_t: return "variable";
680 case tm_tag_externvar_t: return "extern";
681 case tm_tag_macro_t: return "define";
682 case tm_tag_macro_with_arg_t: return "macro";
683 case tm_tag_file_t: return "file";
684 default: return NULL;
686 return NULL;
689 TMTagType tm_tag_name_type(const char* tag_name)
691 g_return_val_if_fail(tag_name, tm_tag_undef_t);
693 if (strcmp(tag_name, "class") == 0) return tm_tag_class_t;
694 else if (strcmp(tag_name, "enum") == 0) return tm_tag_enum_t;
695 else if (strcmp(tag_name, "enumval") == 0) return tm_tag_enumerator_t;
696 else if (strcmp(tag_name, "field") == 0) return tm_tag_field_t;
697 else if (strcmp(tag_name, "function") == 0) return tm_tag_function_t;
698 else if (strcmp(tag_name, "interface") == 0) return tm_tag_interface_t;
699 else if (strcmp(tag_name, "member") == 0) return tm_tag_member_t;
700 else if (strcmp(tag_name, "method") == 0) return tm_tag_method_t;
701 else if (strcmp(tag_name, "namespace") == 0) return tm_tag_namespace_t;
702 else if (strcmp(tag_name, "package") == 0) return tm_tag_package_t;
703 else if (strcmp(tag_name, "prototype") == 0) return tm_tag_prototype_t;
704 else if (strcmp(tag_name, "struct") == 0) return tm_tag_struct_t;
705 else if (strcmp(tag_name, "typedef") == 0) return tm_tag_typedef_t;
706 else if (strcmp(tag_name, "union") == 0) return tm_tag_union_t;
707 else if (strcmp(tag_name, "variable") == 0) return tm_tag_variable_t;
708 else if (strcmp(tag_name, "extern") == 0) return tm_tag_externvar_t;
709 else if (strcmp(tag_name, "define") == 0) return tm_tag_macro_t;
710 else if (strcmp(tag_name, "macro") == 0) return tm_tag_macro_with_arg_t;
711 else if (strcmp(tag_name, "file") == 0) return tm_tag_file_t;
712 else return tm_tag_undef_t;
715 static const char *tm_tag_impl_name(TMTag *tag)
717 g_return_val_if_fail(tag && (tm_tag_file_t != tag->type), NULL);
718 if (TAG_IMPL_VIRTUAL == tag->atts.entry.impl)
719 return "virtual";
720 else
721 return NULL;
724 static const char *tm_tag_access_name(TMTag *tag)
726 g_return_val_if_fail(tag && (tm_tag_file_t != tag->type), NULL);
727 if (TAG_ACCESS_PUBLIC == tag->atts.entry.access)
728 return "public";
729 else if (TAG_ACCESS_PROTECTED == tag->atts.entry.access)
730 return "protected";
731 else if (TAG_ACCESS_PRIVATE == tag->atts.entry.access)
732 return "private";
733 else
734 return NULL;
737 void tm_tag_print(TMTag *tag, FILE *fp)
739 const char *laccess, *impl, *type;
740 if (!tag || !fp)
741 return;
742 if (tm_tag_file_t == tag->type)
744 fprintf(fp, "%s\n", tag->name);
745 return;
747 laccess = tm_tag_access_name(tag);
748 impl = tm_tag_impl_name(tag);
749 type = tm_tag_type_name(tag);
750 if (laccess)
751 fprintf(fp, "%s ", laccess);
752 if (impl)
753 fprintf(fp, "%s ", impl);
754 if (type)
755 fprintf(fp, "%s ", type);
756 if (tag->atts.entry.var_type)
757 fprintf(fp, "%s ", tag->atts.entry.var_type);
758 if (tag->atts.entry.scope)
759 fprintf(fp, "%s::", tag->atts.entry.scope);
760 fprintf(fp, "%s", tag->name);
761 if (tag->atts.entry.arglist)
762 fprintf(fp, "%s", tag->atts.entry.arglist);
763 if (tag->atts.entry.inheritance)
764 fprintf(fp, " : from %s", tag->atts.entry.inheritance);
765 if ((tag->atts.entry.file) && (tag->atts.entry.line > 0))
766 fprintf(fp, "[%s:%ld]", tag->atts.entry.file->work_object.file_name
767 , tag->atts.entry.line);
768 fprintf(fp, "\n");
771 void tm_tags_array_print(GPtrArray *tags, FILE *fp)
773 guint i;
774 TMTag *tag;
775 if (!(tags && (tags->len > 0) && fp))
776 return;
777 for (i = 0; i < tags->len; ++i)
779 tag = TM_TAG(tags->pdata[i]);
780 tm_tag_print(tag, fp);
784 gint tm_tag_scope_depth(const TMTag *t)
786 gint depth;
787 char *s;
788 if(!(t && t->atts.entry.scope))
789 return 0;
790 for (s = t->atts.entry.scope, depth = 0; s; s = strstr(s, "::"))
792 ++ depth;
793 ++ s;
795 return depth;