Files
cworker/clparser.c
2023-08-15 08:35:06 +02:00

194 lines
4.9 KiB
C

/*
* Copyright 2023 Oleg Borodin <borodin@unix7.org>
*/
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <logger.h>
#include <clparser.h>
#define INIT_BSIZE 64
static char* strcopy(char* src) {
size_t srcsize = strlen(src) + 1;
char* dst = malloc(srcsize);
memset(dst, '\0', srcsize);
strcpy(dst, src);
return dst;
}
static char* strconcat(char** str, int num) {
size_t tsize = 0;
size_t size[num];
for (int i = 0; i < num; i++) {
size[i] = 0;
if (str[i] != NULL) {
size[i] = strlen(str[i]);
tsize += size[i];
}
}
tsize++;
char* dst = malloc(tsize);
memset(dst, '\0', tsize);
int pos = 0;
for (int i = 0; i < num; i++) {
if (str[i] != NULL) {
strcpy(&dst[pos], str[i]);
pos += size[i];
}
}
return dst;
}
void clparser_init(clparser_t * parser, cllexer_t * lexer) {
parser->lexer = lexer;
parser->bindarr = malloc(sizeof(clbind_t) * INIT_BSIZE);
parser->bindcapa = INIT_BSIZE;
parser->bindsize = 0;
}
void clparser_bind(clparser_t * parser, int type, char* key, void* ref) {
if (parser->bindsize >= parser->bindcapa) {
return; // TODO
}
clbind_t* b = &(parser->bindarr[parser->bindsize]);
b->type = type;
b->key = key;
b->ref = ref;
parser->bindsize++;
}
#define MAX_TOKEN_SIZE 1024
static int clparser_compile(clparser_t * parser, char* arg, char** refkey, char** refval) {
cllexer_t* lex = parser->lexer;
cllexer_reset(lex, arg);
char token[MAX_TOKEN_SIZE];
int type = 0;
int pos = 0;
char* key;
char* vals[2] = { NULL };
while ((type = cllexer_gettoken(lex, token)) != CLLEXTOK_END) {
switch (pos) {
// POS 0
case 0:{
if (type == CLLEXTOK_KEY) {
pos++;
} else {
return -1;
}
break;
}
// POS 1
case 1:{
if (type == CLLEXTOK_WORD) {
key = strcopy(token);
pos++;
} else {
return -1;
}
break;
}
// POS 2
case 2:{
if (type == CLLEXTOK_SEP) {
pos++;
} else {
return -1;
}
break;
}
// POS 3
case 3:{
if (type == CLLEXTOK_WORD || type == CLLEXTOK_KEY) {
pos++;
vals[0] = strcopy(token);
} else {
return -1;
}
break;
}
// POS 4
case 4:{
if (type == CLLEXTOK_WORD) {
pos++;
vals[1] = strcopy(token);
} else {
return -1;
}
break;
}
default:{
return -1;
}
}
}
*refkey = key;
*refval = strconcat(vals, 2);
free(vals[0]);
free(vals[1]);
return 0;
}
int clparser_parse(clparser_t * parser, char** argv, int argc) {
for (int i = 0; i < argc; i++) {
char* key;
char* val;
if (clparser_compile(parser, argv[i], &key, &val) < 0) {
return -1;
}
for (int i = 0; i < parser->bindsize; i++) {
if (strcmp(parser->bindarr[i].key, key) == 0) {
switch (parser->bindarr[i].type) {
case CLVALTYPE_INT:{
char* eptr = NULL;
*(int *)(parser->bindarr[i].ref) = (int)strtol(val, &eptr, 10);
free(key);
free(val);
break;
}
case CLVALTYPE_STR:{
*(char **)(parser->bindarr[i].ref) = strcopy(val);
free(key);
free(val);
break;
}
case CLVALTYPE_BOOL:{
*(bool*)(parser->bindarr[i].ref) = false;
if (strcmp(val, "true") == 0) {
*(bool*)(parser->bindarr[i].ref) = true;
} else if (strcmp(val, "false") == 0) {
*(bool*)(parser->bindarr[i].ref) = false;
} else {
log_error("wrong boolean key value: %s = %s", key, val);
}
free(key);
free(val);
break;
}
}
}
}
}
return 0;
}
void clparser_destroy(clparser_t * parser) {
free(parser->bindarr);
}