clsync
stringex.c
Go to the documentation of this file.
1 /*
2  clsync - file tree sync utility based on inotify/kqueue/bsm
3 
4  Copyright (C) 2014 Dmitry Yu Okunev <dyokunev@ut.mephi.ru> 0x8E30679C
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 #include <stdlib.h> // free()
21 #include <string.h> // strtok_r()
22 #include <errno.h> // errno
23 
24 #include "malloc.h"
25 #include "error.h"
26 
27 static int _str_splitargs (
28  char *ptr,
29  char **arg_start_p,
30  int quotes,
31  int ( *handler ) ( char *, size_t, void * ),
32  char *additional_arg
33 )
34 {
35  char *arg_start, *arg;
36  size_t arg_len;
37  int rc;
38  arg_start = *arg_start_p;
39  *arg_start_p = &ptr[1];
40  arg_len = ptr - arg_start;
41 
42  if ( arg_len == 0 ) // Skipping nearby spaces
43  return 0;
44 
45  arg = xmalloc ( arg_len + 1 );
46 
47  if ( quotes ) {
48  size_t s, d;
49  s = d = 0;
50 
51  while ( s < arg_len ) {
52  if ( arg_start[s] )
53  arg[d++] = arg_start[s];
54 
55  s++;
56  }
57 
58  arg_len = d;
59  } else
60  memcpy ( arg, arg_start, arg_len );
61 
62 #ifdef _DEBUG
63  debug ( 15, "%p %p %i: <%s>", arg_start, ptr, arg_len, arg );
64 #endif
65  arg[arg_len] = 0;
66 
67  if ( ( rc = handler ( arg, arg_len, additional_arg ) ) ) {
68  free ( arg );
69  return rc;
70  }
71 
72  return 0;
73 }
74 
76  char *_instr,
77  int ( *handler ) ( char *, size_t, void * ),
78  void *arg
79 )
80 {
81  debug ( 9, "" );
82  char *arg_start, *ptr, *instr;
83  int quotes = 0;
84  instr = strdup ( _instr );
85  ptr = instr;
86  arg_start = instr;
87 
88  while ( 1 ) {
89  ptr = strpbrk ( ptr, " \t\"\'" );
90 #ifdef _DEBUG
91  debug ( 10, "ptr == %p", ptr );
92 #endif
93 
94  if ( ptr == NULL )
95  break;
96 
97 #ifdef _DEBUG
98  debug ( 10, "*ptr == \"%c\" (%i)", *ptr, *ptr );
99 #endif
100 
101  switch ( * ( ptr++ ) ) {
102  case ' ':
103  case '\t': {
104  int rc;
105 
106  if ( ( rc = _str_splitargs ( &ptr[-1], &arg_start, quotes, handler, arg ) ) )
107  return rc;
108 
109  quotes = 0;
110  break;
111  }
112 
113  case '"':
114  ptr[-1] = 0;
115  quotes++;
116 
117  while ( ( ptr = strchr ( ptr, '"' ) ) != NULL ) {
118  // Checking for escaping
119  char *p;
120  p = &ptr[-1];
121 
122  while ( *p == '\\' ) {
123  p--;
124 #ifdef PARANOID
125 
126  if ( p < instr )
127  critical ( "Dangerous internal error" );
128 
129 #endif
130  }
131 
132  if ( ( ptr - p ) % 2 )
133  break;
134  }
135 
136  if ( ptr == NULL ) {
137  errno = EINVAL;
138  error ( "Unterminated quote <\"> in string: <%s>", instr );
139  return errno;
140  }
141 
142  *ptr = 0;
143  quotes++;
144  ptr++;
145  break;
146 
147  case '\'':
148  ptr[-1] = 0;
149  quotes++;
150  ptr = strchr ( ptr, '\'' );
151 
152  if ( ptr == NULL ) {
153  errno = EINVAL;
154  error ( "Unterminated quote <'> in string: <%s>", instr );
155  return errno;
156  }
157 
158  *ptr = 0;
159  quotes++;
160  ptr++;
161  break;
162  }
163  }
164 
165  int rc = _str_splitargs ( strchr ( arg_start, 0 ), &arg_start, quotes, handler, arg );
166  free ( instr );
167  return rc;
168 }
socket_sockthreaddata::arg
void * arg
Definition: socket.h:214
str_splitargs
int str_splitargs(char *_instr, int(*handler)(char *, size_t, void *), void *arg)
Definition: stringex.c:75
error
#define error(...)
Definition: error.h:36
error.h
malloc.h
debug
#define debug(debug_level,...)
Definition: error.h:50
critical
#define critical(...)
Definition: error.h:32
_str_splitargs
static int _str_splitargs(char *ptr, char **arg_start_p, int quotes, int(*handler)(char *, size_t, void *), char *additional_arg)
Definition: stringex.c:27