comparison config.c @ 803:236a184bf6f0

Merge
author Michael Pavone <pavone@retrodev.com>
date Sun, 26 Jul 2015 16:51:03 -0700
parents 0b692b5d154b
children 7ed55a361e79
comparison
equal deleted inserted replaced
802:6811f601008f 803:236a184bf6f0
7 #include "util.h" 7 #include "util.h"
8 #include <stdio.h> 8 #include <stdio.h>
9 #include <stdlib.h> 9 #include <stdlib.h>
10 #include <string.h> 10 #include <string.h>
11 11
12 #define MAX_NEST 30 //way more than I'll ever need 12 #ifdef __MINGW64_VERSION_MAJOR
13 #define MINGW_W64_VERSION (__MINGW64_VERSION_MAJOR * 1000 + __MINGW64_VERSION_MINOR)
14 #else
15 #define MINGW_W64_VERSION 0
16 #endif
13 17
14 #ifdef _WIN32 18 #if defined(_WIN32) && (MINGW_W64_VERSION < 3003)
15 char * strtok_r(char * input, char * sep, char ** state) 19 char * strtok_r(char * input, char * sep, char ** state)
16 { 20 {
17 if (input) { 21 if (input) {
18 *state = input; 22 *state = input;
19 } 23 }
30 } 34 }
31 return NULL; 35 return NULL;
32 } 36 }
33 #endif 37 #endif
34 38
35 tern_node * parse_config(char * config_data) 39 tern_node * parse_config_int(char **state, int started, int *line)
36 { 40 {
37 char *state, *curline; 41 char *config_data, *curline;
38 char *prefix = NULL;
39 int nest_level = 0;
40 char * prefix_parts[MAX_NEST];
41 int line = 1;
42 tern_node * head = NULL; 42 tern_node * head = NULL;
43 while ((curline = strtok_r(config_data, "\n", &state))) 43 config_data = started ? NULL : *state;
44 while ((curline = strtok_r(config_data, "\n", state)))
44 { 45 {
46
45 config_data = NULL; 47 config_data = NULL;
46 curline = strip_ws(curline); 48 curline = strip_ws(curline);
47 int len = strlen(curline); 49 int len = strlen(curline);
48 if (!len) { 50 if (!len) {
51 *line = *line + 1;
49 continue; 52 continue;
50 } 53 }
51 if (curline[0] == '#') { 54 if (curline[0] == '#') {
55 *line = *line + 1;
52 continue; 56 continue;
53 } 57 }
54 if (curline[0] == '}') { 58 if (curline[0] == '}') {
55 if (!nest_level) { 59 if (started) {
56 fprintf(stderr, "unexpected } on line %d\n", line); 60 return head;
57 exit(1);
58 } 61 }
59 if (prefix) { 62 fatal_error("unexpected } on line %d\n", *line);
60 free(prefix);
61 prefix = NULL;
62 }
63 nest_level--;
64 curline = strip_ws(curline+1);
65 } 63 }
64
66 char * end = curline + len - 1; 65 char * end = curline + len - 1;
67 if (*end == '{') { 66 if (*end == '{') {
68 *end = 0; 67 *end = 0;
69 curline = strip_ws(curline); 68 curline = strip_ws(curline);
70 prefix_parts[nest_level++] = curline; 69 *line = *line + 1;
71 if (prefix) { 70 head = tern_insert_node(head, curline, parse_config_int(state, 1, line));
72 free(prefix);
73 prefix = NULL;
74 }
75 } else { 71 } else {
76 if (nest_level && !prefix) {
77 prefix = alloc_concat_m(nest_level, prefix_parts);
78 }
79 char * val = strip_ws(split_keyval(curline)); 72 char * val = strip_ws(split_keyval(curline));
80 char * key = curline; 73 char * key = curline;
81 if (*key) { 74 if (*val) {
82 if (prefix) {
83 key = alloc_concat(prefix, key);
84 }
85 head = tern_insert_ptr(head, key, strdup(val)); 75 head = tern_insert_ptr(head, key, strdup(val));
86 if (prefix) { 76 } else {
87 free(key); 77 fprintf(stderr, "Key %s is missing a value on line %d\n", key, *line);
88 }
89 } 78 }
79 *line = *line + 1;
90 } 80 }
91 } 81 }
92 if (prefix) {
93 free(prefix);
94 }
95 return head; 82 return head;
83 }
84
85 tern_node * parse_config(char * config_data)
86 {
87 int line = 1;
88 return parse_config_int(&config_data, 0, &line);
96 } 89 }
97 90
98 tern_node * parse_config_file(char * config_path) 91 tern_node * parse_config_file(char * config_path)
99 { 92 {
100 tern_node * ret = NULL; 93 tern_node * ret = NULL;
104 } 97 }
105 long config_size = file_size(config_file); 98 long config_size = file_size(config_file);
106 if (!config_size) { 99 if (!config_size) {
107 goto config_empty; 100 goto config_empty;
108 } 101 }
109 char * config_data = malloc(config_size); 102 char * config_data = malloc(config_size+1);
110 if (fread(config_data, 1, config_size, config_file) != config_size) { 103 if (fread(config_data, 1, config_size, config_file) != config_size) {
111 goto config_read_fail; 104 goto config_read_fail;
112 } 105 }
106 config_data[config_size] = '\0';
107
113 ret = parse_config(config_data); 108 ret = parse_config(config_data);
114 config_read_fail: 109 config_read_fail:
115 free(config_data); 110 free(config_data);
116 config_empty: 111 config_empty:
117 fclose(config_file); 112 fclose(config_file);
143 success: 138 success:
144 if (ret) { 139 if (ret) {
145 return ret; 140 return ret;
146 } 141 }
147 no_config: 142 no_config:
148 fputs("Failed to find a config file in ~/.config/blastem/blastem.cfg or in the blastem executable directory\n", stderr); 143 fatal_error("Failed to find a config file in ~/.config/blastem/blastem.cfg or in the blastem executable directory\n");
149 exit(1); 144 //this will never get reached, but the compiler doesn't know that. Let's make it happy
145 return NULL;
150 } 146 }
151 147