mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-08-22 01:57:43 +00:00
This conversion is nothing more than what is required to get it to compile. Further improvements will come as the code is refactored. Unfortunately due to C++ not supporting designated initializers, the auto generation of af names needed to be reworked, and "netlink" and "unix" domain socket keywords leaked in. Since these where going to be added in separate patches I have not bothered to do the extra work to replace them with a temporary place holder. Signed-off-by: John Johansen <john.johansen@canonical.com> [tyhicks: merged with dbus changes and memory leak fixes] Signed-off-by: Tyler Hicks <tyhicks@canonical.com> Acked-by: Seth Arnold <seth.arnold@canonical.com> Acked-by: Steve Beattie <steve@nxnw.org>
653 lines
14 KiB
Plaintext
653 lines
14 KiB
Plaintext
/*
|
|
* Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
|
|
* NOVELL (All rights reserved)
|
|
* Copyright (c) 2010 - 2012
|
|
* Canonical Ltd.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of version 2 of the GNU General Public
|
|
* License published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, contact Canonical, Ltd.
|
|
*/
|
|
|
|
/* Definitions section */
|
|
/* %option main */
|
|
|
|
/* eliminates need to link with libfl */
|
|
%option noyywrap
|
|
%option nounput
|
|
%option stack
|
|
|
|
%{
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <libintl.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
#include <dirent.h>
|
|
#define _(s) gettext(s)
|
|
|
|
#include "parser.h"
|
|
#include "parser_include.h"
|
|
#include "parser_yacc.h"
|
|
#include "lib.h"
|
|
|
|
#ifdef PDEBUG
|
|
#undef PDEBUG
|
|
#endif
|
|
/* #define DEBUG */
|
|
#ifdef DEBUG
|
|
static int yy_top_state(void);
|
|
#define PDEBUG(fmt, args...) printf("Lexer (Line %d) (state %s): " fmt, current_lineno, state_names[YY_START], ## args)
|
|
#else
|
|
#define PDEBUG(fmt, args...) /* Do nothing */
|
|
#endif
|
|
#define NPDEBUG(fmt, args...) /* Do nothing */
|
|
|
|
#define DUMP_PREPROCESS do { if (preprocess_only) ECHO; } while (0)
|
|
|
|
#define DUMP_AND_DEBUG(X...) \
|
|
do { \
|
|
DUMP_PREPROCESS; \
|
|
PDEBUG(X); \
|
|
} while (0)
|
|
|
|
#define EAT_TOKEN(X...) DUMP_AND_DEBUG(X)
|
|
|
|
#define RETURN_TOKEN(X) \
|
|
do { \
|
|
DUMP_AND_DEBUG("Matched: %s\n", yytext); \
|
|
return (X); \
|
|
} while (0)
|
|
|
|
#define POP() \
|
|
do { \
|
|
DUMP_AND_DEBUG(" (pop_to(%s)): Matched: %s\n", state_names[yy_top_state()], yytext); \
|
|
yy_pop_state(); \
|
|
} while (0)
|
|
|
|
#define PUSH(X) \
|
|
do { \
|
|
DUMP_AND_DEBUG(" (push(%s)): Matched: %s\n", state_names[(X)], yytext); \
|
|
yy_push_state(X); \
|
|
} while (0)
|
|
|
|
#define POP_AND_RETURN(X) \
|
|
do { \
|
|
POP(); \
|
|
return (X); \
|
|
} while (0)
|
|
|
|
#define PUSH_AND_RETURN(X, Y) \
|
|
do { \
|
|
PUSH(X); \
|
|
return (Y); \
|
|
} while (0)
|
|
|
|
#define BEGIN_AND_RETURN(X, Y) \
|
|
do { \
|
|
DUMP_AND_DEBUG(" (begin(%s)): Matched: %s\n", state_names[(X)], yytext); \
|
|
BEGIN(X); \
|
|
return (Y); \
|
|
} while (0)
|
|
|
|
|
|
#define YY_NO_INPUT
|
|
|
|
#define STATE_TABLE_ENT(X) [(X)] = #X
|
|
/* static char *const state_names[]; */
|
|
|
|
struct ignored_suffix_t {
|
|
const char * text;
|
|
int len;
|
|
int silent;
|
|
};
|
|
|
|
struct ignored_suffix_t ignored_suffixes[] = {
|
|
/* Debian packging files, which are in flux during install
|
|
should be silently ignored. */
|
|
{ ".dpkg-new", 9, 1 },
|
|
{ ".dpkg-old", 9, 1 },
|
|
{ ".dpkg-dist", 10, 1 },
|
|
{ ".dpkg-bak", 9, 1 },
|
|
/* RPM packaging files have traditionally not been silently
|
|
ignored */
|
|
{ ".rpmnew", 7, 0 },
|
|
{ ".rpmsave", 8, 0 },
|
|
/* Backup files should be mentioned */
|
|
{ "~", 1, 0 },
|
|
{ NULL, 0, 0 }
|
|
};
|
|
|
|
static int is_blacklisted(const char *name, const char *path)
|
|
{
|
|
int name_len;
|
|
struct ignored_suffix_t *suffix;
|
|
name_len = strlen(name);
|
|
/* skip blacklisted suffixes */
|
|
for (suffix = ignored_suffixes; suffix->text; suffix++) {
|
|
char *found;
|
|
if ( (found = strstr((char *) name, suffix->text)) &&
|
|
found - name + suffix->len == name_len ) {
|
|
if (!suffix->silent)
|
|
PERROR("Ignoring: '%s'\n", path);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
struct cb_struct {
|
|
const char *fullpath;
|
|
const char *filename;
|
|
};
|
|
|
|
static int include_dir_cb(__unused DIR *dir, const char *name, struct stat *st,
|
|
void *data)
|
|
{
|
|
struct cb_struct *d = (struct cb_struct *) data;
|
|
|
|
char *path;
|
|
|
|
/* skip dotfiles silently. */
|
|
if (*name == '.')
|
|
return 0;
|
|
|
|
if (asprintf(&path, "%s/%s", d->fullpath, name) < 0)
|
|
yyerror("Out of memory");
|
|
|
|
if (is_blacklisted(name, path))
|
|
return 0;
|
|
|
|
if (S_ISREG(st->st_mode)) {
|
|
if (!(yyin = fopen(path,"r")))
|
|
yyerror(_("Could not open '%s' in '%s'"), path, d->filename);
|
|
PDEBUG("Opened include \"%s\" in \"%s\"\n", path, d->filename);
|
|
update_mru_tstamp(yyin);
|
|
push_include_stack(path);
|
|
yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE));
|
|
}
|
|
|
|
free(path);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void include_filename(char *filename, int search)
|
|
{
|
|
FILE *include_file = NULL;
|
|
struct stat my_stat;
|
|
char *fullpath = NULL;
|
|
|
|
if (search) {
|
|
if (preprocess_only)
|
|
fprintf(yyout, "\n\n##included <%s>\n", filename);
|
|
include_file = search_path(filename, &fullpath);
|
|
} else {
|
|
if (preprocess_only)
|
|
fprintf(yyout, "\n\n##included \"%s\"\n", filename);
|
|
fullpath = strdup(filename);
|
|
include_file = fopen(fullpath, "r");
|
|
}
|
|
|
|
if (!include_file)
|
|
yyerror(_("Could not open '%s'"),
|
|
fullpath ? fullpath: filename);
|
|
|
|
if (fstat(fileno(include_file), &my_stat))
|
|
yyerror(_("fstat failed for '%s'"), fullpath);
|
|
|
|
if (S_ISREG(my_stat.st_mode)) {
|
|
yyin = include_file;
|
|
update_mru_tstamp(include_file);
|
|
PDEBUG("Opened include \"%s\"\n", fullpath);
|
|
push_include_stack(fullpath);
|
|
yypush_buffer_state(yy_create_buffer( yyin, YY_BUF_SIZE ));
|
|
} else if (S_ISDIR(my_stat.st_mode)) {
|
|
struct cb_struct data = { fullpath, filename };
|
|
fclose(include_file);
|
|
include_file = NULL;
|
|
if (dirat_for_each(NULL, fullpath, &data, include_dir_cb)) {
|
|
yyerror(_("Could not process include directory"
|
|
" '%s' in '%s'"), fullpath, filename);;
|
|
}
|
|
}
|
|
|
|
if (fullpath)
|
|
free(fullpath);
|
|
}
|
|
|
|
%}
|
|
|
|
CARET "^"
|
|
OPEN_BRACE \{
|
|
CLOSE_BRACE \}
|
|
SLASH \/
|
|
COLON :
|
|
END_OF_RULE [,]
|
|
RANGE -
|
|
MODE_CHARS ([RrWwaLlMmkXx])|(([Pp]|[Cc])[Xx])|(([Pp]|[Cc])?([IiUu])[Xx])
|
|
MODES {MODE_CHARS}+
|
|
WS [[:blank:]]
|
|
NUMBER [[:digit:]]+
|
|
|
|
ID_CHARS [^ \t\n"!,]
|
|
ID {ID_CHARS}|(,{ID_CHARS})
|
|
IDS {ID}+
|
|
POST_VAR_ID_CHARS [^ \t\n"!,]{-}[=\+]
|
|
POST_VAR_ID {POST_VAR_ID_CHARS}|(,{POST_VAR_ID_CHARS})
|
|
LIST_VALUE_ID_CHARS [^ \t\n"!,]{-}[()]
|
|
LIST_VALUE_ID {LIST_VALUE_ID_CHARS}+
|
|
QUOTED_LIST_VALUE_ID {LIST_VALUE_ID}|\"{LIST_VALUE_ID}\"
|
|
ID_CHARS_NOEQ [^ \t\n"!,]{-}[=]
|
|
LEADING_ID_CHARS_NOEQ [^ \t\n"!,]{-}[=()+&]
|
|
ID_NOEQ {ID_CHARS_NOEQ}|(,{ID_CHARS_NOEQ})
|
|
IDS_NOEQ {LEADING_ID_CHARS_NOEQ}{ID_NOEQ}*
|
|
ALLOWED_QUOTED_ID [^\0"]|\\\"
|
|
QUOTED_ID \"{ALLOWED_QUOTED_ID}*\"
|
|
|
|
IP {NUMBER}\.{NUMBER}\.{NUMBER}\.{NUMBER}
|
|
|
|
HAT hat{WS}*
|
|
PROFILE profile{WS}*
|
|
KEYWORD [[:alpha:]_]+
|
|
VARIABLE_NAME [[:alpha:]][[:alnum:]_]*
|
|
SET_VAR_PREFIX @
|
|
SET_VARIABLE {SET_VAR_PREFIX}(\{{VARIABLE_NAME}\}|{VARIABLE_NAME})
|
|
BOOL_VARIABLE $(\{{VARIABLE_NAME}\}|{VARIABLE_NAME})
|
|
|
|
PATHNAME (\/|{SET_VARIABLE}{POST_VAR_ID}){ID}*
|
|
QPATHNAME \"(\/|{SET_VAR_PREFIX})([^\0"]|\\\")*\"
|
|
|
|
OPEN_PAREN \(
|
|
CLOSE_PAREN \)
|
|
COMMA \,
|
|
EQUALS =
|
|
ADD_ASSIGN \+=
|
|
ARROW ->
|
|
LT_EQUAL <=
|
|
|
|
/* IF adding new state please update state_names table at eof */
|
|
%x SUB_ID
|
|
%x SUB_VALUE
|
|
%x EXTCOND_MODE
|
|
%x EXTCONDLIST_MODE
|
|
%x NETWORK_MODE
|
|
%x LIST_VAL_MODE
|
|
%x LIST_COND_MODE
|
|
%x LIST_COND_VAL
|
|
%x LIST_COND_PAREN_VAL
|
|
%x ASSIGN_MODE
|
|
%x RLIMIT_MODE
|
|
%x MOUNT_MODE
|
|
%x DBUS_MODE
|
|
%x CHANGE_PROFILE_MODE
|
|
%x INCLUDE
|
|
|
|
%%
|
|
|
|
%{
|
|
/* Copied directly into yylex function */
|
|
if (parser_token) {
|
|
int t = parser_token;
|
|
parser_token = 0;
|
|
return t;
|
|
}
|
|
%}
|
|
|
|
<INITIAL,INCLUDE,LIST_VAL_MODE,EXTCOND_MODE,LIST_COND_VAL,LIST_COND_PAREN_VAL,LIST_COND_MODE,EXTCONDLIST_MODE,ASSIGN_MODE,NETWORK_MODE,CHANGE_PROFILE_MODE,RLIMIT_MODE,MOUNT_MODE,DBUS_MODE>{
|
|
{WS}+ { DUMP_PREPROCESS; /* Ignoring whitespace */ }
|
|
}
|
|
|
|
<INCLUDE>{
|
|
(\<([^\> \t\n]+)\>|\"([^\" \t\n]+)\") { /* <filename> */
|
|
char *filename = strdup(yytext);
|
|
filename[strlen(filename) - 1] = '\0';
|
|
include_filename(filename + 1, *filename == '<');
|
|
free(filename);
|
|
yy_pop_state();
|
|
}
|
|
|
|
[^\<\>\" \t\n]+ { /* filename */
|
|
include_filename(yytext, 0);
|
|
yy_pop_state();
|
|
}
|
|
}
|
|
|
|
<<EOF>> {
|
|
fclose(yyin);
|
|
pop_include_stack();
|
|
yypop_buffer_state();
|
|
if ( !YY_CURRENT_BUFFER )
|
|
yyterminate();
|
|
}
|
|
|
|
<INITIAL,MOUNT_MODE,DBUS_MODE>{
|
|
{VARIABLE_NAME}/{WS}*= {
|
|
/* we match to the = in the lexer so that we can switch scanner
|
|
* state. By the time the parser see the = it may be too late
|
|
* as bison may have requested the next token from the scanner
|
|
*/
|
|
int token = get_keyword_token(yytext);
|
|
|
|
if (token == TOK_PEER) {
|
|
PUSH_AND_RETURN(EXTCONDLIST_MODE, TOK_CONDLISTID);
|
|
} else {
|
|
yylval.id = processid(yytext, yyleng);
|
|
PUSH_AND_RETURN(EXTCOND_MODE, TOK_CONDID);
|
|
}
|
|
}
|
|
{VARIABLE_NAME}/{WS}+in{WS}*\( {
|
|
/* we match to 'in' in the lexer so that we can switch scanner
|
|
* state. By the time the parser see the 'in' it may be to
|
|
* late as bison may have requested the next token from the
|
|
* scanner
|
|
*/
|
|
yylval.id = processid(yytext, yyleng);
|
|
PUSH_AND_RETURN(EXTCOND_MODE, TOK_CONDID);
|
|
}
|
|
}
|
|
|
|
<SUB_ID>{
|
|
({IDS}|{QUOTED_ID}) {
|
|
/* Go into separate state to match generic ID strings */
|
|
yylval.id = processid(yytext, yyleng);
|
|
POP_AND_RETURN(TOK_ID);
|
|
}
|
|
}
|
|
|
|
<SUB_VALUE>{
|
|
({IDS}|{QUOTED_ID}) {
|
|
/* Go into separate state to match generic VALUE strings */
|
|
yylval.id = processid(yytext, yyleng);
|
|
POP_AND_RETURN(TOK_VALUE);
|
|
}
|
|
}
|
|
|
|
<LIST_VAL_MODE>{
|
|
{CLOSE_PAREN} { POP_AND_RETURN(TOK_CLOSEPAREN); }
|
|
|
|
{COMMA} { EAT_TOKEN("listval: ,\n"); }
|
|
|
|
({LIST_VALUE_ID}|{QUOTED_ID}) {
|
|
yylval.id = processid(yytext, yyleng);
|
|
RETURN_TOKEN(TOK_VALUE);
|
|
}
|
|
}
|
|
|
|
<EXTCOND_MODE>{
|
|
{EQUALS}{WS}*/[^(\n]{-}{WS} { BEGIN_AND_RETURN(SUB_VALUE, TOK_EQUALS);}
|
|
|
|
{EQUALS} { RETURN_TOKEN(TOK_EQUALS); }
|
|
|
|
/* Don't push state here as this is a transition start condition and
|
|
* we want to return to the start condition that invoked <EXTCOND_MODE>
|
|
* when LIST_VAL_ID is done
|
|
*/
|
|
{OPEN_PAREN} { BEGIN_AND_RETURN(LIST_VAL_MODE, TOK_OPENPAREN); }
|
|
|
|
in { RETURN_TOKEN(TOK_IN); }
|
|
}
|
|
|
|
<LIST_COND_VAL>{
|
|
({LIST_VALUE_ID}|{QUOTED_LIST_VALUE_ID}) {
|
|
yylval.id = processid(yytext, yyleng);
|
|
POP_AND_RETURN(TOK_VALUE);
|
|
}
|
|
}
|
|
|
|
<LIST_COND_PAREN_VAL>{
|
|
{CLOSE_PAREN} { POP(); }
|
|
|
|
({LIST_VALUE_ID}|{QUOTED_LIST_VALUE_ID}) {
|
|
yylval.id = processid(yytext, yyleng);
|
|
RETURN_TOKEN(TOK_VALUE);
|
|
}
|
|
}
|
|
|
|
<LIST_COND_MODE>{
|
|
{CLOSE_PAREN} { POP_AND_RETURN(TOK_CLOSEPAREN); }
|
|
|
|
{COMMA} { EAT_TOKEN("listcond: , \n"); }
|
|
|
|
{ID_CHARS_NOEQ}+ {
|
|
yylval.id = processid(yytext, yyleng);
|
|
RETURN_TOKEN(TOK_CONDID);
|
|
}
|
|
|
|
{EQUALS}{WS}*{OPEN_PAREN} {
|
|
PUSH_AND_RETURN(LIST_COND_PAREN_VAL, TOK_EQUALS);
|
|
}
|
|
|
|
{EQUALS} {
|
|
PUSH_AND_RETURN(LIST_COND_VAL, TOK_EQUALS);
|
|
}
|
|
}
|
|
|
|
<EXTCONDLIST_MODE>{
|
|
{EQUALS} { RETURN_TOKEN(TOK_EQUALS); }
|
|
|
|
{OPEN_PAREN} {
|
|
/* Don't push state here as this is a transition
|
|
* start condition and we want to return to the start
|
|
* condition that invoked <EXTCONDLIST_MODE> when
|
|
* LIST_VAL_ID is done
|
|
*/
|
|
BEGIN_AND_RETURN(LIST_COND_MODE, TOK_OPENPAREN);
|
|
}
|
|
}
|
|
|
|
<ASSIGN_MODE>{
|
|
({IDS}|{QUOTED_ID}) {
|
|
yylval.var_val = processid(yytext, yyleng);
|
|
RETURN_TOKEN(TOK_VALUE);
|
|
}
|
|
|
|
{END_OF_RULE} {
|
|
yylval.id = strdup(yytext);
|
|
DUMP_PREPROCESS;
|
|
yyerror(_("Variable declarations do not accept trailing commas"));
|
|
}
|
|
|
|
\\\n { DUMP_PREPROCESS; current_lineno++ ; }
|
|
|
|
\r?\n {
|
|
DUMP_PREPROCESS;
|
|
current_lineno++;
|
|
yy_pop_state();
|
|
}
|
|
}
|
|
|
|
<NETWORK_MODE>{
|
|
{IDS} {
|
|
yylval.id = strdup(yytext);
|
|
RETURN_TOKEN(TOK_ID);
|
|
}
|
|
}
|
|
|
|
<CHANGE_PROFILE_MODE>{
|
|
{ARROW} { RETURN_TOKEN(TOK_ARROW); }
|
|
|
|
({IDS}|{QUOTED_ID}) {
|
|
yylval.id = processid(yytext, yyleng);
|
|
POP_AND_RETURN(TOK_ID);
|
|
}
|
|
}
|
|
|
|
<RLIMIT_MODE>{
|
|
-?{NUMBER}[[:alpha:]]* {
|
|
yylval.var_val = strdup(yytext);
|
|
RETURN_TOKEN(TOK_VALUE);
|
|
}
|
|
|
|
{KEYWORD} {
|
|
yylval.id = strdup(yytext);
|
|
if (strcmp(yytext, "infinity") == 0)
|
|
RETURN_TOKEN(TOK_VALUE);
|
|
RETURN_TOKEN(TOK_ID);
|
|
}
|
|
|
|
{LT_EQUAL} { RETURN_TOKEN(TOK_LE); }
|
|
}
|
|
|
|
<DBUS_MODE>{
|
|
send { RETURN_TOKEN(TOK_SEND); }
|
|
receive { RETURN_TOKEN(TOK_RECEIVE); }
|
|
bind { RETURN_TOKEN(TOK_BIND); }
|
|
read { RETURN_TOKEN(TOK_READ); }
|
|
write { RETURN_TOKEN(TOK_WRITE); }
|
|
{OPEN_PAREN} {
|
|
yy_push_state(LIST_VAL_MODE);
|
|
RETURN_TOKEN(TOK_OPENPAREN);
|
|
}
|
|
(r|w|rw|wr)/([[:space:],]) {
|
|
yylval.mode = strdup(yytext);
|
|
RETURN_TOKEN(TOK_MODE);
|
|
}
|
|
}
|
|
|
|
<MOUNT_MODE,DBUS_MODE>{
|
|
{ARROW} { RETURN_TOKEN(TOK_ARROW); }
|
|
|
|
({IDS_NOEQ}|{PATHNAME}|{QUOTED_ID}) {
|
|
yylval.id = processid(yytext, yyleng);
|
|
RETURN_TOKEN(TOK_ID);
|
|
}
|
|
}
|
|
|
|
#include/.*\r?\n { PUSH(INCLUDE); }
|
|
|
|
#.*\r?\n { /* normal comment */
|
|
DUMP_AND_DEBUG("comment(%d): %s\n", current_lineno, yytext);
|
|
current_lineno++;
|
|
}
|
|
|
|
{CARET} { PUSH_AND_RETURN(SUB_ID, TOK_CARET); }
|
|
|
|
{ARROW} { RETURN_TOKEN(TOK_ARROW); }
|
|
|
|
{EQUALS} { PUSH_AND_RETURN(ASSIGN_MODE, TOK_EQUALS); }
|
|
|
|
{ADD_ASSIGN} { PUSH_AND_RETURN(ASSIGN_MODE, TOK_ADD_ASSIGN); }
|
|
|
|
{SET_VARIABLE} {
|
|
yylval.set_var = strdup(yytext);
|
|
RETURN_TOKEN(TOK_SET_VAR);
|
|
}
|
|
|
|
{BOOL_VARIABLE} {
|
|
yylval.bool_var = strdup(yytext);
|
|
RETURN_TOKEN(TOK_BOOL_VAR);
|
|
}
|
|
|
|
{OPEN_BRACE} { RETURN_TOKEN(TOK_OPEN); }
|
|
|
|
{CLOSE_BRACE} { RETURN_TOKEN(TOK_CLOSE); }
|
|
|
|
({PATHNAME}|{QPATHNAME}) {
|
|
yylval.id = processid(yytext, yyleng);
|
|
RETURN_TOKEN(TOK_ID);
|
|
}
|
|
|
|
({MODES})/([[:space:],]) {
|
|
yylval.mode = strdup(yytext);
|
|
RETURN_TOKEN(TOK_MODE);
|
|
}
|
|
|
|
{HAT} { PUSH_AND_RETURN(SUB_ID, TOK_HAT); }
|
|
|
|
{PROFILE} { PUSH_AND_RETURN(SUB_ID, TOK_PROFILE); }
|
|
|
|
{COLON} { RETURN_TOKEN(TOK_COLON); }
|
|
|
|
{OPEN_PAREN} { PUSH_AND_RETURN(LIST_VAL_MODE, TOK_OPENPAREN); }
|
|
|
|
{VARIABLE_NAME} {
|
|
DUMP_PREPROCESS;
|
|
int token = get_keyword_token(yytext);
|
|
int state = INITIAL;
|
|
|
|
/* special cases */
|
|
switch (token) {
|
|
case -1:
|
|
/* no token found */
|
|
yylval.id = processunquoted(yytext, yyleng);
|
|
RETURN_TOKEN(TOK_ID);
|
|
break;
|
|
case TOK_RLIMIT:
|
|
state = RLIMIT_MODE;
|
|
break;
|
|
case TOK_NETWORK:
|
|
state = NETWORK_MODE;
|
|
break;
|
|
case TOK_CHANGE_PROFILE:
|
|
state = CHANGE_PROFILE_MODE;
|
|
break;
|
|
case TOK_MOUNT:
|
|
case TOK_REMOUNT:
|
|
case TOK_UMOUNT:
|
|
state = MOUNT_MODE;
|
|
break;
|
|
case TOK_DBUS:
|
|
state = DBUS_MODE;
|
|
break;
|
|
default: /* nothing */
|
|
break;
|
|
}
|
|
PUSH_AND_RETURN(state, token);
|
|
}
|
|
|
|
<INITIAL,NETWORK_MODE,RLIMIT_MODE,MOUNT_MODE,DBUS_MODE>{
|
|
{END_OF_RULE} {
|
|
if (YY_START != INITIAL)
|
|
yy_pop_state();
|
|
RETURN_TOKEN(TOK_END_OF_RULE);
|
|
}
|
|
|
|
\r?\n {
|
|
DUMP_PREPROCESS;
|
|
current_lineno++;
|
|
}
|
|
}
|
|
|
|
<INITIAL,SUB_ID,SUB_VALUE,LIST_VAL_MODE,EXTCOND_MODE,LIST_COND_VAL,LIST_COND_PAREN_VAL,LIST_COND_MODE,EXTCONDLIST_MODE,ASSIGN_MODE,NETWORK_MODE,CHANGE_PROFILE_MODE,MOUNT_MODE,DBUS_MODE>{
|
|
[^\n] {
|
|
DUMP_PREPROCESS;
|
|
/* Something we didn't expect */
|
|
yyerror(_("Found unexpected character: '%s'"), yytext);
|
|
}
|
|
}
|
|
%%
|
|
|
|
/* Create a table mapping lexer state number to the name used in the
|
|
* in the code. This allows for better debug output
|
|
*/
|
|
static const char *const state_names[] = {
|
|
STATE_TABLE_ENT(INITIAL),
|
|
STATE_TABLE_ENT(SUB_ID),
|
|
STATE_TABLE_ENT(SUB_VALUE),
|
|
STATE_TABLE_ENT(EXTCOND_MODE),
|
|
STATE_TABLE_ENT(EXTCONDLIST_MODE),
|
|
STATE_TABLE_ENT(NETWORK_MODE),
|
|
STATE_TABLE_ENT(LIST_VAL_MODE),
|
|
STATE_TABLE_ENT(LIST_COND_MODE),
|
|
STATE_TABLE_ENT(LIST_COND_VAL),
|
|
STATE_TABLE_ENT(LIST_COND_PAREN_VAL),
|
|
STATE_TABLE_ENT(ASSIGN_MODE),
|
|
STATE_TABLE_ENT(RLIMIT_MODE),
|
|
STATE_TABLE_ENT(MOUNT_MODE),
|
|
STATE_TABLE_ENT(DBUS_MODE),
|
|
STATE_TABLE_ENT(CHANGE_PROFILE_MODE),
|
|
STATE_TABLE_ENT(INCLUDE),
|
|
};
|