Annotation of hatari/src/cfgopts.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Hatari - cfgopts.c
                      3:  *
                      4:  * The functions in this file are used to load and save the ASCII
                      5:  * configuration file.
                      6:  * Original information text follows:
                      7:  */
                      8: /*<<---------------[         cfgopts.c        ]------------------------/
                      9: /                                                                      /
                     10: /  Functional                                                          /
                     11: /     Description: Configuration file I/O                              /
                     12: /                                                                      /
                     13: /  Input         : Configuration file name                             /
                     14: /                  Configuration parameters in a structure             /
                     15: /                                                                      /
                     16: /  Process       : Interpret information by parameter and read or      /
                     17: /                  write back to the configuration file.               /
                     18: /                                                                      /
                     19: /  Ouput         : updated configuration file or updated structure.    /
                     20: /                                                                      /
                     21: /  Programmer    : Jeffry J. Brickley                                  /
                     22: /                                                                      /
                     23: /                                                                      /
                     24: /---------------------------------------------------------------------*/
                     25: 
                     26: /*---------------------------------------------------------------------/
                     27: /
                     28: /  Description:  CfgOpts is based on GETOPTS by Bob Stout.  It will
                     29: /                process a configuration file based one words and
                     30: /                store it in a structure pointing to physical data
                     31: /                area for each storage item.
                     32: /  i.e. ???.CFG:
                     33: /    Port=1
                     34: /    work_space=C:\temp
                     35: /    menus=TRUE
                     36: /    user=Jeffry Brickley
                     37: /  will write to the following structure:
                     38: /    struct Config_Tag configs[] = {
                     39: /    {"port",       Int_Tag,    &port_number},
                     40: /    {"work_space", String_Tag,  &work_space},
                     41: /    {"menus",      Bool_Tag, &menu_flag},
                     42: /    {"user",       String_Tag,  &User_name},
                     43: /    {NULL,         Error_Tag,   NULL}
                     44: /    };
                     45: /  Note that the structure must always be terminated by a NULL row as
                     46: /     was the same with GETOPTS.  This however is slightly more
                     47: /     complicated than scaning the command line (but not by much) for
                     48: /     data as there can be more variety in words than letters and an
                     49: /     number of data items limited only by memory.
                     50: /
                     51: /  Like the original code from which this was taken, this is released
                     52: /  to the Public Domain.  I cannot make any guarentees other than these
                     53: /  work for me and I find them usefull.  Feel free to pass these on to
                     54: /  a friend, but please do not charge him....
                     55: /
                     56: /---------------------------------------------------------------------*/
                     57: 
                     58: #include <stdio.h>
                     59: #include <stdlib.h>
                     60: #include <string.h>
                     61: 
                     62: #include "main.h"
                     63: #include "cfgopts.h"
                     64: 
                     65: 
                     66: 
                     67: /* --- Remove spaces from beginning and end of a string --- */
                     68: static char *trim(char *buffer)
                     69: {
                     70:   const char SPACE = ' ';
                     71:   const char TABULA = '\t';
                     72: 
                     73:   if (buffer != NULL)
                     74:   {
                     75:     int i, linelen;
                     76:     
                     77:     linelen = strlen(buffer);
                     78: 
                     79:     for (i = 0; i < linelen; i++)
                     80:     {
                     81:       if (buffer[i] != SPACE && buffer[i] != TABULA)
                     82:         break;
                     83:     }
                     84: 
                     85:     if (i > 0 && i < linelen)
                     86:     {
                     87:       linelen -= i;
                     88:       memmove(buffer, buffer + i, linelen);
                     89:     }
                     90: 
                     91:     for (i = linelen; i > 0; i--)
                     92:     {
                     93:       int j = i - 1;
                     94:       if (buffer[j] != SPACE && buffer[j] != TABULA)
                     95:         break;
                     96:     }
                     97: 
                     98:     buffer[i] = '\0';
                     99:   }
                    100: 
                    101:   return buffer;
                    102: }
                    103: 
                    104: 
                    105: /*---------------------------------------------------------------------/
                    106: /   reads from an input configuration (INI) file.
                    107: /---------------------------------------------------------------------*/
                    108: /*>>------[   input_config()   ]-------------[ 08-02-95 14:02PM ]------/
                    109: / return value:
                    110: /     int                     ; number of records read or -1 on error
                    111: / parameters:
                    112: /     char *filename          ; filename of INI style file
                    113: /     struct Config_Tag configs[]; Configuration structure
                    114: /     char *header            ; INI header name (i.e. "[TEST]")
                    115: /-------------------------------------------------------------------<<*/
                    116: int input_config(const char *filename, struct Config_Tag configs[], char *header)
                    117: {
                    118:    struct Config_Tag *ptr;
                    119:    int count=0, lineno=0;
                    120:    FILE *file;
                    121:    char *fptr,*tok,*next;
                    122:    char line[1024];
                    123: 
                    124:    file = fopen(filename,"r");
                    125:    if (file == NULL) return -1;                 /* return error designation. */
                    126: 
                    127:    if (header != NULL)
                    128:    {
                    129:      do
                    130:      {
                    131:        fptr = trim(fgets(line, sizeof(line), file));  /* get input line */
                    132:      }
                    133:      while ( memcmp(line,header,strlen(header)) && !feof(file));
                    134:    }
                    135: 
                    136:    if ( !feof(file) )
                    137:     do
                    138:     {
                    139:       fptr = trim(fgets(line, sizeof(line), file));   /* get input line */
                    140:       if ( fptr==NULL ) continue;
                    141:       lineno++;
                    142:       if (line[0] == '#')  continue;            /* skip comments */
                    143:       if (line[0] == '[')  continue;            /* skip next header */
                    144:       tok = trim(strtok(line, "=\n\r"));        /* get first token */
                    145:       if (tok != NULL)
                    146:       {
                    147:          next = trim(strtok(NULL, "=\n\r"));    /* get actual config information */
                    148:          for (ptr = configs; ptr->buf; ++ptr)   /* scan for token */
                    149:          {
                    150:             if (!strcmp(tok, ptr->code))        /* got a match? */
                    151:             {
                    152:                switch (ptr->type)               /* check type */
                    153:                {
                    154:                case Bool_Tag:
                    155:                   if (!strcasecmp(next,"FALSE"))
                    156:                      *((BOOL *)(ptr->buf)) = FALSE;
                    157:                   else if (!strcasecmp(next,"TRUE"))
                    158:                      *((BOOL *)(ptr->buf)) = TRUE;
                    159:                   ++count;
                    160:                   break;
                    161: 
                    162:                case Char_Tag:
                    163:                   sscanf(next, "%c", (char *)(ptr->buf));
                    164:                   ++count;
                    165:                   break;
                    166: 
                    167:                case Short_Tag:
                    168:                   sscanf(next, "%hd", (short *)(ptr->buf));
                    169:                   ++count;
                    170:                   break;
                    171: 
                    172:                case Int_Tag:
                    173:                   sscanf(next, "%d", (int *)(ptr->buf));
                    174:                   ++count;
                    175:                   break;
                    176: 
                    177:                case Long_Tag:
                    178:                   sscanf(next, "%ld", (long *)(ptr->buf));
                    179:                   ++count;
                    180:                   break;
                    181: 
                    182:                case Float_Tag:
                    183:                   sscanf(next, "%g", (float *)ptr->buf);
                    184:                   ++count;
                    185:                   break;
                    186: 
                    187:                case Double_Tag:
                    188:                   sscanf(next, "%lg", (double *)ptr->buf);
                    189:                   ++count;
                    190:                   break;
                    191: 
                    192:                case String_Tag:
                    193:                   if(next)
                    194:                     strcpy((char *)ptr->buf, next);
                    195:                   else
                    196:                     *(char *)ptr->buf = 0;
                    197:                   ++count;
                    198:                   break;
                    199: 
                    200:                case Error_Tag:
                    201:                default:
                    202:                   printf("Error in Config file %s on line %d\n", filename, lineno);
                    203:                   break;
                    204:                }
                    205:             }
                    206: 
                    207:          }
                    208:       }
                    209:     }
                    210:     while ( fptr!=NULL && line[0]!='[');
                    211: 
                    212:    fclose(file);
                    213:    return count;
                    214: }
                    215: 
                    216: 
                    217: /* Write out an settings line */
                    218: int write_token(FILE *outfile, struct Config_Tag *ptr)
                    219: {
                    220:   fprintf(outfile,"%s = ",ptr->code);
                    221: 
                    222:   switch (ptr->type)    /* check type */
                    223:   {
                    224:     case Bool_Tag:
                    225:       fprintf(outfile,"%s\n", *((BOOL *)(ptr->buf)) ? "TRUE" : "FALSE");
                    226:       break;
                    227: 
                    228:     case Char_Tag:
                    229:       fprintf(outfile, "%c\n", *((char *)(ptr->buf)));
                    230:       break;
                    231: 
                    232:     case Short_Tag:
                    233:       fprintf(outfile, "%hd\n", *((short *)(ptr->buf)));
                    234:       break;
                    235: 
                    236:     case Int_Tag:
                    237:       fprintf(outfile, "%d\n", *((int *)(ptr->buf)));
                    238:       break;
                    239: 
                    240:     case Long_Tag:
                    241:       fprintf(outfile, "%ld\n", *((long *)(ptr->buf)));
                    242:       break;
                    243: 
                    244:     case Float_Tag:
                    245:       fprintf(outfile, "%g\n", *((float *)ptr->buf));
                    246:       break;
                    247: 
                    248:     case Double_Tag:
                    249:       fprintf(outfile, "%g\n", *((double *)ptr->buf));
                    250:       break;
                    251: 
                    252:     case String_Tag:
                    253:       fprintf(outfile, "%s\n",(char *)ptr->buf);
                    254:       break;
                    255: 
                    256:     case Error_Tag:
                    257:     default:
                    258:       fprintf(stderr, "Error in Config structure (Contact author).\n");
                    259:       return -1;
                    260:   }
                    261: 
                    262:   return 0;
                    263: }
                    264: 
                    265: 
                    266: /*---------------------------------------------------------------------/
                    267: /   updates an input configuration (INI) file from a structure.
                    268: /---------------------------------------------------------------------*/
                    269: /*>>------[   update_config()  ]-------------[ 08-02-95 14:02PM ]------/
                    270: / return value:
                    271: /     int                     ; Number of records read & updated
                    272: / parameters:
                    273: /     char *filename          ; filename of INI file
                    274: /     struct Config_Tag configs[]; Configuration structure
                    275: /     char *header            ; INI header name (i.e. "[TEST]")
                    276: /-------------------------------------------------------------------<<*/
                    277: int update_config(const char *filename, struct Config_Tag configs[], char *header)
                    278: {
                    279:    struct Config_Tag *ptr;
                    280:    int count=0, lineno=0;
                    281:    FILE *cfgfile, *tempfile;
                    282:    char *fptr, *tok, *next;
                    283:    char line[1024];
                    284: 
                    285:    cfgfile = fopen(filename, "r");
                    286: 
                    287:    /* If the cfg file does not yet exists, we can create it directly: */
                    288:    if (cfgfile == NULL)
                    289:    {
                    290:       cfgfile = fopen(filename, "w");
                    291:       if (cfgfile == NULL)
                    292:          return -1;                             /* return error designation. */
                    293:       if (header != NULL)
                    294:       {
                    295:          fprintf(cfgfile,"%s\n",header);
                    296:       }
                    297:       for (ptr=configs; ptr->buf; ++ptr)        /* scan for token */
                    298:       {
                    299:          if(write_token(cfgfile, ptr) == 0)
                    300:            ++count;
                    301:       }
                    302: 
                    303:       fclose(cfgfile);
                    304:       return count;
                    305:    }
                    306: 
                    307:    tempfile = tmpfile();                        /* Open a temporary file for output */
                    308:    if (tempfile == NULL)
                    309:    {
                    310:       fclose(cfgfile);
                    311:       return -1;                                /* return error designation. */
                    312:    }
                    313: 
                    314:    if (header != NULL)
                    315:    {
                    316:       do
                    317:       {
                    318:          fptr = trim(fgets(line, sizeof(line), cfgfile));  /* get input line */
                    319:          if (feof(cfgfile))
                    320:            break;
                    321:          fprintf(tempfile, "%s", line);
                    322:       }
                    323:       while(memcmp(line, header, strlen(header)));
                    324:    }
                    325: 
                    326:    if (feof(cfgfile))
                    327:    {
                    328:       if (header != NULL)
                    329:       {
                    330:          fprintf(tempfile, "\n%s\n", header);
                    331:       }
                    332:       for (ptr = configs; ptr->buf; ++ptr)                /* scan for token */
                    333:       {
                    334:          if(write_token(tempfile, ptr) == 0)
                    335:            ++count;
                    336:       }
                    337:    }
                    338:    else
                    339:    {
                    340:       for(;;)
                    341:       {
                    342:          fptr = trim(fgets(line, sizeof(line), cfgfile));  /* get input line */
                    343:          if (fptr == NULL)  break;
                    344:          lineno++;
                    345:          if (line[0] == '#')
                    346:          {
                    347:             fprintf(tempfile, "%s", line);
                    348:             continue;                                 /* skip comments */
                    349:          }
                    350:          if (line[0] == '[' || feof(cfgfile))
                    351:          {
                    352:            break;
                    353:          }
                    354: 
                    355:          tok = trim(strtok(line, "=\n\r"));           /* get first token */
                    356:          if (tok != NULL)
                    357:          {
                    358:             next = strtok(line, "=\n\r");             /* get actual config information */
                    359:             for (ptr = configs; ptr->buf; ++ptr)      /* scan for token */
                    360:             {
                    361:                if (!strcmp(tok, ptr->code))           /* got a match? */
                    362:                {
                    363:                  if(write_token(tempfile, ptr) == 0)
                    364:                    ++count;
                    365:                }
                    366: 
                    367:             }
                    368:          }
                    369:       }
                    370: 
                    371:       if (!feof(cfgfile) && fptr != NULL)
                    372:         fprintf(tempfile, "\n%s", line);
                    373: 
                    374:       for(;;)
                    375:       {
                    376:         fptr = trim(fgets(line, sizeof(line), cfgfile));  /* get input line */
                    377:         if (feof(cfgfile))
                    378:           break;
                    379:         fprintf(tempfile, "%s", line);
                    380:       }
                    381:    }
                    382: 
                    383: 
                    384:    /* Re-open the config file for writing: */
                    385:    fclose(cfgfile);
                    386:    cfgfile = fopen(filename, "wb");
                    387:    if (cfgfile == NULL)
                    388:    {
                    389:      fclose(tempfile);
                    390:      return -1;
                    391:    }
                    392: 
                    393:    if(fseek(tempfile, 0, SEEK_SET) != 0)
                    394:    {
                    395:      fclose(cfgfile);
                    396:      fclose(tempfile);
                    397:      return -1;
                    398:    }
                    399: 
                    400:    /* Now copy the temporary file to the configuration file: */
                    401:    while(!feof(tempfile))
                    402:    {
                    403:      int copycount;
                    404:      copycount = fread(line, sizeof(char), sizeof(line), tempfile);
                    405:      if(fwrite(line, sizeof(char), copycount, cfgfile) != copycount)
                    406:      {
                    407:        fclose(cfgfile);
                    408:        fclose(tempfile);
                    409:        return -1;
                    410:      }
                    411:    }
                    412: 
                    413:    fclose(cfgfile);
                    414:    fclose(tempfile);
                    415:    return count;
                    416: }
                    417: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.