LLOOP Index | GSP Language | GSP Library | Framework Classes | Component Classes

filewindows.gsp

This is the verbatim text of the file "filewindows.gsp" part of the LLOOP package. The copyright remains with Michel MEHL. All rights reserved.



/**
 * Reads a windows file/directory name or path.
 * This is quite different from reading a unix path.
 *
 * Names are separated with backslash chars '\' and no escape sequence is allowed. 
 *
 * Any printable char (0x20 to 0x7E in ASCII) except '/', ',', ':', '*', '?', '"', '<', '>' and '|'  can be used for the names, but the first encountered white space char marks the end of the path. File names containing white space chars must be enclosed by double quotes. 
 */


token FileWindowsToken 
  extends class universal::File()
          class universal::String()
  include <stdio.h>, 
          <ctype.h>, 
           "universal__File.h", 
           "universal__String.h"
  alias "filewindows"

  declare    /* Extra declarations in token class */
  {{
    private:

    /* The char is stored in a int. With gcc the value contained 
     * in a char was correctly assigned at the end of the parse 
     * function but was lost and set to zero when returning from
     * the top-level parse function call!
     */

    int m_iQuoteChar;
      
    public:
     
      inline bool acceptChar(register char c)
	{
	  switch(c)
	    {
	      case '/': case ',': case ':': case '*': case '?': case '\"': case '<': case '>': case '|' :
		return false;

   	      default:
		if ((!m_iQuoteChar) && isspace(c))
		  return false;
		else
		  return isprint(c); // Otherwise any other printable char is OK
	    }
	}
  }}

  implement 
  {{
  }}

  parse
  {{
    /* Set explicitly the file system type for the file object so that it
     * is managed the proper way afterwards by the file object.
     */

    m_fs = FS_WINDOWS;

    m_iQuoteChar = 0;
    char c = 0;
    char cPrev = 0;
    register char cQuoteChar = 0;        		

    setEmpty();

    /* Get first char. If double quote char is found, store it
     * for further processing of the input.
     *
     * If any failure occurred or the first char is not accepted, abort.
     */

    is.get(c);
    if (c == '\"')
      {        
	cQuoteChar = c;
	m_iQuoteChar = c;
	is.get(c);
      }

    if (is.fail() || !acceptChar(c))
      abort(""); 

    append(c);

    /* Attempt to read second char.
     * If there is a failure, it is OK since the first has
     * been accepted.
     *
     *  DRIVERLETTER: or any other accepted char
     * of a file name
     */

    cPrev = c;
    c = 0;
    is.get(c);

    if (is.fail())
      {
	
	// If there was a starting quote refuse this case
	if (cQuoteChar) 
	  abort(""); 
	// Otherwise it is OK: the name has just one valid char, i.e.
	// the one read just before contained in cPrev
	else           
	  ;	
      }
    else
      {
	/* If there is a second double quote, it means it is
	 * a quote containing the single char which was read before. 
	 * This shall be accepted.
	 * Stream is already correctly positioned for the following of the 
	 * parsing.
	 */

	if (cQuoteChar && (c == '\"'))
	  {
	    // Nothing more to do
	  }

	/* The path can be an absolute path starting either
	 * with a driver letter like 'C:' or with '\\'.
	 * These cases must be accepted.
	 * Otherwise, it means only the previous char is accepted.
	 */
	
	else if (!acceptChar(c) && 
		 !(isalpha(cPrev) && c == ':') &&
		 !(cPrev == '\\' && c == '\\')
		 )
	  {
	    /* Need to rewind of 1 char in the stream. 
	     * It is a no-op if there is any failure.
	     */
	    
	    is.seekg(-1, ios::cur); 
	  }
	else
	  {
	    append(c);
	    is.get(c);

	    if (cQuoteChar)
	      {
		// Read path within quotes: Space chars are accepted
		while (!is.fail() && acceptChar(c))
		  {
		    append(c);
		    is.get(c);
		  }

		if (is.fail() || c != cQuoteChar)
		  abort("");

		// Stream is correctly positioned
	      }    
	    else
	      {
		// Read path: Space chars are not accepted
		while (!is.fail() && acceptChar(c))
		  {
		    append(c);
		    is.get(c);
		  }

		/* Need to rewind of 1 char in the stream. 
		 * It is a no-op if there is any failure.
		 */
		
		is.seekg(-1, ios::cur); 
	      }
	  }
      }

    /* Set the file name by passing the const char* of the result string, 
     * since ending null char may have been extracted and accepted!
     * This ensures a clean string is constructed from that C string.
     * If the name is empty, it is an error !
     */

    setName(str()); 

    /* If the name is empty, it is an error !
     */

    if (name().empty())
      abort("");
  }}

  expand
  {{
    if (m_iQuoteChar)
      {
	os << (char)m_iQuoteChar << (*this) << (char)m_iQuoteChar;
      }
    else
      {
	os << (*this);
      }
  }} 
  test
  {{
    "c:"                          : pass {c:}
    "\\"                          : pass {\}
    "d:\\"                        : pass {d:\}
    "\\\\schtroumpf\\village"     : pass {\\schtroumpf\village}
    "\\\\schtroumpf\\village\\"   : pass {\\schtroumpf\village\}
    "\"c:\""                      : pass {"c:"}
    "\"\\\""                      : pass {"\\"}
    "\"d:\\\""                    : pass {"d:\"}
    "\"\\\\schtroumpf\\village\"" : pass {"\\schtroumpf\village"}
    "\"\\\\schtroumpf\\village\\\"" : pass {"\\schtroumpf\village\"}
    "\"\\\\schtroumpf\\village in the forest\\\"" : pass {"\\schtroumpf\village in the forest\"}
    "c"                           : pass {c}
    ":"                           : fail {:}
    "::"                          : fail {::}
    ":::"                         : fail {:::}
    "\"file"                      : fail {"file}
    "c d"                         : fail {c d} {c d}
    "\"\\\\"                      : fail {"\\}
    "\\\\ "                       : fail {\\ } {\\}
    "path with spaces\\fileame"   : fail {path with spaces}
    "\"path with spaces\\filename\"" : pass {"path with spaces\filename"}
  }}

This file is part of the LLOOP Reversible Object-Oriented Parser Generator. Copyright (c) 2005-2006 Michel MEHL, France. All rights reserved. LLOOP is distributed by the company ERSA SaRL.


Copyright (c) 2005-2006 Michel MEHL, Haguenau, France
LLOOP version 1.1