2 * matdb-dotcode: reads in Craig's Dotcode materials database.
6 Copyright (C) 2008 Joseph Pingenot
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU Affero General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU Affero General Public License for more details.
18 You should have received a copy of the GNU Affero General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include <matdb-dotcode.h>
29 void insert_into_matdb(struct matdb *mdb, struct matdb_material **mat, struct matdb_bowing **bow) {
32 fprintf(stderr, "inserting material %s\n", (*mat)->name->str);
34 g_hash_table_insert(mdb->materials, (gpointer)g_strdup((*mat)->name->str), (gpointer)(*mat));
39 fprintf(stderr, "inserting bowing %s:%s\n", (*bow)->from->str, (*bow)->to->str);
41 g_hash_table_insert(mdb->bowings, (gpointer)g_strdup((*bow)->from->str), (gpointer)(*bow));
46 /*Functions to be used by the hash.*/
47 static void destroy_string(gpointer data) {
50 static void destroy_double(gpointer data){
54 /*Removes leading and trailing whitespace, comments, and reduces
55 redundant whitespace down to one tab, makes an empty line an empty string.*/
56 static void prettify_line(char *line) {
59 register int in_whitespace;
60 register int leading_whitespace;
61 for(look=write=line, in_whitespace=0, leading_whitespace=1; *look != '\0'; look++) {
63 fprintf(stderr, " look=%d(%c) write=%d(%c) in_whitespace=%d leading_whitespace=%d: ", (look-line), *look, (write-line), *write, in_whitespace, leading_whitespace);
67 fprintf(stderr, "comment\n");
77 fprintf(stderr, "whitespace\n");
79 if((!leading_whitespace) && (!in_whitespace)) *write++ = '\t';
84 fprintf(stderr, "default\n");
87 in_whitespace=leading_whitespace=0;
91 for(look=write=line; *look != '\0'; look++) {
96 if(*(look+1) == '\0') {
105 * 1: failure malloc'ing / initializing mdb struct
106 * 2: failure opening file.
107 * 4: failure reading line.
108 * 8: warning reading line: no tab separator (line parsing error)
109 * 16: warning reading line: bad section declaration
110 * 32: warning reading line: unable to allocate material struct.
111 * 64: warning reading line: ignored line (unallocated material struct)
112 * 128: warning reading line: unable to allocate bowing struct
113 * 256: warning reading line: ignored line (unallocated bowing struct)
114 * 512: warning reading file: improper section detected (programming
116 *1024: warning reading file: no : separator in bowing materials
118 *2048: warning reading file: unable to read numeric value for property.
120 struct matdb* read_matdb_dotcode(const GString *name, int* err) {
122 fprintf(stderr, "in read_matdb_dotcode(%s, %d)\n", name->str, *err);
125 struct matdb *mdb = (struct matdb*)malloc(sizeof(struct matdb));
126 if(mdb == NULL) {*err = 1; return NULL;}
129 if((mdb->materials = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_material_gpointer)) == NULL) {
134 if((mdb->bowings = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_bowing_gpointer)) == NULL) {
136 g_hash_table_unref(mdb->materials);
140 struct matdb_material *mat = NULL;
141 struct matdb_bowing *bow = NULL;
143 * 0 (no/global section)
150 FILE *infile = fopen(name->str, "r");
152 g_hash_table_unref(mdb->materials);
153 g_hash_table_unref(mdb->bowings);
159 fprintf(stderr, "infile=%x\n", (unsigned int)infile);
163 while(!feof(infile)) {
165 fprintf(stderr, "mat=%x(%s), bow=%x(%s:%s)\n", (unsigned int)mat, mat?mat->name->str:"", (unsigned int)bow, bow?bow->from->str:"", bow?bow->to->str:"");
168 if((val = getline(&line, &n, infile)) == -1) {
170 fprintf(stderr, "getline returned %d\n", val);
172 if(!feof(infile)) *err = 4;
177 fprintf(stderr, "line=(%s)\n", line);
181 fprintf(stderr, "%d: prettified line=(%s)\n", section, line);
187 char *i = index(line, '\t');
192 /*At this point, we have line which stores the first word on the
193 line, and i which stores the second word on the line.
198 fprintf(stderr, "part_a=(%s) part_b=(%s)\n", line, i);
200 /*If we have a material or bowing underway, save it off*/
201 if(strcasecmp(line, "material") == 0) {
202 insert_into_matdb(mdb, &mat, &bow);
203 if((mat = (struct matdb_material*)malloc(sizeof(struct matdb_material))) == NULL) {
206 if((mat->name = g_string_new(i)) == NULL) {
212 if((mat->properties = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_double)) == NULL) {
214 g_string_free(mat->name, TRUE);
220 fprintf(stderr, "new material (%s):\n", i);
223 }else if(strcasecmp(line, "bow") == 0) {
224 insert_into_matdb(mdb, &mat, &bow);
225 if((bow = (struct matdb_bowing*)malloc(sizeof(struct matdb_bowing))) == NULL) {
228 if((to = index(i, ':')) == NULL) {
235 /*Same trick as before, but i now stores the from material,
236 and to the to material
238 if((bow->from = g_string_new(i)) == NULL) {
244 if((bow->to = g_string_new(to)) == NULL) {
246 g_string_free(bow->from, TRUE);
251 if((bow->properties = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_double)) == NULL) {
253 g_string_free(bow->to, TRUE);
254 g_string_free(bow->from, TRUE);
260 fprintf(stderr, "new bowing (%s:%s):\n", i, to);
264 /*Process a property.*/
267 ht = mat->properties;
270 ht = bow->properties;
277 if((value = (double*)malloc(sizeof(double))) == NULL) {
281 if(sscanf(" %g", i, value) != 1) {
285 g_hash_table_insert(ht, (gpointer)g_strdup(i), (gpointer)value);
287 fprintf(stderr, "\t%d/%s\t%g(%s)\n", section, line, *value, i);
295 insert_into_matdb(mdb, &mat, &bow);