该函数获取配置文件nginx.conf中的配置行或者配置块起始处的token.将这些token放在cf->args动态数组中, 并返回这些token所在配置文件中的位置.
例如一个配置行的话. 就返回NGX_OK. 配置行以分号结尾. 如果是一个配置块的起始处, 即以'{'结尾, 则返回NGX_CONF_BLOCK_START.
对于token的定义为: 连续非空白字符. 单双引号包围的字符. 单双引号内允许转义序列如\t, \r, \n.
'#'之后为注释. 其后行内的所有字符全部忽略.
理解该函数的要点只需理解几个标识的具体含义即可.
found: 为1表明发现一个token. 然后将该token压入cf->args数组中.
need_space: token被单双引号包围时, 最后一个分号后面必须是空白字符、分号、坐花括号或者右括号(
左括号匹配在代码中没看见?). 否则出错.
last_space: 为1表明前面扫描的字符均为空白字符. 即还未发现token起始位置. 为0表明已找到token的起始位置.
sharp_comment: 扫描到'#'字符后置1, 其后所有字符都会忽略直至一行结束.
quoted: 转义序列, '\'之后的字符被跳过.然后quoted置0.
s_quoted, d_quoted: token以单或双引号起始, 必须以单或双引号结束.
例如:
worker_processes 1;
解析后cf->args数组里有两个ngx_str_t结构. 两个字符串分别是"worker_processes"和"1", 返回值为NGX_OK。
event {
worker_connections 1024;
}
解析时cf_args数组里有一个ngx_str_t结构.字符串为"event". 返回值为NGX_CONF_BLOCK_START.
-
static ngx_int_t
-
ngx_conf_read_token(ngx_conf_t *cf)
-
{
-
u_char *start, ch, *src, *dst;
-
off_t file_size;
-
size_t len;
-
ssize_t n, size;
-
ngx_uint_t found, need_space, last_space, sharp_comment, variable;
-
ngx_uint_t quoted, s_quoted, d_quoted, start_line;
-
ngx_str_t *word;
-
ngx_buf_t *b;
-
-
found = 0;
-
need_space = 0;
-
last_space = 1;
-
sharp_comment = 0;
-
variable = 0;
-
quoted = 0;
-
s_quoted = 0;
-
d_quoted = 0;
-
-
cf->args->nelts = 0;
-
b = cf->conf_file->buffer;
-
start = b->pos;
-
start_line = cf->conf_file->line;
-
-
file_size = ngx_file_size(&cf->conf_file->file.info);
-
-
for ( ;; ) {
-
//已处理完缓冲区中的字符.
-
if (b->pos >= b->last) {
-
-
if (cf->conf_file->file.offset >= file_size) {
-
//文件已处理完. 但是已解析出的token数大于0或者已发现一个token的
-
//起始位置. 配置行不完整. 配置语法出错。
-
if (cf->args->nelts > 0 || !last_space) {
-
-
if (cf->conf_file->file.fd == NGX_INVALID_FILE) {
-
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-
"unexpected end of parameter, "
-
"expecting \";\"");
-
return NGX_ERROR;
-
}
-
-
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-
"unexpected end of file, "
-
"expecting \";\" or \"}\"");
-
return NGX_ERROR;
-
}
-
//处理完配置文件.
-
return NGX_CONF_FILE_DONE;
-
}
-
//未处理的缓冲区字符长度.
-
len = b->pos - start;
-
//若长度等于缓冲区长度. 则配置出错.
-
//token长度不能大于NGX_CONF_BUFFER.
-
if (len == NGX_CONF_BUFFER) {
-
cf->conf_file->line = start_line;
-
-
if (d_quoted) {
-
ch = '"';
-
-
} else if (s_quoted) {
-
ch = '\'';
-
-
} else {
-
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-
"too long parameter \"%*s...\" started",
-
10, start);
-
return NGX_ERROR;
-
}
-
-
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-
"too long parameter, probably "
-
"missing terminating \"%c\" character", ch);
-
return NGX_ERROR;
-
}
-
//将未处理完的字符拷贝到缓冲区开始出. 这些字符是一个token的一部分
-
if (len) {
-
ngx_memmove(b->start, start, len);
-
}
-
// 配置文件未处理的长度.
-
size = (ssize_t) (file_size - cf->conf_file->file.offset);
-
//若超过可用缓冲区长度则一次读取可用缓冲区长度的字符.
-
if (size > b->end - (b->start + len)) {
-
size = b->end - (b->start + len);
-
}
-
//从上次读取结束的地方开始读取size个字符继续处理.
-
n = ngx_read_file(&cf->conf_file->file, b->start + len, size,
-
cf->conf_file->file.offset);
-
-
if (n == NGX_ERROR) {
-
return NGX_ERROR;
-
}
-
-
if (n != size) {
-
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-
ngx_read_file_n " returned "
-
"only %z bytes instead of %z",
-
n, size);
-
return NGX_ERROR;
-
}
-
//[b->pos, b->last) 之间是需要处理的字符.
-
b->pos = b->start + len;
-
b->last = b->pos + n;
-
start = b->start;
-
}
-
-
ch = *b->pos++;
-
//当前字符是换行符. 行计数器增1, 若之前扫描到该行首是注释符, 则注释标识清
-
//0。
-
if (ch == LF) {
-
cf->conf_file->line++;
-
-
if (sharp_comment) {
-
sharp_comment = 0;
-
}
-
}
-
//当前行是注释行, 吃掉该行后续所有字符.
-
if (sharp_comment) {
-
continue;
-
}
-
//跳过\后面的字符. 即转义序列.
-
if (quoted) {
-
quoted = 0;
-
continue;
-
}
-
//当token被单或双引号包围是need_space会被置1.
-
if (need_space) {
-
-
if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) {
-
last_space = 1;
-
need_space = 0;
-
continue;
-
}
-
-
-
//配置行以分号结尾.
-
if (ch == ';') {
-
return NGX_OK;
-
}
-
//配置块以{开始
-
if (ch == '{') {
-
return NGX_CONF_BLOCK_START;
-
}
-
-
if (ch == ')') {
-
last_space = 1;
-
need_space = 0;
-
-
} else {
-
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-
"unexpected \"%c\"", ch);
-
return NGX_ERROR;
-
}
-
}
-
//last_space为1表明未发现token起始位置, 吃掉所有空白字符.
-
if (last_space) {
-
if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) {
-
continue;
-
}
-
//非空白字符是一个token的起始位置.
-
start = b->pos - 1;
-
start_line = cf->conf_file->line;
-
-
switch (ch) {
-
-
case ';':
-
case '{':
-
//在分号和左括号之前必定会出现至少一个token. 否则是配置语法错误
-
if (cf->args->nelts == 0) {
-
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-
"unexpected \"%c\"", ch);
-
return NGX_ERROR;
-
}
-
//配置块起始位置.
-
if (ch == '{') {
-
return NGX_CONF_BLOCK_START;
-
}
-
//配置行结束.
-
return NGX_OK;
-
//配置块结束标识右括号独占一行.
-
case '}':
-
if (cf->args->nelts != 0) {
-
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-
"unexpected \"}\"");
-
return NGX_ERROR;
-
}
-
-
return NGX_CONF_BLOCK_DONE;
-
//注释符.
-
case '#':
-
sharp_comment = 1;
-
continue;
-
//转义序列.其后面的一个字符将被跳过.
-
case '\\':
-
quoted = 1;
-
last_space = 0;
-
continue;
-
//引号开头的token.
-
case '"':
-
start++;
-
d_quoted = 1;
-
last_space = 0;
-
continue;
-
-
case '\'':
-
start++;
-
s_quoted = 1;
-
last_space = 0;
-
continue;
-
-
default:
-
last_space = 0;
-
}
-
//到这里开始处理token字符.
-
} else {
-
if (ch == '{' && variable) {
-
continue;
-
}
-
-
variable = 0;
-
//转义序列.其后面的一个字符将被跳过
-
if (ch == '\\') {
-
quoted = 1;
-
continue;
-
}
-
//??????这里是什么???
-
if (ch == '$') {
-
variable = 1;
-
continue;
-
}
-
//单双引号包围的字符是一个token.
-
if (d_quoted) {
-
if (ch == '"') {
-
d_quoted = 0;
-
need_space = 1;
-
found = 1;
-
}
-
-
} else if (s_quoted) {
-
if (ch == '\'') {
-
s_quoted = 0;
-
need_space = 1;
-
found = 1;
-
}
-
//字符是空格、制表符、换行符、分号或是左花括号表示一个token的结束.
-
//也即发现一个token
-
} else if (ch == ' ' || ch == '\t' || ch == CR || ch == LF
-
|| ch == ';' || ch == '{')
-
{
-
last_space = 1;
-
found = 1;
-
}
-
-
if (found) {
-
//将该token放入cf->args动态数组中.
-
word = ngx_array_push(cf->args);
-
if (word == NULL) {
-
return NGX_ERROR;
-
}
-
-
word->data = ngx_pnalloc(cf->pool, b->pos - start + 1);
-
if (word->data == NULL) {
-
return NGX_ERROR;
-
}
-
//将token中的转义序列转义后复制给word->data, 其他的按原样复制.
-
for (dst = word->data, src = start, len = 0;
-
src < b->pos - 1;
-
len++)
-
{
-
if (*src == '\\') {
-
switch (src[1]) {
-
case '"':
-
case '\'':
-
case '\\':
-
src++;
-
break;
-
-
case 't':
-
*dst++ = '\t';
-
src += 2;
-
continue;
-
-
case 'r':
-
*dst++ = '\r';
-
src += 2;
-
continue;
-
-
case 'n':
-
*dst++ = '\n';
-
src += 2;
-
continue;
-
}
-
-
}
-
*dst++ = *src++;
-
}
-
*dst = '\0';
-
word->len = len;
-
//若token以分号结束则处理完一个配置行.
-
if (ch == ';') {
-
return NGX_OK;
-
}
-
//若token以左花括号结束则发现配置块起始位置.
-
if (ch == '{') {
-
return NGX_CONF_BLOCK_START;
-
}
-
//发现token标识清0
-
found = 0;
-
}
-
}
-
}
-
}
阅读(4342) | 评论(0) | 转发(0) |