#include "conf.h"
#include "logging.h"
#include <string.h>
int cfg_parse_basic_file(ConfigParser *parser,
FILE *in) {
parser->lines_begin =
NULL;
parser->lines_end =
NULL;
CxMempool *mp = cxBasicMempoolCreate(
512);
CxAllocator *a = (CxAllocator*)mp->allocator;
parser->mp = a;
cxmutstr mline;
mline.ptr =
NULL;
mline.length =
0;
ConfigLine *start_line =
NULL;
ConfigLine *end_line =
NULL;
cxmutstr l;
while((l = cfg_readln(in)).ptr !=
NULL) {
void *org_ptr = l.ptr;
ConfigLine *line =
OBJ_NEW(parser->mp, ConfigLine);
line->line = cx_strdup_a(parser->mp, cx_strcast(l));
line->object =
NULL;
line->type =
LINE_OTHER;
CFG_LINE_ADD(&parser->lines_begin, &parser->lines_end, line);
l = cfg_trim_comment(l);
line->type = cfg_get_basic_type(l);
if(line->type ==
LINE_OTHER) {
if(mline.ptr !=
NULL) {
char *ptr = cxMalloc(a, mline.length + l.length +
1);
memcpy(ptr, mline.ptr, mline.length);
memcpy(ptr + mline.length -
1, l.ptr, l.length);
mline.length += l.length;
free(mline.ptr);
mline.ptr = ptr;
mline.ptr[mline.length] =
0;
end_line = line;
line->type =
LINE_MULTI;
}
if(l.ptr[l.length -
1] ==
'\\') {
if(mline.ptr ==
NULL) {
mline = cx_strdup_a(parser->mp, cx_strcast(l));
start_line = line;
}
}
else {
cxmutstr ll;
if(mline.ptr ==
NULL) {
ll = l;
start_line = line;
end_line = line;
}
else {
ll = mline;
}
int r = parser->parse(parser, start_line, end_line, ll);
if(mline.ptr !=
NULL) {
free(mline.ptr);
mline.ptr =
NULL;
mline.length =
0;
start_line =
NULL;
end_line =
NULL;
}
if(r !=
0) {
free(org_ptr);
return -
1;
}
}
}
free(org_ptr);
}
return 0;
}
cxmutstr cfg_readln(
FILE *file) {
cxmutstr ns;
ns.ptr =
NULL;
ns.length =
0;
if(!feof(file)) {
char buf[
512];
buf[
0] =
0;
int len =
512;
if(fgets(buf, len, file) ==
NULL) {
return ns;
}
if(*buf ==
0) {
printf(
"???\n");
return ns;
}
char *ptr;
if((ptr = strrchr(buf,
'\n'))) {
ptr[
0] =
0;
}
cxmutstr line = cx_mutstr(buf);
return cx_strdup(cx_strcast(line));
}
cxmutstr s;
s.ptr =
NULL;
s.length =
0;
return s;
}
cxmutstr cfg_trim_comment(cxmutstr line) {
cxmutstr nl = line;
for(
int i=
0;i<line.length;i++) {
if(line.ptr[i] ==
'#') {
if(i >
0) {
nl.ptr = line.ptr + i -
1;
nl.length = i;
break;
}
else {
nl.ptr = line.ptr;
nl.length =
0;
break;
}
}
}
return cx_strtrim_m(nl);
}
cxmutstr cfg_param(cxmutstr params, cxmutstr *name, cxmutstr *value) {
name->ptr =
NULL;
name->length =
0;
value->ptr =
NULL;
value->length =
0;
int i;
for(i=
0;i<params.length;i++) {
char c = params.ptr[i];
if(c ==
'=') {
break;
}
else if(c <
33) {
name->ptr = params.ptr;
name->length = i;
params.ptr = params.ptr + i;
params.length -= i;
return cx_strtrim_m(params);
}
}
name->ptr = params.ptr;
name->length = i;
i++;
if(i>=params.length) {
cxmutstr ns;
ns.ptr =
NULL;
ns.length =
0;
return ns;
}
int quote =
0;
value->ptr = params.ptr + i;
for(;i<params.length;i++) {
char c = params.ptr[i];
if(c ==
'""') {
if(quote) {
break;
}
else {
quote =
1;
value->ptr++;
}
}
else if(!quote && c <
33) {
break;
}
}
if(quote) {
value->length = i - name->length -
2;
i++;
}
else {
value->length = i - name->length -
1;
}
if(value->length <=
0) {
value->length =
0;
value->ptr =
NULL;
}
params.ptr += i;
params.length -= i;
return cx_strtrim_m(params);
}
cxmutstr cfg_param_get(ConfigParam *param, cxstring name) {
while(param !=
NULL) {
if(!cx_strcmp((cxstring){param->name.ptr, param->name.length}, name)) {
return param->value;
}
param = param->next;
}
return (cxmutstr){
NULL,
0 };
}
ConfigDirective* cfg_parse_directive(cxmutstr line, CxAllocator *mp) {
if(line.length <
6) {
ws_cfg_log(
LOG_FAILURE,
"cfg_parse_directive: line too short");
return NULL;
}
cxstring name;
int i;
for(i=
0;i<line.length;i++) {
if(line.ptr[i] <
33) {
break;
}
}
name.ptr = line.ptr;
name.length = i;
ConfigDirective *directive =
OBJ_NEW(mp, ConfigDirective);
directive->directive_type = cx_strdup_a(mp, name);
directive->type_num = cfg_get_directive_type_num(name);
directive->condition =
NULL;
cxstring param_str;
param_str.ptr = name.ptr + i;
param_str.length = line.length - i;
param_str = cx_strtrim(param_str);
directive->value = cx_strdup_a(mp, param_str);
return directive;
}
ConfigParam* cfg_param_list(cxmutstr param_str, CxAllocator *mp) {
cxmutstr pname;
cxmutstr pvalue;
ConfigParam *plist_begin =
NULL;
ConfigParam *plist_end =
NULL;
for(;;) {
param_str = cfg_param(param_str, &pname, &pvalue);
if(pname.length <=
0) {
break;
}
ConfigParam *param =
OBJ_NEW(mp, ConfigParam);
param->name = cx_strdup_a(mp, cx_strcast(pname));
param->next =
NULL;
if(pvalue.length >
0) {
param->value = cx_strdup_a(mp, cx_strcast(pvalue));
}
else {
param->value.ptr =
NULL;
param->value.length =
0;
}
CFG_PARAM_ADD(&plist_begin, &plist_end, param);
}
return plist_begin;
}
int cfg_get_directive_type_num(cxstring type) {
int dt = -
1;
if(cx_strcmp(type, cx_str(
"AuthTrans")) ==
0) {
dt = NSAPIAuthTrans;
}
else if(cx_strcmp(type, cx_str(
"NameTrans")) ==
0) {
dt = NSAPINameTrans;
}
else if(cx_strcmp(type, cx_str(
"PathCheck")) ==
0) {
dt = NSAPIPathCheck;
}
else if(cx_strcmp(type, cx_str(
"ObjectType")) ==
0) {
dt = NSAPIObjectType;
}
else if(cx_strcmp(type, cx_str(
"Service")) ==
0) {
dt = NSAPIService;
}
else if(cx_strcmp(type, cx_str(
"Error")) ==
0) {
dt = NSAPIError;
}
else if(cx_strcmp(type, cx_str(
"AddLog")) ==
0) {
dt = NSAPIAddLog;
}
else if(cx_strcmp(type, cx_str(
"Init")) ==
0) {
dt =
INIT_DIRECTIVE;
}
return dt;
}
int cfg_get_basic_type(cxmutstr line) {
if(line.length ==
0) {
return LINE_NOCONTENT;
}
else if(line.ptr[
0] ==
'#') {
return LINE_NOCONTENT;
}
return LINE_OTHER;
}
int cfg_get_line_type(cxmutstr line) {
if(line.length <
3) {
return LINE_ERROR;
}
if(line.ptr[
0] ==
'<') {
if(line.ptr[
1] ==
'/') {
return LINE_END_TAG;
}
else {
return LINE_BEGIN_TAG;
}
}
else {
return LINE_DIRECTIVE;
}
}
int cfg_get_tag_type(cxstring tag) {
if(!cx_strcmp(tag, cx_str(
"Object"))) {
return TAG_OBJECT;
}
else if(!cx_strcmp(tag, cx_str(
"If"))) {
return TAG_IF;
}
else if(!cx_strcmp(tag, cx_str(
"ElseIf"))) {
return TAG_ELSEIF;
}
else if(!cx_strcmp(tag, cx_str(
"Else"))) {
return TAG_ELSE;
}
else if(!cx_strcmp(tag, cx_str(
"Client"))) {
return TAG_CLIENT;
}
return -
1;
}
cxmutstr cfg_get_end_tag_name(cxmutstr line) {
cxmutstr ns;
ns.ptr =
NULL;
ns.length =
0;
if(line.length <
4) {
return ns;
}
cxmutstr name;
name.ptr = line.ptr +
2;
name.length = line.length -
3;
if(line.ptr[
0] !=
'<'
|| line.ptr[
1] !=
'/'
|| line.ptr[line.length -
1] !=
'>')
{
return ns;
}
return cx_strtrim_m(name);
}
ConfigTag* cfg_parse_begin_tag(cxmutstr line, CxAllocator *mp) {
if(line.length <
4) {
return NULL;
}
if(line.ptr[
0] !=
'<' || line.ptr[line.length -
1] !=
'>') {
return NULL;
}
cxmutstr name;
name.ptr = line.ptr +
1;
int i;
for(i=
1;i<line.length -
1;i++) {
if(line.ptr[i] <
33) {
break;
}
}
name.length = i -
1;
if(name.length <
1) {
return NULL;
}
ConfigTag *tag =
OBJ_NEW(mp, ConfigTag);
tag->name = cx_strdup_a(mp, cx_strcast(name));
tag->param =
NULL;
cxmutstr param_str;
param_str.ptr = line.ptr + i;
param_str.length = line.length - name.length -
2;
param_str = cx_strtrim_m(param_str);
if(param_str.length ==
0) {
return tag;
}
tag->param_str = cx_strdup_a(mp, cx_strcast(param_str));
cxmutstr pname;
cxmutstr pvalue;
for(;;) {
param_str = cfg_param(param_str, &pname, &pvalue);
if(pname.length ==
0) {
break;
}
ConfigParam *param =
OBJ_NEW(mp, ConfigParam);
param->next =
NULL;
param->name = cx_strdup_a(mp, cx_strcast(pname));
if(pvalue.length >
0) {
param->value = cx_strdup_a(mp, cx_strcast(pvalue));
}
else {
param->value.ptr =
NULL;
param->value.length =
0;
}
CFG_PARAM_ADD(&tag->param,
NULL, param);
}
return tag;
}