dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libmail / common / s_string.c
bloba57889d96a4ffea43c61b6219d737850d1560fc6
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
30 #pragma ident "%Z%%M% %I% %E% SMI"
32 #include <sys/types.h>
33 #include <stdio.h>
34 #include <ctype.h>
35 #include "s_string.h"
36 #include <stdlib.h>
38 /* global to this file */
39 #define STRLEN 128UL
40 #define STRALLOC 128UL
41 #define MAXINCR 250000UL
43 /* buffer pool for allocating string structures */
44 typedef struct {
45 string s[STRALLOC];
46 size_t o;
47 } stralloc;
48 static stralloc *freep = NULL;
50 /* pool of freed strings */
51 static string *freed = NULL;
52 static string *s_alloc(void);
53 static void s_simplegrow(string *, size_t);
55 void
56 s_free(string *sp)
58 if (sp != NULL) {
59 sp->ptr = (char *)freed;
60 freed = sp;
64 /* allocate a string head */
65 static string *
66 s_alloc(void)
68 if (freep == NULL || freep->o >= STRALLOC) {
69 freep = (stralloc *)malloc(sizeof (stralloc));
70 if (freep == NULL) {
71 perror("allocating string");
72 exit(1);
74 freep->o = (size_t)0;
76 return (&(freep->s[freep->o++]));
79 /* create a new `short' string */
80 string *
81 s_new(void)
83 string *sp;
85 if (freed != NULL) {
86 sp = freed;
87 /*LINTED*/
88 freed = (string *)(freed->ptr);
89 sp->ptr = sp->base;
90 return (sp);
92 sp = s_alloc();
93 sp->base = sp->ptr = malloc(STRLEN);
94 if (sp->base == NULL) {
95 perror("allocating string");
96 exit(1);
98 sp->end = sp->base + STRLEN;
99 s_terminate(sp);
100 return (sp);
103 /* grow a string's allocation by at least `incr' bytes */
104 static void
105 s_simplegrow(string *sp, size_t incr)
107 char *cp;
108 size_t size;
111 * take a larger increment to avoid mallocing too often
113 if (((sp->end - sp->base) < incr) && (MAXINCR < incr))
114 size = (sp->end - sp->base) + incr;
115 else if ((sp->end - sp->base) > MAXINCR)
116 size = (sp->end - sp->base) + MAXINCR;
117 else
118 size = (size_t)2 * (sp->end - sp->base);
120 cp = realloc(sp->base, size);
121 if (cp == NULL) {
122 perror("string:");
123 exit(1);
125 sp->ptr = (sp->ptr - sp->base) + cp;
126 sp->end = cp + size;
127 sp->base = cp;
130 /* grow a string's allocation */
132 s_grow(string *sp, int c)
134 s_simplegrow(sp, (size_t)2);
135 s_putc(sp, c);
136 return (c);
139 /* return a string containing a character array (this had better not grow) */
140 string *
141 s_array(char *cp, size_t len)
143 string *sp = s_alloc();
145 sp->base = sp->ptr = cp;
146 sp->end = sp->base + len;
147 return (sp);
150 /* return a string containing a copy of the passed char array */
151 string*
152 s_copy(char *cp)
154 string *sp;
155 size_t len;
157 sp = s_alloc();
158 len = strlen(cp)+1;
159 sp->base = malloc(len);
160 if (sp->base == NULL) {
161 perror("string:");
162 exit(1);
164 sp->end = sp->base + len; /* point past end of allocation */
165 (void) strcpy(sp->base, cp);
166 sp->ptr = sp->end - (size_t)1; /* point to NULL terminator */
167 return (sp);
170 /* convert string to lower case */
171 void
172 s_tolower(string *sp)
174 char *cp;
176 for (cp = sp->ptr; *cp; cp++)
177 *cp = tolower(*cp);
180 void
181 s_skipwhite(string *sp)
183 while (isspace(*sp->ptr))
184 s_skipc(sp);
187 /* append a char array to a string */
188 string *
189 s_append(string *to, char *from)
191 if (to == NULL)
192 to = s_new();
193 if (from == NULL)
194 return (to);
195 for (; *from; from++)
196 s_putc(to, (int)(unsigned int)*from);
197 s_terminate(to);
198 return (to);
202 * Append a logical input sequence into a string. Ignore blank and
203 * comment lines. Backslash preceding newline indicates continuation.
204 * The `lineortoken' variable indicates whether the sequence to beinput
205 * is a whitespace delimited token or a whole line.
207 * FILE *fp; stream to read from
208 * string *to; where to put token
209 * int lineortoken; how the sequence terminates
211 * Returns a pointer to the string or NULL. Trailing newline is stripped off.
213 string *
214 s_seq_read(FILE *fp, string *to, int lineortoken)
216 int c;
217 int done = 0;
219 if (feof(fp))
220 return (NULL);
222 /* get rid of leading goo */
223 do {
224 c = getc(fp);
225 switch (c) {
226 case EOF:
227 if (to != NULL)
228 s_terminate(to);
229 return (NULL);
230 case '#':
231 /*LINTED*/
232 while ((c = getc(fp)) != '\n' && c != EOF)
233 continue;
234 break;
235 case ' ':
236 case '\t':
237 case '\n':
238 case '\r':
239 case '\f':
240 break;
241 default:
242 done = 1;
243 break;
245 } while (!done);
247 if (to == NULL)
248 to = s_new();
250 /* gather up a sequence */
251 for (;;) {
252 switch (c) {
253 case '\\':
254 c = getc(fp);
255 if (c != '\n') {
256 s_putc(to, (int)(unsigned int)'\\');
257 s_putc(to, c);
259 break;
260 case EOF:
261 case '\r':
262 case '\f':
263 case '\n':
264 s_terminate(to);
265 return (to);
266 case ' ':
267 case '\t':
268 if (lineortoken == TOKEN) {
269 s_terminate(to);
270 return (to);
272 /* fall through */
273 default:
274 s_putc(to, c);
275 break;
277 c = getc(fp);
281 string *
282 s_tok(string *from, char *split)
284 char *splitend = strpbrk(from->ptr, split);
286 if (splitend) {
287 string *to = s_new();
288 for (; from->ptr < splitend; ) {
289 s_putc(to, (int)(unsigned int)*from->ptr);
290 from->ptr++;
292 s_terminate(to);
293 s_restart(to);
294 /* LINT: warning due to lint bug */
295 from->ptr += strspn(from->ptr, split);
296 return (to);
299 else if (from->ptr[0]) {
300 string *to = s_clone(from);
301 while (*from->ptr)
302 from->ptr++;
303 return (to);
306 else
307 return (NULL);
311 * Append an input line to a string.
313 * Returns a pointer to the string (or NULL).
314 * Trailing newline is left on.
316 char *
317 s_read_line(FILE *fp, string *to)
319 int c;
320 size_t len = 0;
322 s_terminate(to);
324 /* end of input */
325 if (feof(fp) || (c = getc(fp)) == EOF)
326 return (NULL);
328 /* gather up a line */
329 for (; ; ) {
330 len++;
331 switch (c) {
332 case EOF:
333 s_terminate(to);
334 return (to->ptr - len);
335 case '\n':
336 s_putc(to, (int)(unsigned int)'\n');
337 s_terminate(to);
338 return (to->ptr - len);
339 default:
340 s_putc(to, c);
341 break;
343 c = getc(fp);
348 * Read till eof
350 size_t
351 s_read_to_eof(FILE *fp, string *to)
353 size_t got;
354 size_t have;
356 s_terminate(to);
358 for (; ; ) {
359 if (feof(fp))
360 break;
361 /* allocate room for a full buffer */
362 have = to->end - to->ptr;
363 if (have < 4096UL)
364 s_simplegrow(to, (size_t)4096);
366 /* get a buffers worth */
367 have = to->end - to->ptr;
368 got = fread(to->ptr, (size_t)1, have, fp);
369 if (got == (size_t)0)
370 break;
371 /* LINT: warning due to lint bug */
372 to->ptr += got;
375 /* null terminate the line */
376 s_terminate(to);
377 return (to->ptr - to->base);
381 * Get the next field from a string. The field is delimited by white space,
382 * single or double quotes.
384 * string *from; string to parse
385 * string *to; where to put parsed token
387 string *
388 s_parse(string *from, string *to)
390 while (isspace(*from->ptr))
391 from->ptr++;
392 if (*from->ptr == '\0')
393 return (NULL);
394 if (to == NULL)
395 to = s_new();
396 if (*from->ptr == '\'') {
397 from->ptr++;
398 for (; *from->ptr != '\'' && *from->ptr != '\0'; from->ptr++)
399 s_putc(to, (int)(unsigned int)*from->ptr);
400 if (*from->ptr == '\'')
401 from->ptr++;
402 } else if (*from->ptr == '"') {
403 from->ptr++;
404 for (; *from->ptr != '"' && *from->ptr != '\0'; from->ptr++)
405 s_putc(to, (int)(unsigned int)*from->ptr);
406 if (*from->ptr == '"')
407 from->ptr++;
408 } else {
409 for (; !isspace(*from->ptr) && *from->ptr != '\0'; from->ptr++)
410 s_putc(to, (int)(unsigned int)*from->ptr);
412 s_terminate(to);
414 return (to);