/ OSX / libsecurity_codesigning / antlr2 / src / ANTLRUtil.cpp
ANTLRUtil.cpp
  1  /* ANTLR Translator Generator
  2   * Project led by Terence Parr at http://www.jGuru.com
  3   * Software rights: http://www.antlr.org/license.html
  4   *
  5   * $Id:$
  6   */
  7  
  8  #include <antlr/config.hpp>
  9  #include <antlr/IOException.hpp>
 10  #include <antlr/ANTLRUtil.hpp>
 11  
 12  #include <istream>
 13  #include <cctype>
 14  #include <string>
 15  
 16  #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE
 17  namespace antlr {
 18  #endif
 19  
 20  /** Eat whitespace from the input stream
 21   * @param is the stream to read from
 22   */
 23  ANTLR_USE_NAMESPACE(std)istream& eatwhite( ANTLR_USE_NAMESPACE(std)istream& is )
 24  {
 25  	char c;
 26  	while( is.get(c) )
 27  	{
 28  #ifdef ANTLR_CCTYPE_NEEDS_STD
 29  		if( !ANTLR_USE_NAMESPACE(std)isspace(c) )
 30  #else
 31  		if( !isspace(c) )
 32  #endif
 33  		{
 34  			is.putback(c);
 35  			break;
 36  		}
 37  	}
 38  	return is;
 39  }
 40  
 41  /** Read a string enclosed by '"' from a stream. Also handles escaping of \".
 42   * Skips leading whitespace.
 43   * @param in the istream to read from.
 44   * @returns the string read from file exclusive the '"'
 45   * @throws IOException if string is badly formatted
 46   */
 47  ANTLR_USE_NAMESPACE(std)string read_string( ANTLR_USE_NAMESPACE(std)istream& in )
 48  {
 49  	char ch;
 50  	ANTLR_USE_NAMESPACE(std)string ret("");
 51  	// States for a simple state machine...
 52  	enum { START, READING, ESCAPE, FINISHED };
 53  	int state = START;
 54  
 55  	eatwhite(in);
 56  
 57  	while( state != FINISHED && in.get(ch) )
 58  	{
 59  		switch( state )
 60  		{
 61  		case START:
 62  			// start state: check wether starting with " then switch to READING
 63  			if( ch != '"' )
 64  				throw IOException("string must start with '\"'");
 65  			state = READING;
 66  			continue;
 67  		case READING:
 68  			// reading state: look out for escape sequences and closing "
 69  			if( ch == '\\' )		// got escape sequence
 70  			{
 71  				state = ESCAPE;
 72  				continue;
 73  			}
 74  			if( ch == '"' ) 		// close quote -> stop
 75  			{
 76  				state = FINISHED;
 77  				continue;
 78  			}
 79  			ret += ch;				// else append...
 80  			continue;
 81  		case ESCAPE:
 82  			switch(ch)
 83  			{
 84  			case '\\':
 85  				ret += ch;
 86  				state = READING;
 87  				continue;
 88  			case '"':
 89  				ret += ch;
 90  				state = READING;
 91  				continue;
 92  			case '0':
 93  				ret += '\0';
 94  				state = READING;
 95  				continue;
 96  			default:						// unrecognized escape is not mapped
 97  				ret += '\\';
 98  				ret += ch;
 99  				state = READING;
100  				continue;
101  			}
102  		}
103  	}
104  	if( state != FINISHED )
105  		throw IOException("badly formatted string: "+ret);
106  
107  	return ret;
108  }
109  
110  /* Read a ([A-Z][0-9][a-z]_)* kindoff thing. Skips leading whitespace.
111   * @param in the istream to read from.
112   */
113  ANTLR_USE_NAMESPACE(std)string read_identifier( ANTLR_USE_NAMESPACE(std)istream& in )
114  {
115  	char ch;
116  	ANTLR_USE_NAMESPACE(std)string ret("");
117  
118  	eatwhite(in);
119  
120  	while( in.get(ch) )
121  	{
122  #ifdef ANTLR_CCTYPE_NEEDS_STD
123  		if( ANTLR_USE_NAMESPACE(std)isupper(ch) ||
124  			 ANTLR_USE_NAMESPACE(std)islower(ch) ||
125  			 ANTLR_USE_NAMESPACE(std)isdigit(ch) ||
126  			 ch == '_' )
127  #else
128  		if( isupper(ch) || islower(ch) || isdigit(ch) || ch == '_' )
129  #endif
130  			ret += ch;
131  		else
132  		{
133  			in.putback(ch);
134  			break;
135  		}
136  	}
137  	return ret;
138  }
139  
140  /** Read a attribute="value" thing. Leading whitespace is skipped.
141   * Between attribute and '=' no whitespace is allowed. After the '=' it is
142   * permitted.
143   * @param in the istream to read from.
144   * @param attribute string the attribute name is put in
145   * @param value string the value of the attribute is put in
146   * @throws IOException if something is fishy. E.g. malformed quoting
147   * or missing '='
148   */
149  void read_AttributeNValue( ANTLR_USE_NAMESPACE(std)istream& in,
150  									ANTLR_USE_NAMESPACE(std)string& attribute,
151  									ANTLR_USE_NAMESPACE(std)string& value )
152  {
153  	attribute = read_identifier(in);
154  
155  	char ch;
156  	if( in.get(ch) && ch == '=' )
157  		value = read_string(in);
158  	else
159  		throw IOException("invalid attribute=value thing "+attribute);
160  }
161  
162  #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE
163  }
164  #endif