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