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.
19 #include "colprint_p.h"
30 typedef struct sRoleObject
{
35 struct roleControlBlock
{
41 typedef struct sKindObject
{
44 struct roleControlBlock
*rcb
;
45 ptrArray
* dynamicSeparators
;
48 struct kindControlBlock
{
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
;
75 enableKind (kind
->master
, enable
);
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
)
92 size_t len
= strlen (rdef
->name
);
93 for (int i
= 0; i
< len
; i
++)
94 Assert (isalnum ((unsigned char) rdef
->name
[i
]));
97 robj
->free
= freefunc
;
98 robj
->def
->id
= roleId
;
101 static struct roleControlBlock
* allocRoleControlBlock (kindObject
*kind
)
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
);
116 extern struct kindControlBlock
* allocKindControlBlock (parserDefinition
*parser
)
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
));
147 kind
->rcb
= allocRoleControlBlock (kind
);
148 kind
->dynamicSeparators
= NULL
;
154 static void freeRoleControlBlock (struct roleControlBlock
*rcb
)
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
);
166 extern void freeKindControlBlock (struct kindControlBlock
* kcb
)
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
);
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
));
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
)
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
);
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
)
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
)
251 kindDefinition
* kdef
;
253 for (i
= 0; i
< countKinds (kcb
); ++i
)
255 kdef
= getKind (kcb
, i
);
256 if (kdef
->letter
== letter
)
262 extern kindDefinition
*getKindForName (struct kindControlBlock
* kcb
, const char* name
)
265 kindDefinition
* kdef
;
267 for (i
= 0; i
< countKinds (kcb
); ++i
)
269 kdef
= getKind (kcb
, i
);
271 if (kdef
->name
&& (strcmp(kdef
->name
, name
) == 0))
277 extern int getKindIndexForLetter (struct kindControlBlock
* kcb
, char letter
)
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
)
294 kindDefinition
* kdef
;
296 for (i
= 0; i
< countKinds (kcb
); ++i
)
298 kdef
= getKind (kcb
, i
);
300 if (kdef
->name
&& (strcmp(kdef
->name
, name
) == 0))
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
)
316 roleDefinition
*rdef
;
318 for (i
= 0; i
< countRoles (kcb
, kindIndex
); ++i
)
320 rdef
= getRole(kcb
, kindIndex
, i
);
322 if (rdef
->name
&& (strcmp(rdef
->name
, name
) == 0))
328 static void linkKinds (langType master
, kindDefinition
*masterKind
, kindDefinition
*slaveKind
)
330 kindDefinition
*tail
;
332 slaveKind
->master
= masterKind
;
337 tail
->enabled
= masterKind
->enabled
;
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
);
373 static void scopeSeparatorDelete (void *data
)
375 scopeSeparator
*sep
= data
;
376 eFree ((void *)sep
->separator
);
377 sep
->separator
= NULL
;
381 extern int defineScopeSeparator(struct kindControlBlock
* kcb
,
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
),
402 kcb
->defaultRootScopeSeparator
.separator
= eStrdup (separator
);
406 "Don't specify a real kind as parent when defining a default scope separator: %d",
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
);
424 static scopeSeparator
*getScopeSeparatorDynamic(kindObject
*kobj
, int parentKindIndex
)
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
)
440 static const scopeSeparator
*getScopeSeparatorStatic(kindDefinition
*kdef
, int parentKindIndex
)
442 scopeSeparator
*table
= kdef
->separators
;
447 while (table
- kdef
->separators
< (int)kdef
->separatorCount
)
449 if (table
->parentKindIndex
== parentKindIndex
)
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
)
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
);
484 sep
= getScopeSeparatorStatic (kobj
->def
, parentKindIndex
);
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
;
498 if (kcb
->defaultScopeSeparator
.separator
)
499 return &kcb
->defaultScopeSeparator
;
501 static scopeSeparator defaultSeparator
= {
503 .parentKindIndex
= KIND_WILDCARD_INDEX
,
505 return &defaultSeparator
;
510 extern bool doesParserUseKind (struct kindControlBlock
* kcb
, char letter
)
513 kindDefinition
*kdef
;
515 for (k
= 0; k
< countKinds (kcb
); k
++)
517 kdef
= getKind(kcb
, k
);
518 if (kdef
->letter
== letter
)
525 extern struct colprintTable
* kindColprintTableNew (void)
527 return colprintTableNew ("L:LANGUAGE", "L:LETTER", "L:NAME", "L:ENABLED",
528 "L:REFONLY", "L:NROLES", "L:MASTER",
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
543 : "ThisShouldNotBePrintedKindNameMustBeGiven");
544 colprintLineAppendColumnBool (line
, kdef
->enabled
);
545 colprintLineAppendColumnBool (line
, kdef
->referenceOnly
);
546 colprintLineAppendColumnInt (line
, count
);
547 colprintLineAppendColumnCString (line
, (kdef
->master
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
;
574 r
= strcmp (a_parser
, b_parser
);
578 a_letter
= colprintLineGetColumn (a
, 1);
579 b_letter
= colprintLineGetColumn (b
, 1);
580 r
= strcmp (a_letter
, b_letter
);
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
)
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
;
616 const char *start
= c
+ 1;
617 const char *end
= strchr(c
, '}');
620 error (FATAL
, "'{' is not closed with '}' in \"%s\"", c
);
622 error (FATAL
, "empty kind name is given in \"%s\"", c
);
625 kname_len
= end
- start
;
629 for (unsigned int i
= 0; i
< countKinds (kcb
); i
++)
631 const kindDefinition
*k
= getKind (kcb
, i
);
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
))
663 vStringDelete (kind_l_and_n
);
665 if ((i
== countKinds (kcb
)) && (*c
!= KIND_WILDCARD
) && (!allowMissingKind
))
666 error (FATAL
, "No such letter kind in %s: %c\n", lang
->name
, *c
);
670 static int roleColprintCompareLines(struct colprintLine
*a
, struct colprintLine
*b
)
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
);
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
);
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
);