jaillex.l revision 250227
1214117Sjamie%{ 2214117Sjamie/*- 3223190Sjamie * Copyright (c) 2011 James Gritton 4214117Sjamie * All rights reserved. 5214117Sjamie * 6214117Sjamie * Redistribution and use in source and binary forms, with or without 7214117Sjamie * modification, are permitted provided that the following conditions 8214117Sjamie * are met: 9214117Sjamie * 1. Redistributions of source code must retain the above copyright 10214117Sjamie * notice, this list of conditions and the following disclaimer. 11214117Sjamie * 2. Redistributions in binary form must reproduce the above copyright 12214117Sjamie * notice, this list of conditions and the following disclaimer in the 13214117Sjamie * documentation and/or other materials provided with the distribution. 14214117Sjamie * 15214117Sjamie * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16214117Sjamie * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17214117Sjamie * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18214117Sjamie * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19214117Sjamie * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20214117Sjamie * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21214117Sjamie * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22214117Sjamie * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23214117Sjamie * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24214117Sjamie * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25214117Sjamie * SUCH DAMAGE. 26214117Sjamie */ 27214117Sjamie 28214117Sjamie#include <sys/cdefs.h> 29214117Sjamie__FBSDID("$FreeBSD: head/usr.sbin/jail/jaillex.l 250227 2013-05-03 23:51:32Z jkim $"); 30214117Sjamie 31214117Sjamie#include <err.h> 32214117Sjamie#include <stddef.h> 33214117Sjamie#include <stdlib.h> 34214117Sjamie#include <string.h> 35214117Sjamie 36214117Sjamie#include "jailp.h" 37214117Sjamie#include "y.tab.h" 38214117Sjamie 39214117Sjamieextern int yynerrs; 40214117Sjamie 41214117Sjamiestatic ssize_t text2lval(size_t triml, size_t trimr, int tovar); 42214117Sjamie 43214117Sjamiestatic int instr; 44214117Sjamiestatic int lineno = 1; 45214117Sjamie%} 46214117Sjamie 47250227Sjkim%option noinput 48250227Sjkim%option nounput 49250227Sjkim 50214117Sjamie%start _ DQ 51214117Sjamie 52214117Sjamie%% 53214117Sjamie 54214117Sjamie /* Whitespace or equivalent */ 55214117Sjamie<_>[ \t]+ instr = 0; 56214117Sjamie<_>#.* ; 57214117Sjamie<_>\/\/.* ; 58214117Sjamie<_>\/\*([^*]|(\*+([^*\/])))*\*+\/ { 59214117Sjamie const char *s; 60214117Sjamie 61214117Sjamie for (s = yytext; s < yytext + yyleng; s++) 62214117Sjamie if (*s == '\n') 63214117Sjamie lineno++; 64214117Sjamie instr = 0; 65214117Sjamie } 66214117Sjamie<_>\n { 67214117Sjamie lineno++; 68214117Sjamie instr = 0; 69214117Sjamie } 70214117Sjamie 71214117Sjamie /* Reserved tokens */ 72214117Sjamie<_>\+= { 73214117Sjamie instr = 0; 74214117Sjamie return PLEQ; 75214117Sjamie } 76214117Sjamie<_>[,;={}] { 77214117Sjamie instr = 0; 78214117Sjamie return yytext[0]; 79214117Sjamie } 80214117Sjamie 81214117Sjamie /* Atomic (unquoted) strings */ 82214117Sjamie<_,DQ>[A-Za-z0-9_!%&()\-.:<>?@\[\]^`|~]+ | 83214117Sjamie<_,DQ>\\(.|\n|[0-7]{1,3}|x[0-9A-Fa-f]{1,2}) | 84214117Sjamie<_,DQ>[$*+/\\] { 85214117Sjamie (void)text2lval(0, 0, 0); 86214117Sjamie return instr ? STR1 : (instr = 1, STR); 87214117Sjamie } 88214117Sjamie 89214117Sjamie /* Single and double quoted strings */ 90214117Sjamie<_>'([^\'\\]|\\(.|\n))*' { 91214117Sjamie (void)text2lval(1, 1, 0); 92214117Sjamie return instr ? STR1 : (instr = 1, STR); 93214117Sjamie } 94214117Sjamie<_>\"([^"\\]|\\(.|\n))*\" | 95214117Sjamie<DQ>[^\"$\\]([^"\\]|\\(.|\n))*\" { 96214117Sjamie size_t skip; 97214117Sjamie ssize_t atvar; 98214117Sjamie 99214117Sjamie skip = yytext[0] == '"' ? 1 : 0; 100214117Sjamie atvar = text2lval(skip, 1, 1); 101214117Sjamie if (atvar < 0) 102214117Sjamie BEGIN _; 103214117Sjamie else { 104214117Sjamie /* 105214117Sjamie * The string has a variable inside it. 106214117Sjamie * Go into DQ mode to get the variable 107214117Sjamie * and then the rest of the string. 108214117Sjamie */ 109214117Sjamie BEGIN DQ; 110214117Sjamie yyless(atvar); 111214117Sjamie } 112214117Sjamie return instr ? STR1 : (instr = 1, STR); 113214117Sjamie } 114214117Sjamie<DQ>\" BEGIN _; 115214117Sjamie 116214117Sjamie /* Variables, single-word or bracketed */ 117214117Sjamie<_,DQ>$[A-Za-z_][A-Za-z_0-9]* { 118214117Sjamie (void)text2lval(1, 0, 0); 119214117Sjamie return instr ? VAR1 : (instr = 1, VAR); 120214117Sjamie } 121214117Sjamie<_>$\{([^\n{}]|\\(.|\n))*\} | 122214117Sjamie<DQ>$\{([^\n\"{}]|\\(.|\n))*\} { 123214117Sjamie (void)text2lval(2, 1, 0); 124214117Sjamie return instr ? VAR1 : (instr = 1, VAR); 125214117Sjamie } 126214117Sjamie 127214117Sjamie /* Partially formed bits worth complaining about */ 128214117Sjamie<_>\/\*([^*]|(\*+([^*\/])))*\** { 129214117Sjamie warnx("%s line %d: unterminated comment", 130214117Sjamie cfname, lineno); 131214117Sjamie yynerrs++; 132214117Sjamie } 133214117Sjamie<_>'([^\n'\\]|\\.)* | 134214117Sjamie<_>\"([^\n\"\\]|\\.)* { 135214117Sjamie warnx("%s line %d: unterminated string", 136214117Sjamie cfname, lineno); 137214117Sjamie yynerrs++; 138214117Sjamie } 139214117Sjamie<_>$\{([^\n{}]|\\.)* | 140214117Sjamie<DQ>$\{([^\n\"{}]|\\.)* { 141214117Sjamie warnx("%s line %d: unterminated variable", 142214117Sjamie cfname, lineno); 143214117Sjamie yynerrs++; 144214117Sjamie } 145214117Sjamie 146214117Sjamie /* A hack because "<0>" rules aren't allowed */ 147214117Sjamie<_>. return yytext[0]; 148214117Sjamie.|\n { 149214117Sjamie BEGIN _; 150214117Sjamie yyless(0); 151214117Sjamie } 152214117Sjamie 153214117Sjamie%% 154214117Sjamie 155214117Sjamievoid 156214117Sjamieyyerror(const char *s) 157214117Sjamie{ 158214117Sjamie if (!yytext) 159214117Sjamie warnx("%s line %d: %s", cfname, lineno, s); 160214117Sjamie else if (!yytext[0]) 161214117Sjamie warnx("%s: unexpected EOF", cfname); 162214117Sjamie else 163214117Sjamie warnx("%s line %d: %s: %s", cfname, lineno, yytext, s); 164214117Sjamie} 165214117Sjamie 166214117Sjamie/* 167214117Sjamie * Copy string from yytext to yylval, handling backslash escapes, 168214117Sjamie * and optionally stopping at the beginning of a variable. 169214117Sjamie */ 170214117Sjamiestatic ssize_t 171214117Sjamietext2lval(size_t triml, size_t trimr, int tovar) 172214117Sjamie{ 173214117Sjamie char *d; 174214117Sjamie const char *s, *se; 175214117Sjamie 176214117Sjamie yylval.cs = d = emalloc(yyleng - trimr - triml + 1); 177214117Sjamie se = yytext + (yyleng - trimr); 178214117Sjamie for (s = yytext + triml; s < se; s++, d++) { 179214117Sjamie if (*s != '\\') { 180214117Sjamie if (tovar && *s == '$') { 181214117Sjamie *d = '\0'; 182214117Sjamie return s - yytext; 183214117Sjamie } 184214117Sjamie if (*s == '\n') 185214117Sjamie lineno++; 186214117Sjamie *d = *s; 187214117Sjamie continue; 188214117Sjamie } 189214117Sjamie s++; 190214117Sjamie if (*s >= '0' && *s <= '7') { 191214117Sjamie *d = *s - '0'; 192214117Sjamie if (s + 1 < se && s[1] >= '0' && s[1] <= '7') { 193214117Sjamie *d = 010 * *d + (*++s - '0'); 194214117Sjamie if (s + 1 < se && s[1] >= '0' && s[1] <= '7') 195214117Sjamie *d = 010 * *d + (*++s - '0'); 196214117Sjamie } 197214117Sjamie continue; 198214117Sjamie } 199214117Sjamie switch (*s) { 200214117Sjamie case 'a': *d = '\a'; break; 201214117Sjamie case 'b': *d = '\b'; break; 202214117Sjamie case 'f': *d = '\f'; break; 203214117Sjamie case 'n': *d = '\n'; break; 204214117Sjamie case 'r': *d = '\r'; break; 205214117Sjamie case 't': *d = '\t'; break; 206214117Sjamie case 'v': *d = '\v'; break; 207214117Sjamie case '\n': d--; lineno++; break; 208214117Sjamie default: *d = *s; break; 209214117Sjamie case 'x': 210214117Sjamie *d = 0; 211214117Sjamie if (s + 1 >= se) 212214117Sjamie break; 213214117Sjamie if (s[1] >= '0' && s[1] <= '9') 214214117Sjamie *d = *++s - '0'; 215214117Sjamie else if (s[1] >= 'A' && s[1] <= 'F') 216214117Sjamie *d = *++s + (0xA - 'A'); 217214117Sjamie else if (s[1] >= 'a' && s[1] <= 'a') 218214117Sjamie *d = *++s + (0xa - 'a'); 219214117Sjamie else 220214117Sjamie break; 221214117Sjamie if (s + 1 >= se) 222214117Sjamie break; 223214117Sjamie if (s[1] >= '0' && s[1] <= '9') 224214117Sjamie *d = *d * 0x10 + (*++s - '0'); 225214117Sjamie else if (s[1] >= 'A' && s[1] <= 'F') 226214117Sjamie *d = *d * 0x10 + (*++s + (0xA - 'A')); 227214117Sjamie else if (s[1] >= 'a' && s[1] <= 'a') 228214117Sjamie *d = *d * 0x10 + (*++s + (0xa - 'a')); 229214117Sjamie } 230214117Sjamie } 231214117Sjamie *d = '\0'; 232214117Sjamie return -1; 233214117Sjamie} 234