nginx 配置文件解析函数------------ngx_conf_read_token
来源:互联网 发布:游戏狗软件 编辑:程序博客网 时间:2024/06/11 22:51
1. 首先在函数ngx_conf_parse 根据文件名申请buff
2.根据文件大小读取文件内容
3. 逐个读取字符
解析文件中的字符步骤:
一)last_space 为1的情况,表示刚开始解析或者是前面已经解析到一个关键字(一般以空格,分号, 左大括号等为边界).
1. pos指针一个字符一个字符往右移动 ch = *pos++
2. 遇到空格,制表符(\t),回车,换行,直接跳过
3.更新局部变量start为pos指针-1
4.遇到分号,左大括号和右大括号直接return返回
5.遇到# 设置comment标记,continue
6.遇到\,’,”,设置对应标记,并将last_space 设置为0
7.其它情况设置last_space 为0
二)Last_sapce 不为0,解析关键字过程中
1. 遇到${,continue
2.遇到\, $等设置标记位,continue
3.遇到第二个双引号或者单引号,清空引号标记位,设置找到关键字标记found=1,并且设置后面跟着的字符必须有空格Need_space=1
4.遇到空格,\t,回车,换行,{,分号,设置找到关键字标记found=1,并设置last_space为1,重新开始寻找新的关键字.
5.找到关键字found=1,从存放关键字的数组cf->args找到一个空位置,将关键字存放到该字符串数组的空位中。如果是因为第4步骤的分号或者{设置的,这return OK或BLOKC_START。更新found为0
static ngx_int_tngx_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;/*设置保存参数的数组个数为0,即清空保存配置的数组*/ /*获取配置文件的buffer*/ b = cf->conf_file->buffer; /*上一次读取结束的文件buf位置,第一次读取时为文件的起始位置*/ start = b->pos; /*上一次读取的结束行数*/ start_line = cf->conf_file->line; /*配置文件大小(字节)*/ file_size = ngx_file_size(&cf->conf_file->file.info); ngx_conf_log_error(NGX_LOG_DEBUG,cf,0,"file_size=%lu,start_line=%uz",file_size,start_line); for ( ;; ) { /*第一次,b->pos = b->last,后续b->last指向读取buffer的结尾, * 从第2次循环开始,如果为真,表示前一次读取的buffer已经全部解析完毕,需要进入判断一下是否文件已经读完,或者没有读完的话,继续读取 * 第2次以后if为真的情况是,文件的大小大于buffer的长度(4096),此时需要多次读取*/ if (b->pos >= b->last) { /*如果偏移量大于文件大小,说明文件已读取完毕,返回NGX_CONF_FILE_DONE*/ if (cf->conf_file->file.offset >= file_size) { 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; } ngx_conf_log_error(NGX_LOG_DEBUG,cf,0,"start =%d,pos=%d",start,b->pos); return NGX_CONF_FILE_DONE; } /*这个两个值在重新执行for循环的情况下应该相等,因为前面刚刚把b->pos赋值给了start*/ len = b->pos - start; /*len表示还有多少已扫描但是没有被解析*/ /*如果这个长度超过了最大文件buffer,NGX_CONF_BUFFER(4096),出错返回*/ 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; } /**/ if (len) { ngx_memmove(b->start, start, len); } size = (ssize_t) (file_size - cf->conf_file->file.offset); /*即文件大小大于分配的buffer长度,size取为buffer长度*/ if (size > b->end - (b->start + len)) { size = b->end - (b->start + len); } /*读取size大小的文件数据到buf中,起始地址为b->start + len,修改文件偏移量*/ 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; } /*修改当前buf的位置b->pos*/ b->pos = b->start + len; /*指向数据的结尾*/ b->last = b->pos + n; start = b->start; } /*一个字节一个字节地循环处理文件buff内容*/ ch = *b->pos++; /*如果是换行符*/ if (ch == LF) { cf->conf_file->line++;//处理的行数+1 if (sharp_comment) {//修改注释行标记位 sharp_comment = 0; } } /*如果前面是#开头的注释,直接跳过#后面的所有字符,直到上面的遇到换行符后, * 将该注释标记去除,表示注释结束,新的行开始0*/ if (sharp_comment) { continue; } /*前面有反斜杠转义字符\,说明这个字符是一个转义字符,忽略\后面的字符*/ if (quoted) { quoted = 0; continue; } /*need_space默认为0,单引号或者双引号结束后,需要有以下分隔符: * 空格,制表符,回车,换行,分号,左大括号,右小括号 * 遇到其它都是错误的,返回error*/ if (need_space) { /*如果遇到空格,制表符,回车,换行,则将need_space清空,last_space置1*/ if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) { last_space = 1; need_space = 0; continue; } /*如果遇到分号;则该行读取结束*/ if (ch == ';') { return NGX_OK; } /*遇到'{'表示新的block的开始*/ 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,last_space表示上一个字符为字符串分隔符,需要重新计算start,以表示新的token的起始地址*/ if (last_space) { /*遇到空格,制表符,回车,换行等字符,则无需处理*/ if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) { continue; } start = b->pos - 1;/*更新start值,作为新的token(关键字)的起始地址*/ start_line = cf->conf_file->line; switch (ch) { /*遇到;或者{,直接返回*/ case ';': case '{': 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标记*/ sharp_comment = 1; continue; case '\\':/*遇到\,设置quoted=1,last_space=0*/ quoted = 1; last_space = 0; continue; case '"'://遇到第一个“,设置d_quoted为1 start++; d_quoted = 1; last_space = 0; continue; case '\''://遇到第一个单引号',设置s_quoted为1 start++; s_quoted = 1; last_space = 0; continue; default: last_space = 0; } } else { if (ch == '{' && variable) { continue; } variable = 0; if (ch == '\\') { quoted = 1; continue; } /*遇到$符,设置variable为1*/ if (ch == '$') { variable = 1; continue; } if (d_quoted) { if (ch == '"') {//遇到第二个双引号”,设置d_quoted=0,need_space=1,found=1 d_quoted = 0; need_space = 1; found = 1; } } else if (s_quoted) {//遇到第二个单引号’,设置s_quoted=0,need_space=1,found=1 if (ch == '\'') { s_quoted = 0; need_space = 1; found = 1; } } else if (ch == ' ' || ch == '\t' || ch == CR || ch == LF || ch == ';' || ch == '{')//遇到空格,制表符,回车,换行符,分号,{,设置last_space=1,found=1 { last_space = 1; found = 1; } //正常情况下,遇到空格或分号结束时,设置了last_space=1,found=1 if (found) { /*args是初始化为10个ngx_str_t大小的动态数组,在ngx_init_cycle中初始化 * 存放配置文件中的一行中的关键字,如: * worker_processes 1; * args的第一个数组元素就是 worker_process * 第二个数组元素就是1*/ word = ngx_array_push(cf->args);//找到数组可用的位置 if (word == NULL) { return NGX_ERROR; } /*文件数据的起始位置为start,当前的位置为b->pos*/ word->data = ngx_pnalloc(cf->pool, b->pos - start + 1); if (word->data == NULL) { return NGX_ERROR; } /*将start开始的数据拷贝到word->data中,并记录拷贝的大小len*/ 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; /*正常情况下,遇到分号,返回一行*/ if (ch == ';') { return NGX_OK; } /*如果是一个block,如event,则返回NGX_CONF_BLOCK_START*/ if (ch == '{') { return NGX_CONF_BLOCK_START; } /*等于其它的符号,如空格,则继续循环*/ found = 0; } } }}
0 0
- nginx 配置文件解析函数------------ngx_conf_read_token
- nginx的配置文件解析:ngx_conf_read_token函数
- 15.Nginx解析配置文件之ngx_conf_read_token
- ngx_conf_read_token函数
- nginx ngx_conf_read_token详细分析
- 【Nginx】初识nginx---配置文件解析
- nginx 配置文件解析
- Nginx配置文件解析
- Nginx配置文件解析之一
- nginx配置文件解析
- nginx 配置文件解析--二
- nginx配置文件解析
- Nginx的配置文件解析
- nginx 配置文件解析
- NGINX的配置文件解析
- 解析Nginx配置文件
- Nginx.conf配置文件解析
- nginx配置文件解析
- PNB第四季度高不良资产5,367千万卢比的亏损纪录
- Windows内核中的数据结构与函数调用
- N的二进制中1的个数
- 【福利】个推携手Testin,总价16万“企业服务大礼包”免费领!
- 使用LR11过程中遇到的一些问题汇总
- nginx 配置文件解析函数------------ngx_conf_read_token
- Unix时间工具类----多种时间计算,特定时刻计算。。。。
- web中用ajax传递json数据到后台
- 表格
- 深入浅出RxJava三--响应式的好处
- Unreal Cook Book:VR应用中的焦点目标拾取
- php中in_array需要注意的一点
- swift Image加载
- XML解析——SAX方式