#include "conf.h"
#include <string.h>
int cfg_parse_basic_file(ConfigParser *parser,
FILE *in) {
parser->lines =
NULL;
UcxMempool *mp = ucx_mempool_new(
512);
parser->mp = mp->allocator;
sstr_t mline;
mline.ptr =
NULL;
mline.length =
0;
ConfigLine *start_line;
ConfigLine *end_line;
sstr_t l;
while((l = cfg_readln(in)).ptr !=
NULL) {
void *org_ptr = l.ptr;
ConfigLine *line =
OBJ_NEW(parser->mp, ConfigLine);
line->line = sstrdup_a(parser->mp, l);
line->object =
NULL;
line->type =
LINE_OTHER;
if(parser->lines) {
parser->lines = ucx_list_append_a(parser->mp, parser->lines, line);
}
else {
parser->lines = ucx_list_append_a(parser->mp, parser->lines, line);
}
l = cfg_trim_comment(l);
line->type = cfg_get_basic_type(l);
if(line->type ==
LINE_OTHER) {
if(mline.ptr !=
NULL) {
char *ptr = ucx_mempool_malloc(
mp,
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 = sstrdup_a(parser->mp, l);
start_line = line;
}
}
else {
sstr_t 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;
}
sstr_t cfg_readln(
FILE *file) {
sstr_t 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;
}
sstr_t line = sstr(buf);
return sstrdup(line);
}
sstr_t s;
s.ptr =
NULL;
s.length =
0;
return s;
}
sstr_t cfg_trim_comment(
sstr_t line) {
sstr_t 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 sstrtrim(nl);
}
sstr_t cfg_param(
sstr_t params,
sstr_t *name,
sstr_t *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 sstrtrim(params);
}
}
name->ptr = params.ptr;
name->length = i;
i++;
if(i>=params.length) {
sstr_t 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 sstrtrim(params);
}
sstr_t cfg_param_get(UcxList *list,
sstr_t name) {
while(list !=
NULL) {
ConfigParam *param = list->data;
if(!sstrcmp(param->name, name)) {
return param->value;
}
list = list->next;
}
sstr_t ns;
ns.ptr =
NULL;
ns.length =
0;
return ns;
}
ConfigDirective* cfg_parse_directive(
sstr_t line, UcxAllocator *mp) {
if(line.length <
6) {
log_ereport(
LOG_FAILURE,
"cfg_parse_directive: line too short");
return NULL;
}
sstr_t 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 = sstrdup_a(mp, name);
directive->type_num = cfg_get_directive_type_num(name);
directive->condition =
NULL;
sstr_t param_str;
param_str.ptr = name.ptr + i;
param_str.length = line.length - i;
param_str = sstrtrim(param_str);
directive->value = sstrdup_a(mp, param_str);
return directive;
}
UcxList* cfg_param_list(
sstr_t param_str, UcxAllocator *mp) {
sstr_t pname;
sstr_t pvalue;
UcxList *plist =
NULL;
for(;;) {
param_str = cfg_param(param_str, &pname, &pvalue);
if(pname.length <=
0) {
break;
}
ConfigParam *param =
OBJ_NEW(mp, ConfigParam);
param->name = sstrdup_a(mp, pname);
if(pvalue.length >
0) {
param->value = sstrdup_a(mp, pvalue);
}
else {
param->value.ptr =
NULL;
param->value.length =
0;
}
plist = ucx_list_append_a(mp, plist, param);
}
return plist;
}
int cfg_get_directive_type_num(
sstr_t type) {
int dt = -
1;
if(sstrcmp(type, sstr(
"AuthTrans")) ==
0) {
dt = NSAPIAuthTrans;
}
else if(sstrcmp(type, sstr(
"NameTrans")) ==
0) {
dt = NSAPINameTrans;
}
else if(sstrcmp(type, sstr(
"PathCheck")) ==
0) {
dt = NSAPIPathCheck;
}
else if(sstrcmp(type, sstr(
"ObjectType")) ==
0) {
dt = NSAPIObjectType;
}
else if(sstrcmp(type, sstr(
"Service")) ==
0) {
dt = NSAPIService;
}
else if(sstrcmp(type, sstr(
"Error")) ==
0) {
dt = NSAPIError;
}
else if(sstrcmp(type, sstr(
"AddLog")) ==
0) {
dt = NSAPIAddLog;
}
else if(sstrcmp(type, sstr(
"Init")) ==
0) {
dt =
INIT_DIRECTIVE;
}
return dt;
}
int cfg_get_basic_type(
sstr_t line) {
if(line.length ==
0) {
return LINE_NOCONTENT;
}
else if(line.ptr[
0] ==
'#') {
return LINE_NOCONTENT;
}
return LINE_OTHER;
}
int cfg_get_line_type(
sstr_t 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(
sstr_t tag) {
if(!sstrcmp(tag, sstr(
"Object"))) {
return TAG_OBJECT;
}
else if(!sstrcmp(tag, sstr(
"If"))) {
return TAG_IF;
}
else if(!sstrcmp(tag, sstr(
"ElseIf"))) {
return TAG_ELSEIF;
}
else if(!sstrcmp(tag, sstr(
"Else"))) {
return TAG_ELSE;
}
else if(!sstrcmp(tag, sstr(
"Client"))) {
return TAG_CLIENT;
}
return -
1;
}
sstr_t cfg_get_end_tag_name(
sstr_t line) {
sstr_t ns;
ns.ptr =
NULL;
ns.length =
0;
if(line.length <
4) {
return ns;
}
sstr_t 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 sstrtrim(name);
}
ConfigTag* cfg_parse_begin_tag(
sstr_t line, UcxAllocator *mp) {
if(line.length <
4) {
return NULL;
}
if(line.ptr[
0] !=
'<' || line.ptr[line.length -
1] !=
'>') {
return NULL;
}
sstr_t 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 = sstrdup_a(mp, name);
tag->param =
NULL;
sstr_t param_str;
param_str.ptr = line.ptr + i;
param_str.length = line.length - name.length -
2;
param_str = sstrtrim(param_str);
if(param_str.length ==
0) {
return tag;
}
tag->param_str = sstrdup_a(mp, param_str);
sstr_t pname;
sstr_t pvalue;
for(;;) {
param_str = cfg_param(param_str, &pname, &pvalue);
if(pname.length ==
0) {
break;
}
ConfigParam *param =
OBJ_NEW(mp, ConfigParam);
param->name = sstrdup_a(mp, pname);
if(pvalue.length >
0) {
param->value = sstrdup_a(mp, pvalue);
}
else {
param->value.ptr =
NULL;
param->value.length =
0;
}
tag->param = ucx_list_append_a(mp, tag->param, param);
}
return tag;
}
ConfigDirective* cfg_directivelist_get(UcxList *dirs,
sstr_t name) {
while(dirs !=
NULL) {
ConfigDirective *d = dirs->data;
if(d !=
NULL) {
if(!sstrcmp(d->directive_type, name)) {
return d;
}
}
dirs = dirs->next;
}
return NULL;
}
sstr_t cfg_directivelist_get_str(UcxList *dirs,
sstr_t name) {
ConfigDirective *d = cfg_directivelist_get(dirs, name);
if(d ==
NULL) {
sstr_t n;
n.ptr =
NULL;
n.length =
0;
return n;
}
return d->value;
}
static void cfg_list_free(
void *list) {
ucx_list_free(list);
}
static void cfg_map_free(
void *map) {
ucx_map_free(map);
}
void cfg_map_destr(UcxMempool *mp, UcxMap *map) {
if(map) {
ucx_mempool_reg_destr(mp, map, cfg_map_free);
}
}