]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - usr.sbin/jail/jaillex.l
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / usr.sbin / jail / jaillex.l
1 %{
2 /*-
3  * Copyright (c) 2011 James Gritton
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30
31 #include <err.h>
32 #include <stddef.h>
33 #include <stdlib.h>
34 #include <string.h>
35
36 #include "jailp.h"
37 #include "y.tab.h"
38
39 extern int yynerrs;
40
41 static ssize_t text2lval(size_t triml, size_t trimr, int tovar);
42
43 static int instr;
44 static int lineno = 1;
45
46 #define YY_DECL int yylex(void)
47 %}
48
49 %option noinput
50 %option nounput
51
52 %start _ DQ
53
54 %%
55
56                         /* Whitespace or equivalent */
57 <_>[ \t]+               instr = 0;
58 <_>#.*                  ;
59 <_>\/\/.*               ;
60 <_>\/\*([^*]|(\*+([^*\/])))*\*+\/ {
61                                 const char *s;
62
63                                 for (s = yytext; s < yytext + yyleng; s++)
64                                         if (*s == '\n')
65                                                 lineno++;
66                                 instr = 0;
67                         }
68 <_>\n                   {
69                                 lineno++;
70                                 instr = 0;
71                         }
72
73                         /* Reserved tokens */
74 <_>\+=                  {
75                                 instr = 0;
76                                 return PLEQ;
77                         }
78 <_>[,;={}]              {
79                                 instr = 0;
80                                 return yytext[0];
81                         }
82
83                         /* Atomic (unquoted) strings */
84 <_,DQ>[A-Za-z0-9_!%&()\-.:<>?@\[\]^`|~]+ |
85 <_,DQ>\\(.|\n|[0-7]{1,3}|x[0-9A-Fa-f]{1,2}) |
86 <_,DQ>[$*+/\\]          {
87                                 (void)text2lval(0, 0, 0);
88                                 return instr ? STR1 : (instr = 1, STR);
89                         }
90
91                         /* Single and double quoted strings */
92 <_>'([^\'\\]|\\(.|\n))*' {
93                                 (void)text2lval(1, 1, 0);
94                                 return instr ? STR1 : (instr = 1, STR);
95                         }
96 <_>\"([^"\\]|\\(.|\n))*\" |
97 <DQ>[^\"$\\]([^"\\]|\\(.|\n))*\" {
98                                 size_t skip;
99                                 ssize_t atvar;
100
101                                 skip = yytext[0] == '"' ? 1 : 0;
102                                 atvar = text2lval(skip, 1, 1);
103                                 if (atvar < 0)
104                                         BEGIN _;
105                                 else {
106                                         /*
107                                          * The string has a variable inside it.
108                                          * Go into DQ mode to get the variable
109                                          * and then the rest of the string.
110                                          */
111                                         BEGIN DQ;
112                                         yyless(atvar);
113                                 }
114                                 return instr ? STR1 : (instr = 1, STR);
115                         }
116 <DQ>\"                  BEGIN _;
117
118                         /* Variables, single-word or bracketed */
119 <_,DQ>$[A-Za-z_][A-Za-z_0-9]* {
120                                 (void)text2lval(1, 0, 0);
121                                 return instr ? VAR1 : (instr = 1, VAR);
122                         }
123 <_>$\{([^\n{}]|\\(.|\n))*\} |
124 <DQ>$\{([^\n\"{}]|\\(.|\n))*\} {
125                                 (void)text2lval(2, 1, 0);
126                                 return instr ? VAR1 : (instr = 1, VAR);
127                         }
128
129                         /* Partially formed bits worth complaining about */
130 <_>\/\*([^*]|(\*+([^*\/])))*\** {
131                                 warnx("%s line %d: unterminated comment",
132                                     cfname, lineno);
133                                 yynerrs++;
134                         }
135 <_>'([^\n'\\]|\\.)*     |
136 <_>\"([^\n\"\\]|\\.)*   {
137                                 warnx("%s line %d: unterminated string",
138                                     cfname, lineno);
139                                 yynerrs++;
140                         }
141 <_>$\{([^\n{}]|\\.)*    |
142 <DQ>$\{([^\n\"{}]|\\.)* {
143                                 warnx("%s line %d: unterminated variable",
144                                     cfname, lineno);
145                                 yynerrs++;
146                         }
147
148                         /* A hack because "<0>" rules aren't allowed */
149 <_>.                    return yytext[0];
150 .|\n                    {
151                                 BEGIN _;
152                                 yyless(0);
153                         }
154
155 %%
156
157 void
158 yyerror(const char *s)
159 {
160         if (!yytext)
161                 warnx("%s line %d: %s", cfname, lineno, s);
162         else if (!yytext[0])
163                 warnx("%s: unexpected EOF", cfname);
164         else
165                 warnx("%s line %d: %s: %s", cfname, lineno, yytext, s);
166 }
167
168 /*
169  * Copy string from yytext to yylval, handling backslash escapes,
170  * and optionally stopping at the beginning of a variable.
171  */
172 static ssize_t
173 text2lval(size_t triml, size_t trimr, int tovar)
174 {
175         char *d;
176         const char *s, *se;
177
178         yylval.cs = d = emalloc(yyleng - trimr - triml + 1);
179         se = yytext + (yyleng - trimr);
180         for (s = yytext + triml; s < se; s++, d++) {
181                 if (*s != '\\') {
182                         if (tovar && *s == '$') {
183                                 *d = '\0';
184                                 return s - yytext;
185                         }
186                         if (*s == '\n')
187                                 lineno++;
188                         *d = *s;
189                         continue;
190                 }
191                 s++;
192                 if (*s >= '0' && *s <= '7') {
193                         *d = *s - '0';
194                         if (s + 1 < se && s[1] >= '0' && s[1] <= '7') {
195                                 *d = 010 * *d + (*++s - '0');
196                                 if (s + 1 < se && s[1] >= '0' && s[1] <= '7')
197                                         *d = 010 * *d + (*++s - '0');
198                         }
199                         continue;
200                 }
201                 switch (*s) {
202                 case 'a':       *d = '\a';      break;
203                 case 'b':       *d = '\b';      break;
204                 case 'f':       *d = '\f';      break;
205                 case 'n':       *d = '\n';      break;
206                 case 'r':       *d = '\r';      break;
207                 case 't':       *d = '\t';      break;
208                 case 'v':       *d = '\v';      break;
209                 case '\n':      d--; lineno++;  break;
210                 default:        *d = *s;        break;
211                 case 'x':
212                         *d = 0;
213                         if (s + 1 >= se)
214                                 break;
215                         if (s[1] >= '0' && s[1] <= '9')
216                                 *d = *++s - '0';
217                         else if (s[1] >= 'A' && s[1] <= 'F')
218                                 *d = *++s + (0xA - 'A');
219                         else if (s[1] >= 'a' && s[1] <= 'a')
220                                 *d = *++s + (0xa - 'a');
221                         else
222                                 break;
223                         if (s + 1 >= se)
224                                 break;
225                         if (s[1] >= '0' && s[1] <= '9')
226                                 *d = *d * 0x10 + (*++s - '0');
227                         else if (s[1] >= 'A' && s[1] <= 'F')
228                                 *d = *d * 0x10 + (*++s + (0xA - 'A'));
229                         else if (s[1] >= 'a' && s[1] <= 'a')
230                                 *d = *d * 0x10 + (*++s + (0xa - 'a'));
231                 }
232         }
233         *d = '\0';
234         return -1;
235 }