clsync
Loading...
Searching...
No Matches
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
27static 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}
#define critical(...)
Definition error.h:32
#define error(...)
Definition error.h:36
#define debug(debug_level,...)
Definition error.h:50
int str_splitargs(char *_instr, int(*handler)(char *, size_t, void *), void *arg)
Definition stringex.c:75
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