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]
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 #include <sys/types.h>
36 /* global to this file */
38 #define STRALLOC 128UL
39 #define MAXINCR 250000UL
41 /* buffer pool for allocating string structures */
46 static stralloc
*freep
= NULL
;
48 /* pool of freed strings */
49 static string
*freed
= NULL
;
50 static string
*s_alloc(void);
51 static void s_simplegrow(string
*, size_t);
57 sp
->ptr
= (char *)freed
;
62 /* allocate a string head */
66 if (freep
== NULL
|| freep
->o
>= STRALLOC
) {
67 freep
= (stralloc
*)malloc(sizeof (stralloc
));
69 perror("allocating string");
74 return (&(freep
->s
[freep
->o
++]));
77 /* create a new `short' string */
86 freed
= (string
*)(freed
->ptr
);
91 sp
->base
= sp
->ptr
= malloc(STRLEN
);
92 if (sp
->base
== NULL
) {
93 perror("allocating string");
96 sp
->end
= sp
->base
+ STRLEN
;
101 /* grow a string's allocation by at least `incr' bytes */
103 s_simplegrow(string
*sp
, size_t incr
)
109 * take a larger increment to avoid mallocing too often
111 if (((sp
->end
- sp
->base
) < incr
) && (MAXINCR
< incr
))
112 size
= (sp
->end
- sp
->base
) + incr
;
113 else if ((sp
->end
- sp
->base
) > MAXINCR
)
114 size
= (sp
->end
- sp
->base
) + MAXINCR
;
116 size
= (size_t)2 * (sp
->end
- sp
->base
);
118 cp
= realloc(sp
->base
, size
);
123 sp
->ptr
= (sp
->ptr
- sp
->base
) + cp
;
128 /* grow a string's allocation */
130 s_grow(string
*sp
, int c
)
132 s_simplegrow(sp
, (size_t)2);
137 /* return a string containing a character array (this had better not grow) */
139 s_array(char *cp
, size_t len
)
141 string
*sp
= s_alloc();
143 sp
->base
= sp
->ptr
= cp
;
144 sp
->end
= sp
->base
+ len
;
148 /* return a string containing a copy of the passed char array */
157 sp
->base
= malloc(len
);
158 if (sp
->base
== NULL
) {
162 sp
->end
= sp
->base
+ len
; /* point past end of allocation */
163 (void) strcpy(sp
->base
, cp
);
164 sp
->ptr
= sp
->end
- (size_t)1; /* point to NULL terminator */
168 /* convert string to lower case */
170 s_tolower(string
*sp
)
174 for (cp
= sp
->ptr
; *cp
; cp
++)
179 s_skipwhite(string
*sp
)
181 while (isspace(*sp
->ptr
))
185 /* append a char array to a string */
187 s_append(string
*to
, char *from
)
193 for (; *from
; from
++)
194 s_putc(to
, (int)(unsigned int)*from
);
200 * Append a logical input sequence into a string. Ignore blank and
201 * comment lines. Backslash preceding newline indicates continuation.
202 * The `lineortoken' variable indicates whether the sequence to beinput
203 * is a whitespace delimited token or a whole line.
205 * FILE *fp; stream to read from
206 * string *to; where to put token
207 * int lineortoken; how the sequence terminates
209 * Returns a pointer to the string or NULL. Trailing newline is stripped off.
212 s_seq_read(FILE *fp
, string
*to
, int lineortoken
)
220 /* get rid of leading goo */
230 while ((c
= getc(fp
)) != '\n' && c
!= EOF
)
248 /* gather up a sequence */
254 s_putc(to
, (int)(unsigned int)'\\');
266 if (lineortoken
== TOKEN
) {
280 s_tok(string
*from
, char *split
)
282 char *splitend
= strpbrk(from
->ptr
, split
);
285 string
*to
= s_new();
286 for (; from
->ptr
< splitend
; ) {
287 s_putc(to
, (int)(unsigned int)*from
->ptr
);
292 /* LINT: warning due to lint bug */
293 from
->ptr
+= strspn(from
->ptr
, split
);
297 else if (from
->ptr
[0]) {
298 string
*to
= s_clone(from
);
309 * Append an input line to a string.
311 * Returns a pointer to the string (or NULL).
312 * Trailing newline is left on.
315 s_read_line(FILE *fp
, string
*to
)
323 if (feof(fp
) || (c
= getc(fp
)) == EOF
)
326 /* gather up a line */
332 return (to
->ptr
- len
);
334 s_putc(to
, (int)(unsigned int)'\n');
336 return (to
->ptr
- len
);
349 s_read_to_eof(FILE *fp
, string
*to
)
359 /* allocate room for a full buffer */
360 have
= to
->end
- to
->ptr
;
362 s_simplegrow(to
, (size_t)4096);
364 /* get a buffers worth */
365 have
= to
->end
- to
->ptr
;
366 got
= fread(to
->ptr
, (size_t)1, have
, fp
);
367 if (got
== (size_t)0)
369 /* LINT: warning due to lint bug */
373 /* null terminate the line */
375 return (to
->ptr
- to
->base
);
379 * Get the next field from a string. The field is delimited by white space,
380 * single or double quotes.
382 * string *from; string to parse
383 * string *to; where to put parsed token
386 s_parse(string
*from
, string
*to
)
388 while (isspace(*from
->ptr
))
390 if (*from
->ptr
== '\0')
394 if (*from
->ptr
== '\'') {
396 for (; *from
->ptr
!= '\'' && *from
->ptr
!= '\0'; from
->ptr
++)
397 s_putc(to
, (int)(unsigned int)*from
->ptr
);
398 if (*from
->ptr
== '\'')
400 } else if (*from
->ptr
== '"') {
402 for (; *from
->ptr
!= '"' && *from
->ptr
!= '\0'; from
->ptr
++)
403 s_putc(to
, (int)(unsigned int)*from
->ptr
);
404 if (*from
->ptr
== '"')
407 for (; !isspace(*from
->ptr
) && *from
->ptr
!= '\0'; from
->ptr
++)
408 s_putc(to
, (int)(unsigned int)*from
->ptr
);