兼容90%标准C的词法分析器

时间:2022-11-15 10:31:39

不能分词八进制和数字类型加前/后缀的情况

拿这个词法分析器跑了一遍整个Nginx源码,基本都能正确的分出结果,后面有测试例子~

 #ifndef _STATES_H_
#define _STATES_H_ #include "log_config.h" __LOG_BEGIN_NAMESPACE enum _states
{
IN_NONE,
IN_NUM,
IN_0XNUM,
IN_INT,
IN_FLOAT,
IN_E,
IN_ALPHA,
IN_MINUS,
IN_PLUS,
IN_MULTIPLE,
IN_EXCLAMATION_POINT,
IN_AND,
IN_DIVIDE,
IN_PERCENT,
IN_LEFT_NARROW,
IN_RIGHT_NARROW,
IN_EQUAL,
IN_XOR,
IN_OR,
IN_DOT,
IN_C_COMMENT,
IN_CPP_COMMENT,
IN_FIRST_DOUBLE_QUOTATION_MARKS,
IN_SINGLE_QUOTATION_MARKS,
IN_COLON
}; __LOG_END_NAMESPACE #endif
 #ifndef _TOKEN_H_
#define _TOKEN_H_ #include <string> #include "log_config.h" __LOG_BEGIN_NAMESPACE
enum token_attr
{
NONE,//表示空属性
KEYWORD,//关键字 (if, else, ...)
INT, //整数 (1, 100, ...)
FLOAT,//浮点数 (0.1, 3.14, ...)
SYMBOL,//符号 (=, <, *, &, (, )...)
VARIABLE,//变量 (变量名, 函数名, 结构体名...)
STRING
//.......
};
struct token
{
token() :name(""), line_no(), attr(NONE) {} std::string name;
long line_no;
enum token_attr attr; void set_all(const std::string& _name,
const long _line, enum token_attr _attr)
{
set_name(_name);
set_line(_line);
set_attr(_attr);
}
void set_name(const std::string& str){ name = str; }
void set_line(const long l){ line_no = l; }
void set_attr(enum token_attr a){ attr = a; }
};
__LOG_END_NAMESPACE
#endif
 #ifndef _SCANNER_H_
#define _SCANNER_H_ #include <algorithm>
#include <string>
#include <vector> #include "log_config.h"
#include "token.h" __LOG_BEGIN_NAMESPACE
//struct token;
class scanner
{
public:
explicit scanner(const std::string& _code) :code(_code), index(), line_no() {}
//explicit scanner(const std::string& file_name, std::ifstream::openmode opm);
std::vector<token> get_all_tokens();
inline bool is_num(const char& ch);//ch是数字
inline bool is_alpha(const char& ch);//ch是字母
inline bool is_symbol(const char& ch);//ch是符号(=,<,*,&,(,)...)
inline bool is_variable(const char& ch);//ch是变量
inline char get_next_char();
inline void put_char();
private:
std::string code;
std::string::size_type index;
long line_no; std::vector<token> tok_vec;
};
__LOG_END_NAMESPACE
#endif
 #include <cctype>
