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

1.1.1.2 ! 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: char CfgOpts_rcsid[] = "Hatari $Id: cfgopts.c,v 1.4 2004/07/05 16:53:17 thothy Exp $";
        !            58: 
        !            59: #include <stdio.h>
        !            60: #include <stdlib.h>
        !            61: #include <string.h>
        !            62: 
        !            63: #include "main.h"
        !            64: #include "cfgopts.h"
        !            65: 
        !            66: 
        !            67: 
        !            68: /* --- Remove spaces from beginning and end of a string --- */
        !            69: static char *trim(char *buffer)
        !            70: {
        !            71:   const char SPACE = ' ';
        !            72:   const char TABULA = '\t';
        !            73: 
        !            74:   if (buffer != NULL)
        !            75:   {
        !            76:     int i, linelen;
        !            77:     
        !            78:     linelen = strlen(buffer);
        !            79: 
        !            80:     for (i = 0; i < linelen; i++)
        !            81:     {
        !            82:       if (buffer[i] != SPACE && buffer[i] != TABULA)
        !            83:         break;
        !            84:     }
        !            85: 
        !            86:     if (i > 0 && i < linelen)
        !            87:     {
        !            88:       linelen -= i;
        !            89:       memmove(buffer, buffer + i, linelen);
        !            90:     }
        !            91: 
        !            92:     for (i = linelen; i > 0; i--)
        !            93:     {
        !            94:       int j = i - 1;
        !            95:       if (buffer[j] != SPACE && buffer[j] != TABULA)
        !            96:         break;
        !            97:     }
        !            98: 
        !            99:     buffer[i] = '\0';
        !           100:   }
        !           101: 
        !           102:   return buffer;
        !           103: }
        !           104: 
        !           105: 
        !           106: /*---------------------------------------------------------------------/
        !           107: /   reads from an input configuration (INI) file.
        !           108: /---------------------------------------------------------------------*/
        !           109: /*>>------[   input_config()   ]-------------[ 08-02-95 14:02PM ]------/
        !           110: / return value:
        !           111: /     int                     ; number of records read or -1 on error
        !           112: / parameters:
        !           113: /     char *filename          ; filename of INI style file
        !           114: /     struct Config_Tag configs[]; Configuration structure
        !           115: /     char *header            ; INI header name (i.e. "[TEST]")
        !           116: /-------------------------------------------------------------------<<*/
        !           117: int input_config(const char *filename, struct Config_Tag configs[], char *header)
        !           118: {
        !           119:    struct Config_Tag *ptr;
        !           120:    int count=0, lineno=0;
        !           121:    FILE *file;
        !           122:    char *fptr,*tok,*next;
        !           123:    char line[1024];
        !           124: 
        !           125:    file = fopen(filename,"r");
        !           126:    if (file == NULL) return -1;                 /* return error designation. */
        !           127: 
        !           128:    if (header != NULL)
        !           129:    {
        !           130:      do
        !           131:      {
        !           132:        fptr = trim(fgets(line, sizeof(line), file));  /* get input line */
        !           133:      }
        !           134:      while ( memcmp(line,header,strlen(header)) && !feof(file));
        !           135:    }
        !           136: 
        !           137:    if ( !feof(file) )
        !           138:     do
        !           139:     {
        !           140:       fptr = trim(fgets(line, sizeof(line), file));   /* get input line */
        !           141:       if ( fptr==NULL ) continue;
        !           142:       lineno++;
        !           143:       if (line[0] == '#')  continue;            /* skip comments */
        !           144:       if (line[0] == '[')  continue;            /* skip next header */
        !           145:       tok = trim(strtok(line, "=\n\r"));        /* get first token */
        !           146:       if (tok != NULL)
        !           147:       {
        !           148:          next = trim(strtok(NULL, "=\n\r"));    /* get actual config information */
        !           149:          for (ptr = configs; ptr->buf; ++ptr)   /* scan for token */
        !           150:          {
        !           151:             if (!strcmp(tok, ptr->code))        /* got a match? */
        !           152:             {
        !           153:                switch (ptr->type)               /* check type */
        !           154:                {
        !           155:                case Bool_Tag:
        !           156:                   if (!strcasecmp(next,"FALSE"))
        !           157:                      *((BOOL *)(ptr->buf)) = FALSE;
        !           158:                   else if (!strcasecmp(next,"TRUE"))
        !           159:                      *((BOOL *)(ptr->buf)) = TRUE;
        !           160:                   ++count;
        !           161:                   break;
        !           162: 
        !           163:                case Char_Tag:
        !           164:                   sscanf(next, "%c", (char *)(ptr->buf));
        !           165:                   ++count;
        !           166:                   break;
        !           167: 
        !           168:                case Short_Tag:
        !           169:                   sscanf(next, "%hd", (short *)(ptr->buf));
        !           170:                   ++count;
        !           171:                   break;
        !           172: 
        !           173:                case Int_Tag:
        !           174:                   sscanf(next, "%d", (int *)(ptr->buf));
        !           175:                   ++count;
        !           176:                   break;
        !           177: 
        !           178:                case Long_Tag:
        !           179:                   sscanf(next, "%ld", (long *)(ptr->buf));
        !           180:                   ++count;
        !           181:                   break;
        !           182: 
        !           183:                case Float_Tag:
        !           184:                   sscanf(next, "%g", (float *)ptr->buf);
        !           185:                   ++count;
        !           186:                   break;
        !           187: 
        !           188:                case Double_Tag:
        !           189:                   sscanf(next, "%lg", (double *)ptr->buf);
        !           190:                   ++count;
        !           191:                   break;
        !           192: 
        !           193:                case String_Tag:
        !           194:                   if(next)
        !           195:                     strcpy((char *)ptr->buf, next);
        !           196:                   else
        !           197:                     *(char *)ptr->buf = 0;
        !           198:                   ++count;
        !           199:                   break;
        !           200: 
        !           201:                case Error_Tag:
        !           202:                default:
        !           203:                   printf("Error in Config file %s on line %d\n", filename, lineno);
        !           204:                   break;
        !           205:                }
        !           206:             }
        !           207: 
        !           208:          }
        !           209:       }
        !           210:     }
        !           211:     while ( fptr!=NULL && line[0]!='[');
        !           212: 
        !           213:    fclose(file);
        !           214:    return count;
        !           215: }
        !           216: 
        !           217: 
        !           218: /* Write out an settings line */
        !           219: static int write_token(FILE *outfile, struct Config_Tag *ptr)
        !           220: {
        !           221:   fprintf(outfile,"%s = ",ptr->code);
        !           222: 
        !           223:   switch (ptr->type)    /* check type */
        !           224:   {
        !           225:     case Bool_Tag:
        !           226:       fprintf(outfile,"%s\n", *((BOOL *)(ptr->buf)) ? "TRUE" : "FALSE");
        !           227:       break;
        !           228: 
        !           229:     case Char_Tag:
        !           230:       fprintf(outfile, "%c\n", *((char *)(ptr->buf)));
        !           231:       break;
        !           232: 
        !           233:     case Short_Tag:
        !           234:       fprintf(outfile, "%hd\n", *((short *)(ptr->buf)));
        !           235:       break;
        !           236: 
        !           237:     case Int_Tag:
        !           238:       fprintf(outfile, "%d\n", *((int *)(ptr->buf)));
        !           239:       break;
        !           240: 
        !           241:     case Long_Tag:
        !           242:       fprintf(outfile, "%ld\n", *((long *)(ptr->buf)));
        !           243:       break;
        !           244: 
        !           245:     case Float_Tag:
        !           246:       fprintf(outfile, "%g\n", *((float *)ptr->buf));
        !           247:       break;
        !           248: 
        !           249:     case Double_Tag:
        !           250:       fprintf(outfile, "%g\n", *((double *)ptr->buf));
        !           251:       break;
        !           252: 
        !           253:     case String_Tag:
        !           254:       fprintf(outfile, "%s\n",(char *)ptr->buf);
        !           255:       break;
        !           256: 
        !           257:     case Error_Tag:
        !           258:     default:
        !           259:       fprintf(stderr, "Error in Config structure (Contact author).\n");
        !           260:       return -1;
        !           261:   }
        !           262: 
        !           263:   return 0;
        !           264: }
        !           265: 
        !           266: 
        !           267: /*---------------------------------------------------------------------/
        !           268: /   updates an input configuration (INI) file from a structure.
        !           269: /---------------------------------------------------------------------*/
        !           270: /*>>------[   update_config()  ]-------------[ 08-02-95 14:02PM ]------/
        !           271: / return value:
        !           272: /     int                     ; Number of records read & updated
        !           273: / parameters:
        !           274: /     char *filename          ; filename of INI file
        !           275: /     struct Config_Tag configs[]; Configuration structure
        !           276: /     char *header            ; INI header name (i.e. "[TEST]")
        !           277: /-------------------------------------------------------------------<<*/
        !           278: int update_config(const char *filename, struct Config_Tag configs[], char *header)
        !           279: {
        !           280:    struct Config_Tag *ptr;
        !           281:    int count=0, lineno=0;
        !           282:    FILE *cfgfile, *tempfile;
        !           283:    char *fptr, *tok, *next;
        !           284:    char line[1024];
        !           285: 
        !           286:    cfgfile = fopen(filename, "r");
        !           287: 
        !           288:    /* If the cfg file does not yet exists, we can create it directly: */
        !           289:    if (cfgfile == NULL)
        !           290:    {
        !           291:       cfgfile = fopen(filename, "w");
        !           292:       if (cfgfile == NULL)
        !           293:          return -1;                             /* return error designation. */
        !           294:       if (header != NULL)
        !           295:       {
        !           296:          fprintf(cfgfile,"%s\n",header);
        !           297:       }
        !           298:       for (ptr=configs; ptr->buf; ++ptr)        /* scan for token */
        !           299:       {
        !           300:          if(write_token(cfgfile, ptr) == 0)
        !           301:            ++count;
        !           302:       }
        !           303: 
        !           304:       fclose(cfgfile);
        !           305:       return count;
        !           306:    }
        !           307: 
        !           308:    tempfile = tmpfile();                        /* Open a temporary file for output */
        !           309:    if (tempfile == NULL)
        !           310:    {
        !           311:       fclose(cfgfile);
        !           312:       return -1;                                /* return error designation. */
        !           313:    }
        !           314: 
        !           315:    if (header != NULL)
        !           316:    {
        !           317:       do
        !           318:       {
        !           319:          fptr = trim(fgets(line, sizeof(line), cfgfile));  /* get input line */
        !           320:          if (feof(cfgfile))
        !           321:            break;
        !           322:          fprintf(tempfile, "%s", line);
        !           323:       }
        !           324:       while(memcmp(line, header, strlen(header)));
        !           325:    }
        !           326: 
        !           327:    if (feof(cfgfile))
        !           328:    {
        !           329:       if (header != NULL)
        !           330:       {
        !           331:          fprintf(tempfile, "\n%s\n", header);
        !           332:       }
        !           333:       for (ptr = configs; ptr->buf; ++ptr)                /* scan for token */
        !           334:       {
        !           335:          if(write_token(tempfile, ptr) == 0)
        !           336:            ++count;
        !           337:       }
        !           338:    }
        !           339:    else
        !           340:    {
        !           341:       char *savedtokenflags;            /* Array to log the saved tokens */
        !           342:       int numtokens;                    /* Total number of tokens to save */
        !           343: 
        !           344:       /* Find total number of tokens: */
        !           345:       numtokens = 0;
        !           346:       for (ptr=configs; ptr->buf; ++ptr)
        !           347:       {
        !           348:          numtokens += 1;
        !           349:       }
        !           350: 
        !           351:       savedtokenflags = malloc(numtokens * sizeof(char));
        !           352:       if (savedtokenflags)
        !           353:         memset(savedtokenflags, 0, numtokens * sizeof(char));
        !           354: 
        !           355:       for(;;)
        !           356:       {
        !           357:          fptr = trim(fgets(line, sizeof(line), cfgfile));  /* get input line */
        !           358:          if (fptr == NULL)  break;
        !           359:          lineno++;
        !           360:          if (line[0] == '#')
        !           361:          {
        !           362:             fprintf(tempfile, "%s", line);
        !           363:             continue;                                 /* skip comments */
        !           364:          }
        !           365:          if (line[0] == '[' || feof(cfgfile))
        !           366:          {
        !           367:            break;
        !           368:          }
        !           369: 
        !           370:          tok = trim(strtok(line, "=\n\r"));           /* get first token */
        !           371:          if (tok != NULL)
        !           372:          {
        !           373:             int i = 0;
        !           374:             next = strtok(line, "=\n\r");             /* get actual config information */
        !           375:             for (ptr = configs; ptr->buf; ++ptr, i++) /* scan for token */
        !           376:             {
        !           377:                if (!strcmp(tok, ptr->code))           /* got a match? */
        !           378:                {
        !           379:                  if (write_token(tempfile, ptr) == 0)
        !           380:                  {
        !           381:                    if (savedtokenflags)
        !           382:                      savedtokenflags[i] = TRUE;
        !           383:                    count += 1;
        !           384:                  }
        !           385:                }
        !           386:             }
        !           387:          }
        !           388:       }
        !           389: 
        !           390:       /* Write remaining (new?) tokens that were not in the configuration file, yet */
        !           391:       if (count != numtokens && savedtokenflags != NULL)
        !           392:       {
        !           393:         int i;
        !           394:         for (ptr = configs, i = 0; ptr->buf; ++ptr, i++)
        !           395:         {
        !           396:           if (!savedtokenflags[i])
        !           397:           {
        !           398:             if (write_token(tempfile, ptr) == 0)
        !           399:             {
        !           400:               count += 1;
        !           401:               fprintf(stderr, "Wrote new token %s -> %s \n", header, ptr->code);
        !           402:             }
        !           403:           }
        !           404:         }
        !           405:       }
        !           406: 
        !           407:       if (savedtokenflags)  free(savedtokenflags);
        !           408:       savedtokenflags = NULL;
        !           409: 
        !           410:       if (!feof(cfgfile) && fptr != NULL)
        !           411:         fprintf(tempfile, "\n%s", line);
        !           412: 
        !           413:       for(;;)
        !           414:       {
        !           415:         fptr = trim(fgets(line, sizeof(line), cfgfile));  /* get input line */
        !           416:         if (feof(cfgfile))
        !           417:           break;
        !           418:         fprintf(tempfile, "%s", line);
        !           419:       }
        !           420:    }
        !           421: 
        !           422: 
        !           423:    /* Re-open the config file for writing: */
        !           424:    fclose(cfgfile);
        !           425:    cfgfile = fopen(filename, "wb");
        !           426:    if (cfgfile == NULL)
        !           427:    {
        !           428:      fclose(tempfile);
        !           429:      return -1;
        !           430:    }
        !           431: 
        !           432:    if(fseek(tempfile, 0, SEEK_SET) != 0)
        !           433:    {
        !           434:      fclose(cfgfile);
        !           435:      fclose(tempfile);
        !           436:      return -1;
        !           437:    }
        !           438: 
        !           439:    /* Now copy the temporary file to the configuration file: */
        !           440:    while(!feof(tempfile))
        !           441:    {
        !           442:      size_t copycount;
        !           443:      copycount = fread(line, sizeof(char), sizeof(line), tempfile);
        !           444:      if(fwrite(line, sizeof(char), copycount, cfgfile) != copycount)
        !           445:      {
        !           446:        fclose(cfgfile);
        !           447:        fclose(tempfile);
        !           448:        return -1;
        !           449:      }
        !           450:    }
        !           451: 
        !           452:    fclose(cfgfile);
        !           453:    fclose(tempfile);
        !           454:    return count;
        !           455: }
        !           456: 

unix.superglobalmegacorp.com

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