summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--Makefile17
-rw-r--r--example.ini19
-rw-r--r--nebula2.c251
4 files changed, 284 insertions, 5 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..9b9b0c1
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+*.o
+nebula2
diff --git a/Makefile b/Makefile
index f4e475c..81c41cb 100644
--- a/Makefile
+++ b/Makefile
@@ -1,11 +1,18 @@
-CC=gcc -Wall -Werror -pedantic -std=c99
-
-all:
+CC=gcc
+CFLAGS=-Wall -Werror -pedantic -std=c99 -static
+LIBS=-Liniparser -liniparser
+nebula2: nebula2.o iniparser/libiniparser.a
+ $(CC) $(CFLAGS) -o nebula2 nebula2.o iniparser/libiniparser.a
+iniparser/libiniparser.a:
+ make -C iniparser libiniparser.a
%.o:%.c
- $(CC) -c -o $@ $<
+ $(CC) $(CFLAGS) -c -o $@ $<
clean:
- rm -f *.o \ No newline at end of file
+ rm -f *.o
+
+nuke: clean
+ rm -f nebula2 \ No newline at end of file
diff --git a/example.ini b/example.ini
new file mode 100644
index 0000000..79826a7
--- /dev/null
+++ b/example.ini
@@ -0,0 +1,19 @@
+[nebula2]
+width=800
+height=600
+
+jobsize=100000
+jobs=10000
+procn=6
+
+statefile=example.state
+
+iter0=20
+iter1=200
+iter2=2000
+
+color0=ff0000
+color1=00ff00
+color2=0000ff
+
+output=example.bmp
diff --git a/nebula2.c b/nebula2.c
new file mode 100644
index 0000000..e22e255
--- /dev/null
+++ b/nebula2.c
@@ -0,0 +1,251 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "iniparser/src/iniparser.h"
+
+typedef struct {
+ int r, g, b;
+} color_t;
+
+typedef struct {
+ int width, height;
+ int jobsize, jobs, procn;
+
+ char* statefile;
+ char* output;
+
+ int iters_n;
+ int* iters;
+ color_t* colors;
+} config_t;
+
+void
+usage(void) {}
+
+void
+conf_destroy(config_t* conf) {
+ if(conf->iters) {
+ free(conf->iters);
+ }
+ if(conf->colors) {
+ free(conf->colors);
+ }
+ free(conf);
+}
+
+int
+parse_color(dictionary* ini, char* key, color_t* col) {
+ char r[3];
+ char g[3];
+ char b[3];
+ char* endptr;
+ char* s = iniparser_getstring(ini, key, "");
+
+ if(strlen(s) != 6) {
+ fprintf(stderr, "Config value '%s' is not a color or is missing.\n", key);
+ return 0;
+ }
+
+ memcpy(r, s, 2);
+ memcpy(g, s + 2, 2);
+ memcpy(b, s + 4, 2);
+ r[2] = '\0';
+ g[2] = '\0';
+ b[2] = '\0';
+
+ col->r = strtol(r, &endptr, 16);
+ if(*endptr != '\0') {
+ fprintf(stderr, "Config value '%s' is not a color.\n", key);
+ return 0;
+ }
+ col->g = strtol(g, &endptr, 16);
+ if(*endptr != '\0') {
+ fprintf(stderr, "Config value '%s' is not a color.\n", key);
+ return 0;
+ }
+ col->b = strtol(b, &endptr, 16);
+ if(*endptr != '\0') {
+ fprintf(stderr, "Config value '%s' is not a color.\n", key);
+ return 0;
+ }
+
+ return 1;
+}
+
+#define NAMEBUF_SIZE 32
+
+int
+conf_get_int(dictionary* ini, char* key, int* val) {
+ if(!iniparser_find_entry(ini, key)) {
+ fprintf(stderr, "Missing config key: %s\n", key);
+ return 0;
+ }
+
+ *val = iniparser_getint(ini, key, -1);
+
+ if(*val <= 0) {
+ fprintf(stderr, "Value for key '%s' is invalid.\n", key);
+ return 0;
+ }
+
+ return 1;
+}
+
+char*
+conf_get_string(dictionary* ini, char* key, char* def) {
+ char* _s;
+ char* s;
+ size_t l;
+
+ _s = iniparser_getstring(ini, key, def);
+
+ l = strlen(_s) + 1;
+ if(!(s = malloc(sizeof(char) * l))) {
+ return NULL;
+ }
+
+ return strcpy(s, _s);
+}
+
+int
+conf_load(char* path, config_t** conf) {
+ int i;
+ dictionary* ini = NULL;
+ char namebuf[NAMEBUF_SIZE];
+
+ if(!(*conf = malloc(sizeof(config_t)))) {
+ fputs("Could not allocate memory.\n", stderr);
+ goto failed;
+ }
+
+ (*conf)->iters = NULL;
+ (*conf)->colors = NULL;
+ (*conf)->statefile = NULL;
+ (*conf)->output = NULL;
+
+ if(!(ini = iniparser_load(path))) {
+ fputs("Could not parse ini file.\n", stderr);
+ goto failed;
+ }
+
+ if(
+ (!conf_get_int(ini, "nebula2:width", &((*conf)->width))) ||
+ (!conf_get_int(ini, "nebula2:height", &((*conf)->height))) ||
+ (!conf_get_int(ini, "nebula2:jobsize", &((*conf)->jobsize))) ||
+ (!conf_get_int(ini, "nebula2:jobs", &((*conf)->jobs))) ||
+ (!conf_get_int(ini, "nebula2:procn", &((*conf)->procn)))) {
+ goto failed;
+ }
+
+ if(!((*conf)->statefile = conf_get_string(ini, "nebula2:statefile", ""))) {
+ goto failed;
+ }
+ if(!((*conf)->output = conf_get_string(ini, "nebula2:output", ""))) {
+ goto failed;
+ }
+
+ for((*conf)->iters_n = 0;; ((*conf)->iters_n)++) {
+ if(snprintf(namebuf, NAMEBUF_SIZE, "nebula2:iter%d", (*conf)->iters_n) < 0) {
+ fputs("Error while counting iterX values.\n", stderr);
+ goto failed;
+ }
+
+ if(!iniparser_find_entry(ini, namebuf)) {
+ break;
+ }
+ }
+
+ if((*conf)->iters_n == 0) {
+ fputs("Need at least one iterX value.\n", stderr);
+ goto failed;
+ }
+
+ if(!((*conf)->iters = malloc(sizeof(int) * ((*conf)->iters_n)))) {
+ fputs("Could not allocate memory.\n", stderr);
+ goto failed;
+ }
+ if(!((*conf)->colors = malloc(sizeof(color_t) * ((*conf)->iters_n)))) {
+ fputs("Could not allocate memory.\n", stderr);
+ goto failed;
+ }
+
+ for(i = 0; i < (*conf)->iters_n; i++) {
+ if(snprintf(namebuf, NAMEBUF_SIZE, "nebula2:iter%d", i) < 0) {
+ fputs("Error while reading iterX values.\n", stderr);
+ goto failed;
+ }
+
+ if(!conf_get_int(ini, namebuf, &((*conf)->iters[i]))) {
+ goto failed;
+ }
+
+ if(snprintf(namebuf, NAMEBUF_SIZE, "nebula2:color%d", i) < 0) {
+ fputs("Error while reading colorX values.\n", stderr);
+ goto failed;
+ }
+
+ if(!parse_color(ini, namebuf, &((*conf)->colors[i]))) {
+ goto failed;
+ }
+ }
+
+ iniparser_freedict(ini);
+ return 1;
+
+failed:
+ if(*conf) {
+ conf_destroy(*conf);
+ *conf = NULL;
+ }
+ if(ini) {
+ iniparser_freedict(ini);
+ }
+ return 0;
+}
+
+void
+conf_print(config_t* conf) {
+ int i;
+ color_t col;
+
+ printf("width: %d\n", conf->width);
+ printf("height: %d\n", conf->height);
+ printf("jobsize: %d\n", conf->jobsize);
+ printf("jobs: %d\n", conf->jobs);
+ printf("procn: %d\n", conf->procn);
+ printf("statefile: %s\n", conf->statefile);
+ printf("output: %s\n", conf->output);
+
+ for(i = 0; i < conf->iters_n; i++) {
+ col = conf->colors[i];
+ printf("Iteration %d: %d, %02x%02x%02x\n", i, conf->iters[i], col.r, col.g, col.b);
+ }
+}
+
+int
+main(int argc, char** argv) {
+ int rv = 1;
+ config_t* conf = NULL;
+
+ if(argc < 2) {
+ usage();
+ goto tidyup;
+ }
+
+ if(!conf_load(argv[1], &conf)) {
+ goto tidyup;
+ }
+
+ conf_print(conf);
+
+ /*nebula2(conf);*/
+
+ rv = 0; /* All OK, we return with no error. */
+tidyup:
+ if(conf) {
+ conf_destroy(conf);
+ }
+
+ return rv;
+}