profile.c

Go to the documentation of this file.
00001 
00002 /*
00003  * Initialization-File Functions.
00004  *
00005  * From the Wine project
00006  
00007  Copyright (C) 1993, 1994 Miguel de Icaza.
00008  
00009  This program is free software; you can redistribute it and/or modify
00010  it under the terms of the GNU General Public License as published by
00011  the Free Software Foundation; either version 2 of the License, or
00012  (at your option) any later version.
00013  
00014  This program is distributed in the hope that it will be useful,
00015  but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  GNU General Public License for more details.
00018  
00019  You should have received a copy of the GNU General Public License
00020  along with this program; if not, write to the Free Software
00021  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
00022  */
00023 
00024 /*
00025 static char Copyright[] = "Copyright (C) 1993, 1994 Miguel de Icaza";
00026 static char rcsid[] = "$Id: profile.c,v 1.1 2004/07/11 15:26:35 sash Exp $";
00027 */
00028 
00029 #include <stdio.h>
00030 #include <string.h>
00031 #include <stdlib.h>   /* For free() and atoi() */
00032 #include <sys/types.h>
00033 /* 
00034  * #include "mad.h"
00035  * #include "util.h"
00036  * #include "global.h"
00037  */
00038 /*
00039  * this was in mad.h, Memory Allocation Debugging system 
00040  * Hopefully, i'll have not too many problems with memory,
00041  * so i just drop it.         sash
00042  */
00043 #define xmalloc(x, y)     malloc (x)
00044 #include "profile.h"
00045 
00046 #define INIFILE "win.ini"
00047 #define STRSIZE 255
00048 #define overflow (next == &CharBuffer [STRSIZE-1])
00049 
00050 enum {
00051    FirstBrace, OnSecHeader, IgnoreToEOL, KeyDef, KeyValue, FirstChar
00052 };
00053 
00054 typedef struct TKeys {
00055    char   *KeyName;
00056    char   *Value;
00057    struct TKeys *link;
00058 } TKeys;
00059 
00060 typedef struct TSecHeader {
00061    char   *AppName;
00062    TKeys  *Keys;
00063    struct TSecHeader *link;
00064 } TSecHeader;
00065 
00066 typedef struct TProfile {
00067    char   *FileName;
00068    TSecHeader *Section;
00069    struct TProfile *link;
00070 } TProfile;
00071 
00072 TProfile *Current = 0;
00073 TProfile *Base = 0;
00074 
00075 static int
00076 is_loaded (char *FileName, TSecHeader ** section)
00077 {
00078    TProfile *p = Base;
00079 
00080    while (p) {
00081       if (!strcasecmp (FileName, p->FileName)) {
00082    Current = p;
00083    *section = p->Section;
00084    return 1;
00085       }
00086       p = p->link;
00087    }
00088    return 0;
00089 }
00090 
00091 /*#define DEBUG */
00092 
00093 static TSecHeader *
00094 load (char *file)
00095 {
00096    FILE   *f;
00097    int     state;
00098    TSecHeader *SecHeader = 0;
00099    char    CharBuffer[STRSIZE];
00100    char   *next = "";   /* Not needed */
00101    int     c;
00102 
00103    if ((f = fopen (file, "r")) == NULL)
00104       return NULL;
00105 
00106    state = FirstBrace;
00107    while ((c = getc (f)) != EOF) {
00108       if (c == '\r')    /* Ignore Carriage Return */
00109    continue;
00110 
00111       switch (state) {
00112 
00113       case OnSecHeader:
00114    if (c == ']' || overflow) {
00115       *next = '\0';
00116       next = CharBuffer;
00117       SecHeader->AppName = strdup (CharBuffer);
00118       state = IgnoreToEOL;
00119    } else
00120       *next++ = c;
00121    break;
00122 
00123       case IgnoreToEOL:
00124    if (c == '\n') {
00125       state = FirstChar;
00126       next = CharBuffer;
00127    }
00128    break;
00129 
00130       case FirstBrace:
00131       case FirstChar:
00132    if (c == '#' || c == ';') {
00133       state = IgnoreToEOL;
00134       break;
00135    }
00136       case KeyDef:
00137    if (c == '[') {
00138       TSecHeader *temp;
00139 
00140       temp = SecHeader;
00141       SecHeader = (TSecHeader *) xmalloc (sizeof (TSecHeader),
00142             "KeyDef");
00143       SecHeader->link = temp;
00144       SecHeader->Keys = 0;
00145       state = OnSecHeader;
00146       next = CharBuffer;
00147       break;
00148    }
00149    if (state == FirstBrace) /* On first pass, don't allow dangling keys */
00150       break;
00151 
00152    if (state == FirstChar)  /* On first pass, don't allow dangling keys */
00153       state = KeyDef;
00154 
00155    if (c == ' ' || c == '\t')
00156       break;
00157 
00158    if (c == '\n' || overflow) { /* Abort Definition */
00159 #ifdef DEBUG
00160       printf ("Abort %s (%s)\n", next, CharBuffer);
00161 #endif
00162       next = CharBuffer;
00163       break;
00164    }
00165    if (c == '=' || overflow) {
00166       TKeys  *temp;
00167 
00168       temp = SecHeader->Keys;
00169       *next = '\0';
00170       SecHeader->Keys = (TKeys *) xmalloc (sizeof (TKeys), "KD2");
00171       SecHeader->Keys->link = temp;
00172       SecHeader->Keys->KeyName = strdup (CharBuffer);
00173       state = KeyValue;
00174       next = CharBuffer;
00175    } else
00176       *next++ = c;
00177    break;
00178 
00179       case KeyValue:
00180    if (overflow || c == '\n') {
00181       *next = '\0';
00182       SecHeader->Keys->Value = strdup (CharBuffer);
00183       state = c == '\n' ? FirstChar : IgnoreToEOL;
00184       next = CharBuffer;
00185 #ifdef DEBUG
00186       printf ("[%s] (%s)=%s\n", SecHeader->AppName,
00187         SecHeader->Keys->KeyName, SecHeader->Keys->Value);
00188 #endif
00189    } else
00190       *next++ = c;
00191    break;
00192 
00193       }       /* switch */
00194 #ifdef DEBUG
00195       printf ("%i Step %c [%s] (%s)\n", state, c, next, CharBuffer);
00196 #endif
00197    }        /* while ((c = getc (f)) != EOF) */
00198    return SecHeader;
00199 }
00200 
00201 static void
00202 new_key (TSecHeader * section, char *KeyName, char *Value)
00203 {
00204    TKeys  *key;
00205 
00206    key = (TKeys *) xmalloc (sizeof (TKeys), "new_key");
00207    key->KeyName = strdup (KeyName);
00208    key->Value = strdup (Value);
00209    key->link = section->Keys;
00210    section->Keys = key;
00211 }
00212 
00213 char   *
00214 GetSetProfileChar (int set, char *AppName, char *KeyName,
00215        char *Default, char *FileName)
00216 {
00217 
00218    TProfile *New;
00219    TSecHeader *section;
00220    TKeys  *key;
00221 
00222    if (!is_loaded (FileName, &section)) {
00223       New = (TProfile *) xmalloc (sizeof (TProfile), "GetSetProfile");
00224       New->link = Base;
00225       New->FileName = strdup (FileName);
00226       New->Section = load (FileName);
00227       Base = New;
00228       section = New->Section;
00229       Current = New;
00230    }
00231    /* Start search */
00232    for (; section; section = section->link) {
00233       if (strcasecmp (section->AppName, AppName))
00234    continue;
00235       for (key = section->Keys; key; key = key->link) {
00236    if (strcasecmp (key->KeyName, KeyName))
00237       continue;
00238    if (set) {
00239       free (key->Value);
00240       key->Value = strdup (Default);
00241    }
00242    return key->Value;
00243       }
00244       /* If getting the information, then don't write the information
00245        * to the INI file, need to run a couple of tests with windog */
00246       /* No key found */
00247       if (set) {
00248    new_key (section, KeyName, Default);
00249    return 0;
00250       }
00251    }
00252 
00253    /* Non existent section */
00254    if (set) {
00255       section = (TSecHeader *) xmalloc (sizeof (TSecHeader), "GSP3");
00256       section->AppName = strdup (AppName);
00257       section->Keys = 0;
00258       new_key (section, KeyName, Default);
00259       section->link = Current->Section;
00260       Current->Section = section;
00261    }
00262    return Default;
00263 }
00264 
00265 short
00266 GetSetProfile (int set, char *AppName, char *KeyName, char *Default,
00267          char *ReturnedString, short Size, char *FileName)
00268 {
00269    char   *s;
00270 
00271    s = GetSetProfileChar (set, AppName, KeyName, Default, FileName);
00272    if (!set) {
00273       ReturnedString[Size - 1] = 0;
00274       strncpy (ReturnedString, s, Size - 1);
00275    }
00276    return 1;
00277 }
00278 
00279 short
00280 GetPrivateProfileString (char *AppName, char *KeyName,
00281        char *Default, char *ReturnedString,
00282        short Size, char *FileName)
00283 {
00284    return (GetSetProfile (0, AppName, KeyName, Default, ReturnedString, Size, FileName));
00285 }
00286 
00287 char   *
00288 get_profile_string (char *AppName, char *KeyName, char *Default,
00289         char *FileName)
00290 {
00291    return GetSetProfileChar (0, AppName, KeyName, Default, FileName);
00292 }
00293 
00294 int
00295 GetProfileString (char *AppName, char *KeyName, char *Default,
00296       char *ReturnedString, int Size)
00297 {
00298    return GetPrivateProfileString (AppName, KeyName, Default,
00299            ReturnedString, Size, INIFILE);
00300 }
00301 
00302 int
00303 GetPrivateProfileInt (char *AppName, char *KeyName, short Default,
00304           char *File)
00305 {
00306    static char IntBuf[10];
00307    static char buf[10];
00308 
00309    sprintf (buf, "%d", Default);
00310 
00311    /* Check the exact semantic with the SDK */
00312    GetPrivateProfileString (AppName, KeyName, buf, IntBuf, 5, File);
00313    if (!strcasecmp (IntBuf, "true"))
00314       return 1;
00315    if (!strcasecmp (IntBuf, "yes"))
00316       return 1;
00317    return atoi (IntBuf);
00318 }
00319 
00320 int
00321 GetProfileInt (char *AppName, char *KeyName, int Default)
00322 {
00323    return GetPrivateProfileInt (AppName, KeyName, Default, INIFILE);
00324 }
00325 
00326 int
00327 WritePrivateProfileString (char *AppName, char *KeyName, char *String,
00328          char *FileName)
00329 {
00330    return GetSetProfile (1, AppName, KeyName, String, "", 0, FileName);
00331 }
00332 
00333 int
00334 WriteProfileString (char *AppName, char *KeyName, char *String)
00335 {
00336    return (WritePrivateProfileString (AppName, KeyName, String, INIFILE));
00337 }
00338 
00339 static void
00340 dump_keys (FILE * profile, TKeys * p)
00341 {
00342    if (!p)
00343       return;
00344    dump_keys (profile, p->link);
00345    fprintf (profile, "%s=%s\n", p->KeyName, p->Value);
00346 }
00347 
00348 static void
00349 dump_sections (FILE * profile, TSecHeader * p)
00350 {
00351    if (!p)
00352       return;
00353    dump_sections (profile, p->link);
00354    if (p->AppName[0]) {
00355       fprintf (profile, "\n[%s]\n", p->AppName);
00356       dump_keys (profile, p->Keys);
00357    }
00358 }
00359 
00360 static void
00361 dump_profile (TProfile * p)
00362 {
00363    FILE   *profile;
00364 
00365    if (!p)
00366       return;
00367    dump_profile (p->link);
00368    if ((profile = fopen (p->FileName, "w")) != NULL) {
00369       dump_sections (profile, p->Section);
00370       fclose (profile);
00371    }
00372 }
00373 
00374 /*
00375  * Must be called at the end of wine run
00376  */
00377 
00378 void
00379 sync_profiles (void)
00380 {
00381    dump_profile (Base);
00382 }
00383 
00384 static void
00385 free_keys (TKeys * p)
00386 {
00387    if (!p)
00388       return;
00389    free_keys (p->link);
00390    free (p->KeyName);
00391    free (p->Value);
00392    free (p);
00393 }
00394 
00395 static void
00396 free_sections (TSecHeader * p)
00397 {
00398    if (!p)
00399       return;
00400    free_sections (p->link);
00401    free_keys (p->Keys);
00402    free (p->AppName);
00403    p->link = 0;
00404    p->Keys = 0;
00405    free (p);
00406 }
00407 
00408 static void
00409 free_profile (TProfile * p)
00410 {
00411    if (!p)
00412       return;
00413    free_profile (p->link);
00414    free_sections (p->Section);
00415    free (p->FileName);
00416    free (p);
00417 }
00418 
00419 void
00420 free_profiles (void)
00421 {
00422    free_profile (Base);
00423 }
00424 
00425 void   *
00426 profile_init_iterator (char *appname, char *file)
00427 {
00428    TProfile *New;
00429    TSecHeader *section;
00430 
00431    if (!is_loaded (file, &section)) {
00432       New = (TProfile *) xmalloc (sizeof (TProfile), "GetSetProfile");
00433       New->link = Base;
00434       New->FileName = strdup (file);
00435       New->Section = load (file);
00436       Base = New;
00437       section = New->Section;
00438       Current = New;
00439    }
00440    for (; section; section = section->link) {
00441       if (strcasecmp (section->AppName, appname))
00442    continue;
00443       return section->Keys;
00444    }
00445    return 0;
00446 }
00447 
00448 void   *
00449 profile_iterator_next (void *s, char **key, char **value)
00450 {
00451    TKeys  *keys = (TKeys *) s;
00452 
00453    if (keys) {
00454       *key = keys->KeyName;
00455       *value = keys->Value;
00456       keys = keys->link;
00457    }
00458    return keys;
00459 }
00460 
00461 void
00462 profile_clean_section (char *appname, char *file)
00463 {
00464    TSecHeader *section;
00465 
00466    /* We assume the user has called one of the other initialization funcs */
00467    if (!is_loaded (file, &section)) {
00468       fprintf (stderr, "Warning: profile_clean_section called before init\n");
00469       return;
00470    }
00471    /* We only disable the section, so it will still be freed, but it */
00472    /* won't be find by further walks of the structure */
00473 
00474    for (; section; section = section->link) {
00475       if (strcasecmp (section->AppName, appname))
00476    continue;
00477       section->AppName[0] = 0;
00478    }
00479 }

Generated on 16 Jun 2013 for mollersim by  doxygen 1.6.1