#include <fstream>
#include <iostream>
#include <set> #include "keywords.h"
#include "log_config.h"
#include "scanner.h"
#include "states.h" __LOG_BEGIN_NAMESPACE std::vector<token> scanner::get_all_tokens(){
token tok;
std::string str;
long line = ;
enum _states state = IN_NONE;
char ch = get_next_char();
//跳过前导空白符
while (isblank(ch) || isspace(ch) || ch == '\n')
{
if (ch == '\n')
++line;
ch = get_next_char();
}
put_char();
//开始分词
while (){
ch = get_next_char();
if (ch == '\n' && state != IN_CPP_COMMENT)
{
++line;
continue;
}
if (ch == EOF || index == code.size())
break;
switch (state)
{
//-------------------------------------
case IN_NONE://初始状态
if (is_num(ch))
{
str = ch;
state = IN_NUM;
}
else if (is_variable(ch))
{
str = ch;
state = IN_ALPHA;
}
else if (ch == '(' || ch == ')' ||
ch == '[' || ch == ']' ||
ch == ',' || ch == '~' ||
ch == '?' || //ch == ':' ||
ch == ';' || ch == '{' ||
ch == '}' || ch == '#')
{
str = ch;
tok.set_all(str, line, SYMBOL);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
else if (ch == '-')
{
str = ch;
state = IN_MINUS;
}
else if (ch == '!')
{
str = ch;
state = IN_EXCLAMATION_POINT;
}
else if (ch == '+')
{
str = ch;
state = IN_PLUS;
}
else if (ch == '*')
{
str = ch;
state = IN_MULTIPLE;
}
else if (ch == '&')
{
str = ch;
state = IN_AND;
}
else if (ch == '/')
{
str = ch;
state = IN_DIVIDE;
}
else if (ch == '%')
{
str = ch;
state = IN_PERCENT;
}
else if (ch == '<')
{
str = ch;
state = IN_LEFT_NARROW;
}
else if (ch == '>')
{
str = ch;
state = IN_RIGHT_NARROW;
}
else if (ch == '=')
{
str = ch;
state = IN_EQUAL;
}
else if (ch == '^')
{
str = ch;
state = IN_XOR;
}
else if (ch == '|')
{
str = ch;
state = IN_OR;
}
else if (ch == '.')
{
str = ch;
state = IN_DOT;
}
else if (ch == '"')
{
str = ch;
state = IN_FIRST_DOUBLE_QUOTATION_MARKS;
}
else if (ch == ':')
{
str = ch;
state = IN_COLON;
}
else if (ch == '\'')
{
str = ch;
state = IN_SINGLE_QUOTATION_MARKS;
}
break;
//-------------------------------------
case IN_NUM:
if (is_num(ch))
{
str += ch;
state = IN_NUM;
}
else if (ch == 'e' || ch == 'E')
{
str += ch;
state = IN_E;
}
else if (ch == '.')
{
str += ch;
state = IN_DOT;
}
else
{
if (str == "" && (ch == 'X' || ch == 'x'))
{
str += ch;
state = IN_0XNUM;
}
else
{
put_char();
tok.set_all(str, line, INT);
this->tok_vec.push_back(tok);
state = IN_NONE;
}
}
break;
//-------------------------------------
case IN_0XNUM:
if (is_num(ch) ||
(ch >= 'A' && ch <= 'F') ||
(ch >= 'a' && ch <= 'f'))
{
str += ch;
state = IN_0XNUM;
}
else
{
put_char();
tok.set_all(str, line, INT);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
break;
//-------------------------------------
case IN_E:
if (ch == '-')
{
str += ch;
state = IN_MINUS;
}
else if (ch == '+')
{
str += ch;
state = IN_PLUS;
}
else if (is_num(ch))
{
str += ch;
state = IN_NUM;
}
break;
//-------------------------------------
case IN_ALPHA:
if (is_alpha(ch) || is_num(ch) || ch == '_')
{
str += ch;
state = IN_ALPHA;
}
else
{
put_char();
if (keywords.find(str) == keywords.end())
{
tok.set_all(str, line, VARIABLE);
}
else
{
tok.set_all(str, line, KEYWORD);
}
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
break;
//-------------------------------------
case IN_MINUS:
if (ch == '>')
{// ->
str += ch;
tok.set_all(str, line, SYMBOL);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
else if (ch == '-')
{// --
str += ch;
tok.set_all(str, line, SYMBOL);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
else if (ch == '=')
{// -=
str += ch;
tok.set_all(str, line, SYMBOL);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
else if (is_num(ch))
{//负数
str += ch;
state = IN_NUM;
}
else
{//'-'
put_char();
tok.set_all(str, line, SYMBOL);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
break;
//-------------------------------------
case IN_EXCLAMATION_POINT:
if (ch == '=')
{ // !=
str += ch;
tok.set_all(str, line, SYMBOL);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
else
{//'!'
put_char();
tok.set_all(str, line, SYMBOL);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
break;
//------------------------------
case IN_PLUS:
if (ch == '+')
{// ++
str += ch;
tok.set_all(str, line, SYMBOL);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
else if (ch == '=')
{// +=
str += ch;
tok.set_all(str, line, SYMBOL);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
else if (is_num(ch))
{//正数
str += ch;
state = IN_NUM;
}
else
{//'+'
put_char();
tok.set_all(str, line, SYMBOL);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
break;
//-------------------------
case IN_MULTIPLE:
if (ch == '=')
{// *=
str += ch;
tok.set_all(str, line, SYMBOL);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
else
{//'*'
put_char();
tok.set_all(str, line, SYMBOL);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
break;
//---------------------
case IN_AND:
if (ch == '&')
{// &&
str += ch;
tok.set_all(str, line, SYMBOL);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
else if (ch == '=')
{// &=
str += ch;
tok.set_all(str, line, SYMBOL);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
else
{// &
put_char();
tok.set_all(str, line, SYMBOL);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
break;
//---------------------
case IN_DIVIDE:
if (ch == '=')
{// /=
str += ch;
tok.set_all(str, line, SYMBOL);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
else if (ch == '/')
{// //
str.clear();
state = IN_CPP_COMMENT;
}
else if (ch == '*')
{// /*
str.clear();
state = IN_C_COMMENT;
}
else
{// /
put_char();
tok.set_all(str, line, SYMBOL);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
break;
//----------------------------
case IN_C_COMMENT:
if (ch == '*')
{
ch = get_next_char();
if (ch == '/')
{
state = IN_NONE;
continue;
}
else
{
state = IN_C_COMMENT;
}
}
else
{
state = IN_C_COMMENT;
}
break;
//----------------------------
case IN_CPP_COMMENT:
if (ch == '\n')
{
put_char();
state = IN_NONE;
}
else
{
state = IN_CPP_COMMENT;
}
break;
//----------------------------
case IN_PERCENT:
if (ch == '=')
{// %=
str += ch;
tok.set_all(str, line, SYMBOL);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
else
{// %
put_char();
tok.set_all(str, line, SYMBOL);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
break;
//------------------------
case IN_LEFT_NARROW:
if (ch == '<')
{// <<
str += ch;
tok.set_all(str, line, SYMBOL);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
else if (ch == '=')
{// <=
str += ch;
tok.set_all(str, line, SYMBOL);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
else
{// <
put_char();
tok.set_all(str, line, SYMBOL);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
break;
//------------------------
case IN_RIGHT_NARROW:
if (ch == '>')
{// >>
str += ch;
tok.set_all(str, line, SYMBOL);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
else if (ch == '=')
{// >=
str += ch;
tok.set_all(str, line, SYMBOL);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
else
{// >
put_char();
tok.set_all(str, line, SYMBOL);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
break;
//----------------------------
case IN_EQUAL:
if (ch == '=')
{// ==
str += ch;
tok.set_all(str, line, SYMBOL);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
else
{// =
put_char();
tok.set_all(str, line, SYMBOL);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
break;
//-------------------------
case IN_XOR:
if (ch == '=')
{// ^=
str += ch;
tok.set_all(str, line, SYMBOL);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
else
{// ^
put_char();
tok.set_all(str, line, SYMBOL);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
break;
//---------------------------
case IN_OR:
if (ch == '|')
{// ||
str += ch;
tok.set_all(str, line, SYMBOL);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
else if (ch == '=')
{// |=
str += ch;
tok.set_all(str, line, SYMBOL);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
else
{// |
put_char();
tok.set_all(str, line, SYMBOL);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
break;
//---------------------
case IN_DOT:
if (is_num(ch))
{
str += ch;
state = IN_NUM;
}
else
{
put_char();
tok.set_all(str, line, SYMBOL);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
break;
//-------------------
case IN_FIRST_DOUBLE_QUOTATION_MARKS:
if (ch == '\\')
{//遇到转义符
str += ch;
ch = get_next_char();
if (ch == '"')
{
str += ch;
}
else
{
put_char();
}
state = IN_FIRST_DOUBLE_QUOTATION_MARKS;
}
else if (ch == '"')
{
str += ch;
tok.set_all(str, line, STRING);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
else
{
str += ch;
state = IN_FIRST_DOUBLE_QUOTATION_MARKS;
}
break;
//---------------------------
case IN_COLON:
if (ch == ':')
{
str += ch;
tok.set_all(str, line, SYMBOL);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
else
{
put_char();
tok.set_all(str, line, SYMBOL);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
break;
//--------------------------
case IN_SINGLE_QUOTATION_MARKS:
if (ch != '\'')
{
str += ch;
state = IN_SINGLE_QUOTATION_MARKS;
}
else
{
str += ch;
tok.set_all(str, line, STRING);
this->tok_vec.push_back(tok);
str.clear();
state = IN_NONE;
}
break;
//--------------------------
default:
break;
}// switch
}// while
return std::move(tok_vec);
} bool scanner::is_alpha(const char& ch)
{
if ((ch >= 'A' && ch <= 'Z') ||
(ch >= 'a' && ch <= 'z'))
return true;
return false;
}
bool scanner::is_num(const char& ch)
{
if (ch >= '' && ch <= '')
return true;
return false;
}
bool scanner::is_variable(const char& ch)
{
if (ch == '_' || is_alpha(ch))
return true;
return false;
}
char scanner::get_next_char()
{
return code[index++];
}
void scanner::put_char()
{
--index;
}
//scanner::scanner(const std::string& file_name, std::ifstream::openmode opm)
//{
// std::ifstream ifs;
// ifs.open(file_name, opm);
// if (ifs)
// {
// ifs.seekg(0, ifs.end);
// std::size_t len = ifs.tellg();
// ifs.seekg(0, ifs.beg);
// code.resize(len + 1);
// ifs.read((char*)&*(code.begin()), len);
// code[len ] = '\0';
//
//
// std::cout << code << std::endl;
// }
// ifs.close();
//}
__LOG_END_NAMESPACE

测试如下:

 #include <iostream>
#include <vector>
#include <fstream> #include "scanner.h" using namespace std;
int main()
{
string file_name("C:\\Users\\zxh\\Desktop\\test1.c");
ofstream ofs("C:\\Users\\zxh\\Desktop\\result.c");
std::ifstream ifs;
ifs.open(file_name, ifstream::binary);
if (ifs)
{
ifs.seekg(, ifs.end);
std::size_t len = ifs.tellg();
ifs.seekg(, ifs.beg);
string _code;
_code.resize(len + );
ifs.read((char*)&*(_code.begin()), len);
_code[len + ] = '\0';
ifs.close();
scanner s(_code);
vector<token> v = s.get_all_tokens();
for (const auto s : v)
{
ofs << s.name << " " << s.line_no << " "; }
}
system("pause");
return ;
}

分词的代码选取为Nginx源码下的一个函数

 static ngx_int_t
ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)
{
int events;
uint32_t revents;
ngx_int_t instance, i;
ngx_uint_t level;
ngx_err_t err;
ngx_event_t *rev, *wev, **queue;
ngx_connection_t *c; int i = 0XFFFFFFFF, 0X1234defc, 0x3333; /* NGX_TIMER_INFINITE == INFTIM */ ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, ,
"epoll timer: %M", timer); events = epoll_wait(ep, event_list, (int) nevents, timer); err = (events == -) ? ngx_errno : ; if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
ngx_time_update();
} if (err) {
if (err == NGX_EINTR) { if (ngx_event_timer_alarm) {
ngx_event_timer_alarm = ;
return NGX_OK;
} level = NGX_LOG_INFO; } else {
level = NGX_LOG_ALERT;
} ngx_log_error(level, cycle->log, err, "epoll_wait() failed");
return NGX_ERROR;
} if (events == ) {
if (timer != NGX_TIMER_INFINITE) {
return NGX_OK;
} ngx_log_error(NGX_LOG_ALERT, cycle->log, ,
"epoll_wait() returned no events without timeout");
return NGX_ERROR;
} ngx_mutex_lock(ngx_posted_events_mutex); for (i = ; i < events; i++) {
c = event_list[i].data.ptr; instance = (uintptr_t) c & ;
c = (ngx_connection_t *) ((uintptr_t) c & (uintptr_t) ~); rev = c->read; if (c->fd == - || rev->instance != instance) { /*
* the stale event from a file descriptor
* that was just closed in this iteration
*/ ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, ,
"epoll: stale event %p", c);
continue;
} revents = event_list[i].events; ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, ,
"epoll: fd:%d ev:%04XD d:%p",
c->fd, revents, event_list[i].data.ptr); if (revents & (EPOLLERR|EPOLLHUP)) {
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, ,
"epoll_wait() error on fd:%d ev:%04XD",
c->fd, revents);
} #if 0
if (revents & ~(EPOLLIN|EPOLLOUT|EPOLLERR|EPOLLHUP)) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, ,
"strange epoll_wait() events fd:%d ev:%04XD",
c->fd, revents);
}
#endif if ((revents & (EPOLLERR|EPOLLHUP))
&& (revents & (EPOLLIN|EPOLLOUT)) == )
{
/*
* if the error events were returned without EPOLLIN or EPOLLOUT,
* then add these flags to handle the events at least in one
* active handler
*/ revents |= EPOLLIN|EPOLLOUT;
} if ((revents & EPOLLIN) && rev->active) { #if (NGX_HAVE_EPOLLRDHUP)
if (revents & EPOLLRDHUP) {
rev->pending_eof = ;
}
#endif if ((flags & NGX_POST_THREAD_EVENTS) && !rev->accept) {
rev->posted_ready = ; } else {
rev->ready = ;
} if (flags & NGX_POST_EVENTS) {
queue = (ngx_event_t **) (rev->accept ?
&ngx_posted_accept_events : &ngx_posted_events); ngx_locked_post_event(rev, queue); } else {
rev->handler(rev);
}
} wev = c->write; if ((revents & EPOLLOUT) && wev->active) { if (c->fd == - || wev->instance != instance) { /*
* the stale event from a file descriptor
* that was just closed in this iteration
*/ ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, ,
"epoll: stale event %p", c);
continue;
} if (flags & NGX_POST_THREAD_EVENTS) {
wev->posted_ready = ; } else {
wev->ready = ;
} if (flags & NGX_POST_EVENTS) {
ngx_locked_post_event(wev, &ngx_posted_events); } else {
wev->handler(wev);
}
}
} ngx_mutex_unlock(ngx_posted_events_mutex); return NGX_OK;
}

分词结果如下

 static
ngx_int_t
ngx_epoll_process_events
(
ngx_cycle_t
*
cycle
,
ngx_msec_t
timer
,
ngx_uint_t
flags
)
{
int
events
;
uint32_t
revents
;
ngx_int_t
instance
,
i
;
ngx_uint_t
level
;
ngx_err_t
err
;
ngx_event_t
*
rev
,
*
wev
,
*
*
queue
;
ngx_connection_t
*
c
;
int
i
=
0XFFFFFFFF
,
0X1234defc
,
0x3333
;
ngx_log_debug1
(
NGX_LOG_DEBUG_EVENT
,
cycle
->
log
, ,
"epoll timer: %M"
,
timer
)
;
events
=
epoll_wait
(
ep
,
event_list
,
(
int
)
nevents
,
timer
)
;
err
=
(
events
==
-
)
?
ngx_errno
: ;
if
(
flags
&
NGX_UPDATE_TIME
||
ngx_event_timer_alarm
)
{
ngx_time_update
(
)
;
}
if
(
err
)
{
if
(
err
==
NGX_EINTR
)
{
if
(
ngx_event_timer_alarm
)
{
ngx_event_timer_alarm
= ;
return
NGX_OK
;
}
level
=
NGX_LOG_INFO
;
}
else
{
level
=
NGX_LOG_ALERT
;
}
ngx_log_error
(
level
,
cycle
->
log
,
err
,
"epoll_wait() failed"
)
;
return
NGX_ERROR
;
}
if
(
events
== )
{
if
(
timer
!=
NGX_TIMER_INFINITE
)
{
return
NGX_OK
;
}
ngx_log_error
(
NGX_LOG_ALERT
,
cycle
->
log
, ,
"epoll_wait() returned no events without timeout"
)
;
return
NGX_ERROR
;
}
ngx_mutex_lock
(
ngx_posted_events_mutex
)
;
for
(
i
= ;
i
<
events
;
i
++
)
{
c
=
event_list
[
i
]
.
data
.
ptr
;
instance
=
(
uintptr_t
)
c
& ;
c
=
(
ngx_connection_t
*
)
(
(
uintptr_t
)
c
&
(
uintptr_t
)
~ )
;
rev
=
c
->
read
;
if
(
c
->
fd
==
-
||
rev
->
instance
!=
instance
)
{
ngx_log_debug1
(
NGX_LOG_DEBUG_EVENT
,
cycle
->
log
, ,
"epoll: stale event %p"
,
c
)
;
continue
;
}
revents
=
event_list
[
i
]
.
events
;
ngx_log_debug3
(
NGX_LOG_DEBUG_EVENT
,
cycle
->
log
, ,
"epoll: fd:%d ev:%04XD d:%p"
,
c
->
fd
,
revents
,
event_list
[
i
]
.
data
.
ptr
)
;
if
(
revents
&
(
EPOLLERR
|
EPOLLHUP
)
)
{
ngx_log_debug2
(
NGX_LOG_DEBUG_EVENT
,
cycle
->
log
, ,
"epoll_wait() error on fd:%d ev:%04XD"
,
c
->
fd
,
revents
)
;
}
#
if if
(
revents
&
~
(
EPOLLIN
|
EPOLLOUT
|
EPOLLERR
|
EPOLLHUP
)
)
{
ngx_log_error
(
NGX_LOG_ALERT
,
cycle
->
log
, ,
"strange epoll_wait() events fd:%d ev:%04XD"
,
c
->
fd
,
revents
)
;
}
#
endif
if
(
(
revents
&
(
EPOLLERR
|
EPOLLHUP
)
)
&&
(
revents
&
(
EPOLLIN
|
EPOLLOUT
)
)
== )
{
revents
|=
EPOLLIN
|
EPOLLOUT
;
}
if
(
(
revents
&
EPOLLIN
)
&&
rev
->
active
)
{
#
if
(
NGX_HAVE_EPOLLRDHUP
)
if
(
revents
&
EPOLLRDHUP
)
{
rev
->
pending_eof
= ;
}
#
endif
if
(
(
flags
&
NGX_POST_THREAD_EVENTS
)
&&
!
rev
->
accept
)
{
rev
->
posted_ready
= ;
}
else
{
rev
->
ready
= ;
}
if
(
flags
&
NGX_POST_EVENTS
)
{
queue
=
(
ngx_event_t
*
*
)
(
rev
->
accept
?
&
ngx_posted_accept_events
:
&
ngx_posted_events
)
;
ngx_locked_post_event
(
rev
,
queue
)
;
}
else
{
rev
->
handler
(
rev
)
;
}
}
wev
=
c
->
write
;
if
(
(
revents
&
EPOLLOUT
)
&&
wev
->
active
)
{
if
(
c
->
fd
==
-
||
wev
->
instance
!=
instance
)
{
ngx_log_debug1
(
NGX_LOG_DEBUG_EVENT
,
cycle
->
log
, ,
"epoll: stale event %p"
,
c
)
;
continue
;
}
if
(
flags
&
NGX_POST_THREAD_EVENTS
)
{
wev
->
posted_ready
= ;
}
else
{
wev
->
ready
= ;
}
if
(
flags
&
NGX_POST_EVENTS
)
{
ngx_locked_post_event
(
wev
,
&
ngx_posted_events
)
;
}
else
{
wev
->
handler
(
wev
)
;
}
}
}
ngx_mutex_unlock
(
ngx_posted_events_mutex
)
;
return
NGX_OK
;
}