/* */
This source file includes following definitions.
- split
- recover
- split_dump
- parse_xid
- nextstring
- nextelement
1 /*
2 * Copyright (c) 2002, 2010 Tama Communications Corporation
3 *
4 * This file is part of GNU GLOBAL.
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23 #include <stdio.h>
24 #include "split.h"
25 #include "die.h"
26
27 /** @file
28 * Substring manager like @NAME{perl}'s @NAME{split}.
29 *
30 * @code
31 * Initial status.
32 * +------------------------------------------------------
33 * line |main 100 ./main.c main(argc, argv)\n
34 * @endcode
35 *
36 * The result of @CODE{split(line, 4, &list)}:
37 *
38 * @code
39 * +------------------------------------------------------
40 * list line |main\0 100\0 ./main.c\0 main(argc, argv)\n
41 * +---------+ ^ ^ ^ ^ ^ ^ ^
42 * |npart=4 | | | | | | | |
43 * +---------+ | | | | | | |
44 * | start *----+ | | | | | |
45 * | end *--------+ | | | | |
46 * | save ' '| | | | | |
47 * +---------+ | | | | |
48 * | start *-----------------+ | | | |
49 * | end *--------------------+ | | |
50 * | save ' '| | | |
51 * +---------+ | | |
52 * | start *------------------------+ | |
53 * | end *--------------------------------+ |
54 * | save ' '| |
55 * +---------+ |
56 * | start *----------------------------------------+
57 * | end *--+
58 * | save | |
59 * +---------+ =
60 * @endcode
61 *
62 * The result of @CODE{split(line, 2, &list)}:
63 *
64 * @code
65 * +------------------------------------------------------
66 * list line |main\0 100 ./main.c main(argc, argv)\n
67 * +---------+ ^ ^ ^
68 * |npart=2 | | | |
69 * +---------+ | | |
70 * | start *----+ | |
71 * | end *--------+ |
72 * | save ' '| |
73 * +---------+ |
74 * | start *-----------------+
75 * | end *--+
76 * | save | |
77 * +---------+ =
78 * @endcode
79 *
80 * The result of recover().
81 * @code
82 * +------------------------------------------------------
83 * line |main 100 ./main.c main(argc, argv)\n
84 * @endcode
85 *
86 * Recover() recover initial status of line with saved char in @NAME{savec}.
87 */
88
89 #define isblank(c) ((c) == ' ' || (c) == '\t')
90
91 /**
92 * split: split a string into pieces
93 *
94 * @param[in] line string
95 * @param[in] npart parts number
96 * @param[in,out] list split table
97 * @return part count
98 */
99 int
100 split(const char *line, int npart, SPLIT *list) /* virtually const */
101 {
102 char *s = (char *)line;
103 struct part *part = &list->part[0];
104 int count;
105
106 if (npart > NPART)
107 npart = NPART;
108 npart--;
109 for (count = 0; *s && count < npart; count++) {
110 while (*s && isblank(*s))
111 s++;
112 if (*s == '\0')
113 break;
114 part->start = s;
115 while (*s && !isblank(*s))
116 s++;
117 part->end = s;
118 part->savec = *s;
119 part++;
120 }
121 if (*s) {
122 while (*s && isblank(*s))
123 s++;
124 part->start = s;
125 part->end = (char *)0;
126 part->savec = 0;
127 count++;
128 part++;
129 }
130 while (part-- > &list->part[0]) {
131 if (part->savec != '\0')
132 *part->end = '\0';
133 }
134 return list->npart = count;
135 }
136 /**
137 * recover: recover initial status of line.
138 *
139 * @param[in,out] list split table
140 */
141 void
142 recover(SPLIT *list)
143 {
144 int i, c;
145 for (i = 0; i < list->npart; i++) {
146 if ((c = list->part[i].savec) != '\0')
147 *(list->part[i].end) = c;
148 }
149 }
150 /**
151 * split_dump: dump split structure.
152 */
153 void
154 split_dump(SPLIT *list)
155 {
156 int i;
157 struct part *part;
158
159 fprintf(stderr, "npart: %d\n", list->npart);
160
161 for (i = 0; i < list->npart; i++) {
162 part = &list->part[i];
163 fprintf(stderr, "string[%d]: |%s|\n", i, part->start);
164 fprintf(stderr, "savec[%d] : |%c|\n", i, part->savec);
165 }
166 }
167 /**
168 * parse_xid: extract fid from @a ctags_xid format record.
169 *
170 * @param[in] ctags_xid ctags-xid record
171 * @param[out] s_fid file id(string) if not @VAR{NULL}
172 * @param[out] n_fid file id(integer) if not @VAR{NULL}
173 * @return pointer to the @NAME{ctags_x} part
174 */
175 const char *
176 parse_xid(const char *ctags_xid, char *s_fid, int *n_fid)
177 {
178 const char *p;
179 int i, n;
180
181 i = n = 0;
182 for (p = ctags_xid; *p && *p >= '0' && *p <= '9'; p++) {
183 n = n * 10 + (*p - '0');
184 if (s_fid)
185 s_fid[i++] = *p;
186 }
187 if (*p++ != ' ')
188 die("illegal ctags-xid format record. '%s'", ctags_xid);
189 if (s_fid)
190 s_fid[i] = '\0';
191 if (n_fid != NULL)
192 *n_fid = n;
193 return p;
194 }
195 /**
196 * nextstring: seek to the next string.
197 *
198 * @param[in] s original string
199 * @return next string
200 *
201 * @code
202 * s v
203 * "aaaaaa\0bbbbb\0"
204 * @endcode
205 */
206 const char *
207 nextstring(const char *s)
208 {
209 while (*s)
210 s++;
211 return s + 1;
212 }
213 /**
214 * nextelement: seek to the next element
215 *
216 * @param[in] s point the current element or the following blanks
217 * @return next element
218 *
219 * @code{.txt}
220 * s s return value
221 * v v v
222 * xxxxx yyyyy zzzzzz
223 * (current) (next)
224 * @endcode
225 */
226 const char *
227 nextelement(const char *s)
228 {
229 while (*s && !isblank(*s))
230 s++;
231 if (!*s)
232 die("nextelement: unexpected end of string(1).");
233 while (*s && isblank(*s))
234 s++;
235 if (!*s)
236 die("nextelement: unexpected end of string(2).");
237 return s;
238 }
/* */