1: /*
  2:  * Some portions copyright (c) 1994-1995 by Symantec
  3:  * Copyright (c) 1999-2011 by Digital Mars
  4:  * All Rights Reserved
  5:  * http://www.digitalmars.com
  6:  * Written by Walter Bright
  7:  *
  8:  * This source file is made available for personal use
  9:  * only. The license is in /dmd/src/dmd/backendlicense.txt
 10:  * For any other uses, please contact Digital Mars.
 11:  */
 12: 
 13: #include        <stdio.h>
 14: #include        <string.h>
 15: #include        <stdlib.h>
 16: #include        <ctype.h>
 17: 
 18: #if _WIN32
 19: #include <windows.h>
 20: #endif
 21: 
 22: #if __APPLE__
 23: #include        <sys/syslimits.h>
 24: #endif
 25: 
 26: #if __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
 27: // for PATH_MAX
 28: #include        <limits.h>
 29: #endif
 30: 
 31: #if __sun&&__SVR4
 32: #include        <alloca.h>
 33: #endif
 34: 
 35: #include        "root.h"
 36: #include        "rmem.h"
 37: 
 38: #define LOG     0
 39: 
 40: char *skipspace(const char *p);
 41: 
 42: #if __GNUC__
 43: char *strupr(char *s)
 44: {
 45:     char *t = s;
 46: 
 47:     while (*s)
 48:     {
 49:         *s = toupper(*s);
 50:         s++;
 51:     }
 52: 
 53:     return t;
 54: }
 55: #endif
 56: 
 57: /*****************************
 58:  * Read and analyze .ini file.
 59:  * Input:
 60:  *      argv0   program name (argv[0])
 61:  *      inifile .ini file name
 62:  * Returns:
 63:  *      file name of ini file
 64:  *      Note: this is a memory leak
 65:  */
 66: 
 67: const char *inifile(const char *argv0x, const char *inifilex)
 68: {
 69:     char *argv0 = (char *)argv0x;
 70:     char *inifile = (char *)inifilex;   // do const-correct later
 71:     char *path;         // need path for @P macro
 72:     char *filename;
 73:     OutBuffer buf;
 74:     int i;
 75:     int k;
 76:     int envsection = 0;
 77: 
 78: #if LOG
 79:     printf("inifile(argv0 = '%s', inifile = '%s')\n", argv0, inifile);
 80: #endif
 81:     if (FileName::absolute(inifile))
 82:     {
 83:         filename = inifile;
 84:     }
 85:     else
 86:     {
 87:         /* Look for inifile in the following sequence of places:
 88:          *      o current directory
 89:          *      o home directory
 90:          *      o directory off of argv0
 91:          *      o /etc/
 92:          */
 93:         if (FileName::exists(inifile))
 94:         {
 95:             filename = inifile;
 96:         }
 97:         else
 98:         {
 99:             filename = FileName::combine(getenv("HOME"), inifile);
warning C4996: 'getenv': This function or variable may be unsafe. Consider using _dupenv_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdlib.h(433) : see declaration of 'getenv'
100: if (!FileName::exists(filename)) 101: { 102: #if _WIN32 // This fix by Tim Matthews 103: char resolved_name[MAX_PATH + 1]; 104: if(GetModuleFileName(NULL, resolved_name, MAX_PATH + 1) && FileName::exists(resolved_name)) 105: { 106: filename = (char *)FileName::replaceName(resolved_name, inifile); 107: if(FileName::exists(filename)) 108: goto Ldone; 109: } 110: #endif 111: filename = (char *)FileName::replaceName(argv0, inifile); 112: if (!FileName::exists(filename)) 113: { 114: #if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4 115: #if __GLIBC__ || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4 // This fix by Thomas Kuehne 116: /* argv0 might be a symbolic link, 117: * so try again looking past it to the real path 118: */ 119: #if __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4 120: char resolved_name[PATH_MAX + 1]; 121: char* real_argv0 = realpath(argv0, resolved_name); 122: #else 123: char* real_argv0 = realpath(argv0, NULL); 124: #endif 125: //printf("argv0 = %s, real_argv0 = %p\n", argv0, real_argv0); 126: if (real_argv0) 127: { 128: filename = (char *)FileName::replaceName(real_argv0, inifile); 129: #if linux 130: free(real_argv0); 131: #endif 132: if (FileName::exists(filename)) 133: goto Ldone; 134: } 135: #else 136: #error use of glibc non-standard extension realpath(char*, NULL) 137: #endif 138: if (1){ 139: // Search PATH for argv0 140: const char *p = getenv("PATH"); 141: #if LOG 142: printf("\tPATH='%s'\n", p); 143: #endif 144: Strings *paths = FileName::splitPath(p); 145: filename = FileName::searchPath(paths, argv0, 0); 146: if (!filename) 147: goto Letc; // argv0 not found on path 148: filename = (char *)FileName::replaceName(filename, inifile); 149: if (FileName::exists(filename)) 150: goto Ldone; 151: } 152: #endif 153: 154: // Search /etc/ for inifile 155: Letc:
warning C4102: 'Letc' : unreferenced label
156: filename = FileName::combine((char *)"/etc/", inifile); 157: 158: Ldone: 159: ; 160: } 161: } 162: } 163: } 164: path = FileName::path(filename); 165: #if LOG 166: printf("\tpath = '%s', filename = '%s'\n", path, filename); 167: #endif 168: 169: File file(filename); 170: 171: if (file.read()) 172: return filename; // error reading file 173: 174: // Parse into lines 175: int eof = 0; 176: for (i = 0; i < file.len && !eof; i++)
warning C4018: '<' : signed/unsigned mismatch
177: { 178: int linestart = i; 179: 180: for (; i < file.len; i++)
warning C4018: '<' : signed/unsigned mismatch
181: { 182: switch (file.buffer[i]) 183: { 184: case '\r': 185: break; 186: 187: case '\n': 188: // Skip if it was preceded by '\r' 189: if (i && file.buffer[i - 1] == '\r') 190: goto Lskip; 191: break; 192: 193: case 0: 194: case 0x1A: 195: eof = 1; 196: break; 197: 198: default: 199: continue; 200: } 201: break; 202: } 203: 204: // The line is file.buffer[linestart..i] 205: char *line; 206: int len; 207: char *p; 208: char *pn; 209: 210: line = (char *)&file.buffer[linestart]; 211: len = i - linestart; 212: 213: buf.reset(); 214: 215: // First, expand the macros. 216: // Macros are bracketed by % characters. 217: 218: for (k = 0; k < len; k++) 219: { 220: if (line[k] == '%') 221: { 222: int j; 223: 224: for (j = k + 1; j < len; j++) 225: { 226: if (line[j] == '%') 227: { 228: if (j - k == 3 && memicmp(&line[k + 1], "@P", 2) == 0)
warning C4996: 'memicmp': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _memicmp. See online help for details. c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(93) : see declaration of 'memicmp'
229: { 230: // %@P% is special meaning the path to the .ini file 231: p = path; 232: if (!*p) 233: p = (char *)"."; 234: } 235: else 236: { int len = j - k;
warning C6246: Local declaration of 'len' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '206' of 'c:\projects\extern\d\dmd\src\inifile.c': Lines: 206
237: char tmp[10]; // big enough most of the time 238: 239: if (len <= sizeof(tmp)) 240: p = tmp; 241: else 242: p = (char *)alloca(len);
warning C6255: _alloca indicates failure by raising a stack overflow exception. Consider using _malloca instead
warning C6263: Using _alloca in a loop: this can quickly overflow stack: Lines: 224
243: len--; 244: memcpy(p, &line[k + 1], len); 245: p[len] = 0; 246: strupr(p);
warning C4996: 'strupr': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _strupr. See online help for details. c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(252) : see declaration of 'strupr'
247: p = getenv(p);
warning C4996: 'getenv': This function or variable may be unsafe. Consider using _dupenv_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdlib.h(433) : see declaration of 'getenv'
248: if (!p) 249: p = (char *)""; 250: } 251: buf.writestring(p); 252: k = j; 253: goto L1; 254: } 255: } 256: } 257: buf.writeByte(line[k]); 258: L1: 259: ; 260: } 261: 262: // Remove trailing spaces 263: while (buf.offset && isspace(buf.data[buf.offset - 1])) 264: buf.offset--; 265: 266: p = buf.toChars(); 267: 268: // The expanded line is in p. 269: // Now parse it for meaning. 270: 271: p = skipspace(p); 272: switch (*p) 273: { 274: case ';': // comment 275: case 0: // blank 276: break; 277: 278: case '[': // look for [Environment] 279: p = skipspace(p + 1); 280: for (pn = p; isalnum(*pn); pn++)
warning C6328: 'char' passed as parameter '1' when 'unsigned char' is required in call to 'isalnum'
281: ; 282: if (pn - p == 11 && 283: memicmp(p, "Environment", 11) == 0 && 284: *skipspace(pn) == ']' 285: )
warning C4996: 'memicmp': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _memicmp. See online help for details. c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(93) : see declaration of 'memicmp'
286: envsection = 1; 287: else 288: envsection = 0; 289: break; 290: 291: default: 292: if (envsection) 293: { 294: pn = p; 295: 296: // Convert name to upper case; 297: // remove spaces bracketing = 298: for (p = pn; *p; p++) 299: { if (islower(*p))
warning C6328: 'char' passed as parameter '1' when 'unsigned char' is required in call to 'islower'
300: *p &= ~0x20; 301: else if (isspace(*p))
warning C6328: 'char' passed as parameter '1' when 'unsigned char' is required in call to 'isspace'
302: memmove(p, p + 1, strlen(p)); 303: else if (*p == '=') 304: { 305: p++; 306: while (isspace(*p))
warning C6328: 'char' passed as parameter '1' when 'unsigned char' is required in call to 'isspace'
307: memmove(p, p + 1, strlen(p)); 308: break; 309: } 310: } 311: 312: putenv(strdup(pn));
warning C4996: 'putenv': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _putenv. See online help for details. c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdlib.h(869) : see declaration of 'putenv'
warning C6031: Return value ignored: 'putenv'
313: #if LOG 314: printf("\tputenv('%s')\n", pn); 315: //printf("getenv(\"TEST\") = '%s'\n",getenv("TEST")); 316: #endif 317: } 318: break; 319: } 320: 321: Lskip: 322: ; 323: } 324: return filename; 325: } 326: 327: /******************** 328: * Skip spaces. 329: */ 330: 331: char *skipspace(const char *p) 332: { 333: while (isspace(*p))
warning C6328: 'const char' passed as parameter '1' when 'unsigned char' is required in call to 'isspace'
334: p++; 335: return (char *)p; 336: } 337: 338: