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