perl.h: Comment was mistakenly passed to the preprocessor
[perl.git] / reentr.c
1 /* -*- buffer-read-only: t -*-
2  *
3  *    reentr.c
4  *
5  *    Copyright (C) 2002, 2003, 2005, 2006, 2007 by Larry Wall and others
6  *
7  *    You may distribute under the terms of either the GNU General Public
8  *    License or the Artistic License, as specified in the README file.
9  *
10  * !!!!!!!   DO NOT EDIT THIS FILE   !!!!!!!
11  * This file is built by regen/reentr.pl from data in regen/reentr.pl.
12  * Any changes made here will be lost!
13  *
14  * "Saruman," I said, standing away from him, "only one hand at a time can
15  *  wield the One, and you know that well, so do not trouble to say we!"
16  *
17  * This file contains a collection of automatically created wrappers
18  * (created by running reentr.pl) for reentrant (thread-safe) versions of
19  * various library calls, such as getpwent_r.  The wrapping is done so
20  * that other files like pp_sys.c calling those library functions need not
21  * care about the differences between various platforms' idiosyncrasies
22  * regarding these reentrant interfaces.  
23  */
24
25 #include "EXTERN.h"
26 #define PERL_IN_REENTR_C
27 #include "perl.h"
28 #include "reentr.h"
29
30 void
31 Perl_reentrant_size(pTHX) {
32 #ifdef USE_REENTRANT_API
33 #define REENTRANTSMALLSIZE       256    /* Make something up. */
34 #define REENTRANTUSUALSIZE      4096    /* Make something up. */
35 #ifdef HAS_ASCTIME_R
36         PL_reentrant_buffer->_asctime_size = REENTRANTSMALLSIZE;
37 #endif /* HAS_ASCTIME_R */
38 #ifdef HAS_CRYPT_R
39 #endif /* HAS_CRYPT_R */
40 #ifdef HAS_CTIME_R
41         PL_reentrant_buffer->_ctime_size = REENTRANTSMALLSIZE;
42 #endif /* HAS_CTIME_R */
43 #ifdef HAS_GETGRNAM_R
44 #   if defined(HAS_SYSCONF) && defined(_SC_GETGR_R_SIZE_MAX) && !defined(__GLIBC__)
45         PL_reentrant_buffer->_grent_size = sysconf(_SC_GETGR_R_SIZE_MAX);
46         if (PL_reentrant_buffer->_grent_size == (size_t) -1)
47                 PL_reentrant_buffer->_grent_size = REENTRANTUSUALSIZE;
48 #   else
49 #       if defined(__osf__) && defined(__alpha) && defined(SIABUFSIZ)
50         PL_reentrant_buffer->_grent_size = SIABUFSIZ;
51 #       else
52 #           ifdef __sgi
53         PL_reentrant_buffer->_grent_size = BUFSIZ;
54 #           else
55         PL_reentrant_buffer->_grent_size = REENTRANTUSUALSIZE;
56 #           endif
57 #       endif
58 #   endif 
59 #endif /* HAS_GETGRNAM_R */
60 #ifdef HAS_GETHOSTBYNAME_R
61 #if   !(GETHOSTBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
62         PL_reentrant_buffer->_hostent_size = REENTRANTUSUALSIZE;
63 #endif
64 #endif /* HAS_GETHOSTBYNAME_R */
65 #ifdef HAS_GETLOGIN_R
66         PL_reentrant_buffer->_getlogin_size = REENTRANTSMALLSIZE;
67 #endif /* HAS_GETLOGIN_R */
68 #ifdef HAS_GETNETBYNAME_R
69 #if   !(GETNETBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
70         PL_reentrant_buffer->_netent_size = REENTRANTUSUALSIZE;
71 #endif
72 #endif /* HAS_GETNETBYNAME_R */
73 #ifdef HAS_GETPROTOBYNAME_R
74 #if   !(GETPROTOBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
75         PL_reentrant_buffer->_protoent_size = REENTRANTUSUALSIZE;
76 #endif
77 #endif /* HAS_GETPROTOBYNAME_R */
78 #ifdef HAS_GETPWNAM_R
79 #   if defined(HAS_SYSCONF) && defined(_SC_GETPW_R_SIZE_MAX) && !defined(__GLIBC__)
80         PL_reentrant_buffer->_pwent_size = sysconf(_SC_GETPW_R_SIZE_MAX);
81         if (PL_reentrant_buffer->_pwent_size == (size_t) -1)
82                 PL_reentrant_buffer->_pwent_size = REENTRANTUSUALSIZE;
83 #   else
84 #       if defined(__osf__) && defined(__alpha) && defined(SIABUFSIZ)
85         PL_reentrant_buffer->_pwent_size = SIABUFSIZ;
86 #       else
87 #           ifdef __sgi
88         PL_reentrant_buffer->_pwent_size = BUFSIZ;
89 #           else
90         PL_reentrant_buffer->_pwent_size = REENTRANTUSUALSIZE;
91 #           endif
92 #       endif
93 #   endif 
94 #endif /* HAS_GETPWNAM_R */
95 #ifdef HAS_GETSERVBYNAME_R
96 #if   !(GETSERVBYNAME_R_PROTO == REENTRANT_PROTO_I_CCSD)
97         PL_reentrant_buffer->_servent_size = REENTRANTUSUALSIZE;
98 #endif
99 #endif /* HAS_GETSERVBYNAME_R */
100 #ifdef HAS_GETSPNAM_R
101 #   if defined(HAS_SYSCONF) && defined(_SC_GETPW_R_SIZE_MAX) && !defined(__GLIBC__)
102         PL_reentrant_buffer->_spent_size = sysconf(_SC_GETPW_R_SIZE_MAX);
103         if (PL_reentrant_buffer->_spent_size == (size_t) -1)
104                 PL_reentrant_buffer->_spent_size = REENTRANTUSUALSIZE;
105 #   else
106 #       if defined(__osf__) && defined(__alpha) && defined(SIABUFSIZ)
107         PL_reentrant_buffer->_spent_size = SIABUFSIZ;
108 #       else
109 #           ifdef __sgi
110         PL_reentrant_buffer->_spent_size = BUFSIZ;
111 #           else
112         PL_reentrant_buffer->_spent_size = REENTRANTUSUALSIZE;
113 #           endif
114 #       endif
115 #   endif 
116 #endif /* HAS_GETSPNAM_R */
117 #ifdef HAS_READDIR_R
118         /* This is the size Solaris recommends.
119          * (though we go static, should use pathconf() instead) */
120         PL_reentrant_buffer->_readdir_size = sizeof(struct dirent) + MAXPATHLEN + 1;
121 #endif /* HAS_READDIR_R */
122 #ifdef HAS_READDIR64_R
123         /* This is the size Solaris recommends.
124          * (though we go static, should use pathconf() instead) */
125         PL_reentrant_buffer->_readdir64_size = sizeof(struct dirent64) + MAXPATHLEN + 1;
126 #endif /* HAS_READDIR64_R */
127 #ifdef HAS_SETLOCALE_R
128         PL_reentrant_buffer->_setlocale_size = REENTRANTSMALLSIZE;
129 #endif /* HAS_SETLOCALE_R */
130 #ifdef HAS_STRERROR_R
131         PL_reentrant_buffer->_strerror_size = REENTRANTSMALLSIZE;
132 #endif /* HAS_STRERROR_R */
133 #ifdef HAS_TTYNAME_R
134         PL_reentrant_buffer->_ttyname_size = REENTRANTSMALLSIZE;
135 #endif /* HAS_TTYNAME_R */
136
137 #endif /* USE_REENTRANT_API */
138 }
139
140 void
141 Perl_reentrant_init(pTHX) {
142 #ifdef USE_REENTRANT_API
143         Newx(PL_reentrant_buffer, 1, REENTR);
144         Perl_reentrant_size(aTHX);
145 #ifdef HAS_ASCTIME_R
146         Newx(PL_reentrant_buffer->_asctime_buffer, PL_reentrant_buffer->_asctime_size, char);
147 #endif /* HAS_ASCTIME_R */
148 #ifdef HAS_CRYPT_R
149 #if CRYPT_R_PROTO != REENTRANT_PROTO_B_CCD
150         PL_reentrant_buffer->_crypt_struct_buffer = 0;
151 #endif
152 #endif /* HAS_CRYPT_R */
153 #ifdef HAS_CTIME_R
154         Newx(PL_reentrant_buffer->_ctime_buffer, PL_reentrant_buffer->_ctime_size, char);
155 #endif /* HAS_CTIME_R */
156 #ifdef HAS_GETGRNAM_R
157 #   ifdef USE_GRENT_FPTR
158         PL_reentrant_buffer->_grent_fptr = NULL;
159 #   endif
160         Newx(PL_reentrant_buffer->_grent_buffer, PL_reentrant_buffer->_grent_size, char);
161 #endif /* HAS_GETGRNAM_R */
162 #ifdef HAS_GETHOSTBYNAME_R
163 #if   !(GETHOSTBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
164         Newx(PL_reentrant_buffer->_hostent_buffer, PL_reentrant_buffer->_hostent_size, char);
165 #endif
166 #endif /* HAS_GETHOSTBYNAME_R */
167 #ifdef HAS_GETLOGIN_R
168         Newx(PL_reentrant_buffer->_getlogin_buffer, PL_reentrant_buffer->_getlogin_size, char);
169 #endif /* HAS_GETLOGIN_R */
170 #ifdef HAS_GETNETBYNAME_R
171 #if   !(GETNETBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
172         Newx(PL_reentrant_buffer->_netent_buffer, PL_reentrant_buffer->_netent_size, char);
173 #endif
174 #endif /* HAS_GETNETBYNAME_R */
175 #ifdef HAS_GETPROTOBYNAME_R
176 #if   !(GETPROTOBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
177         Newx(PL_reentrant_buffer->_protoent_buffer, PL_reentrant_buffer->_protoent_size, char);
178 #endif
179 #endif /* HAS_GETPROTOBYNAME_R */
180 #ifdef HAS_GETPWNAM_R
181 #   ifdef USE_PWENT_FPTR
182         PL_reentrant_buffer->_pwent_fptr = NULL;
183 #   endif
184         Newx(PL_reentrant_buffer->_pwent_buffer, PL_reentrant_buffer->_pwent_size, char);
185 #endif /* HAS_GETPWNAM_R */
186 #ifdef HAS_GETSERVBYNAME_R
187 #if   !(GETSERVBYNAME_R_PROTO == REENTRANT_PROTO_I_CCSD)
188         Newx(PL_reentrant_buffer->_servent_buffer, PL_reentrant_buffer->_servent_size, char);
189 #endif
190 #endif /* HAS_GETSERVBYNAME_R */
191 #ifdef HAS_GETSPNAM_R
192 #   ifdef USE_SPENT_FPTR
193         PL_reentrant_buffer->_spent_fptr = NULL;
194 #   endif
195         Newx(PL_reentrant_buffer->_spent_buffer, PL_reentrant_buffer->_spent_size, char);
196 #endif /* HAS_GETSPNAM_R */
197 #ifdef HAS_READDIR_R
198         PL_reentrant_buffer->_readdir_struct = (struct dirent*)safemalloc(PL_reentrant_buffer->_readdir_size);
199 #endif /* HAS_READDIR_R */
200 #ifdef HAS_READDIR64_R
201         PL_reentrant_buffer->_readdir64_struct = (struct dirent64*)safemalloc(PL_reentrant_buffer->_readdir64_size);
202 #endif /* HAS_READDIR64_R */
203 #ifdef HAS_SETLOCALE_R
204         Newx(PL_reentrant_buffer->_setlocale_buffer, PL_reentrant_buffer->_setlocale_size, char);
205 #endif /* HAS_SETLOCALE_R */
206 #ifdef HAS_STRERROR_R
207         Newx(PL_reentrant_buffer->_strerror_buffer, PL_reentrant_buffer->_strerror_size, char);
208 #endif /* HAS_STRERROR_R */
209 #ifdef HAS_TTYNAME_R
210         Newx(PL_reentrant_buffer->_ttyname_buffer, PL_reentrant_buffer->_ttyname_size, char);
211 #endif /* HAS_TTYNAME_R */
212
213 #endif /* USE_REENTRANT_API */
214 }
215
216 void
217 Perl_reentrant_free(pTHX) {
218 #ifdef USE_REENTRANT_API
219 #ifdef HAS_ASCTIME_R
220         Safefree(PL_reentrant_buffer->_asctime_buffer);
221 #endif /* HAS_ASCTIME_R */
222 #ifdef HAS_CRYPT_R
223 #if CRYPT_R_PROTO != REENTRANT_PROTO_B_CCD
224         Safefree(PL_reentrant_buffer->_crypt_struct_buffer);
225 #endif
226 #endif /* HAS_CRYPT_R */
227 #ifdef HAS_CTIME_R
228         Safefree(PL_reentrant_buffer->_ctime_buffer);
229 #endif /* HAS_CTIME_R */
230 #ifdef HAS_GETGRNAM_R
231         Safefree(PL_reentrant_buffer->_grent_buffer);
232 #endif /* HAS_GETGRNAM_R */
233 #ifdef HAS_GETHOSTBYNAME_R
234 #if   !(GETHOSTBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
235         Safefree(PL_reentrant_buffer->_hostent_buffer);
236 #endif
237 #endif /* HAS_GETHOSTBYNAME_R */
238 #ifdef HAS_GETLOGIN_R
239         Safefree(PL_reentrant_buffer->_getlogin_buffer);
240 #endif /* HAS_GETLOGIN_R */
241 #ifdef HAS_GETNETBYNAME_R
242 #if   !(GETNETBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
243         Safefree(PL_reentrant_buffer->_netent_buffer);
244 #endif
245 #endif /* HAS_GETNETBYNAME_R */
246 #ifdef HAS_GETPROTOBYNAME_R
247 #if   !(GETPROTOBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
248         Safefree(PL_reentrant_buffer->_protoent_buffer);
249 #endif
250 #endif /* HAS_GETPROTOBYNAME_R */
251 #ifdef HAS_GETPWNAM_R
252         Safefree(PL_reentrant_buffer->_pwent_buffer);
253 #endif /* HAS_GETPWNAM_R */
254 #ifdef HAS_GETSERVBYNAME_R
255 #if   !(GETSERVBYNAME_R_PROTO == REENTRANT_PROTO_I_CCSD)
256         Safefree(PL_reentrant_buffer->_servent_buffer);
257 #endif
258 #endif /* HAS_GETSERVBYNAME_R */
259 #ifdef HAS_GETSPNAM_R
260         Safefree(PL_reentrant_buffer->_spent_buffer);
261 #endif /* HAS_GETSPNAM_R */
262 #ifdef HAS_READDIR_R
263         Safefree(PL_reentrant_buffer->_readdir_struct);
264 #endif /* HAS_READDIR_R */
265 #ifdef HAS_READDIR64_R
266         Safefree(PL_reentrant_buffer->_readdir64_struct);
267 #endif /* HAS_READDIR64_R */
268 #ifdef HAS_SETLOCALE_R
269         Safefree(PL_reentrant_buffer->_setlocale_buffer);
270 #endif /* HAS_SETLOCALE_R */
271 #ifdef HAS_STRERROR_R
272         Safefree(PL_reentrant_buffer->_strerror_buffer);
273 #endif /* HAS_STRERROR_R */
274 #ifdef HAS_TTYNAME_R
275         Safefree(PL_reentrant_buffer->_ttyname_buffer);
276 #endif /* HAS_TTYNAME_R */
277
278         Safefree(PL_reentrant_buffer);
279 #endif /* USE_REENTRANT_API */
280 }
281
282 void*
283 Perl_reentrant_retry(const char *f, ...)
284 {
285     void *retptr = NULL;
286     va_list ap;
287 #ifdef USE_REENTRANT_API
288     dTHX;
289     /* Easier to special case this here than in embed.pl. (Look at what it
290        generates for proto.h) */
291     PERL_ARGS_ASSERT_REENTRANT_RETRY;
292 #endif
293     va_start(ap, f);
294     {
295 #ifdef USE_REENTRANT_API
296 #  if defined(USE_HOSTENT_BUFFER) || defined(USE_GRENT_BUFFER) || defined(USE_NETENT_BUFFER) || defined(USE_PWENT_BUFFER) || defined(USE_PROTOENT_BUFFER) || defined(USE_SERVENT_BUFFER)
297     void *p0;
298 #  endif
299 #  if defined(USE_SERVENT_BUFFER)
300     void *p1;
301 #  endif
302 #  if defined(USE_HOSTENT_BUFFER)
303     size_t asize;
304 #  endif
305 #  if defined(USE_HOSTENT_BUFFER) || defined(USE_NETENT_BUFFER) || defined(USE_PROTOENT_BUFFER) || defined(USE_SERVENT_BUFFER)
306     int anint;
307 #  endif
308
309     switch (PL_op->op_type) {
310 #ifdef USE_HOSTENT_BUFFER
311     case OP_GHBYADDR:
312     case OP_GHBYNAME:
313     case OP_GHOSTENT:
314         {
315 #ifdef PERL_REENTRANT_MAXSIZE
316             if (PL_reentrant_buffer->_hostent_size <=
317                 PERL_REENTRANT_MAXSIZE / 2)
318 #endif
319             {
320                 PL_reentrant_buffer->_hostent_size *= 2;
321                 Renew(PL_reentrant_buffer->_hostent_buffer,
322                       PL_reentrant_buffer->_hostent_size, char);
323                 switch (PL_op->op_type) {
324                 case OP_GHBYADDR:
325                     p0    = va_arg(ap, void *);
326                     asize = va_arg(ap, size_t);
327                     anint  = va_arg(ap, int);
328                     retptr = gethostbyaddr(p0, asize, anint); break;
329                 case OP_GHBYNAME:
330                     p0 = va_arg(ap, void *);
331                     retptr = gethostbyname((char *)p0); break;
332                 case OP_GHOSTENT:
333                     retptr = gethostent(); break;
334                 default:
335                     SETERRNO(ERANGE, LIB_INVARG);
336                     break;
337                 }
338             }
339         }
340         break;
341 #endif
342 #ifdef USE_GRENT_BUFFER
343     case OP_GGRNAM:
344     case OP_GGRGID:
345     case OP_GGRENT:
346         {
347 #ifdef PERL_REENTRANT_MAXSIZE
348             if (PL_reentrant_buffer->_grent_size <=
349                 PERL_REENTRANT_MAXSIZE / 2)
350 #endif
351             {
352                 Gid_t gid;
353                 PL_reentrant_buffer->_grent_size *= 2;
354                 Renew(PL_reentrant_buffer->_grent_buffer,
355                       PL_reentrant_buffer->_grent_size, char);
356                 switch (PL_op->op_type) {
357                 case OP_GGRNAM:
358                     p0 = va_arg(ap, void *);
359                     retptr = getgrnam((char *)p0); break;
360                 case OP_GGRGID:
361 #if Gid_t_size < INTSIZE
362                     gid = (Gid_t)va_arg(ap, int);
363 #else
364                     gid = va_arg(ap, Gid_t);
365 #endif
366                     retptr = getgrgid(gid); break;
367                 case OP_GGRENT:
368                     retptr = getgrent(); break;
369                 default:
370                     SETERRNO(ERANGE, LIB_INVARG);
371                     break;
372                 }
373             }
374         }
375         break;
376 #endif
377 #ifdef USE_NETENT_BUFFER
378     case OP_GNBYADDR:
379     case OP_GNBYNAME:
380     case OP_GNETENT:
381         {
382 #ifdef PERL_REENTRANT_MAXSIZE
383             if (PL_reentrant_buffer->_netent_size <=
384                 PERL_REENTRANT_MAXSIZE / 2)
385 #endif
386             {
387                 Netdb_net_t net;
388                 PL_reentrant_buffer->_netent_size *= 2;
389                 Renew(PL_reentrant_buffer->_netent_buffer,
390                       PL_reentrant_buffer->_netent_size, char);
391                 switch (PL_op->op_type) {
392                 case OP_GNBYADDR:
393                     net = va_arg(ap, Netdb_net_t);
394                     anint = va_arg(ap, int);
395                     retptr = getnetbyaddr(net, anint); break;
396                 case OP_GNBYNAME:
397                     p0 = va_arg(ap, void *);
398                     retptr = getnetbyname((char *)p0); break;
399                 case OP_GNETENT:
400                     retptr = getnetent(); break;
401                 default:
402                     SETERRNO(ERANGE, LIB_INVARG);
403                     break;
404                 }
405             }
406         }
407         break;
408 #endif
409 #ifdef USE_PWENT_BUFFER
410     case OP_GPWNAM:
411     case OP_GPWUID:
412     case OP_GPWENT:
413         {
414 #ifdef PERL_REENTRANT_MAXSIZE
415             if (PL_reentrant_buffer->_pwent_size <=
416                 PERL_REENTRANT_MAXSIZE / 2)
417 #endif
418             {
419                 Uid_t uid;
420                 PL_reentrant_buffer->_pwent_size *= 2;
421                 Renew(PL_reentrant_buffer->_pwent_buffer,
422                       PL_reentrant_buffer->_pwent_size, char);
423                 switch (PL_op->op_type) {
424                 case OP_GPWNAM:
425                     p0 = va_arg(ap, void *);
426                     retptr = getpwnam((char *)p0); break;
427                 case OP_GPWUID:
428 #if Uid_t_size < INTSIZE
429                     uid = (Uid_t)va_arg(ap, int);
430 #else
431                     uid = va_arg(ap, Uid_t);
432 #endif
433                     retptr = getpwuid(uid); break;
434                 case OP_GPWENT:
435                     retptr = getpwent(); break;
436                 default:
437                     SETERRNO(ERANGE, LIB_INVARG);
438                     break;
439                 }
440             }
441         }
442         break;
443 #endif
444 #ifdef USE_PROTOENT_BUFFER
445     case OP_GPBYNAME:
446     case OP_GPBYNUMBER:
447     case OP_GPROTOENT:
448         {
449 #ifdef PERL_REENTRANT_MAXSIZE
450             if (PL_reentrant_buffer->_protoent_size <=
451                 PERL_REENTRANT_MAXSIZE / 2)
452 #endif
453             {
454                 PL_reentrant_buffer->_protoent_size *= 2;
455                 Renew(PL_reentrant_buffer->_protoent_buffer,
456                       PL_reentrant_buffer->_protoent_size, char);
457                 switch (PL_op->op_type) {
458                 case OP_GPBYNAME:
459                     p0 = va_arg(ap, void *);
460                     retptr = getprotobyname((char *)p0); break;
461                 case OP_GPBYNUMBER:
462                     anint = va_arg(ap, int);
463                     retptr = getprotobynumber(anint); break;
464                 case OP_GPROTOENT:
465                     retptr = getprotoent(); break;
466                 default:
467                     SETERRNO(ERANGE, LIB_INVARG);
468                     break;
469                 }
470             }
471         }
472         break;
473 #endif
474 #ifdef USE_SERVENT_BUFFER
475     case OP_GSBYNAME:
476     case OP_GSBYPORT:
477     case OP_GSERVENT:
478         {
479 #ifdef PERL_REENTRANT_MAXSIZE
480             if (PL_reentrant_buffer->_servent_size <=
481                 PERL_REENTRANT_MAXSIZE / 2)
482 #endif
483             {
484                 PL_reentrant_buffer->_servent_size *= 2;
485                 Renew(PL_reentrant_buffer->_servent_buffer,
486                       PL_reentrant_buffer->_servent_size, char);
487                 switch (PL_op->op_type) {
488                 case OP_GSBYNAME:
489                     p0 = va_arg(ap, void *);
490                     p1 = va_arg(ap, void *);
491                     retptr = getservbyname((char *)p0, (char *)p1); break;
492                 case OP_GSBYPORT:
493                     anint = va_arg(ap, int);
494                     p0 = va_arg(ap, void *);
495                     retptr = getservbyport(anint, (char *)p0); break;
496                 case OP_GSERVENT:
497                     retptr = getservent(); break;
498                 default:
499                     SETERRNO(ERANGE, LIB_INVARG);
500                     break;
501                 }
502             }
503         }
504         break;
505 #endif
506     default:
507         /* Not known how to retry, so just fail. */
508         break;
509     }
510 #else
511     PERL_UNUSED_ARG(f);
512 #endif
513     }
514     va_end(ap);
515     return retptr;
516 }
517
518 /* ex: set ro: */