Path390.cpp
上传用户:zhuqijet
上传日期:2013-06-25
资源大小:10074k
文件大小:18k
源码类别:

词法分析

开发平台:

Visual C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 2002 The Apache Software Foundation.  All rights
  5.  * reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  *
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  *
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in
  16.  *    the documentation and/or other materials provided with the
  17.  *    distribution.
  18.  *
  19.  * 3. The end-user documentation included with the redistribution,
  20.  *    if any, must include the following acknowledgment:
  21.  *       "This product includes software developed by the
  22.  *        Apache Software Foundation (http://www.apache.org/)."
  23.  *    Alternately, this acknowledgment may appear in the software itself,
  24.  *    if and wherever such third-party acknowledgments normally appear.
  25.  *
  26.  * 4. The names "Xerces" and "Apache Software Foundation" must
  27.  *    not be used to endorse or promote products derived from this
  28.  *    software without prior written permission. For written
  29.  *    permission, please contact apache@apache.org.
  30.  *
  31.  * 5. Products derived from this software may not be called "Apache",
  32.  *    nor may "Apache" appear in their name, without prior written
  33.  *    permission of the Apache Software Foundation.
  34.  *
  35.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38.  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42.  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44.  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45.  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46.  * SUCH DAMAGE.
  47.  * ====================================================================
  48.  *
  49.  * This software consists of voluntary contributions made by many
  50.  * individuals on behalf of the Apache Software Foundation, and was
  51.  * originally based on software copyright (c) 1999, International
  52.  * Business Machines, Inc., http://www.ibm.com .  For more information
  53.  * on the Apache Software Foundation, please see
  54.  * <http://www.apache.org/>.
  55.  */
  56. /*
  57.  * $Id: Path390.cpp,v 1.1 2002/11/22 14:57:32 tng Exp $
  58.  */
  59. //#include "stdafx.h"
  60. #include <fstream.h>
  61. #include <stdio.h>
  62. #include <ctype.h>
  63. #include <typeinfo>
  64. #define _XOPEN_SOURCE_EXTENDED 1
  65. #include <stdlib.h>
  66. #include <string.h>
  67. #include "Path390.hpp"
  68. XERCES_CPP_NAMESPACE_BEGIN
  69. //Constructors:
  70. Path390::Path390() {
  71.    _error = 0;
  72.    _absolute = false;
  73.    _dsnabsolute = false;
  74.    _parsestate=PARSE_NONE;
  75.    _orgparms=0;
  76.    _resultpath=0;
  77.    _orgpath=0;
  78. }
  79. Path390::Path390(char * s) {
  80.    _error = 0;
  81.    _absolute = false;
  82.    _dsnabsolute = false;
  83.    _parsestate=PARSE_NONE;
  84.    _orgparms=0;
  85.    _resultpath=0;
  86.    _orgpath=0;
  87.    setPath(s);
  88. }
  89. //Destructor:
  90. Path390::~Path390() {
  91.    if (_orgparms)
  92.       free (_orgparms);
  93.    if (_resultpath)
  94.       free(_resultpath);
  95.    if (_orgpath)
  96.       free(_orgpath);
  97. }
  98. // This path parser is state driven in order to support an incremental parse of the input path.
  99. // This is so that, for example, someone only wants to determine whether the path is absolute or
  100. // relative, then it will only parse sufficient information to determine this. This information
  101. // is saved in the object so that this does not need to be re-parsed if later one wanted to
  102. // retrieve, for example, the parameters.
  103. // The states are:
  104. //    PARSE_NONE - initial state, nothing is parsed.
  105. //    PARSE_ABSOLUTE_URI - Absolute or relative path has been determined.
  106. //    PARSE_PATHTYPE - The type of the path has been determined
  107. //    PARSE_PUNCT - The important delimiters have been located to make later parsing simpler.
  108. //    PARSE_PARMS - The parms have been located and retrieved.
  109. //    PARSE_PARSED - The path has been fully parsed.
  110. //
  111. // Each of the following methods handle the parsing corresponding to each state.
  112. //
  113. // Determine if the path is absolute or relative.
  114. void Path390::_determine_uri_abs() {
  115.    if (_parsestate == PARSE_NONE) {
  116.       if (*_curpos == '/') {
  117.          _uriabsolute=true;
  118.          _curpos++;
  119.       } else
  120.          _uriabsolute=false;
  121.       _parsestate = PARSE_ABSOLUTE_URI;
  122.    }
  123. }
  124. // Determine the path type. This could be:
  125. //    PATH390_HFS - format is hfs:/xxx/xxx...
  126. //    PATH390_DSN1 - format is dsn:/xxx/xxx...
  127. //    PATH390_DSN2 - format is dsn://xxxxx...
  128. //    PATH390_DD - format is dd:xxx...
  129. //    PATH390_OTHER - format is any other paths.
  130. void Path390::_determine_type() {
  131.    char firstfour[5];
  132.    if (_parsestate == PARSE_ABSOLUTE_URI) {
  133.       char * ff=firstfour;
  134.       int ffi=0;
  135.       while ((_curpos[ffi]) && (ffi<4)) {ff[ffi] = toupper(_curpos[ffi]); ffi++;}
  136.       if ( (ffi>=4) && !strncmp(firstfour,"DSN:",4) ) {
  137.          _pathtype = PATH390_DSN1;
  138.          _curpos+=4;
  139.          _absolute = true;
  140.          if ( ((*_curpos) && (*_curpos == '/')) && ((*(_curpos+1)) && (*(_curpos+1) == '/')) ) {
  141.             _pathtype = PATH390_DSN2;
  142.             }
  143.          }
  144.       else if ( (ffi>=4) && !strncmp(firstfour,"HFS:",4) ) {
  145.          _pathtype = PATH390_HFS;
  146.          _curpos+=4;
  147.          if (*_curpos == '/')
  148.             _absolute = true;
  149.          else
  150.             _absolute = false;
  151.          }
  152.       else if ( (ffi>=3) && !strncmp(firstfour,"DD:",3) ) {
  153.          _absolute = true;
  154.          _pathtype = PATH390_DD;
  155.          _curpos+=3;
  156.          }
  157.       else {
  158.          _pathtype = PATH390_OTHER;
  159.          if (_uriabsolute)
  160.             _curpos--;
  161.          }
  162.       _parsestate = PARSE_PATHTYPE;
  163.    }
  164. }
  165. // This takes one pass through the path any determines the location of important delimiters
  166. // including / ; . and (
  167. // It will also detect some error conditions
  168. void Path390::_determine_punct() {
  169.    if (_parsestate == PARSE_PATHTYPE) {
  170.       char * source = _curpos;
  171.       _lastsemi = 0;
  172.       _lastslash = 0;
  173.       _lastparen = 0;
  174.       _parmStart = 0;
  175.       _pathEnd = 0;
  176.       _numperiods = 0;
  177.       _numsemicolons = 0;
  178.       _extStart = 0;
  179.       while (*source) {
  180.          switch (*source) {
  181.             case ';':
  182.                _lastsemi = source;
  183.                _parmStart = source+1;
  184.                _numsemicolons++;
  185.                break;
  186.             case '/':
  187.                _lastslash = source;
  188.                _pathEnd = source;
  189.                break;
  190.             case '.':
  191.                _extStart = source+1;
  192.                _numperiods++;
  193.                break;
  194.             case '(':
  195.                _lastparen = source+1;
  196.                break;
  197.          }
  198.          *source++;
  199.       }
  200.       if ( (_parmStart) && (_parmStart<=_pathEnd) ) {
  201.          _error = ERROR_SEMICOLON_NOT_ALLOWED;
  202.          _lastsemi = 0;
  203.          _parmStart = 0;
  204.       }
  205.       if ( ((_pathtype == PATH390_DD) || (_pathtype == PATH390_DSN1) || (_pathtype == PATH390_DSN1)) &&
  206.            (_extStart <= _pathEnd) ) {
  207.          if (_extStart)
  208.             _error = ERROR_PERIOD_NOT_ALLOWED;
  209.          _extStart = 0;
  210.       }
  211.       if (_extStart < _lastparen)
  212.          _extStart = 0;
  213.       _parsestate = PARSE_PUNCT;
  214.    }
  215. }
  216. // This extracts the parameters from the path if there are any. It also determines if the parameters
  217. // contain type=record
  218. void Path390::_determine_parms() {
  219.    if (_parsestate == PARSE_PUNCT) {
  220.       char * tr = 0;
  221.       if (_parmStart) {
  222.          _orgparmlen = strlen(_parmStart)+1;
  223.          _orgparms = (char *) malloc(_orgparmlen);
  224.          char * ts=_parmStart;
  225.          char * td=_orgparms;
  226.          while (*ts)
  227.            *td++ = tolower(*ts++);
  228.          *td = 0;
  229.          *_lastsemi = 0;
  230.          tr = strstr(_orgparms,"type=record");
  231.       }
  232.       if (tr)
  233.         _typerecord = tr - _orgparms;
  234.       else
  235.         _typerecord = -1;
  236.       _parsestate = PARSE_PARMS;
  237.    }
  238. }
  239. // Complete the rest of the parse.
  240. void Path390::_parse_rest() {
  241.    if (_parsestate == PARSE_PARMS) {
  242.       char *source;
  243.       char *dest;
  244.       char * filename_start;
  245.       char * tmpPos;
  246.       int pathlen = strlen(_curpos);
  247.       _resultpath = (char *) malloc(pathlen+10);
  248.       source = _curpos;
  249.       dest = _resultpath;
  250.       switch (_pathtype) {
  251.          case PATH390_DSN1:
  252.             // This format needs to be mangled from a hierarchical (hfs style) path to the
  253.             // traditional MVS format. First check for some errors.
  254.             if (_lastparen) {
  255.                _error = ERROR_NO_PAREN_ALLOWED;
  256.                break;
  257.             }
  258.             if ((_uriabsolute) && (!_absolute)) {
  259.                _error = ERROR_ABS_PATH_REQUIRED;
  260.                break;
  261.             }
  262.             if ( ((_extStart) && (_numperiods > 1)) ||
  263.                  ((!_extStart) && (_numperiods)) ) {
  264.                _error = ERROR_NO_EXTRA_PERIODS_ALLOWED;
  265.                break;
  266.             }
  267.             if ( ((_parmStart) && (_numsemicolons > 1)) ||
  268.                  ((!_parmStart) && (_numsemicolons)) ) {
  269.                _error = ERROR_NO_EXTRA_SEMIS_ALLOWED;
  270.                break;
  271.             }
  272.             // start out the result with //
  273.             *dest++ = '/';
  274.             *dest++ = '/';
  275.             // If the input path starts with a / then it is absolute and it must be
  276.             // enclosed in 's
  277.             _dsnabsolute = false;
  278.             if (*source == '/') {
  279.               _dsnabsolute = true;
  280.               source++;
  281.             } else if (_uriabsolute) {
  282.                _error = ERROR_MUST_BE_ABSOLUTE;
  283.                break;
  284.             }
  285.             char * pathstart;
  286.             pathstart = source;
  287.             // Add in the ' if this is an absolute path'
  288.             if (_dsnabsolute) *dest++ = ''';
  289.             // If there is a / in the path....
  290.             tmpPos = source;
  291.             if (_pathEnd > source) {
  292.                // copy everything up to the last /, replacing / with .
  293.                while( source < _pathEnd ) {
  294.                   switch( *source ) {
  295.                       case '/':
  296.                          *dest = '.';
  297.                          break;
  298.                       default:
  299.                          *dest = *source;
  300.                   }
  301.                   dest++; source++;
  302.                }
  303.                // bump past the last /
  304.                source++;
  305.             }
  306.             // Now we try to locate the extension, and copy that.
  307.             filename_start = 0;
  308.             if ( _extStart != NULL ) {
  309.                tmpPos = _extStart;
  310.                if ( (*tmpPos != '') && (*tmpPos != ';') && (source != pathstart) )
  311.                   *dest++='.';
  312.                while ( (*tmpPos != '') && (*tmpPos != ';') ) {
  313.                   *dest++ = *tmpPos++;
  314.                }
  315.                // if there is a filename, add a (
  316.                if (source < (_extStart-1)) {
  317.                  filename_start = tmpPos;
  318.                  *dest++ = '(';
  319.                  }
  320.             }
  321.             else if (source != pathstart)
  322.                *dest++ = '.';
  323.             // Now we copy in the filename.
  324.             tmpPos = source;
  325.             while( ((*tmpPos != '') && (*tmpPos != ';'))  && ((_extStart == NULL) || (tmpPos < (_extStart-1))) ) {
  326.                *dest++ = *tmpPos++;
  327.             }
  328.             // Finally cap off the filename with optional ")"
  329.             if ( (_extStart != NULL) && (filename_start) ) *dest++ = ')';
  330.             // Add on the ending ' if necessary.
  331.             if (_dsnabsolute) *dest++ = ''';
  332.             // make it a null terminated string.
  333.             *dest = '';
  334.             break;
  335.          case PATH390_HFS:
  336.             // it is in hfs: format. If it is relative, then add on a ./ otherwise
  337.             // just copy the string.
  338.             if (!_absolute) {
  339.                if (_uriabsolute) {
  340.                   _error = ERROR_MUST_BE_ABSOLUTE;
  341.                   break;
  342.                }
  343.                *dest++='.';
  344.                *dest++='/';
  345.             }
  346.             strcpy(dest,source);
  347.             break;
  348.          case PATH390_DD:
  349.             // It's in dd: format. This is similar to the dsn: format, just shorter.
  350.             // Start it out with dd:
  351.             *dest++='D';
  352.             *dest++='D';
  353.             *dest++=':';
  354.             tmpPos = source;
  355.             // if there is a / present in the path...
  356.             if (_pathEnd > source) {
  357.                // copy everything up to the last /, replacing / with .
  358.                while( source < _pathEnd ) {
  359.                   switch( *source ) {
  360.                       case '/':
  361.                          *dest = '.';
  362.                          break;
  363.                       default:
  364.                          *dest = *source;
  365.                   }
  366.                   dest++; source++;
  367.                }
  368.                // bump past the last /
  369.                source++;
  370.             }
  371.             // Now we try to locate the extension, and copy that.
  372.             filename_start = 0;
  373.             if ( _extStart != NULL ) {
  374.                tmpPos = _extStart;
  375.                if ( (*tmpPos != '') && (*tmpPos != ';') && (source != _curpos) )
  376.                   *dest++='.';
  377.                while ( (*tmpPos != '') && (*tmpPos != ';') ) {
  378.                   *dest++ = *tmpPos++;
  379.                }
  380.                // if there is a filename, add a (
  381.                if (source < (_extStart-1)) {
  382.                  filename_start = tmpPos;
  383.                  *dest++ = '(';
  384.                  }
  385.             }
  386.             else if (source != _curpos)
  387.                *dest++ = '.';
  388.             // Now we copy in the filename.
  389.             tmpPos = source;
  390.             while( ((*tmpPos != '') && (*tmpPos != ';'))  && ((_extStart == NULL) || (tmpPos < (_extStart-1))) ) {
  391.                *dest++ = *tmpPos++;
  392.             }
  393.             // Finally cap off the filename with optional ")"
  394.             if ( (_extStart != NULL) && (filename_start) ) *dest++ = ')';
  395.             *dest = '';
  396.             break;
  397.          case PATH390_DSN2:
  398.             // This is in dsn: format with the traditional MVS dataset name. Just fall into
  399.             // the default case to copy the path to the destination after making sure that
  400.             // there are no extra slashes.
  401.             {
  402.             int lastslash=5;
  403.             if (_uriabsolute)
  404.               lastslash=6;
  405.             if ( (_lastslash) && ((_lastslash-_orgpath)>lastslash) ) {
  406.                _error = ERROR_BAD_DSN2;
  407.                break;
  408.             }
  409.             }
  410.          default:
  411.             // for all other cases simply copy over the string.
  412.             strcpy(dest,source);
  413.             break;
  414.       }
  415.       _parsestate = PARSE_PARSED;
  416.    }
  417. }
  418. // Public methods start here:
  419. // This sets a new path into the object. Re-initialize everything and do an initial
  420. // parse.
  421. void Path390::setPath(char * s) {
  422.    if (_orgparms)
  423.       free (_orgparms);
  424.    if (_resultpath)
  425.       free(_resultpath);
  426.    if (_orgpath)
  427.       free(_orgpath);
  428.    _error = 0;
  429.    _absolute = false;
  430.    _dsnabsolute = false;
  431.    _orglen = strlen(s);
  432.    _orgpath = (char *) malloc(_orglen+1);
  433.    strcpy(_orgpath,s);
  434.    _curpos = _orgpath;
  435.    _parsestate=PARSE_NONE;
  436.    // Do an initial parse...
  437.    _determine_uri_abs();
  438.    _determine_type();
  439. }
  440. // Do the parse to completion and return any errors found.
  441. int Path390::fullParse() {
  442.    // Do an initial parse...
  443.    _determine_uri_abs();
  444.    _determine_type();
  445.    _determine_punct();
  446.    if (_error) {
  447. //      printf("found error-%dn",_error);
  448.       return _error;
  449.    }
  450.    _determine_parms();
  451.    _parse_rest();
  452.    return _error;
  453. }
  454. // Get the path in a format which is required by fopen. First make sure that the path is
  455. // completely parsed
  456. char * Path390::getfopenPath() {
  457.    _determine_uri_abs();
  458.    _determine_type();
  459.    _determine_punct();
  460.    if (_error)  {
  461. //      printf("found error-%dn",_error);
  462.       return 0;
  463.    }
  464.    _determine_parms();
  465.    _parse_rest();
  466.    if (_error)  {
  467. //      printf("found error-%dn",_error);
  468.       return 0;
  469.    }
  470.    if (_resultpath[0])
  471.       return _resultpath;
  472.    else
  473.       return 0;
  474. }
  475. // Get the parms in a format which is required by fopen. First make sure that the path is
  476. // completely parsed
  477. char * Path390::getfopenParms() {
  478.    _determine_uri_abs();
  479.    _determine_type();
  480.    _determine_punct();
  481.    if (_error)  {
  482. //      printf("found error-%dn",_error);
  483.       return 0;
  484.    }
  485.    _determine_parms();
  486.    _parse_rest();
  487.    if (_error)  {
  488. //      printf("found error-%dn",_error);
  489.       return 0;
  490.    }
  491.    if ( (_orgparms) && (_orgparms[0]) )
  492.       return _orgparms;
  493.    else
  494.       return 0;
  495. }
  496. // return whether there is type=record parameter in the parameter list.
  497. bool Path390::isRecordType() {
  498.    _determine_uri_abs();
  499.    _determine_type();
  500.    _determine_punct();
  501.    if (_error)  {
  502. //      printf("found error-%dn",_error);
  503.       return false;
  504.    }
  505.    _determine_parms();
  506.    _parse_rest();
  507.    if (_error)  {
  508. //      printf("found error-%dn",_error);
  509.       return false;
  510.    }
  511.    if ( (_orgparms) && (_typerecord>=0) )
  512.       return true;
  513.    else
  514.       return false;
  515. }
  516. // This returns the path type
  517. int Path390::getPathType() {
  518.    _determine_uri_abs();
  519.    _determine_type();
  520.    return _pathtype;
  521. }
  522. // This returns the error code which was found when the path was parsed
  523. int Path390::getError() {
  524.    _determine_uri_abs();
  525.    _determine_type();
  526.    _determine_punct();
  527.    if (_error)  {
  528.  //     return _error;
  529.    }
  530.    _determine_parms();
  531.    _parse_rest();
  532.    if (_error)  {
  533.  //     return _error;
  534.    }
  535.    return _error;
  536. }
  537. // returns whether the path is relative or absolute.
  538. bool Path390::isRelative() {
  539.    _determine_uri_abs();
  540.    _determine_type();
  541. return !(_absolute|_uriabsolute);
  542. }
  543. XERCES_CPP_NAMESPACE_END