xref: /Universal-ctags/parsers/systemdunit.c (revision 6b1a862e526d5017f9f212a321f59d67c859d521)
1 /*
2 *
3 *   Copyright (c) 2015, Red Hat, Inc.
4 *   Copyright (c) 2015, Masatake YAMATO
5 *
6 *   This source code is released for free distribution under the terms of the
7 *   GNU General Public License version 2 or (at your option) any later version.
8 *
9 */
10 
11 /*
12 *   INCLUDE FILES
13 */
14 #include "general.h"  /* must always come first */
15 
16 #include <ctype.h>
17 #include <string.h>
18 
19 #include "entry.h"
20 #include "iniconf.h"
21 #include "parse.h"
22 #include "read.h"
23 #include "routines.h"
24 #include "vstring.h"
25 #include "xtag.h"
26 
27 
28 
29 /*
30 *   DATA DEFINITIONS
31 */
32 typedef enum {
33 	K_UNIT,
34 } systemdUnitKind;
35 
36 typedef enum {
37 	R_UNIT_Requires,
38 	R_UNIT_Wants,
39 	R_UNIT_After,
40 	R_UNIT_Before,
41 	R_UNIT_RequiredBy,
42 	R_UNIT_WantedBy,
43 
44 } systemdUnitRole;
45 
46 static roleDefinition SystemdUnitUnitRoles [] = {
47 	{ true, "Requires", "referred in Requires key" },
48 	{ true, "Wants", "referred in Wants key" },
49 	{ true, "After", "referred in After key" },
50 	{ true, "Before", "referred in Before key" },
51 	{ true, "RequiredBy", "referred in RequiredBy key" },
52 	{ true, "WantedBy", "referred in WantedBy key" },
53 	/* ... */
54 };
55 
56 static kindDefinition SystemdUnitKinds [] = {
57 	{ true, 'u', "unit", "units",
58 	  .referenceOnly = true, ATTACH_ROLES(SystemdUnitUnitRoles)},
59 };
60 
roleOf(const char * key,int kind)61 static int roleOf (const char* key, int kind)
62 {
63 	int i;
64 
65 	for (i = 0; i < SystemdUnitKinds [kind].nRoles; i++)
66 	{
67 		if (strcmp (SystemdUnitKinds [kind].roles[i].name, key) == 0)
68 			return i;
69 	}
70 
71 	return -1;
72 }
73 
makeSystemdReferencedUnit(const char * value,int kind,int role)74 static void makeSystemdReferencedUnit (const char *value, int kind, int role)
75 {
76 	vString *unit = vStringNew ();
77 
78 	while (*value != '\0')
79 	{
80 		if (*value == ',')
81 		{
82 			makeSimpleRefTag (unit, kind, role);
83 			vStringClear (unit);
84 		}
85 		else if (! isspace ((int) *value))
86 			vStringPut (unit, *value);
87 
88 		value++;
89 	}
90 
91 	if (vStringLength (unit) > 0)
92 		makeSimpleRefTag (unit, kind, role);
93 	vStringDelete (unit);
94 }
95 
newDataCallback(iniconfSubparser * s CTAGS_ATTR_UNUSED,const char * section CTAGS_ATTR_UNUSED,const char * key,const char * value)96 static void newDataCallback (iniconfSubparser *s CTAGS_ATTR_UNUSED,
97 							 const char *section CTAGS_ATTR_UNUSED, const char *key, const char *value)
98 {
99 	int r;
100 
101 	if (isXtagEnabled (XTAG_REFERENCE_TAGS) && value)
102 	{
103 		r = roleOf (key, K_UNIT);
104 		if (r >= 0)
105 			makeSystemdReferencedUnit (value, K_UNIT, r);
106 	}
107 }
108 
findSystemdUnitTags(void)109 static void findSystemdUnitTags (void)
110 {
111 	scheduleRunningBaseparser (0);
112 }
113 
SystemdUnitParser(void)114 extern parserDefinition* SystemdUnitParser (void)
115 {
116 	static const char *const extensions [] = { "service", "socket", "device",
117 											   "mount", "automount", "swap", "target",
118 											   "path", "timer", "snapshot",
119 											   "slice", NULL };
120 	static iniconfSubparser systemdUnitSubparser = {
121 		.subparser = {
122 			.direction = SUBPARSER_SUB_RUNS_BASE,
123 		},
124 		.newDataNotify = newDataCallback,
125 	};
126 	static parserDependency dependencies [] = {
127 		[0] = { DEPTYPE_SUBPARSER, "Iniconf", &systemdUnitSubparser },
128 	};
129 
130 	parserDefinition* const def = parserNew ("SystemdUnit");
131 
132 	def->dependencies = dependencies;
133 	def->dependencyCount = ARRAY_SIZE(dependencies);
134 	def->kindTable      = SystemdUnitKinds;
135 	def->kindCount  = ARRAY_SIZE (SystemdUnitKinds);
136 	def->extensions = extensions;
137 	def->parser     = findSystemdUnitTags;
138 	def->useCork    = CORK_QUEUE;
139 	return def;
140 }
141