tng 2002/11/22 06:57:32 Modified: c/src/xercesc/util/Platforms/OS390 Makefile.in OS390PlatformUtils.cpp Added: c/src/xercesc/util/Platforms/OS390 FileHandleImpl.cpp FileHandleImpl.hpp Path390.cpp Path390.hpp Log: 390: support record-oriented MVS datasets with the DOM Level 3 serialization APIs. Patch by Chris Larsson and Stephen Dulin. Revision Changes Path 1.3 +7 -1 xml-xerces/c/src/xercesc/util/Platforms/OS390/Makefile.in Index: Makefile.in =================================================================== RCS file: /home/cvs/xml-xerces/c/src/xercesc/util/Platforms/OS390/Makefile.in,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- Makefile.in 26 Jul 2002 16:49:28 -0000 1.2 +++ Makefile.in 22 Nov 2002 14:57:32 -0000 1.3 @@ -54,6 +54,9 @@ # <http://www.apache.org/>. # # $Log$ +# Revision 1.3 2002/11/22 14:57:32 tng +# 390: support record-oriented MVS datasets with the DOM Level 3 serialization APIs. Patch by Chris Larsson and Stephen Dulin. +# # Revision 1.2 2002/07/26 16:49:28 tng # [Bug 2681] Can't build with gcc/g++ not named 'gcc'/'g++'. Patch from Jonathan Lennox. # @@ -94,6 +97,9 @@ SUBMODULE = Platforms/OS390 CPP_PUBHEADERS = OS390Defs.hpp -CPP_OBJECTS = OS390PlatformUtils.$(TO) +CPP_OBJECTS = \ + OS390PlatformUtils.$(TO) \ + Path390.$(TO) \ + FileHandleImpl.$(TO) include ../../Makefile.util.submodule 1.6 +509 -309 xml-xerces/c/src/xercesc/util/Platforms/OS390/OS390PlatformUtils.cpp Index: OS390PlatformUtils.cpp =================================================================== RCS file: /home/cvs/xml-xerces/c/src/xercesc/util/Platforms/OS390/OS390PlatformUtils.cpp,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- OS390PlatformUtils.cpp 4 Nov 2002 15:13:01 -0000 1.5 +++ OS390PlatformUtils.cpp 22 Nov 2002 14:57:32 -0000 1.6 @@ -1,7 +1,7 @@ /* * The Apache Software License, Version 1.1 * - * Copyright (c) 1999-2000 The Apache Software Foundation. All rights + * Copyright (c) 1999-2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without @@ -88,9 +88,13 @@ #include <xercesc/util/XMLString.hpp> #include <xercesc/util/XMLUniDefs.hpp> #include <xercesc/util/XMLUni.hpp> +#include "Path390.hpp" +#include "FileHandleImpl.hpp" #if defined (XML_USE_ICU_TRANSCODER) #include <xercesc/util/Transcoders/ICU/ICUTransService.hpp> +#elif defined (XML_USE_UNICONV390_TRANSCODER) + #include <xercesc/util/Transcoders/Uniconv390/Uniconv390TransService.hpp> #else // use native transcoder #include <xercesc/util/Transcoders/Iconv390/Iconv390TransService.hpp> #endif @@ -119,20 +123,21 @@ void XMLPlatformUtils::platformInit() { + // The next conditional section is to turn on support for allowing // the NEL character as a valid whitespace character. Once this is // enabled the parser is non-compliant with the XML standard. // Assumption: Once this is enabled, it cannot be reset and // should remain the same during the same process. #if defined XML_ALLOW_NELWS - try - { + try + { XMLPlatformUtils::recognizeNEL(true); - } - catch (...) - { - panic(XMLPlatformUtils::Panic_SystemInit); - } + } + catch (...) + { + panic(XMLPlatformUtils::Panic_SystemInit); + } #endif // The next section checks if Posix is enabled on the OS/390 system. @@ -143,20 +148,19 @@ // Assumption: Once this is enabled, it cannot be reset and // should remain the same during the same process. -#ifdef OS390BATCH - try - { - if (__isPosixOn()) - { + try + { + if (__isPosixOn()) + { if (!isPosixEnabled) isPosixEnabled = true; - } - } - catch (...) - { - panic(XMLPlatformUtils::Panic_SystemInit); - } -#endif + } + } + catch (...) + { + panic(XMLPlatformUtils::Panic_SystemInit); + } + } // --------------------------------------------------------------------------- @@ -193,7 +197,7 @@ catch(...) { - panic(XMLPlatformUtils::Panic_CantLoadMsgDomain); + panic(XMLPlatformUtils::Panic_CantLoadMsgDomain); } return retVal; } @@ -210,6 +214,11 @@ return new ICUTransService; } +#elif defined (XML_USE_UNICONV390_TRANSCODER) +{ + + return new Uniconv390TransService; +} #else { return new Iconv390TransService; @@ -245,55 +254,119 @@ // --------------------------------------------------------------------------- -// XMLPlatformUtils: File Methods +// Local Functions // --------------------------------------------------------------------------- -unsigned int XMLPlatformUtils::curFilePos(FileHandle theFile) -{ - // Get the current position - int curPos = ftell( (FILE*)theFile); - if (curPos == -1) - ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotGetSize); +static void emptyBuffer(XMLByte* writeBuffer, + size_t bytesToWrite, + FileHandleImpl* fhiPtr) +{ + FILE* fileHandle = (FILE*)fhiPtr->getHandle(); + size_t bytesThisWrite = 0; + size_t bytesThisPass = 0; + int typeRecordLrecl = 0; + bool isTypeRecord = fhiPtr->isRecordType(); + + if (isTypeRecord) + typeRecordLrecl = fhiPtr->getLrecl(); + + // Try to write as many bytes as possible at a time to the file. + // If less than the total bytes were written then loop as many times + // as necessary until all bytes are written. For the case of + // an MVS dataset with "type=record" specified, we must not + // attempt to write more than one logical record at a time + // or it will fail and not return the number of bytes remaining. + + while (bytesToWrite > 0) + { + if ((isTypeRecord) && + (bytesToWrite > typeRecordLrecl)) + { + bytesThisPass = typeRecordLrecl; - return (unsigned int)curPos; -} + } + else + bytesThisPass = bytesToWrite; -void XMLPlatformUtils::closeFile(FileHandle theFile) -{ - if (fclose((FILE*)theFile)) - ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotCloseFile); + bytesThisWrite = fwrite(writeBuffer, sizeof(XMLByte), bytesThisPass, fileHandle); + + if (ferror(fileHandle)) + ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotWriteToFile); + + bytesToWrite -= bytesThisWrite; + writeBuffer += bytesThisWrite; + } // while (bytesToWrite > 0) + + return; } -unsigned int XMLPlatformUtils::fileSize(FileHandle theFile) + +static FileHandleImpl* openRead(char* tmpFileName) { - // Get the current position - long int curPos = ftell((FILE*)theFile); - if (curPos == -1) - ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotGetCurPos); + FileHandleImpl* retVal; + FILE* fileHandle = 0; + Path390 pathobj; + pathobj.setPath(tmpFileName); + int optionBufferSize = strlen("rb,"); - // Seek to the end and save that value for return - if (fseek( (FILE*)theFile, 0, SEEK_END) ) - ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotSeekToEnd); + // Check if we have fopen options specified in addition to a + // filename. If we do then we need to build a buffer that has + // "rb," followed by the options. Otherwise we just pass "rb" + // in as the options. - long int retVal = ftell( (FILE*)theFile); - if (retVal == -1) - ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotSeekToEnd); + if (pathobj.getfopenParms()) + { + optionBufferSize += (strlen(pathobj.getfopenParms()) + 1); + } + char* optionBuffer = new char[optionBufferSize]; + ArrayJanitor<char> janText((char*)optionBuffer); + strcpy(optionBuffer,"rb"); - // And put the pointer back - if (fseek( (FILE*)theFile, curPos, SEEK_SET) ) - ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotSeekToPos); + // Build the options buffer - return (unsigned int)retVal; -} + if (pathobj.getfopenParms()) + { + strcpy(optionBuffer + 2, ","); + strcpy(optionBuffer + 3, pathobj.getfopenParms()); + } -FileHandle XMLPlatformUtils::openFile(const XMLCh* const fileName) -{ - char* tmpFileName = XMLString::transcode(fileName); - ArrayJanitor<char> janText((char*)tmpFileName); - FileHandle retVal = (FILE*)fopen( tmpFileName , "rb" ); + // If we don't have a valid path specified just exit now + + if (pathobj.getfopenPath() == NULL) + return 0; + + // Take the file handle returned by fopen and create an instance + // of the FileHandleImpl class. + + fileHandle = fopen(pathobj.getfopenPath(), optionBuffer); + retVal = new FileHandleImpl(fileHandle, _FHI_READ, pathobj.isRecordType()); -#ifdef OS390BATCH - if (retVal == NULL) { + // temp fix for HFS files with "type=record" specified + // close the file and re-open it without the fopen options + // since they don't work too well with HFS files. + + if ((pathobj.isRecordType()) && (fileHandle != NULL)) + { + int fldata_rc = 0; + fldata_t fileinfo; + fldata_rc = fldata(fileHandle, pathobj.getfopenPath(), &fileinfo); + + if (fldata_rc) + ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotReadFromFile); + + if (fileinfo.__dsorgHFS) + { + if (fclose(fileHandle)) + ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotCloseFile); + + fileHandle=fopen(pathobj.getfopenPath(), "rb"); + retVal->setHandle(fileHandle); + retVal->setRecordType(_FHI_NOT_TYPE_RECORD); + } + } + // End temp fix ...... + + if ((fileHandle == NULL) && (pathobj.getPathType() == PATH390_OTHER)) { // // We failed to open the file using its native format (OE or MVS) // Try to go an extra step to map the path into a MVS dataset under BATCH: @@ -305,7 +378,7 @@ // path/path2/filename => //path.path2.filename char* datasetName = new char[ strlen(tmpFileName) + 5 ]; - ArrayJanitor<char> janText((char*)datasetName); + ArrayJanitor<char> janText1((char*)datasetName); char *datasetPos = datasetName, *tmpPos = tmpFileName; // We are in EBCDIC mode here @@ -313,7 +386,7 @@ // or a MVS data set strcpy(datasetName, "//"); - *datasetPos += 2; + datasetPos += 2; // If we have a leading '/' then the path is absolute @@ -361,283 +434,405 @@ if( *tmpFileName == '/' ) *datasetPos++ = '\''; *datasetPos = '\0'; - retVal = (FILE*)fopen( datasetName , "rb" ); + fileHandle = fopen( datasetName , optionBuffer); + retVal->setHandle(fileHandle); } -#endif // fix for file:// protocol // the tmpFileName has a prefix of //absolute path // for example, file:////u/.... instead of file:///u/.... // the fopen() on OS/390 cannot open a //u/... POSIX file - if (retVal == NULL) { - if ((tmpFileName[0] == '/') && (tmpFileName[1] == '/')) { - char *srcName = tmpFileName + 1; // points past the first '/' - retVal = (FILE*)fopen( srcName , "rb" ); - } + + if ((fileHandle == NULL) && (pathobj.getPathType() == PATH390_OTHER)) + { + if ((tmpFileName[0] == '/') && (tmpFileName[1] == '/')) + { + char *srcName = tmpFileName + 1; // points past the first '/' + fileHandle = fopen(srcName , optionBuffer); + + retVal->setHandle(fileHandle); + + // temp fix for HFS files with type=record specified + // close the file and re-open it without the fopen options + // since they don't work too well with HFS files. + + if (pathobj.isRecordType()) + { + int fldata_rc = 0; + fldata_t fileinfo; + fldata_rc = fldata(fileHandle, srcName, &fileinfo); + + if (fldata_rc) + ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotReadFromFile); + + if (fileinfo.__dsorgHFS) + { + if (fclose(fileHandle)) + ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotCloseFile); + + fileHandle=fopen(srcName, "rb"); + retVal->setHandle(fileHandle); + retVal->setRecordType(_FHI_NOT_TYPE_RECORD); + } + } + // End temp fix ...... + } + } + + // If the fopen failed we have a pointer to the FileHandleImpl class but + // inside that class a file handle of NULL. In this case we need to delete + // the class and return a NULL to the caller since they should be checking + // for a NULL returned as a file open failed indicator. + + if (fileHandle == NULL) + { + delete retVal; + retVal = 0; } - if( retVal == NULL ) - return 0; return retVal; + } -FileHandle XMLPlatformUtils::openFile(const char* const fileName) + +static FileHandleImpl* openWrite(char* tmpFileName) { - FileHandle retVal = (FILE*)fopen( fileName , "rb" ); + FileHandleImpl* retVal; + FILE* fileHandle = 0; + Path390 pathobj; + pathobj.setPath(tmpFileName); + fldata_t fileinfo; + int fldata_rc = 0; + int optionBufferSize = strlen("wb,"); + int fileLrecl = 0; + bool isTypeRecord = _FHI_NOT_TYPE_RECORD; + + // Check if we have fopen options specified in addition to a + // filename. If we do then we need to build a buffer that has + // "wb," followed by the options. Otherwise we just pass "wb" + // in as the options. + + if (pathobj.getfopenParms()) + optionBufferSize += (strlen(pathobj.getfopenParms()) + 1); + + char* optionBuffer = new char[optionBufferSize]; + ArrayJanitor<char> janText((char*)optionBuffer); + strcpy(optionBuffer,"wb"); -#ifdef OS390BATCH - if (retVal == NULL) { - // - // We failed to open the file using its native format (OE or MVS) - // Try to go an extra step to map the path into a MVS dataset under BATCH: - // - // /path/path2/filename.ext => //'path.path2.ext(filename)' - // /path/path2/filename => //'path.path2.filename' - // and - // path/path2/filename.ext => //path.path2.ext(filename) - // path/path2/filename => //path.path2.filename + // Build the options buffer - char* datasetName = new char[ strlen(fileName) + 5 ]; - ArrayJanitor<char> janText((char*)datasetName); - char *datasetPos = datasetName, *tmpPos = (char *)fileName; + if (pathobj.getfopenParms()) + { + strcpy(optionBuffer + 2, ","); + strcpy(optionBuffer + 3, pathobj.getfopenParms()); + } - // We are in EBCDIC mode here - // Specify "//" to indicate that the filename refers to a non-POSIX file - // or a MVS data set + // FileHandleImpl class. The constructor will allocate our staging + // buffer if it is a "type=record" open. - strcpy(datasetName, "//"); - *datasetPos += 2; + fileHandle = fopen(pathobj.getfopenPath(),optionBuffer); - // If we have a leading '/' then the path is absolute + // If this is a "type=record" open then we need to determine the + // LRECL of the file. The fldata info will have this in it. + // We save this in the FileHandleImpl class for use on subsequent + // writes to the file. - if( *tmpPos == '/' ) { - *datasetPos++ = '\''; - tmpPos++; - } + if (pathobj.isRecordType()) + { + isTypeRecord = _FHI_TYPE_RECORD; + fldata_rc = fldata(fileHandle, pathobj.getfopenPath(), &fileinfo); - // Find the last '/' in the path - this seperates the path from the - // filename. Then copy the pathname. + if (fldata_rc) + ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotWriteToFile); - char* pathEnd = strrchr((char*) tmpPos, '/' ); - if( pathEnd == NULL ) pathEnd = tmpPos - 1; - while( tmpPos <= pathEnd ) { - switch( *tmpPos ) { - case '/': - *datasetPos = '.'; - break; - default: - *datasetPos = *tmpPos; - } - datasetPos++; tmpPos++; - } + fileLrecl = fileinfo.__maxreclen; - // Now we try to locate the extension, and copy that. + // temp fix for HFS files + // close the file and re-open it without the fopen options + // since they don't work too well with HFS files. - char* extStart = strrchr((char*) fileName, '.' ); - if ( extStart != NULL ) { - tmpPos = extStart + 1; - while( *tmpPos != '\0' ) { - *datasetPos++ = *tmpPos++; - } - *datasetPos++ = '('; - } + if (fileinfo.__dsorgHFS) + { + if (fclose(fileHandle)) + ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotCloseFile); - // Now we copy in the filename. + fileHandle=fopen(pathobj.getfopenPath(), "wb"); + + } + // end temp fix - tmpPos = pathEnd + 1; - while( *tmpPos != '\0' && ((extStart == NULL) || (tmpPos < extStart)) ) { - *datasetPos++ = *tmpPos++; } - // Finally cap off the filename with optional ")" and "'", plus a null - if( extStart != NULL ) *datasetPos++ = ')'; - if( *fileName == '/' ) *datasetPos++ = '\''; - *datasetPos = '\0'; + // If the fopen failed we won't need to create an instance of the + // FileHandleImpl class .... just return a NULL wich the caller recognizes + // as a failure. If we have a valid file handle then we'll build create + // an instance of the class and return that to the caller. - retVal = (FILE*)fopen( datasetName , "rb" ); + if (fileHandle == NULL) + retVal = 0; + else + retVal = new FileHandleImpl(fileHandle, _FHI_WRITE, isTypeRecord,fileLrecl); - } -#endif + return retVal; +} - // fix for file:// protocol - // the fileName has a prefix of //absolute path - // for example, file:////u/.... instead of file:///u/.... - // the fopen() on OS/390 cannot open a //u/... POSIX file - if (retVal == NULL) { - if ((fileName[0] == '/') && (fileName[1] == '/')) { - const char *srcName = fileName + 1; // points past the first '/' - retVal = (FILE*)fopen( srcName , "rb" ); - } + +// --------------------------------------------------------------------------- +// XMLPlatformUtils: File Methods +// --------------------------------------------------------------------------- +unsigned int XMLPlatformUtils::curFilePos(FileHandle theFile) +{ + // Get the current position + FileHandleImpl* fhiPtr = (FileHandleImpl*) theFile; + FILE* fileHandle = (FILE*)fhiPtr->getHandle(); + int curPos = ftell(fileHandle); + + if (curPos == -1) + ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotGetSize); + + return (unsigned int)curPos; +} + +void XMLPlatformUtils::closeFile(FileHandle theFile) +{ + FileHandleImpl* fhiPtr = (FileHandleImpl*) theFile; + FILE* fileHandle = (FILE*)fhiPtr->getHandle(); + + // We need to handle a close differently if this was a + // "type=record" open. In that case we may have data sitting in + // the staging buffer that is waiting to be written to the file. + // In this case write that data to the file before we actually + // close it. + + if ( (fhiPtr->getOpenType() == _FHI_WRITE) && + (fhiPtr->isRecordType()) && + (fhiPtr->getNextByte()) ) + { + XMLByte* tmpFlush = fhiPtr->getStgBufferPtr(); + size_t bytesToWrite = fhiPtr->getNextByte(); + emptyBuffer(tmpFlush, bytesToWrite,fhiPtr); } - if( retVal == NULL ) - return 0; - return retVal; + // Do the regular close stuff .... + + if (fclose(fileHandle)) + ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotCloseFile); + + // Delete the instance of the FileHandleImpl class (this will free the + // staging buffer for us) + + delete fhiPtr; + } -FileHandle XMLPlatformUtils::openFileToWrite(const XMLCh* const fileName) +unsigned int XMLPlatformUtils::fileSize(FileHandle theFile) { - const char* tmpFileName = XMLString::transcode(fileName); - ArrayJanitor<char> janText((char*)tmpFileName); - char* semicolon; - char* optStart; - int optOffset = 0; - int dsnSize = 0; - int optSize = 0; - - // Check if this is an MVS dataset. If it is we need to allow - // DCB options to be passed in the URI we get. The options - // will be after the ";" in the URI in this case. - if ((tmpFileName[0] == '/') && (tmpFileName[1] == '/')) - { - semicolon = strrchr((char*)tmpFileName,';'); - if (semicolon == NULL) - dsnSize = strlen(tmpFileName); - else - { - dsnSize = semicolon - tmpFileName; - optStart = semicolon; - optStart++; - optOffset = optStart - tmpFileName; - optSize = (strlen(tmpFileName) - optOffset); - } + // Get the current position + FileHandleImpl* fhiPtr = (FileHandleImpl*) theFile; + FILE* fileHandle = (FILE*)fhiPtr->getHandle(); + long int curPos = ftell(fileHandle); - // Make a copy of the dataset name to pass to fopen - char* dsnbuf = new char[dsnSize + 1]; - ArrayJanitor<char> janText1((char*)dsnbuf); - strncpy(dsnbuf, tmpFileName, dsnSize); - - // If no options specified, then we just put a "wb" in there. - // Otherwise we put a "wb" followed by a comma followed by - // the options string. - if (optSize == 0) - optSize += 3; - else - optSize += 4; + if (curPos == -1) + ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotGetCurPos); - // Save the options for fopen - char* optbuf = new char[optSize]; - ArrayJanitor<char> janText2((char*)optbuf); - strcpy(optbuf, "wb"); + // Seek to the end and save that value for return + if (fseek(fileHandle, 0, SEEK_END)) + ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotSeekToEnd); - if (optSize != 3) - { - strcpy(optbuf + 2, ","); - strncpy(optbuf +3, optStart, optSize); - } + long int retVal = ftell(fileHandle); - return fopen(dsnbuf, optbuf); + if (retVal == -1) + ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotSeekToEnd); - } - else - return fopen(tmpFileName, "wb"); + // And put the pointer back + if (fseek(fileHandle, curPos, SEEK_SET) ) + ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotSeekToPos); + + return (unsigned int)retVal; } -FileHandle XMLPlatformUtils::openFileToWrite(const char* const fileName) +FileHandle XMLPlatformUtils::openFile(const XMLCh* const fileName) { - char* semicolon; - char* optStart; - int optOffset = 0; - int dsnSize = 0; - int optSize = 0; - - // Check if this is an MVS dataset. If it is we need to allow - // DCB options to be passed in the URI we get. The options - // will be after the ";" in the URI in this case. - if ((fileName[0] == '/') && (fileName[1] == '/')) - { - semicolon = strrchr((char*)fileName,';'); - if (semicolon == NULL) - dsnSize = strlen(fileName); - else - { - dsnSize = semicolon - fileName; - optStart = semicolon; - optStart++; - optOffset = optStart - fileName; - optSize = (strlen(fileName) - optOffset); - } + char* tmpFileName = XMLString::transcode(fileName); + ArrayJanitor<char> janText((char*)tmpFileName); - // Make a copy of the dataset name to pass to fopen - char* dsnbuf = new char[dsnSize + 1]; - ArrayJanitor<char> janText1((char*)dsnbuf); - strncpy(dsnbuf, fileName, dsnSize); - - // If no options specified, then we just put a "wb" in there. - // Otherwise we put a "wb" followed by a comma followed by - // the options string. - if (optSize == 0) - optSize += 3; - else - optSize += 4; + return openRead(tmpFileName); +} - // Save the options for fopen - char* optbuf = new char[optSize]; - ArrayJanitor<char> janText2((char*)optbuf); - strcpy(optbuf, "wb"); - if (optSize != 3) - { - strcpy(optbuf + 2, ","); - strncpy(optbuf +3, optStart, optSize); - } +FileHandle XMLPlatformUtils::openFile(const char* const fileName) +{ + char* tmpFileName = new char[strlen(fileName) + 1]; + ArrayJanitor<char> janText((char*)tmpFileName); + strcpy(tmpFileName,fileName); - return fopen(dsnbuf, optbuf); + return openRead(tmpFileName); +} - } - else - return fopen(fileName, "wb"); +FileHandle XMLPlatformUtils::openFileToWrite(const XMLCh* const fileName) +{ + char* tmpFileName = XMLString::transcode(fileName); + ArrayJanitor<char> janText((char*)tmpFileName); + + return openWrite(tmpFileName); } + +FileHandle XMLPlatformUtils::openFileToWrite(const char* const fileName) +{ + char* tmpFileName = new char[strlen(fileName) + 1]; + ArrayJanitor<char> janText((char*)tmpFileName); + strcpy(tmpFileName,fileName); + + return openWrite(tmpFileName); +} + + void XMLPlatformUtils::writeBufferToFile( FileHandle const theFile , long toWrite , const XMLByte* const toFlush) { - if (!theFile || + FileHandleImpl* fhiPtr = (FileHandleImpl*) theFile; + FILE* fileHandle = (FILE*)fhiPtr->getHandle(); + + if (!fileHandle || (toWrite <= 0 ) || - !toFlush ) + !toFlush ) return; - const XMLByte* tmpFlush = (const XMLByte*) toFlush; - size_t bytesWritten = 0; + XMLByte* tmpFlush = (XMLByte*) toFlush; - while (true) + // For writes where the file has been opened with the "type=record" + // option we must do a lot of extra work. In this case we have + // a staging buffer that we copy data to and only write it out + // when we find a newline or line feed in the buffer. + + if (fhiPtr->isRecordType()) { - bytesWritten=fwrite(tmpFlush, sizeof(XMLByte), toWrite, (FILE*)theFile); + XMLByte* inputBufferPtr = tmpFlush; + XMLByte* stageBufferStartPtr = fhiPtr->getStgBufferPtr(); + int stageBufferNextByte = fhiPtr->getNextByte(); + XMLByte* stageBufferAddPtr = stageBufferStartPtr + stageBufferNextByte; + int stageThisAdd = 0; + int stageTotalAdded = 0; + int stageToWrite = 0; + int fileLrecl = fhiPtr->getLrecl(); + + // Check each byte passed into us. If it is a new line or + // line feed we copy up to and including that byte to the + // staging buffer starting at the next available byte. We + // then write the valid contents of the staging buffer to + // the file and then continue going thru the input data + // since a newline is not the end of the input. + // Also we want to copy the data to the staging buffer and + // write it to disk as soon as the staging buffer contains + // a logical record's worth of data. - if(ferror((FILE*)theFile)) - { - ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotWriteToFile); - } + for(int i = 0; i < toWrite; i++) + { + if ( (tmpFlush[i] == '\n') || + (tmpFlush[i] == 0x25) || + ((stageBufferNextByte + (i + 1)) - stageTotalAdded == fileLrecl) ) + { + stageThisAdd = (i + 1) - stageTotalAdded; + memcpy((void*) stageBufferAddPtr, (void*) inputBufferPtr, stageThisAdd); + stageTotalAdded += stageThisAdd; + inputBufferPtr += stageThisAdd; + stageBufferAddPtr += stageThisAdd; + stageToWrite = stageBufferAddPtr - stageBufferStartPtr; + emptyBuffer(stageBufferStartPtr, stageToWrite, fhiPtr); + stageBufferAddPtr = stageBufferStartPtr; + stageBufferNextByte = 0; + } + } // for loop + + + // When we finish looping thru the input buffer we may have data + // left in it that was not copied to the staging buffer yet. Copy + // whatever is left in the input buffer to the staging buffer now + // and update the staging buffer next byte offset. + + if (stageTotalAdded < toWrite) + { + stageThisAdd = toWrite - stageTotalAdded; + memcpy((void*) stageBufferAddPtr, (void*) inputBufferPtr, stageThisAdd); + stageBufferNextByte += stageThisAdd; + } - if (bytesWritten < toWrite) //incomplete write - { - tmpFlush+=bytesWritten; - toWrite-=bytesWritten; - bytesWritten=0; - } - else - return; + fhiPtr->setNextByte(stageBufferNextByte); } - return; + // Normal type of write, just write data to disk ... + + else + emptyBuffer(tmpFlush, toWrite, fhiPtr); + + return; } + unsigned int XMLPlatformUtils::readFileBuffer( FileHandle theFile , const unsigned int toRead , XMLByte* const toFill) { - size_t noOfItemsRead = fread( (void*) toFill, 1, toRead, (FILE*)theFile); + FileHandleImpl* fhiPtr = (FileHandleImpl*) theFile; + FILE* fileHandle = (FILE*)fhiPtr->getHandle(); + size_t noOfItemsRead = 0; + bool isTypeRecord = fhiPtr->isRecordType(); + + // On a read, if this was a "type=record" open then we do not want + // to return any terminating NULLS that fill out a logical + // record. We also will discard a record that is all NULLS. - if(ferror((FILE*)theFile)) + while (true) { - ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotReadFromFile); - } + noOfItemsRead = fread( (void*) toFill, 1, toRead, fileHandle); + + if(ferror(fileHandle)) + ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotReadFromFile); + + if (isTypeRecord) + { + if (noOfItemsRead == 0) + break; + + // Go thru the data we read and strip off trailing NULLS + // until a non-NULL is encountered. If a record is all + // NULLS then we discard it. + + bool recordIsValid = false; + + for (int i = noOfItemsRead; i > 0; i--) + { + if (toFill[i - 1]) + { + recordIsValid = true; + break; + } + else + noOfItemsRead--; + } + + // If we didn't hit a non-NULL we need will go read another + // record in hopes of returning some valid data. + + if (recordIsValid) + break; + else + { + noOfItemsRead = 0; + break; + } + } // isTypeRecord + // for a "non-type=record" read we do only one read + else + break; + } // while (true) return (unsigned int)noOfItemsRead; } @@ -646,11 +841,12 @@ void XMLPlatformUtils::resetFile(FileHandle theFile) { // Seek to the start of the file - if (fseek((FILE*)theFile, 0, SEEK_SET) ) - ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotResetFile); + FileHandleImpl* fhiPtr = (FileHandleImpl*) theFile; + FILE* fileHandle = (FILE*)fhiPtr->getHandle(); + if (fseek(fileHandle, 0, SEEK_SET) ) + ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotResetFile); } - // --------------------------------------------------------------------------- // XMLPlatformUtils: File system methods // --------------------------------------------------------------------------- @@ -665,22 +861,23 @@ char* newSrc = XMLString::transcode(srcPath); ArrayJanitor<char> janText(newSrc); - if ( (newSrc != NULL) && (newSrc[0] != NULL) && (newSrc[1] != NULL) && //@DEM - (newSrc[0] == '/') && (newSrc[1] == '/') ) //@DEM - return XMLString::transcode(newSrc); //@DEM + Path390 pathobj; + pathobj.setPath(newSrc); + char* retPath = 0; // Use a local buffer that is big enough for the largest legal path char *absPath = new char[_POSIX_PATH_MAX]; ArrayJanitor<char> janText2(absPath); - //get the absolute path - char* retPath = realpath(newSrc, absPath); - - if (!retPath) - { - ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotGetBasePathName); + if ( (pathobj.getPathType() == PATH390_HFS) || (pathobj.getPathType() == PATH390_OTHER) ) { + //get the absolute path + char* retPath = realpath(pathobj.getfopenPath(), absPath); + if (!retPath) { + ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotGetBasePathName); + } + return XMLString::transcode(absPath); } - return XMLString::transcode(absPath); + return XMLString::transcode(newSrc); } bool XMLPlatformUtils::isRelative(const XMLCh* const toCheck) @@ -700,7 +897,6 @@ if (toCheck[0] == 0x2F) return false; -#ifdef OS390BATCH // // Determine whether we are using the DD convention // 'D': 0x44 'd': 0x64 ':': 0x3A @@ -710,13 +906,22 @@ ((toCheck[0] == (0x44)) || (toCheck[0] == (0x64))) && ((toCheck[1] == (0x44)) || (toCheck[1] == (0x64))) && (toCheck[2] == XMLCh(0x3A)) - ) - return false; + ) + return false; } -#endif - // Else assume its a relative path - return true; + char* tmpFileName = XMLString::transcode(toCheck); + ArrayJanitor<char> janText((char*)tmpFileName); + Path390 pathobj; + pathobj.setPath(tmpFileName); + + // let Path390 do the final determination + return pathobj.isRelative(); + + + + + } XMLCh* XMLPlatformUtils::weavePaths @@ -807,7 +1012,7 @@ // The base cannot provide enough levels, so its in error/ if (basePtr < basePath) - ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_BasePathUnderflow); + ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_BasePathUnderflow); } } @@ -837,6 +1042,7 @@ } + // ----------------------------------------------------------------------- // Mutex methods // OS390BATCH: Unless POSIX(ON) is specified, pthread functions are @@ -848,57 +1054,47 @@ { if (mtxHandle == NULL) return; -#ifdef OS390BATCH if (isPosixEnabled) { -#endif if (pthread_mutex_destroy( (pthread_mutex_t*)mtxHandle)) { - ThrowXML(XMLPlatformUtilsException, XMLExcepts::Mutex_CouldNotDestroy); + ThrowXML(XMLPlatformUtilsException, XMLExcepts::Mutex_CouldNotDestroy); } if ( (pthread_mutex_t*)mtxHandle) delete mtxHandle; -#ifdef OS390BATCH } // __isPosixOn else { if ( (int*)mtxHandle) delete mtxHandle; } -#endif } void XMLPlatformUtils::lockMutex(void* const mtxHandle) { if (mtxHandle == NULL) return; -#ifdef OS390BATCH if (isPosixEnabled) { -#endif if (pthread_mutex_lock( (pthread_mutex_t*)mtxHandle)) { - ThrowXML(XMLPlatformUtilsException, XMLExcepts::Mutex_CouldNotLock); + ThrowXML(XMLPlatformUtilsException, XMLExcepts::Mutex_CouldNotLock); } -#ifdef OS390BATCH } // __isPosixOn else { - int locked = 1, unlocked; + int locked = 1, unlocked; do { unlocked = 0; compareAndSwap( (void**) &mtxHandle, (void*) locked, (void*) unlocked ); } while( unlocked != 0 ); } -#endif return; } void* XMLPlatformUtils::makeMutex() { -#ifdef OS390BATCH if (isPosixEnabled) { -#endif pthread_mutex_t* mutex = new pthread_mutex_t; if (mutex == NULL) { - ThrowXML(XMLPlatformUtilsException, XMLExcepts::Mutex_CouldNotCreate); + ThrowXML(XMLPlatformUtilsException, XMLExcepts::Mutex_CouldNotCreate); } pthread_mutexattr_t* attr = new pthread_mutexattr_t; @@ -914,33 +1110,27 @@ return (void*)(mutex); -#ifdef OS390BATCH } // __isPosixOn else { - int* mutex = new int; - *mutex = 0; - return (void*)(mutex); + int* mutex = new int; + *mutex = 0; + return (void*)(mutex); } -#endif } void XMLPlatformUtils::unlockMutex(void* const mtxHandle) { if (mtxHandle == NULL) return; -#ifdef OS390BATCH if (isPosixEnabled) { -#endif if (pthread_mutex_unlock( (pthread_mutex_t*)mtxHandle)) { - ThrowXML(XMLPlatformUtilsException, XMLExcepts::Mutex_CouldNotUnlock); + ThrowXML(XMLPlatformUtilsException, XMLExcepts::Mutex_CouldNotUnlock); } -#ifdef OS390BATCH } // __isPosixOn else { - if (*(int*) mtxHandle == 0 ) - *(int*) mtxHandle = 0; + if (*(int*) mtxHandle == 0 ) + *(int*) mtxHandle = 0; } -#endif } #else // #ifndef APP_NO_THREADS @@ -964,6 +1154,7 @@ #endif // APP_NO_THREADS + // ----------------------------------------------------------------------- // Miscellaneous synchronization methods // ----------------------------------------------------------------------- @@ -1001,7 +1192,16 @@ FileHandle XMLPlatformUtils::openStdInHandle() { - return (FileHandle)fdopen(dup(0), "rb"); + FileHandleImpl* retVal; + FILE* fileHandle = 0; + fileHandle = fdopen(dup(0), "rb"); + if (fileHandle) + retVal = new FileHandleImpl(fileHandle, _FHI_READ, _FHI_NOT_TYPE_RECORD); + else + retVal = 0; + + return retVal; + } void XMLPlatformUtils::platformTerm() 1.1 xml-xerces/c/src/xercesc/util/Platforms/OS390/FileHandleImpl.cpp Index: FileHandleImpl.cpp =================================================================== /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Xerces" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact apache\@apache.org. * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation, and was * originally based on software copyright (c) 1999, International * Business Machines, Inc., http://www.ibm.com . For more information * on the Apache Software Foundation, please see * <http://www.apache.org/>. */ /* * $Id: FileHandleImpl.cpp,v 1.1 2002/11/22 14:57:32 tng Exp $ */ #include <fstream.h> #include <stdio.h> #include <ctype.h> #include <typeinfo> #define _XOPEN_SOURCE_EXTENDED 1 #include <stdlib.h> #include <xercesc/util/XMLUniDefs.hpp> #include "FileHandleImpl.hpp" XERCES_CPP_NAMESPACE_BEGIN //Constructor: FileHandleImpl::FileHandleImpl(FILE* open_handle, int o_type, bool r_type, int fileLrecl): Handle(open_handle), openType(o_type), recordType(r_type), lrecl(fileLrecl) { stgBufferPtr = 0; nextByte = 0; if ((openType == _FHI_WRITE) && (recordType == _FHI_TYPE_RECORD) && (lrecl != 0)) { stgBufferPtr = new XMLByte [lrecl]; } // printf("FileHandleImpl constructor called\n"); // printf("stgBufferPtr is: x%8.8X\n", stgBufferPtr); // printf("Handle is: x%8.8X\n", Handle); // printf("openType is : %d\n",openType); // printf("recordType is : %d\n",recordType); // printf("lrecl is : %d\n",lrecl); } //Destructor: FileHandleImpl::~FileHandleImpl() { // printf("FileHandleImpl destructor called\n"); // printf("stgBufferPtr is: x%8.8X\n", stgBufferPtr); // printf("Handle is: x%8.8X\n", Handle); // printf("openType is : %d\n",openType); // printf("recordType is : %d\n",recordType); if (stgBufferPtr != 0) { // printf("stgBufferPtr is being freed at: x%8.8X\n", stgBufferPtr); delete [] stgBufferPtr; } } XERCES_CPP_NAMESPACE_END 1.1 xml-xerces/c/src/xercesc/util/Platforms/OS390/FileHandleImpl.hpp Index: FileHandleImpl.hpp =================================================================== /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Xerces" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact apache\@apache.org. * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation, and was * originally based on software copyright (c) 1999, International * Business Machines, Inc., http://www.ibm.com . For more information * on the Apache Software Foundation, please see * <http://www.apache.org/>. */ /* * $Id: FileHandleImpl.hpp,v 1.1 2002/11/22 14:57:32 tng Exp $ */ #ifndef FILEHANDLEIMPL_HPP #define FILEHANDLEIMPL_HPP #include <xercesc/util/XercesDefs.hpp> XERCES_CPP_NAMESPACE_BEGIN class FileHandleImpl { private: FILE* Handle; // handle from fopen XMLByte* stgBufferPtr; // address of staging buffer int nextByte; // NAB in staging buffer int openType; // 0=write, 1=read int lrecl; // LRECL if openType is write bool recordType; // true if "type=record" public: FileHandleImpl(FILE* open_handle, int o_type, bool r_type, int fileLrecl=0); ~FileHandleImpl(); void setHandle(FILE* newHandlePtr) { Handle = newHandlePtr; } void* getHandle() { return Handle; } XMLByte* getStgBufferPtr() { return stgBufferPtr; } int getNextByte() { return nextByte; } void setNextByte(int newNextByte) { nextByte = newNextByte; } int getOpenType() { return openType; } bool isRecordType() { return recordType; } void setRecordType(bool newType) { recordType = newType; } int getLrecl() { return lrecl; } void setLrecl(int newLrecl) { lrecl = newLrecl; } }; // Constants for the openType member #define _FHI_WRITE 0 #define _FHI_READ 1 // Constant for the typeRecord member #define _FHI_NOT_TYPE_RECORD 0 #define _FHI_TYPE_RECORD 1 XERCES_CPP_NAMESPACE_END #endif 1.1 xml-xerces/c/src/xercesc/util/Platforms/OS390/Path390.cpp Index: Path390.cpp =================================================================== /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Xerces" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact apache\@apache.org. * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation, and was * originally based on software copyright (c) 1999, International * Business Machines, Inc., http://www.ibm.com . For more information * on the Apache Software Foundation, please see * <http://www.apache.org/>. */ /* * $Id: Path390.cpp,v 1.1 2002/11/22 14:57:32 tng Exp $ */ //#include "stdafx.h" #include <fstream.h> #include <stdio.h> #include <ctype.h> #include <typeinfo> #define _XOPEN_SOURCE_EXTENDED 1 #include <stdlib.h> #include <string.h> #include "Path390.hpp" XERCES_CPP_NAMESPACE_BEGIN //Constructors: Path390::Path390() { _error = 0; _absolute = false; _dsnabsolute = false; _parsestate=PARSE_NONE; _orgparms=0; _resultpath=0; _orgpath=0; } Path390::Path390(char * s) { _error = 0; _absolute = false; _dsnabsolute = false; _parsestate=PARSE_NONE; _orgparms=0; _resultpath=0; _orgpath=0; setPath(s); } //Destructor: Path390::~Path390() { if (_orgparms) free (_orgparms); if (_resultpath) free(_resultpath); if (_orgpath) free(_orgpath); } // This path parser is state driven in order to support an incremental parse of the input path. // This is so that, for example, someone only wants to determine whether the path is absolute or // relative, then it will only parse sufficient information to determine this. This information // is saved in the object so that this does not need to be re-parsed if later one wanted to // retrieve, for example, the parameters. // The states are: // PARSE_NONE - initial state, nothing is parsed. // PARSE_ABSOLUTE_URI - Absolute or relative path has been determined. // PARSE_PATHTYPE - The type of the path has been determined // PARSE_PUNCT - The important delimiters have been located to make later parsing simpler. // PARSE_PARMS - The parms have been located and retrieved. // PARSE_PARSED - The path has been fully parsed. // // Each of the following methods handle the parsing corresponding to each state. // // Determine if the path is absolute or relative. void Path390::_determine_uri_abs() { if (_parsestate == PARSE_NONE) { if (*_curpos == '/') { _uriabsolute=true; _curpos++; } else _uriabsolute=false; _parsestate = PARSE_ABSOLUTE_URI; } } // Determine the path type. This could be: // PATH390_HFS - format is hfs:/xxx/xxx... // PATH390_DSN1 - format is dsn:/xxx/xxx... // PATH390_DSN2 - format is dsn://xxxxx... // PATH390_DD - format is dd:xxx... // PATH390_OTHER - format is any other paths. void Path390::_determine_type() { char firstfour[5]; if (_parsestate == PARSE_ABSOLUTE_URI) { char * ff=firstfour; int ffi=0; while ((_curpos[ffi]) && (ffi<4)) {ff[ffi] = toupper(_curpos[ffi]); ffi++;} if ( (ffi>=4) && !strncmp(firstfour,"DSN:",4) ) { _pathtype = PATH390_DSN1; _curpos+=4; _absolute = true; if ( ((*_curpos) && (*_curpos == '/')) && ((*(_curpos+1)) && (*(_curpos+1) == '/')) ) { _pathtype = PATH390_DSN2; } } else if ( (ffi>=4) && !strncmp(firstfour,"HFS:",4) ) { _pathtype = PATH390_HFS; _curpos+=4; if (*_curpos == '/') _absolute = true; else _absolute = false; } else if ( (ffi>=3) && !strncmp(firstfour,"DD:",3) ) { _absolute = true; _pathtype = PATH390_DD; _curpos+=3; } else { _pathtype = PATH390_OTHER; if (_uriabsolute) _curpos--; } _parsestate = PARSE_PATHTYPE; } } // This takes one pass through the path any determines the location of important delimiters // including / ; . and ( // It will also detect some error conditions void Path390::_determine_punct() { if (_parsestate == PARSE_PATHTYPE) { char * source = _curpos; _lastsemi = 0; _lastslash = 0; _lastparen = 0; _parmStart = 0; _pathEnd = 0; _numperiods = 0; _numsemicolons = 0; _extStart = 0; while (*source) { switch (*source) { case ';': _lastsemi = source; _parmStart = source+1; _numsemicolons++; break; case '/': _lastslash = source; _pathEnd = source; break; case '.': _extStart = source+1; _numperiods++; break; case '(': _lastparen = source+1; break; } *source++; } if ( (_parmStart) && (_parmStart<=_pathEnd) ) { _error = ERROR_SEMICOLON_NOT_ALLOWED; _lastsemi = 0; _parmStart = 0; } if ( ((_pathtype == PATH390_DD) || (_pathtype == PATH390_DSN1) || (_pathtype == PATH390_DSN1)) && (_extStart <= _pathEnd) ) { if (_extStart) _error = ERROR_PERIOD_NOT_ALLOWED; _extStart = 0; } if (_extStart < _lastparen) _extStart = 0; _parsestate = PARSE_PUNCT; } } // This extracts the parameters from the path if there are any. It also determines if the parameters // contain type=record void Path390::_determine_parms() { if (_parsestate == PARSE_PUNCT) { char * tr = 0; if (_parmStart) { _orgparmlen = strlen(_parmStart)+1; _orgparms = (char *) malloc(_orgparmlen); char * ts=_parmStart; char * td=_orgparms; while (*ts) *td++ = tolower(*ts++); *td = 0; *_lastsemi = 0; tr = strstr(_orgparms,"type=record"); } if (tr) _typerecord = tr - _orgparms; else _typerecord = -1; _parsestate = PARSE_PARMS; } } // Complete the rest of the parse. void Path390::_parse_rest() { if (_parsestate == PARSE_PARMS) { char *source; char *dest; char * filename_start; char * tmpPos; int pathlen = strlen(_curpos); _resultpath = (char *) malloc(pathlen+10); source = _curpos; dest = _resultpath; switch (_pathtype) { case PATH390_DSN1: // This format needs to be mangled from a hierarchical (hfs style) path to the // traditional MVS format. First check for some errors. if (_lastparen) { _error = ERROR_NO_PAREN_ALLOWED; break; } if ((_uriabsolute) && (!_absolute)) { _error = ERROR_ABS_PATH_REQUIRED; break; } if ( ((_extStart) && (_numperiods > 1)) || ((!_extStart) && (_numperiods)) ) { _error = ERROR_NO_EXTRA_PERIODS_ALLOWED; break; } if ( ((_parmStart) && (_numsemicolons > 1)) || ((!_parmStart) && (_numsemicolons)) ) { _error = ERROR_NO_EXTRA_SEMIS_ALLOWED; break; } // start out the result with // *dest++ = '/'; *dest++ = '/'; // If the input path starts with a / then it is absolute and it must be // enclosed in 's _dsnabsolute = false; if (*source == '/') { _dsnabsolute = true; source++; } else if (_uriabsolute) { _error = ERROR_MUST_BE_ABSOLUTE; break; } char * pathstart; pathstart = source; // Add in the ' if this is an absolute path' if (_dsnabsolute) *dest++ = '\''; // If there is a / in the path.... tmpPos = source; if (_pathEnd > source) { // copy everything up to the last /, replacing / with . while( source < _pathEnd ) { switch( *source ) { case '/': *dest = '.'; break; default: *dest = *source; } dest++; source++; } // bump past the last / source++; } // Now we try to locate the extension, and copy that. filename_start = 0; if ( _extStart != NULL ) { tmpPos = _extStart; if ( (*tmpPos != '\0') && (*tmpPos != ';') && (source != pathstart) ) *dest++='.'; while ( (*tmpPos != '\0') && (*tmpPos != ';') ) { *dest++ = *tmpPos++; } // if there is a filename, add a ( if (source < (_extStart-1)) { filename_start = tmpPos; *dest++ = '('; } } else if (source != pathstart) *dest++ = '.'; // Now we copy in the filename. tmpPos = source; while( ((*tmpPos != '\0') && (*tmpPos != ';')) && ((_extStart == NULL) || (tmpPos < (_extStart-1))) ) { *dest++ = *tmpPos++; } // Finally cap off the filename with optional ")" if ( (_extStart != NULL) && (filename_start) ) *dest++ = ')'; // Add on the ending ' if necessary. if (_dsnabsolute) *dest++ = '\''; // make it a null terminated string. *dest = '\0'; break; case PATH390_HFS: // it is in hfs: format. If it is relative, then add on a ./ otherwise // just copy the string. if (!_absolute) { if (_uriabsolute) { _error = ERROR_MUST_BE_ABSOLUTE; break; } *dest++='.'; *dest++='/'; } strcpy(dest,source); break; case PATH390_DD: // It's in dd: format. This is similar to the dsn: format, just shorter. // Start it out with dd: *dest++='D'; *dest++='D'; *dest++=':'; tmpPos = source; // if there is a / present in the path... if (_pathEnd > source) { // copy everything up to the last /, replacing / with . while( source < _pathEnd ) { switch( *source ) { case '/': *dest = '.'; break; default: *dest = *source; } dest++; source++; } // bump past the last / source++; } // Now we try to locate the extension, and copy that. filename_start = 0; if ( _extStart != NULL ) { tmpPos = _extStart; if ( (*tmpPos != '\0') && (*tmpPos != ';') && (source != _curpos) ) *dest++='.'; while ( (*tmpPos != '\0') && (*tmpPos != ';') ) { *dest++ = *tmpPos++; } // if there is a filename, add a ( if (source < (_extStart-1)) { filename_start = tmpPos; *dest++ = '('; } } else if (source != _curpos) *dest++ = '.'; // Now we copy in the filename. tmpPos = source; while( ((*tmpPos != '\0') && (*tmpPos != ';')) && ((_extStart == NULL) || (tmpPos < (_extStart-1))) ) { *dest++ = *tmpPos++; } // Finally cap off the filename with optional ")" if ( (_extStart != NULL) && (filename_start) ) *dest++ = ')'; *dest = '\0'; break; case PATH390_DSN2: // This is in dsn: format with the traditional MVS dataset name. Just fall into // the default case to copy the path to the destination after making sure that // there are no extra slashes. { int lastslash=5; if (_uriabsolute) lastslash=6; if ( (_lastslash) && ((_lastslash-_orgpath)>lastslash) ) { _error = ERROR_BAD_DSN2; break; } } default: // for all other cases simply copy over the string. strcpy(dest,source); break; } _parsestate = PARSE_PARSED; } } // Public methods start here: // This sets a new path into the object. Re-initialize everything and do an initial // parse. void Path390::setPath(char * s) { if (_orgparms) free (_orgparms); if (_resultpath) free(_resultpath); if (_orgpath) free(_orgpath); _error = 0; _absolute = false; _dsnabsolute = false; _orglen = strlen(s); _orgpath = (char *) malloc(_orglen+1); strcpy(_orgpath,s); _curpos = _orgpath; _parsestate=PARSE_NONE; // Do an initial parse... _determine_uri_abs(); _determine_type(); } // Do the parse to completion and return any errors found. int Path390::fullParse() { // Do an initial parse... _determine_uri_abs(); _determine_type(); _determine_punct(); if (_error) { // printf("found error-%d\n",_error); return _error; } _determine_parms(); _parse_rest(); return _error; } // Get the path in a format which is required by fopen. First make sure that the path is // completely parsed char * Path390::getfopenPath() { _determine_uri_abs(); _determine_type(); _determine_punct(); if (_error) { // printf("found error-%d\n",_error); return 0; } _determine_parms(); _parse_rest(); if (_error) { // printf("found error-%d\n",_error); return 0; } if (_resultpath[0]) return _resultpath; else return 0; } // Get the parms in a format which is required by fopen. First make sure that the path is // completely parsed char * Path390::getfopenParms() { _determine_uri_abs(); _determine_type(); _determine_punct(); if (_error) { // printf("found error-%d\n",_error); return 0; } _determine_parms(); _parse_rest(); if (_error) { // printf("found error-%d\n",_error); return 0; } if ( (_orgparms) && (_orgparms[0]) ) return _orgparms; else return 0; } // return whether there is type=record parameter in the parameter list. bool Path390::isRecordType() { _determine_uri_abs(); _determine_type(); _determine_punct(); if (_error) { // printf("found error-%d\n",_error); return false; } _determine_parms(); _parse_rest(); if (_error) { // printf("found error-%d\n",_error); return false; } if ( (_orgparms) && (_typerecord>=0) ) return true; else return false; } // This returns the path type int Path390::getPathType() { _determine_uri_abs(); _determine_type(); return _pathtype; } // This returns the error code which was found when the path was parsed int Path390::getError() { _determine_uri_abs(); _determine_type(); _determine_punct(); if (_error) { // return _error; } _determine_parms(); _parse_rest(); if (_error) { // return _error; } return _error; } // returns whether the path is relative or absolute. bool Path390::isRelative() { _determine_uri_abs(); _determine_type(); return !(_absolute|_uriabsolute); } XERCES_CPP_NAMESPACE_END 1.1 xml-xerces/c/src/xercesc/util/Platforms/OS390/Path390.hpp Index: Path390.hpp =================================================================== /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Xerces" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact apache\@apache.org. * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation, and was * originally based on software copyright (c) 1999, International * Business Machines, Inc., http://www.ibm.com . For more information * on the Apache Software Foundation, please see * <http://www.apache.org/>. */ /* * $Id: Path390.hpp,v 1.1 2002/11/22 14:57:32 tng Exp $ */ #ifndef PATH390_HPP #define PATH390_HPP #include <xercesc/util/XercesDefs.hpp> XERCES_CPP_NAMESPACE_BEGIN class Path390 { public: // Constructors and Destructor Path390(); ~Path390(); Path390(char *s); // Set a new path in the object. This will overlay any existing path and // re-initialize the object. void setPath(char *s); // This performs a complete parse of the path. It returns the error code or 0 // if there was no error. int fullParse(); // This returns the path in a format as required by fopen char * getfopenPath(); // This returns the parameters in a format as required by fopen char * getfopenParms(); // This returns the type of the path. See the constants defined below. int getPathType(); // This returns the error code that was found during the parse int getError(); // Returns whether the path is relative or absolute bool isRelative(); // Returns whether or not type=record shows up in the path. bool isRecordType(); private: int _pathtype; char * _orgpath; int _orglen; char * _resultpath; bool _absolute; bool _uriabsolute; bool _dsnabsolute; char * _curpos; int _parsestate; int _numperiods; int _numsemicolons; int _error; char * _orgparms; int _orgparmlen; char * _lastsemi; char * _lastslash; char * _lastparen; char * _parmStart; char * _pathEnd; char * _extStart; int _typerecord; // internal only methods: void _determine_uri_abs(); void _determine_type(); void _determine_punct(); void _determine_parms(); void _parse_rest(); }; // Internal constants for the _parsestate variable: #define PARSE_NONE 0 #define PARSE_ABSOLUTE_URI 1 #define PARSE_PATHTYPE 2 #define PARSE_PUNCT 3 #define PARSE_PARMS 4 #define PARSE_PARSED 5 // These are the possible error return codes: #define NO_ERROR 0 #define ERROR_SEMICOLON_NOT_ALLOWED 101 #define ERROR_PERIOD_NOT_ALLOWED 102 #define ERROR_NO_PAREN_ALLOWED 103 #define ERROR_ABS_PATH_REQUIRED 104 #define ERROR_NO_EXTRA_PERIODS_ALLOWED 105 #define ERROR_MUST_BE_ABSOLUTE 106 #define ERROR_BAD_DD 107 #define ERROR_BAD_DSN2 108 #define ERROR_NO_EXTRA_SEMIS_ALLOWED 109 // Constants for the _pathtype variable and the return value from getPathType() method: #define PATH390_HFS 1 #define PATH390_DSN1 2 // format is dsn:/chrisl/data/xml/member1. #define PATH390_DSN2 3 // format is dsn://'chrisl.data.xml(member1)' #define PATH390_DD 4 #define PATH390_OTHER 5 XERCES_CPP_NAMESPACE_END #endif
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]