Convert tabs to spaces. Remove accidently committed debug line
[xiph/unicode.git] / postfish / config.c
blob046e979f9360a24c3884df3b9525ec5c70951fab
1 /*
3 * postfish
4 *
5 * Copyright (C) 2002-2005 Monty
7 * Postfish 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 2, or (at your option)
10 * any later version.
12 * Postfish 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.
17 * You should have received a copy of the GNU General Public License
18 * along with Postfish; see the file COPYING. If not, write to the
19 * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "postfish.h"
25 #include "config.h"
26 #include <errno.h>
27 #include <string.h>
28 #include <ctype.h>
30 typedef struct {
31 char *key;
32 int bank;
33 int A;
34 int B;
35 int C;
36 int vals;
37 int *vec;
38 char *string;
39 } configentry;
41 static int configentries=0;
42 static configentry *config_list=0;
44 static int look_for_key(char *key,int bank,int A, int B, int C){
45 int i;
46 for(i=0;i<configentries;i++)
47 if(!strcmp(key,config_list[i].key) &&
48 config_list[i].bank==bank &&
49 config_list[i].A==A &&
50 config_list[i].B==B &&
51 config_list[i].C==C)return i;
52 return -1;
55 /* query the loaded config; this is just an interface to pre-parsed
56 input */
57 const char *config_get_string(char *key,int bank, int A, int B, int C){
58 int i=look_for_key(key,bank,A,B,C);
59 if(i==-1)return NULL;
61 return config_list[i].string;
64 int config_get_integer(char *key,int bank, int A, int B, int C,int valnum, int *val){
65 int i=look_for_key(key,bank,A,B,C);
66 if(i==-1)return -1;
67 if(valnum<config_list[i].vals){
68 *val=config_list[i].vec[valnum];
69 return 0;
71 return -1;
74 int config_get_sigat(char *key,int bank, int A, int B, int C,int valnum, sig_atomic_t *val){
75 int ival=*val;
76 int ret=config_get_integer(key, bank, A, B, C,valnum, &ival);
77 *val=ival;
78 return ret;
81 int config_get_vector(char *key,int bank, int A, int B, int C,int n, sig_atomic_t *v){
82 int i=look_for_key(key,bank,A,B,C),j;
83 if(i==-1)return -1;
85 for(j=0;j<n && j<config_list[i].vals;j++)
86 v[j]=config_list[i].vec[j];
87 return 0;
90 static configentry *old_or_new(char *key,int bank,int A, int B, int C){
91 int i=look_for_key(key,bank,A,B,C);
93 if(i==-1){
94 /* create a new entry */
95 i=configentries;
96 configentries++;
97 if(config_list){
98 config_list=realloc(config_list,sizeof(*config_list)*configentries);
99 memset(&config_list[i],0,sizeof(*config_list));
100 }else{
101 config_list=calloc(1,sizeof(*config_list));
103 config_list[i].key=strdup(key);
104 config_list[i].bank=bank;
105 config_list[i].A=A;
106 config_list[i].B=B;
107 config_list[i].C=C;
109 return config_list+i;
112 static void extend_vec(configentry *c,int n){
113 if(n>c->vals){
114 if(!c->vec)
115 c->vec=calloc(n,sizeof(*c->vec));
116 else{
117 c->vec=realloc(c->vec,n*sizeof(*c->vec));
118 memset(c->vec+c->vals,0,(n-c->vals)*sizeof(*c->vec));
120 c->vals=n;
124 /* dump changes back into existing local config state; this is mostly
125 an elaborate means of meging changes into an existing file that may
126 be a superset of what's currently running */
127 void config_set_string(char *key,int bank, int A, int B, int C, const char *s){
128 configentry *c=old_or_new(key,bank,A,B,C);
129 c->string=strdup(s);
132 void config_set_integer(char *key,int bank, int A, int B, int C, int valnum, int val){
133 configentry *c=old_or_new(key,bank,A,B,C);
134 extend_vec(c,valnum+1);
135 c->vec[valnum]=val;
138 void config_set_vector(char *key,int bank, int A, int B, int C,int n, sig_atomic_t *v){
139 int i;
140 configentry *c=old_or_new(key,bank,A,B,C);
141 extend_vec(c,n);
142 for(i=0;i<n;i++)
143 c->vec[i]=v[i];
146 int config_load(char *filename){
147 FILE *f=fopen(filename,"r");
148 char key[80];
149 int bank,A,B,C,width,rev;
150 int errflag=0;
152 fprintf(stderr,"Loading state configuration file %s... ",filename);
154 sprintf(key,"[file beginning]");
156 if(!f){
157 fprintf(stderr,"No config file %s; will be created on save/exit.\n",filename);
158 return 0;
161 /* search for magic */
162 if(fscanf(f,"Postfish rev %d",&rev)!=1 || rev!=2){
163 fprintf(stderr,"File %s is not a postfish state configuration file.\n",filename);
164 fclose(f);
165 return -1;
168 /* load file */
169 while(!feof(f)){
170 int c=fgetc(f);
171 switch(c){
172 case '(': /* string type input */
174 if (fscanf(f,"%79s bank%d A%d B%d C%d l%d \"",
175 key,&bank,&A,&B,&C,&width)==6){
176 char *buffer=calloc(width+1,sizeof(*buffer));
177 for(c=0;c<width;c++)buffer[c]=fgetc(f);
179 config_set_string(key,bank,A,B,C,buffer);
180 free(buffer);
181 fscanf(f,"\" )");
182 errflag=0;
183 }else{
184 if(!errflag){
185 fprintf(stderr,"Configuration file parse error after %s\n",key);
186 errflag=1;
190 break;
191 case '[': /* vector type input */
192 if (fscanf(f,"%79s bank%d A%d B%d C%d v%d \"",
193 key,&bank,&A,&B,&C,&width)==6){
194 int *vec=calloc(width,sizeof(*vec));
195 for(c=0;c<width;c++){
196 if(fscanf(f,"%d",vec+c)!=1){
197 if(!errflag){
198 fprintf(stderr,"Configuration file parse error after %s\n",key);
199 errflag=1;
200 break;
204 fscanf(f," ]");
206 config_set_vector(key,bank,A,B,C,width,vec);
207 free(vec);
208 errflag=0;
209 }else{
210 if(!errflag){
211 fprintf(stderr,"Configuration file parse error after %s\n",key);
212 errflag=1;
216 break;
217 default:
218 /* whitespace OK, other characters indicate a parse error */
219 if(!isspace(c) && !errflag && c!=EOF){
220 fprintf(stderr,"Configuration file parse error after %s\n",key);
221 errflag=1;
224 break;
228 fclose(f);
229 fprintf(stderr,"done.\n");
230 return 0;
233 /* save the config */
234 void config_save(char *filename){
235 int i,j;
236 FILE *f=fopen(filename,"w");
238 fprintf(stderr,"Saving state to %s ...",filename);
240 if(!f){
241 fprintf(stderr,"\nUnable to save config file %s: %s\n",filename,strerror(errno));
242 return;
245 fprintf(f,"Postfish rev 2\n");
247 for(i=0;i<configentries;i++){
248 configentry *c=config_list+i;
249 if(c->string)
250 fprintf(f,"(%s bank%d A%d B%d C%d l%d \"%s\" )\n",
251 c->key,c->bank,c->A,c->B,c->C,strlen(c->string),c->string);
252 if(c->vec){
253 fprintf(f,"[%s bank%d A%d B%d C%d v%d ",
254 c->key,c->bank,c->A,c->B,c->C,c->vals);
255 for(j=0;j<c->vals;j++)
256 fprintf(f,"%d ",c->vec[j]);
258 fprintf(f,"]\n");
261 fclose(f);
262 fprintf(stderr," done.\n");