Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/jail/jaillex.l
Show All 32 Lines | |||||
#include <err.h> | #include <err.h> | ||||
#include <stddef.h> | #include <stddef.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include "jailp.h" | #include "jailp.h" | ||||
#include "y.tab.h" | #include "y.tab.h" | ||||
extern int yynerrs; | #define YY_DECL int yylex(YYSTYPE *yylval, yyscan_t yyscanner) | ||||
#define YY_EXTRA_TYPE struct cflex* | |||||
static ssize_t text2lval(size_t triml, size_t trimr, int tovar); | extern YY_DECL; | ||||
static int instr; | static int instr; | ||||
static int lineno = 1; | |||||
#define YY_DECL int yylex(void) | static ssize_t text2lval(size_t triml, size_t trimr, int tovar, | ||||
YYSTYPE *yylval, yyscan_t scanner); | |||||
%} | %} | ||||
%option noyywrap | %option noyywrap | ||||
%option noinput | %option noinput | ||||
%option nounput | %option nounput | ||||
%option reentrant | |||||
%option yylineno | |||||
%start _ DQ | %start _ DQ | ||||
%% | %% | ||||
/* Whitespace or equivalent */ | /* Whitespace or equivalent */ | ||||
<_>[ \t]+ instr = 0; | <_>[ \t]+ instr = 0; | ||||
<_>#.* ; | <_>#.* ; | ||||
<_>\/\/.* ; | <_>\/\/.* ; | ||||
<_>\/\*([^*]|(\*+([^*\/])))*\*+\/ { | <_>\/\*([^*]|(\*+([^*\/])))*\*+\/ instr = 0; | ||||
const char *s; | <_>\n instr = 0; | ||||
for (s = yytext; s < yytext + yyleng; s++) | |||||
if (*s == '\n') | |||||
lineno++; | |||||
instr = 0; | |||||
} | |||||
<_>\n { | |||||
lineno++; | |||||
instr = 0; | |||||
} | |||||
/* Reserved tokens */ | /* Reserved tokens */ | ||||
<_>\+= { | <_>\+= { | ||||
instr = 0; | instr = 0; | ||||
return PLEQ; | return PLEQ; | ||||
} | } | ||||
<_>[,;={}] { | <_>[,;={}] { | ||||
instr = 0; | instr = 0; | ||||
return yytext[0]; | return yytext[0]; | ||||
} | } | ||||
/* Atomic (unquoted) strings */ | /* Atomic (unquoted) strings */ | ||||
<_,DQ>[A-Za-z0-9_!%&()\-.:<>?@\[\]^`|~]+ | | <_,DQ>[A-Za-z0-9_!%&()\-.:<>?@\[\]^`|~]+ | | ||||
<_,DQ>\\(.|\n|[0-7]{1,3}|x[0-9A-Fa-f]{1,2}) | | <_,DQ>\\(.|\n|[0-7]{1,3}|x[0-9A-Fa-f]{1,2}) | | ||||
<_,DQ>[$*+/\\] { | <_,DQ>[$*+/\\] { | ||||
(void)text2lval(0, 0, 0); | (void)text2lval(0, 0, 0, yylval, yyscanner); | ||||
return instr ? STR1 : (instr = 1, STR); | return instr ? STR1 : (instr = 1, STR); | ||||
} | } | ||||
/* Single and double quoted strings */ | /* Single and double quoted strings */ | ||||
<_>'([^\'\\]|\\(.|\n))*' { | <_>'([^\'\\]|\\(.|\n))*' { | ||||
(void)text2lval(1, 1, 0); | (void)text2lval(1, 1, 0, yylval, yyscanner); | ||||
return instr ? STR1 : (instr = 1, STR); | return instr ? STR1 : (instr = 1, STR); | ||||
} | } | ||||
<_>\"([^"\\]|\\(.|\n))*\" | | <_>\"([^"\\]|\\(.|\n))*\" | | ||||
<DQ>[^\"$\\]([^"\\]|\\(.|\n))*\" { | <DQ>[^\"$\\]([^"\\]|\\(.|\n))*\" { | ||||
size_t skip; | size_t skip; | ||||
ssize_t atvar; | ssize_t atvar; | ||||
skip = yytext[0] == '"' ? 1 : 0; | skip = yytext[0] == '"' ? 1 : 0; | ||||
atvar = text2lval(skip, 1, 1); | atvar = text2lval(skip, 1, 1, yylval, | ||||
yyscanner); | |||||
if (atvar < 0) | if (atvar < 0) | ||||
BEGIN _; | BEGIN _; | ||||
else { | else { | ||||
/* | /* | ||||
* The string has a variable inside it. | * The string has a variable inside it. | ||||
* Go into DQ mode to get the variable | * Go into DQ mode to get the variable | ||||
* and then the rest of the string. | * and then the rest of the string. | ||||
*/ | */ | ||||
BEGIN DQ; | BEGIN DQ; | ||||
yyless(atvar); | yyless(atvar); | ||||
} | } | ||||
return instr ? STR1 : (instr = 1, STR); | return instr ? STR1 : (instr = 1, STR); | ||||
} | } | ||||
<DQ>\" BEGIN _; | <DQ>\" BEGIN _; | ||||
/* Variables, single-word or bracketed */ | /* Variables, single-word or bracketed */ | ||||
<_,DQ>$[A-Za-z_][A-Za-z_0-9]* { | <_,DQ>$[A-Za-z_][A-Za-z_0-9]* { | ||||
(void)text2lval(1, 0, 0); | (void)text2lval(1, 0, 0, yylval, yyscanner); | ||||
return instr ? VAR1 : (instr = 1, VAR); | return instr ? VAR1 : (instr = 1, VAR); | ||||
} | } | ||||
<_>$\{([^\n{}]|\\(.|\n))*\} | | <_>$\{([^\n{}]|\\(.|\n))*\} | | ||||
<DQ>$\{([^\n\"{}]|\\(.|\n))*\} { | <DQ>$\{([^\n\"{}]|\\(.|\n))*\} { | ||||
(void)text2lval(2, 1, 0); | (void)text2lval(2, 1, 0, yylval, yyscanner); | ||||
return instr ? VAR1 : (instr = 1, VAR); | return instr ? VAR1 : (instr = 1, VAR); | ||||
} | } | ||||
/* Partially formed bits worth complaining about */ | /* Partially formed bits worth complaining about */ | ||||
<_>\/\*([^*]|(\*+([^*\/])))*\** { | <_>\/\*([^*]|(\*+([^*\/])))*\** { | ||||
warnx("%s line %d: unterminated comment", | warnx("%s line %d: unterminated comment", | ||||
cfname, lineno); | yyextra->cfname, yylineno); | ||||
yynerrs++; | yyextra->error = 1; | ||||
} | } | ||||
<_>'([^\n'\\]|\\.)* | | <_>'([^\n'\\]|\\.)* | | ||||
<_>\"([^\n\"\\]|\\.)* { | <_>\"([^\n\"\\]|\\.)* { | ||||
warnx("%s line %d: unterminated string", | warnx("%s line %d: unterminated string", | ||||
cfname, lineno); | yyextra->cfname, yylineno); | ||||
yynerrs++; | yyextra->error = 1; | ||||
} | } | ||||
<_>$\{([^\n{}]|\\.)* | | <_>$\{([^\n{}]|\\.)* | | ||||
<DQ>$\{([^\n\"{}]|\\.)* { | <DQ>$\{([^\n\"{}]|\\.)* { | ||||
warnx("%s line %d: unterminated variable", | warnx("%s line %d: unterminated variable", | ||||
cfname, lineno); | yyextra->cfname, yylineno); | ||||
yynerrs++; | yyextra->error = 1; | ||||
} | } | ||||
/* A hack because "<0>" rules aren't allowed */ | /* A hack because "<0>" rules aren't allowed */ | ||||
<_>. return yytext[0]; | <_>. return yytext[0]; | ||||
.|\n { | .|\n { | ||||
BEGIN _; | BEGIN _; | ||||
yyless(0); | yyless(0); | ||||
} | } | ||||
%% | %% | ||||
void | |||||
yyerror(const char *s) | |||||
{ | |||||
if (!yytext) | |||||
warnx("%s line %d: %s", cfname, lineno, s); | |||||
else if (!yytext[0]) | |||||
warnx("%s: unexpected EOF", cfname); | |||||
else | |||||
warnx("%s line %d: %s: %s", cfname, lineno, yytext, s); | |||||
} | |||||
/* | /* | ||||
* Copy string from yytext to yylval, handling backslash escapes, | * Copy string from yytext to yylval, handling backslash escapes, | ||||
* and optionally stopping at the beginning of a variable. | * and optionally stopping at the beginning of a variable. | ||||
*/ | */ | ||||
static ssize_t | static ssize_t | ||||
text2lval(size_t triml, size_t trimr, int tovar) | text2lval(size_t triml, size_t trimr, int tovar, YYSTYPE *yylval, | ||||
yyscan_t scanner) | |||||
{ | { | ||||
char *d; | char *d; | ||||
const char *s, *se; | const char *s, *se; | ||||
yylval.cs = d = emalloc(yyleng - trimr - triml + 1); | struct yyguts_t *yyg = scanner; | ||||
yylval->cs = d = emalloc(yyleng - trimr - triml + 1); | |||||
se = yytext + (yyleng - trimr); | se = yytext + (yyleng - trimr); | ||||
for (s = yytext + triml; s < se; s++, d++) { | for (s = yytext + triml; s < se; s++, d++) { | ||||
if (*s != '\\') { | if (*s != '\\') { | ||||
if (tovar && *s == '$') { | if (tovar && *s == '$') { | ||||
*d = '\0'; | *d = '\0'; | ||||
return s - yytext; | return s - yytext; | ||||
} | } | ||||
if (*s == '\n') | |||||
lineno++; | |||||
*d = *s; | *d = *s; | ||||
continue; | continue; | ||||
} | } | ||||
s++; | s++; | ||||
if (*s >= '0' && *s <= '7') { | if (*s >= '0' && *s <= '7') { | ||||
*d = *s - '0'; | *d = *s - '0'; | ||||
if (s + 1 < se && s[1] >= '0' && s[1] <= '7') { | if (s + 1 < se && s[1] >= '0' && s[1] <= '7') { | ||||
*d = 010 * *d + (*++s - '0'); | *d = 010 * *d + (*++s - '0'); | ||||
if (s + 1 < se && s[1] >= '0' && s[1] <= '7') | if (s + 1 < se && s[1] >= '0' && s[1] <= '7') | ||||
*d = 010 * *d + (*++s - '0'); | *d = 010 * *d + (*++s - '0'); | ||||
} | } | ||||
continue; | continue; | ||||
} | } | ||||
switch (*s) { | switch (*s) { | ||||
case 'a': *d = '\a'; break; | case 'a': *d = '\a'; break; | ||||
case 'b': *d = '\b'; break; | case 'b': *d = '\b'; break; | ||||
case 'f': *d = '\f'; break; | case 'f': *d = '\f'; break; | ||||
case 'n': *d = '\n'; break; | case 'n': *d = '\n'; break; | ||||
case 'r': *d = '\r'; break; | case 'r': *d = '\r'; break; | ||||
case 't': *d = '\t'; break; | case 't': *d = '\t'; break; | ||||
case 'v': *d = '\v'; break; | case 'v': *d = '\v'; break; | ||||
case '\n': d--; lineno++; break; | |||||
default: *d = *s; break; | default: *d = *s; break; | ||||
case '\n': d--; break; | |||||
case 'x': | case 'x': | ||||
*d = 0; | *d = 0; | ||||
if (s + 1 >= se) | if (s + 1 >= se) | ||||
break; | break; | ||||
if (s[1] >= '0' && s[1] <= '9') | if (s[1] >= '0' && s[1] <= '9') | ||||
*d = *++s - '0'; | *d = *++s - '0'; | ||||
else if (s[1] >= 'A' && s[1] <= 'F') | else if (s[1] >= 'A' && s[1] <= 'F') | ||||
*d = *++s + (0xA - 'A'); | *d = *++s + (0xA - 'A'); | ||||
Show All 17 Lines |