basic argument parsing, sql setups and other preparations

This commit is contained in:
theBreadCompany 2025-06-03 06:16:37 +02:00
parent f9659e0430
commit 9399f71406
9 changed files with 392 additions and 0 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
cmake-*-debug
*.db

6
CMakeLists.txt Normal file
View file

@ -0,0 +1,6 @@
cmake_minimum_required(VERSION 3.31)
project(klist C)
set(CMAKE_C_STANDARD 90)
add_subdirectory(src)

1
src/CMakeLists.txt Normal file
View file

@ -0,0 +1 @@
add_subdirectory(main)

3
src/main/CMakeLists.txt Normal file
View file

@ -0,0 +1,3 @@
add_executable(klist main.c sql.c util.c)
target_include_directories(klist PRIVATE include)
target_link_libraries(klist sqlite3)

30
src/main/include/sql.h Normal file
View file

@ -0,0 +1,30 @@
#pragma once
enum KLIST_SQL {
INIT,
ADD_USER,
GET_USER,
GET_USERS,
MOD_USER_NAME,
MOD_USER_LOCAL,
MOD_USER_DISCORD,
MOD_USER_GOOGLE,
ADD_LIST,
GET_LIST,
GET_LISTS,
MOD_LIST_NAME,
DEL_LIST,
ADD_STAGE,
GET_STAGE,
GET_STAGES_FOR_LIST,
DEL_STAGE,
ADD_TASK,
GET_TASK,
GET_TASKS,
MOD_TASK_NAME,
MOD_TASK_DESCRIPTION,
DEL_TASK,
_KLIST_SQL_COUNT
};
char *klist_sql_get(const enum KLIST_SQL);

81
src/main/include/util.h Normal file
View file

@ -0,0 +1,81 @@
#pragma once
#include <sqlite3.h>
#include <sys/types.h>
/*
* command parsing
*/
enum klist_command {
USER,
LIST,
TASK,
};
struct klist {
sqlite3 *db;
sqlite3_stmt **stmts;
u_int cmd;
void *cmd_ctx;
int error;
};
typedef struct klist klist;
klist *klist_init(char *db);
void klist_deinit(klist *list);
enum klist_user_command {
USER_GET,
USER_DELETE
};
struct klist_user_context {
enum klist_command cmd;
};
typedef struct klist_user_context klist_user_context;
klist_user_context *klist_user_context_init(klist *list);
void klist_user_context_deinit(klist_user_context *ctx);
enum klist_list_command {
LIST_ADD,
LIST_EDIT,
LIST_GET,
LIST_DELETE,
};
struct klist_list_context {
enum klist_user_command cmd;
char *name;
char **stages;
};
typedef struct klist_list_context klist_list_context;
klist_list_context *klist_list_context_init(klist *list);
void klist_list_context_deinit(klist_list_context *ctx);
enum klist_task_command {
TASK_ADD,
TASK_EDIT,
TASK_GET,
TASK_DELETE,
};
struct klist_task_context {
enum klist_task_command cmd;
char *list;
char *name;
char *stage;
};
typedef struct klist_task_context klist_task_context;
klist_task_context *klist_task_context_init(klist *list);
void klist_task_context_deinit(klist_task_context *ctx);
/*
* sql preparations
*/
void klist_sql_prepare(klist *, char *db);

148
src/main/main.c Normal file
View file

@ -0,0 +1,148 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "util.h"
void print_help(char **argv);
void setup(klist *ctx, int argc, char **argv);
int main(int argc, char **argv) {
klist *ctx = klist_init("test.db");
if (argc == 1) {
print_help(argv);
ctx->error = 1;
}
if (!ctx->error) {
setup(ctx, argc, argv);
switch (ctx->cmd) {
case USER:
switch (((klist_list_context *)ctx->cmd_ctx)->cmd) {
case USER_GET:
case USER_DELETE:
default: ;
}
case LIST:
switch (((klist_user_context *)ctx->cmd_ctx)->cmd) {
case LIST_ADD:
case LIST_EDIT:
case LIST_GET:
case LIST_DELETE:
default: ;
}
case TASK:
switch (((klist_task_context *)ctx->cmd_ctx)->cmd) {
case TASK_ADD:
case TASK_EDIT:
case TASK_GET:
case TASK_DELETE:
default: ;
}
default: ;
}
}
const int error = ctx->error;
klist_deinit(ctx);
return error;
}
void print_help(char **argv) {
fprintf(stderr, "Usage: %s <action>\n", argv[0]);
}
void setup(klist *ctx, int argc, char **argv) {
if (strcmp(argv[1], "user") == 0)
ctx->cmd = USER;
else if (strcmp(argv[1], "list") == 0)
ctx->cmd = LIST;
else if (strcmp(argv[1], "task") == 0)
ctx->cmd = TASK;
else print_help(argv);
int opt;
switch (ctx->cmd) {
case USER:
optind = 2;
while ((opt = getopt(argc, argv, "dg")) != -1)
switch (opt) {
case 'd':
fprintf(stderr, "Deleting user %u\n", getuid());
break;
case 'g':
fprintf(stderr, "Printing user lists\n");
break;
default:
print_help(argv);
}
break;
case LIST:
if (argc < 3) {
fprintf(stderr, "Prints all lists.\n");
break;
}
klist_list_context *list_ctx = malloc(sizeof(struct klist_list_context));
optind = 3;
while ((opt = getopt(argc, argv, "aeds:")) != -1)
switch (opt) {
case 'a':
list_ctx->cmd = LIST_ADD;
break;
case 'e':
list_ctx->cmd = LIST_EDIT;
break;
case 'd':
list_ctx->cmd = LIST_DELETE;
break;
default:
print_help(argv);
fprintf(stderr, ""
"list options:"
"-a\tadd a list"
"-e\tedit a list"
"-d\tdelete a list"
"Not providing a parameter prints all lists.");
}
ctx->cmd_ctx = list_ctx;
break;
case TASK:
if (argc < 3) {
fprintf(stderr, "Prints all lists.\n");
break;
}
klist_list_context *task_ctx = malloc(sizeof(struct klist_task_context));
optind = 3;
while ((opt = getopt(argc, argv, "aeds:")) != -1)
switch (opt) {
case 'a':
task_ctx->cmd = TASK_ADD;
break;
case 'e':
task_ctx->cmd = TASK_EDIT;
break;
case 'd':
task_ctx->cmd = TASK_DELETE;
break;
default:
print_help(argv);
fprintf(stderr, ""
"task options:"
"-a\tadd a task"
"-e\tedit a task"
"-d\tdelete a task"
"Not providing a parameter prints all tasks of a list.");
}
ctx->cmd_ctx = task_ctx;
break;
default:
fprintf(stderr, "How did we land here?! Pls report argv[1] = %s\n", argv[1]);
print_help(argv);
}
}

