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