1 /*
2 *
3 * Copyright (c) 2015, Red Hat, Inc.
4 * Copyright (c) 2015, Masatake YAMATO
5 *
6 * Author: Masatake YAMATO <yamato@redhat.com>
7 *
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.
10 *
11 */
12
13 #include "general.h" /* must always come first */
14
15 #include <errno.h>
16 #include <stdlib.h>
17 #include <string.h>
18
19 #include "ctags.h"
20 #include "debug.h"
21 #include "entry.h"
22 #include "entry_p.h"
23 #include "field.h"
24 #include "field_p.h"
25 #include "kind.h"
26 #include "options_p.h"
27 #include "parse_p.h"
28 #include "read.h"
29 #include "routines.h"
30 #include "trashbox.h"
31 #include "writer_p.h"
32 #include "xtag_p.h"
33
34 #include "optscript.h"
35 #include "script_p.h"
36
37 #define FIELD_NULL_LETTER_CHAR '-'
38 #define FIELD_NULL_LETTER_STRING "-"
39
40 typedef struct sFieldObject {
41 fieldDefinition *def;
42 vString *buffer;
43 const char* nameWithPrefix;
44 langType language;
45 fieldType sibling;
46 } fieldObject;
47
48 static const char *renderFieldName (const tagEntryInfo *const tag, const char *value, vString* b);
49 static const char *renderFieldNameNoEscape (const tagEntryInfo *const tag, const char *value CTAGS_ATTR_UNUSED, vString* b);
50 static const char *renderFieldInput (const tagEntryInfo *const tag, const char *value, vString* b);
51 static const char *renderFieldInputNoEscape (const tagEntryInfo *const tag, const char *value, vString* b);
52 static const char *renderFieldCompactInputLine (const tagEntryInfo *const tag, const char *value, vString* b);
53 static const char *renderFieldSignature (const tagEntryInfo *const tag, const char *value, vString* b);
54 static const char *renderFieldSignatureNoEscape (const tagEntryInfo *const tag, const char *value, vString* b);
55 static const char *renderFieldScope (const tagEntryInfo *const tag, const char *value, vString* b);
56 static const char *renderFieldScopeNoEscape (const tagEntryInfo *const tag, const char *value, vString* b);
57 static const char *renderFieldTyperef (const tagEntryInfo *const tag, const char *value, vString* b);
58 static const char *renderFieldInherits (const tagEntryInfo *const tag, const char *value, vString* b);
59 static const char *renderFieldKindName (const tagEntryInfo *const tag, const char *value, vString* b);
60 static const char *renderFieldLineNumber (const tagEntryInfo *const tag, const char *value, vString* b);
61 static const char *renderFieldLanguage (const tagEntryInfo *const tag, const char *value, vString* b);
62 static const char *renderFieldAccess (const tagEntryInfo *const tag, const char *value, vString* b);
63 static const char *renderFieldKindLetter (const tagEntryInfo *const tag, const char *value, vString* b);
64 static const char *renderFieldImplementation (const tagEntryInfo *const tag, const char *value, vString* b);
65 static const char *renderFieldFile (const tagEntryInfo *const tag, const char *value, vString* b);
66 static const char *renderFieldPattern (const tagEntryInfo *const tag, const char *value, vString* b);
67 static const char *renderFieldRoles (const tagEntryInfo *const tag, const char *value, vString* b);
68 static const char *renderFieldRefMarker (const tagEntryInfo *const tag, const char *value, vString* b);
69 static const char *renderFieldExtras (const tagEntryInfo *const tag, const char *value, vString* b);
70 static const char *renderFieldXpath (const tagEntryInfo *const tag, const char *value, vString* b);
71 static const char *renderFieldScopeKindName(const tagEntryInfo *const tag, const char *value, vString* b);
72 static const char *renderFieldEnd (const tagEntryInfo *const tag, const char *value, vString* b);
73 static const char *renderFieldEpoch (const tagEntryInfo *const tag, const char *value, vString* b);
74 static const char *renderFieldNth (const tagEntryInfo *const tag, const char *value, vString* b);
75
76 static bool doesContainAnyCharInName (const tagEntryInfo *const tag, const char *value, const char *chars);
77 static bool doesContainAnyCharInInput (const tagEntryInfo *const tag, const char*value, const char *chars);
78 static bool doesContainAnyCharInFieldScope (const tagEntryInfo *const tag, const char *value, const char *chars);
79 static bool doesContainAnyCharInSignature (const tagEntryInfo *const tag, const char *value, const char *chars);
80
81 static bool isTyperefFieldAvailable (const tagEntryInfo *const tag);
82 static bool isFileFieldAvailable (const tagEntryInfo *const tag);
83 static bool isInheritsFieldAvailable (const tagEntryInfo *const tag);
84 static bool isAccessFieldAvailable (const tagEntryInfo *const tag);
85 static bool isImplementationFieldAvailable (const tagEntryInfo *const tag);
86 static bool isSignatureFieldAvailable (const tagEntryInfo *const tag);
87 static bool isExtrasFieldAvailable (const tagEntryInfo *const tag);
88 static bool isXpathFieldAvailable (const tagEntryInfo *const tag);
89 static bool isEndFieldAvailable (const tagEntryInfo *const tag);
90 static bool isEpochAvailable (const tagEntryInfo *const tag);
91 static bool isNthAvailable (const tagEntryInfo *const tag);
92
93 static EsObject* getFieldValueForName (const tagEntryInfo *, const fieldDefinition *);
94 static EsObject* setFieldValueForName (tagEntryInfo *, const fieldDefinition *, const EsObject *);
95 static EsObject* getFieldValueForInput (const tagEntryInfo *, const fieldDefinition *);
96 static EsObject* getFieldValueForKind (const tagEntryInfo *, const fieldDefinition *);
97 static EsObject* getFieldValueForTyperef (const tagEntryInfo *, const fieldDefinition *);
98 static EsObject* setFieldValueForTyperef (tagEntryInfo *, const fieldDefinition *, const EsObject *);
99 static EsObject* checkFieldValueForTyperef (const fieldDefinition *, const EsObject *);
100 static EsObject* getFieldValueForScope (const tagEntryInfo *, const fieldDefinition *);
101 static EsObject* setFieldValueForScope (tagEntryInfo *, const fieldDefinition *, const EsObject *);
102 static EsObject* checkFieldValueForScope (const fieldDefinition *, const EsObject *);
103 static EsObject* getFieldValueForExtras (const tagEntryInfo *, const fieldDefinition *);
104 static EsObject* getFieldValueForAccess (const tagEntryInfo *, const fieldDefinition *);
105 static EsObject* setFieldValueForAccess (tagEntryInfo *, const fieldDefinition *, const EsObject *);
106 static EsObject* getFieldValueForSignature (const tagEntryInfo *, const fieldDefinition *);
107 static EsObject* setFieldValueForSignature (tagEntryInfo *, const fieldDefinition *, const EsObject *);
108 static EsObject* getFieldValueForRoles (const tagEntryInfo *, const fieldDefinition *);
109 static EsObject* getFieldValueForLineCommon (const tagEntryInfo *, const fieldDefinition *);
110 static EsObject* checkFieldValueForLineCommon (const fieldDefinition *, const EsObject *);
111 static EsObject* setFieldValueForLineCommon (tagEntryInfo *, const fieldDefinition *, const EsObject *);
112 static EsObject* setFieldValueForInherits (tagEntryInfo *, const fieldDefinition *, const EsObject *);
113
114 #define WITH_DEFUALT_VALUE(str) ((str)?(str):FIELD_NULL_LETTER_STRING)
115
116 static fieldDefinition fieldDefinitionsFixed [] = {
117 [FIELD_NAME] = {
118 .letter = 'N',
119 .name = "name",
120 .description = "tag name",
121 .enabled = true,
122 .render = renderFieldName,
123 .renderNoEscaping = renderFieldNameNoEscape,
124 .doesContainAnyChar = doesContainAnyCharInName,
125 .isValueAvailable = NULL,
126 .dataType = FIELDTYPE_STRING,
127 .getterValueType = NULL,
128 .getValueObject = getFieldValueForName,
129 .setterValueType = NULL,
130 .checkValueForSetter= NULL,
131 .setValueObject = setFieldValueForName,
132 },
133 [FIELD_INPUT_FILE] = {
134 .letter = 'F',
135 .name = "input",
136 .description = "input file",
137 .enabled = true,
138 .render = renderFieldInput,
139 .renderNoEscaping = renderFieldInputNoEscape,
140 .doesContainAnyChar = doesContainAnyCharInInput,
141 .isValueAvailable = NULL,
142 .dataType = FIELDTYPE_STRING,
143 .getterValueType = NULL,
144 .getValueObject = getFieldValueForInput,
145 .setterValueType = NULL,
146 .checkValueForSetter= NULL,
147 .setValueObject = NULL,
148 },
149 [FIELD_PATTERN] = {
150 .letter = 'P',
151 .name = "pattern",
152 .description = "pattern",
153 .enabled = true,
154 .render = renderFieldPattern,
155 .renderNoEscaping = NULL,
156 .doesContainAnyChar = NULL,
157 .isValueAvailable = NULL,
158 .dataType = FIELDTYPE_STRING|FIELDTYPE_BOOL,
159 },
160 };
161
162 static fieldDefinition fieldDefinitionsExuberant [] = {
163 [FIELD_COMPACT_INPUT_LINE - FIELD_ECTAGS_START] = {
164 .letter = 'C',
165 .name = "compact",
166 .description = "compact input line (used only in xref output)",
167 .enabled = false,
168 .render = renderFieldCompactInputLine,
169 .renderNoEscaping = NULL,
170 .doesContainAnyChar = NULL,
171 .isValueAvailable = NULL,
172 .dataType = FIELDTYPE_STRING,
173 },
174 [FIELD_FILE_SCOPE - FIELD_ECTAGS_START] = {
175 .letter = 'f',
176 .name = "file",
177 .description = "File-restricted scoping",
178 .enabled = true,
179 .render = renderFieldFile,
180 .renderNoEscaping = NULL,
181 .doesContainAnyChar = NULL,
182 .isValueAvailable = isFileFieldAvailable,
183 .dataType = FIELDTYPE_BOOL,
184 },
185 [FIELD_KIND_LONG - FIELD_ECTAGS_START] = {
186 .letter = 'K',
187 .name = NULL,
188 .description = "Kind of tag in long-name form",
189 .enabled = false,
190 .render = renderFieldKindName,
191 .renderNoEscaping = NULL,
192 .doesContainAnyChar = NULL,
193 .isValueAvailable = NULL,
194 .dataType = FIELDTYPE_STRING,
195 },
196 [FIELD_KIND - FIELD_ECTAGS_START] = {
197 .letter ='k',
198 .name = NULL,
199 .description = "Kind of tag in one-letter form",
200 .enabled = true,
201 .render = renderFieldKindLetter,
202 .renderNoEscaping = NULL,
203 .doesContainAnyChar = NULL,
204 .isValueAvailable = NULL,
205 .dataType = FIELDTYPE_STRING,
206 },
207 [FIELD_LANGUAGE - FIELD_ECTAGS_START] = {
208 .letter = 'l',
209 .name = "language",
210 .description = "Language of input file containing tag",
211 .enabled = false,
212 .render = renderFieldLanguage,
213 .renderNoEscaping = NULL,
214 .doesContainAnyChar = NULL,
215 .dataType = FIELDTYPE_STRING,
216 },
217 [FIELD_LINE_NUMBER - FIELD_ECTAGS_START] = {
218 .letter = 'n',
219 .name = "line",
220 .description = "Line number of tag definition",
221 .enabled = false,
222 .render = renderFieldLineNumber,
223 .renderNoEscaping = NULL,
224 .doesContainAnyChar = NULL,
225 .isValueAvailable = NULL,
226 .dataType = FIELDTYPE_INTEGER,
227 .getterValueType = "int",
228 .getValueObject = getFieldValueForLineCommon,
229 .setterValueType = "matchloc|int",
230 .checkValueForSetter= checkFieldValueForLineCommon,
231 .setValueObject = setFieldValueForLineCommon,
232 },
233 [FIELD_SCOPE - FIELD_ECTAGS_START] = {
234 .letter = 's',
235 .name = NULL,
236 .description = "[tags output] scope (kind:name) of tag definition, [xref and json output] name of scope",
237 .enabled = true,
238 .render = renderFieldScope,
239 .renderNoEscaping = renderFieldScopeNoEscape,
240 .doesContainAnyChar = doesContainAnyCharInFieldScope,
241 .isValueAvailable = NULL,
242 .dataType = FIELDTYPE_STRING,
243 },
244 [FIELD_TYPE_REF - FIELD_ECTAGS_START] = {
245 .letter = 't',
246 .name = "typeref",
247 .description = "Type and name of a variable or typedef",
248 .enabled = true,
249 .render = renderFieldTyperef,
250 .renderNoEscaping = NULL,
251 .doesContainAnyChar = NULL,
252 .isValueAvailable = isTyperefFieldAvailable,
253 .dataType = FIELDTYPE_STRING,
254 .getterValueType = "[string string]",
255 .getValueObject = getFieldValueForTyperef,
256 .setterValueType = "[string string]|string|index:int|false",
257 .checkValueForSetter= checkFieldValueForTyperef,
258 .setValueObject = setFieldValueForTyperef,
259 },
260 [FIELD_KIND_KEY - FIELD_ECTAGS_START] = {
261 .letter = 'z',
262 .name = "kind",
263 .description = "[tags output] prepend \"kind:\" to k/ (or K/) field output, [xref and json output] kind in long-name form",
264 .enabled = false,
265 /* Following renderer is for handling --_xformat=%{kind};
266 and is not for tags output. */
267 .render = renderFieldKindName,
268 .renderNoEscaping = NULL,
269 .doesContainAnyChar = NULL,
270 .isValueAvailable = NULL,
271 .dataType = FIELDTYPE_STRING,
272 .getterValueType = "name",
273 .getValueObject = getFieldValueForKind,
274 .setterValueType = NULL,
275 .checkValueForSetter= NULL,
276 .setValueObject = NULL,
277 },
278 [FIELD_INHERITANCE - FIELD_ECTAGS_START] = {
279 .letter = 'i',
280 .name = "inherits",
281 .description = "Inheritance information",
282 .enabled = false,
283 .render = renderFieldInherits,
284 .renderNoEscaping = NULL,
285 .doesContainAnyChar = NULL,
286 .isValueAvailable = isInheritsFieldAvailable,
287 .dataType = FIELDTYPE_STRING|FIELDTYPE_BOOL,
288 .getterValueType = NULL,
289 .getValueObject = NULL,
290 .setterValueType = NULL,
291 .checkValueForSetter= NULL,
292 .setValueObject = setFieldValueForInherits,
293 },
294 [FIELD_ACCESS - FIELD_ECTAGS_START] = {
295 .letter = 'a',
296 .name = "access",
297 .description = "Access (or export) of class members",
298 .enabled = false,
299 .render = renderFieldAccess,
300 .renderNoEscaping = NULL,
301 .doesContainAnyChar = NULL,
302 .isValueAvailable = isAccessFieldAvailable,
303 .dataType = FIELDTYPE_STRING,
304 .getterValueType = NULL,
305 .getValueObject = getFieldValueForAccess,
306 .setterValueType = NULL,
307 .checkValueForSetter= NULL,
308 .setValueObject = setFieldValueForAccess,
309 },
310 [FIELD_IMPLEMENTATION - FIELD_ECTAGS_START] = {
311 .letter = 'm',
312 .name = "implementation",
313 .description = "Implementation information",
314 .enabled = false,
315 .render = renderFieldImplementation,
316 .renderNoEscaping = NULL,
317 .doesContainAnyChar = NULL,
318 .isValueAvailable = isImplementationFieldAvailable,
319 .dataType = FIELDTYPE_STRING,
320
321 },
322 [FIELD_SIGNATURE - FIELD_ECTAGS_START] = {
323 .letter = 'S',
324 .name = "signature",
325 .description = "Signature of routine (e.g. prototype or parameter list)",
326 .enabled = false,
327 .render = renderFieldSignature,
328 .renderNoEscaping = renderFieldSignatureNoEscape,
329 .doesContainAnyChar = doesContainAnyCharInSignature,
330 .isValueAvailable = isSignatureFieldAvailable,
331 .dataType = FIELDTYPE_STRING,
332 .getterValueType = NULL,
333 .getValueObject = getFieldValueForSignature,
334 .setterValueType = NULL,
335 .checkValueForSetter= NULL,
336 .setValueObject = setFieldValueForSignature,
337 },
338 };
339
340 static fieldDefinition fieldDefinitionsUniversal [] = {
341 [FIELD_REF_MARK - FIELDS_UCTAGS_START] = {
342 .letter = 'R',
343 .name = NULL,
344 .description = "Marker (R or D) representing whether tag is definition or reference",
345 .enabled = false,
346 .render = renderFieldRefMarker,
347 .renderNoEscaping = NULL,
348 .doesContainAnyChar = NULL,
349 .isValueAvailable = NULL,
350 .dataType = FIELDTYPE_STRING,
351 },
352 [FIELD_SCOPE_KEY - FIELDS_UCTAGS_START] = {
353 .letter = 'Z',
354 .name = "scope",
355 .description = "[tags output] prepend \"scope:\" key to s/scope field output, [xref and json output] the same as s/ field",
356 .enabled = false,
357 /* Following renderer is for handling --_xformat=%{scope};
358 and is not for tags output. */
359 .render = renderFieldScope,
360 .renderNoEscaping = renderFieldScopeNoEscape,
361 .doesContainAnyChar = doesContainAnyCharInFieldScope,
362 .isValueAvailable = NULL,
363 .dataType = FIELDTYPE_STRING,
364 .getterValueType = "int",
365 .getValueObject = getFieldValueForScope,
366 .setterValueType = "int",
367 .checkValueForSetter= checkFieldValueForScope,
368 .setValueObject = setFieldValueForScope,
369 },
370 [FIELD_SCOPE_KIND_LONG - FIELDS_UCTAGS_START] = {
371 .letter = 'p',
372 .name = "scopeKind",
373 .description = "[tags output] no effect, [xref and json output] kind of scope in long-name form",
374 .enabled = false,
375 .render = renderFieldScopeKindName,
376 .renderNoEscaping = NULL,
377 .doesContainAnyChar = NULL,
378 .isValueAvailable = NULL,
379 .dataType = FIELDTYPE_STRING,
380 },
381 [FIELD_ROLES - FIELDS_UCTAGS_START] = {
382 .letter = 'r',
383 .name = "roles",
384 .description = "Roles",
385 .enabled = false,
386 .render = renderFieldRoles,
387 .renderNoEscaping = NULL,
388 .doesContainAnyChar = NULL,
389 .isValueAvailable = NULL,
390 .dataType = FIELDTYPE_STRING,
391 .getterValueType = "[ role1:name ... rolen:name ]",
392 .getValueObject = getFieldValueForRoles,
393 .setterValueType = NULL,
394 .checkValueForSetter= NULL,
395 .setValueObject = NULL,
396 },
397 [FIELD_EXTRAS - FIELDS_UCTAGS_START] = {
398 .letter = 'E',
399 .name = "extras",
400 .description = "Extra tag type information",
401 .enabled = false,
402 .render = renderFieldExtras,
403 .renderNoEscaping = NULL,
404 .doesContainAnyChar = NULL,
405 .isValueAvailable = isExtrasFieldAvailable,
406 .dataType = FIELDTYPE_STRING,
407 .getterValueType = "[ extra1:name ... extran:name ]",
408 .getValueObject = getFieldValueForExtras,
409 .setterValueType = NULL,
410 .checkValueForSetter= NULL,
411 .setValueObject = NULL,
412 },
413 [FIELD_XPATH - FIELDS_UCTAGS_START] = {
414 .letter = 'x',
415 .name = "xpath",
416 .description = "xpath for the tag",
417 .enabled = false,
418 .render = renderFieldXpath,
419 .renderNoEscaping = NULL,
420 .doesContainAnyChar = NULL,
421 .isValueAvailable = isXpathFieldAvailable,
422 .dataType = FIELDTYPE_STRING,
423 },
424 [FIELD_END_LINE - FIELDS_UCTAGS_START] = {
425 .letter = 'e',
426 .name = "end",
427 .description = "end lines of various items",
428 .enabled = false,
429 .render = renderFieldEnd,
430 .renderNoEscaping = NULL,
431 .doesContainAnyChar = NULL,
432 .isValueAvailable = isEndFieldAvailable,
433 .dataType = FIELDTYPE_INTEGER,
434 .getterValueType = "int",
435 .getValueObject = getFieldValueForLineCommon,
436 .setterValueType = "matchloc|int",
437 .checkValueForSetter= checkFieldValueForLineCommon,
438 .setValueObject = setFieldValueForLineCommon,
439
440 },
441 [FIELD_EPOCH - FIELDS_UCTAGS_START] = {
442 .letter = 'T',
443 .name = "epoch",
444 .description = "the last modified time of the input file (only for F/file kind tag)",
445 .enabled = true,
446 .render = renderFieldEpoch,
447 .renderNoEscaping = NULL,
448 .doesContainAnyChar = NULL,
449 .isValueAvailable = isEpochAvailable,
450 .dataType = FIELDTYPE_INTEGER,
451 },
452 [FIELD_NTH - FIELDS_UCTAGS_START] = {
453 .letter = 'o',
454 .name = "nth",
455 .description = "the order in the parent scope",
456 .enabled = false,
457 .render = renderFieldNth,
458 .renderNoEscaping = NULL,
459 .doesContainAnyChar = NULL,
460 .isValueAvailable = isNthAvailable,
461 .dataType = FIELDTYPE_INTEGER,
462 },
463 };
464
465
466 static unsigned int fieldObjectUsed = 0;
467 static unsigned int fieldObjectAllocated = 0;
468 static fieldObject* fieldObjects = NULL;
469
initFieldObjects(void)470 extern void initFieldObjects (void)
471 {
472 unsigned int i;
473 fieldObject *fobj;
474
475 Assert (fieldObjects == NULL);
476
477 fieldObjectAllocated
478 = ARRAY_SIZE (fieldDefinitionsFixed)
479 + ARRAY_SIZE (fieldDefinitionsExuberant)
480 + ARRAY_SIZE (fieldDefinitionsUniversal);
481 fieldObjects = xMalloc (fieldObjectAllocated, fieldObject);
482 DEFAULT_TRASH_BOX(&fieldObjects, eFreeIndirect);
483
484 fieldObjectUsed = 0;
485
486 for (i = 0; i < ARRAY_SIZE (fieldDefinitionsFixed); i++)
487 {
488 fobj = fieldObjects + i + fieldObjectUsed;
489 fobj->def = fieldDefinitionsFixed + i;
490 fobj->buffer = NULL;
491 fobj->nameWithPrefix = fobj->def->name;
492 fobj->language = LANG_IGNORE;
493 fobj->sibling = FIELD_UNKNOWN;
494 fobj->def->ftype = i + fieldObjectUsed;
495 }
496 fieldObjectUsed += ARRAY_SIZE (fieldDefinitionsFixed);
497
498 for (i = 0; i < ARRAY_SIZE (fieldDefinitionsExuberant); i++)
499 {
500 fobj = fieldObjects + i + fieldObjectUsed;
501 fobj->def = fieldDefinitionsExuberant +i;
502 fobj->buffer = NULL;
503 fobj->nameWithPrefix = fobj->def->name;
504 fobj->language = LANG_IGNORE;
505 fobj->sibling = FIELD_UNKNOWN;
506 fobj->def->ftype = i + fieldObjectUsed;
507 }
508 fieldObjectUsed += ARRAY_SIZE (fieldDefinitionsExuberant);
509
510 for (i = 0; i < ARRAY_SIZE (fieldDefinitionsUniversal); i++)
511 {
512 char *nameWithPrefix;
513
514 fobj = fieldObjects + i + fieldObjectUsed;
515 fobj->def = fieldDefinitionsUniversal + i;
516 fobj->buffer = NULL;
517
518 if (fobj->def->name)
519 {
520 nameWithPrefix = eMalloc (sizeof CTAGS_FIELD_PREFIX + strlen (fobj->def->name) + 1);
521 nameWithPrefix [0] = '\0';
522 strcat (nameWithPrefix, CTAGS_FIELD_PREFIX);
523 strcat (nameWithPrefix, fobj->def->name);
524 fobj->nameWithPrefix = nameWithPrefix;
525 DEFAULT_TRASH_BOX(nameWithPrefix, eFree);
526 }
527 else
528 fobj->nameWithPrefix = NULL;
529 fobj->language = LANG_IGNORE;
530 fobj->sibling = FIELD_UNKNOWN;
531 fobj->def->ftype = i + fieldObjectUsed;
532 }
533 fieldObjectUsed += ARRAY_SIZE (fieldDefinitionsUniversal);
534
535 Assert ( fieldObjectAllocated == fieldObjectUsed );
536 }
537
getFieldObject(fieldType type)538 static fieldObject* getFieldObject(fieldType type)
539 {
540 Assert ((0 <= type) && ((unsigned int)type < fieldObjectUsed));
541 return fieldObjects + type;
542 }
543
getFieldTypeForOption(char letter)544 extern fieldType getFieldTypeForOption (char letter)
545 {
546 unsigned int i;
547
548 for (i = 0; i < fieldObjectUsed; i++)
549 {
550 if (fieldObjects [i].def->letter == letter)
551 return i;
552 }
553 return FIELD_UNKNOWN;
554 }
555
getFieldTypeForName(const char * name)556 extern fieldType getFieldTypeForName (const char *name)
557 {
558 return getFieldTypeForNameAndLanguage (name, LANG_IGNORE);
559 }
560
getFieldTypeForNameAndLanguage(const char * fieldName,langType language)561 extern fieldType getFieldTypeForNameAndLanguage (const char *fieldName, langType language)
562 {
563 static bool initialized = false;
564 unsigned int i;
565
566 if (fieldName == NULL)
567 return FIELD_UNKNOWN;
568
569 if (language == LANG_AUTO && (initialized == false))
570 {
571 initialized = true;
572 initializeParser (LANG_AUTO);
573 }
574 else if (language != LANG_IGNORE && (initialized == false))
575 initializeParser (language);
576
577 for (i = 0; i < fieldObjectUsed; i++)
578 {
579 if (fieldObjects [i].def->name
580 && strcmp (fieldObjects [i].def->name, fieldName) == 0
581 && ((language == LANG_AUTO)
582 || (fieldObjects [i].language == language)))
583 return i;
584 }
585
586 return FIELD_UNKNOWN;
587 }
588
getFieldDescription(fieldType type)589 extern const char* getFieldDescription (fieldType type)
590 {
591 fieldObject* fobj;
592
593 fobj = getFieldObject (type);
594 return fobj->def->description;
595 }
596
getFieldName(fieldType type)597 extern const char* getFieldName(fieldType type)
598 {
599 fieldObject* fobj;
600
601 fobj = getFieldObject (type);
602 if (Option.putFieldPrefix)
603 return fobj->nameWithPrefix;
604 else
605 return fobj->def->name;
606 }
607
getFieldLetter(fieldType type)608 extern unsigned char getFieldLetter (fieldType type)
609 {
610 fieldObject* fobj = getFieldObject (type);
611
612 return fobj->def->letter == '\0'
613 ? FIELD_NULL_LETTER_CHAR
614 : fobj->def->letter;
615 }
616
doesFieldHaveValue(fieldType type,const tagEntryInfo * tag)617 extern bool doesFieldHaveValue (fieldType type, const tagEntryInfo *tag)
618 {
619 if (getFieldObject(type)->def->isValueAvailable)
620 return getFieldObject(type)->def->isValueAvailable(tag);
621 else
622 return true;
623 }
624
renderAsIs(vString * b CTAGS_ATTR_UNUSED,const char * s)625 static const char *renderAsIs (vString* b CTAGS_ATTR_UNUSED, const char *s)
626 {
627 return s;
628 }
629
renderEscapedString(const char * s,const tagEntryInfo * const tag CTAGS_ATTR_UNUSED,vString * b)630 static const char *renderEscapedString (const char *s,
631 const tagEntryInfo *const tag CTAGS_ATTR_UNUSED,
632 vString* b)
633 {
634 vStringCatSWithEscaping (b, s);
635 return vStringValue (b);
636 }
637
renderEscapedName(const bool isTagName,const char * s,const tagEntryInfo * const tag,vString * b)638 static const char *renderEscapedName (const bool isTagName,
639 const char* s,
640 const tagEntryInfo *const tag,
641 vString* b)
642 {
643 int unexpected_byte = 0;
644
645 if (isTagName && (!tag->isPseudoTag) && (*s == ' ' || *s == '!'))
646 {
647 /* Don't allow a leading space or exclamation mark as it conflicts with
648 * pseudo-tags when sorting. Anything with a lower byte value is
649 * escaped by renderEscapedString() already. */
650 unexpected_byte = *s;
651 switch (*s)
652 {
653 case ' ': vStringCatS (b, "\\x20"); s++; break;
654 case '!': vStringCatS (b, "\\x21"); s++; break;
655 default: AssertNotReached();
656 }
657 }
658 else
659 {
660 /* Find the first byte needing escaping for the warning message */
661 const char *p = s;
662
663 while (*p > 0x1F && *p != 0x7F)
664 p++;
665 unexpected_byte = *p;
666 }
667
668 if (unexpected_byte)
669 {
670 const kindDefinition *kdef = getTagKind (tag);
671 verbose ("Unexpected character %#04x included in a tagEntryInfo: %s\n", unexpected_byte, s);
672 verbose ("File: %s, Line: %lu, Lang: %s, Kind: %c\n",
673 tag->inputFileName, tag->lineNumber, getLanguageName(tag->langType), kdef->letter);
674 verbose ("Escape the character\n");
675 }
676
677 return renderEscapedString (s, tag, b);
678 }
679
renderFieldName(const tagEntryInfo * const tag,const char * value CTAGS_ATTR_UNUSED,vString * b)680 static const char *renderFieldName (const tagEntryInfo *const tag, const char *value CTAGS_ATTR_UNUSED, vString* b)
681 {
682 return renderEscapedName (true, tag->name, tag, b);
683 }
684
renderFieldNameNoEscape(const tagEntryInfo * const tag,const char * value CTAGS_ATTR_UNUSED,vString * b)685 static const char *renderFieldNameNoEscape (const tagEntryInfo *const tag, const char *value CTAGS_ATTR_UNUSED, vString* b)
686 {
687 return renderAsIs (b, tag->name);
688 }
689
doesContainAnyCharInName(const tagEntryInfo * const tag,const char * value CTAGS_ATTR_UNUSED,const char * chars)690 static bool doesContainAnyCharInName (const tagEntryInfo *const tag, const char *value CTAGS_ATTR_UNUSED, const char *chars)
691 {
692 return strpbrk (tag->name, chars)? true: false;
693 }
694
renderFieldInput(const tagEntryInfo * const tag,const char * value CTAGS_ATTR_UNUSED,vString * b)695 static const char *renderFieldInput (const tagEntryInfo *const tag, const char *value CTAGS_ATTR_UNUSED, vString* b)
696 {
697 const char *f = tag->inputFileName;
698
699 if (Option.lineDirectives && tag->sourceFileName)
700 f = tag->sourceFileName;
701 return renderEscapedString (f, tag, b);
702 }
703
renderFieldInputNoEscape(const tagEntryInfo * const tag,const char * value CTAGS_ATTR_UNUSED,vString * b)704 static const char *renderFieldInputNoEscape (const tagEntryInfo *const tag, const char *value CTAGS_ATTR_UNUSED, vString* b)
705 {
706 const char *f = tag->inputFileName;
707
708 if (Option.lineDirectives && tag->sourceFileName)
709 f = tag->sourceFileName;
710
711 return renderAsIs (b, f);
712 }
713
doesContainAnyCharInInput(const tagEntryInfo * const tag,const char * value CTAGS_ATTR_UNUSED,const char * chars)714 static bool doesContainAnyCharInInput (const tagEntryInfo *const tag, const char *value CTAGS_ATTR_UNUSED, const char *chars)
715 {
716 const char *f = tag->inputFileName;
717
718 if (Option.lineDirectives && tag->sourceFileName)
719 f = tag->sourceFileName;
720
721 return strpbrk (f, chars)? true: false;
722 }
723
renderFieldSignature(const tagEntryInfo * const tag,const char * value CTAGS_ATTR_UNUSED,vString * b)724 static const char *renderFieldSignature (const tagEntryInfo *const tag, const char *value CTAGS_ATTR_UNUSED, vString* b)
725 {
726 return renderEscapedString (WITH_DEFUALT_VALUE (tag->extensionFields.signature),
727 tag, b);
728 }
729
renderFieldSignatureNoEscape(const tagEntryInfo * const tag,const char * value CTAGS_ATTR_UNUSED,vString * b)730 static const char *renderFieldSignatureNoEscape (const tagEntryInfo *const tag, const char *value CTAGS_ATTR_UNUSED, vString* b)
731 {
732 return renderAsIs (b, WITH_DEFUALT_VALUE (tag->extensionFields.signature));
733 }
734
doesContainAnyCharInSignature(const tagEntryInfo * const tag,const char * value CTAGS_ATTR_UNUSED,const char * chars)735 static bool doesContainAnyCharInSignature (const tagEntryInfo *const tag, const char *value CTAGS_ATTR_UNUSED, const char *chars)
736 {
737 return (tag->extensionFields.signature && strpbrk(tag->extensionFields.signature, chars))
738 ? true
739 : false;
740 }
741
renderFieldScope(const tagEntryInfo * const tag,const char * value CTAGS_ATTR_UNUSED,vString * b)742 static const char *renderFieldScope (const tagEntryInfo *const tag, const char *value CTAGS_ATTR_UNUSED, vString* b)
743 {
744 const char* scope;
745
746 getTagScopeInformation ((tagEntryInfo *const)tag, NULL, &scope);
747 return scope? renderEscapedName (false, scope, tag, b): NULL;
748 }
749
renderFieldScopeNoEscape(const tagEntryInfo * const tag,const char * value CTAGS_ATTR_UNUSED,vString * b)750 static const char *renderFieldScopeNoEscape (const tagEntryInfo *const tag, const char *value CTAGS_ATTR_UNUSED, vString* b)
751 {
752 const char* scope;
753
754 getTagScopeInformation ((tagEntryInfo *const)tag, NULL, &scope);
755 return scope? renderAsIs (b, scope): NULL;
756 }
757
doesContainAnyCharInFieldScope(const tagEntryInfo * const tag,const char * value CTAGS_ATTR_UNUSED,const char * chars)758 static bool doesContainAnyCharInFieldScope (const tagEntryInfo *const tag, const char *value CTAGS_ATTR_UNUSED, const char *chars)
759 {
760 const char* scope;
761
762 getTagScopeInformation ((tagEntryInfo *const)tag, NULL, &scope);
763 return (scope && strpbrk (scope, chars));
764 }
765
766
renderFieldInherits(const tagEntryInfo * const tag,const char * value CTAGS_ATTR_UNUSED,vString * b)767 static const char *renderFieldInherits (const tagEntryInfo *const tag, const char *value CTAGS_ATTR_UNUSED, vString* b)
768 {
769 return renderEscapedString (WITH_DEFUALT_VALUE (tag->extensionFields.inheritance),
770 tag, b);
771 }
772
renderFieldTyperef(const tagEntryInfo * const tag,const char * value CTAGS_ATTR_UNUSED,vString * b)773 static const char *renderFieldTyperef (const tagEntryInfo *const tag, const char *value CTAGS_ATTR_UNUSED, vString* b)
774 {
775 /* Return "-" instead of "-:-". */
776 if (tag->extensionFields.typeRef [0] == NULL
777 && tag->extensionFields.typeRef [1] == NULL)
778 return renderAsIs (b, FIELD_NULL_LETTER_STRING);
779
780 vStringCatS (b, WITH_DEFUALT_VALUE (tag->extensionFields.typeRef [0]));
781 vStringPut (b, ':');
782 return renderEscapedName (false, WITH_DEFUALT_VALUE (tag->extensionFields.typeRef [1]), tag, b);
783 }
784
785
renderFieldCommon(fieldType type,const tagEntryInfo * tag,int index,bool noEscaping)786 static const char* renderFieldCommon (fieldType type,
787 const tagEntryInfo *tag,
788 int index,
789 bool noEscaping)
790 {
791 fieldObject *fobj = fieldObjects + type;
792 const char *value;
793 fieldRenderer rfn;
794
795 Assert (tag);
796 Assert (index < 0 || ((unsigned int)index) < tag->usedParserFields);
797
798 if (index >= 0)
799 {
800 const tagField *f = getParserFieldForIndex (tag, index);
801
802 value = f->value;
803 }
804 else
805 value = NULL;
806
807 if (noEscaping)
808 rfn = fobj->def->renderNoEscaping;
809 else
810 rfn = fobj->def->render;
811 Assert (rfn);
812
813 fobj->buffer = vStringNewOrClearWithAutoRelease (fobj->buffer);
814 return rfn (tag, value, fobj->buffer);
815 }
816
renderField(fieldType type,const tagEntryInfo * tag,int index)817 extern const char* renderField (fieldType type, const tagEntryInfo *tag, int index)
818 {
819 return renderFieldCommon (type, tag, index, false);
820 }
821
renderFieldNoEscaping(fieldType type,const tagEntryInfo * tag,int index)822 extern const char* renderFieldNoEscaping (fieldType type, const tagEntryInfo *tag, int index)
823 {
824 return renderFieldCommon (type, tag, index, true);
825 }
826
defaultDoesContainAnyChar(const tagEntryInfo * const tag CTAGS_ATTR_UNUSED,const char * value,const char * chars)827 static bool defaultDoesContainAnyChar (const tagEntryInfo *const tag CTAGS_ATTR_UNUSED, const char* value, const char* chars)
828 {
829 return strpbrk (value, chars)? true: false;
830 }
831
doesFieldHaveTabOrNewlineChar(fieldType type,const tagEntryInfo * tag,int index)832 extern bool doesFieldHaveTabOrNewlineChar (fieldType type, const tagEntryInfo *tag, int index)
833 {
834 fieldObject *fobj = fieldObjects + type;
835 const char *value;
836 bool (* doesContainAnyChar) (const tagEntryInfo *const, const char*, const char*) = fobj->def->doesContainAnyChar;
837
838 Assert (tag);
839 Assert (index == NO_PARSER_FIELD || ((unsigned int)index) < tag->usedParserFields);
840
841 if (doesContainAnyChar == NULL)
842 {
843 if (index == NO_PARSER_FIELD)
844 return false;
845 else
846 doesContainAnyChar = defaultDoesContainAnyChar;
847 }
848
849 if (index >= 0)
850 {
851 const tagField *f = getParserFieldForIndex (tag, index);
852
853 value = f->value;
854 }
855 else
856 value = NULL;
857
858 return (* doesContainAnyChar) (tag, value, "\t\n");
859 }
860
861 /* Writes "line", stripping leading and duplicate white space.
862 */
renderCompactInputLine(vString * b,const char * const line)863 static const char* renderCompactInputLine (vString *b, const char *const line)
864 {
865 bool lineStarted = false;
866 const char *p;
867 int c;
868
869 /* Write everything up to, but not including, the newline.
870 */
871 for (p = line, c = *p ; c != NEWLINE && c != '\0' ; c = *++p)
872 {
873 if (lineStarted || ! isspace (c)) /* ignore leading spaces */
874 {
875 lineStarted = true;
876 if (isspace (c))
877 {
878 int next;
879
880 /* Consume repeating white space.
881 */
882 while (next = *(p+1) , isspace (next) && next != NEWLINE)
883 ++p;
884 c = ' '; /* force space character for any white space */
885 }
886 if (c != CRETURN || *(p + 1) != NEWLINE)
887 vStringPut (b, c);
888 }
889 }
890 return vStringValue (b);
891 }
892
renderFieldKindName(const tagEntryInfo * const tag,const char * value CTAGS_ATTR_UNUSED,vString * b)893 static const char *renderFieldKindName (const tagEntryInfo *const tag, const char *value CTAGS_ATTR_UNUSED, vString* b)
894 {
895 const char* name = getTagKindName (tag);
896 return renderAsIs (b, name);
897 }
898
renderFieldCompactInputLine(const tagEntryInfo * const tag,const char * value CTAGS_ATTR_UNUSED,vString * b)899 static const char *renderFieldCompactInputLine (const tagEntryInfo *const tag,
900 const char *value CTAGS_ATTR_UNUSED,
901 vString* b)
902 {
903 const char *line;
904 static vString *tmp;
905
906 if (tag->isPseudoTag)
907 {
908 Assert (tag->pattern);
909 return tag->pattern;
910 }
911
912 tmp = vStringNewOrClearWithAutoRelease (tmp);
913
914 line = readLineFromBypassForTag (tmp, tag, NULL);
915 if (line)
916 renderCompactInputLine (b, line);
917 else
918 {
919 /* If no associated line for tag is found, we cannot prepare
920 * parameter to writeCompactInputLine(). In this case we
921 * use an empty string as LINE.
922 */
923 vStringClear (b);
924 }
925
926 return vStringValue (b);
927 }
928
renderFieldLineNumber(const tagEntryInfo * const tag,const char * value CTAGS_ATTR_UNUSED,vString * b)929 static const char *renderFieldLineNumber (const tagEntryInfo *const tag,
930 const char *value CTAGS_ATTR_UNUSED,
931 vString* b)
932 {
933 long ln = tag->lineNumber;
934 char buf[32] = {[0] = '\0'};
935
936 if (Option.lineDirectives && (tag->sourceLineNumberDifference != 0))
937 ln += tag->sourceLineNumberDifference;
938 snprintf (buf, sizeof(buf), "%ld", ln);
939 vStringCatS (b, buf);
940 return vStringValue (b);
941 }
942
943 struct renderRoleData {
944 vString* b;
945 int nRoleWritten;
946 };
947
renderRoleByIndex(const tagEntryInfo * const tag,int roleIndex,void * data)948 static void renderRoleByIndex (const tagEntryInfo *const tag, int roleIndex, void *data)
949 {
950 struct renderRoleData *rdata = data;
951
952 if (!isLanguageRoleEnabled (tag->langType, tag->kindIndex, roleIndex))
953 return;
954
955 if (rdata->nRoleWritten > 0)
956 vStringPut(rdata->b, ',');
957
958 const roleDefinition * role = getTagRole(tag, roleIndex);
959 renderRole (role, rdata->b);
960 rdata->nRoleWritten++;
961 }
962
foreachRoleBits(const tagEntryInfo * const tag,void (* fn)(const tagEntryInfo * const,int,void *),void * data)963 static roleBitsType foreachRoleBits (const tagEntryInfo *const tag,
964 void (* fn) (const tagEntryInfo *const, int, void *),
965 void *data)
966 {
967 roleBitsType rbits = tag->extensionFields.roleBits;
968 if (!rbits)
969 return rbits;
970
971 int roleCount = countLanguageRoles (tag->langType, tag->kindIndex);
972
973 for (int roleIndex = 0; roleIndex < roleCount; roleIndex++)
974 {
975 if ((rbits >> roleIndex) & (roleBitsType)1)
976 fn (tag, roleIndex, data);
977 }
978 return rbits;
979 }
980
renderFieldRoles(const tagEntryInfo * const tag,const char * value CTAGS_ATTR_UNUSED,vString * b)981 static const char *renderFieldRoles (const tagEntryInfo *const tag,
982 const char *value CTAGS_ATTR_UNUSED,
983 vString* b)
984 {
985 struct renderRoleData data = { .b = b, .nRoleWritten = 0 };
986
987 if (!foreachRoleBits (tag, renderRoleByIndex, &data))
988 vStringCatS (b, ROLE_DEFINITION_NAME);
989 return vStringValue (b);
990 }
991
renderFieldLanguage(const tagEntryInfo * const tag,const char * value CTAGS_ATTR_UNUSED,vString * b)992 static const char *renderFieldLanguage (const tagEntryInfo *const tag,
993 const char *value CTAGS_ATTR_UNUSED,
994 vString* b)
995 {
996 const char *l;
997
998 if (Option.lineDirectives && (tag->sourceLangType != LANG_IGNORE))
999 l = getLanguageName(tag->sourceLangType);
1000 else
1001 {
1002 Assert (tag->langType != LANG_IGNORE);
1003 l = getLanguageName(tag->langType);
1004 }
1005
1006 return renderAsIs (b, WITH_DEFUALT_VALUE(l));
1007 }
1008
renderFieldAccess(const tagEntryInfo * const tag,const char * value CTAGS_ATTR_UNUSED,vString * b)1009 static const char *renderFieldAccess (const tagEntryInfo *const tag,
1010 const char *value CTAGS_ATTR_UNUSED,
1011 vString* b)
1012 {
1013 return renderAsIs (b, WITH_DEFUALT_VALUE (tag->extensionFields.access));
1014 }
1015
renderFieldKindLetter(const tagEntryInfo * const tag,const char * value CTAGS_ATTR_UNUSED,vString * b)1016 static const char *renderFieldKindLetter (const tagEntryInfo *const tag,
1017 const char *value CTAGS_ATTR_UNUSED,
1018 vString* b)
1019 {
1020 static char c[2] = { [1] = '\0' };
1021
1022 c [0] = getTagKindLetter(tag);
1023
1024 return renderAsIs (b, c);
1025 }
1026
renderFieldImplementation(const tagEntryInfo * const tag,const char * value CTAGS_ATTR_UNUSED,vString * b)1027 static const char *renderFieldImplementation (const tagEntryInfo *const tag,
1028 const char *value CTAGS_ATTR_UNUSED,
1029 vString* b)
1030 {
1031 return renderAsIs (b, WITH_DEFUALT_VALUE (tag->extensionFields.implementation));
1032 }
1033
renderFieldFile(const tagEntryInfo * const tag,const char * value CTAGS_ATTR_UNUSED,vString * b)1034 static const char *renderFieldFile (const tagEntryInfo *const tag,
1035 const char *value CTAGS_ATTR_UNUSED,
1036 vString* b)
1037 {
1038 return renderAsIs (b, tag->isFileScope? "file": FIELD_NULL_LETTER_STRING);
1039 }
1040
renderFieldPattern(const tagEntryInfo * const tag,const char * value CTAGS_ATTR_UNUSED,vString * b)1041 static const char *renderFieldPattern (const tagEntryInfo *const tag,
1042 const char *value CTAGS_ATTR_UNUSED,
1043 vString* b)
1044 {
1045 if (tag->isFileEntry)
1046 return NULL;
1047 else if (tag->pattern)
1048 vStringCatS (b, tag->pattern);
1049 else
1050 {
1051 char* tmp;
1052
1053 tmp = makePatternString (tag);
1054 vStringCatS (b, tmp);
1055 eFree (tmp);
1056 }
1057 return vStringValue (b);
1058 }
1059
renderFieldRefMarker(const tagEntryInfo * const tag,const char * value CTAGS_ATTR_UNUSED,vString * b)1060 static const char *renderFieldRefMarker (const tagEntryInfo *const tag,
1061 const char *value CTAGS_ATTR_UNUSED,
1062 vString* b)
1063 {
1064 static char c[2] = { [1] = '\0' };
1065
1066 c [0] = (tag->extensionFields.roleBits)? 'R': 'D';
1067
1068 return renderAsIs (b, c);
1069 }
1070
renderFieldExtras(const tagEntryInfo * const tag,const char * value CTAGS_ATTR_UNUSED,vString * b)1071 static const char *renderFieldExtras (const tagEntryInfo *const tag,
1072 const char *value CTAGS_ATTR_UNUSED,
1073 vString* b)
1074 {
1075 int i;
1076 bool hasExtra = false;
1077 int c = countXtags();
1078
1079 for (i = 0; i < c; i++)
1080 {
1081 const char *name = getXtagName (i);
1082
1083 if (!name)
1084 continue;
1085
1086 if (isTagExtraBitMarked (tag, i))
1087 {
1088
1089 if (hasExtra)
1090 vStringPut (b, ',');
1091 vStringCatS (b, name);
1092 hasExtra = true;
1093 }
1094 }
1095
1096 if (hasExtra)
1097 return vStringValue (b);
1098 else
1099 return NULL;
1100 }
1101
renderFieldXpath(const tagEntryInfo * const tag,const char * value CTAGS_ATTR_UNUSED,vString * b)1102 static const char *renderFieldXpath (const tagEntryInfo *const tag,
1103 const char *value CTAGS_ATTR_UNUSED,
1104 vString* b)
1105 {
1106 #ifdef HAVE_LIBXML
1107 if (tag->extensionFields.xpath)
1108 return renderEscapedString (tag->extensionFields.xpath,
1109 tag, b);
1110 #endif
1111 return NULL;
1112 }
1113
renderFieldScopeKindName(const tagEntryInfo * const tag,const char * value CTAGS_ATTR_UNUSED,vString * b)1114 static const char *renderFieldScopeKindName(const tagEntryInfo *const tag,
1115 const char *value CTAGS_ATTR_UNUSED,
1116 vString* b)
1117 {
1118 const char* kind;
1119
1120 getTagScopeInformation ((tagEntryInfo *const)tag, &kind, NULL);
1121 return kind? renderAsIs (b, kind): NULL;
1122 }
1123
renderFieldEnd(const tagEntryInfo * const tag,const char * value CTAGS_ATTR_UNUSED,vString * b)1124 static const char *renderFieldEnd (const tagEntryInfo *const tag,
1125 const char *value CTAGS_ATTR_UNUSED,
1126 vString* b)
1127 {
1128 static char buf[21];
1129
1130 if (tag->extensionFields.endLine != 0)
1131 {
1132 sprintf (buf, "%lu", tag->extensionFields.endLine);
1133 return renderAsIs (b, buf);
1134 }
1135 else
1136 return NULL;
1137 }
1138
renderFieldEpoch(const tagEntryInfo * const tag,const char * value,vString * b)1139 static const char *renderFieldEpoch (const tagEntryInfo *const tag,
1140 const char *value, vString* b)
1141 {
1142 #define buf_len 21
1143 static char buf[buf_len];
1144
1145 if (snprintf (buf, buf_len, "%lld", (long long)tag->extensionFields.epoch) > 0)
1146 return renderAsIs (b, buf);
1147 else
1148 return NULL;
1149 #undef buf_len
1150 }
1151
renderFieldNth(const tagEntryInfo * const tag,const char * value,vString * b)1152 static const char *renderFieldNth (const tagEntryInfo *const tag,
1153 const char *value, vString* b)
1154 {
1155 #define buf_len 12
1156 static char buf[buf_len];
1157
1158 if (tag->extensionFields.nth > NO_NTH_FIELD
1159 && snprintf (buf, buf_len, "%d", (int)tag->extensionFields.nth) > 0)
1160 return renderAsIs (b, buf);
1161 else
1162 return NULL;
1163 #undef buf_len
1164 }
1165
isTyperefFieldAvailable(const tagEntryInfo * const tag)1166 static bool isTyperefFieldAvailable (const tagEntryInfo *const tag)
1167 {
1168 return (tag->extensionFields.typeRef [0] != NULL
1169 && tag->extensionFields.typeRef [1] != NULL)? true: false;
1170 }
1171
isFileFieldAvailable(const tagEntryInfo * const tag)1172 static bool isFileFieldAvailable (const tagEntryInfo *const tag)
1173 {
1174 return tag->isFileScope? true: false;
1175 }
1176
isInheritsFieldAvailable(const tagEntryInfo * const tag)1177 static bool isInheritsFieldAvailable (const tagEntryInfo *const tag)
1178 {
1179 return (tag->extensionFields.inheritance != NULL)? true: false;
1180 }
1181
isAccessFieldAvailable(const tagEntryInfo * const tag)1182 static bool isAccessFieldAvailable (const tagEntryInfo *const tag)
1183 {
1184 return (tag->extensionFields.access != NULL)? true: false;
1185 }
1186
isImplementationFieldAvailable(const tagEntryInfo * const tag)1187 static bool isImplementationFieldAvailable (const tagEntryInfo *const tag)
1188 {
1189 return (tag->extensionFields.implementation != NULL)? true: false;
1190 }
1191
isSignatureFieldAvailable(const tagEntryInfo * const tag)1192 static bool isSignatureFieldAvailable (const tagEntryInfo *const tag)
1193 {
1194 return (tag->extensionFields.signature != NULL)? true: false;
1195 }
1196
isExtrasFieldAvailable(const tagEntryInfo * const tag)1197 static bool isExtrasFieldAvailable (const tagEntryInfo *const tag)
1198 {
1199 unsigned int i;
1200
1201 if (tag->extraDynamic)
1202 return true;
1203 for (i = 0; i < sizeof (tag->extra); i++)
1204 if (tag->extra [i])
1205 return true;
1206
1207 return false;
1208 }
1209
isXpathFieldAvailable(const tagEntryInfo * const tag)1210 static bool isXpathFieldAvailable (const tagEntryInfo *const tag)
1211 {
1212 #ifdef HAVE_LIBXML
1213 return (tag->extensionFields.xpath != NULL)? true: false;
1214 #else
1215 return false;
1216 #endif
1217 }
1218
isEndFieldAvailable(const tagEntryInfo * const tag)1219 static bool isEndFieldAvailable (const tagEntryInfo *const tag)
1220 {
1221 return (tag->extensionFields.endLine != 0)? true: false;
1222 }
1223
isEpochAvailable(const tagEntryInfo * const tag)1224 static bool isEpochAvailable (const tagEntryInfo *const tag)
1225 {
1226 return (tag->kindIndex == KIND_FILE_INDEX)
1227 ? true
1228 : false;
1229 }
1230
isNthAvailable(const tagEntryInfo * const tag)1231 static bool isNthAvailable (const tagEntryInfo *const tag)
1232 {
1233 Assert (tag->langType >= NO_NTH_FIELD);
1234 return (tag->extensionFields.nth != NO_NTH_FIELD)? true: false;
1235 }
1236
isFieldEnabled(fieldType type)1237 extern bool isFieldEnabled (fieldType type)
1238 {
1239 return getFieldObject(type)->def->enabled;
1240 }
1241
enableField(fieldType type,bool state)1242 extern bool enableField (fieldType type, bool state)
1243 {
1244 fieldDefinition *def = getFieldObject(type)->def;
1245 bool old = def->enabled;
1246 getFieldObject(type)->def->enabled = state;
1247
1248 if (isCommonField (type))
1249 verbose ("enable field \"%s\": %s\n",
1250 getFieldObject(type)->def->name,
1251 (state? "yes": "no"));
1252 else
1253 verbose ("enable field \"%s\"<%s>: %s\n",
1254 getFieldObject(type)->def->name,
1255 getLanguageName (getFieldOwner(type)),
1256 (state? "yes": "no"));
1257 return old;
1258 }
1259
isCommonField(fieldType type)1260 extern bool isCommonField (fieldType type)
1261 {
1262 return (FIELD_BUILTIN_LAST < type)? false: true;
1263 }
1264
getFieldOwner(fieldType type)1265 extern int getFieldOwner (fieldType type)
1266 {
1267 return getFieldObject(type)->language;
1268 }
1269
getFieldDataType(fieldType type)1270 extern unsigned int getFieldDataType (fieldType type)
1271 {
1272 return getFieldObject(type)->def->dataType;
1273 }
1274
isFieldValueAvailableAlways(fieldType type)1275 extern bool isFieldValueAvailableAlways (fieldType type)
1276 {
1277 return getFieldObject(type)->def->isValueAvailable == NULL;
1278 }
1279
doesFieldHaveRenderer(fieldType type,bool noEscaping)1280 extern bool doesFieldHaveRenderer (fieldType type, bool noEscaping)
1281 {
1282 if (noEscaping)
1283 return getFieldObject(type)->def->renderNoEscaping? true: false;
1284 else
1285 return getFieldObject(type)->def->render? true: false;
1286 }
1287
countFields(void)1288 extern int countFields (void)
1289 {
1290 return fieldObjectUsed;
1291 }
1292
nextSiblingField(fieldType type)1293 extern fieldType nextSiblingField (fieldType type)
1294 {
1295 fieldObject *fobj;
1296
1297 fobj = fieldObjects + type;
1298 return fobj->sibling;
1299 }
1300
updateSiblingField(fieldType type,const char * name)1301 static void updateSiblingField (fieldType type, const char* name)
1302 {
1303 int i;
1304 fieldObject *fobj;
1305
1306 for (i = type; i > 0; i--)
1307 {
1308 fobj = fieldObjects + i - 1;
1309 if (fobj->def->name && (strcmp (fobj->def->name, name) == 0))
1310 {
1311 Assert (fobj->sibling == FIELD_UNKNOWN);
1312 fobj->sibling = type;
1313 break;
1314 }
1315 }
1316 }
1317
defaultRenderer(const tagEntryInfo * const tag CTAGS_ATTR_UNUSED,const char * value,vString * buffer CTAGS_ATTR_UNUSED)1318 static const char* defaultRenderer (const tagEntryInfo *const tag CTAGS_ATTR_UNUSED,
1319 const char *value,
1320 vString * buffer CTAGS_ATTR_UNUSED)
1321 {
1322 return renderEscapedString (value, tag, buffer);
1323 }
1324
defineField(fieldDefinition * def,langType language)1325 extern int defineField (fieldDefinition *def, langType language)
1326 {
1327 fieldObject *fobj;
1328 char *nameWithPrefix;
1329 size_t i;
1330
1331 Assert (def);
1332 Assert (def->name);
1333 for (i = 0; i < strlen (def->name); i++)
1334 {
1335 Assert ( isalpha (def->name [i]) );
1336 }
1337 def->letter = NUL_FIELD_LETTER;
1338
1339 if (fieldObjectUsed == fieldObjectAllocated)
1340 {
1341 fieldObjectAllocated *= 2;
1342 fieldObjects = xRealloc (fieldObjects, fieldObjectAllocated, fieldObject);
1343 }
1344 fobj = fieldObjects + (fieldObjectUsed);
1345 def->ftype = fieldObjectUsed++;
1346
1347 if (def->render == NULL)
1348 {
1349 def->render = defaultRenderer;
1350 def->renderNoEscaping = NULL;
1351 def->doesContainAnyChar = NULL;
1352 }
1353
1354 if (! def->dataType)
1355 def->dataType = FIELDTYPE_STRING;
1356
1357 fobj->def = def;
1358
1359 fobj->buffer = NULL;
1360
1361 nameWithPrefix = eMalloc (sizeof CTAGS_FIELD_PREFIX + strlen (def->name) + 1);
1362 nameWithPrefix [0] = '\0';
1363 strcat (nameWithPrefix, CTAGS_FIELD_PREFIX);
1364 strcat (nameWithPrefix, def->name);
1365 fobj->nameWithPrefix = nameWithPrefix;
1366 DEFAULT_TRASH_BOX(nameWithPrefix, eFree);
1367
1368 fobj->language = language;
1369 fobj->sibling = FIELD_UNKNOWN;
1370
1371 updateSiblingField (def->ftype, def->name);
1372 return def->ftype;
1373 }
1374
1375 #define FIELD_COL_LETTER 0
1376 #define FIELD_COL_NAME 1
1377 #define FIELD_COL_ENABLED 2
1378 #define FIELD_COL_LANGUAGE 3
1379 #define FIELD_COL_JSTYPE 4
1380 #define FIELD_COL_FIXED 5
1381 #define FIELD_COL_OPERATOR 6
1382 #define FIELD_COL_DESCRIPTION 7
1383
fieldColprintTableNew(void)1384 extern struct colprintTable * fieldColprintTableNew (void)
1385 {
1386 return colprintTableNew ("L:LETTER", "L:NAME", "L:ENABLED",
1387 "L:LANGUAGE", "L:JSTYPE", "L:FIXED",
1388 "L:OP", "L:DESCRIPTION", NULL);
1389 }
1390
fieldColprintAddLine(struct colprintTable * table,int i)1391 static void fieldColprintAddLine (struct colprintTable *table, int i)
1392 {
1393 fieldObject *fobj = getFieldObject(i);
1394 fieldDefinition *fdef = fobj->def;
1395
1396 struct colprintLine *line = colprintTableGetNewLine(table);
1397
1398 colprintLineAppendColumnChar (line,
1399 (fdef->letter == NUL_FIELD_LETTER)
1400 ? FIELD_NULL_LETTER_CHAR
1401 : fdef->letter);
1402
1403 const char *name = getFieldName (i);
1404 colprintLineAppendColumnCString (line, name? name: RSV_NONE);
1405 colprintLineAppendColumnBool (line, fdef->enabled);
1406 colprintLineAppendColumnCString (line,
1407 fobj->language == LANG_IGNORE
1408 ? RSV_NONE
1409 : getLanguageName (fobj->language));
1410
1411 char typefields [] = "---";
1412 {
1413 unsigned int bmask, offset;
1414 unsigned int type = getFieldDataType(i);
1415 for (bmask = 1, offset = 0;
1416 bmask < FIELDTYPE_END_MARKER;
1417 bmask <<= 1, offset++)
1418 if (type & bmask)
1419 typefields[offset] = fieldDataTypeFalgs[offset];
1420 }
1421 colprintLineAppendColumnCString (line, typefields);
1422 colprintLineAppendColumnBool (line, writerDoesTreatFieldAsFixed (i));
1423
1424 char operator[] = {'-', '-', '\0'};
1425 if (fdef->getValueObject)
1426 operator[0] = 'r';
1427 if (fdef->setValueObject)
1428 operator[1] = 'w';
1429 colprintLineAppendColumnCString (line, operator);
1430 colprintLineAppendColumnCString (line, fdef->description);
1431 }
1432
fieldColprintAddCommonLines(struct colprintTable * table)1433 extern void fieldColprintAddCommonLines (struct colprintTable *table)
1434 {
1435 for (int i = 0; i <= FIELD_BUILTIN_LAST; i++)
1436 fieldColprintAddLine(table, i);
1437 }
1438
fieldColprintAddLanguageLines(struct colprintTable * table,langType language)1439 extern void fieldColprintAddLanguageLines (struct colprintTable *table, langType language)
1440 {
1441 for (unsigned int i = FIELD_BUILTIN_LAST + 1; i < fieldObjectUsed; i++)
1442 {
1443 fieldObject *fobj = getFieldObject(i);
1444 if (fobj->language == language)
1445 fieldColprintAddLine (table, i);
1446 }
1447 }
1448
fieldColprintCompareLines(struct colprintLine * a,struct colprintLine * b)1449 static int fieldColprintCompareLines (struct colprintLine *a , struct colprintLine *b)
1450 {
1451 const char *a_fixed = colprintLineGetColumn (a, FIELD_COL_FIXED);
1452 const char *b_fixed = colprintLineGetColumn (b, FIELD_COL_FIXED);
1453 const char *a_parser = colprintLineGetColumn (a, FIELD_COL_LANGUAGE);
1454 const char *b_parser = colprintLineGetColumn (b, FIELD_COL_LANGUAGE);
1455
1456 if ((strcmp (a_fixed, "yes") == 0)
1457 && (strcmp (b_fixed, "yes") == 0))
1458 {
1459 /* name, input, pattern, compact */
1460 const char *a_name = colprintLineGetColumn (a, FIELD_COL_NAME);
1461 const char *b_name = colprintLineGetColumn (b, FIELD_COL_NAME);
1462 const char *ref_name;
1463 unsigned int a_index = ~0U;
1464 unsigned int b_index = ~0U;
1465
1466 for (unsigned int i = 0; i < ARRAY_SIZE(fieldDefinitionsFixed); i++)
1467 {
1468 ref_name = fieldDefinitionsFixed [i].name;
1469 if (strcmp (a_name, ref_name) == 0)
1470 a_index = i;
1471 if (strcmp (b_name, ref_name) == 0)
1472 b_index = i;
1473 if ((a_index != ~0U) || (b_index != ~0U))
1474 break;
1475 }
1476
1477 if (a_index < b_index)
1478 return -1;
1479 else if (a_index == b_index)
1480 return 0; /* ??? */
1481 else
1482 return 1;
1483 }
1484 else if ((strcmp (a_fixed, "yes") == 0)
1485 && (strcmp (b_fixed, "yes") != 0))
1486 return -1;
1487 else if ((strcmp (a_fixed, "yes") != 0)
1488 && (strcmp (b_fixed, "yes") == 0))
1489 return 1;
1490
1491 if (strcmp (a_parser, RSV_NONE) == 0
1492 && strcmp (b_parser, RSV_NONE) != 0)
1493 return -1;
1494 else if (strcmp (a_parser, RSV_NONE) != 0
1495 && strcmp (b_parser, RSV_NONE) == 0)
1496 return 1;
1497 else if (strcmp (a_parser, RSV_NONE) != 0
1498 && strcmp (b_parser, RSV_NONE) != 0)
1499 {
1500 int r;
1501 r = strcmp (a_parser, b_parser);
1502 if (r != 0)
1503 return r;
1504
1505 const char *a_name = colprintLineGetColumn (a, FIELD_COL_NAME);
1506 const char *b_name = colprintLineGetColumn (b, FIELD_COL_NAME);
1507
1508 return strcmp(a_name, b_name);
1509 }
1510 else
1511 {
1512 const char *a_letter = colprintLineGetColumn (a, FIELD_COL_LETTER);
1513 const char *b_letter = colprintLineGetColumn (b, FIELD_COL_LETTER);
1514
1515 return strcmp(a_letter, b_letter);
1516 }
1517 }
1518
fieldColprintTablePrint(struct colprintTable * table,bool withListHeader,bool machinable,FILE * fp)1519 extern void fieldColprintTablePrint (struct colprintTable *table,
1520 bool withListHeader, bool machinable, FILE *fp)
1521 {
1522 colprintTableSort (table, fieldColprintCompareLines);
1523 colprintTablePrint (table, 0, withListHeader, machinable, fp);
1524 }
1525
getFieldGetterValueType(fieldType type)1526 extern const char * getFieldGetterValueType (fieldType type)
1527 {
1528 fieldObject *fobj = getFieldObject (type);
1529 return (fobj? fobj->def->getterValueType: NULL);
1530 }
1531
getFieldValue(fieldType type,const tagEntryInfo * tag)1532 extern EsObject * getFieldValue (fieldType type, const tagEntryInfo *tag)
1533 {
1534 fieldObject* fobj;
1535
1536 fobj = getFieldObject (type);
1537 if (fobj && fobj->def->getValueObject)
1538 return fobj->def->getValueObject (tag, fobj->def);
1539 return es_nil;
1540 }
1541
hasFieldGetter(fieldType type)1542 extern bool hasFieldGetter (fieldType type)
1543 {
1544 fieldObject *fobj = getFieldObject (type);
1545 return (fobj && fobj->def->getValueObject);
1546 }
1547
getFieldSetterValueType(fieldType type)1548 extern const char * getFieldSetterValueType (fieldType type)
1549 {
1550 fieldObject *fobj = getFieldObject (type);
1551 return (fobj? fobj->def->setterValueType: NULL);
1552 }
1553
setFieldValue(fieldType type,tagEntryInfo * tag,const EsObject * val)1554 extern EsObject * setFieldValue (fieldType type, tagEntryInfo *tag, const EsObject *val)
1555 {
1556 fieldObject *fobj;
1557
1558 fobj = getFieldObject (type);
1559 if (fobj && fobj->def->setValueObject)
1560 return fobj->def->setValueObject (tag, fobj->def, val);
1561 return es_false;
1562 }
1563
hasFieldSetter(fieldType type)1564 extern bool hasFieldSetter (fieldType type)
1565 {
1566 fieldObject *fobj = getFieldObject (type);
1567 return (fobj && fobj->def->setValueObject);
1568 }
1569
1570
hasFieldValueCheckerForSetter(fieldType type)1571 extern bool hasFieldValueCheckerForSetter (fieldType type)
1572 {
1573 fieldObject *fobj = getFieldObject (type);
1574 return (fobj && fobj->def->checkValueForSetter);
1575 }
1576
checkFieldValueForSetter(fieldType type,const EsObject * val)1577 extern EsObject* checkFieldValueForSetter (fieldType type, const EsObject *val)
1578 {
1579 fieldObject *fobj = getFieldObject (type);
1580 return fobj->def->checkValueForSetter (fobj->def, val);
1581 }
1582
getFieldValueForName(const tagEntryInfo * tag,const fieldDefinition * fdef)1583 static EsObject* getFieldValueForName (const tagEntryInfo *tag, const fieldDefinition *fdef)
1584 {
1585 return opt_string_new_from_cstr (tag->name);
1586 }
1587
setFieldValueForName(tagEntryInfo * tag,const fieldDefinition * fdef,const EsObject * val)1588 static EsObject* setFieldValueForName (tagEntryInfo *tag, const fieldDefinition *fdef, const EsObject *val)
1589 {
1590 eFree ((char*) tag->name);
1591 const char *cstr = opt_string_get_cstr (val);
1592 tag->name = eStrdup (cstr);
1593 return es_false;
1594 }
1595
getFieldValueForInput(const tagEntryInfo * tag,const fieldDefinition * fdef)1596 static EsObject* getFieldValueForInput (const tagEntryInfo *tag, const fieldDefinition *fdef)
1597 {
1598 return opt_string_new_from_cstr (tag->inputFileName);
1599 }
1600
getFieldValueForKind(const tagEntryInfo * tag,const fieldDefinition * fdef)1601 static EsObject* getFieldValueForKind (const tagEntryInfo *tag, const fieldDefinition *fdef)
1602 {
1603 const char *kind_name = getLanguageKindName (tag->langType, tag->kindIndex);
1604 return opt_name_new_from_cstr (kind_name);
1605 }
1606
getFieldValueForTyperef(const tagEntryInfo * tag,const fieldDefinition * fdef)1607 static EsObject* getFieldValueForTyperef (const tagEntryInfo *tag, const fieldDefinition *fdef)
1608 {
1609 if (tag->extensionFields.typeRef [0] == NULL
1610 && tag->extensionFields.typeRef [1] == NULL)
1611 return es_nil;
1612
1613 EsObject *a = opt_array_new ();
1614 EsObject *e0 = tag->extensionFields.typeRef [0]
1615 ? opt_string_new_from_cstr(tag->extensionFields.typeRef [0])
1616 : es_false;
1617 EsObject *e1 = tag->extensionFields.typeRef [1]
1618 ? opt_string_new_from_cstr(tag->extensionFields.typeRef [1])
1619 : es_false;
1620 opt_array_put (a, 0, e0);
1621 opt_array_put (a, 1, e1);
1622 es_object_unref (e0);
1623 es_object_unref (e1);
1624 return a;
1625 }
1626
setFieldValueForTyperef(tagEntryInfo * tag,const fieldDefinition * fdef,const EsObject * obj)1627 static EsObject* setFieldValueForTyperef (tagEntryInfo *tag, const fieldDefinition *fdef, const EsObject *obj)
1628 {
1629 const char *tmp[2] = {NULL, NULL};
1630
1631 for (int i = 0 ; i < 2; i++)
1632 {
1633 if (tag->extensionFields.typeRef [i])
1634 tmp [i] = tag->extensionFields.typeRef [i];
1635 }
1636
1637 if (es_boolean_p (obj))
1638 {
1639 for (int i = 0 ; i < 2; i++)
1640 {
1641 if (tag->extensionFields.typeRef [i])
1642 tag->extensionFields.typeRef [i] = NULL;
1643 }
1644 }
1645 else if (es_object_get_type (obj) == OPT_TYPE_ARRAY)
1646 {
1647 for (int i = 0 ; i < 2; i++)
1648 {
1649 EsObject *e = opt_array_get (obj, i);
1650 if (es_boolean_p (e))
1651 {
1652 if (tag->extensionFields.typeRef [i])
1653 tag->extensionFields.typeRef [i] = NULL;
1654 }
1655 else if (es_object_get_type (e) == OPT_TYPE_STRING)
1656 {
1657 tag->extensionFields.typeRef [i] = eStrdup (opt_string_get_cstr (e));
1658 }
1659 }
1660 }
1661 else if (es_object_get_type (obj) == OPT_TYPE_STRING)
1662 {
1663 const char *str = opt_string_get_cstr (obj);
1664 tag->extensionFields.typeRef [0] = eStrdup ("typename");
1665 tag->extensionFields.typeRef [1] = eStrdup (str);
1666 }
1667 else if (es_integer_p (obj))
1668 {
1669 int index = es_integer_get (obj);
1670 tagEntryInfo *e = getEntryInCorkQueue (index);
1671 if (e)
1672 {
1673 const char *name = e->name;
1674 const char *kindName = getLanguageKindName (e->langType, e->kindIndex);
1675
1676 tag->extensionFields.typeRef [0] = eStrdup (kindName);
1677 tag->extensionFields.typeRef [1] = eStrdup (name);
1678 }
1679 }
1680 else
1681 {
1682 AssertNotReached();
1683 return OPT_ERR_TYPECHECK;
1684 }
1685
1686 for (int i = 0; i < 2; i++)
1687 if (tmp [i])
1688 eFree ((char*)tmp[i]);
1689
1690 return es_false;
1691 }
1692
checkFieldValueForTyperef(const fieldDefinition * fdef,const EsObject * obj)1693 static EsObject* checkFieldValueForTyperef (const fieldDefinition *fdef, const EsObject *obj)
1694 {
1695 if (es_boolean_p (obj))
1696 {
1697 if (!es_object_equal (es_false, obj))
1698 return OPT_ERR_TYPECHECK;
1699 }
1700 else if (es_object_get_type (obj) == OPT_TYPE_ARRAY)
1701 {
1702 if (opt_array_length (obj) != 2)
1703 return OPT_ERR_TYPECHECK;
1704
1705 for (unsigned int i = 0; i < 2; i++)
1706 {
1707 EsObject *e = opt_array_get (obj, i);
1708 if (es_object_get_type (e) != OPT_TYPE_STRING)
1709 return OPT_ERR_TYPECHECK;
1710 }
1711 }
1712 else if (es_object_get_type (obj) == OPT_TYPE_STRING)
1713 ;
1714 else if (es_integer_p (obj))
1715 {
1716 int index = es_integer_get (obj);
1717 if (index >= countEntryInCorkQueue ())
1718 return OPTSCRIPT_ERR_NOTAGENTRY;
1719 }
1720 else
1721 return OPT_ERR_TYPECHECK;
1722 return es_false;
1723 }
1724
getFieldValueForScope(const tagEntryInfo * tag,const fieldDefinition * fdef)1725 static EsObject* getFieldValueForScope (const tagEntryInfo *tag, const fieldDefinition *fdef)
1726 {
1727 return es_integer_new (tag->extensionFields.scopeIndex);
1728 }
1729
setFieldValueForScope(tagEntryInfo * tag,const fieldDefinition * fdef,const EsObject * obj)1730 static EsObject* setFieldValueForScope (tagEntryInfo *tag, const fieldDefinition *fdef, const EsObject *obj)
1731 {
1732 int index = es_integer_get (obj);
1733 if (index < countEntryInCorkQueue ())
1734 {
1735 tag->extensionFields.scopeIndex = index;
1736 return es_false;
1737 }
1738
1739 return OPTSCRIPT_ERR_NOTAGENTRY;
1740 }
1741
checkFieldValueForScope(const fieldDefinition * fdef,const EsObject * obj)1742 static EsObject* checkFieldValueForScope (const fieldDefinition *fdef, const EsObject *obj)
1743 {
1744 if (!es_integer_p (obj))
1745 return OPT_ERR_TYPECHECK;
1746
1747 if (es_integer_get (obj) < 0)
1748 return OPT_ERR_RANGECHECK;
1749
1750 return es_false;
1751 }
1752
getFieldValueForExtras(const tagEntryInfo * tag,const fieldDefinition * fdef)1753 static EsObject* getFieldValueForExtras (const tagEntryInfo *tag, const fieldDefinition *fdef)
1754 {
1755 if (!isTagExtra (tag))
1756 return es_nil;
1757
1758 EsObject* a = opt_array_new ();
1759
1760 for (int i = 0; i < countXtags (); i++)
1761 {
1762 if (!isTagExtraBitMarked (tag, i))
1763 continue;
1764
1765 langType lang = getXtagOwner (i);
1766 const char *lang_name = (lang == LANG_IGNORE)
1767 ? NULL
1768 : getLanguageName (lang);
1769 const char *extra_name = getXtagName (i);
1770
1771 EsObject *extra;
1772 if (lang_name == NULL)
1773 extra = opt_name_new_from_cstr (extra_name);
1774 else
1775 {
1776 vString *tmp = vStringNewInit (lang_name);
1777 vStringPut (tmp, '.');
1778 vStringCatS (tmp, extra_name);
1779 extra = opt_name_new_from_cstr (vStringValue (tmp));
1780 vStringDelete (tmp);
1781 }
1782 opt_array_add (a, extra);
1783 es_object_unref (extra);
1784 }
1785 return a;
1786 }
1787
getFieldValueForCOMMON(const char * field,const tagEntryInfo * tag,const fieldDefinition * fdef)1788 static EsObject* getFieldValueForCOMMON (const char *field, const tagEntryInfo *tag, const fieldDefinition *fdef)
1789 {
1790 if (!field)
1791 return es_nil;
1792 return (opt_name_new_from_cstr (field));
1793 }
1794
setFieldValueForCOMMON(const char ** field,tagEntryInfo * tag,const fieldDefinition * fdef,const EsObject * obj)1795 static EsObject* setFieldValueForCOMMON (const char **field, tagEntryInfo *tag, const fieldDefinition *fdef, const EsObject *obj)
1796 {
1797 if (*field)
1798 eFree ((char *)*field);
1799
1800 const char *str = opt_string_get_cstr (obj);
1801 *field = eStrdup (str);
1802 return es_false;
1803 }
1804
getFieldValueForAccess(const tagEntryInfo * tag,const fieldDefinition * fdef)1805 static EsObject* getFieldValueForAccess (const tagEntryInfo *tag, const fieldDefinition *fdef)
1806 {
1807 return getFieldValueForCOMMON(tag->extensionFields.access, tag, fdef);
1808 }
1809
setFieldValueForAccess(tagEntryInfo * tag,const fieldDefinition * fdef,const EsObject * obj)1810 static EsObject* setFieldValueForAccess (tagEntryInfo *tag, const fieldDefinition *fdef, const EsObject *obj)
1811 {
1812 return setFieldValueForCOMMON(&tag->extensionFields.access, tag, fdef, obj);
1813 }
1814
getFieldValueForSignature(const tagEntryInfo * tag,const fieldDefinition * fdef)1815 static EsObject* getFieldValueForSignature (const tagEntryInfo *tag, const fieldDefinition *fdef)
1816 {
1817 return getFieldValueForCOMMON(tag->extensionFields.signature, tag, fdef);
1818 }
1819
setFieldValueForSignature(tagEntryInfo * tag,const fieldDefinition * fdef,const EsObject * obj)1820 static EsObject* setFieldValueForSignature (tagEntryInfo *tag, const fieldDefinition *fdef, const EsObject *obj)
1821 {
1822 return setFieldValueForCOMMON(&tag->extensionFields.signature, tag, fdef, obj);
1823 }
1824
makeRolesArray(const tagEntryInfo * const tag,int roleIndex,void * data)1825 static void makeRolesArray (const tagEntryInfo *const tag, int roleIndex, void *data)
1826 {
1827 EsObject *a = data;
1828
1829 const roleDefinition *role = getTagRole (tag, roleIndex);
1830 EsObject *r = opt_name_new_from_cstr (role->name);
1831 opt_array_add (a, r);
1832 es_object_unref (r);
1833 }
1834
getFieldValueForRoles(const tagEntryInfo * tag,const fieldDefinition * fdef)1835 static EsObject* getFieldValueForRoles (const tagEntryInfo *tag, const fieldDefinition *fdef)
1836 {
1837 EsObject *a = opt_array_new ();
1838
1839 if (!foreachRoleBits (tag, makeRolesArray, a))
1840 {
1841 EsObject *r = opt_name_new_from_cstr (ROLE_DEFINITION_NAME);
1842 opt_array_add (a, r);
1843 es_object_unref (r);
1844 }
1845 return a;
1846 }
1847
getFieldValueForLineCommon(const tagEntryInfo * tag,const fieldDefinition * fdef)1848 static EsObject* getFieldValueForLineCommon (const tagEntryInfo *tag, const fieldDefinition *fdef)
1849 {
1850 if (fdef->ftype == FIELD_END_LINE)
1851 return ((int)tag->extensionFields.endLine == 0)
1852 ? es_nil
1853 : es_integer_new ((int)tag->extensionFields.endLine);
1854 else
1855 return ((int)tag->lineNumber == 0)
1856 ? es_nil
1857 : es_integer_new ((int)tag->lineNumber);
1858 }
1859
checkFieldValueForLineCommon(const fieldDefinition * fdef,const EsObject * obj)1860 static EsObject* checkFieldValueForLineCommon (const fieldDefinition *fdef, const EsObject *obj)
1861 {
1862 return es_false;
1863 }
1864
setFieldValueForLineCommon(tagEntryInfo * tag,const fieldDefinition * fdef,const EsObject * obj)1865 static EsObject* setFieldValueForLineCommon (tagEntryInfo *tag, const fieldDefinition *fdef, const EsObject *obj)
1866 {
1867 int l;
1868 if (es_object_get_type (obj) == OPT_TYPE_MATCHLOC)
1869 {
1870 matchLoc *loc = es_pointer_get (obj);
1871 l = loc->line;
1872 }
1873 else if (es_integer_p (obj))
1874 {
1875 l = es_integer_get (obj);
1876 if (l < 1)
1877 return OPT_ERR_RANGECHECK;
1878
1879 /* If the new line number is too large,
1880 we cannot fill tag->filePosition wit
1881 getInputFilePositionForLine(); */
1882 if (fdef->ftype == FIELD_LINE_NUMBER
1883 && l < getInputLineNumber())
1884 return OPT_ERR_RANGECHECK;
1885 }
1886 else
1887 return OPT_ERR_TYPECHECK;
1888
1889 if (fdef->ftype == FIELD_END_LINE)
1890 tag->extensionFields.endLine = l;
1891 else
1892 {
1893 tag->lineNumber = l;
1894 tag->filePosition = getInputFilePositionForLine (l);
1895 }
1896
1897 return es_false;
1898 }
1899
setFieldValueForInherits(tagEntryInfo * tag,const fieldDefinition * fdef,const EsObject * obj)1900 static EsObject* setFieldValueForInherits (tagEntryInfo *tag, const fieldDefinition *fdef, const EsObject *obj)
1901 {
1902 if (es_object_get_type (obj) == OPT_TYPE_STRING)
1903 {
1904 if (tag->extensionFields.inheritance)
1905 eFree ((void *)tag->extensionFields.inheritance);
1906 const char *str = opt_string_get_cstr (obj);
1907 tag->extensionFields.inheritance = eStrdup (str);
1908 }
1909 else if (es_object_equal (es_false, obj))
1910 {
1911 if (tag->extensionFields.inheritance)
1912 {
1913 eFree ((void *)tag->extensionFields.inheritance);
1914 tag->extensionFields.inheritance = NULL;
1915 }
1916 }
1917 else
1918 return OPT_ERR_RANGECHECK; /* true is not acceptable. */
1919
1920 return es_false;
1921 }
1922