Import upstream 2.3.14
[packages/xinetd.git] / libs / src / str / strparse.c
1 /*
2  * (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
3  * All rights reserved.  The file named COPYRIGHT specifies the terms 
4  * and conditions for redistribution.
5  */
6
7 #include "config.h"
8 #include <string.h>
9 #include <unistd.h>
10 #include <stdlib.h>
11
12 #include "str.h"
13 #include "strparse.h"
14 #include "sio.h"
15
16 static int str_errno ;
17
18 #define HANDLE_ERROR( flags, retval, errp, errval, msg )    \
19         if ( flags & STR_RETURN_ERROR )                 \
20         {                                               \
21                *errp = errval ;                         \
22                return( retval ) ;                       \
23         }                                               \
24         else                                            \
25                terminate( msg );
26
27
28 char *new_string( const char *s )
29 {
30    if ( s )
31       return strdup( s ) ;
32    else
33       return 0;
34 }
35
36 str_h str_parse( register char *str, const char *separ, int flags, int *errnop )
37 {
38         register struct str_handle *hp ;
39         int *errp = ( errnop == NULL ) ? &str_errno : errnop ;
40
41         if ( separ == NULL ) {
42                 HANDLE_ERROR( flags, NULL, errp, STR_ENULLSEPAR,
43                         "STR str_parse: NULL separator" ) ;
44         }
45
46         hp = (struct str_handle *) malloc( sizeof( struct str_handle ) ) ;
47         if ( hp == NULL ) {
48                 HANDLE_ERROR( flags, NULL, errp, STR_ENOMEM,
49                         "STR str_parse: malloc failed" ) ;
50         }
51
52         hp->string = str ;
53         hp->pos = str ;
54         hp->separator = new_string( separ ) ;
55         if ( hp->separator == NULL ) {
56                 if ( flags & STR_RETURN_ERROR )
57                 {
58                         free( (char *) hp ) ;
59                         *errp = STR_ENOMEM ;
60                         return( NULL ) ;
61                 } else {
62                         terminate( "STR str_parse: malloc failed" ) ;
63                 }
64         }
65         
66         hp->flags = flags ;
67         hp->errnop = errp ;
68         hp->no_more = ( str == NULL ) ;
69         return( (str_h) hp ) ;
70 }
71
72
73 void str_endparse( str_h handle )
74 {
75         register struct str_handle *hp = (struct str_handle *) handle ;
76
77         if( hp->separator != NULL )
78                 free( hp->separator ) ;
79         free( (char *) handle ) ;
80 }
81
82
83 /*
84  * Change the string
85  */
86 int str_setstr( str_h handle, char *newstr )
87 {
88         register struct str_handle *hp = (struct str_handle *) handle ;
89                 
90         if ( newstr == NULL ) {
91                 HANDLE_ERROR( hp->flags, STR_ERR, hp->errnop, STR_ENULLSTRING,
92                         "STR str_setstr: NULL string" ) ;
93         }
94                                 
95         hp->string = newstr ;
96         hp->pos = newstr ;
97         hp->no_more = FALSE ;
98         return( STR_OK ) ;
99 }
100
101
102 char *str_component( str_h handle )
103 {
104         register char                   *start ;
105         register char                   *last ;
106         register unsigned int           sep_count ;
107         char                            *retval ;
108         int                             last_char ;
109         register struct str_handle      *hp     = (struct str_handle *) handle ;
110         register int                    first_call = ( hp->pos == hp->string ) ;
111
112         if ( hp->no_more )
113                 return( NULL ) ;
114
115         /*
116          * Get number of separator characters.
117          * Find beginning of component.
118          */
119         sep_count = strspn( hp->pos, hp->separator ) ;
120
121         /*
122          * If this is the first call, and there are separator characters
123          * at the beginning of the string and the STR_NULL_START flag is set
124          * we return a 0-length string.
125          */
126         if ( first_call && ( sep_count > 0 ) && ( hp->flags & STR_NULL_START ))
127         {
128                 start = hp->pos ;
129                 last = hp->pos ;
130         }
131         else
132         {
133                 start = hp->pos + sep_count ;
134
135                 if ( *start == '\0' )
136                 {
137                         last = start ;
138                         hp->no_more = TRUE ;
139                         if ( ! ( hp->flags & STR_NULL_END ) )
140                                 return( NULL ) ;
141                 }
142                 else
143                 {
144                         last = strpbrk( start, hp->separator ) ;
145                         if ( last == NULL )
146                                 last = start + strlen( start ) ;
147                 }
148         }
149
150         /*
151          * At this point, the following variables must be set:
152          *              start:  beginning of component
153          *              last:   end of component + 1
154          *
155          * If STR_MALLOC is set, allocate space for the new string.
156          *
157          * NOTE: If STR_MALLOC is not set, the processed string is trashed.
158          */
159         last_char = *last ;
160         if ( hp->flags & STR_MALLOC )
161         {
162                 int len = last - start ;
163
164                 retval = malloc( (unsigned)len + 1 ) ;
165                 if ( retval == NULL ) {
166                         HANDLE_ERROR( hp->flags, NULL, hp->errnop, STR_ENOMEM,
167                                 "STR str_component: malloc failed" ) ;
168                 }
169                 strncpy( retval, start, len )[ len ] = '\0' ;
170         }
171         else
172         {
173                 retval = start ;
174                 *last = '\0' ;
175         }
176
177         /*
178          * Check if last_char is NUL to avoid setting hp->pos past the
179          * end of the string
180          */
181         hp->pos = ( last_char == '\0' ) ? last : last+1 ;
182         return( retval ) ;
183 }
184