00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <stdio.h>
00019 #include <string.h>
00020 #include <ctype.h>
00021 #include <stdlib.h>
00022
00023 #include "conftree.h"
00024 #include "lsp.h"
00025 #include "confpile.h"
00026
00027 #define ALLOC(X) (pCT->memory_allocating_function((X),pCT->pMemorySegment))
00028 #define FREE(X) (pCT->memory_releasing_function((X),pCT->pMemorySegment))
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 static int BuildSubTree(ptConfigTree pCT,
00048 tLspObject *pLSP,
00049 CFT_NODE *plNindex,
00050 long *plSindex,
00051 LVAL q){
00052
00053
00054
00055 LVAL r;
00056 long prev;
00057 CFT_NODE lThisNode;
00058
00059 prev = 0;
00060
00061 while( q ){
00062
00063
00064 pCT->Root[(*plNindex)-1].lKey = *plSindex;
00065
00066 if( prev )pCT->Root[prev-1].lNext = *plNindex;
00067
00068 pCT->Root[(*plNindex)-1].lNext = 0;
00069
00070 prev = *plNindex;
00071
00072
00073 strcpy(pCT->StringTable+*plSindex,getsymbol(car(q)));
00074
00075 *plSindex += strlen(getsymbol(car(q))) +1;
00076
00077
00078 r = cadr(q);
00079 if( consp(r) ){
00080 lThisNode = *plNindex;
00081
00082 ++(*plNindex);
00083 pCT->Root[lThisNode-1].Val.lVal = (*plNindex);
00084
00085 pCT->Root[lThisNode-1].fFlag = CFT_NODE_BRANCH;
00086
00087
00088 BuildSubTree(pCT,
00089 pLSP,
00090 plNindex,
00091 plSindex,
00092 r);
00093 }else{
00094
00095 if( stringp(r) || symbolp(r) ){
00096 strcpy(pCT->StringTable+*plSindex,getstring(r));
00097 pCT->Root[(*plNindex)-1].Val.lVal = *plSindex;
00098 pCT->Root[(*plNindex)-1].fFlag = CFT_NODE_LEAF | CFT_TYPE_STRING;
00099 *plSindex += strlen(getstring(r)) +1;
00100 }else
00101 if( floatp(r) ){
00102 pCT->Root[(*plNindex)-1].Val.dVal = getfloat(r);
00103 pCT->Root[(*plNindex)-1].fFlag = CFT_NODE_LEAF | CFT_TYPE_REAL;
00104 }else
00105 if( integerp(r) ){
00106 pCT->Root[(*plNindex)-1].Val.lVal = getint(r);
00107 pCT->Root[(*plNindex)-1].fFlag = CFT_NODE_LEAF | CFT_TYPE_INTEGER;
00108 }
00109
00110 (*plNindex)++;
00111 }
00112
00113 q = cddr(q);
00114 }
00115 return 0;
00116 }
00117
00118 extern int GlobalDebugDisplayFlag;
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137 static void RemoveNil(ptConfigTree pCT,
00138 tLspObject *pLSP,
00139 LVAL *q){
00140
00141
00142
00143 LVAL r,*p;
00144
00145 if( NULL == q )return;
00146
00147 p = q;
00148 while( *q ){
00149 r = cadr(*q);
00150 if( NULL == r ){
00151 *q = cddr(*q);
00152 continue;
00153 }
00154 if( consp(r) ){
00155 RemoveNil(pCT,pLSP,&((*q)->n_value.n_cons._cdr->n_value.n_cons._car));
00156 }
00157 if( *q )
00158 q = & ( (*q)->n_value.n_cons._cdr);
00159 if( *q )
00160 q = & ( (*q)->n_value.n_cons._cdr);
00161 }
00162 return;
00163 }
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174 static int CountSubTree(ptConfigTree pCT,
00175 tLspObject *pLSP,
00176 long *plNodeCounter,
00177 long *plStringCounter,
00178 LVAL q){
00179
00180
00181
00182 LVAL r;
00183 int iError;
00184 while( q ){
00185 (*plNodeCounter)++;
00186 if( ! symbolp(car(q)) ){
00187 if( GlobalDebugDisplayFlag ){
00188 fprintf(stderr,"The node should have been a symbol.\n");
00189 pprint(q,stderr);
00190 }
00191 return CFT_ERROR_SYNTAX;
00192 }
00193 *plStringCounter += strlen(getsymbol(car(q))) + 1;
00194 r = cadr(q);
00195 if( consp(r) ){
00196 iError = CountSubTree(pCT,pLSP,plNodeCounter,plStringCounter,r);
00197 if( iError )
00198 return CFT_ERROR_SYNTAX;
00199 }else{
00200 if( stringp(r) || symbolp(r) ){
00201 *plStringCounter += strlen( getstring(r) ) + 1;
00202 }else{
00203 if( (!floatp(r)) && (!integerp(r)) ){
00204 if( GlobalDebugDisplayFlag ){
00205 fprintf(stderr,"The node should have been an integer, float or integer.\n");
00206 pprint(r,stderr);
00207 fprintf(stderr,"This is the value of the symbol ");
00208 pprint(q,stderr);
00209 }
00210 return CFT_ERROR_SYNTAX;
00211 }
00212 }
00213 }
00214 q = cddr(q);
00215 }
00216 return 0;
00217 }
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230 int cft_ReadTextConfig(ptConfigTree pCT,
00231 char *pszFileName
00232 ){
00233
00234
00235 FILE *fp;
00236 tLspObject MyLSP,*pLSP;
00237 LVAL q;
00238 int iError;
00239 long lNindex,lSindex;
00240
00241 pLSP = &MyLSP;
00242 lsp_init(pLSP,-1,1,pCT->memory_allocating_function,
00243 pCT->memory_releasing_function,
00244 pCT->pMemorySegment);
00245 fp = fopen(pszFileName,"r");
00246 if( fp == NULL )return CFT_ERROR_FILE;
00247 q = readlist(fp);
00248 fclose(fp);
00249 pCT->cNode = 0;
00250 pCT->cbStringTable = 0;
00251 RemoveNil(pCT,pLSP,&q);
00252 if( iError = CountSubTree(pCT,
00253 pLSP,
00254 &(pCT->cNode),
00255 &(pCT->cbStringTable),
00256 q) )return iError;
00257 if( pCT->cNode == 0 )return CFT_ERROR_EMPTY;
00258 pCT->Root = ALLOC(pCT->cNode*sizeof(tConfigNode));
00259 if( pCT->Root == NULL )return CFT_ERROR_MEMORY;
00260 pCT->StringTable = ALLOC(pCT->cbStringTable);
00261 if( pCT->StringTable == NULL ){
00262 FREE(pCT->Root);
00263 return CFT_ERROR_MEMORY;
00264 }
00265 lNindex = 1;
00266 lSindex = 0;
00267 BuildSubTree(pCT,pLSP,&lNindex,&lSindex,q);
00268 freelist(q);
00269 return 0;
00270 }
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299 static int DumpTree(ptConfigTree pCT,
00300 FILE *fp,
00301 CFT_NODE hNode,
00302 int offset
00303 ){
00304
00305
00306
00307
00308 CFT_NODE hNodeIter;
00309 char *s;
00310 char *t;
00311
00312 hNodeIter = hNode;
00313 while( hNodeIter ){
00314 if( (pCT->Root[hNodeIter-1].fFlag&CFT_NODE_MASK) == CFT_NODE_BRANCH ){
00315 fprintf(fp,"%*s%s (\n",offset,"",pCT->StringTable+pCT->Root[hNodeIter-1].lKey);
00316 DumpTree(pCT,fp,cft_EnumFirst(pCT,hNodeIter),offset+2);
00317 fprintf(fp,"%*s )\n",offset,"");
00318 }else
00319 if( (pCT->Root[hNodeIter-1].fFlag&CFT_TYPE_MASK) == CFT_TYPE_STRING ){
00320 fprintf(fp,"%*s%s ",offset,"",pCT->StringTable+pCT->Root[hNodeIter-1].lKey);
00321 t = "\"";
00322 for( s = pCT->StringTable+pCT->Root[hNodeIter-1].Val.lVal ; *s ; s++ ){
00323 if( *s == '\n' || *s == '\r' ){
00324 t = "\"\"\"";
00325 break;
00326 }
00327 }
00328 fprintf(fp,t);
00329 for( s = pCT->StringTable+pCT->Root[hNodeIter-1].Val.lVal ; *s ; s++ ){
00330 if( *s == '"' ){
00331 fprintf(fp,"\\\"");
00332 continue;
00333 }
00334 if( *s == '\\' ){
00335 fprintf(fp,"\\\\");
00336 continue;
00337 }
00338 fprintf(fp,"%c",*s);
00339 }
00340 fprintf(fp,"%s\n",t);
00341 }else
00342 if( (pCT->Root[hNodeIter-1].fFlag&CFT_TYPE_MASK) == CFT_TYPE_INTEGER ){
00343 fprintf(fp,"%*s%s %d\n",offset,"",pCT->StringTable+pCT->Root[hNodeIter-1].lKey,
00344 pCT->Root[hNodeIter-1].Val.lVal);
00345 }else
00346 if( (pCT->Root[hNodeIter-1].fFlag&CFT_TYPE_MASK) == CFT_TYPE_REAL ){
00347 fprintf(fp,"%*s%s %f\n",offset,"",pCT->StringTable+pCT->Root[hNodeIter-1].lKey,
00348 pCT->Root[hNodeIter-1].Val.dVal);
00349 }
00350 hNodeIter = cft_EnumNext(pCT,hNodeIter);
00351 }
00352 return 0;
00353 }
00354
00355
00356
00357
00358
00359
00360 int cft_DumpConfig(ptConfigTree pCT,
00361 char *pszFileName
00362 ){
00363
00364
00365 FILE *fp;
00366 int iError;
00367 int iShouldClose = 0;
00368
00369 if( !strcmp(pszFileName,"STDOUT") )
00370 fp = stdout;
00371 else
00372 if( !strcmp(pszFileName,"STDERR") )
00373 fp = stderr;
00374 else{
00375 fp = fopen(pszFileName,"w");
00376 iShouldClose = 1;
00377 }
00378 if( fp == NULL )return CFT_ERROR_FILE;
00379 iError = DumpTree(pCT,fp,CFT_ROOT_NODE,0);
00380 if( iShouldClose )fclose(fp);
00381 return iError;
00382 }
00383
00384
00385
00386
00387
00388
00389
00390 int cft_DumbConfig(ptConfigTree pCT,
00391 char *pszFileName
00392 ){
00393
00394
00395 int i;
00396 FILE *fp;
00397 int iShouldClose = 0;
00398
00399 if( !strcmp(pszFileName,"STDOUT") )
00400 fp = stdout;
00401 else
00402 if( !strcmp(pszFileName,"STDERR") )
00403 fp = stderr;
00404 else{
00405 fp = fopen(pszFileName,"w");
00406 iShouldClose = 1;
00407 }
00408 if( fp == NULL )return CFT_ERROR_FILE;
00409 for( i=0 ; i < pCT->cNode ; i++ ){
00410 fprintf(fp,"Node %d:",i+1);
00411 fprintf(fp,"(%s)",pCT->StringTable+pCT->Root[i].lKey);
00412 switch( pCT->Root[i].fFlag ){
00413 case CFT_NODE_BRANCH: fprintf(fp," BRANCH %d",pCT->Root[i].Val.lVal); break;
00414 case CFT_TYPE_STRING: fprintf(fp," \"%s\"",pCT->StringTable+pCT->Root[i].Val.lVal); break;
00415 case CFT_TYPE_INTEGER: fprintf(fp," %d",pCT->Root[i].Val.lVal); break;
00416 case CFT_TYPE_REAL: fprintf(fp," %lf",pCT->Root[i].Val.dVal); break;
00417 default: fprintf(fp,"Unknown node type: %d",pCT->Root[i].fFlag);
00418 }
00419 fprintf(fp," NEXT->%d",pCT->Root[i].lNext);
00420 fprintf(fp,"\n");
00421 }
00422
00423 if( iShouldClose )fclose(fp);
00424 return 0;
00425 }