/* * Copyright 2002,2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * $Id: Path390.cpp 176026 2004-09-08 13:57:07Z peiyongz $ */ //#include "stdafx.h" #include #include #include #include #define _XOPEN_SOURCE_EXTENDED 1 #include #include #include "Path390.hpp" #include #include 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) XMLPlatformUtils::fgMemoryManager->deallocate(_orgparms);//free (_orgparms); if (_resultpath) XMLPlatformUtils::fgMemoryManager->deallocate(_resultpath);//free(_resultpath); if (_orgpath) XMLPlatformUtils::fgMemoryManager->deallocate(_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*) XMLPlatformUtils::fgMemoryManager->allocate(_orgparmlen * sizeof(char));// (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*) XMLPlatformUtils::fgMemoryManager->allocate((pathlen+10) * sizeof(char));//(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) XMLPlatformUtils::fgMemoryManager->deallocate(_orgparms);//free (_orgparms); if (_resultpath) XMLPlatformUtils::fgMemoryManager->deallocate(_resultpath);//free(_resultpath); if (_orgpath) XMLPlatformUtils::fgMemoryManager->deallocate(_orgpath);//free(_orgpath); _error = 0; _orgparms = 0; _resultpath = 0; _absolute = false; _dsnabsolute = false; _orglen = strlen(s); _orgpath = (char*) XMLPlatformUtils::fgMemoryManager->allocate((_orglen+1) * sizeof(char));//(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