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.
12 #include <glib-object.h>
18 #define LIBCTAGS_DEFINED
22 #define TAG_NEW(T) ((T) = g_slice_new0(TMTag))
23 #define TAG_FREE(T) g_slice_free(TMTag, (T))
26 /* Note: To preserve binary compatibility, it is very important
27 that you only *append* to this list ! */
33 TA_POS
, /* Obsolete */
47 static guint
*s_sort_attrs
= NULL
;
48 static gboolean s_partial
= FALSE
;
50 static const char *s_tag_type_names
[] = {
51 "class", /* classes */
52 "enum", /* enumeration names */
53 "enumerator", /* enumerators (values inside an enumeration) */
54 "externvar", /* external variable declarations */
56 "function", /* function definitions */
57 "interface", /* interfaces */
58 "macro", /* macro definitions */
59 "member", /* class, struct, and union members */
60 "method", /* methods */
61 "namespace", /* namespaces */
62 "package", /* packages */
63 "prototype", /* function prototypes */
64 "struct", /* structure names */
65 "typedef", /* typedefs */
66 "union", /* union names */
67 "variable", /* variable definitions */
68 "other" /* Other tag type (non C/C++/Java) */
71 static int s_tag_types
[] = {
92 GType
tm_tag_get_type(void)
94 static GType gtype
= 0;
95 if (G_UNLIKELY (gtype
== 0))
97 gtype
= g_boxed_type_register_static("TMTag", (GBoxedCopyFunc
)tm_tag_ref
,
98 (GBoxedFreeFunc
)tm_tag_unref
);
103 static int get_tag_type(const char *tag_name
)
107 g_return_val_if_fail(tag_name
, 0);
108 for (i
=0; i
< sizeof(s_tag_type_names
)/sizeof(char *); ++i
)
110 cmp
= strcmp(tag_name
, s_tag_type_names
[i
]);
112 return s_tag_types
[i
];
116 /* other is not checked above as it is last, not sorted alphabetically */
117 if (strcmp(tag_name
, "other") == 0)
118 return tm_tag_other_t
;
120 fprintf(stderr
, "Unknown tag type %s\n", tag_name
);
122 return tm_tag_undef_t
;
125 gboolean
tm_tag_init(TMTag
*tag
, TMSourceFile
*file
, const tagEntryInfo
*tag_entry
)
128 if (NULL
== tag_entry
)
130 /* This is a file tag */
135 tag
->name
= g_strdup(file
->work_object
.file_name
);
136 tag
->type
= tm_tag_file_t
;
137 /* tag->atts.file.timestamp = file->work_object.analyze_time; */
138 tag
->atts
.file
.lang
= file
->lang
;
139 tag
->atts
.file
.inactive
= FALSE
;
145 /* This is a normal tag entry */
146 if (NULL
== tag_entry
->name
)
148 tag
->name
= g_strdup(tag_entry
->name
);
149 tag
->type
= get_tag_type(tag_entry
->kindName
);
150 tag
->atts
.entry
.local
= tag_entry
->isFileScope
;
151 tag
->atts
.entry
.pointerOrder
= 0; /* backward compatibility (use var_type instead) */
152 tag
->atts
.entry
.line
= tag_entry
->lineNumber
;
153 if (NULL
!= tag_entry
->extensionFields
.arglist
)
154 tag
->atts
.entry
.arglist
= g_strdup(tag_entry
->extensionFields
.arglist
);
155 if ((NULL
!= tag_entry
->extensionFields
.scope
[1]) &&
156 (isalpha(tag_entry
->extensionFields
.scope
[1][0]) ||
157 tag_entry
->extensionFields
.scope
[1][0] == '_'))
158 tag
->atts
.entry
.scope
= g_strdup(tag_entry
->extensionFields
.scope
[1]);
159 if (tag_entry
->extensionFields
.inheritance
!= NULL
)
160 tag
->atts
.entry
.inheritance
= g_strdup(tag_entry
->extensionFields
.inheritance
);
161 if (tag_entry
->extensionFields
.varType
!= NULL
)
162 tag
->atts
.entry
.var_type
= g_strdup(tag_entry
->extensionFields
.varType
);
163 if (tag_entry
->extensionFields
.access
!= NULL
)
165 if (0 == strcmp("public", tag_entry
->extensionFields
.access
))
166 tag
->atts
.entry
.access
= TAG_ACCESS_PUBLIC
;
167 else if (0 == strcmp("protected", tag_entry
->extensionFields
.access
))
168 tag
->atts
.entry
.access
= TAG_ACCESS_PROTECTED
;
169 else if (0 == strcmp("private", tag_entry
->extensionFields
.access
))
170 tag
->atts
.entry
.access
= TAG_ACCESS_PRIVATE
;
171 else if (0 == strcmp("friend", tag_entry
->extensionFields
.access
))
172 tag
->atts
.entry
.access
= TAG_ACCESS_FRIEND
;
173 else if (0 == strcmp("default", tag_entry
->extensionFields
.access
))
174 tag
->atts
.entry
.access
= TAG_ACCESS_DEFAULT
;
178 g_warning("Unknown access type %s", tag_entry
->extensionFields
.access
);
180 tag
->atts
.entry
.access
= TAG_ACCESS_UNKNOWN
;
183 if (tag_entry
->extensionFields
.implementation
!= NULL
)
185 if ((0 == strcmp("virtual", tag_entry
->extensionFields
.implementation
))
186 || (0 == strcmp("pure virtual", tag_entry
->extensionFields
.implementation
)))
187 tag
->atts
.entry
.impl
= TAG_IMPL_VIRTUAL
;
191 g_warning("Unknown implementation %s", tag_entry
->extensionFields
.implementation
);
193 tag
->atts
.entry
.impl
= TAG_IMPL_UNKNOWN
;
196 if ((tm_tag_macro_t
== tag
->type
) && (NULL
!= tag
->atts
.entry
.arglist
))
197 tag
->type
= tm_tag_macro_with_arg_t
;
198 tag
->atts
.entry
.file
= file
;
203 TMTag
*tm_tag_new(TMSourceFile
*file
, const tagEntryInfo
*tag_entry
)
208 if (FALSE
== tm_tag_init(tag
, file
, tag_entry
))
216 gboolean
tm_tag_init_from_file(TMTag
*tag
, TMSourceFile
*file
, FILE *fp
)
221 guchar changed_char
= TA_NAME
;
224 if ((NULL
== fgets((gchar
*)buf
, BUFSIZ
, fp
)) || ('\0' == *buf
))
226 for (start
= end
= buf
, status
= TRUE
; (TRUE
== status
); start
= end
, ++ end
)
228 while ((*end
< TA_NAME
) && (*end
!= '\0') && (*end
!= '\n'))
230 if (('\0' == *end
) || ('\n' == *end
))
234 if (NULL
== tag
->name
)
236 if (!isprint(*start
))
239 tag
->name
= g_strdup((gchar
*)start
);
246 tag
->atts
.entry
.line
= atol((gchar
*)start
+ 1);
249 tag
->atts
.entry
.local
= atoi((gchar
*)start
+ 1);
252 tag
->type
= (TMTagType
) atoi((gchar
*)start
+ 1);
255 tag
->atts
.entry
.arglist
= g_strdup((gchar
*)start
+ 1);
258 tag
->atts
.entry
.scope
= g_strdup((gchar
*)start
+ 1);
261 tag
->atts
.entry
.pointerOrder
= atoi((gchar
*)start
+ 1);
264 tag
->atts
.entry
.var_type
= g_strdup((gchar
*)start
+ 1);
267 tag
->atts
.entry
.inheritance
= g_strdup((gchar
*)start
+ 1);
270 if (tm_tag_file_t
!= tag
->type
)
272 g_warning("Got time attribute for non-file tag %s", tag
->name
);
276 tag
->atts
.file
.timestamp
= atol((gchar
*)start
+ 1);
279 if (tm_tag_file_t
!= tag
->type
)
281 g_warning("Got lang attribute for non-file tag %s", tag
->name
);
285 tag
->atts
.file
.lang
= atoi((gchar
*)start
+ 1);
288 if (tm_tag_file_t
!= tag
->type
)
290 g_warning("Got inactive attribute for non-file tag %s", tag
->name
);
294 tag
->atts
.file
.inactive
= (gboolean
) atoi((gchar
*)start
+ 1);
297 tag
->atts
.entry
.access
= *(start
+ 1);
300 tag
->atts
.entry
.impl
= *(start
+ 1);
304 g_warning("Unknown attribute %s", start
+ 1);
311 if (NULL
== tag
->name
)
313 if (tm_tag_file_t
!= tag
->type
)
314 tag
->atts
.entry
.file
= file
;
318 /* alternative parser for Pascal and LaTeX global tags files with the following format
319 * tagname|return value|arglist|description\n */
320 gboolean
tm_tag_init_from_file_alt(TMTag
*tag
, TMSourceFile
*file
, FILE *fp
)
325 /*guchar changed_char = TA_NAME;*/
328 if ((NULL
== fgets((gchar
*)buf
, BUFSIZ
, fp
)) || ('\0' == *buf
))
333 for (start
= end
= buf
, status
= TRUE
; (TRUE
== status
); start
= end
, ++ end
)
335 while ((*end
< TA_NAME
) && (*end
!= '\0') && (*end
!= '\n'))
337 if (('\0' == *end
) || ('\n' == *end
))
339 /*changed_char = *end;*/
341 if (NULL
== tag
->name
&& !isprint(*start
))
344 fields
= g_strsplit((gchar
*)start
, "|", -1);
345 field_len
= g_strv_length(fields
);
347 if (field_len
>= 1) tag
->name
= g_strdup(fields
[0]);
348 else tag
->name
= NULL
;
349 if (field_len
>= 2 && fields
[1] != NULL
) tag
->atts
.entry
.var_type
= g_strdup(fields
[1]);
350 if (field_len
>= 3 && fields
[2] != NULL
) tag
->atts
.entry
.arglist
= g_strdup(fields
[2]);
351 tag
->type
= tm_tag_prototype_t
;
356 if (NULL
== tag
->name
)
358 if (tm_tag_file_t
!= tag
->type
)
359 tag
->atts
.entry
.file
= file
;
363 TMTag
*tm_tag_new_from_file(TMSourceFile
*file
, FILE *fp
, gint mode
, gboolean format_pipe
)
371 result
= tm_tag_init_from_file_alt(tag
, file
, fp
);
373 result
= tm_tag_init_from_file(tag
, file
, fp
);
380 tag
->atts
.file
.lang
= mode
;
384 gboolean
tm_tag_write(TMTag
*tag
, FILE *fp
, guint attrs
)
386 fprintf(fp
, "%s", tag
->name
);
387 if (attrs
& tm_tag_attr_type_t
)
388 fprintf(fp
, "%c%d", TA_TYPE
, tag
->type
);
389 if (tag
->type
== tm_tag_file_t
)
391 if (attrs
& tm_tag_attr_time_t
)
392 fprintf(fp
, "%c%ld", TA_TIME
, tag
->atts
.file
.timestamp
);
393 if (attrs
& tm_tag_attr_lang_t
)
394 fprintf(fp
, "%c%d", TA_LANG
, tag
->atts
.file
.lang
);
395 if ((attrs
& tm_tag_attr_inactive_t
) && tag
->atts
.file
.inactive
)
396 fprintf(fp
, "%c%d", TA_INACTIVE
, tag
->atts
.file
.inactive
);
400 if ((attrs
& tm_tag_attr_arglist_t
) && (NULL
!= tag
->atts
.entry
.arglist
))
401 fprintf(fp
, "%c%s", TA_ARGLIST
, tag
->atts
.entry
.arglist
);
402 if (attrs
& tm_tag_attr_line_t
)
403 fprintf(fp
, "%c%ld", TA_LINE
, tag
->atts
.entry
.line
);
404 if (attrs
& tm_tag_attr_local_t
)
405 fprintf(fp
, "%c%d", TA_LOCAL
, tag
->atts
.entry
.local
);
406 if ((attrs
& tm_tag_attr_scope_t
) && (NULL
!= tag
->atts
.entry
.scope
))
407 fprintf(fp
, "%c%s", TA_SCOPE
, tag
->atts
.entry
.scope
);
408 if ((attrs
& tm_tag_attr_inheritance_t
) && (NULL
!= tag
->atts
.entry
.inheritance
))
409 fprintf(fp
, "%c%s", TA_INHERITS
, tag
->atts
.entry
.inheritance
);
410 if (attrs
& tm_tag_attr_pointer_t
)
411 fprintf(fp
, "%c%d", TA_POINTER
, tag
->atts
.entry
.pointerOrder
);
412 if ((attrs
& tm_tag_attr_vartype_t
) && (NULL
!= tag
->atts
.entry
.var_type
))
413 fprintf(fp
, "%c%s", TA_VARTYPE
, tag
->atts
.entry
.var_type
);
414 if ((attrs
& tm_tag_attr_access_t
) && (TAG_ACCESS_UNKNOWN
!= tag
->atts
.entry
.access
))
415 fprintf(fp
, "%c%c", TA_ACCESS
, tag
->atts
.entry
.access
);
416 if ((attrs
& tm_tag_attr_impl_t
) && (TAG_IMPL_UNKNOWN
!= tag
->atts
.entry
.impl
))
417 fprintf(fp
, "%c%c", TA_IMPL
, tag
->atts
.entry
.impl
);
419 if (fprintf(fp
, "\n"))
425 static void tm_tag_destroy(TMTag
*tag
)
428 if (tm_tag_file_t
!= tag
->type
)
430 g_free(tag
->atts
.entry
.arglist
);
431 g_free(tag
->atts
.entry
.scope
);
432 g_free(tag
->atts
.entry
.inheritance
);
433 g_free(tag
->atts
.entry
.var_type
);
438 void tm_tag_free(gpointer tag
)
444 void tm_tag_unref(TMTag
*tag
)
446 /* be NULL-proof because tm_tag_free() was NULL-proof and we indent to be a
447 * drop-in replacment of it */
448 if (NULL
!= tag
&& g_atomic_int_dec_and_test(&tag
->refcount
))
455 TMTag
*tm_tag_ref(TMTag
*tag
)
457 g_atomic_int_inc(&tag
->refcount
);
461 int tm_tag_compare(const void *ptr1
, const void *ptr2
)
463 unsigned int *sort_attr
;
465 TMTag
*t1
= *((TMTag
**) ptr1
);
466 TMTag
*t2
= *((TMTag
**) ptr2
);
468 if ((NULL
== t1
) || (NULL
== t2
))
470 g_warning("Found NULL tag");
473 if (NULL
== s_sort_attrs
)
476 return strncmp(NVL(t1
->name
, ""), NVL(t2
->name
, ""), strlen(NVL(t1
->name
, "")));
478 return strcmp(NVL(t1
->name
, ""), NVL(t2
->name
, ""));
481 for (sort_attr
= s_sort_attrs
; *sort_attr
!= tm_tag_attr_none_t
; ++ sort_attr
)
485 case tm_tag_attr_name_t
:
487 returnval
= strncmp(NVL(t1
->name
, ""), NVL(t2
->name
, ""), strlen(NVL(t1
->name
, "")));
489 returnval
= strcmp(NVL(t1
->name
, ""), NVL(t2
->name
, ""));
493 case tm_tag_attr_type_t
:
494 if (0 != (returnval
= (t1
->type
- t2
->type
)))
497 case tm_tag_attr_file_t
:
498 if (0 != (returnval
= (t1
->atts
.entry
.file
- t2
->atts
.entry
.file
)))
501 case tm_tag_attr_scope_t
:
502 if (0 != (returnval
= strcmp(NVL(t1
->atts
.entry
.scope
, ""), NVL(t2
->atts
.entry
.scope
, ""))))
505 case tm_tag_attr_arglist_t
:
506 if (0 != (returnval
= strcmp(NVL(t1
->atts
.entry
.arglist
, ""), NVL(t2
->atts
.entry
.arglist
, ""))))
508 int line_diff
= (t1
->atts
.entry
.line
- t2
->atts
.entry
.line
);
510 return line_diff
? line_diff
: returnval
;
513 case tm_tag_attr_vartype_t
:
514 if (0 != (returnval
= strcmp(NVL(t1
->atts
.entry
.var_type
, ""), NVL(t2
->atts
.entry
.var_type
, ""))))
517 case tm_tag_attr_line_t
:
518 if (0 != (returnval
= (t1
->atts
.entry
.line
- t2
->atts
.entry
.line
)))
526 gboolean
tm_tags_prune(GPtrArray
*tags_array
)
529 for (i
=0, count
= 0; i
< tags_array
->len
; ++i
)
531 if (NULL
!= tags_array
->pdata
[i
])
532 tags_array
->pdata
[count
++] = tags_array
->pdata
[i
];
534 tags_array
->len
= count
;
538 gboolean
tm_tags_dedup(GPtrArray
*tags_array
, TMTagAttrType
*sort_attributes
)
542 if ((!tags_array
) || (!tags_array
->len
))
544 s_sort_attrs
= sort_attributes
;
546 for (i
= 1; i
< tags_array
->len
; ++i
)
548 if (0 == tm_tag_compare(&(tags_array
->pdata
[i
- 1]), &(tags_array
->pdata
[i
])))
550 tags_array
->pdata
[i
-1] = NULL
;
553 tm_tags_prune(tags_array
);
557 gboolean
tm_tags_custom_dedup(GPtrArray
*tags_array
, TMTagCompareFunc compare_func
)
561 if ((!tags_array
) || (!tags_array
->len
))
563 for (i
= 1; i
< tags_array
->len
; ++i
)
565 if (0 == compare_func(&(tags_array
->pdata
[i
- 1]), &(tags_array
->pdata
[i
])))
566 tags_array
->pdata
[i
-1] = NULL
;
568 tm_tags_prune(tags_array
);
572 /* Sorts newly-added tags and merges them in order with existing tags.
573 * This is much faster than resorting the whole array.
574 * Note: Having the caller append to the existing array should be faster
575 * than creating a new array which would likely get resized more than once.
576 * tags_array: array with new (perhaps unsorted) tags appended.
577 * orig_len: number of existing tags. */
578 gboolean
tm_tags_merge(GPtrArray
*tags_array
, gsize orig_len
,
579 TMTagAttrType
*sort_attributes
, gboolean dedup
)
581 gpointer
*copy
, *a
, *b
;
584 if ((!tags_array
) || (!tags_array
->len
) || orig_len
>= tags_array
->len
)
587 return tm_tags_sort(tags_array
, sort_attributes
, dedup
);
588 copy_len
= tags_array
->len
- orig_len
;
589 copy
= g_memdup(tags_array
->pdata
+ orig_len
, copy_len
* sizeof(gpointer
));
590 s_sort_attrs
= sort_attributes
;
592 /* enforce copy sorted with same attributes for merge */
593 qsort(copy
, copy_len
, sizeof(gpointer
), tm_tag_compare
);
594 a
= tags_array
->pdata
+ orig_len
- 1;
595 b
= copy
+ copy_len
- 1;
596 for (i
= tags_array
->len
- 1;; i
--)
598 gint cmp
= tm_tag_compare(a
, b
);
600 tags_array
->pdata
[i
] = (cmp
>= 0) ? *a
-- : *b
--;
601 if (a
< tags_array
->pdata
)
603 /* include remainder of copy as well as current value of b */
604 memcpy(tags_array
->pdata
, copy
, ((b
+ 1) - copy
) * sizeof(gpointer
));
608 break; /* remaining elements of 'a' are in place already */
614 tm_tags_dedup(tags_array
, sort_attributes
);
618 gboolean
tm_tags_sort(GPtrArray
*tags_array
, TMTagAttrType
*sort_attributes
, gboolean dedup
)
620 if ((!tags_array
) || (!tags_array
->len
))
622 s_sort_attrs
= sort_attributes
;
624 qsort(tags_array
->pdata
, tags_array
->len
, sizeof(gpointer
), tm_tag_compare
);
627 tm_tags_dedup(tags_array
, sort_attributes
);
631 gboolean
tm_tags_custom_sort(GPtrArray
*tags_array
, TMTagCompareFunc compare_func
, gboolean dedup
)
633 if ((!tags_array
) || (!tags_array
->len
))
635 qsort(tags_array
->pdata
, tags_array
->len
, sizeof(gpointer
), compare_func
);
637 tm_tags_custom_dedup(tags_array
, compare_func
);
641 GPtrArray
*tm_tags_extract(GPtrArray
*tags_array
, guint tag_types
)
645 if (NULL
== tags_array
)
647 new_tags
= g_ptr_array_new();
648 for (i
=0; i
< tags_array
->len
; ++i
)
650 if (NULL
!= tags_array
->pdata
[i
])
652 if (tag_types
& (((TMTag
*) tags_array
->pdata
[i
])->type
))
653 g_ptr_array_add(new_tags
, tags_array
->pdata
[i
]);
659 void tm_tags_array_free(GPtrArray
*tags_array
, gboolean free_all
)
664 for (i
= 0; i
< tags_array
->len
; ++i
)
665 tm_tag_unref(tags_array
->pdata
[i
]);
667 g_ptr_array_free(tags_array
, TRUE
);
669 g_ptr_array_set_size(tags_array
, 0);
673 TMTag
**tm_tags_find(const GPtrArray
*sorted_tags_array
, const char *name
,
674 gboolean partial
, int * tagCount
)
676 static TMTag
*tag
= NULL
;
680 if ((!sorted_tags_array
) || (!sorted_tags_array
->len
))
684 tag
= g_new0(TMTag
, 1);
685 tag
->name
= (char *) name
;
688 result
= (TMTag
**) bsearch(&tag
, sorted_tags_array
->pdata
, sorted_tags_array
->len
689 , sizeof(gpointer
), tm_tag_compare
);
690 /* There can be matches on both sides of result */
693 TMTag
**last
= (TMTag
**) &sorted_tags_array
->pdata
[sorted_tags_array
->len
- 1];
696 /* First look for any matches after result */
699 for (; adv
<= last
&& *adv
; ++ adv
)
701 if (0 != tm_tag_compare(&tag
, adv
))
705 /* Now look for matches from result and below */
706 for (; result
>= (TMTag
**) sorted_tags_array
->pdata
; -- result
)
708 if (0 != tm_tag_compare(&tag
, (TMTag
**) result
))
712 *tagCount
=tagMatches
;
713 ++ result
; /* Correct address for the last successful match */
716 return (TMTag
**) result
;
719 const char *tm_tag_type_name(const TMTag
*tag
)
721 g_return_val_if_fail(tag
, NULL
);
724 case tm_tag_class_t
: return "class";
725 case tm_tag_enum_t
: return "enum";
726 case tm_tag_enumerator_t
: return "enumval";
727 case tm_tag_field_t
: return "field";
728 case tm_tag_function_t
: return "function";
729 case tm_tag_interface_t
: return "interface";
730 case tm_tag_member_t
: return "member";
731 case tm_tag_method_t
: return "method";
732 case tm_tag_namespace_t
: return "namespace";
733 case tm_tag_package_t
: return "package";
734 case tm_tag_prototype_t
: return "prototype";
735 case tm_tag_struct_t
: return "struct";
736 case tm_tag_typedef_t
: return "typedef";
737 case tm_tag_union_t
: return "union";
738 case tm_tag_variable_t
: return "variable";
739 case tm_tag_externvar_t
: return "extern";
740 case tm_tag_macro_t
: return "define";
741 case tm_tag_macro_with_arg_t
: return "macro";
742 case tm_tag_file_t
: return "file";
743 default: return NULL
;
748 TMTagType
tm_tag_name_type(const char* tag_name
)
750 g_return_val_if_fail(tag_name
, tm_tag_undef_t
);
752 if (strcmp(tag_name
, "class") == 0) return tm_tag_class_t
;
753 else if (strcmp(tag_name
, "enum") == 0) return tm_tag_enum_t
;
754 else if (strcmp(tag_name
, "enumval") == 0) return tm_tag_enumerator_t
;
755 else if (strcmp(tag_name
, "field") == 0) return tm_tag_field_t
;
756 else if (strcmp(tag_name
, "function") == 0) return tm_tag_function_t
;
757 else if (strcmp(tag_name
, "interface") == 0) return tm_tag_interface_t
;
758 else if (strcmp(tag_name
, "member") == 0) return tm_tag_member_t
;
759 else if (strcmp(tag_name
, "method") == 0) return tm_tag_method_t
;
760 else if (strcmp(tag_name
, "namespace") == 0) return tm_tag_namespace_t
;
761 else if (strcmp(tag_name
, "package") == 0) return tm_tag_package_t
;
762 else if (strcmp(tag_name
, "prototype") == 0) return tm_tag_prototype_t
;
763 else if (strcmp(tag_name
, "struct") == 0) return tm_tag_struct_t
;
764 else if (strcmp(tag_name
, "typedef") == 0) return tm_tag_typedef_t
;
765 else if (strcmp(tag_name
, "union") == 0) return tm_tag_union_t
;
766 else if (strcmp(tag_name
, "variable") == 0) return tm_tag_variable_t
;
767 else if (strcmp(tag_name
, "extern") == 0) return tm_tag_externvar_t
;
768 else if (strcmp(tag_name
, "define") == 0) return tm_tag_macro_t
;
769 else if (strcmp(tag_name
, "macro") == 0) return tm_tag_macro_with_arg_t
;
770 else if (strcmp(tag_name
, "file") == 0) return tm_tag_file_t
;
771 else return tm_tag_undef_t
;
774 static const char *tm_tag_impl_name(TMTag
*tag
)
776 g_return_val_if_fail(tag
&& (tm_tag_file_t
!= tag
->type
), NULL
);
777 if (TAG_IMPL_VIRTUAL
== tag
->atts
.entry
.impl
)
783 static const char *tm_tag_access_name(TMTag
*tag
)
785 g_return_val_if_fail(tag
&& (tm_tag_file_t
!= tag
->type
), NULL
);
786 if (TAG_ACCESS_PUBLIC
== tag
->atts
.entry
.access
)
788 else if (TAG_ACCESS_PROTECTED
== tag
->atts
.entry
.access
)
790 else if (TAG_ACCESS_PRIVATE
== tag
->atts
.entry
.access
)
796 void tm_tag_print(TMTag
*tag
, FILE *fp
)
798 const char *laccess
, *impl
, *type
;
801 if (tm_tag_file_t
== tag
->type
)
803 fprintf(fp
, "%s\n", tag
->name
);
806 laccess
= tm_tag_access_name(tag
);
807 impl
= tm_tag_impl_name(tag
);
808 type
= tm_tag_type_name(tag
);
810 fprintf(fp
, "%s ", laccess
);
812 fprintf(fp
, "%s ", impl
);
814 fprintf(fp
, "%s ", type
);
815 if (tag
->atts
.entry
.var_type
)
816 fprintf(fp
, "%s ", tag
->atts
.entry
.var_type
);
817 if (tag
->atts
.entry
.scope
)
818 fprintf(fp
, "%s::", tag
->atts
.entry
.scope
);
819 fprintf(fp
, "%s", tag
->name
);
820 if (tag
->atts
.entry
.arglist
)
821 fprintf(fp
, "%s", tag
->atts
.entry
.arglist
);
822 if (tag
->atts
.entry
.inheritance
)
823 fprintf(fp
, " : from %s", tag
->atts
.entry
.inheritance
);
824 if ((tag
->atts
.entry
.file
) && (tag
->atts
.entry
.line
> 0))
825 fprintf(fp
, "[%s:%ld]", tag
->atts
.entry
.file
->work_object
.file_name
826 , tag
->atts
.entry
.line
);
830 void tm_tags_array_print(GPtrArray
*tags
, FILE *fp
)
834 if (!(tags
&& (tags
->len
> 0) && fp
))
836 for (i
= 0; i
< tags
->len
; ++i
)
838 tag
= TM_TAG(tags
->pdata
[i
]);
839 tm_tag_print(tag
, fp
);
843 gint
tm_tag_scope_depth(const TMTag
*t
)
847 if(!(t
&& t
->atts
.entry
.scope
))
849 for (s
= t
->atts
.entry
.scope
, depth
= 0; s
; s
= strstr(s
, "::"))