$include (..\lib\compStch.ext) /* *============================================================================ * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE * * Permission to use for any purpose, modify, copy, and make enhancements * and derivative works of the software is granted if attribution is given to * R.M. Gillmore, dba the ACME Software Deli, as the author * * While the ACME Software Deli does not work for money, there is nonetheless * a significant amount of work involved. The ACME Software Deli maintains the * rights to all code written, though it may be used and distributed as long as * the following conditions are maintained. * * 1. The copyright statement at the top of each code block is maintained in * your distribution. * 2. You do not identify yourself as the ACME Software Deli * 3. Any changes made to the software are sent to the ACME Software Deli *============================================================================ */ $eject iniManagerModule: do; $set ( LOGGING = 0 ) $if not noID declare IDString (*) byte data ( '@(#)iniMgr.p86 $Author: rmgillmore $ $Date:: 2025-05-04 19:35:39#$:', 0 ); $endif $include (..\lib\comnDefs.ext) $set ( iniManagerSource ) $include (..\lib\iniMgr.ext) $include (..\lib\mem.ext) $include (..\lib\fileIO.ext) $include (..\lib\string.ext) $include (..\lib\ptrMath.ext) $include (..\lib\arrayMgr.ext) $include (..\lib\errCode.ext) $if LOGGING $include (..\lib\logger.ext) $endif /* * The iniHandle points to a structure containing the file's name, and the * array of sections, managed by arrayMgr */ declare iniHandleStruc literally 'structure ( fileName pointer, sectionArray pointer, changesMade boolean )', /* * This is the structure of each element in the sectionArray in the * iniHandleStruct. A section contains a name, and an array of keyValue * pairs, managed by arrayMgr */ sectionStruc literally 'structure ( sectionName pointer, keyValueArray pointer )', /* * each element in the key/value array is composed of the key name, and it's * associated value (values are ALWAYS strings). The interpretation of the * string is left to the caller */ keyValueStruc literally 'structure ( keyNamePtr pointer, valuePtr pointer )'; /* *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= * isWhitespace() *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */ isWhitespace: procedure ( charIn ) boolean reentrant; declare charIn char, returnCode boolean; returnCode = False; if ( ( SPACE = charIn ) or ( TAB = charIn ) or ( CR = charIn ) or ( LF = charIn ) ) then do; returnCode = True; end; return ( returnCode ); end isWhitespace; /* *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= * stripWhitespace() *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */ declare stripLocation_t literally 'integer', LEADING literally '0', TRAILING literally '1'; stripWhitespace: procedure ( stringInPtr, position ) reentrant; declare stringInPtr pointer, position stripLocation_t; declare stringIn based stringInPtr (*) char, indexStep integer, indexStart integer, stringIndex integer, done boolean; if ( position = LEADING ) then do; indexStep = 1; indexStart = 0; end; else if ( position = TRAILING ) then do; indexStep = -1; indexStart = signed( strlen( stringInPtr ) ) - 1; end; stringIndex = indexStart; done = False; do while ( not done ); if isWhitespace( stringIn( stringIndex ) ) then do; stringIndex = stringIndex + indexStep; end; else done = True; end; /* while not done */ if ( position = LEADING ) then do; if ( stringIndex > 0 ) then call strcpy( @stringIn, @stringIn( stringIndex ) ); end; else do; stringIn( stringIndex + 1 ) = EOS; end; end stripWhitespace; /* *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= * captureSectionName() *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */ captureSectionName: procedure ( stringInPtr ) pointer reentrant; declare stringInPtr pointer; declare localString based stringInPtr (*) char, stringIndex integer, sectionNamePtr pointer; /* * the input string will have the section name, followed * by the closing bracket. Also, there could be leading * and trailing whitespace ==> " sectionName ]" */ localString( strlen( @localString ) - 1 ) = EOS; call stripWhitespace( @localString, LEADING ); call stripWhitespace( @localString, TRAILING ); sectionNamePtr = strdup( @localString ); return ( sectionNamePtr ); end captureSectionName; /* *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= * captureKeyValue() *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */ captureKeyValue: procedure ( stringInPtr, keyNamePtrAddress, valuePtrAddress ) reentrant; declare stringInPtr pointer, keyNamePtrAddress pointer, valuePtrAddress pointer, keyNamePtr based keyNamePtrAddress pointer, valuePtr based valuePtrAddress pointer, equalStringPtr pointer, singleChar based equalStringPtr char; /* * the input string will be formatted with a key name, * an equal sign, and a value string. As with everything else, * there may be whitespace among the key name, equal sign and value * string. */ keyNamePtr = stringInPtr; equalStringPtr = strchr( keyNamePtr, '=' ); singleChar = EOS; valuePtr = incPtr( equalStringPtr, size( singleChar ), 1 ); $if LOGGING call addToLog( DEBUG, __FILE__, __LINE__, @( 'keyNamePtr: ''%s'' valuePtr: ''%s''', 0 ), keyNamePtr, valuePtr ); $endif /* * the leading and trailing whitespace has been trimmed, so find the * equal sign, and trim whitespace again. The first token will be * the key, while the second token will be the value */ call stripWhitespace( keyNamePtr, TRAILING ); call stripWhitespace( valuePtr, LEADING ); $if LOGGING call addToLog( DEBUG, __FILE__, __LINE__, @( 'keyNamePtr: ''%s'' valuePtr: ''%s''', 0 ), keyNamePtr, valuePtr ); $endif keyNamePtr = strdup( keyNamePtr ); valuePtr = strdup( valuePtr ); end captureKeyValue; /* *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= * findKeyValue() * * Walk the array of key/value pairs looking for the key whose name was * specified. When found, return the address of that key/value pair. If a * pair with the specified key name was not found, return NULL *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */ findKeyValue: procedure ( keyValueArray, keyNamePtr ) pointer reentrant; declare keyValueArray pointer, /* the array of key/value pairs */ keyNamePtr pointer; /* a string with the key name */ declare done boolean, status word, keyValuePtr pointer, keyValueElement based keyValuePtr keyValueStruc; $if LOGGING call addToLog( DEBUG, __FILE__, __LINE__, @( 'Looking for ''%s'' in the array at %p', 0 ), keyNamePtr, keyValueArray ); $endif done = False; keyValuePtr = 1; call rewindArray( keyValueArray ); do while ( ( not done ) and ( keyValuePtr <> NULL ) ); call nextElement( keyValueArray, @keyValuePtr, @status ); if ( status <> 0 ) then do; $if LOGGING call addToLog( DEBUG, __FILE__, __LINE__, @( 'status: %d, No key named ''%s''', 0 ), status, keyNamePtr ); $endif keyValuePtr = NULL; done = True; end; else do; $if LOGGING call addToLog( DEBUG, __FILE__, __LINE__, @( 'Element address ''%p''', 0 ), keyValuePtr ); call addToLog( DEBUG, __FILE__, __LINE__, @( 'keyName ''%s'' (%p) whose value is ''%s'' (%p)', 0 ), keyValueElement.keyNamePtr, keyValueElement.keyNamePtr, keyValueElement.valuePtr, keyValueElement.valuePtr ); $endif if ( strcmp( keyValueElement.keyNamePtr, keyNamePtr ) = 0 ) then do; $if LOGGING call addToLog( DEBUG, __FILE__, __LINE__, @( 'we found ''%s''', 0 ), keyNamePtr ); $endif done = True; end; end; /* found a section element */ end; /* while not done */ return ( keyValuePtr ); end findKeyValue; /* *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= * findSection() * * Walk the array of sections looking for the section whose name was specified. * When found, return the address of that section. If a section with the * specified name was not found, return NULL *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */ findSection: procedure ( sectionArray, sectionNamePtr ) pointer reentrant; declare sectionArray pointer, /* address of array of sections */ sectionNamePtr pointer, /* name of section - string */ sectionElementPtr pointer, /* address of sectionElement */ sectionElement based sectionElementPtr sectionStruc; declare done boolean, status word; $if LOGGING call addToLog( DEBUG, __FILE__, __LINE__, @( 'We are looking for ''%s''', 0 ), sectionNamePtr ); $endif done = False; call rewindArray( sectionArray ); do while ( not done ); call nextElement( sectionArray, @sectionElementPtr, @status ); if ( status <> 0 ) then do; $if LOGGING call addToLog( DEBUG, __FILE__, __LINE__, @( 'No section named %s', 0 ), sectionNamePtr ); $endif sectionElementPtr = NULL; done = True; end; else do; $if LOGGING call addToLog( DEBUG, __FILE__, __LINE__, @( 'sectionElement: %p whose name is ''%s''', 0 ), sectionElementPtr, sectionElement.sectionName ); $endif if ( strcmp( sectionElement.sectionName, sectionNamePtr ) = 0 ) then do; $if LOGGING call addToLog( DEBUG, __FILE__, __LINE__, @( 'we found ''%s'' in %p', 0 ), sectionNamePtr, sectionElementPtr ); $endif done = True; end; end; /* found a section element */ end; /* while not done */ return ( sectionElementPtr ); end findSection; /* *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= * addToSection() *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */ addToSection: procedure ( sectionArray, keyNamePtr, valuePtr ) reentrant; declare sectionArray pointer, sectionElement based sectionArray sectionStruc, keyNamePtr pointer, valuePtr pointer, keyValuePtr pointer, keyValue based keyValuePtr keyValueStruc, status word; /* * Given the name of the section, and a key/value pair, add the key/value * pair to the section array. * * Note that while the intent here is to ADD the key/value pair to the section, * if the key exists in the section, change only the value and we're done. */ declare done boolean, freeReturned integer; $if LOGGING call addToLog( DEBUG, __FILE__, __LINE__, @( 'adding to section %p''%s'': keyName: %p[''%s''] value: %p[''%s'']', 0 ), sectionElement.sectionName, sectionElement.sectionName, keyNamePtr, keyNamePtr, valuePtr, valuePtr ); $endif call rewindArray( sectionElement.keyValueArray ); done = False; do while ( not done ); call nextElement( sectionElement.keyValueArray, @keyValuePtr, @status ); if ( strcmp( keyValue.keyNamePtr, keyNamePtr ) = 0 ) then do; /* * we found a key/value, so change the value and we are done */ freeReturned = free( keyValue.valuePtr ); keyValue.valuePtr = strdup( valuePtr ); done = True; end; else if ( status <> 0 ) then do; keyValuePtr = malloc( size( keyValue ) ); keyValue.keyNamePtr = strdup( keyNamePtr ); keyValue.valuePtr = strdup( valuePtr ); $if LOGGING call addToLog( DEBUG, __FILE__, __LINE__, @( 'adding to section %p ''%s'': keyName: %p[''%s''] value: %p[''%s'']', 0 ), sectionElement.sectionName, sectionElement.sectionName, keyValue.keyNamePtr, keyValue.keyNamePtr, keyValue.valuePtr, keyValue.valuePtr ); $endif call appendElement( sectionElement.keyValueArray, @keyValuePtr, @status ); $if LOGGING call addToLog( DEBUG, __FILE__, __LINE__, @( 'added to section %p ''%s'': keyName: %p[''%s''] value: %p[''%s'']', 0 ), sectionElement.sectionName, sectionElement.sectionName, keyValue.keyNamePtr, keyValue.keyNamePtr, keyValue.valuePtr, keyValue.valuePtr ); $endif done = True; end; end; /* while not done */ end addToSection; /* *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= * createSection() *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */ createSection: procedure ( iniHandlePtr, sectionNamePtr ) pointer reentrant; declare iniHandlePtr iniHandle_t, iniHandle based iniHandlePtr iniHandleStruc, sectionNamePtr pointer, sectionPtr pointer, sectionElement based sectionPtr sectionStruc, status word; /* * Before we create a section, we should ensure there is not already a * section with the same name (in other words, the section already exists) */ $if LOGGING call addToLog( DEBUG, __FILE__, __LINE__, @( 'looking for section ''%s''', 0 ), sectionNamePtr ); call addToLog( DEBUG, __FILE__, __LINE__, @( 'iniHandle.sectionArray: %p', 0 ), iniHandle.sectionArray ); $endif if ( arrayLength( iniHandle.sectionArray ) = 0 ) then do; /* * no sections */ $if LOGGING call addToLog( DEBUG, __FILE__, __LINE__, @( 'iniHandle.sectionArray: %p', 0 ), iniHandle.sectionArray ); $endif sectionPtr = malloc( size( sectionElement ) ); sectionElement.sectionName = sectionNamePtr; sectionElement.keyValueArray = createArray( 1, pointerType ); call appendElement( iniHandle.sectionArray, @sectionPtr, @status ); iniHandle.changesMade = True; end; else do; /* * there are sections, see if this section already exists. if it * does not exist, create it */ declare done boolean; call rewindArray( iniHandle.sectionArray ); done = False; do while ( not done ); call nextElement( iniHandle.sectionArray, @sectionPtr, @status ); $if LOGGING call addToLog( DEBUG, __FILE__, __LINE__, @( 'sectionElement: %p', 0 ), sectionPtr ); $endif if ( strcmp( sectionElement.sectionName, sectionNamePtr ) = 0 ) then do; done = True; end; else if ( status <> 0 ) then do; sectionPtr = malloc( size( sectionElement ) ); sectionElement.sectionName = sectionNamePtr; sectionElement.keyValueArray = createArray( 1, pointerType ); call appendElement( iniHandle.sectionArray, @sectionPtr, @status ); done = True; iniHandle.changesMade = True; end; end; /* while not done */ end; return( sectionPtr ); end createSection; /* *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= * openIni() * * open the specified .ini file, read the contents to memory for later use. If * the .ini file does not exist, a file is created. * * The handle returned is a loose equivalent of a this pointer in a class * implementation. *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */ openIni: procedure ( fileNamePtr ) iniHandle_t reentrant public; declare fileNamePtr pointer, fileName based fileNamePtr (*) char; declare returnHandle iniHandle_t, fileHandle word, freeReturned word, localIniHandle based returnHandle iniHandleStruc; returnHandle = malloc( size( localIniHandle ) ); $if LOGGING call addToLog( DEBUG, __FILE__, __LINE__, @( 'returnHandle: %p', 0 ), returnHandle ); $endif if ( returnHandle <> NULL ) then do; localIniHandle.sectionArray = createArray( 1, pointerType ); $if LOGGING call addToLog( DEBUG, __FILE__, __LINE__, @( 'sectionArray: %p', 0 ), localIniHandle.sectionArray ); $endif localIniHandle.fileName = strdup( fileNamePtr ); $if LOGGING call addToLog( DEBUG, __FILE__, __LINE__, @( 'dup filename: %p (%s)', 0 ), localIniHandle.fileName, localIniHandle.fileName ); $endif /* * the caller has specified the name of the .ini file. if the file * actually exists, we will have a handle. */ fileHandle = fopen( fileNamePtr, @( 'r', 0 ) ); if ( 0 = errno ) then do; declare lineRead ( MAX_LINE ) char, lineReadPtr pointer, sectionNamePtr pointer, sectionPtr pointer, keyNamePtr pointer, valuePtr pointer; sectionNamePtr = NULL; /* * Conceptually, an initialization file is composed of an array * of sections. A section is composed of a name, and an array * of key/value pairs * * The .ini file looks like this: * * # this is a comment line (will be ignored, and lost when * # when the file is written) * * [section1] * name1 = value1 * name2 = value2 * * [section2] * Aname = Avalue * AnotherName = YetAnotherValue * * there may be more than 1 key/value pair in each section, * and more than 1 section in the file. The key must be unique * within a section, but need not be unique within the file * * indentation is not significant, but is acceptable */ do while ( not feof( fileHandle ) ); /* * read a line, and split it up */ lineReadPtr = fgets( fileHandle, @lineRead, size( lineRead ) - 1 ); call stripWhitespace( @lineRead, LEADING ); call stripWhitespace( @lineRead, TRAILING ); if ( strlen( @lineRead ) > 0 ) then do; if ( lineRead( 0 ) = '[' ) then do; /* * remove the leading bracket and send it on (the name * returned is a string whose memory was allocated, * so it must be freed upon close) */ sectionNamePtr = captureSectionName( @lineRead( 1 ) ); sectionPtr = createSection( returnHandle, sectionNamePtr ); end; else do; /* * what we have here is a key/value pair ... isolate * the key and value from either side of an equal * sign. Of course, white space is allowed */ call captureKeyValue( @lineRead, @keyNamePtr, @valuePtr ); call addToSection( sectionPtr, keyNamePtr, valuePtr ); end; end; end; call fclose( fileHandle ); end; /* file opened */ else do; declare numberWritten word; /* * if the file does not exist, create it. */ fileHandle = fopen( fileNamePtr, @( 'w', 0 ) ); numberWritten = fwrite( fileHandle, @( ' ' ), 1 ); call fclose( fileHandle ); end; localIniHandle.changesMade = False; end; $if LOGGING call addToLog( DEBUG, __FILE__, __LINE__, @( 'returning Handle: %p', 0 ), returnHandle ); $endif return ( returnHandle ); end openIni; /* *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= * closeIni() * * Using the iniHandle provided, write any "unsaved" data to the .ini file, * then close the file * * The return code will be zero unless the file could not be closed * successfully. If the return value is not zero, the value was returned * from the DOS call. *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */ closeIni: procedure ( iniHandlePtr ) integer reentrant public; declare iniHandlePtr iniHandle_t, iniHandle based iniHandlePtr iniHandleStruc; declare returnCode integer, status word, sectionsArrayIndex integer, keyValueArrayIndex integer, freeReturned integer, sectionElementPtr pointer, sectionElement based sectionElementPtr sectionStruc, keyValuePtr pointer, keyValueElement based keyValuePtr keyValueStruc, fileHandle word; returnCode = 0; /* * to close the ini, it is necessary to free the key/value pairs from a section, * and then to remove the section */ if ( iniHandle.changesMade ) then do; fileHandle = fopen( iniHandle.fileName, @( 'w', 0 ) ); end; /* * for each section in the array */ do sectionsArrayIndex = 0 to ( arrayLength( iniHandle.sectionArray ) - 1 ); /* * get the section */ call getElement( iniHandle.sectionArray, sectionsArrayIndex, @sectionElementPtr, @status ); if ( iniHandle.changesMade ) then do; call fprintf( fileHandle, @( '[%s]\n', 0 ), sectionElement.sectionName ); end; /* * return the memory occupied for the section name */ freeReturned = free( sectionElement.sectionName ); /* * for each key/value pair in the section */ do keyValueArrayIndex = 0 to ( arrayLength( sectionElement.keyValueArray ) - 1 ); /* * get the key/value pair */ call getElement( sectionElement.keyValueArray, keyValueArrayIndex, @keyValuePtr, @status ); if ( iniHandle.changesMade ) then do; call fprintf( fileHandle, @( '\t%s = %s\n', 0 ), keyValueElement.keyNamePtr, keyValueElement.ValuePtr ); end; /* * free the keyName, the value, and then the memory which grouped them */ freeReturned = free( keyValueElement.keyNamePtr ); freeReturned = free( keyValueElement.ValuePtr ); freeReturned = free( keyValuePtr ); end; /* for each key/value pair */ /* * release the key value array */ if ( iniHandle.changesMade ) then do; call fprintf( fileHandle, @( '\n', 0 ) ); end; call deleteArray( sectionElement.keyValueArray ); /* * free the section element */ freeReturned = free( sectionElementPtr ); end; /* * release the array of sections */ call deleteArray( iniHandle.sectionArray ); /* * release the memory for the initialization filename */ freeReturned = free( iniHandle.fileName ); if ( iniHandle.changesMade ) then do; call fclose( fileHandle ); end; return ( returnCode ); end closeIni; /* *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= * abortIni() * * close the file, tossing any changes on the floor *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */ abortIni: procedure ( iniHandlePtr ) reentrant public; declare iniHandlePtr iniHandle_t, iniHandle based iniHandlePtr iniHandleStruc; declare ignoredCode integer; /* * we will force changesMade to False, thus essentially throwing all that * may have changed to the floor */ iniHandle.changesMade = False; ignoredCode = closeIni( iniHandlePtr ); end abortIni; /* *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= * reportIniData() * * Using the handle to the iniData, report everything in memory to the stdout * in a format similar to the .ini file *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */ reportIniData: procedure ( iniHandlePtr ) reentrant public; declare iniHandlePtr iniHandle_t, iniHandle based iniHandlePtr iniHandleStruc; declare returnCode integer, status word, sectionsArrayIndex integer, keyValueArrayIndex integer, freeReturned boolean, sectionElementPtr pointer, sectionElement based sectionElementPtr sectionStruc, keyValuePtr pointer, keyValueElement based keyValuePtr keyValueStruc; returnCode = 0; /* * to close the ini, it is necessary to free the key/value pairs from a section, * and then to remove the section */ call printf( @( 'iniHandlePtr: %p\n', 0 ), iniHandlePtr ); call printf( @( 'filename: (%p)''%s''\n', 0 ), iniHandle.fileName, iniHandle.fileName ); call printf( @( 'changesMade: %T\n', 0 ), iniHandle.changesMade ); /* * for each section in the array */ do sectionsArrayIndex = 0 to ( arrayLength( iniHandle.sectionArray ) - 1 ); /* * get the section */ call getElement( iniHandle.sectionArray, sectionsArrayIndex, @sectionElementPtr, @status ); /* * return the memory occupied for the section name */ call printf( @( 'section: ''%s''\n', 0 ), sectionElement.sectionName ); /* * for each key/value pair in the section */ do keyValueArrayIndex = 0 to ( arrayLength( sectionElement.keyValueArray ) - 1 ); /* * get the key/value pair */ call getElement( sectionElement.keyValueArray, keyValueArrayIndex, @keyValuePtr, @status ); call printf( @( '\t''%s'' = ''%s''\n', 0 ), keyValueElement.keyNamePtr, keyValueElement.valuePtr ); end; /* for each key/value pair */ call printf( @( '\n', 0 ) ); end; end reportIniData; /* *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= * getFromIniData() * * Using the section name and key name, return the string representing the * value stored. If there is no key name in the specified section, NULL is * returned for the value. *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */ getFromIniData: procedure ( iniHandlePtr, sectionNamePtr, keyNamePtr ) pointer reentrant public; declare iniHandlePtr iniHandle_t, sectionNamePtr pointer, keyNamePtr pointer; declare iniHandle based iniHandlePtr iniHandleStruc, sectionElementPtr pointer, sectionElement based sectionElementPtr sectionStruc, keyValuePtr pointer, keyValue based keyValuePtr keyValueStruc, valuePtr pointer; valuePtr = NULL; sectionElementPtr = findSection( iniHandle.sectionArray, sectionNamePtr ); if ( sectionElementPtr <> NULL ) then do; keyValuePtr = findKeyValue( sectionElement.keyValueArray, keyNamePtr ); if ( keyValuePtr <> NULL ) then do; valuePtr = keyValue.valuePtr; end; end; return ( valuePtr ); end getFromIniData; /* *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= * storeInIniData() * * add the specified key/value pair in the specified section. If the * specified key does not exist in the specified section, the key/value pair * are stored in the section. If, however, the section does not exist, it is * created, and the key/value is added. *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */ storeInIniData: procedure ( iniHandlePtr, sectionNameIn, keyNameIn, valuePtrIn ) reentrant public; declare iniHandlePtr iniHandle_t, iniHandle based iniHandlePtr iniHandleStruc, sectionNameIn pointer, keyNameIn pointer, valuePtrIn pointer; declare sectionNamePtr pointer, sectionElementPtr pointer, sectionElement based sectionElementPtr sectionStruc; sectionNamePtr = strdup( sectionNameIn ); sectionElementPtr = findSection( iniHandle.sectionArray, sectionNamePtr ); if ( NULL = sectionElementPtr ) then do; sectionElementPtr = createSection( iniHandlePtr, sectionNamePtr ); end; call addToSection( sectionElementPtr, keyNameIn, valuePtrIn ); /* * regardless of what we had to do, there were changes made */ iniHandle.changesMade = True; end storeInIniData; deleteSection: procedure ( sectionArray, sectionName ) reentrant; declare sectionArray pointer, sectionName pointer, /* a string */ sectionElementPtr pointer, sectionElement based sectionElementPtr sectionStruc, sectionIndex integer, status integer, done boolean, keyElementPtr pointer, keyElement based keyElementPtr keyValueStruc, keyIndex integer; done = False; sectionIndex = 0; do while ( not done ); call getElement( sectionArray, sectionIndex, @sectionElementPtr, @status ); if ( status <> 0 ) then do; done = True; end; /* there is no section which matches */ else if ( strcmp( sectionElement.sectionName, sectionName ) = 0 ) then do; /* * we have the proper section, now remove each item key/value, * then the key/value array */ do keyIndex = 0 to arrayLength( sectionElement.keyValueArray ) - 1; call getElement( sectionElement.keyValueArray, keyIndex, @keyElementPtr, @status ); if ( status = 0 ) then do; declare freeReturned integer; /* * free the memory of each element in the array */ freeReturned = free( keyElement.keyNamePtr ); freeReturned = free( keyElement.valuePtr ); freeReturned = free( keyElementPtr ); end; end; /* * now that all of the key/value elements have been released, * remove the array */ call deleteArray( sectionElement.keyValueArray ); call removeElementAt( sectionArray, sectionIndex ); done = True; end; /* we found the section */ else do; /* * this is not the section, go to the next one */ sectionIndex = sectionIndex + 1; end; end; /* while not done */ end deleteSection; /* *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= * removeFromIniData() * * remove the key (and its value) from the section. If that is the final * key/value pair in the section, the section is removed also. If keyNamePtr * is NULL, the entire section is removed. *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */ removeFromIniData: procedure ( iniHandlePtr, sectionNamePtr, keyNamePtr ) reentrant public; declare iniHandlePtr iniHandle_t, iniHandle based iniHandlePtr iniHandleStruc, sectionNamePtr pointer, keyNamePtr pointer; declare sectionElementPtr pointer, sectionElement based sectionElementPtr sectionStruc, keyValuePtr pointer, keyValue based keyValuePtr keyValueStruc, done boolean, status integer, freeReturned integer, keyIndex integer; sectionElementPtr = findSection( iniHandle.sectionArray, sectionNamePtr ); if ( sectionElementPtr <> NULL ) then do; if ( NULL = keyNamePtr ) then do; /* * remove the entire section */ call deleteSection( iniHandle.sectionArray, sectionNamePtr ); iniHandle.changesMade = True; end; else do; /* * look for the named key, and its value, and remove it */ done = False; keyIndex = 0; do while ( not done ); call getElement( sectionElement.keyValueArray, keyIndex, @keyValuePtr, @status ); if ( status <> 0 ) then do; /* * there was no key with the supplied name */ done = True; end; else if ( strcmp( keyValue.keyNamePtr, keyNamePtr ) = 0 ) then do; /* * We have found the key, so remove it */ freeReturned = free( keyValue.keyNamePtr ); freeReturned = free( keyValue.valuePtr ); freeReturned = free( keyValuePtr ); call removeElementAt( sectionElement.keyValueArray, keyIndex ); done = True; iniHandle.changesMade = True; end; if ( not done ) then do; keyIndex = keyIndex + 1; end; end; end; end; end removeFromIniData; end iniManagerModule;