mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
389 lines
9.1 KiB
LLVM
389 lines
9.1 KiB
LLVM
%top{
|
|
// Include stdint.h at the start of the generated file. Typically
|
|
// MSVC will include this header later, after the definitions of
|
|
// the integral type macros. MSVC then complains that about the
|
|
// redefinition of the types. Including stdint.h early avoids this.
|
|
#include <stdint.h>
|
|
}
|
|
|
|
%{
|
|
#include "pac_action.h"
|
|
#include "pac_array.h"
|
|
#include "pac_attr.h"
|
|
#include "pac_case.h"
|
|
#include "pac_common.h"
|
|
#include "pac_conn.h"
|
|
#include "pac_dataptr.h"
|
|
#include "pac_dataunit.h"
|
|
#include "pac_dbg.h"
|
|
#include "pac_decl.h"
|
|
#include "pac_exception.h"
|
|
#include "pac_expr.h"
|
|
#include "pac_flow.h"
|
|
#include "pac_id.h"
|
|
#include "pac_nullptr.h"
|
|
#include "pac_number.h"
|
|
#include "pac_output.h"
|
|
#include "pac_param.h"
|
|
#include "pac_parse.h"
|
|
#include "pac_record.h"
|
|
#include "pac_type.h"
|
|
#include "pac_utils.h"
|
|
|
|
#include <errno.h>
|
|
#include <string_view>
|
|
|
|
#ifdef _MSC_VER
|
|
#include <filesystem>
|
|
#else
|
|
#include <libgen.h>
|
|
#include <memory>
|
|
#endif
|
|
|
|
int line_number = 1;
|
|
|
|
int begin_pac_primitive(int tok);
|
|
int end_pac_primitive();
|
|
|
|
int string_token(int tok) {
|
|
yylval.str = copy_string(yytext);
|
|
return tok;
|
|
}
|
|
|
|
int char_token(int tok) {
|
|
yylval.val = yytext[0];
|
|
return tok;
|
|
}
|
|
|
|
void include_file(const char* filename);
|
|
|
|
std::string do_dirname(std::string_view s) {
|
|
#ifdef _MSC_VER
|
|
return std::filesystem::path(s).parent_path().string();
|
|
#else
|
|
std::unique_ptr<char[]> tmp{new char[s.size() + 1]};
|
|
strncpy(tmp.get(), s.data(), s.size());
|
|
tmp[s.size()] = '\0';
|
|
|
|
char* dn = dirname(tmp.get());
|
|
if ( ! dn )
|
|
return "";
|
|
|
|
std::string res{dn};
|
|
|
|
return res;
|
|
#endif
|
|
}
|
|
|
|
%}
|
|
|
|
/* EC -- embedded code state */
|
|
/* PP -- PAC primitive state */
|
|
/* INCL -- @include line */
|
|
|
|
%s EC INCL PP RE
|
|
|
|
WS [ \t]+
|
|
ID [A-Za-z_][A-Za-z_0-9]*
|
|
D [0-9]+
|
|
HEX [0-9a-fA-F]+
|
|
FILE [^ \t\n]+
|
|
ESCSEQ (\\([^\n]|[0-7]{3}|x[[:xdigit:]]{2}))
|
|
|
|
%option nounput
|
|
|
|
%%
|
|
|
|
<INITIAL>"%include" {
|
|
BEGIN(INCL);
|
|
}
|
|
|
|
<INCL>{WS} /* skip whitespace */
|
|
|
|
<INCL>{FILE} {
|
|
BEGIN(INITIAL);
|
|
include_file(yytext);
|
|
}
|
|
|
|
<INITIAL>"%extern{" {
|
|
BEGIN(EC);
|
|
return TOK_LPB_EXTERN;
|
|
}
|
|
<INITIAL>"%header{" {
|
|
BEGIN(EC);
|
|
return TOK_LPB_HEADER;
|
|
}
|
|
<INITIAL>"%code{" {
|
|
BEGIN(EC);
|
|
return TOK_LPB_CODE;
|
|
}
|
|
<INITIAL>"%init{" {
|
|
BEGIN(EC);
|
|
return TOK_LPB_INIT;
|
|
}
|
|
<INITIAL>"%cleanup{" {
|
|
BEGIN(EC);
|
|
return TOK_LPB_CLEANUP;
|
|
}
|
|
<INITIAL>"%member{" {
|
|
BEGIN(EC);
|
|
return TOK_LPB_MEMBER;
|
|
}
|
|
<INITIAL>"%eof{" {
|
|
BEGIN(EC);
|
|
return TOK_LPB_EOF;
|
|
}
|
|
<INITIAL>"%{" {
|
|
BEGIN(EC);
|
|
return TOK_LPB;
|
|
}
|
|
<EC>"%}" {
|
|
BEGIN(INITIAL);
|
|
return TOK_RPB;
|
|
}
|
|
|
|
<EC>"${" return begin_pac_primitive(TOK_PAC_VAL);
|
|
<EC>"$set{" return begin_pac_primitive(TOK_PAC_SET);
|
|
<EC>"$type{" return begin_pac_primitive(TOK_PAC_TYPE);
|
|
<EC>"$typeof{" return begin_pac_primitive(TOK_PAC_TYPEOF);
|
|
<EC>"$const_def{" return begin_pac_primitive(TOK_PAC_CONST_DEF);
|
|
|
|
<EC>"//".* return string_token(TOK_EMBEDDED_STRING);
|
|
<EC>. return char_token(TOK_EMBEDDED_ATOM);
|
|
<EC>\n { ++line_number; return char_token(TOK_EMBEDDED_ATOM); }
|
|
|
|
<PP>"}" return end_pac_primitive();
|
|
|
|
<INITIAL,PP>\n ++line_number;
|
|
<INITIAL>#.* /* eat comments */
|
|
<INITIAL,PP>{WS} /* eat whitespace */
|
|
|
|
<INITIAL>"RE/" {
|
|
BEGIN(RE);
|
|
return TOK_BEGIN_RE;
|
|
}
|
|
|
|
<RE>([^/\\\n]|{ESCSEQ})+ return string_token(TOK_REGEX);
|
|
|
|
<RE>"/" {
|
|
BEGIN(INITIAL);
|
|
return TOK_END_RE;
|
|
}
|
|
|
|
<RE>[\\\n] return yytext[0];
|
|
|
|
<INITIAL>analyzer return TOK_ANALYZER;
|
|
<INITIAL>enum return TOK_ENUM;
|
|
<INITIAL>extern return TOK_EXTERN;
|
|
<INITIAL>flow return TOK_FLOW;
|
|
<INITIAL>function return TOK_FUNCTION;
|
|
<INITIAL>let return TOK_LET;
|
|
<INITIAL>refine return TOK_REFINE;
|
|
<INITIAL>type return TOK_TYPE;
|
|
|
|
<INITIAL>align return TOK_ALIGN;
|
|
<INITIAL>case return TOK_CASE;
|
|
<INITIAL>casefunc return TOK_CASEFUNC;
|
|
<INITIAL>casetype return TOK_CASETYPE;
|
|
<INITIAL>connection return TOK_CONNECTION;
|
|
<INITIAL>datagram {
|
|
yylval.val = AnalyzerDataUnit::DATAGRAM;
|
|
return TOK_DATAUNIT;
|
|
}
|
|
<INITIAL>default return TOK_DEFAULT;
|
|
<INITIAL>downflow {
|
|
yylval.val = AnalyzerFlow::DOWN;
|
|
return TOK_FLOWDIR;
|
|
}
|
|
<INITIAL>flowunit {
|
|
yylval.val = AnalyzerDataUnit::FLOWUNIT;
|
|
return TOK_DATAUNIT;
|
|
}
|
|
<INITIAL>nullptr {
|
|
yylval.nullp = new Nullptr();
|
|
return TOK_NULLPTR;
|
|
}
|
|
<INITIAL>of return TOK_OF;
|
|
<INITIAL>offsetof return TOK_OFFSETOF;
|
|
<INITIAL>padding return TOK_PADDING;
|
|
<INITIAL>record return TOK_RECORD;
|
|
<INITIAL>sizeof return TOK_SIZEOF;
|
|
<INITIAL>to return TOK_TO;
|
|
<INITIAL>typeattr return TOK_TYPEATTR;
|
|
<INITIAL>upflow {
|
|
yylval.val = AnalyzerFlow::UP;
|
|
return TOK_FLOWDIR;
|
|
}
|
|
<INITIAL>withcontext return TOK_WITHCONTEXT;
|
|
<INITIAL>withinput return TOK_WITHINPUT;
|
|
|
|
<INITIAL>&also return TOK_ATTR_ALSO;
|
|
<INITIAL>&byteorder return TOK_ATTR_BYTEORDER;
|
|
<INITIAL>&check {
|
|
fprintf(stderr,
|
|
"warning in %s:%d: &check is a deprecated no-op, use &enforce\n",
|
|
input_filename.c_str(), line_number);
|
|
return TOK_ATTR_CHECK;
|
|
}
|
|
<INITIAL>&chunked return TOK_ATTR_CHUNKED;
|
|
<INITIAL>&enforce return TOK_ATTR_ENFORCE;
|
|
<INITIAL>&exportsourcedata return TOK_ATTR_EXPORTSOURCEDATA;
|
|
<INITIAL>&if return TOK_ATTR_IF;
|
|
<INITIAL>&length return TOK_ATTR_LENGTH;
|
|
<INITIAL>&let return TOK_ATTR_LET;
|
|
<INITIAL>&linebreaker return TOK_ATTR_LINEBREAKER;
|
|
<INITIAL>&oneline return TOK_ATTR_ONELINE;
|
|
<INITIAL>&refcount return TOK_ATTR_REFCOUNT;
|
|
<INITIAL>&requires return TOK_ATTR_REQUIRES;
|
|
<INITIAL>&restofdata return TOK_ATTR_RESTOFDATA;
|
|
<INITIAL>&restofflow return TOK_ATTR_RESTOFFLOW;
|
|
<INITIAL>&transient return TOK_ATTR_TRANSIENT;
|
|
<INITIAL>&until return TOK_ATTR_UNTIL;
|
|
|
|
<INITIAL,PP>"0x"{HEX} {
|
|
int n;
|
|
sscanf(yytext + 2, "%x", &n);
|
|
yylval.num = new Number(yytext, n);
|
|
return TOK_NUMBER;
|
|
}
|
|
|
|
<INITIAL,PP>{D} {
|
|
int n;
|
|
sscanf(yytext, "%d", &n);
|
|
yylval.num = new Number(yytext, n);
|
|
return TOK_NUMBER;
|
|
}
|
|
|
|
<INITIAL,PP>{ID}(::{ID})* {
|
|
yylval.id = new ID(yytext);
|
|
return TOK_ID;
|
|
}
|
|
|
|
<INITIAL>"$"{ID} {
|
|
yylval.id = new ID(yytext);
|
|
return TOK_ID;
|
|
}
|
|
|
|
<INITIAL>\"([^\\\n\"]|{ESCSEQ})*\" return string_token(TOK_STRING);
|
|
|
|
<INITIAL,PP>"==" return TOK_EQUAL;
|
|
<INITIAL,PP>"!=" return TOK_NEQ;
|
|
<INITIAL,PP>">=" return TOK_GE;
|
|
<INITIAL,PP>"<=" return TOK_LE;
|
|
<INITIAL,PP>"<<" return TOK_LSHIFT;
|
|
<INITIAL,PP>">>" return TOK_RSHIFT;
|
|
<INITIAL,PP>"&&" return TOK_AND;
|
|
<INITIAL,PP>"||" return TOK_OR;
|
|
<INITIAL,PP>"+=" return TOK_PLUSEQ;
|
|
<INITIAL>"->" return TOK_RIGHTARROW;
|
|
|
|
<INITIAL,PP>[\.!%*/+\-&|\^,:;<=>?()\[\]{}~] return yytext[0];
|
|
|
|
%%
|
|
|
|
void begin_RE() {
|
|
BEGIN(RE);
|
|
}
|
|
|
|
void end_RE() { BEGIN(INITIAL); }
|
|
|
|
// The DECL state is deprecated
|
|
void begin_decl() {
|
|
// BEGIN(DECL);
|
|
}
|
|
|
|
void end_decl() {
|
|
// BEGIN(INITIAL);
|
|
}
|
|
|
|
int begin_pac_primitive(int tok) {
|
|
BEGIN(PP);
|
|
return tok;
|
|
}
|
|
|
|
int end_pac_primitive() {
|
|
BEGIN(EC);
|
|
return TOK_END_PAC;
|
|
}
|
|
|
|
constexpr int MAX_INCLUDE_DEPTH = 100;
|
|
|
|
struct IncludeState {
|
|
YY_BUFFER_STATE yystate;
|
|
string input_filename;
|
|
int line_number;
|
|
};
|
|
|
|
IncludeState include_stack[MAX_INCLUDE_DEPTH];
|
|
int include_stack_ptr = 0;
|
|
|
|
void switch_to_file(FILE* fp) { yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE)); }
|
|
|
|
void switch_to_file(const char* filename) {
|
|
if ( include_stack_ptr >= MAX_INCLUDE_DEPTH ) {
|
|
fprintf(stderr, "Includes nested too deeply");
|
|
exit(1);
|
|
}
|
|
|
|
IncludeState state = {YY_CURRENT_BUFFER, input_filename, line_number};
|
|
include_stack[include_stack_ptr++] = state;
|
|
|
|
FILE* fp = fopen(filename, "r");
|
|
|
|
if ( ! fp ) {
|
|
fprintf(stderr, "%s:%d: error: cannot include file \"%s\"\n", input_filename.c_str(), line_number, filename);
|
|
exit(1);
|
|
}
|
|
|
|
yyin = fp;
|
|
input_filename = string(filename);
|
|
line_number = 1;
|
|
switch_to_file(yyin);
|
|
if ( ! FLAGS_quiet )
|
|
fprintf(stderr, "switching to file %s\n", input_filename.c_str());
|
|
}
|
|
|
|
void include_file(const char* filename) {
|
|
ASSERT(filename);
|
|
|
|
string full_filename;
|
|
if ( filename[0] == '/' )
|
|
full_filename = filename;
|
|
else if ( filename[0] == '.' ) {
|
|
string dir = do_dirname(input_filename);
|
|
|
|
if ( ! dir.empty() )
|
|
full_filename = dir + "/" + filename;
|
|
else {
|
|
fprintf(stderr, "%s:%d error: cannot include file \"%s\": %s\n", input_filename.c_str(), line_number,
|
|
filename, strerror(errno));
|
|
exit(1);
|
|
}
|
|
}
|
|
else {
|
|
int i;
|
|
for ( i = 0; i < (int)FLAGS_include_directories.size(); ++i ) {
|
|
full_filename = FLAGS_include_directories[i] + filename;
|
|
DEBUG_MSG("Try include file: \"%s\"\n", full_filename.c_str());
|
|
if ( access(full_filename.c_str(), R_OK) == 0 )
|
|
break;
|
|
}
|
|
if ( i >= (int)FLAGS_include_directories.size() )
|
|
full_filename = filename;
|
|
}
|
|
|
|
switch_to_file(full_filename.c_str());
|
|
}
|
|
|
|
int yywrap() {
|
|
yy_delete_buffer(YY_CURRENT_BUFFER);
|
|
--include_stack_ptr;
|
|
if ( include_stack_ptr < 0 )
|
|
return 1;
|
|
|
|
IncludeState state = include_stack[include_stack_ptr];
|
|
yy_switch_to_buffer(state.yystate);
|
|
input_filename = state.input_filename;
|
|
line_number = state.line_number;
|
|
return 0;
|
|
}
|