3 * Copyright (c) 2015, Red Hat, Inc.
4 * Copyright (c) 2015, Masatake YAMATO
6 * Author: Masatake YAMATO <yamato@redhat.com>
8 * This source code is released for free distribution under the terms of the
9 * GNU General Public License version 2 or (at your option) any later version.
13 #include "general.h" /* must always come first */
26 #include "options_p.h"
34 #define FIELD_NULL_LETTER_CHAR '-'
35 #define FIELD_NULL_LETTER_STRING "-"
37 typedef struct sFieldObject
{
40 const char* nameWithPrefix
;
45 static const char *renderFieldName (const tagEntryInfo
*const tag
, const char *value
, vString
* b
);
46 static const char *renderFieldNameNoEscape (const tagEntryInfo
*const tag
, const char *value CTAGS_ATTR_UNUSED
, vString
* b
);
47 static const char *renderFieldInput (const tagEntryInfo
*const tag
, const char *value
, vString
* b
);
48 static const char *renderFieldInputNoEscape (const tagEntryInfo
*const tag
, const char *value
, vString
* b
);
49 static const char *renderFieldCompactInputLine (const tagEntryInfo
*const tag
, const char *value
, vString
* b
);
50 static const char *renderFieldSignature (const tagEntryInfo
*const tag
, const char *value
, vString
* b
);
51 static const char *renderFieldSignatureNoEscape (const tagEntryInfo
*const tag
, const char *value
, vString
* b
);
52 static const char *renderFieldScope (const tagEntryInfo
*const tag
, const char *value
, vString
* b
);
53 static const char *renderFieldScopeNoEscape (const tagEntryInfo
*const tag
, const char *value
, vString
* b
);
54 static const char *renderFieldTyperef (const tagEntryInfo
*const tag
, const char *value
, vString
* b
);
55 static const char *renderFieldInherits (const tagEntryInfo
*const tag
, const char *value
, vString
* b
);
56 static const char *renderFieldKindName (const tagEntryInfo
*const tag
, const char *value
, vString
* b
);
57 static const char *renderFieldLineNumber (const tagEntryInfo
*const tag
, const char *value
, vString
* b
);
58 static const char *renderFieldLanguage (const tagEntryInfo
*const tag
, const char *value
, vString
* b
);
59 static const char *renderFieldAccess (const tagEntryInfo
*const tag
, const char *value
, vString
* b
);
60 static const char *renderFieldKindLetter (const tagEntryInfo
*const tag
, const char *value
, vString
* b
);
61 static const char *renderFieldImplementation (const tagEntryInfo
*const tag
, const char *value
, vString
* b
);
62 static const char *renderFieldFile (const tagEntryInfo
*const tag
, const char *value
, vString
* b
);
63 static const char *renderFieldPattern (const tagEntryInfo
*const tag
, const char *value
, vString
* b
);
64 static const char *renderFieldRoles (const tagEntryInfo
*const tag
, const char *value
, vString
* b
);
65 static const char *renderFieldRefMarker (const tagEntryInfo
*const tag
, const char *value
, vString
* b
);
66 static const char *renderFieldExtras (const tagEntryInfo
*const tag
, const char *value
, vString
* b
);
67 static const char *renderFieldXpath (const tagEntryInfo
*const tag
, const char *value
, vString
* b
);
68 static const char *renderFieldScopeKindName(const tagEntryInfo
*const tag
, const char *value
, vString
* b
);
69 static const char *renderFieldEnd (const tagEntryInfo
*const tag
, const char *value
, vString
* b
);
71 static bool doesContainAnyCharInName (const tagEntryInfo
*const tag
, const char *value
, const char *chars
);
72 static bool doesContainAnyCharInInput (const tagEntryInfo
*const tag
, const char*value
, const char *chars
);
73 static bool doesContainAnyCharInFieldScope (const tagEntryInfo
*const tag
, const char *value
, const char *chars
);
74 static bool doesContainAnyCharInSignature (const tagEntryInfo
*const tag
, const char *value
, const char *chars
);
76 static bool isLanguageFieldAvailable (const tagEntryInfo
*const tag
);
77 static bool isTyperefFieldAvailable (const tagEntryInfo
*const tag
);
78 static bool isFileFieldAvailable (const tagEntryInfo
*const tag
);
79 static bool isInheritsFieldAvailable (const tagEntryInfo
*const tag
);
80 static bool isAccessFieldAvailable (const tagEntryInfo
*const tag
);
81 static bool isImplementationFieldAvailable (const tagEntryInfo
*const tag
);
82 static bool isSignatureFieldAvailable (const tagEntryInfo
*const tag
);
83 static bool isExtrasFieldAvailable (const tagEntryInfo
*const tag
);
84 static bool isXpathFieldAvailable (const tagEntryInfo
*const tag
);
85 static bool isEndFieldAvailable (const tagEntryInfo
*const tag
);
88 #define DEFINE_FIELD(L, N, V, H, DT, RE) \
89 DEFINE_FIELD_FULL (L, N, V, H, NULL, DT, RE, NULL, NULL)
90 #define DEFINE_FIELD_FULL(L, N, V, H, A, DT, RE, RN, DCAC) \
97 .renderNoEscaping= RN, \
98 .doesContainAnyChar = DCAC, \
99 .isValueAvailable = A, \
103 #define WITH_DEFUALT_VALUE(str) ((str)?(str):FIELD_NULL_LETTER_STRING)
105 static fieldDefinition fieldDefinitionsFixed
[] = {
107 DEFINE_FIELD_FULL ('N', "name", true,
111 renderFieldName
, renderFieldNameNoEscape
,
112 doesContainAnyCharInName
),
113 DEFINE_FIELD_FULL ('F', "input", true,
117 renderFieldInput
, renderFieldInputNoEscape
,
118 doesContainAnyCharInInput
),
119 DEFINE_FIELD ('P', "pattern", true,
121 FIELDTYPE_STRING
|FIELDTYPE_BOOL
,
125 static fieldDefinition fieldDefinitionsExuberant
[] = {
126 DEFINE_FIELD ('C', "compact", false,
127 "compact input line (used only in xref output)",
129 renderFieldCompactInputLine
),
131 /* EXTENSION FIELDS */
132 DEFINE_FIELD_FULL ('a', "access", false,
133 "Access (or export) of class members",
134 isAccessFieldAvailable
,
136 renderFieldAccess
, NULL
, NULL
),
137 DEFINE_FIELD_FULL ('f', "file", true,
138 "File-restricted scoping",
139 isFileFieldAvailable
,
141 renderFieldFile
, NULL
, NULL
),
142 DEFINE_FIELD_FULL ('i', "inherits", false,
143 "Inheritance information",
144 isInheritsFieldAvailable
,
145 FIELDTYPE_STRING
|FIELDTYPE_BOOL
,
146 renderFieldInherits
, NULL
, NULL
),
147 DEFINE_FIELD ('K', NULL
, false,
148 "Kind of tag in long-name form",
150 renderFieldKindName
),
151 DEFINE_FIELD ('k', NULL
, true,
152 "Kind of tag in one-letter form",
154 renderFieldKindLetter
),
155 DEFINE_FIELD_FULL ('l', "language", false,
156 "Language of input file containing tag",
157 isLanguageFieldAvailable
,
159 renderFieldLanguage
, NULL
, NULL
),
160 DEFINE_FIELD_FULL ('m', "implementation", false,
161 "Implementation information",
162 isImplementationFieldAvailable
,
164 renderFieldImplementation
, NULL
, NULL
),
165 DEFINE_FIELD ('n', "line", false,
166 "Line number of tag definition",
168 renderFieldLineNumber
),
169 DEFINE_FIELD_FULL ('S', "signature", false,
170 "Signature of routine (e.g. prototype or parameter list)",
171 isSignatureFieldAvailable
,
173 renderFieldSignature
, renderFieldSignatureNoEscape
,
174 doesContainAnyCharInSignature
),
175 DEFINE_FIELD_FULL ('s', NULL
, true,
176 "[tags output] scope (kind:name) of tag definition, [xref and json output] name of scope",
179 renderFieldScope
, renderFieldScopeNoEscape
,
180 doesContainAnyCharInFieldScope
),
181 DEFINE_FIELD_FULL ('t', "typeref", true,
182 "Type and name of a variable or typedef",
183 isTyperefFieldAvailable
,
185 renderFieldTyperef
, NULL
, NULL
),
186 DEFINE_FIELD ('z', "kind", false,
187 "[tags output] prepend \"kind:\" to k/ (or K/) field output, [xref and json output] kind in long-name form",
189 /* Following renderer is for handling --_xformat=%{kind};
190 and is not for tags output. */
191 renderFieldKindName
),
194 static fieldDefinition fieldDefinitionsUniversal
[] = {
195 DEFINE_FIELD ('r', "roles", false,
199 DEFINE_FIELD ('R', NULL
, false,
200 "Marker (R or D) representing whether tag is definition or reference",
202 renderFieldRefMarker
),
203 DEFINE_FIELD_FULL ('Z', "scope", false,
204 "[tags output] prepend \"scope:\" key to s/scope field output, [xref and json output] the same as s/ field",
207 /* Following renderer is for handling --_xformat=%{scope};
208 and is not for tags output. */
209 renderFieldScope
, renderFieldScopeNoEscape
,
210 doesContainAnyCharInFieldScope
),
211 DEFINE_FIELD_FULL ('E', "extras", false,
212 "Extra tag type information",
213 isExtrasFieldAvailable
,
215 renderFieldExtras
, NULL
, NULL
),
216 DEFINE_FIELD_FULL ('x', "xpath", false,
218 isXpathFieldAvailable
,
220 renderFieldXpath
, NULL
, NULL
),
221 DEFINE_FIELD ('p', "scopeKind", false,
222 "[tags output] no effect, [xref and json output] kind of scope in long-name form",
224 renderFieldScopeKindName
),
225 DEFINE_FIELD_FULL ('e', "end", false,
226 "end lines of various items",
229 renderFieldEnd
, NULL
, NULL
),
233 static unsigned int fieldObjectUsed
= 0;
234 static unsigned int fieldObjectAllocated
= 0;
235 static fieldObject
* fieldObjects
= NULL
;
237 extern void initFieldObjects (void)
242 Assert (fieldObjects
== NULL
);
245 = ARRAY_SIZE (fieldDefinitionsFixed
)
246 + ARRAY_SIZE (fieldDefinitionsExuberant
)
247 + ARRAY_SIZE (fieldDefinitionsUniversal
);
248 fieldObjects
= xMalloc (fieldObjectAllocated
, fieldObject
);
249 DEFAULT_TRASH_BOX(&fieldObjects
, eFreeIndirect
);
253 for (i
= 0; i
< ARRAY_SIZE (fieldDefinitionsFixed
); i
++)
255 fobj
= fieldObjects
+ i
+ fieldObjectUsed
;
256 fobj
->def
= fieldDefinitionsFixed
+ i
;
258 fobj
->nameWithPrefix
= fobj
->def
->name
;
259 fobj
->language
= LANG_IGNORE
;
260 fobj
->sibling
= FIELD_UNKNOWN
;
262 fieldObjectUsed
+= ARRAY_SIZE (fieldDefinitionsFixed
);
264 for (i
= 0; i
< ARRAY_SIZE (fieldDefinitionsExuberant
); i
++)
266 fobj
= fieldObjects
+ i
+ fieldObjectUsed
;
267 fobj
->def
= fieldDefinitionsExuberant
+i
;
269 fobj
->nameWithPrefix
= fobj
->def
->name
;
270 fobj
->language
= LANG_IGNORE
;
271 fobj
->sibling
= FIELD_UNKNOWN
;
273 fieldObjectUsed
+= ARRAY_SIZE (fieldDefinitionsExuberant
);
275 for (i
= 0; i
< ARRAY_SIZE (fieldDefinitionsUniversal
); i
++)
277 char *nameWithPrefix
;
279 fobj
= fieldObjects
+ i
+ fieldObjectUsed
;
280 fobj
->def
= fieldDefinitionsUniversal
+ i
;
285 nameWithPrefix
= eMalloc (sizeof CTAGS_FIELD_PREFIX
+ strlen (fobj
->def
->name
) + 1);
286 nameWithPrefix
[0] = '\0';
287 strcat (nameWithPrefix
, CTAGS_FIELD_PREFIX
);
288 strcat (nameWithPrefix
, fobj
->def
->name
);
289 fobj
->nameWithPrefix
= nameWithPrefix
;
290 DEFAULT_TRASH_BOX(nameWithPrefix
, eFree
);
293 fobj
->nameWithPrefix
= NULL
;
294 fobj
->language
= LANG_IGNORE
;
295 fobj
->sibling
= FIELD_UNKNOWN
;
297 fieldObjectUsed
+= ARRAY_SIZE (fieldDefinitionsUniversal
);
299 Assert ( fieldObjectAllocated
== fieldObjectUsed
);
302 static fieldObject
* getFieldObject(fieldType type
)
304 Assert ((0 <= type
) && ((unsigned int)type
< fieldObjectUsed
));
305 return fieldObjects
+ type
;
308 extern fieldType
getFieldTypeForOption (char letter
)
312 for (i
= 0; i
< fieldObjectUsed
; i
++)
314 if (fieldObjects
[i
].def
->letter
== letter
)
317 return FIELD_UNKNOWN
;
320 extern fieldType
getFieldTypeForName (const char *name
)
322 return getFieldTypeForNameAndLanguage (name
, LANG_IGNORE
);
325 extern fieldType
getFieldTypeForNameAndLanguage (const char *fieldName
, langType language
)
327 static bool initialized
= false;
330 if (fieldName
== NULL
)
331 return FIELD_UNKNOWN
;
333 if (language
== LANG_AUTO
&& (initialized
== false))
336 initializeParser (LANG_AUTO
);
338 else if (language
!= LANG_IGNORE
&& (initialized
== false))
339 initializeParser (language
);
341 for (i
= 0; i
< fieldObjectUsed
; i
++)
343 if (fieldObjects
[i
].def
->name
344 && strcmp (fieldObjects
[i
].def
->name
, fieldName
) == 0
345 && ((language
== LANG_AUTO
)
346 || (fieldObjects
[i
].language
== language
)))
350 return FIELD_UNKNOWN
;
353 extern const char* getFieldDescription (fieldType type
)
357 fobj
= getFieldObject (type
);
358 return fobj
->def
->description
;
361 extern const char* getFieldName(fieldType type
)
365 fobj
= getFieldObject (type
);
366 if (Option
.putFieldPrefix
)
367 return fobj
->nameWithPrefix
;
369 return fobj
->def
->name
;
372 extern unsigned char getFieldLetter (fieldType type
)
374 fieldObject
* fobj
= getFieldObject (type
);
376 return fobj
->def
->letter
== '\0'
377 ? FIELD_NULL_LETTER_CHAR
381 extern bool doesFieldHaveValue (fieldType type
, const tagEntryInfo
*tag
)
383 if (getFieldObject(type
)->def
->isValueAvailable
)
384 return getFieldObject(type
)->def
->isValueAvailable(tag
);
389 static const char *renderAsIs (vString
* b CTAGS_ATTR_UNUSED
, const char *s
)
394 static const char *renderEscapedString (const char *s
,
395 const tagEntryInfo
*const tag CTAGS_ATTR_UNUSED
,
398 vStringCatSWithEscaping (b
, s
);
399 return vStringValue (b
);
402 static const char *renderEscapedName (const bool isTagName
,
404 const tagEntryInfo
*const tag
,
407 int unexpected_byte
= 0;
409 if (isTagName
&& (!tag
->isPseudoTag
) && (*s
== ' ' || *s
== '!'))
411 /* Don't allow a leading space or exclamation mark as it conflicts with
412 * pseudo-tags when sorting. Anything with a lower byte value is
413 * escaped by renderEscapedString() already. */
414 unexpected_byte
= *s
;
417 case ' ': vStringCatS (b
, "\\x20"); s
++; break;
418 case '!': vStringCatS (b
, "\\x21"); s
++; break;
419 default: AssertNotReached();
424 /* Find the first byte needing escaping for the warning message */
427 while (*p
> 0x1F && *p
!= 0x7F)
429 unexpected_byte
= *p
;
434 const kindDefinition
*kdef
= getTagKind (tag
);
435 verbose ("Unexpected character %#04x included in a tagEntryInfo: %s\n", unexpected_byte
, s
);
436 verbose ("File: %s, Line: %lu, Lang: %s, Kind: %c\n",
437 tag
->inputFileName
, tag
->lineNumber
, getLanguageName(tag
->langType
), kdef
->letter
);
438 verbose ("Escape the character\n");
441 return renderEscapedString (s
, tag
, b
);
444 static const char *renderFieldName (const tagEntryInfo
*const tag
, const char *value CTAGS_ATTR_UNUSED
, vString
* b
)
446 return renderEscapedName (true, tag
->name
, tag
, b
);
449 static const char *renderFieldNameNoEscape (const tagEntryInfo
*const tag
, const char *value CTAGS_ATTR_UNUSED
, vString
* b
)
451 return renderAsIs (b
, tag
->name
);
454 static bool doesContainAnyCharInName (const tagEntryInfo
*const tag
, const char *value CTAGS_ATTR_UNUSED
, const char *chars
)
456 return strpbrk (tag
->name
, chars
)? true: false;
459 static const char *renderFieldInput (const tagEntryInfo
*const tag
, const char *value CTAGS_ATTR_UNUSED
, vString
* b
)
461 const char *f
= tag
->inputFileName
;
463 if (Option
.lineDirectives
&& tag
->sourceFileName
)
464 f
= tag
->sourceFileName
;
465 return renderEscapedString (f
, tag
, b
);
468 static const char *renderFieldInputNoEscape (const tagEntryInfo
*const tag
, const char *value CTAGS_ATTR_UNUSED
, vString
* b
)
470 const char *f
= tag
->inputFileName
;
472 if (Option
.lineDirectives
&& tag
->sourceFileName
)
473 f
= tag
->sourceFileName
;
475 return renderAsIs (b
, f
);
478 static bool doesContainAnyCharInInput (const tagEntryInfo
*const tag
, const char *value CTAGS_ATTR_UNUSED
, const char *chars
)
480 const char *f
= tag
->inputFileName
;
482 if (Option
.lineDirectives
&& tag
->sourceFileName
)
483 f
= tag
->sourceFileName
;
485 return strpbrk (f
, chars
)? true: false;
488 static const char *renderFieldSignature (const tagEntryInfo
*const tag
, const char *value CTAGS_ATTR_UNUSED
, vString
* b
)
490 return renderEscapedString (WITH_DEFUALT_VALUE (tag
->extensionFields
.signature
),
494 static const char *renderFieldSignatureNoEscape (const tagEntryInfo
*const tag
, const char *value CTAGS_ATTR_UNUSED
, vString
* b
)
496 return renderAsIs (b
, WITH_DEFUALT_VALUE (tag
->extensionFields
.signature
));
499 static bool doesContainAnyCharInSignature (const tagEntryInfo
*const tag
, const char *value CTAGS_ATTR_UNUSED
, const char *chars
)
501 return (tag
->extensionFields
.signature
&& strpbrk(tag
->extensionFields
.signature
, chars
))
506 static const char *renderFieldScope (const tagEntryInfo
*const tag
, const char *value CTAGS_ATTR_UNUSED
, vString
* b
)
510 getTagScopeInformation ((tagEntryInfo
*const)tag
, NULL
, &scope
);
511 return scope
? renderEscapedName (false, scope
, tag
, b
): NULL
;
514 static const char *renderFieldScopeNoEscape (const tagEntryInfo
*const tag
, const char *value CTAGS_ATTR_UNUSED
, vString
* b
)
518 getTagScopeInformation ((tagEntryInfo
*const)tag
, NULL
, &scope
);
519 return scope
? renderAsIs (b
, scope
): NULL
;
522 static bool doesContainAnyCharInFieldScope (const tagEntryInfo
*const tag
, const char *value CTAGS_ATTR_UNUSED
, const char *chars
)
526 getTagScopeInformation ((tagEntryInfo
*const)tag
, NULL
, &scope
);
527 return (scope
&& strpbrk (scope
, chars
));
531 static const char *renderFieldInherits (const tagEntryInfo
*const tag
, const char *value CTAGS_ATTR_UNUSED
, vString
* b
)
533 return renderEscapedString (WITH_DEFUALT_VALUE (tag
->extensionFields
.inheritance
),
537 static const char *renderFieldTyperef (const tagEntryInfo
*const tag
, const char *value CTAGS_ATTR_UNUSED
, vString
* b
)
539 /* Return "-" instead of "-:-". */
540 if (tag
->extensionFields
.typeRef
[0] == NULL
541 && tag
->extensionFields
.typeRef
[1] == NULL
)
542 return renderAsIs (b
, FIELD_NULL_LETTER_STRING
);
544 vStringCatS (b
, WITH_DEFUALT_VALUE (tag
->extensionFields
.typeRef
[0]));
546 return renderEscapedName (false, WITH_DEFUALT_VALUE (tag
->extensionFields
.typeRef
[1]), tag
, b
);
550 static const char* renderFieldCommon (fieldType type
,
551 const tagEntryInfo
*tag
,
555 fieldObject
*fobj
= fieldObjects
+ type
;
560 Assert (index
< 0 || ((unsigned int)index
) < tag
->usedParserFields
);
564 const tagField
*f
= getParserFieldForIndex (tag
, index
);
572 rfn
= fobj
->def
->renderNoEscaping
;
574 rfn
= fobj
->def
->render
;
577 fobj
->buffer
= vStringNewOrClearWithAutoRelease (fobj
->buffer
);
578 return rfn (tag
, value
, fobj
->buffer
);
581 extern const char* renderField (fieldType type
, const tagEntryInfo
*tag
, int index
)
583 return renderFieldCommon (type
, tag
, index
, false);
586 extern const char* renderFieldNoEscaping (fieldType type
, const tagEntryInfo
*tag
, int index
)
588 return renderFieldCommon (type
, tag
, index
, true);
591 static bool defaultDoesContainAnyChar (const tagEntryInfo
*const tag CTAGS_ATTR_UNUSED
, const char* value
, const char* chars
)
593 return strpbrk (value
, chars
)? true: false;
596 extern bool doesFieldHaveTabOrNewlineChar (fieldType type
, const tagEntryInfo
*tag
, int index
)
598 fieldObject
*fobj
= fieldObjects
+ type
;
600 bool (* doesContainAnyChar
) (const tagEntryInfo
*const, const char*, const char*) = fobj
->def
->doesContainAnyChar
;
603 Assert (index
== NO_PARSER_FIELD
|| ((unsigned int)index
) < tag
->usedParserFields
);
605 if (doesContainAnyChar
== NULL
)
607 if (index
== NO_PARSER_FIELD
)
610 doesContainAnyChar
= defaultDoesContainAnyChar
;
615 const tagField
*f
= getParserFieldForIndex (tag
, index
);
622 return (* doesContainAnyChar
) (tag
, value
, "\t\n");
625 /* Writes "line", stripping leading and duplicate white space.
627 static const char* renderCompactInputLine (vString
*b
, const char *const line
)
629 bool lineStarted
= false;
633 /* Write everything up to, but not including, the newline.
635 for (p
= line
, c
= *p
; c
!= NEWLINE
&& c
!= '\0' ; c
= *++p
)
637 if (lineStarted
|| ! isspace (c
)) /* ignore leading spaces */
644 /* Consume repeating white space.
646 while (next
= *(p
+1) , isspace (next
) && next
!= NEWLINE
)
648 c
= ' '; /* force space character for any white space */
650 if (c
!= CRETURN
|| *(p
+ 1) != NEWLINE
)
654 return vStringValue (b
);
657 static const char *renderFieldKindName (const tagEntryInfo
*const tag
, const char *value CTAGS_ATTR_UNUSED
, vString
* b
)
659 const char* name
= getTagKindName (tag
);
660 return renderAsIs (b
, name
);
663 static const char *renderFieldCompactInputLine (const tagEntryInfo
*const tag
,
664 const char *value CTAGS_ATTR_UNUSED
,
670 if (tag
->isPseudoTag
)
672 Assert (tag
->pattern
);
676 tmp
= vStringNewOrClearWithAutoRelease (tmp
);
678 line
= readLineFromBypassForTag (tmp
, tag
, NULL
);
680 renderCompactInputLine (b
, line
);
683 /* If no associated line for tag is found, we cannot prepare
684 * parameter to writeCompactInputLine(). In this case we
685 * use an empty string as LINE.
690 return vStringValue (b
);
693 static const char *renderFieldLineNumber (const tagEntryInfo
*const tag
,
694 const char *value CTAGS_ATTR_UNUSED
,
697 long ln
= tag
->lineNumber
;
698 char buf
[32] = {[0] = '\0'};
700 if (Option
.lineDirectives
&& (tag
->sourceLineNumberDifference
!= 0))
701 ln
+= tag
->sourceLineNumberDifference
;
702 snprintf (buf
, sizeof(buf
), "%ld", ln
);
703 vStringCatS (b
, buf
);
704 return vStringValue (b
);
707 static const char *renderFieldRoles (const tagEntryInfo
*const tag
,
708 const char *value CTAGS_ATTR_UNUSED
,
711 roleBitsType rbits
= tag
->extensionFields
.roleBits
;
712 const roleDefinition
* role
;
715 int roleCount
= countLanguageRoles (tag
->langType
, tag
->kindIndex
);
716 int nRoleWritten
= 0;
718 for (int roleIndex
= 0; roleIndex
< roleCount
; roleIndex
++)
720 if (((rbits
>> roleIndex
) & (roleBitsType
)1)
721 && isLanguageRoleEnabled (tag
->langType
, tag
->kindIndex
, roleIndex
))
723 if (nRoleWritten
> 0)
726 role
= getTagRole(tag
, roleIndex
);
727 renderRole (role
, b
);
733 vStringCatS (b
, ROLE_DEFINITION_NAME
);
734 return vStringValue (b
);
737 static const char *renderFieldLanguage (const tagEntryInfo
*const tag
,
738 const char *value CTAGS_ATTR_UNUSED
,
743 if (Option
.lineDirectives
&& (tag
->sourceLangType
!= LANG_IGNORE
))
744 l
= getLanguageName(tag
->sourceLangType
);
746 l
= getLanguageName(tag
->langType
);
748 return renderAsIs (b
, WITH_DEFUALT_VALUE(l
));
751 static const char *renderFieldAccess (const tagEntryInfo
*const tag
,
752 const char *value CTAGS_ATTR_UNUSED
,
755 return renderAsIs (b
, WITH_DEFUALT_VALUE (tag
->extensionFields
.access
));
758 static const char *renderFieldKindLetter (const tagEntryInfo
*const tag
,
759 const char *value CTAGS_ATTR_UNUSED
,
762 static char c
[2] = { [1] = '\0' };
764 c
[0] = getTagKindLetter(tag
);
766 return renderAsIs (b
, c
);
769 static const char *renderFieldImplementation (const tagEntryInfo
*const tag
,
770 const char *value CTAGS_ATTR_UNUSED
,
773 return renderAsIs (b
, WITH_DEFUALT_VALUE (tag
->extensionFields
.implementation
));
776 static const char *renderFieldFile (const tagEntryInfo
*const tag
,
777 const char *value CTAGS_ATTR_UNUSED
,
780 return renderAsIs (b
, tag
->isFileScope
? "file": FIELD_NULL_LETTER_STRING
);
783 static const char *renderFieldPattern (const tagEntryInfo
*const tag
,
784 const char *value CTAGS_ATTR_UNUSED
,
787 if (tag
->isFileEntry
)
789 else if (tag
->pattern
)
790 vStringCatS (b
, tag
->pattern
);
795 tmp
= makePatternString (tag
);
796 vStringCatS (b
, tmp
);
799 return vStringValue (b
);
802 static const char *renderFieldRefMarker (const tagEntryInfo
*const tag
,
803 const char *value CTAGS_ATTR_UNUSED
,
806 static char c
[2] = { [1] = '\0' };
808 c
[0] = (tag
->extensionFields
.roleBits
)? 'R': 'D';
810 return renderAsIs (b
, c
);
813 static const char *renderFieldExtras (const tagEntryInfo
*const tag
,
814 const char *value CTAGS_ATTR_UNUSED
,
818 bool hasExtra
= false;
819 int c
= countXtags();
821 for (i
= 0; i
< c
; i
++)
823 const char *name
= getXtagName (i
);
828 if (isTagExtraBitMarked (tag
, i
))
833 vStringCatS (b
, name
);
839 return vStringValue (b
);
844 static const char *renderFieldXpath (const tagEntryInfo
*const tag
,
845 const char *value CTAGS_ATTR_UNUSED
,
849 if (tag
->extensionFields
.xpath
)
850 return renderEscapedString (tag
->extensionFields
.xpath
,
856 static const char *renderFieldScopeKindName(const tagEntryInfo
*const tag
,
857 const char *value CTAGS_ATTR_UNUSED
,
862 getTagScopeInformation ((tagEntryInfo
*const)tag
, &kind
, NULL
);
863 return kind
? renderAsIs (b
, kind
): NULL
;
866 static const char *renderFieldEnd (const tagEntryInfo
*const tag
,
867 const char *value CTAGS_ATTR_UNUSED
,
872 if (tag
->extensionFields
.endLine
!= 0)
874 sprintf (buf
, "%lu", tag
->extensionFields
.endLine
);
875 return renderAsIs (b
, buf
);
881 static bool isLanguageFieldAvailable (const tagEntryInfo
*const tag
)
883 return (tag
->langType
== LANG_IGNORE
)? false: true;
886 static bool isTyperefFieldAvailable (const tagEntryInfo
*const tag
)
888 return (tag
->extensionFields
.typeRef
[0] != NULL
889 && tag
->extensionFields
.typeRef
[1] != NULL
)? true: false;
892 static bool isFileFieldAvailable (const tagEntryInfo
*const tag
)
894 return tag
->isFileScope
? true: false;
897 static bool isInheritsFieldAvailable (const tagEntryInfo
*const tag
)
899 return (tag
->extensionFields
.inheritance
!= NULL
)? true: false;
902 static bool isAccessFieldAvailable (const tagEntryInfo
*const tag
)
904 return (tag
->extensionFields
.access
!= NULL
)? true: false;
907 static bool isImplementationFieldAvailable (const tagEntryInfo
*const tag
)
909 return (tag
->extensionFields
.implementation
!= NULL
)? true: false;
912 static bool isSignatureFieldAvailable (const tagEntryInfo
*const tag
)
914 return (tag
->extensionFields
.signature
!= NULL
)? true: false;
917 static bool isExtrasFieldAvailable (const tagEntryInfo
*const tag
)
920 for (i
= 0; i
< sizeof (tag
->extra
); i
++)
924 else if (tag
->extraDynamic
)
931 static bool isXpathFieldAvailable (const tagEntryInfo
*const tag
)
934 return (tag
->extensionFields
.xpath
!= NULL
)? true: false;
940 static bool isEndFieldAvailable (const tagEntryInfo
*const tag
)
942 return (tag
->extensionFields
.endLine
!= 0)? true: false;
945 extern bool isFieldEnabled (fieldType type
)
947 return getFieldObject(type
)->def
->enabled
;
950 extern bool enableField (fieldType type
, bool state
, bool warnIfFixedField
)
952 fieldDefinition
*def
= getFieldObject(type
)->def
;
953 bool old
= def
->enabled
;
954 if (writerDoesTreatFieldAsFixed (type
))
956 if ((!state
) && warnIfFixedField
)
958 if (def
->name
&& def
->letter
!= NUL_FIELD_LETTER
)
959 error(WARNING
, "Cannot disable fixed field: '%c'{%s}",
960 def
->letter
, def
->name
);
962 error(WARNING
, "Cannot disable fixed field: {%s}",
964 else if (def
->letter
!= NUL_FIELD_LETTER
)
965 error(WARNING
, "Cannot disable fixed field: '%c'",
966 getFieldObject(type
)->def
->letter
);
973 getFieldObject(type
)->def
->enabled
= state
;
975 if (isCommonField (type
))
976 verbose ("enable field \"%s\": %s\n",
977 getFieldObject(type
)->def
->name
,
978 (state
? "yes": "no"));
980 verbose ("enable field \"%s\"<%s>: %s\n",
981 getFieldObject(type
)->def
->name
,
982 getLanguageName (getFieldOwner(type
)),
983 (state
? "yes": "no"));
988 extern bool isCommonField (fieldType type
)
990 return (FIELD_BUILTIN_LAST
< type
)? false: true;
993 extern int getFieldOwner (fieldType type
)
995 return getFieldObject(type
)->language
;
998 extern unsigned int getFieldDataType (fieldType type
)
1000 return getFieldObject(type
)->def
->dataType
;
1003 extern bool doesFieldHaveRenderer (fieldType type
, bool noEscaping
)
1006 return getFieldObject(type
)->def
->renderNoEscaping
? true: false;
1008 return getFieldObject(type
)->def
->render
? true: false;
1011 extern int countFields (void)
1013 return fieldObjectUsed
;
1016 extern fieldType
nextSiblingField (fieldType type
)
1020 fobj
= fieldObjects
+ type
;
1021 return fobj
->sibling
;
1024 static void updateSiblingField (fieldType type
, const char* name
)
1029 for (i
= type
; i
> 0; i
--)
1031 fobj
= fieldObjects
+ i
- 1;
1032 if (fobj
->def
->name
&& (strcmp (fobj
->def
->name
, name
) == 0))
1034 Assert (fobj
->sibling
== FIELD_UNKNOWN
);
1035 fobj
->sibling
= type
;
1041 static const char* defaultRenderer (const tagEntryInfo
*const tag CTAGS_ATTR_UNUSED
,
1043 vString
* buffer CTAGS_ATTR_UNUSED
)
1045 return renderEscapedString (value
, tag
, buffer
);
1048 extern int defineField (fieldDefinition
*def
, langType language
)
1051 char *nameWithPrefix
;
1056 for (i
= 0; i
< strlen (def
->name
); i
++)
1058 Assert ( isalpha (def
->name
[i
]) );
1060 def
->letter
= NUL_FIELD_LETTER
;
1062 if (fieldObjectUsed
== fieldObjectAllocated
)
1064 fieldObjectAllocated
*= 2;
1065 fieldObjects
= xRealloc (fieldObjects
, fieldObjectAllocated
, fieldObject
);
1067 fobj
= fieldObjects
+ (fieldObjectUsed
);
1068 def
->ftype
= fieldObjectUsed
++;
1070 if (def
->render
== NULL
)
1072 def
->render
= defaultRenderer
;
1073 def
->renderNoEscaping
= NULL
;
1074 def
->doesContainAnyChar
= NULL
;
1077 if (! def
->dataType
)
1078 def
->dataType
= FIELDTYPE_STRING
;
1082 fobj
->buffer
= NULL
;
1084 nameWithPrefix
= eMalloc (sizeof CTAGS_FIELD_PREFIX
+ strlen (def
->name
) + 1);
1085 nameWithPrefix
[0] = '\0';
1086 strcat (nameWithPrefix
, CTAGS_FIELD_PREFIX
);
1087 strcat (nameWithPrefix
, def
->name
);
1088 fobj
->nameWithPrefix
= nameWithPrefix
;
1089 DEFAULT_TRASH_BOX(nameWithPrefix
, eFree
);
1091 fobj
->language
= language
;
1092 fobj
->sibling
= FIELD_UNKNOWN
;
1094 updateSiblingField (def
->ftype
, def
->name
);
1098 #define FIELD_COL_LETTER 0
1099 #define FIELD_COL_NAME 1
1100 #define FIELD_COL_ENABLED 2
1101 #define FIELD_COL_LANGUAGE 3
1102 #define FIELD_COL_JSTYPE 4
1103 #define FIELD_COL_FIXED 5
1104 #define FIELD_COL_DESCRIPTION 6
1105 extern struct colprintTable
* fieldColprintTableNew (void)
1107 return colprintTableNew ("L:LETTER", "L:NAME", "L:ENABLED",
1108 "L:LANGUAGE", "L:JSTYPE", "L:FIXED", "L:DESCRIPTION", NULL
);
1111 static void fieldColprintAddLine (struct colprintTable
*table
, int i
)
1113 fieldObject
*fobj
= getFieldObject(i
);
1114 fieldDefinition
*fdef
= fobj
->def
;
1116 struct colprintLine
*line
= colprintTableGetNewLine(table
);
1118 colprintLineAppendColumnChar (line
,
1119 (fdef
->letter
== NUL_FIELD_LETTER
)
1120 ? FIELD_NULL_LETTER_CHAR
1123 const char *name
= getFieldName (i
);
1124 colprintLineAppendColumnCString (line
, name
? name
: RSV_NONE
);
1125 colprintLineAppendColumnBool (line
, fdef
->enabled
);
1126 colprintLineAppendColumnCString (line
,
1127 fobj
->language
== LANG_IGNORE
1129 : getLanguageName (fobj
->language
));
1131 char typefields
[] = "---";
1133 unsigned int bmask
, offset
;
1134 unsigned int type
= getFieldDataType(i
);
1135 for (bmask
= 1, offset
= 0;
1136 bmask
< FIELDTYPE_END_MARKER
;
1137 bmask
<<= 1, offset
++)
1139 typefields
[offset
] = fieldDataTypeFalgs
[offset
];
1141 colprintLineAppendColumnCString (line
, typefields
);
1142 colprintLineAppendColumnBool (line
, writerDoesTreatFieldAsFixed (i
));
1143 colprintLineAppendColumnCString (line
, fdef
->description
);
1146 extern void fieldColprintAddCommonLines (struct colprintTable
*table
)
1148 for (int i
= 0; i
<= FIELD_BUILTIN_LAST
; i
++)
1149 fieldColprintAddLine(table
, i
);
1152 extern void fieldColprintAddLanguageLines (struct colprintTable
*table
, langType language
)
1154 for (unsigned int i
= FIELD_BUILTIN_LAST
+ 1; i
< fieldObjectUsed
; i
++)
1156 fieldObject
*fobj
= getFieldObject(i
);
1157 if (fobj
->language
== language
)
1158 fieldColprintAddLine (table
, i
);
1162 static int fieldColprintCompareLines (struct colprintLine
*a
, struct colprintLine
*b
)
1164 const char *a_fixed
= colprintLineGetColumn (a
, FIELD_COL_FIXED
);
1165 const char *b_fixed
= colprintLineGetColumn (b
, FIELD_COL_FIXED
);
1166 const char *a_parser
= colprintLineGetColumn (a
, FIELD_COL_LANGUAGE
);
1167 const char *b_parser
= colprintLineGetColumn (b
, FIELD_COL_LANGUAGE
);
1169 if ((strcmp (a_fixed
, "yes") == 0)
1170 && (strcmp (b_fixed
, "yes") == 0))
1172 /* name, input, pattern, compact */
1173 const char *a_name
= colprintLineGetColumn (a
, FIELD_COL_NAME
);
1174 const char *b_name
= colprintLineGetColumn (b
, FIELD_COL_NAME
);
1175 const char *ref_name
;
1176 unsigned int a_index
= ~0U;
1177 unsigned int b_index
= ~0U;
1179 for (unsigned int i
= 0; i
< ARRAY_SIZE(fieldDefinitionsFixed
); i
++)
1181 ref_name
= fieldDefinitionsFixed
[i
].name
;
1182 if (strcmp (a_name
, ref_name
) == 0)
1184 if (strcmp (b_name
, ref_name
) == 0)
1186 if ((a_index
!= ~0U) || (b_index
!= ~0U))
1190 if (a_index
< b_index
)
1192 else if (a_index
== b_index
)
1197 else if ((strcmp (a_fixed
, "yes") == 0)
1198 && (strcmp (b_fixed
, "yes") != 0))
1200 else if ((strcmp (a_fixed
, "yes") != 0)
1201 && (strcmp (b_fixed
, "yes") == 0))
1204 if (strcmp (a_parser
, RSV_NONE
) == 0
1205 && strcmp (b_parser
, RSV_NONE
) != 0)
1207 else if (strcmp (a_parser
, RSV_NONE
) != 0
1208 && strcmp (b_parser
, RSV_NONE
) == 0)
1210 else if (strcmp (a_parser
, RSV_NONE
) != 0
1211 && strcmp (b_parser
, RSV_NONE
) != 0)
1214 r
= strcmp (a_parser
, b_parser
);
1218 const char *a_name
= colprintLineGetColumn (a
, FIELD_COL_NAME
);
1219 const char *b_name
= colprintLineGetColumn (b
, FIELD_COL_NAME
);
1221 return strcmp(a_name
, b_name
);
1225 const char *a_letter
= colprintLineGetColumn (a
, FIELD_COL_LETTER
);
1226 const char *b_letter
= colprintLineGetColumn (b
, FIELD_COL_LETTER
);
1228 return strcmp(a_letter
, b_letter
);
1232 extern void fieldColprintTablePrint (struct colprintTable
*table
,
1233 bool withListHeader
, bool machinable
, FILE *fp
)
1235 colprintTableSort (table
, fieldColprintCompareLines
);
1236 colprintTablePrint (table
, 0, withListHeader
, machinable
, fp
);