1 /*
2  *	Various utilities
3  *	Copyright
4  *		(C) 1992 Joseph H. Allen
5  *		(C) 2001 Marek 'Marx' Grac
6  *
7  *	This file is part of JOE (Joe's Own Editor)
8  */
9 #include "config.h"
10 
11 __RCSID("$MirOS: contrib/code/jupp/utils.c,v 1.11 2018/11/11 18:15:39 tg Exp $");
12 
13 #include <errno.h>
14 #include <stdlib.h>
15 #include <unistd.h>
16 
17 #include "charmap.h"
18 #include "blocks.h"
19 #include "utils.h"
20 
21 /*
22  * return minimum/maximum of two numbers
23  */
uns_min(unsigned int a,unsigned int b)24 unsigned int uns_min(unsigned int a, unsigned int b)
25 {
26 	return a < b ? a : b;
27 }
28 
int_min(signed int a,signed int b)29 signed int int_min(signed int a, signed int b)
30 {
31 	return a < b ? a : b;
32 }
33 
long_max(signed long int a,signed long int b)34 signed long int long_max(signed long int a, signed long int b)
35 {
36 	return a > b ? a : b;
37 }
38 
long_min(signed long int a,signed long int b)39 signed long int long_min(signed long int a, signed long int b)
40 {
41 	return a < b ? a : b;
42 }
43 
44 /* Versions of 'read' and 'write' which automatically retry when interrupted */
45 ssize_t
joe_read(int fd,void * buf,size_t size)46 joe_read(int fd, void *buf, size_t size)
47 {
48 	ssize_t rt;
49 
50 	do {
51 		rt = read(fd, buf, size);
52 	} while (rt < 0 && errno == EINTR);
53 	return rt;
54 }
55 
56 ssize_t
joe_write(int fd,const void * buf,size_t size)57 joe_write(int fd, const void *buf, size_t size)
58 {
59 	ssize_t rt;
60 
61 	do {
62 		rt = write(fd, buf, size);
63 	} while (rt < 0 && errno == EINTR);
64 	return rt;
65 }
66 
67 /* Similarily, read and write an exact amount (up to EOF) */
68 ssize_t
joe_readex(int fd,void * buf_,size_t size)69 joe_readex(int fd, void *buf_, size_t size)
70 {
71 	unsigned char *buf = buf_;
72 	ssize_t rv = 0, z;
73 
74 	while (size) {
75 		if ((z = read(fd, buf, size)) < 0) {
76 			if (errno == EINTR)
77 				continue;
78 			return (rv ? /* fucked up since we got some */ -2 : -1);
79 		}
80 		if (z == 0)
81 			break;
82 		rv += z;
83 		buf += z;
84 		size -= z;
85 	}
86 	return (rv);
87 }
88 
89 #if 0 /* unused */
90 ssize_t
91 joe_writex(int fd, const void *buf_, size_t size)
92 {
93 	const unsigned char *buf = buf_;
94 	ssize_t rv = 0, z;
95 
96 	while (size) {
97 		if ((z = write(fd, buf, size)) < 0) {
98 			if (errno == EINTR)
99 				continue;
100 			return (rv ? /* fucked up since we got some */ -2 : -1);
101 		}
102 		rv += z;
103 		buf += z;
104 		size -= z;
105 	}
106 	return (rv);
107 }
108 #endif
109 
110 #ifndef SIG_ERR
111 #define SIG_ERR ((sighandler_t) -1)
112 #endif
113 
114 /* wrapper to hide signal interface differrencies */
joe_set_signal(int signum,sighandler_t handler)115 int joe_set_signal(int signum, sighandler_t handler)
116 {
117 	int retval;
118 #ifdef HAVE_SIGACTION
119 	struct sigaction sact;
120 
121 	mset(&sact, 0, sizeof(sact));
122 	sact.sa_handler = handler;
123 #ifdef SA_INTERRUPT
124 	sact.sa_flags = SA_INTERRUPT;
125 #endif
126 	retval = sigaction(signum, &sact, NULL);
127 #elif defined(HAVE_SIGVEC)
128 	struct sigvec svec;
129 
130 	mset(&svec, 0, sizeof(svec));
131 	svec.sv_handler = handler;
132 #ifdef HAVE_SV_INTERRUPT
133 	svec.sv_flags = SV_INTERRUPT;
134 #endif
135 	retval = sigvec(signum, &svec, NULL);
136 #else
137 	retval = (signal(signum, handler) != SIG_ERR) ? 0 : -1;
138 #ifdef HAVE_SIGINTERRUPT
139 	siginterrupt(signum, 1);
140 #endif
141 #endif
142 	return(retval);
143 }
144 
145 /* Helpful little parsing utilities */
146 
147 /* Skip whitespace and return first non-whitespace character */
148 
149 int
parse_ws(unsigned char ** pp,int cmt)150 parse_ws(unsigned char **pp, int cmt)
151 {
152 	unsigned char *p = *pp;
153 	while (*p==' ' || *p=='\t')
154 		++p;
155 	if (*p=='\r' || *p=='\n' || *p==cmt)
156 		*p = 0;
157 	*pp = p;
158 	return *p;
159 }
160 
161 /* Parse an identifier into a buffer.  Identifier is truncated to a maximum of len chars. */
162 
163 int
parse_ident(unsigned char ** pp,unsigned char * buf,int len)164 parse_ident(unsigned char **pp, unsigned char *buf, int len)
165 {
166 	unsigned char *p = *pp;
167 	if (joe_isalphx(locale_map,*p)) {
168 		while(len && joe_isalnux(locale_map,*p))
169 			*buf++= *p++, --len;
170 		*buf=0;
171 		while(joe_isalnux(locale_map,*p))
172 			++p;
173 		*pp = p;
174 		return 0;
175 	} else
176 		return -1;
177 }
178 
179 /* Parse to next whitespace */
180 
181 int
parse_tows(unsigned char ** pp,unsigned char * buf)182 parse_tows(unsigned char **pp, unsigned char *buf)
183 {
184 	unsigned char *p = *pp;
185 	while (*p && *p!=' ' && *p!='\t' && *p!='\n' && *p!='\r' && *p!='#')
186 		*buf++ = *p++;
187 
188 	*pp = p;
189 	*buf = 0;
190 	return 0;
191 }
192 
193 /* Parse a keyword */
194 
195 int
parse_kw(unsigned char ** pp,const unsigned char * kw)196 parse_kw(unsigned char **pp, const unsigned char *kw)
197 {
198 	unsigned char *p = *pp;
199 	while(*kw && *kw==*p)
200 		++kw, ++p;
201 	if(!*kw && !joe_isalnux(locale_map,*p)) {
202 		*pp = p;
203 		return 0;
204 	} else
205 		return -1;
206 }
207 
208 /* Parse a field */
209 
210 int
parse_field(unsigned char ** pp,const unsigned char * kw)211 parse_field(unsigned char **pp, const unsigned char *kw)
212 {
213 	unsigned char *p = *pp;
214 	while(*kw && *kw==*p)
215 		++kw, ++p;
216 	if(!*kw && (!*p || *p==' ' || *p=='\t' || *p=='#' || *p=='\n' || *p=='\r')) {
217 		*pp = p;
218 		return 0;
219 	} else
220 		return -1;
221 }
222 
223 /* Parse a character */
224 
225 int
parse_char(unsigned char ** pp,unsigned char c)226 parse_char(unsigned char **pp, unsigned char c)
227 {
228 	unsigned char *p = *pp;
229 	if (*p == c) {
230 		*pp = p+1;
231 		return 0;
232 	} else
233 		return -1;
234 }
235 
236 /*
237  * Parse a string into a buffer.  Returns 0 for success.
238  * Leaves escape sequences in string.
239  */
240 int
parse_string(unsigned char ** pp,unsigned char * buf,int len)241 parse_string(unsigned char **pp, unsigned char *buf, int len)
242 {
243 	unsigned char *p = *pp;
244 	if(*p=='\"') {
245 		++p;
246 		while(len && *p && *p!='\"')
247 			if(*p=='\\' && p[1] && len>2) {
248 				*buf++ = *p++;
249 				*buf++ = *p++;
250 				len-=2;
251 			} else {
252 				*buf++ = *p++;
253 				--len;
254 			}
255 		*buf = 0;
256 		while(*p && *p!='\"')
257 			if(*p=='\\' && p[1])
258 				p+=2;
259 			else
260 				p++;
261 		if(*p=='\"') {
262 			*pp= p+1;
263 			return 0;
264 		}
265 	}
266 	return -1;
267 }
268 
269 /* Parse a character range: a-z */
270 int
parse_range(unsigned char ** pp,int * first,int * second)271 parse_range(unsigned char **pp, int *first, int *second)
272 {
273 	unsigned char *p = *pp;
274 	int a, b;
275 	if(!*p)
276 		return -1;
277 	if(*p=='\\' && p[1]) {
278 		++p;
279 		if(*p=='n')
280 			a = '\n';
281 		else if(*p=='t')
282 			a = '\t';
283 		else
284 			a = *p;
285 		++p;
286 	} else
287 		a = *p++;
288 	if(*p=='-' && p[1]) {
289 		++p;
290 		if(*p=='\\' && p[1]) {
291 			++p;
292 			if(*p=='n')
293 				b = '\n';
294 			else if(*p=='t')
295 				b = '\t';
296 			else
297 				b = *p;
298 			++p;
299 		} else
300 			b = *p++;
301 	} else
302 		b = a;
303 	*first = a;
304 	*second = b;
305 	*pp = p;
306 	return 0;
307 }
308