iproute2/tc/emp_ematch.l
Wolfgang Bumiller 7ac29190db tc/lexer: let quotes actually start strings
The lexer will go with the longest match, so previously
the starting double quotes of a string would be swallowed by
the [^ \t\r\n()]+ pattern leaving the user no way to
actually use strings with escape sequences.
Fix this by not allowing this case to start with double
quotes.

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
2018-01-24 08:49:10 -08:00

147 lines
3.4 KiB
Plaintext

/* SPDX-License-Identifier: GPL-2.0 */
%{
#include "emp_ematch.yacc.h"
#include "m_ematch.h"
extern int ematch_argc;
extern char **ematch_argv;
#define yylval ematch_lval
#define NEXT_EM_ARG() do { ematch_argc--; ematch_argv++; } while(0);
#define YY_INPUT(buf, result, max_size) \
{ \
next: \
if (ematch_argc <= 0) \
result = YY_NULL; \
else if (**ematch_argv == '\0') { \
NEXT_EM_ARG(); \
goto next; \
} else { \
if (max_size <= strlen(*ematch_argv) + 1) { \
fprintf(stderr, "match argument too long.\n"); \
result = YY_NULL; \
} else { \
strcpy(buf, *ematch_argv); \
result = strlen(*ematch_argv) + 1; \
buf[result-1] = ' '; \
buf[result] = '\0'; \
NEXT_EM_ARG(); \
} \
} \
}
static void __attribute__ ((unused)) yyunput (int c,char *buf_ptr );
static void __attribute__ ((unused)) yy_push_state (int new_state );
static void __attribute__ ((unused)) yy_pop_state (void);
static int __attribute__ ((unused)) yy_top_state (void );
static char *strbuf;
static unsigned int strbuf_size;
static unsigned int strbuf_index;
static void strbuf_enlarge(void)
{
strbuf_size += 512;
strbuf = realloc(strbuf, strbuf_size);
}
static void strbuf_append_char(char c)
{
while (strbuf_index >= strbuf_size)
strbuf_enlarge();
strbuf[strbuf_index++] = c;
}
static void strbuf_append_charp(char *s)
{
while (strbuf_index >= strbuf_size)
strbuf_enlarge();
memcpy(strbuf + strbuf_index, s, strlen(s));
strbuf_index += strlen(s);
}
%}
%x lexstr
%option 8bit stack warn noyywrap prefix="ematch_"
%%
[ \t\r\n]+
\" {
if (strbuf == NULL) {
strbuf_size = 512;
strbuf = calloc(1, strbuf_size);
if (strbuf == NULL)
return ERROR;
}
strbuf_index = 0;
BEGIN(lexstr);
}
<lexstr>\" {
BEGIN(INITIAL);
yylval.b = bstr_new(strbuf, strbuf_index);
yylval.b->quoted = 1;
return ATTRIBUTE;
}
<lexstr>\\[0-7]{1,3} { /* octal escape sequence */
int res;
sscanf(yytext + 1, "%o", &res);
if (res > 0xFF) {
fprintf(stderr, "error: octal escape sequence" \
" out of range\n");
return ERROR;
}
strbuf_append_char((unsigned char) res);
}
<lexstr>\\[0-9]+ { /* catch wrong octal escape seq. */
fprintf(stderr, "error: invalid octale escape sequence\n");
return ERROR;
}
<lexstr>\\x[0-9a-fA-F]{1,2} {
int res;
sscanf(yytext + 2, "%x", &res);
if (res > 0xFF) {
fprintf(stderr, "error: hexadecimal escape " \
"sequence out of range\n");
return ERROR;
}
strbuf_append_char((unsigned char) res);
}
<lexstr>\\n strbuf_append_char('\n');
<lexstr>\\r strbuf_append_char('\r');
<lexstr>\\t strbuf_append_char('\t');
<lexstr>\\v strbuf_append_char('\v');
<lexstr>\\b strbuf_append_char('\b');
<lexstr>\\f strbuf_append_char('\f');
<lexstr>\\a strbuf_append_char('\a');
<lexstr>\\(.|\n) strbuf_append_char(yytext[1]);
<lexstr>[^\\\n\"]+ strbuf_append_charp(yytext);
[aA][nN][dD] return AND;
[oO][rR] return OR;
[nN][oO][tT] return NOT;
"(" |
")" {
return yylval.i = *yytext;
}
[^" \t\r\n()][^ \t\r\n()]* {
yylval.b = bstr_alloc(yytext);
if (yylval.b == NULL)
return ERROR;
return ATTRIBUTE;
}
%%