another update from CVS HEAD, for QA
[alioth/jupp.git] / utils.c
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.9 2017/12/06 21:17:04 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  */
24 unsigned int uns_min(unsigned int a, unsigned int b)
25 {
26         return a < b ? a : b;
27 }
28
29 signed int int_min(signed int a, signed int b)
30 {
31         return a < b ? a : b;
32 }
33
34 signed long int long_max(signed long int a, signed long int b)
35 {
36         return a > b ? a : b;
37 }
38
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 {
47         ssize_t rt;
48
49         do {
50                 rt = read(fd, buf, size);
51         } while (rt < 0 && errno == EINTR);
52         return rt;
53 }
54
55 ssize_t joe_write(int fd, void *buf, size_t size)
56 {
57         ssize_t rt;
58
59         do {
60                 rt = write(fd, buf, size);
61         } while (rt < 0 && errno == EINTR);
62         return rt;
63 }
64
65 #ifndef SIG_ERR
66 #define SIG_ERR ((sighandler_t) -1)
67 #endif
68
69 /* wrapper to hide signal interface differrencies */
70 int joe_set_signal(int signum, sighandler_t handler)
71 {
72         int retval;
73 #ifdef HAVE_SIGACTION
74         struct sigaction sact;
75
76         mset(&sact, 0, sizeof(sact));
77         sact.sa_handler = handler;
78 #ifdef SA_INTERRUPT
79         sact.sa_flags = SA_INTERRUPT;
80 #endif
81         retval = sigaction(signum, &sact, NULL);
82 #elif defined(HAVE_SIGVEC)
83         struct sigvec svec;
84
85         mset(&svec, 0, sizeof(svec));
86         svec.sv_handler = handler;
87 #ifdef HAVE_SV_INTERRUPT
88         svec.sv_flags = SV_INTERRUPT;
89 #endif
90         retval = sigvec(signum, &svec, NULL);
91 #else
92         retval = (signal(signum, handler) != SIG_ERR) ? 0 : -1;
93 #ifdef HAVE_SIGINTERRUPT
94         siginterrupt(signum, 1);
95 #endif
96 #endif
97         return(retval);
98 }
99
100 /* Helpful little parsing utilities */
101
102 /* Skip whitespace and return first non-whitespace character */
103
104 int parse_ws(unsigned char **pp,int cmt)
105 {
106         unsigned char *p = *pp;
107         while (*p==' ' || *p=='\t')
108                 ++p;
109         if (*p=='\r' || *p=='\n' || *p==cmt)
110                 *p = 0;
111         *pp = p;
112         return *p;
113 }
114
115 /* Parse an identifier into a buffer.  Identifier is truncated to a maximum of len chars. */
116
117 int parse_ident(unsigned char **pp, unsigned char *buf, int len)
118 {
119         unsigned char *p = *pp;
120         if (joe_isalphx(locale_map,*p)) {
121                 while(len && joe_isalnux(locale_map,*p))
122                         *buf++= *p++, --len;
123                 *buf=0;
124                 while(joe_isalnux(locale_map,*p))
125                         ++p;
126                 *pp = p;
127                 return 0;
128         } else
129                 return -1;
130 }
131
132 /* Parse to next whitespace */
133
134 int parse_tows(unsigned char **pp, unsigned char *buf)
135 {
136         unsigned char *p = *pp;
137         while (*p && *p!=' ' && *p!='\t' && *p!='\n' && *p!='\r' && *p!='#')
138                 *buf++ = *p++;
139
140         *pp = p;
141         *buf = 0;
142         return 0;
143 }
144
145 /* Parse a keyword */
146
147 int parse_kw(unsigned char **pp, unsigned char *kw)
148 {
149         unsigned char *p = *pp;
150         while(*kw && *kw==*p)
151                 ++kw, ++p;
152         if(!*kw && !joe_isalnux(locale_map,*p)) {
153                 *pp = p;
154                 return 0;
155         } else
156                 return -1;
157 }
158
159 /* Parse a field */
160
161 int parse_field(unsigned char **pp, unsigned char *kw)
162 {
163         unsigned char *p = *pp;
164         while(*kw && *kw==*p)
165                 ++kw, ++p;
166         if(!*kw && (!*p || *p==' ' || *p=='\t' || *p=='#' || *p=='\n' || *p=='\r')) {
167                 *pp = p;
168                 return 0;
169         } else
170                 return -1;
171 }
172
173 /* Parse a character */
174
175 int parse_char(unsigned char **pp, unsigned char c)
176 {
177         unsigned char *p = *pp;
178         if (*p == c) {
179                 *pp = p+1;
180                 return 0;
181         } else
182                 return -1;
183 }
184
185 /* Parse a string into a buffer.  Returns 0 for success.
186    Leaves escape sequences in string. */
187
188 int parse_string(unsigned char **pp, unsigned char *buf, int len)
189 {
190         unsigned char *p= *pp;
191         if(*p=='\"') {
192                 ++p;
193                 while(len && *p && *p!='\"')
194                         if(*p=='\\' && p[1] && len>2) {
195                                 *buf++ = *p++;
196                                 *buf++ = *p++;
197                                 len-=2;
198                         } else {
199                                 *buf++ = *p++;
200                                 --len;
201                         }
202                 *buf = 0;
203                 while(*p && *p!='\"')
204                         if(*p=='\\' && p[1])
205                                 p+=2;
206                         else
207                                 p++;
208                 if(*p=='\"') {
209                         *pp= p+1;
210                         return 0;
211                 }
212         }
213         return -1;
214 }
215
216 /* Parse a character range: a-z */
217
218 int parse_range(unsigned char **pp, int *first, int *second)
219 {
220         unsigned char *p= *pp;
221         int a, b;
222         if(!*p)
223                 return -1;
224         if(*p=='\\' && p[1]) {
225                 ++p;
226                 if(*p=='n')
227                         a = '\n';
228                 else if(*p=='t')
229                         a = '\t';
230                 else
231                         a = *p;
232                 ++p;
233         } else
234                 a = *p++;
235         if(*p=='-' && p[1]) {
236                 ++p;
237                 if(*p=='\\' && p[1]) {
238                         ++p;
239                         if(*p=='n')
240                                 b = '\n';
241                         else if(*p=='t')
242                                 b = '\t';
243                         else
244                                 b = *p;
245                         ++p;
246                 } else
247                         b = *p++;
248         } else
249                 b = a;
250         *first = a;
251         *second = b;
252         *pp = p;
253         return 0;
254 }