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