main.c (2767B)
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <dlfcn.h> 5 #include <time.h> 6 #include <wchar.h> 7 8 typedef struct { 9 char *uid; 10 void *handle; 11 long (*perform)(char *data); 12 } task_t; 13 14 char *load_data(char *task_uid) { 15 // convert YEAR_MT_ST to YEAR_MT 16 int task_uid_len = strlen(task_uid); 17 int idx = 0; 18 for (int i = 0; i < task_uid_len; i++) { 19 char c = task_uid[i]; 20 if (c == '_') { 21 idx = i; 22 } 23 } 24 char task_uid_base[idx + 1]; 25 snprintf(task_uid_base, idx + 1, "%s", task_uid); 26 char filename[100]; 27 snprintf(filename, 100, "txt/%s.txt", task_uid_base); 28 FILE *fp = fopen(filename, "r"); 29 if (fp == NULL) { 30 return NULL; 31 } 32 fseek(fp, 0, SEEK_END); 33 int len = ftell(fp); 34 fseek(fp, 0, SEEK_SET); 35 char *data = calloc(len + 1, sizeof(char)); 36 fread(data, sizeof(char), len, fp); 37 data[len] = '\0'; 38 return data; 39 } 40 41 void load_task(task_t *task, char *task_uid) { 42 task->uid = task_uid; 43 char cmd[100]; 44 snprintf(cmd, 100, "cc -shared -fPIC -o %s.so -Werror -Wextra -Wall -lm -pedantic src/tasks/aoc_%s.c", task_uid, task_uid); 45 FILE *fp = popen(cmd, "r"); 46 if (fp == NULL) { 47 return; 48 } 49 pclose(fp); 50 char filename[100]; 51 snprintf(filename, 100, "./%s.so", task_uid); 52 task->handle = dlopen(filename, RTLD_LAZY); 53 if (task->handle == NULL) { 54 printf("Error: failed to load task %s!\n%s\n", task_uid, dlerror()); 55 return; 56 } 57 task->perform = dlsym(task->handle, "perform"); 58 char *err = dlerror(); 59 if (err != 0) { 60 printf("Error: failed to link task function %s!\n%s\n", task_uid, err); 61 return; 62 } 63 } 64 65 void unload_task(task_t *task) { 66 if (task == NULL || task->handle == NULL) { 67 return; 68 } 69 dlclose(task->handle); 70 char cmd[100]; 71 snprintf(cmd, 100, "rm %s.so", task->uid); 72 FILE *fp = popen(cmd, "r"); 73 if (fp == NULL) { 74 return; 75 } 76 pclose(fp); 77 } 78 79 int main(int argc, char **argv) { 80 if (argc < 2) { 81 printf("Error: Usage: aoc <task-id>\n"); 82 return 1; 83 } 84 char *task_uid = argv[1]; 85 task_t task = { NULL, NULL, NULL }; 86 load_task(&task, task_uid); 87 if (task.handle == NULL) { 88 return 1; 89 } 90 char *data = load_data(task_uid); 91 printf("task_uid: %s\n", task_uid); 92 struct timespec time_set; 93 clock_gettime(CLOCK_MONOTONIC, &time_set); 94 long result = task.perform(data); 95 struct timespec time_end; 96 clock_gettime(CLOCK_MONOTONIC, &time_end); 97 unload_task(&task); 98 if (data != NULL) { 99 free(data); 100 } 101 long dur_sec = time_end.tv_sec - time_set.tv_sec; 102 long dur_ns = time_end.tv_nsec - time_set.tv_nsec; 103 long dur_ms = dur_ns / 1000000; 104 long dur_ys = (dur_ns / 1000) % 1000; 105 dur_ns = dur_ns % 1000; 106 printf("time: %lds %ldms %ldµs %ldns\n", dur_sec, dur_ms, dur_ys, dur_ns); 107 printf("result: %ld\n", result); 108 return 0; 109 }