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)
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.
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
){
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
;
55 /* query the loaded config; this is just an interface to pre-parsed
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
);
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
);
67 if(valnum
<config_list
[i
].vals
){
68 *val
=config_list
[i
].vec
[valnum
];
74 int config_get_sigat(char *key
,int bank
, int A
, int B
, int C
,int valnum
, sig_atomic_t *val
){
76 int ret
=config_get_integer(key
, bank
, A
, B
, C
,valnum
, &ival
);
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
;
85 for(j
=0;j
<n
&& j
<config_list
[i
].vals
;j
++)
86 v
[j
]=config_list
[i
].vec
[j
];
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
);
94 /* create a new entry */
98 config_list
=realloc(config_list
,sizeof(*config_list
)*configentries
);
99 memset(&config_list
[i
],0,sizeof(*config_list
));
101 config_list
=calloc(1,sizeof(*config_list
));
103 config_list
[i
].key
=strdup(key
);
104 config_list
[i
].bank
=bank
;
109 return config_list
+i
;
112 static void extend_vec(configentry
*c
,int n
){
115 c
->vec
=calloc(n
,sizeof(*c
->vec
));
117 c
->vec
=realloc(c
->vec
,n
*sizeof(*c
->vec
));
118 memset(c
->vec
+c
->vals
,0,(n
-c
->vals
)*sizeof(*c
->vec
));
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
);
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);
138 void config_set_vector(char *key
,int bank
, int A
, int B
, int C
,int n
, sig_atomic_t *v
){
140 configentry
*c
=old_or_new(key
,bank
,A
,B
,C
);
146 int config_load(char *filename
){
147 FILE *f
=fopen(filename
,"r");
149 int bank
,A
,B
,C
,width
,rev
;
152 fprintf(stderr
,"Loading state configuration file %s... ",filename
);
154 sprintf(key
,"[file beginning]");
157 fprintf(stderr
,"No config file %s; will be created on save/exit.\n",filename
);
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
);
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
);
185 fprintf(stderr
,"Configuration file parse error after %s\n",key
);
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){
198 fprintf(stderr
,"Configuration file parse error after %s\n",key
);
206 config_set_vector(key
,bank
,A
,B
,C
,width
,vec
);
211 fprintf(stderr
,"Configuration file parse error after %s\n",key
);
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
);
229 fprintf(stderr
,"done.\n");
233 /* save the config */
234 void config_save(char *filename
){
236 FILE *f
=fopen(filename
,"w");
238 fprintf(stderr
,"Saving state to %s ...",filename
);
241 fprintf(stderr
,"\nUnable to save config file %s: %s\n",filename
,strerror(errno
));
245 fprintf(f
,"Postfish rev 2\n");
247 for(i
=0;i
<configentries
;i
++){
248 configentry
*c
=config_list
+i
;
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
);
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
]);
262 fprintf(stderr
," done.\n");