67
src/main/sql.c Normal file
View file

@ -0,0 +1,67 @@
#include "include/sql.h"
char *klist_sql_get(const enum KLIST_SQL sql) {
switch (sql) {
case INIT: return
"create table if not exists users ("
" id integer primary key,"
" name text not null,"
" local_id integer, -- if the thing is running locally"
" discord_id integer, -- if logging in via web via discord"
" google_id integer -- if logging in via web via google"
");"
"create table if not exists user_lists ("
" id integer primary key,"
" user_id integer not null,"
" list_id integer not null"
");"
"create table if not exists lists ("
" id integer primary key,"
" name text not null,"
" desc text"
");"
"create table if not exists task_stages ("
" id integer primary key,"
" name text not null,"
" desc text,"
" list_id integer not null,"
" foreign key (list_id) references lists(id)"
");"
"-- this currently enables moving tasks _between lists_ (calculated of course)"
"create table if not exists tasks ("
" id integer primary key,"
" name text not null,"
" desc text,"
" stage integer not null,"
" due date,"
" due_stage integer, -- more like target stage"
" foreign key (stage) references task_stages(id),"
" foreign key (due_stage) references task_stages(id)"
")";
case ADD_USER: return "insert into users values (?1, ?2, ?3, ?4)";
case GET_USER: return "select * from users where id = ?1";
case GET_USERS: return "select * from users";
case MOD_USER_NAME: return "update users set name = ?1 where id = ?2";
case MOD_USER_LOCAL: return "update users set local_id = ?1 where id = ?2";;
case MOD_USER_DISCORD: return "update users set discord_id = ?1 where id = ?2";
case MOD_USER_GOOGLE: return "update users set google_id = ?1 where id = ?2";
case ADD_LIST: return "insert into lists values (?1, ?2)";
case GET_LIST: return "select * from lists where id = ?1";
case GET_LISTS: return "select * from lists";
case MOD_LIST_NAME: return "update lists set name = ?1 where id = ?2";
case DEL_LIST: return "delete from lists where id = ?1";
case ADD_STAGE: return "insert into task_stages values (?1, ?2, ?3)";
case GET_STAGE: return "select * from task_stages where id = ?1";
case GET_STAGES_FOR_LIST: return "select * from task_stages";
case DEL_STAGE: return "delete from task_stages where id = ?1";
case ADD_TASK: return "insert into tasks values (?1, ?2, ?3, ?4, ?5, ?6);";
case GET_TASK: return "select * from tasks where id = ?1";
case GET_TASKS: return "select * from tasks;";
case MOD_TASK_NAME: return "update tasks set name = ?1 where id = ?2";
case MOD_TASK_DESCRIPTION: return "update tasks set description = ?1 where id = ?2";
case DEL_TASK: return "delete from tasks where id = ?1";
case _KLIST_SQL_COUNT: return ";";
}
return "";
}

54
src/main/util.c Normal file
View file

@ -0,0 +1,54 @@
#include <stdlib.h>
#include <stdio.h>
#include "util.h"
#include "sql.h"
/*
* command parsing
*/
klist *klist_init(char *db) {
klist *ctx = malloc(sizeof(klist));
ctx->stmts = malloc(sizeof(sqlite3_stmt *) * _KLIST_SQL_COUNT);
ctx->cmd_ctx = NULL;
ctx->error = 0;
klist_sql_prepare(ctx, db);
return ctx;
}
void klist_deinit(klist *ctx) {
sqlite3_close(ctx->db);
if (ctx->cmd_ctx) free(ctx->cmd_ctx);
free(ctx->stmts);
free(ctx);
}
klist_user_context *klist_user_context_init(klist *list) {
klist_user_context *ctx = malloc(sizeof(klist_user_context));
return ctx;
}
void klist_user_context_deinit(klist_user_context *ctx);
klist_list_context *klist_list_context_init(klist *list);
void klist_list_context_deinit(klist_list_context *ctx);
klist_task_context *klist_task_context_init(klist *list);
void klist_task_context_deinit(klist_task_context *ctx);
/*
* sql preparations
*/
void klist_sql_prepare(klist *ctx, char *db) {
ctx->stmts = malloc(sizeof(sqlite3_stmt *) * _KLIST_SQL_COUNT);
sqlite3_open(db ? db : ":memory:", &ctx->db);
int i = 0;
for (i; i < _KLIST_SQL_COUNT; i++)
if (sqlite3_prepare(ctx->db, klist_sql_get(i), 0, &ctx->stmts[i], NULL) != SQLITE_OK)
fprintf(stderr, "sqlite3_prepare: %s\n", sqlite3_errmsg(ctx->db));
}