1 /* NetHack 3.6  posixregex.c	$NHDT-Date: 1434446947 2015/06/16 09:29:07 $  $NHDT-Branch: master $:$NHDT-Revision: 1.5 $ */
2 /* Copyright (c) Sean Hunt  2015.                                 */
3 /* NetHack may be freely redistributed.  See license for details. */
4 
5 #include "hack.h"
6 
7 #include <regex.h>
8 
9 /* The nhregex interface is implemented by several source files. The
10  * file to be used can be linked in by the build.
11  *
12  * The regex standard implemented should be POSIX extended regular
13  * expressions, see:
14  *   http://pubs.opengroup.org/onlinepubs/009696899/basedefs/xbd_chap09.html
15  * If an implementation uses an alternate expression format, this should
16  * be clearly noted; this will result in incompatibility of config files
17  * when NetHack is compiled with that implementation.
18  *
19  * struct nhregex
20  * The nhregex structure is an opaque structure type containing the
21  * information about a compiled regular expression.
22  *
23  * struct nhregex *regex_init(void)
24  * Used to create a new instance of the nhregex structure. It is
25  * uninitialized and can only safely be passed to regex_compile.
26  *
27  * boolean regex_compile(const char *s, struct nhregex *re)
28  * Used to compile s into a regex and store it in re. Returns TRUE if
29  * successful and FALSE otherwise. re is invalidated regardless of
30  * success.
31  *
32  * const char *regex_error_desc(struct nhregex *re)
33  * Used to retrieve an error description from an error created involving
34  * re. Returns NULL if no description can be retrieved. The returned
35  * string may be a static buffer and so is only valid until the next
36  * call to regex_error_desc.
37  *
38  * boolean regex_match(const char *s, struct nhregex *re)
39  * Used to determine if s (or any substring) matches the regex compiled
40  * into re. Only valid if the most recent call to regex_compile on re
41  * succeeded.
42  *
43  * void regex_free(struct nhregex *re)
44  * Deallocate a regex object.
45  */
46 
47 const char regex_id[] = "posixregex";
48 
49 struct nhregex {
50     regex_t re;
51     int err;
52 };
53 
54 struct nhregex *
regex_init()55 regex_init()
56 {
57     return (struct nhregex *) alloc(sizeof(struct nhregex));
58 }
59 
60 boolean
regex_compile(const char * s,struct nhregex * re)61 regex_compile(const char *s, struct nhregex *re)
62 {
63     if (!re)
64         return FALSE;
65     if ((re->err = regcomp(&re->re, s, REG_EXTENDED | REG_NOSUB)))
66         return FALSE;
67     return TRUE;
68 }
69 
70 const char *
regex_error_desc(struct nhregex * re)71 regex_error_desc(struct nhregex *re)
72 {
73     static char buf[BUFSZ];
74 
75     if (!re || !re->err)
76         return (const char *) 0;
77 
78     /* FIXME: Using a static buffer here is not ideal, but avoids memory
79      * leaks. Consider the allocation more carefully. */
80     regerror(re->err, &re->re, buf, BUFSZ);
81 
82     return buf;
83 }
84 
85 boolean
regex_match(const char * s,struct nhregex * re)86 regex_match(const char *s, struct nhregex *re)
87 {
88     int result;
89 
90     if (!re || !s)
91         return FALSE;
92 
93     if ((result = regexec(&re->re, s, 0, (genericptr_t) 0, 0))) {
94         if (result != REG_NOMATCH)
95             re->err = result;
96         return FALSE;
97     }
98     return TRUE;
99 }
100 
101 void
regex_free(struct nhregex * re)102 regex_free(struct nhregex *re)
103 {
104     regfree(&re->re);
105     free(re);
106 }
107