xref: /Universal-ctags/extra-cmds/printtags.c (revision edacac16d211ce9f529cb64befe1b67431a12257)
1 /*
2 *   Copyright (c) 1996-2003, Darren Hiebert
3 *
4 *   This source code is released into the public domain.
5 *
6 *   This module contains functions for reading tag files.
7 */
8 
9 /*
10 *   INCLUDE FILES
11 */
12 
13 #include "printtags.h"
14 #include <stdio.h>
15 
16 
17 /*
18 *   DATA DEFINITIONS
19 */
20 
21 static tagPrintProcs printFILEProcs = {
22 	.printStr = (int  (*) (const char *, void *))fputs,
23 	.printChar = (int  (*) (int, void *))fputc,
24 };
25 
26 
27 /*
28 *   FUNCTION DEFINITIONS
29 */
30 
ultostr(char dst[21],unsigned long d)31 static void ultostr (char dst [21], unsigned long d)
32 {
33 	int o [20];
34 	int i;
35 
36 	if (d == 0)
37 	{
38 		dst [0] = '0';
39 		dst [1] = '\0';
40 		return;
41 	}
42 
43 	for (i = 0; d != 0; i++, d = d/10)
44 		o [i] = d % 10;
45 
46 	for (int j = i - 1; j >= 0; j--)
47 		dst [i - j - 1] = o[j] + '0';
48 	dst [i] = '\0';
49 }
50 
printValue(const char * val,int printingWithEscaping,int (* print_str)(const char *,void *),int (* print_char)(int,void *),void * outfp)51 static void printValue (const char *val, int printingWithEscaping,
52 						int  (* print_str) (const char *, void *),
53 						int  (* print_char) (int, void *),
54 						void *outfp)
55 {
56 	if (printingWithEscaping)
57 	{
58 		for(; *val != '\0'; val++)
59 		{
60 			switch (*val)
61 			{
62 				case '\t': print_str ("\\t",  outfp); break;
63 				case '\r': print_str ("\\r",  outfp); break;
64 				case '\n': print_str ("\\n",  outfp); break;
65 				case '\\': print_str ("\\\\", outfp); break;
66 					/* Universal-CTags extensions */
67 				case '\a': print_str ("\\a", outfp); break;
68 				case '\b': print_str ("\\b", outfp); break;
69 				case '\v': print_str ("\\v", outfp); break;
70 				case '\f': print_str ("\\f", outfp); break;
71 				default:
72 					if ((0x01 <= *val && *val <= 0x1F) || *val == 0x7F)
73 					{
74 						char c[5] = {
75 							[0] = '\\',
76 							[1] = 'x',
77 						};
78 						c [2] = (*val / 16) % 16;
79 #if 0
80 						if (c [2] == 0)
81 						{
82 							c [2] = *val % 16;
83 							c [2] += ( c [2] < 10 )? '0': 'A' - 9;
84 							c [3] = '\0';
85 						}
86 						else
87 #endif
88 						{
89 							c [2] += ( c [2] < 10 )? '0': 'A' - 9;
90 							c [3] = *val % 16;
91 							c [3] += ( c [3] < 10 )? '0': 'A' - 9;
92 							c [4] = '\0';
93 						}
94 						print_str (c, outfp);
95 					}
96 					else
97 						print_char (*val, outfp);
98 			}
99 		}
100 	}
101 	else
102 		print_str (val, outfp);
103 }
104 
tagsPrintTag(const tagEntry * entry,int printingExtensionFields,int printingLineNumber,int printingWithEscaping,int pseudoTag,int (* print_str)(const char *,void *),int (* print_char)(int,void *),void * outfp)105 static void tagsPrintTag (const tagEntry *entry,
106 						  int printingExtensionFields,
107 						  int printingLineNumber,
108 						  int printingWithEscaping,
109 						  int pseudoTag,
110 						  int  (* print_str) (const char *, void *),
111 						  int  (* print_char) (int, void *),
112 						  void *outfp)
113 {
114 	int i;
115 	int first = 1;
116 	const char* separator = ";\"";
117 	const char* const empty = "";
118 /* "sep" returns a value only the first time it is evaluated */
119 #define sep (first ? (first = 0, separator) : empty)
120 
121 	if (entry->name == NULL
122 		|| entry->file == NULL
123 		|| entry->address.pattern == NULL)
124 		return;
125 	if (pseudoTag)
126 		print_str (entry->name, outfp);
127 	else if (*entry->name == '!' && printingWithEscaping)
128 	{
129 		print_str ("\\x21", outfp);
130 		printValue (entry->name + 1, printingWithEscaping,
131 					print_str, print_char, outfp);
132 	}
133 	else if (*entry->name == ' ' && printingWithEscaping)
134 	{
135 		print_str ("\\x20", outfp);
136 		printValue (entry->name + 1, printingWithEscaping,
137 					print_str, print_char, outfp);
138 	}
139 	else
140 		printValue (entry->name, printingWithEscaping,
141 					print_str, print_char, outfp);
142 
143 	print_char ('\t', outfp);
144 	printValue  (entry->file, printingWithEscaping,
145 				 print_str, print_char, outfp);
146 	print_char ('\t', outfp);
147 	print_str (entry->address.pattern, outfp);
148 
149 	if (printingExtensionFields)
150 	{
151 		if (entry->kind != NULL  &&  entry->kind [0] != '\0')
152 		{
153 			print_str (sep, outfp);
154 			print_str ("\tkind:", outfp);
155 			printValue (entry->kind, printingWithEscaping,
156 						print_str, print_char, outfp);
157 			first = 0;
158 		}
159 		if (entry->fileScope)
160 		{
161 			print_str (sep, outfp);
162 			print_str ("\tfile:", outfp);
163 			first = 0;
164 		}
165 		if (printingLineNumber && entry->address.lineNumber > 0)
166 		{
167 			print_str (sep, outfp);
168 			print_str ("\tline:", outfp);
169 			char buf [20 + 1];	/* 20 comes from UINNT64_MAX, 1 is for \0. */
170 			ultostr (buf, entry->address.lineNumber);
171 			print_str (buf, outfp);
172 			first = 0;
173 		}
174 		for (i = 0  ;  i < entry->fields.count  ;  ++i)
175 		{
176 			if (entry->fields.list [i].key)
177 			{
178 				print_str (sep, outfp);
179 				print_char ('\t', outfp);
180 				print_str (entry->fields.list [i].key, outfp);
181 				print_char (':', outfp);
182 				if (entry->fields.list  [i].value)
183 					printValue (entry->fields.list [i].value,
184 								printingWithEscaping, print_str, print_char, outfp);
185 				first = 0;
186 			}
187 		}
188 	}
189 	print_char ('\n', outfp);
190 #undef sep
191 }
192 
tagsPrint(const tagEntry * entry,tagPrintOptions * opt,tagPrintProcs * procs,void * outfp)193 extern int tagsPrint (const tagEntry *entry,
194 					  tagPrintOptions *opt, tagPrintProcs *procs, void *outfp)
195 {
196 	if (!procs)
197 		procs = &printFILEProcs;
198 
199 	tagsPrintTag (entry,
200 				  opt->extensionFields,
201 				  opt->lineNumber,
202 				  opt->escaping,
203 				  0,
204 				  procs->printStr,
205 				  procs->printChar,
206 				  outfp);
207 	return 1;					/* TODO */
208 }
209 
tagsPrintPseudoTag(const tagEntry * entry,tagPrintOptions * opt,tagPrintProcs * procs,void * outfp)210 extern int tagsPrintPseudoTag (const tagEntry *entry,
211 							   tagPrintOptions *opt, tagPrintProcs *procs, void *outfp)
212 {
213 	if (!procs)
214 		procs = &printFILEProcs;
215 
216 	tagsPrintTag (entry,
217 				  opt->extensionFields,
218 				  opt->lineNumber,
219 				  opt->escaping,
220 				  1,
221 				  procs->printStr,
222 				  procs->printChar,
223 				  outfp);
224 	return 1;					/* TODO */
225 }
226