-
Eric Vidal authoredEric Vidal authored
parse_split_from_section.c 6.27 KiB
/*
* parse_split_from_section.c
*
* Copyright (c) 2018-2024 Eric Vidal <eric@obarun.org>
*
* All rights reserved.
*
* This file is part of Obarun. It is subject to the license terms in
* the LICENSE file found in the top-level directory of this
* distribution.
* This file may not be copied, modified, propagated, or distributed
* except according to the terms contained in the LICENSE file./
*/
#include <string.h>
#include <sys/types.h>
#include <oblibs/stack.h>
#include <oblibs/log.h>
#include <oblibs/sastr.h>
#include <oblibs/string.h>
#include <oblibs/mill.h>
#include <skalibs/stralloc.h>
#include <skalibs/types.h> //UINT_FMT
#include <66/parse.h>
#include <66/resolve.h>
#include <66/enum.h>
static ssize_t parse_get_previous_element(stralloc *sa, size_t where)
{
size_t n = sastr_nelement(sa) ;
n-- ;
if ((n - where) < n)
return -1 ;
return sastr_find_element_byid(sa,n - where) ;
}
/* *
* For now the ability to comment an entire section when
* commenting the section name is not available anymore
* */
int parse_split_from_section(resolve_service_t *res, stralloc *secname, char *str, char const *svname)
{
log_flow() ;
int e = 0, r = 0, found = 0 ;
key_all_t const *list = total_list ;
// cpos -> current, ipos -> idx pos, tpos -> temporary pos, end -> end the parse process
size_t len = strlen(str), cpos = 0, ipos = 0, tpos = 0, end = 0 ;
char tline[len + 1] ;
char store[len + UINT_FMT + 1] ; // +6 be paranoid
char *line ;
memset(store, 0, sizeof(char) * (len + UINT_FMT + 1)) ;
// find the name of the current section
ssize_t previous_sec = parse_get_previous_element(secname, 0) ;
if (previous_sec == -1) {
log_warn("get previous section") ;
goto err ;
}
int id = get_enum_by_key(secname->s + previous_sec) ;
if (id < 0) {
log_warn("invalid section name: ", secname->s + previous_sec, " for service: ", svname) ;
goto err ;
}
log_trace("parsing section: ", secname->s + previous_sec) ;
if (!strcmp(secname->s + previous_sec, enum_str_section[SECTION_ENV])) {
str[strlen(str)] = 0 ;
if (!parse_store_g(res, str, SECTION_ENV, KEY_ENVIRON_ENVAL)) {
log_warnu("store resolve file of: ", svname) ;
goto err ;
}
goto end ;
}
while(cpos < len) {
ipos = 0 ;
tpos = 0 ;
end = 0 ;
line = (char *)str + cpos ; // (char *) shut up compiler
/** comment must be the first character found
* at the begin of the line */
if (line[tpos] == '#') {
cpos += get_len_until(line, '\n') + 1 ;
continue ;
}
// empty line or no more key=value?
while (get_sep_before(line, '=', '\n') < 1){
// Try to see if it's an empty line.
r = get_len_until(line, '\n') ;
if (r < 0) {
// end of string
end++ ;
break ;
}
cpos += r + 1 ; // +1 to remove '\n'
if (cpos >= len) {
// end of string
end++ ;
break ;
}
line = (char *)str + cpos ;
}
if (end)
break ;
// get a cleaned key string
wild_zero_all(&MILL_GET_KEY) ;
_init_stack_(stk, strlen(line) + 1) ;
r = mill_element(&stk, line, &MILL_GET_KEY, &tpos) ;
if (r < 1) {
log_warnu("get key at frontend service file of service: ", svname, " from line: ", line, " -- please make a bug report") ;
goto err ;
} else if (!r || tpos + cpos >= len) {
// '=' was not find or end of string?
break ;
}
if (!stack_close(&stk)) {
log_warnu("stack overflow") ;
goto err ;
}
// copy the string to parse
auto_strings(tline, line) ;
tpos = 0 ;
// loop around all keys from the section
while (*total_list[id].list[ipos].name) {
found = 0 ;
// look for a valid key name
if (*list[id].list[ipos].name && !strcmp(stk.s, *list[id].list[ipos].name)) {
found = 1 ;
log_trace("parsing key: ", get_key_by_key_all(id, ipos)) ;
switch(list[id].list[ipos].expected) {
case EXPECT_QUOTE:
r = get_len_until(tline, '\n') ;
if (r >= 0)
/** user migth forgot to close the double-quotes.
* so, only keep the line and not the complete string
* +1 for the parse_line_g which search for the '\n' character */
tline[r + 1] = 0 ;
wild_zero_all(&MILL_GET_DOUBLE_QUOTE) ;
if (!parse_line_g(store, &MILL_GET_DOUBLE_QUOTE, tline, &tpos))
parse_error_return(0, 6, id, ipos) ;
break ;
case EXPECT_BRACKET:
if (!parse_parentheses(store, tline, &tpos))
parse_error_return(0, 6, id, ipos) ;
break ;
case EXPECT_LINE:
case EXPECT_UINT:
case EXPECT_SLASH:
wild_zero_all(&MILL_GET_VALUE) ;
if (!parse_line_g(store, &MILL_GET_VALUE, tline, &tpos))
parse_error_return(0, 6, id, ipos) ;
break ;
default:
return 0 ;
}
}
cpos += tpos ;
if (found) {
if (!parse_store_g(res, store, id, ipos)) {
log_warnu("store resolve file of: ", svname) ;
goto err ;
} ;
break ;
}
ipos++ ;
}
if (!found && r >= 0) {
log_warn("unknown key: ", store," : in section: ", secname->s + previous_sec, " -- ignoring it") ;
tpos = get_len_until(line, '\n') ;
cpos += tpos + 1 ;
}
}
end:
e = 1 ;
err:
return e ;
}