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