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: releng/11.0/usr.sbin/jail/jaillex.l 250926 2013-05-23 05:42:35Z 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; 45250926Sjkim 46250926Sjkim#define YY_DECL int yylex(void) 47214117Sjamie%} 48214117Sjamie 49250227Sjkim%option noinput 50250227Sjkim%option nounput 51250227Sjkim 52214117Sjamie%start _ DQ 53214117Sjamie 54214117Sjamie%% 55214117Sjamie 56214117Sjamie /* Whitespace or equivalent */ 57214117Sjamie<_>[ \t]+ instr = 0; 58214117Sjamie<_>#.* ; 59214117Sjamie<_>\/\/.* ; 60214117Sjamie<_>\/\*([^*]|(\*+([^*\/])))*\*+\/ { 61214117Sjamie const char *s; 62214117Sjamie 63214117Sjamie for (s = yytext; s < yytext + yyleng; s++) 64214117Sjamie if (*s == '\n') 65214117Sjamie lineno++; 66214117Sjamie instr = 0; 67214117Sjamie } 68214117Sjamie<_>\n { 69214117Sjamie lineno++; 70214117Sjamie instr = 0; 71214117Sjamie } 72214117Sjamie 73214117Sjamie /* Reserved tokens */ 74214117Sjamie<_>\+= { 75214117Sjamie instr = 0; 76214117Sjamie return PLEQ; 77214117Sjamie } 78214117Sjamie<_>[,;={}] { 79214117Sjamie instr = 0; 80214117Sjamie return yytext[0]; 81214117Sjamie } 82214117Sjamie 83214117Sjamie /* Atomic (unquoted) strings */ 84214117Sjamie<_,DQ>[A-Za-z0-9_!%&()\-.:<>?@\[\]^`|~]+ | 85214117Sjamie<_,DQ>\\(.|\n|[0-7]{1,3}|x[0-9A-Fa-f]{1,2}) | 86214117Sjamie<_,DQ>[$*+/\\] { 87214117Sjamie (void)text2lval(0, 0, 0); 88214117Sjamie return instr ? STR1 : (instr = 1, STR); 89214117Sjamie } 90214117Sjamie 91214117Sjamie /* Single and double quoted strings */ 92214117Sjamie<_>'([^\'\\]|\\(.|\n))*' { 93214117Sjamie (void)text2lval(1, 1, 0); 94214117Sjamie return instr ? STR1 : (instr = 1, STR); 95214117Sjamie } 96214117Sjamie<_>\"([^"\\]|\\(.|\n))*\" | 97214117Sjamie<DQ>[^\"$\\]([^"\\]|\\(.|\n))*\" { 98214117Sjamie size_t skip; 99214117Sjamie ssize_t atvar; 100214117Sjamie 101214117Sjamie skip = yytext[0] == '"' ? 1 : 0; 102214117Sjamie atvar = text2lval(skip, 1, 1); 103214117Sjamie if (atvar < 0) 104214117Sjamie BEGIN _; 105214117Sjamie else { 106214117Sjamie /* 107214117Sjamie * The string has a variable inside it. 108214117Sjamie * Go into DQ mode to get the variable 109214117Sjamie * and then the rest of the string. 110214117Sjamie */ 111214117Sjamie BEGIN DQ; 112214117Sjamie yyless(atvar); 113214117Sjamie } 114214117Sjamie return instr ? STR1 : (instr = 1, STR); 115214117Sjamie } 116214117Sjamie<DQ>\" BEGIN _; 117214117Sjamie 118214117Sjamie /* Variables, single-word or bracketed */ 119214117Sjamie<_,DQ>$[A-Za-z_][A-Za-z_0-9]* { 120214117Sjamie (void)text2lval(1, 0, 0); 121214117Sjamie return instr ? VAR1 : (instr = 1, VAR); 122214117Sjamie } 123214117Sjamie<_>$\{([^\n{}]|\\(.|\n))*\} | 124214117Sjamie<DQ>$\{([^\n\"{}]|\\(.|\n))*\} { 125214117Sjamie (void)text2lval(2, 1, 0); 126214117Sjamie return instr ? VAR1 : (instr = 1, VAR); 127214117Sjamie } 128214117Sjamie 129214117Sjamie /* Partially formed bits worth complaining about */ 130214117Sjamie<_>\/\*([^*]|(\*+([^*\/])))*\** { 131214117Sjamie warnx("%s line %d: unterminated comment", 132214117Sjamie cfname, lineno); 133214117Sjamie yynerrs++; 134214117Sjamie } 135214117Sjamie<_>'([^\n'\\]|\\.)* | 136214117Sjamie<_>\"([^\n\"\\]|\\.)* { 137214117Sjamie warnx("%s line %d: unterminated string", 138214117Sjamie cfname, lineno); 139214117Sjamie yynerrs++; 140214117Sjamie } 141214117Sjamie<_>$\{([^\n{}]|\\.)* | 142214117Sjamie<DQ>$\{([^\n\"{}]|\\.)* { 143214117Sjamie warnx("%s line %d: unterminated variable", 144214117Sjamie cfname, lineno); 145214117Sjamie yynerrs++; 146214117Sjamie } 147214117Sjamie 148214117Sjamie /* A hack because "<0>" rules aren't allowed */ 149214117Sjamie<_>. return yytext[0]; 150214117Sjamie.|\n { 151214117Sjamie BEGIN _; 152214117Sjamie yyless(0); 153214117Sjamie } 154214117Sjamie 155214117Sjamie%% 156214117Sjamie 157214117Sjamievoid 158214117Sjamieyyerror(const char *s) 159214117Sjamie{ 160214117Sjamie if (!yytext) 161214117Sjamie warnx("%s line %d: %s", cfname, lineno, s); 162214117Sjamie else if (!yytext[0]) 163214117Sjamie warnx("%s: unexpected EOF", cfname); 164214117Sjamie else 165214117Sjamie warnx("%s line %d: %s: %s", cfname, lineno, yytext, s); 166214117Sjamie} 167214117Sjamie 168214117Sjamie/* 169214117Sjamie * Copy string from yytext to yylval, handling backslash escapes, 170214117Sjamie * and optionally stopping at the beginning of a variable. 171214117Sjamie */ 172214117Sjamiestatic ssize_t 173214117Sjamietext2lval(size_t triml, size_t trimr, int tovar) 174214117Sjamie{ 175214117Sjamie char *d; 176214117Sjamie const char *s, *se; 177214117Sjamie 178214117Sjamie yylval.cs = d = emalloc(yyleng - trimr - triml + 1); 179214117Sjamie se = yytext + (yyleng - trimr); 180214117Sjamie for (s = yytext + triml; s < se; s++, d++) { 181214117Sjamie if (*s != '\\') { 182214117Sjamie if (tovar && *s == '$') { 183214117Sjamie *d = '\0'; 184214117Sjamie return s - yytext; 185214117Sjamie } 186214117Sjamie if (*s == '\n') 187214117Sjamie lineno++; 188214117Sjamie *d = *s; 189214117Sjamie continue; 190214117Sjamie } 191214117Sjamie s++; 192214117Sjamie if (*s >= '0' && *s <= '7') { 193214117Sjamie *d = *s - '0'; 194214117Sjamie if (s + 1 < se && s[1] >= '0' && s[1] <= '7') { 195214117Sjamie *d = 010 * *d + (*++s - '0'); 196214117Sjamie if (s + 1 < se && s[1] >= '0' && s[1] <= '7') 197214117Sjamie *d = 010 * *d + (*++s - '0'); 198214117Sjamie } 199214117Sjamie continue; 200214117Sjamie } 201214117Sjamie switch (*s) { 202214117Sjamie case 'a': *d = '\a'; break; 203214117Sjamie case 'b': *d = '\b'; break; 204214117Sjamie case 'f': *d = '\f'; break; 205214117Sjamie case 'n': *d = '\n'; break; 206214117Sjamie case 'r': *d = '\r'; break; 207214117Sjamie case 't': *d = '\t'; break; 208214117Sjamie case 'v': *d = '\v'; break; 209214117Sjamie case '\n': d--; lineno++; break; 210214117Sjamie default: *d = *s; break; 211214117Sjamie case 'x': 212214117Sjamie *d = 0; 213214117Sjamie if (s + 1 >= se) 214214117Sjamie break; 215214117Sjamie if (s[1] >= '0' && s[1] <= '9') 216214117Sjamie *d = *++s - '0'; 217214117Sjamie else if (s[1] >= 'A' && s[1] <= 'F') 218214117Sjamie *d = *++s + (0xA - 'A'); 219214117Sjamie else if (s[1] >= 'a' && s[1] <= 'a') 220214117Sjamie *d = *++s + (0xa - 'a'); 221214117Sjamie else 222214117Sjamie break; 223214117Sjamie if (s + 1 >= se) 224214117Sjamie break; 225214117Sjamie if (s[1] >= '0' && s[1] <= '9') 226214117Sjamie *d = *d * 0x10 + (*++s - '0'); 227214117Sjamie else if (s[1] >= 'A' && s[1] <= 'F') 228214117Sjamie *d = *d * 0x10 + (*++s + (0xA - 'A')); 229214117Sjamie else if (s[1] >= 'a' && s[1] <= 'a') 230214117Sjamie *d = *d * 0x10 + (*++s + (0xa - 'a')); 231214117Sjamie } 232214117Sjamie } 233214117Sjamie *d = '\0'; 234214117Sjamie return -1; 235214117Sjamie} 236