added support for numerical values in option struct
[libgliar] / src / cfg.c
1 /*
2 libgliar - a library that can fake the OpenGL context info returned by
3 the glGet OpenGL calls
4
5 Copyright (C) 2013 Canonical Ltd
6
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
20 Author: Eleni Maria Stea <elene.mst@gmail.com>
21 */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include "cfg.h"
28
29 static char *stripspace(char *s);
30
31
32 struct cfgopt *gliar_load_cfg(const char *fname)
33 {
34         FILE *fp;
35         char buf[512];
36         struct cfgopt *optlist = 0;
37         struct cfgopt *opt = 0;
38
39         if(!(fp = fopen(fname, "r"))) {
40                 return 0;
41         }
42
43         while(fgets(buf, sizeof buf, fp)) {
44                 char *line = stripspace(buf);
45
46                 if(!*line || *line == '#') {
47                         continue;
48                 }
49
50                 if(*line == '[') {
51                         char *end = strrchr(line, ']');
52                         if(!end) {
53                                 fprintf(stderr, "invalid config %s: %s\n", fname, line);
54                                 continue;
55                         }
56                         line++;
57                         *end = 0;
58
59                         if(opt) {
60                                 opt->next = optlist;
61                                 optlist = opt;
62                         }
63
64                         if((opt = malloc(sizeof *opt))) {
65                                 if((opt->key = malloc(strlen(line) + 1))) {
66                                         strcpy(opt->key, line);
67                                         opt->str_val = 0;
68           opt->num_val = 0;
69           opt->type = unknown;
70                                 } else {
71                                         free(opt);
72                                         opt = 0;
73                                 }
74                         }
75                 } else {
76                         char *tmp;
77                         int prev_len = opt->str_val ? strlen(opt->str_val) : 0;
78
79                         if(opt && (tmp = realloc(opt->str_val, prev_len + strlen(line) + 2))) {
80         opt->type = str;
81                                 opt->str_val = tmp;
82                                 if(prev_len) {
83                                         strcat(opt->str_val, " ");
84                                         strcat(opt->str_val, line);
85                                 } else {
86                                         strcpy(opt->str_val, line);
87                                 }
88                         }
89                 }
90         }
91
92         if(opt) {
93                 opt->next = optlist;
94                 optlist = opt;
95         }
96
97         fclose(fp);
98         return optlist;
99 }
100
101 const char *gliar_find_opt(struct cfgopt *list, const char *name)
102 {
103         if(!list || !name) {
104                 return 0;
105         }
106
107         while(list) {
108                 if(strcmp(list->key, name) == 0) {
109                         return list->str_val;
110                 }
111                 list = list->next;
112         }
113         return 0;
114 }
115
116 void gliar_print_opt(struct cfgopt *list)
117 {
118         printf("OPTIONS\n");
119         while(list) {
120                 printf("\"%s\" -> \"%s\"\n", list->key, list->str_val);
121                 list = list->next;
122         }
123 }
124
125 static char *stripspace(char *s)
126 {
127         char *end = s + strlen(s) - 1;
128
129         while(isspace(*s)) s++;
130
131         while(isspace(*end)) {
132                 *end-- = 0;
133         }
134         return s;
135 }