Initial revision
[alioth/jupp.git] / utils.c
1 /* $MirOS: contrib/code/jupp/utils.c,v 1.3 2008/05/13 13:08:31 tg Exp $ */
2 /*
3  *      Various utilities
4  *      Copyright
5  *              (C) 1992 Joseph H. Allen
6  *              (C) 2001 Marek 'Marx' Grac
7  *
8  *      This file is part of JOE (Joe's Own Editor)
9  */
10 #include "config.h"
11
12 #include <errno.h>
13 #ifdef HAVE_UNISTD_H
14 #include <unistd.h>
15 #endif
16 #ifdef HAVE_STDLIB_H
17 #include <stdlib.h>
18 #endif
19
20 #include "i18n.h"
21 #include "utf8.h"
22 #include "charmap.h"
23 #include "blocks.h"
24 #include "utils.h"
25
26
27 #if 0
28 int joe_ispunct(int wide,struct charmap *map,int c)
29 {
30         if (joe_isspace(c))
31                 return 0;
32
33         if (c=='_')
34                 return 1;
35
36         if (isalnum_(wide,map,c))
37                 return 0;
38
39         return joe_isprint(wide,map,c);
40 }
41 #endif
42
43 /*
44  * return minimum/maximum of two numbers
45  */
46 unsigned int uns_min(unsigned int a, unsigned int b)
47 {
48         return a < b ? a : b;
49 }
50
51 signed int int_min(signed int a, signed int b)
52 {
53         return a < b ? a : b;
54 }
55
56 signed long int long_max(signed long int a, signed long int b)
57 {
58         return a > b ? a : b;
59 }
60
61 signed long int long_min(signed long int a, signed long int b)
62 {
63         return a < b ? a : b;
64 }
65
66 #if 0
67 /* 
68  * Characters which are considered as word characters 
69  *      _ is considered as word character because is often used 
70  *      in the names of C/C++ functions
71  */
72 int isalnum_(int wide,struct charmap *map,int c)
73 {
74         /* Fast... */
75         if (c>='0' && c<='9' ||
76             c>='a' && c<='z' ||
77             c>='A' && c<='Z' ||
78             c=='_')
79           return 1;
80         else if(c<128)
81           return 0;
82
83         /* Slow... */
84         if (wide)
85                 return joe_iswalpha(c);
86         else
87                 return joe_iswalpha(to_uni(map,c));
88 }
89
90 int isalpha_(int wide,struct charmap *map,int c)
91 {
92         /* Fast... */
93         if (c>='a' && c<='z' ||
94             c>='A' && c<='Z' ||
95             c=='_')
96           return 1;
97         else if(c<128)
98           return 0;
99
100         /* Slow... */
101         if (wide)
102                 return joe_iswalpha(c);
103         else
104                 return joe_iswalpha(to_uni(map,c));
105 }
106 #endif
107
108 /* Versions of 'read' and 'write' which automatically retry when interrupted */
109 ssize_t joe_read(int fd, void *buf, size_t size)
110 {
111         ssize_t rt;
112
113         do {
114                 rt = read(fd, buf, size);
115         } while (rt < 0 && errno == EINTR);
116         return rt;
117 }
118
119 ssize_t joe_write(int fd, void *buf, size_t size)
120 {
121         ssize_t rt;
122
123         do {
124                 rt = write(fd, buf, size);
125         } while (rt < 0 && errno == EINTR);
126         return rt;
127 }
128
129 /* wrappers to *alloc routines */
130 void *joe_malloc(size_t size)
131 {
132         return malloc(size);
133 }
134
135 void *joe_calloc(size_t nmemb, size_t size)
136 {
137         return calloc(nmemb, size);
138 }
139
140 void *joe_realloc(void *ptr, size_t size)
141 {
142         return realloc(ptr, size);
143 }
144
145 void joe_free(void *ptr)
146 {
147         free(ptr);
148 }
149
150
151 #ifndef SIG_ERR
152 #define SIG_ERR ((sighandler_t) -1)
153 #endif
154
155 /* wrapper to hide signal interface differrencies */
156 int joe_set_signal(int signum, sighandler_t handler)
157 {
158         int retval;
159 #ifdef HAVE_SIGACTION
160         struct sigaction sact;
161
162         mset(&sact, 0, sizeof(sact));
163         sact.sa_handler = handler;
164 #ifdef SA_INTERRUPT
165         sact.sa_flags = SA_INTERRUPT;
166 #endif
167         retval = sigaction(signum, &sact, NULL);
168 #elif defined(HAVE_SIGVEC)
169         struct sigvec svec;
170
171         mset(&svec, 0, sizeof(svec));
172         svec.sv_handler = handler;
173 #ifdef HAVE_SV_INTERRUPT
174         svec.sv_flags = SV_INTERRUPT;
175 #endif
176         retval = sigvec(signum, &svec, NULL);
177 #else
178         retval = (signal(signum, handler) != SIG_ERR) ? 0 : -1;
179 #ifdef HAVE_SIGINTERRUPT
180         siginterrupt(signum, 1);
181 #endif
182 #endif
183         return(retval);
184 }
185
186 /* Helpful little parsing utilities */
187
188 /* Skip whitespace and return first non-whitespace character */
189
190 int parse_ws(unsigned char **pp,int cmt)
191 {
192         unsigned char *p = *pp;
193         while (*p==' ' || *p=='\t')
194                 ++p;
195         if (*p=='\r' || *p=='\n' || *p==cmt)
196                 *p = 0;
197         *pp = p;
198         return *p;
199 }
200
201 /* Parse an identifier into a buffer.  Identifier is truncated to a maximum of len chars. */
202
203 int parse_ident(unsigned char **pp, unsigned char *buf, int len)
204 {
205         unsigned char *p = *pp;
206         if (joe_isalpha_(locale_map,*p)) {
207                 while(len && joe_isalnum_(locale_map,*p))
208                         *buf++= *p++, --len;
209                 *buf=0;
210                 while(joe_isalnum_(locale_map,*p))
211                         ++p;
212                 *pp = p;
213                 return 0;
214         } else
215                 return -1;
216 }
217
218 /* Parse to next whitespace */
219
220 int parse_tows(unsigned char **pp, unsigned char *buf)
221 {
222         unsigned char *p = *pp;
223         while (*p && *p!=' ' && *p!='\t' && *p!='\n' && *p!='\r' && *p!='#')
224                 *buf++ = *p++;
225
226         *pp = p;
227         *buf = 0;
228         return 0;
229 }
230
231 /* Parse a keyword */
232
233 int parse_kw(unsigned char **pp, unsigned char *kw)
234 {
235         unsigned char *p = *pp;
236         while(*kw && *kw==*p)
237                 ++kw, ++p;
238         if(!*kw && !joe_isalnum_(locale_map,*p)) {
239                 *pp = p;
240                 return 0;
241         } else
242                 return -1;
243 }
244
245 /* Parse a field */
246
247 int parse_field(unsigned char **pp, unsigned char *kw)
248 {
249         unsigned char *p = *pp;
250         while(*kw && *kw==*p)
251                 ++kw, ++p;
252         if(!*kw && (!*p || *p==' ' || *p=='\t' || *p=='#' || *p=='\n' || *p=='\r')) {
253                 *pp = p;
254                 return 0;
255         } else
256                 return -1;
257 }
258
259 /* Parse a character */
260
261 int parse_char(unsigned char **pp, unsigned char c)
262 {
263         unsigned char *p = *pp;
264         if (*p == c) {
265                 *pp = p+1;
266                 return 0;
267         } else
268                 return -1;
269 }
270
271 /* Parse an integer.  Returns 0 for success. */
272
273 int parse_int(unsigned char **pp, int *buf)
274 {
275         unsigned char *p = *pp;
276         if ((*p>='0' && *p<='9') || *p=='-') {
277                 *buf = atoi((char *)p);
278                 if(*p=='-')
279                         ++p;
280                 while(*p>='0' && *p<='9')
281                         ++p;
282                 *pp = p;
283                 return 0;
284         } else
285                 return -1;
286 }
287
288 /* Parse a string into a buffer.  Returns 0 for success.
289    Leaves escape sequences in string. */
290
291 int parse_string(unsigned char **pp, unsigned char *buf, int len)
292 {
293         unsigned char *p= *pp;
294         if(*p=='\"') {
295                 ++p;
296                 while(len && *p && *p!='\"')
297                         if(*p=='\\' && p[1] && len>2) {
298                                 *buf++ = *p++;
299                                 *buf++ = *p++;
300                                 len-=2;
301                         } else {
302                                 *buf++ = *p++;
303                                 --len;
304                         }
305                 *buf = 0;
306                 while(*p && *p!='\"')
307                         if(*p=='\\' && p[1])
308                                 p+=2;
309                         else
310                                 p++;
311                 if(*p=='\"') {
312                         *pp= p+1;
313                         return 0;
314                 }
315         }
316         return -1;
317 }
318
319 /* Parse a character range: a-z */
320
321 int parse_range(unsigned char **pp, int *first, int *second)
322 {
323         unsigned char *p= *pp;
324         int a, b;
325         if(!*p)
326                 return -1;
327         if(*p=='\\' && p[1]) {
328                 ++p;
329                 if(*p=='n')
330                         a = '\n';
331                 else if(*p=='t')
332                         a = '\t';
333                 else
334                         a = *p;
335                 ++p;
336         } else
337                 a = *p++;
338         if(*p=='-' && p[1]) {
339                 ++p;
340                 if(*p=='\\' && p[1]) {
341                         ++p;
342                         if(*p=='n')
343                                 b = '\n';
344                         else if(*p=='t')
345                                 b = '\t';
346                         else
347                                 b = *p;
348                         ++p;
349                 } else
350                         b = *p++;
351         } else
352                 b = a;
353         *first = a;
354         *second = b;
355         *pp = p;
356         return 0;
357 }