Update all parsers and related files to ctags p6.1.20240421.0
[geany-mirror.git] / ctags / main / kind.c
blob12f323c1776ceed24b376352bd839a3fd4ad5551
1 /*
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"
15 #include <ctype.h>
16 #include <stdio.h>
17 #include <string.h>
19 #include "colprint_p.h"
20 #include "ctags.h"
21 #include "debug.h"
22 #include "entry.h"
23 #include "kind.h"
24 #include "parse_p.h"
25 #include "options.h"
26 #include "ptrarray.h"
27 #include "routines.h"
28 #include "vstring.h"
30 typedef struct sRoleObject {
31 roleDefinition *def;
32 freeRoleDefFunc free;
33 } roleObject;
35 struct roleControlBlock {
36 roleObject *role;
37 unsigned int count;
38 int owner;
41 typedef struct sKindObject {
42 kindDefinition *def;
43 freeKindDefFunc free;
44 struct roleControlBlock *rcb;
45 ptrArray * dynamicSeparators;
46 } kindObject;
48 struct kindControlBlock {
49 kindObject *kind;
50 unsigned int count;
51 langType owner;
52 scopeSeparator defaultScopeSeparator;
53 scopeSeparator defaultRootScopeSeparator;
56 extern const char *renderRole (const roleDefinition* const role, vString* b)
58 vStringCatS (b, role->name);
59 return vStringValue (b);
62 extern void printKind (const kindDefinition* const kind, bool indent)
64 printf ("%s%c %s%s\n", indent ? " " : "", kind->letter,
65 kind->description != NULL ? kind->description :
66 (kind->name != NULL ? kind->name : ""),
67 kind->enabled ? "" : " [off]");
70 extern void enableKind (kindDefinition *kind, bool enable)
72 kindDefinition *slave;
74 if (kind->master)
75 enableKind (kind->master, enable);
76 else
78 kind->enabled = enable;
79 for (slave = kind->slave; slave; slave = slave->slave)
80 slave->enabled = enable;
84 extern void enableRole (roleDefinition *role, bool enable)
86 role->enabled = enable;
89 static void initRoleObject (roleObject *robj, roleDefinition *rdef, freeRoleDefFunc freefunc, int roleId)
91 #ifdef DEBUG
92 size_t len = strlen (rdef->name);
93 for (int i = 0; i < len; i++)
94 Assert (isalnum ((unsigned char) rdef->name [i]));
95 #endif
96 robj->def = rdef;
97 robj->free = freefunc;
98 robj->def->id = roleId;
101 static struct roleControlBlock* allocRoleControlBlock (kindObject *kind)
103 unsigned int j;
104 struct roleControlBlock* rcb;
106 rcb = xMalloc(1, struct roleControlBlock);
107 rcb->count = kind->def->nRoles;
108 rcb->owner = kind->def->id;
109 rcb->role = xMalloc(rcb->count, roleObject);
110 for (j = 0; j < rcb->count; j++)
111 initRoleObject (rcb->role + j, kind->def->roles + j, NULL, j);
113 return rcb;
116 extern struct kindControlBlock* allocKindControlBlock (parserDefinition *parser)
118 unsigned int i;
119 struct kindControlBlock *kcb;
121 kcb = xMalloc (1, struct kindControlBlock);
122 kcb->kind = xMalloc (parser->kindCount, kindObject);
123 kcb->count = parser->kindCount;
124 kcb->owner = parser->id;
126 kcb->defaultScopeSeparator.parentKindIndex = KIND_WILDCARD_INDEX;
127 kcb->defaultScopeSeparator.separator = NULL;
128 if (parser->defaultScopeSeparator)
129 kcb->defaultScopeSeparator.separator = eStrdup (parser->defaultScopeSeparator);
131 kcb->defaultRootScopeSeparator.parentKindIndex = KIND_GHOST_INDEX;
132 kcb->defaultRootScopeSeparator.separator = NULL;
133 if (parser->defaultRootScopeSeparator)
134 kcb->defaultRootScopeSeparator.separator = eStrdup (parser->defaultRootScopeSeparator);
136 for (i = 0; i < parser->kindCount; ++i)
138 kindObject *kind = kcb->kind + i;
139 kind->def = parser->kindTable + i;
141 Assert (kind->def->letter != KIND_FILE_DEFAULT_LETTER);
142 Assert (kind->def->name == NULL /* SELF (RUNTIME) TEST NEEDS THIS. */
143 || strcmp(kind->def->name, KIND_FILE_DEFAULT_NAME));
145 kind->free = NULL;
146 kind->def->id = i;
147 kind->rcb = allocRoleControlBlock (kind);
148 kind->dynamicSeparators = NULL;
151 return kcb;
154 static void freeRoleControlBlock (struct roleControlBlock *rcb)
156 unsigned int i;
157 for (i = 0; i < rcb->count; ++i)
159 if (rcb->role[i].free)
160 rcb->role [i].free (rcb->role [i].def);
162 eFreeNoNullCheck (rcb->role);
163 eFree (rcb);
166 extern void freeKindControlBlock (struct kindControlBlock* kcb)
168 unsigned int i;
170 for (i = 0; i < kcb->count; ++i)
172 if (kcb->kind [i].free)
173 kcb->kind [i].free (kcb->kind [i].def);
174 freeRoleControlBlock (kcb->kind [i].rcb);
175 if (kcb->kind [i].dynamicSeparators)
176 ptrArrayDelete(kcb->kind [i].dynamicSeparators);
179 if (kcb->defaultRootScopeSeparator.separator)
180 eFree((char *)kcb->defaultRootScopeSeparator.separator);
181 if (kcb->defaultScopeSeparator.separator)
182 eFree((char *)kcb->defaultScopeSeparator.separator);
184 if (kcb->kind)
185 eFree (kcb->kind);
186 eFree (kcb);
189 extern int defineKind (struct kindControlBlock* kcb, kindDefinition *def,
190 freeKindDefFunc freeKindDef)
192 def->id = kcb->count++;
193 kcb->kind = xRealloc (kcb->kind, kcb->count, kindObject);
194 kcb->kind [def->id].def = def;
195 kcb->kind [def->id].free = freeKindDef;
196 kcb->kind [def->id].rcb = allocRoleControlBlock(kcb->kind + def->id);
197 kcb->kind [def->id].dynamicSeparators = NULL;
199 verbose ("Add kind[%d] \"%c,%s,%s\" to %s\n", def->id,
200 def->letter, def->name, def->description,
201 getLanguageName (kcb->owner));
203 return def->id;
206 extern int defineRole (struct kindControlBlock* kcb, int kindIndex,
207 roleDefinition *def, freeRoleDefFunc freeRoleDef)
209 struct roleControlBlock *rcb = kcb->kind[kindIndex].rcb;
210 int roleIndex = rcb->count++;
212 if (roleIndex == ROLE_MAX_COUNT)
214 rcb->count--;
215 error (FATAL, "Too many role definition for kind \"%s\" of language \"%s\" (> %d)",
216 kcb->kind[kindIndex].def->name,
217 getLanguageName (kcb->owner),
218 (int)(ROLE_MAX_COUNT - 1));
221 rcb->role = xRealloc (rcb->role, rcb->count, roleObject);
222 initRoleObject (rcb->role + roleIndex, def, freeRoleDef, roleIndex);
224 return roleIndex;
227 extern bool isRoleEnabled (struct kindControlBlock* kcb, int kindIndex, int roleIndex)
229 roleDefinition *rdef = getRole (kcb, kindIndex, roleIndex);
230 return rdef->enabled;
233 extern unsigned int countKinds (struct kindControlBlock* kcb)
235 return kcb->count;
238 extern unsigned int countRoles (struct kindControlBlock* kcb, int kindIndex)
240 return kcb->kind [kindIndex].rcb->count;
243 extern kindDefinition *getKind (struct kindControlBlock* kcb, int kindIndex)
245 return kcb->kind [kindIndex].def;
248 extern kindDefinition *getKindForLetter (struct kindControlBlock* kcb, char letter)
250 unsigned int i;
251 kindDefinition * kdef;
253 for (i = 0; i < countKinds (kcb); ++i)
255 kdef = getKind (kcb, i);
256 if (kdef->letter == letter)
257 return kdef;
259 return NULL;
262 extern kindDefinition *getKindForName (struct kindControlBlock* kcb, const char* name)
264 unsigned int i;
265 kindDefinition * kdef;
267 for (i = 0; i < countKinds (kcb); ++i)
269 kdef = getKind (kcb, i);
270 Assert(kdef);
271 if (kdef->name && (strcmp(kdef->name, name) == 0))
272 return kdef;
274 return NULL;
277 extern int getKindIndexForLetter (struct kindControlBlock* kcb, char letter)
279 unsigned int i;
280 kindDefinition * kdef;
282 for (i = 0; i < countKinds (kcb); ++i)
284 kdef = getKind (kcb, i);
285 if (kdef->letter == letter)
286 return (unsigned int)i;
288 return KIND_GHOST_INDEX;
291 extern int getKindIndexForName (struct kindControlBlock* kcb, const char* name)
293 unsigned int i;
294 kindDefinition * kdef;
296 for (i = 0; i < countKinds (kcb); ++i)
298 kdef = getKind (kcb, i);
299 Assert(kdef);
300 if (kdef->name && (strcmp(kdef->name, name) == 0))
301 return (int)i;
303 return KIND_GHOST_INDEX;
306 extern roleDefinition* getRole(struct kindControlBlock* kcb, int kindIndex, int roleIndex)
308 struct roleControlBlock *rcb = kcb->kind[kindIndex].rcb;
309 return rcb->role [roleIndex].def;
312 extern roleDefinition* getRoleForName(struct kindControlBlock* kcb,
313 int kindIndex, const char* name)
315 unsigned int i;
316 roleDefinition *rdef;
318 for (i = 0; i < countRoles (kcb, kindIndex); ++i)
320 rdef = getRole(kcb, kindIndex, i);
321 Assert(rdef);
322 if (rdef->name && (strcmp(rdef->name, name) == 0))
323 return rdef;
325 return NULL;
328 static void linkKinds (langType master, kindDefinition *masterKind, kindDefinition *slaveKind)
330 kindDefinition *tail;
332 slaveKind->master = masterKind;
334 tail = slaveKind;
335 while (tail->slave)
337 tail->enabled = masterKind->enabled;
338 tail = tail->slave;
341 tail->slave = masterKind->slave;
342 masterKind->slave = slaveKind;
344 masterKind->syncWith = master;
345 slaveKind->syncWith = master;
348 extern void linkKindDependency (struct kindControlBlock *masterKCB,
349 struct kindControlBlock *slaveKCB)
351 unsigned int k_slave, k_master;
352 kindDefinition *kind_slave, *kind_master;
354 for (k_slave = 0; k_slave < countKinds (slaveKCB); k_slave++)
356 kind_slave = getKind(slaveKCB, k_slave);
357 if (kind_slave->syncWith == LANG_AUTO)
359 for (k_master = 0; k_master < countKinds (masterKCB); k_master++)
361 kind_master = getKind(masterKCB, k_master);
362 if ((kind_slave->letter == kind_master->letter)
363 && (strcmp (kind_slave->name, kind_master->name) == 0))
365 linkKinds (masterKCB->owner, kind_master, kind_slave);
366 break;
373 static void scopeSeparatorDelete (void *data)
375 scopeSeparator *sep = data;
376 eFree ((void *)sep->separator);
377 sep->separator = NULL;
378 eFree (sep);
381 extern int defineScopeSeparator(struct kindControlBlock* kcb,
382 int kindIndex,
383 int parentKindIndex, const char *separator)
385 if (kindIndex == KIND_WILDCARD_INDEX)
387 if (parentKindIndex == KIND_WILDCARD_INDEX)
389 if (kcb->defaultScopeSeparator.separator)
390 eFree ((char *)kcb->defaultScopeSeparator.separator);
391 verbose ("Installing default separator for %s: %s\n",
392 getLanguageName (kcb->owner), separator);
393 kcb->defaultScopeSeparator.separator = eStrdup (separator);
395 else if (parentKindIndex == KIND_GHOST_INDEX)
397 if (kcb->defaultRootScopeSeparator.separator)
398 eFree ((char *)kcb->defaultRootScopeSeparator.separator);
399 verbose ("Installing default root separator for %s: %s\n",
400 getLanguageName (kcb->owner),
401 separator);
402 kcb->defaultRootScopeSeparator.separator = eStrdup (separator);
404 else
405 error (FATAL,
406 "Don't specify a real kind as parent when defining a default scope separator: %d",
407 parentKindIndex);
408 return 0;
410 Assert (kcb->count > kindIndex);
411 kindObject *kind = kcb->kind + kindIndex;
413 if (!kind->dynamicSeparators)
414 kind->dynamicSeparators = ptrArrayNew (scopeSeparatorDelete);
416 scopeSeparator *sep = xMalloc (1, scopeSeparator);
417 sep->parentKindIndex = parentKindIndex;
418 sep->separator = eStrdup(separator);
419 ptrArrayAdd (kind->dynamicSeparators, sep);
421 return 0;
424 static scopeSeparator *getScopeSeparatorDynamic(kindObject *kobj, int parentKindIndex)
426 scopeSeparator *sep;
428 if (kobj->dynamicSeparators)
430 for (unsigned int i = ptrArrayCount (kobj->dynamicSeparators); 0 < i ; i--)
432 sep = ptrArrayItem (kobj->dynamicSeparators, i - 1);
433 if (sep->parentKindIndex == parentKindIndex)
434 return sep;
437 return NULL;
440 static const scopeSeparator *getScopeSeparatorStatic(kindDefinition *kdef, int parentKindIndex)
442 scopeSeparator *table = kdef->separators;
444 if (table == NULL)
445 return NULL;
447 while (table - kdef->separators < (int)kdef->separatorCount)
449 if (table->parentKindIndex == parentKindIndex)
450 return table;
452 /* If a caller wants a root separator for kdef,
453 we should not return a wildcard table. */
454 if (parentKindIndex != KIND_GHOST_INDEX
455 && table->parentKindIndex == KIND_WILDCARD_INDEX)
456 return table;
458 table++;
461 return NULL;
464 extern const scopeSeparator *getScopeSeparator(struct kindControlBlock* kcb,
465 int kindIndex, int parentKindIndex)
467 Assert (kindIndex != KIND_GHOST_INDEX);
468 Assert (kindIndex != KIND_FILE_INDEX);
469 Assert (kindIndex != KIND_WILDCARD_INDEX);
471 Assert (parentKindIndex != KIND_WILDCARD_INDEX);
472 Assert (parentKindIndex != KIND_FILE_INDEX);
473 /* A caller specifies KIND_GHOST_INDEX for parentKindIndex when it
474 * wants root separator. */
476 Assert (kcb->count > kindIndex);
477 kindObject *kobj = kcb->kind + kindIndex;
478 const scopeSeparator *sep;
480 sep = getScopeSeparatorDynamic (kobj, parentKindIndex);
481 if (sep)
482 return sep;
484 sep = getScopeSeparatorStatic (kobj->def, parentKindIndex);
485 if (sep)
486 return sep;
488 /* Cannot find a suitable sep definition.
489 * Use default one. */
490 if (parentKindIndex == KIND_GHOST_INDEX)
492 if (kcb->defaultRootScopeSeparator.separator)
493 return &kcb->defaultRootScopeSeparator;
494 return NULL;
496 else
498 if (kcb->defaultScopeSeparator.separator)
499 return &kcb->defaultScopeSeparator;
501 static scopeSeparator defaultSeparator = {
502 .separator = ".",
503 .parentKindIndex = KIND_WILDCARD_INDEX,
505 return &defaultSeparator;
509 #ifdef DEBUG
510 extern bool doesParserUseKind (struct kindControlBlock* kcb, char letter)
512 unsigned int k;
513 kindDefinition *kdef;
515 for (k = 0; k < countKinds (kcb); k++)
517 kdef = getKind(kcb, k);
518 if (kdef->letter == letter)
519 return true;
521 return false;
523 #endif
525 extern struct colprintTable * kindColprintTableNew (void)
527 return colprintTableNew ("L:LANGUAGE", "L:LETTER", "L:NAME", "L:ENABLED",
528 "L:REFONLY", "L:NROLES", "L:MASTER",
529 "L:DESCRIPTION",
530 NULL);
533 static void kindColprintFillLine (struct colprintLine *line,
534 const char *langName,
535 kindDefinition *kdef)
537 langType lang = getNamedLanguage (langName, 0);
538 unsigned int count = countLanguageRoles(lang, kdef->id);
539 colprintLineAppendColumnCString (line, langName);
540 colprintLineAppendColumnChar (line, kdef->letter);
541 colprintLineAppendColumnCString (line, kdef->name
542 ? kdef->name
543 : "ThisShouldNotBePrintedKindNameMustBeGiven");
544 colprintLineAppendColumnBool (line, kdef->enabled);
545 colprintLineAppendColumnBool (line, kdef->referenceOnly);
546 colprintLineAppendColumnInt (line, count);
547 colprintLineAppendColumnCString (line, (kdef->master
548 || kdef->slave ) ?
549 getLanguageName (kdef->syncWith): RSV_NONE);
550 colprintLineAppendColumnCString (line, kdef->description? kdef->description: "NO DESCRIPTION GIVEN");
553 extern void kindColprintAddLanguageLines (struct colprintTable *table,
554 struct kindControlBlock* kcb)
556 const char *lang = getLanguageName (kcb->owner);
557 for (unsigned int i = 0; i < countKinds (kcb); i++)
559 kindDefinition *kdef = getKind (kcb, i);
560 struct colprintLine *line = colprintTableGetNewLine(table);
562 kindColprintFillLine (line, lang, kdef);
566 static int kindColprintCompareLines (struct colprintLine *a , struct colprintLine *b)
568 const char *a_parser = colprintLineGetColumn (a, 0);
569 const char *b_parser = colprintLineGetColumn (b, 0);
570 const char *a_letter;
571 const char *b_letter;
572 int r;
574 r = strcmp (a_parser, b_parser);
575 if (r != 0)
576 return r;
578 a_letter = colprintLineGetColumn (a, 1);
579 b_letter = colprintLineGetColumn (b, 1);
580 r = strcmp (a_letter, b_letter);
581 if (r != 0)
582 return r;
584 return 0;
587 extern void kindColprintTablePrint (struct colprintTable *table, bool noparser,
588 bool withListHeader, bool machinable, FILE *fp)
590 colprintTableSort (table, kindColprintCompareLines);
591 colprintTablePrint (table, noparser? 1: 0, withListHeader, machinable, fp);
595 extern struct colprintTable * roleColprintTableNew (void)
597 return colprintTableNew ("L:LANGUAGE", "L:KIND(L/N)", "L:NAME",
598 "L:ENABLED", "L:DESCRIPTION", NULL);
601 extern void roleColprintAddRoles (struct colprintTable *table, struct kindControlBlock *kcb,
602 const char *kindspecs)
604 const char* lang;
605 vString *kind_l_and_n;
607 lang = getLanguageName (kcb->owner);
608 kind_l_and_n = vStringNew ();
609 for (const char *c = kindspecs; *c != '\0'; c++)
611 const char *kname = NULL;
612 size_t kname_len;
614 if (*c == '{')
616 const char *start = c + 1;
617 const char *end = strchr(c, '}');
619 if (!end)
620 error (FATAL, "'{' is not closed with '}' in \"%s\"", c);
621 if (start == end)
622 error (FATAL, "empty kind name is given in \"%s\"", c);
624 kname = start;
625 kname_len = end - start;
626 c = end;
629 for (unsigned int i = 0; i < countKinds (kcb); i++)
631 const kindDefinition *k = getKind (kcb, i);
633 if ((kname
634 && strlen (k->name) == kname_len
635 && strncmp (k->name, kname, kname_len) == 0)
636 || (!kname && *c == k->letter)
637 || (!kname && *c == KIND_WILDCARD_LETTER))
639 unsigned int nRoles = countRoles(kcb, i);
640 for (unsigned int j = 0; j < nRoles; j++)
642 const roleDefinition *r = getRole (kcb, i, j);
643 struct colprintLine *line = colprintTableGetNewLine(table);
645 colprintLineAppendColumnCString (line, lang);
647 vStringPut (kind_l_and_n, k->letter);
648 vStringPut (kind_l_and_n, '/');
649 vStringCatS (kind_l_and_n, k->name);
650 colprintLineAppendColumnVString (line, kind_l_and_n);
651 vStringClear (kind_l_and_n);
653 colprintLineAppendColumnCString (line, r->name);
654 colprintLineAppendColumnCString (line,
655 r->enabled ? "on" : "off");
656 colprintLineAppendColumnCString (line, r->description);
658 if (! (!kname && *c == KIND_WILDCARD_LETTER))
659 break;
663 vStringDelete (kind_l_and_n);
664 #if 0
665 if ((i == countKinds (kcb)) && (*c != KIND_WILDCARD) && (!allowMissingKind))
666 error (FATAL, "No such letter kind in %s: %c\n", lang->name, *c);
667 #endif
670 static int roleColprintCompareLines(struct colprintLine *a, struct colprintLine *b)
672 int r;
674 const char *a_parser, *b_parser;
675 a_parser = colprintLineGetColumn (a, 0);
676 b_parser = colprintLineGetColumn (b, 0);
678 r = strcmp(a_parser, b_parser);
679 if (r != 0)
680 return r;
682 const char *a_kindln, *b_kindln;
683 a_kindln = colprintLineGetColumn (a, 1);
684 b_kindln = colprintLineGetColumn (b, 1);
686 r = strcmp(a_kindln, b_kindln);
687 if (r != 0)
688 return r;
690 const char *a_role, *b_role;
691 a_role = colprintLineGetColumn (a, 2);
692 b_role = colprintLineGetColumn (b, 2);
694 return strcmp(a_role, b_role);
697 extern void roleColprintTablePrint (struct colprintTable *table, bool noparser,
698 bool withListHeader, bool machinable, FILE *fp)
700 colprintTableSort (table, roleColprintCompareLines);
701 colprintTablePrint (table, noparser? 1: 0, withListHeader, machinable, fp);