├── CMakeLists.txt ├── README.md └── src ├── NSPlist.cpp ├── NSPlist.h ├── NSPlistLexer.cpp ├── NSPlistLexer.l ├── NSPlistParser.cpp ├── NSPlistParser.h └── NSPlistParser.y /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | project(NSPlist) 3 | 4 | add_library(NSPlist src/NSPlist.cpp src/NSPlistLexer.cpp src/NSPlistParser.cpp) 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NSPlist 2 | -------------------------------------------------------------------------------- /src/NSPlist.cpp: -------------------------------------------------------------------------------- 1 | //****************************************************************************** 2 | // 3 | // Copyright (c) 2015 Microsoft Corporation. All rights reserved. 4 | // 5 | // This code is licensed under the MIT License (MIT). 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 8 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 9 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 10 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 11 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 12 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 13 | // THE SOFTWARE. 14 | // 15 | //****************************************************************************** 16 | 17 | #include 18 | #include 19 | 20 | #include "NSPlist.h" 21 | 22 | static char getEscapedChar(char c) 23 | { 24 | switch (c) { 25 | case '\t': return 't'; 26 | case '\r': return 'r'; 27 | case '\n': return 'n'; 28 | default: return c; 29 | } 30 | } 31 | 32 | static std::string addEscapes(const std::string& str) 33 | { 34 | static std::string specialChars("\\\"\t\r\n"); 35 | 36 | std::string ret; 37 | for (unsigned i = 0; i < str.length(); i++) { 38 | if (std::string::npos != specialChars.find_first_of(str[i])) { 39 | ret += '\\'; 40 | ret += getEscapedChar(str[i]); 41 | } else { 42 | ret += str[i]; 43 | } 44 | } 45 | 46 | return ret; 47 | } 48 | 49 | static bool mustQuote(char c) 50 | { 51 | static std::string allowedChars("_-.$/"); 52 | return !isalnum(c) && allowedChars.find_first_of(c) == std::string::npos; 53 | } 54 | 55 | static std::string quoteString(const std::string& str, bool forceQuote = false) { 56 | std::string escapedStr = addEscapes(str); 57 | for (unsigned i = 0; !forceQuote && i < escapedStr.length(); i++) 58 | forceQuote |= mustQuote(escapedStr[i]); 59 | 60 | if (forceQuote) 61 | return "\"" + escapedStr + "\""; 62 | else 63 | return escapedStr; 64 | } 65 | 66 | static void indent(std::ostream& out, unsigned indentLevel = 0) 67 | { 68 | for (unsigned i = 0; i < indentLevel; i++) out << "\t"; 69 | } 70 | 71 | NSPlistValue::~NSPlistValue() {} 72 | 73 | void NSPlistValue::write(std::ostream& out) const 74 | { 75 | out << "// !$*UTF8*$!" << std::endl; 76 | write(out, 0); 77 | out << std::endl; 78 | } 79 | 80 | void NSPlistString::write(std::ostream& out, unsigned indentLevel) const 81 | { 82 | out << quoteString(m_str); 83 | } 84 | 85 | void NSPlistData::insert(const std::string& hexstr) 86 | { 87 | const char* src = hexstr.c_str(); 88 | assert(hexstr.length() % 2 == 0); 89 | 90 | unsigned int u; 91 | while (sscanf(src, "%2x", &u) == 1) { 92 | m_data.push_back(u); 93 | src += 2; 94 | } 95 | } 96 | 97 | void NSPlistData::insert(const std::vector& data) 98 | { 99 | m_data.insert(m_data.end(), data.begin(),data.end()); 100 | } 101 | 102 | void NSPlistData::write(std::ostream& out, unsigned indentLevel) const 103 | { 104 | char hexbuf[3]; 105 | 106 | out << "<"; 107 | for (unsigned i = 0; i < m_data.size(); i++) { 108 | sprintf(hexbuf, "%02X", static_cast(m_data[i])); 109 | out << hexbuf; 110 | if (i < m_data.size() - 1) 111 | out << " "; 112 | } 113 | out << ">"; 114 | } 115 | 116 | NSPlistArray::~NSPlistArray() 117 | { 118 | NSPlistValueArray::iterator aIt = m_array.begin(); 119 | for (; aIt != m_array.end(); aIt++) 120 | delete (*aIt); 121 | } 122 | 123 | void NSPlistArray::insert(NSPlistValue* val) 124 | { 125 | m_array.push_back(val); 126 | } 127 | 128 | void NSPlistArray::write(std::ostream& out, unsigned indentLevel) const 129 | { 130 | out << "(" << std::endl; 131 | for (unsigned i = 0; i < m_array.size(); i++) { 132 | indent(out, indentLevel + 1); 133 | m_array[i]->write(out, indentLevel + 1); 134 | out << "," << std::endl; 135 | } 136 | indent(out, indentLevel); 137 | out << ")"; 138 | } 139 | 140 | NSPlistDictionary::~NSPlistDictionary() 141 | { 142 | NSPlistValueDict::iterator dIt = m_dict.begin(); 143 | for (; dIt != m_dict.end(); dIt++) 144 | delete (dIt->second); 145 | } 146 | 147 | void NSPlistDictionary::insert(NSPlistString* key, NSPlistValue* val) 148 | { 149 | insert(key->m_str, val); 150 | delete key; 151 | } 152 | 153 | void NSPlistDictionary::insert(const std::string& key, NSPlistValue* val) 154 | { 155 | m_dict[key] = val; 156 | } 157 | 158 | void NSPlistDictionary::write(std::ostream& out, unsigned indentLevel) const 159 | { 160 | out << "{" << std::endl; 161 | NSPlistValueDict::const_iterator dIt = m_dict.begin(); 162 | for (; dIt != m_dict.end(); dIt++) { 163 | indent(out, indentLevel + 1); 164 | out << quoteString(dIt->first) << " = "; 165 | dIt->second->write(out, indentLevel + 1); 166 | out << ";" << std::endl; 167 | } 168 | indent(out, indentLevel); 169 | out << "}"; 170 | } 171 | 172 | NSPlistString* NSPlistString::cast(NSPlistValue* val) 173 | { 174 | return dynamic_cast(val); 175 | } 176 | 177 | const NSPlistString* NSPlistString::cast(const NSPlistValue* val) 178 | { 179 | return dynamic_cast(val); 180 | } 181 | 182 | NSPlistData* NSPlistData::cast(NSPlistValue* val) 183 | { 184 | return dynamic_cast(val); 185 | } 186 | 187 | const NSPlistData* NSPlistData::cast(const NSPlistValue* val) 188 | { 189 | return dynamic_cast(val); 190 | } 191 | 192 | NSPlistArray* NSPlistArray::cast(NSPlistValue* val) 193 | { 194 | return dynamic_cast(val); 195 | } 196 | 197 | const NSPlistArray* NSPlistArray::cast(const NSPlistValue* val) 198 | { 199 | return dynamic_cast(val); 200 | } 201 | 202 | NSPlistDictionary* NSPlistDictionary::cast(NSPlistValue* val) 203 | { 204 | return dynamic_cast(val); 205 | } 206 | 207 | const NSPlistDictionary* NSPlistDictionary::cast(const NSPlistValue* val) 208 | { 209 | return dynamic_cast(val); 210 | } -------------------------------------------------------------------------------- /src/NSPlist.h: -------------------------------------------------------------------------------- 1 | //****************************************************************************** 2 | // 3 | // Copyright (c) 2015 Microsoft Corporation. All rights reserved. 4 | // 5 | // This code is licensed under the MIT License (MIT). 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 8 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 9 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 10 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 11 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 12 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 13 | // THE SOFTWARE. 14 | // 15 | //****************************************************************************** 16 | 17 | #ifndef _NSPLIST_H_ 18 | #define _NSPLIST_H_ 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | typedef enum { 25 | NSPlistStringValue, 26 | NSPlistArrayValue, 27 | NSPlistDictionaryValue, 28 | NSPlistDataValue, 29 | } NSPlistValueType; 30 | 31 | typedef enum { 32 | NSPlistStringString, 33 | NSPlistBoolString, 34 | NSPlistIntegerString, 35 | NSPlistRealString, 36 | NSPlistDateString, 37 | } NSPlistStringType; 38 | 39 | class NSPlistValue { 40 | public: 41 | virtual ~NSPlistValue() = 0; 42 | NSPlistValue(NSPlistValueType type) : m_type(type) {} 43 | void write(std::ostream& out) const; 44 | virtual void write(std::ostream& out, unsigned indentLevel) const = 0; 45 | 46 | NSPlistValueType m_type; 47 | }; 48 | 49 | class NSPlistString : public NSPlistValue { 50 | public: 51 | NSPlistString(const std::string& str, NSPlistStringType subType) 52 | : NSPlistValue(NSPlistStringValue), m_str(str), m_subType(subType) {} 53 | 54 | static NSPlistString* cast(NSPlistValue* val); 55 | static const NSPlistString* cast(const NSPlistValue* val); 56 | 57 | std::string m_str; 58 | NSPlistStringType m_subType; 59 | 60 | private: 61 | virtual void write(std::ostream& out, unsigned indentLevel) const; 62 | }; 63 | 64 | class NSPlistData : public NSPlistValue { 65 | public: 66 | NSPlistData() : NSPlistValue(NSPlistDataValue) {} 67 | void insert(const std::string& hexstr); 68 | void insert(const std::vector& data); 69 | 70 | static NSPlistData* cast(NSPlistValue* val); 71 | static const NSPlistData* cast(const NSPlistValue* val); 72 | 73 | std::vector m_data; 74 | 75 | private: 76 | virtual void write(std::ostream& out, unsigned indentLevel) const; 77 | }; 78 | 79 | typedef std::vector NSPlistValueArray; 80 | 81 | class NSPlistArray : public NSPlistValue { 82 | public: 83 | virtual ~NSPlistArray(); 84 | NSPlistArray() : NSPlistValue(NSPlistArrayValue) {} 85 | void insert(NSPlistValue* val); 86 | 87 | static NSPlistArray* cast(NSPlistValue* val); 88 | static const NSPlistArray* cast(const NSPlistValue* val); 89 | 90 | NSPlistValueArray m_array; 91 | 92 | private: 93 | virtual void write(std::ostream& out, unsigned indentLevel) const; 94 | }; 95 | 96 | typedef std::map NSPlistValueDict; 97 | 98 | class NSPlistDictionary : public NSPlistValue { 99 | public: 100 | virtual ~NSPlistDictionary(); 101 | NSPlistDictionary() : NSPlistValue(NSPlistDictionaryValue) {} 102 | void insert(NSPlistString* key, NSPlistValue* val); 103 | void insert(const std::string& key, NSPlistValue* val); 104 | 105 | static NSPlistDictionary* cast(NSPlistValue* val); 106 | static const NSPlistDictionary* cast(const NSPlistValue* val); 107 | 108 | NSPlistValueDict m_dict; 109 | 110 | private: 111 | virtual void write(std::ostream& out, unsigned indentLevel) const; 112 | }; 113 | 114 | extern bool loadPlistFromBuffer(const char* byteArray, NSPlistValue*& ret); 115 | extern bool loadPlistFromFile(const char* filePath, NSPlistValue*& ret); 116 | 117 | #endif /* _NSPLIST_H_ */ -------------------------------------------------------------------------------- /src/NSPlistLexer.cpp: -------------------------------------------------------------------------------- 1 | #line 2 "NSPlistLexer.cpp" 2 | 3 | #line 4 "NSPlistLexer.cpp" 4 | 5 | #define YY_INT_ALIGNED short int 6 | 7 | /* A lexical scanner generated by flex */ 8 | 9 | #define FLEX_SCANNER 10 | #define YY_FLEX_MAJOR_VERSION 2 11 | #define YY_FLEX_MINOR_VERSION 5 12 | #define YY_FLEX_SUBMINOR_VERSION 35 13 | #if YY_FLEX_SUBMINOR_VERSION > 0 14 | #define FLEX_BETA 15 | #endif 16 | 17 | /* First, we deal with platform-specific or compiler-specific issues. */ 18 | 19 | /* begin standard C headers. */ 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | /* end standard C headers. */ 26 | 27 | /* flex integer type definitions */ 28 | 29 | #ifndef FLEXINT_H 30 | #define FLEXINT_H 31 | 32 | /* C99 systems have . Non-C99 systems may or may not. */ 33 | 34 | #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L 35 | 36 | /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, 37 | * if you want the limit (max/min) macros for int types. 38 | */ 39 | #ifndef __STDC_LIMIT_MACROS 40 | #define __STDC_LIMIT_MACROS 1 41 | #endif 42 | 43 | #include 44 | typedef int8_t flex_int8_t; 45 | typedef uint8_t flex_uint8_t; 46 | typedef int16_t flex_int16_t; 47 | typedef uint16_t flex_uint16_t; 48 | typedef int32_t flex_int32_t; 49 | typedef uint32_t flex_uint32_t; 50 | typedef uint64_t flex_uint64_t; 51 | #else 52 | typedef signed char flex_int8_t; 53 | typedef short int flex_int16_t; 54 | typedef int flex_int32_t; 55 | typedef unsigned char flex_uint8_t; 56 | typedef unsigned short int flex_uint16_t; 57 | typedef unsigned int flex_uint32_t; 58 | #endif /* ! C99 */ 59 | 60 | /* Limits of integral types. */ 61 | #ifndef INT8_MIN 62 | #define INT8_MIN (-128) 63 | #endif 64 | #ifndef INT16_MIN 65 | #define INT16_MIN (-32767-1) 66 | #endif 67 | #ifndef INT32_MIN 68 | #define INT32_MIN (-2147483647-1) 69 | #endif 70 | #ifndef INT8_MAX 71 | #define INT8_MAX (127) 72 | #endif 73 | #ifndef INT16_MAX 74 | #define INT16_MAX (32767) 75 | #endif 76 | #ifndef INT32_MAX 77 | #define INT32_MAX (2147483647) 78 | #endif 79 | #ifndef UINT8_MAX 80 | #define UINT8_MAX (255U) 81 | #endif 82 | #ifndef UINT16_MAX 83 | #define UINT16_MAX (65535U) 84 | #endif 85 | #ifndef UINT32_MAX 86 | #define UINT32_MAX (4294967295U) 87 | #endif 88 | 89 | #endif /* ! FLEXINT_H */ 90 | 91 | #ifdef __cplusplus 92 | 93 | /* The "const" storage-class-modifier is valid. */ 94 | #define YY_USE_CONST 95 | 96 | #else /* ! __cplusplus */ 97 | 98 | /* C99 requires __STDC__ to be defined as 1. */ 99 | #if defined (__STDC__) 100 | 101 | #define YY_USE_CONST 102 | 103 | #endif /* defined (__STDC__) */ 104 | #endif /* ! __cplusplus */ 105 | 106 | #ifdef YY_USE_CONST 107 | #define yyconst const 108 | #else 109 | #define yyconst 110 | #endif 111 | 112 | /* Returned upon end-of-file. */ 113 | #define YY_NULL 0 114 | 115 | /* Promotes a possibly negative, possibly signed char to an unsigned 116 | * integer for use as an array index. If the signed char is negative, 117 | * we want to instead treat it as an 8-bit unsigned char, hence the 118 | * double cast. 119 | */ 120 | #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) 121 | 122 | /* Enter a start condition. This macro really ought to take a parameter, 123 | * but we do it the disgusting crufty way forced on us by the ()-less 124 | * definition of BEGIN. 125 | */ 126 | #define BEGIN (yy_start) = 1 + 2 * 127 | 128 | /* Translate the current start state into a value that can be later handed 129 | * to BEGIN to return to the state. The YYSTATE alias is for lex 130 | * compatibility. 131 | */ 132 | #define YY_START (((yy_start) - 1) / 2) 133 | #define YYSTATE YY_START 134 | 135 | /* Action number for EOF rule of a given start state. */ 136 | #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) 137 | 138 | /* Special action meaning "start processing a new file". */ 139 | #define YY_NEW_FILE yyrestart(yyin ) 140 | 141 | #define YY_END_OF_BUFFER_CHAR 0 142 | 143 | /* Size of default input buffer. */ 144 | #ifndef YY_BUF_SIZE 145 | #define YY_BUF_SIZE 16384 146 | #endif 147 | 148 | /* The state buf must be large enough to hold one state per character in the main buffer. 149 | */ 150 | #define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) 151 | 152 | #ifndef YY_TYPEDEF_YY_BUFFER_STATE 153 | #define YY_TYPEDEF_YY_BUFFER_STATE 154 | typedef struct yy_buffer_state *YY_BUFFER_STATE; 155 | #endif 156 | 157 | #ifndef YY_TYPEDEF_YY_SIZE_T 158 | #define YY_TYPEDEF_YY_SIZE_T 159 | typedef size_t yy_size_t; 160 | #endif 161 | 162 | extern yy_size_t yyleng; 163 | 164 | extern FILE *yyin, *yyout; 165 | 166 | #define EOB_ACT_CONTINUE_SCAN 0 167 | #define EOB_ACT_END_OF_FILE 1 168 | #define EOB_ACT_LAST_MATCH 2 169 | 170 | /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires 171 | * access to the local variable yy_act. Since yyless() is a macro, it would break 172 | * existing scanners that call yyless() from OUTSIDE yylex. 173 | * One obvious solution it to make yy_act a global. I tried that, and saw 174 | * a 5% performance hit in a non-yylineno scanner, because yy_act is 175 | * normally declared as a register variable-- so it is not worth it. 176 | */ 177 | #define YY_LESS_LINENO(n) \ 178 | do { \ 179 | yy_size_t yyl;\ 180 | for ( yyl = n; yyl < yyleng; ++yyl )\ 181 | if ( yytext[yyl] == '\n' )\ 182 | --yylineno;\ 183 | }while(0) 184 | 185 | /* Return all but the first "n" matched characters back to the input stream. */ 186 | #define yyless(n) \ 187 | do \ 188 | { \ 189 | /* Undo effects of setting up yytext. */ \ 190 | int yyless_macro_arg = (n); \ 191 | YY_LESS_LINENO(yyless_macro_arg);\ 192 | *yy_cp = (yy_hold_char); \ 193 | YY_RESTORE_YY_MORE_OFFSET \ 194 | (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ 195 | YY_DO_BEFORE_ACTION; /* set up yytext again */ \ 196 | } \ 197 | while ( 0 ) 198 | 199 | #define unput(c) yyunput( c, (yytext_ptr) ) 200 | 201 | #ifndef YY_STRUCT_YY_BUFFER_STATE 202 | #define YY_STRUCT_YY_BUFFER_STATE 203 | struct yy_buffer_state 204 | { 205 | FILE *yy_input_file; 206 | 207 | char *yy_ch_buf; /* input buffer */ 208 | char *yy_buf_pos; /* current position in input buffer */ 209 | 210 | /* Size of input buffer in bytes, not including room for EOB 211 | * characters. 212 | */ 213 | yy_size_t yy_buf_size; 214 | 215 | /* Number of characters read into yy_ch_buf, not including EOB 216 | * characters. 217 | */ 218 | yy_size_t yy_n_chars; 219 | 220 | /* Whether we "own" the buffer - i.e., we know we created it, 221 | * and can realloc() it to grow it, and should free() it to 222 | * delete it. 223 | */ 224 | int yy_is_our_buffer; 225 | 226 | /* Whether this is an "interactive" input source; if so, and 227 | * if we're using stdio for input, then we want to use getc() 228 | * instead of fread(), to make sure we stop fetching input after 229 | * each newline. 230 | */ 231 | int yy_is_interactive; 232 | 233 | /* Whether we're considered to be at the beginning of a line. 234 | * If so, '^' rules will be active on the next match, otherwise 235 | * not. 236 | */ 237 | int yy_at_bol; 238 | 239 | int yy_bs_lineno; /**< The line count. */ 240 | int yy_bs_column; /**< The column count. */ 241 | 242 | /* Whether to try to fill the input buffer when we reach the 243 | * end of it. 244 | */ 245 | int yy_fill_buffer; 246 | 247 | int yy_buffer_status; 248 | 249 | #define YY_BUFFER_NEW 0 250 | #define YY_BUFFER_NORMAL 1 251 | /* When an EOF's been seen but there's still some text to process 252 | * then we mark the buffer as YY_EOF_PENDING, to indicate that we 253 | * shouldn't try reading from the input source any more. We might 254 | * still have a bunch of tokens to match, though, because of 255 | * possible backing-up. 256 | * 257 | * When we actually see the EOF, we change the status to "new" 258 | * (via yyrestart()), so that the user can continue scanning by 259 | * just pointing yyin at a new input file. 260 | */ 261 | #define YY_BUFFER_EOF_PENDING 2 262 | 263 | }; 264 | #endif /* !YY_STRUCT_YY_BUFFER_STATE */ 265 | 266 | /* Stack of input buffers. */ 267 | static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ 268 | static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ 269 | static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ 270 | 271 | /* We provide macros for accessing buffer states in case in the 272 | * future we want to put the buffer states in a more general 273 | * "scanner state". 274 | * 275 | * Returns the top of the stack, or NULL. 276 | */ 277 | #define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ 278 | ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ 279 | : NULL) 280 | 281 | /* Same as previous macro, but useful when we know that the buffer stack is not 282 | * NULL or when we need an lvalue. For internal use only. 283 | */ 284 | #define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] 285 | 286 | /* yy_hold_char holds the character lost when yytext is formed. */ 287 | static char yy_hold_char; 288 | static yy_size_t yy_n_chars; /* number of characters read into yy_ch_buf */ 289 | yy_size_t yyleng; 290 | 291 | /* Points to current character in buffer. */ 292 | static char *yy_c_buf_p = (char *) 0; 293 | static int yy_init = 0; /* whether we need to initialize */ 294 | static int yy_start = 0; /* start state number */ 295 | 296 | /* Flag which is used to allow yywrap()'s to do buffer switches 297 | * instead of setting up a fresh yyin. A bit of a hack ... 298 | */ 299 | static int yy_did_buffer_switch_on_eof; 300 | 301 | void yyrestart (FILE *input_file ); 302 | void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); 303 | YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ); 304 | void yy_delete_buffer (YY_BUFFER_STATE b ); 305 | void yy_flush_buffer (YY_BUFFER_STATE b ); 306 | void yypush_buffer_state (YY_BUFFER_STATE new_buffer ); 307 | void yypop_buffer_state (void ); 308 | 309 | static void yyensure_buffer_stack (void ); 310 | static void yy_load_buffer_state (void ); 311 | static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ); 312 | 313 | #define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ) 314 | 315 | YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ); 316 | YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ); 317 | YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len ); 318 | 319 | void *yyalloc (yy_size_t ); 320 | void *yyrealloc (void *,yy_size_t ); 321 | void yyfree (void * ); 322 | 323 | #define yy_new_buffer yy_create_buffer 324 | 325 | #define yy_set_interactive(is_interactive) \ 326 | { \ 327 | if ( ! YY_CURRENT_BUFFER ){ \ 328 | yyensure_buffer_stack (); \ 329 | YY_CURRENT_BUFFER_LVALUE = \ 330 | yy_create_buffer(yyin,YY_BUF_SIZE ); \ 331 | } \ 332 | YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ 333 | } 334 | 335 | #define yy_set_bol(at_bol) \ 336 | { \ 337 | if ( ! YY_CURRENT_BUFFER ){\ 338 | yyensure_buffer_stack (); \ 339 | YY_CURRENT_BUFFER_LVALUE = \ 340 | yy_create_buffer(yyin,YY_BUF_SIZE ); \ 341 | } \ 342 | YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ 343 | } 344 | 345 | #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) 346 | 347 | /* Begin user sect3 */ 348 | 349 | #define yywrap(n) 1 350 | #define YY_SKIP_YYWRAP 351 | 352 | typedef unsigned char YY_CHAR; 353 | 354 | FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; 355 | 356 | typedef int yy_state_type; 357 | 358 | extern int yylineno; 359 | 360 | int yylineno = 1; 361 | 362 | extern char *yytext; 363 | #define yytext_ptr yytext 364 | 365 | static yy_state_type yy_get_previous_state (void ); 366 | static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); 367 | static int yy_get_next_buffer (void ); 368 | static void yy_fatal_error (yyconst char msg[] ); 369 | 370 | /* Done after the current pattern has been matched and before the 371 | * corresponding action - sets up yytext. 372 | */ 373 | #define YY_DO_BEFORE_ACTION \ 374 | (yytext_ptr) = yy_bp; \ 375 | yyleng = (yy_size_t) (yy_cp - yy_bp); \ 376 | (yy_hold_char) = *yy_cp; \ 377 | *yy_cp = '\0'; \ 378 | (yy_c_buf_p) = yy_cp; 379 | 380 | #define YY_NUM_RULES 27 381 | #define YY_END_OF_BUFFER 28 382 | /* This struct is not used in this scanner, 383 | but its presence is necessary. */ 384 | struct yy_trans_info 385 | { 386 | flex_int32_t yy_verify; 387 | flex_int32_t yy_nxt; 388 | }; 389 | static yyconst flex_int16_t yy_accept[84] = 390 | { 0, 391 | 0, 0, 0, 0, 15, 15, 0, 0, 28, 26, 392 | 25, 25, 6, 11, 18, 19, 23, 11, 11, 11, 393 | 8, 24, 20, 22, 16, 17, 4, 4, 5, 15, 394 | 15, 7, 15, 15, 12, 26, 26, 21, 25, 11, 395 | 11, 8, 9, 2, 11, 11, 4, 3, 15, 0, 396 | 15, 12, 13, 12, 15, 10, 0, 1, 11, 11, 397 | 9, 12, 15, 13, 0, 12, 15, 15, 15, 15, 398 | 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 399 | 15, 14, 0 400 | } ; 401 | 402 | static yyconst flex_int32_t yy_ec[256] = 403 | { 0, 404 | 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 405 | 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 406 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 407 | 1, 2, 1, 4, 1, 5, 1, 1, 1, 6, 408 | 7, 8, 9, 10, 11, 12, 13, 14, 14, 14, 409 | 14, 14, 14, 14, 14, 14, 14, 15, 16, 17, 410 | 18, 19, 1, 1, 20, 20, 20, 20, 21, 20, 411 | 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 412 | 5, 5, 5, 22, 5, 5, 5, 5, 5, 23, 413 | 1, 24, 1, 1, 5, 1, 20, 20, 20, 20, 414 | 415 | 21, 20, 5, 5, 5, 5, 5, 5, 5, 5, 416 | 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 417 | 5, 5, 25, 1, 26, 1, 1, 1, 1, 1, 418 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 419 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 420 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 421 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 422 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 423 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 424 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 425 | 426 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 427 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 428 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 429 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 430 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 431 | 1, 1, 1, 1, 1 432 | } ; 433 | 434 | static yyconst flex_int32_t yy_meta[27] = 435 | { 0, 436 | 1, 1, 1, 2, 3, 1, 1, 4, 1, 1, 437 | 3, 3, 3, 3, 1, 1, 1, 1, 1, 3, 438 | 3, 3, 3, 1, 1, 1 439 | } ; 440 | 441 | static yyconst flex_int16_t yy_base[91] = 442 | { 0, 443 | 0, 0, 24, 25, 31, 53, 76, 96, 157, 265, 444 | 27, 34, 265, 0, 265, 265, 265, 27, 142, 36, 445 | 134, 265, 265, 265, 265, 265, 0, 0, 140, 123, 446 | 121, 265, 34, 36, 106, 48, 33, 265, 66, 0, 447 | 130, 122, 17, 265, 128, 52, 0, 265, 113, 67, 448 | 58, 140, 59, 153, 169, 67, 126, 265, 191, 111, 449 | 109, 203, 60, 61, 72, 217, 77, 80, 65, 88, 450 | 89, 37, 95, 97, 90, 108, 110, 111, 114, 122, 451 | 83, 84, 265, 241, 245, 249, 97, 253, 256, 260 452 | } ; 453 | 454 | static yyconst flex_int16_t yy_def[91] = 455 | { 0, 456 | 83, 1, 84, 84, 85, 85, 86, 86, 83, 83, 457 | 83, 83, 83, 87, 83, 83, 83, 87, 87, 87, 458 | 18, 83, 83, 83, 83, 83, 88, 88, 83, 89, 459 | 89, 83, 89, 89, 89, 89, 83, 83, 83, 87, 460 | 87, 18, 87, 83, 90, 87, 88, 83, 89, 89, 461 | 89, 89, 89, 89, 89, 83, 90, 83, 90, 87, 462 | 87, 89, 89, 89, 83, 89, 89, 89, 89, 89, 463 | 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 464 | 89, 89, 0, 83, 83, 83, 83, 83, 83, 83 465 | } ; 466 | 467 | static yyconst flex_int16_t yy_nxt[292] = 468 | { 0, 469 | 10, 11, 12, 13, 14, 15, 16, 10, 10, 17, 470 | 18, 19, 20, 21, 10, 22, 23, 24, 10, 14, 471 | 14, 14, 14, 10, 25, 26, 28, 28, 39, 39, 472 | 43, 29, 29, 31, 32, 39, 39, 46, 41, 33, 473 | 42, 33, 34, 44, 35, 51, 56, 52, 45, 53, 474 | 83, 49, 56, 56, 36, 31, 32, 50, 73, 50, 475 | 50, 33, 60, 33, 34, 61, 35, 39, 39, 83, 476 | 49, 53, 53, 64, 64, 70, 36, 11, 12, 55, 477 | 65, 50, 50, 50, 50, 56, 65, 65, 50, 37, 478 | 68, 56, 56, 69, 38, 37, 37, 11, 12, 40, 479 | 480 | 50, 71, 72, 50, 76, 82, 50, 50, 74, 37, 481 | 75, 50, 50, 50, 38, 37, 37, 51, 50, 54, 482 | 50, 77, 61, 78, 61, 79, 55, 80, 58, 50, 483 | 58, 50, 59, 50, 50, 81, 50, 50, 59, 59, 484 | 59, 59, 46, 43, 50, 50, 50, 59, 59, 59, 485 | 59, 51, 48, 52, 46, 43, 83, 83, 83, 83, 486 | 55, 83, 83, 50, 51, 83, 62, 83, 83, 83, 487 | 83, 83, 83, 55, 83, 83, 50, 63, 83, 63, 488 | 83, 83, 64, 83, 83, 83, 83, 83, 83, 83, 489 | 83, 83, 50, 58, 83, 59, 83, 83, 83, 83, 490 | 491 | 83, 59, 59, 59, 59, 83, 83, 83, 83, 83, 492 | 59, 59, 59, 59, 51, 83, 66, 83, 83, 83, 493 | 83, 83, 83, 55, 83, 83, 50, 67, 51, 83, 494 | 52, 83, 83, 83, 83, 83, 83, 55, 83, 83, 495 | 50, 27, 27, 27, 27, 30, 30, 30, 30, 10, 496 | 10, 10, 10, 47, 47, 47, 49, 83, 49, 49, 497 | 57, 57, 57, 57, 9, 83, 83, 83, 83, 83, 498 | 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 499 | 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 500 | 83 501 | 502 | } ; 503 | 504 | static yyconst flex_int16_t yy_chk[292] = 505 | { 0, 506 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 507 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 508 | 1, 1, 1, 1, 1, 1, 3, 4, 11, 11, 509 | 43, 3, 4, 5, 5, 12, 12, 43, 18, 5, 510 | 18, 5, 5, 20, 5, 33, 37, 33, 20, 34, 511 | 36, 36, 37, 37, 5, 6, 6, 33, 72, 34, 512 | 72, 6, 46, 6, 6, 46, 6, 39, 39, 50, 513 | 50, 51, 53, 63, 64, 69, 6, 7, 7, 53, 514 | 56, 51, 53, 63, 64, 65, 56, 56, 69, 7, 515 | 67, 65, 65, 68, 7, 7, 7, 8, 8, 87, 516 | 517 | 67, 70, 71, 68, 75, 81, 81, 82, 73, 8, 518 | 74, 70, 71, 75, 8, 8, 8, 35, 73, 35, 519 | 74, 76, 61, 77, 60, 78, 35, 79, 57, 35, 520 | 45, 76, 45, 77, 78, 80, 49, 79, 45, 45, 521 | 45, 45, 42, 41, 31, 80, 30, 45, 45, 45, 522 | 45, 52, 29, 52, 21, 19, 9, 0, 0, 0, 523 | 52, 0, 0, 52, 54, 0, 54, 0, 0, 0, 524 | 0, 0, 0, 54, 0, 0, 54, 55, 0, 55, 525 | 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, 526 | 0, 0, 55, 59, 0, 59, 0, 0, 0, 0, 527 | 528 | 0, 59, 59, 59, 59, 0, 0, 0, 0, 0, 529 | 59, 59, 59, 59, 62, 0, 62, 0, 0, 0, 530 | 0, 0, 0, 62, 0, 0, 62, 66, 66, 0, 531 | 66, 0, 0, 0, 0, 0, 0, 66, 0, 0, 532 | 66, 84, 84, 84, 84, 85, 85, 85, 85, 86, 533 | 86, 86, 86, 88, 88, 88, 89, 0, 89, 89, 534 | 90, 90, 90, 90, 83, 83, 83, 83, 83, 83, 535 | 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 536 | 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 537 | 83 538 | 539 | } ; 540 | 541 | /* Table of booleans, true if rule could match eol. */ 542 | static yyconst flex_int32_t yy_rule_can_match_eol[28] = 543 | { 0, 544 | 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 545 | 0, 0, 0, 0, 0, 1, 0, 0, }; 546 | 547 | static yy_state_type yy_last_accepting_state; 548 | static char *yy_last_accepting_cpos; 549 | 550 | extern int yy_flex_debug; 551 | int yy_flex_debug = 0; 552 | 553 | /* The intent behind this definition is that it'll catch 554 | * any uses of REJECT which flex missed. 555 | */ 556 | #define REJECT reject_used_but_not_detected 557 | #define yymore() yymore_used_but_not_detected 558 | #define YY_MORE_ADJ 0 559 | #define YY_RESTORE_YY_MORE_OFFSET 560 | char *yytext; 561 | #line 1 "NSPlistLexer.l" 562 | #line 2 "NSPlistLexer.l" 563 | #include "NSPlist.h" 564 | #include "NSPlistParser.h" 565 | #define SAVE_TOKEN yylval.string = strdup(yytext) 566 | #define UNESCAPE_STRING processEscapes(yylval.string) 567 | 568 | #ifdef DEBUG_NSPARSER 569 | #define TERMINATE_LEXER printf("Unrecognized character: %s\n", yytext); yyterminate(); 570 | #else 571 | #define TERMINATE_LEXER yyterminate(); 572 | #endif 573 | 574 | static char getUnescapedChar(char c) 575 | { 576 | switch (c) { 577 | case 't': return '\t'; 578 | case 'r': return '\r'; 579 | case 'n': return '\n'; 580 | default: return c; 581 | } 582 | } 583 | 584 | static void processEscapes(char *data) 585 | { 586 | unsigned s = 0; /* scanning index */ 587 | unsigned w = 0; /* write-back index */ 588 | char p = 0; /* previous character */ 589 | char c = 0; /* current character */ 590 | 591 | while ((c = data[s++]) != '\0') { 592 | if (p == '\\') { 593 | data[w++] = getUnescapedChar(c); 594 | } else if (c != '\\') { 595 | data[w++] = c; 596 | } 597 | p = c; 598 | } 599 | data[w] = '\0'; 600 | } 601 | 602 | #define YY_NO_UNISTD_H 1 603 | 604 | 605 | 606 | #line 607 "NSPlistLexer.cpp" 607 | 608 | #define INITIAL 0 609 | #define COMMENT 1 610 | #define QUOTED 2 611 | #define DATABLOCK 3 612 | 613 | #ifndef YY_NO_UNISTD_H 614 | /* Special case for "unistd.h", since it is non-ANSI. We include it way 615 | * down here because we want the user's section 1 to have been scanned first. 616 | * The user has a chance to override it with an option. 617 | */ 618 | #include 619 | #endif 620 | 621 | #ifndef YY_EXTRA_TYPE 622 | #define YY_EXTRA_TYPE void * 623 | #endif 624 | 625 | static int yy_init_globals (void ); 626 | 627 | /* Accessor methods to globals. 628 | These are made visible to non-reentrant scanners for convenience. */ 629 | 630 | int yylex_destroy (void ); 631 | 632 | int yyget_debug (void ); 633 | 634 | void yyset_debug (int debug_flag ); 635 | 636 | YY_EXTRA_TYPE yyget_extra (void ); 637 | 638 | void yyset_extra (YY_EXTRA_TYPE user_defined ); 639 | 640 | FILE *yyget_in (void ); 641 | 642 | void yyset_in (FILE * in_str ); 643 | 644 | FILE *yyget_out (void ); 645 | 646 | void yyset_out (FILE * out_str ); 647 | 648 | yy_size_t yyget_leng (void ); 649 | 650 | char *yyget_text (void ); 651 | 652 | int yyget_lineno (void ); 653 | 654 | void yyset_lineno (int line_number ); 655 | 656 | /* Macros after this point can all be overridden by user definitions in 657 | * section 1. 658 | */ 659 | 660 | #ifndef YY_SKIP_YYWRAP 661 | #ifdef __cplusplus 662 | extern "C" int yywrap (void ); 663 | #else 664 | extern int yywrap (void ); 665 | #endif 666 | #endif 667 | 668 | static void yyunput (int c,char *buf_ptr ); 669 | 670 | #ifndef yytext_ptr 671 | static void yy_flex_strncpy (char *,yyconst char *,int ); 672 | #endif 673 | 674 | #ifdef YY_NEED_STRLEN 675 | static int yy_flex_strlen (yyconst char * ); 676 | #endif 677 | 678 | #ifndef YY_NO_INPUT 679 | 680 | #ifdef __cplusplus 681 | static int yyinput (void ); 682 | #else 683 | static int input (void ); 684 | #endif 685 | 686 | #endif 687 | 688 | /* Amount of stuff to slurp up with each read. */ 689 | #ifndef YY_READ_BUF_SIZE 690 | #define YY_READ_BUF_SIZE 8192 691 | #endif 692 | 693 | /* Copy whatever the last rule matched to the standard output. */ 694 | #ifndef ECHO 695 | /* This used to be an fputs(), but since the string might contain NUL's, 696 | * we now use fwrite(). 697 | */ 698 | #define ECHO fwrite( yytext, yyleng, 1, yyout ) 699 | #endif 700 | 701 | /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, 702 | * is returned in "result". 703 | */ 704 | #ifndef YY_INPUT 705 | #define YY_INPUT(buf,result,max_size) \ 706 | if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ 707 | { \ 708 | int c = '*'; \ 709 | yy_size_t n; \ 710 | for ( n = 0; n < max_size && \ 711 | (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ 712 | buf[n] = (char) c; \ 713 | if ( c == '\n' ) \ 714 | buf[n++] = (char) c; \ 715 | if ( c == EOF && ferror( yyin ) ) \ 716 | YY_FATAL_ERROR( "input in flex scanner failed" ); \ 717 | result = n; \ 718 | } \ 719 | else \ 720 | { \ 721 | errno=0; \ 722 | while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ 723 | { \ 724 | if( errno != EINTR) \ 725 | { \ 726 | YY_FATAL_ERROR( "input in flex scanner failed" ); \ 727 | break; \ 728 | } \ 729 | errno=0; \ 730 | clearerr(yyin); \ 731 | } \ 732 | }\ 733 | \ 734 | 735 | #endif 736 | 737 | /* No semi-colon after return; correct usage is to write "yyterminate();" - 738 | * we don't want an extra ';' after the "return" because that will cause 739 | * some compilers to complain about unreachable statements. 740 | */ 741 | #ifndef yyterminate 742 | #define yyterminate() return YY_NULL 743 | #endif 744 | 745 | /* Number of entries by which start-condition stack grows. */ 746 | #ifndef YY_START_STACK_INCR 747 | #define YY_START_STACK_INCR 25 748 | #endif 749 | 750 | /* Report a fatal error. */ 751 | #ifndef YY_FATAL_ERROR 752 | #define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) 753 | #endif 754 | 755 | /* end tables serialization structures and prototypes */ 756 | 757 | /* Default declaration of generated scanner - a define so the user can 758 | * easily add parameters. 759 | */ 760 | #ifndef YY_DECL 761 | #define YY_DECL_IS_OURS 1 762 | 763 | extern int yylex (void); 764 | 765 | #define YY_DECL int yylex (void) 766 | #endif /* !YY_DECL */ 767 | 768 | /* Code executed at the beginning of each rule, after yytext and yyleng 769 | * have been set up. 770 | */ 771 | #ifndef YY_USER_ACTION 772 | #define YY_USER_ACTION 773 | #endif 774 | 775 | /* Code executed at the end of each rule. */ 776 | #ifndef YY_BREAK 777 | #define YY_BREAK break; 778 | #endif 779 | 780 | #define YY_RULE_SETUP \ 781 | YY_USER_ACTION 782 | 783 | /** The main scanner function which does all the work. 784 | */ 785 | YY_DECL 786 | { 787 | register yy_state_type yy_current_state; 788 | register char *yy_cp, *yy_bp; 789 | register int yy_act; 790 | 791 | #line 53 "NSPlistLexer.l" 792 | 793 | 794 | #line 795 "NSPlistLexer.cpp" 795 | 796 | if ( !(yy_init) ) 797 | { 798 | (yy_init) = 1; 799 | 800 | #ifdef YY_USER_INIT 801 | YY_USER_INIT; 802 | #endif 803 | 804 | if ( ! (yy_start) ) 805 | (yy_start) = 1; /* first start state */ 806 | 807 | if ( ! yyin ) 808 | yyin = stdin; 809 | 810 | if ( ! yyout ) 811 | yyout = stdout; 812 | 813 | if ( ! YY_CURRENT_BUFFER ) { 814 | yyensure_buffer_stack (); 815 | YY_CURRENT_BUFFER_LVALUE = 816 | yy_create_buffer(yyin,YY_BUF_SIZE ); 817 | } 818 | 819 | yy_load_buffer_state( ); 820 | } 821 | 822 | while ( 1 ) /* loops until end-of-file is reached */ 823 | { 824 | yy_cp = (yy_c_buf_p); 825 | 826 | /* Support of yytext. */ 827 | *yy_cp = (yy_hold_char); 828 | 829 | /* yy_bp points to the position in yy_ch_buf of the start of 830 | * the current run. 831 | */ 832 | yy_bp = yy_cp; 833 | 834 | yy_current_state = (yy_start); 835 | yy_match: 836 | do 837 | { 838 | register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; 839 | if ( yy_accept[yy_current_state] ) 840 | { 841 | (yy_last_accepting_state) = yy_current_state; 842 | (yy_last_accepting_cpos) = yy_cp; 843 | } 844 | while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) 845 | { 846 | yy_current_state = (int) yy_def[yy_current_state]; 847 | if ( yy_current_state >= 84 ) 848 | yy_c = yy_meta[(unsigned int) yy_c]; 849 | } 850 | yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; 851 | ++yy_cp; 852 | } 853 | while ( yy_current_state != 83 ); 854 | yy_cp = (yy_last_accepting_cpos); 855 | yy_current_state = (yy_last_accepting_state); 856 | 857 | yy_find_action: 858 | yy_act = yy_accept[yy_current_state]; 859 | 860 | YY_DO_BEFORE_ACTION; 861 | 862 | if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] ) 863 | { 864 | yy_size_t yyl; 865 | for ( yyl = 0; yyl < yyleng; ++yyl ) 866 | if ( yytext[yyl] == '\n' ) 867 | 868 | yylineno++; 869 | ; 870 | } 871 | 872 | do_action: /* This label is used only to access EOF actions. */ 873 | 874 | switch ( yy_act ) 875 | { /* beginning of action switch */ 876 | case 0: /* must back up */ 877 | /* undo the effects of YY_DO_BEFORE_ACTION */ 878 | *yy_cp = (yy_hold_char); 879 | yy_cp = (yy_last_accepting_cpos); 880 | yy_current_state = (yy_last_accepting_state); 881 | goto yy_find_action; 882 | 883 | case 1: 884 | *yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ 885 | (yy_c_buf_p) = yy_cp -= 1; 886 | YY_DO_BEFORE_ACTION; /* set up yytext again */ 887 | YY_RULE_SETUP 888 | #line 55 "NSPlistLexer.l" 889 | // eat up comment 890 | YY_BREAK 891 | case 2: 892 | YY_RULE_SETUP 893 | #line 57 "NSPlistLexer.l" 894 | BEGIN(COMMENT); 895 | YY_BREAK 896 | case 3: 897 | YY_RULE_SETUP 898 | #line 58 "NSPlistLexer.l" 899 | BEGIN(INITIAL); 900 | YY_BREAK 901 | case 4: 902 | /* rule 4 can match eol */ 903 | YY_RULE_SETUP 904 | #line 59 "NSPlistLexer.l" 905 | // eat comment in chunks 906 | YY_BREAK 907 | case 5: 908 | YY_RULE_SETUP 909 | #line 60 "NSPlistLexer.l" 910 | // eat the lone star 911 | YY_BREAK 912 | case 6: 913 | YY_RULE_SETUP 914 | #line 62 "NSPlistLexer.l" 915 | BEGIN(QUOTED); return LQUOTE; 916 | YY_BREAK 917 | case 7: 918 | YY_RULE_SETUP 919 | #line 63 "NSPlistLexer.l" 920 | BEGIN(INITIAL); return RQUOTE; 921 | YY_BREAK 922 | case 8: 923 | YY_RULE_SETUP 924 | #line 65 "NSPlistLexer.l" 925 | SAVE_TOKEN; return INTEGER; 926 | YY_BREAK 927 | case 9: 928 | YY_RULE_SETUP 929 | #line 67 "NSPlistLexer.l" 930 | SAVE_TOKEN; return REAL; 931 | YY_BREAK 932 | case 10: 933 | YY_RULE_SETUP 934 | #line 69 "NSPlistLexer.l" 935 | SAVE_TOKEN; return HEXSTRING; 936 | YY_BREAK 937 | case 11: 938 | YY_RULE_SETUP 939 | #line 71 "NSPlistLexer.l" 940 | SAVE_TOKEN; return STRING; 941 | YY_BREAK 942 | case 12: 943 | YY_RULE_SETUP 944 | #line 73 "NSPlistLexer.l" 945 | SAVE_TOKEN; return INTEGER; 946 | YY_BREAK 947 | case 13: 948 | YY_RULE_SETUP 949 | #line 75 "NSPlistLexer.l" 950 | SAVE_TOKEN; return REAL; 951 | YY_BREAK 952 | case 14: 953 | YY_RULE_SETUP 954 | #line 77 "NSPlistLexer.l" 955 | SAVE_TOKEN; return DATE; 956 | YY_BREAK 957 | case 15: 958 | /* rule 15 can match eol */ 959 | YY_RULE_SETUP 960 | #line 79 "NSPlistLexer.l" 961 | SAVE_TOKEN; UNESCAPE_STRING; return STRING; 962 | YY_BREAK 963 | case 16: 964 | YY_RULE_SETUP 965 | #line 81 "NSPlistLexer.l" 966 | return LBRACE; 967 | YY_BREAK 968 | case 17: 969 | YY_RULE_SETUP 970 | #line 83 "NSPlistLexer.l" 971 | return RBRACE; 972 | YY_BREAK 973 | case 18: 974 | YY_RULE_SETUP 975 | #line 85 "NSPlistLexer.l" 976 | return LBRACKET; 977 | YY_BREAK 978 | case 19: 979 | YY_RULE_SETUP 980 | #line 87 "NSPlistLexer.l" 981 | return RBRACKET; 982 | YY_BREAK 983 | case 20: 984 | YY_RULE_SETUP 985 | #line 89 "NSPlistLexer.l" 986 | BEGIN(DATABLOCK); return LCHEVRON; 987 | YY_BREAK 988 | case 21: 989 | YY_RULE_SETUP 990 | #line 91 "NSPlistLexer.l" 991 | BEGIN(INITIAL); return RCHEVRON; 992 | YY_BREAK 993 | case 22: 994 | YY_RULE_SETUP 995 | #line 93 "NSPlistLexer.l" 996 | return EQUAL; 997 | YY_BREAK 998 | case 23: 999 | YY_RULE_SETUP 1000 | #line 95 "NSPlistLexer.l" 1001 | return COMMA; 1002 | YY_BREAK 1003 | case 24: 1004 | YY_RULE_SETUP 1005 | #line 97 "NSPlistLexer.l" 1006 | return SEMICOLON; 1007 | YY_BREAK 1008 | case 25: 1009 | /* rule 25 can match eol */ 1010 | YY_RULE_SETUP 1011 | #line 99 "NSPlistLexer.l" 1012 | // eat up whitespace 1013 | YY_BREAK 1014 | case 26: 1015 | YY_RULE_SETUP 1016 | #line 101 "NSPlistLexer.l" 1017 | TERMINATE_LEXER; 1018 | YY_BREAK 1019 | case 27: 1020 | YY_RULE_SETUP 1021 | #line 103 "NSPlistLexer.l" 1022 | ECHO; 1023 | YY_BREAK 1024 | #line 1025 "NSPlistLexer.cpp" 1025 | case YY_STATE_EOF(INITIAL): 1026 | case YY_STATE_EOF(COMMENT): 1027 | case YY_STATE_EOF(QUOTED): 1028 | case YY_STATE_EOF(DATABLOCK): 1029 | yyterminate(); 1030 | 1031 | case YY_END_OF_BUFFER: 1032 | { 1033 | /* Amount of text matched not including the EOB char. */ 1034 | int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; 1035 | 1036 | /* Undo the effects of YY_DO_BEFORE_ACTION. */ 1037 | *yy_cp = (yy_hold_char); 1038 | YY_RESTORE_YY_MORE_OFFSET 1039 | 1040 | if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) 1041 | { 1042 | /* We're scanning a new file or input source. It's 1043 | * possible that this happened because the user 1044 | * just pointed yyin at a new source and called 1045 | * yylex(). If so, then we have to assure 1046 | * consistency between YY_CURRENT_BUFFER and our 1047 | * globals. Here is the right place to do so, because 1048 | * this is the first action (other than possibly a 1049 | * back-up) that will match for the new input source. 1050 | */ 1051 | (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; 1052 | YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; 1053 | YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; 1054 | } 1055 | 1056 | /* Note that here we test for yy_c_buf_p "<=" to the position 1057 | * of the first EOB in the buffer, since yy_c_buf_p will 1058 | * already have been incremented past the NUL character 1059 | * (since all states make transitions on EOB to the 1060 | * end-of-buffer state). Contrast this with the test 1061 | * in input(). 1062 | */ 1063 | if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) 1064 | { /* This was really a NUL. */ 1065 | yy_state_type yy_next_state; 1066 | 1067 | (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; 1068 | 1069 | yy_current_state = yy_get_previous_state( ); 1070 | 1071 | /* Okay, we're now positioned to make the NUL 1072 | * transition. We couldn't have 1073 | * yy_get_previous_state() go ahead and do it 1074 | * for us because it doesn't know how to deal 1075 | * with the possibility of jamming (and we don't 1076 | * want to build jamming into it because then it 1077 | * will run more slowly). 1078 | */ 1079 | 1080 | yy_next_state = yy_try_NUL_trans( yy_current_state ); 1081 | 1082 | yy_bp = (yytext_ptr) + YY_MORE_ADJ; 1083 | 1084 | if ( yy_next_state ) 1085 | { 1086 | /* Consume the NUL. */ 1087 | yy_cp = ++(yy_c_buf_p); 1088 | yy_current_state = yy_next_state; 1089 | goto yy_match; 1090 | } 1091 | 1092 | else 1093 | { 1094 | yy_cp = (yy_last_accepting_cpos); 1095 | yy_current_state = (yy_last_accepting_state); 1096 | goto yy_find_action; 1097 | } 1098 | } 1099 | 1100 | else switch ( yy_get_next_buffer( ) ) 1101 | { 1102 | case EOB_ACT_END_OF_FILE: 1103 | { 1104 | (yy_did_buffer_switch_on_eof) = 0; 1105 | 1106 | if ( yywrap( ) ) 1107 | { 1108 | /* Note: because we've taken care in 1109 | * yy_get_next_buffer() to have set up 1110 | * yytext, we can now set up 1111 | * yy_c_buf_p so that if some total 1112 | * hoser (like flex itself) wants to 1113 | * call the scanner after we return the 1114 | * YY_NULL, it'll still work - another 1115 | * YY_NULL will get returned. 1116 | */ 1117 | (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; 1118 | 1119 | yy_act = YY_STATE_EOF(YY_START); 1120 | goto do_action; 1121 | } 1122 | 1123 | else 1124 | { 1125 | if ( ! (yy_did_buffer_switch_on_eof) ) 1126 | YY_NEW_FILE; 1127 | } 1128 | break; 1129 | } 1130 | 1131 | case EOB_ACT_CONTINUE_SCAN: 1132 | (yy_c_buf_p) = 1133 | (yytext_ptr) + yy_amount_of_matched_text; 1134 | 1135 | yy_current_state = yy_get_previous_state( ); 1136 | 1137 | yy_cp = (yy_c_buf_p); 1138 | yy_bp = (yytext_ptr) + YY_MORE_ADJ; 1139 | goto yy_match; 1140 | 1141 | case EOB_ACT_LAST_MATCH: 1142 | (yy_c_buf_p) = 1143 | &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; 1144 | 1145 | yy_current_state = yy_get_previous_state( ); 1146 | 1147 | yy_cp = (yy_c_buf_p); 1148 | yy_bp = (yytext_ptr) + YY_MORE_ADJ; 1149 | goto yy_find_action; 1150 | } 1151 | break; 1152 | } 1153 | 1154 | default: 1155 | YY_FATAL_ERROR( 1156 | "fatal flex scanner internal error--no action found" ); 1157 | } /* end of action switch */ 1158 | } /* end of scanning one token */ 1159 | } /* end of yylex */ 1160 | 1161 | /* yy_get_next_buffer - try to read in a new buffer 1162 | * 1163 | * Returns a code representing an action: 1164 | * EOB_ACT_LAST_MATCH - 1165 | * EOB_ACT_CONTINUE_SCAN - continue scanning from current position 1166 | * EOB_ACT_END_OF_FILE - end of file 1167 | */ 1168 | static int yy_get_next_buffer (void) 1169 | { 1170 | register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; 1171 | register char *source = (yytext_ptr); 1172 | register int number_to_move, i; 1173 | int ret_val; 1174 | 1175 | if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) 1176 | YY_FATAL_ERROR( 1177 | "fatal flex scanner internal error--end of buffer missed" ); 1178 | 1179 | if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) 1180 | { /* Don't try to fill the buffer, so this is an EOF. */ 1181 | if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) 1182 | { 1183 | /* We matched a single character, the EOB, so 1184 | * treat this as a final EOF. 1185 | */ 1186 | return EOB_ACT_END_OF_FILE; 1187 | } 1188 | 1189 | else 1190 | { 1191 | /* We matched some text prior to the EOB, first 1192 | * process it. 1193 | */ 1194 | return EOB_ACT_LAST_MATCH; 1195 | } 1196 | } 1197 | 1198 | /* Try to read more data. */ 1199 | 1200 | /* First move last chars to start of buffer. */ 1201 | number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; 1202 | 1203 | for ( i = 0; i < number_to_move; ++i ) 1204 | *(dest++) = *(source++); 1205 | 1206 | if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) 1207 | /* don't do the read, it's not guaranteed to return an EOF, 1208 | * just force an EOF 1209 | */ 1210 | YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; 1211 | 1212 | else 1213 | { 1214 | yy_size_t num_to_read = 1215 | YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; 1216 | 1217 | while ( num_to_read <= 0 ) 1218 | { /* Not enough room in the buffer - grow it. */ 1219 | 1220 | /* just a shorter name for the current buffer */ 1221 | YY_BUFFER_STATE b = YY_CURRENT_BUFFER; 1222 | 1223 | int yy_c_buf_p_offset = 1224 | (int) ((yy_c_buf_p) - b->yy_ch_buf); 1225 | 1226 | if ( b->yy_is_our_buffer ) 1227 | { 1228 | yy_size_t new_size = b->yy_buf_size * 2; 1229 | 1230 | if ( new_size <= 0 ) 1231 | b->yy_buf_size += b->yy_buf_size / 8; 1232 | else 1233 | b->yy_buf_size *= 2; 1234 | 1235 | b->yy_ch_buf = (char *) 1236 | /* Include room in for 2 EOB chars. */ 1237 | yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); 1238 | } 1239 | else 1240 | /* Can't grow it, we don't own it. */ 1241 | b->yy_ch_buf = 0; 1242 | 1243 | if ( ! b->yy_ch_buf ) 1244 | YY_FATAL_ERROR( 1245 | "fatal error - scanner input buffer overflow" ); 1246 | 1247 | (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; 1248 | 1249 | num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - 1250 | number_to_move - 1; 1251 | 1252 | } 1253 | 1254 | if ( num_to_read > YY_READ_BUF_SIZE ) 1255 | num_to_read = YY_READ_BUF_SIZE; 1256 | 1257 | /* Read in more data. */ 1258 | YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), 1259 | (yy_n_chars), num_to_read ); 1260 | 1261 | YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); 1262 | } 1263 | 1264 | if ( (yy_n_chars) == 0 ) 1265 | { 1266 | if ( number_to_move == YY_MORE_ADJ ) 1267 | { 1268 | ret_val = EOB_ACT_END_OF_FILE; 1269 | yyrestart(yyin ); 1270 | } 1271 | 1272 | else 1273 | { 1274 | ret_val = EOB_ACT_LAST_MATCH; 1275 | YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = 1276 | YY_BUFFER_EOF_PENDING; 1277 | } 1278 | } 1279 | 1280 | else 1281 | ret_val = EOB_ACT_CONTINUE_SCAN; 1282 | 1283 | if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { 1284 | /* Extend the array by 50%, plus the number we really need. */ 1285 | yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); 1286 | YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); 1287 | if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) 1288 | YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); 1289 | } 1290 | 1291 | (yy_n_chars) += number_to_move; 1292 | YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; 1293 | YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; 1294 | 1295 | (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; 1296 | 1297 | return ret_val; 1298 | } 1299 | 1300 | /* yy_get_previous_state - get the state just before the EOB char was reached */ 1301 | 1302 | static yy_state_type yy_get_previous_state (void) 1303 | { 1304 | register yy_state_type yy_current_state; 1305 | register char *yy_cp; 1306 | 1307 | yy_current_state = (yy_start); 1308 | 1309 | for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) 1310 | { 1311 | register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); 1312 | if ( yy_accept[yy_current_state] ) 1313 | { 1314 | (yy_last_accepting_state) = yy_current_state; 1315 | (yy_last_accepting_cpos) = yy_cp; 1316 | } 1317 | while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) 1318 | { 1319 | yy_current_state = (int) yy_def[yy_current_state]; 1320 | if ( yy_current_state >= 84 ) 1321 | yy_c = yy_meta[(unsigned int) yy_c]; 1322 | } 1323 | yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; 1324 | } 1325 | 1326 | return yy_current_state; 1327 | } 1328 | 1329 | /* yy_try_NUL_trans - try to make a transition on the NUL character 1330 | * 1331 | * synopsis 1332 | * next_state = yy_try_NUL_trans( current_state ); 1333 | */ 1334 | static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) 1335 | { 1336 | register int yy_is_jam; 1337 | register char *yy_cp = (yy_c_buf_p); 1338 | 1339 | register YY_CHAR yy_c = 1; 1340 | if ( yy_accept[yy_current_state] ) 1341 | { 1342 | (yy_last_accepting_state) = yy_current_state; 1343 | (yy_last_accepting_cpos) = yy_cp; 1344 | } 1345 | while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) 1346 | { 1347 | yy_current_state = (int) yy_def[yy_current_state]; 1348 | if ( yy_current_state >= 84 ) 1349 | yy_c = yy_meta[(unsigned int) yy_c]; 1350 | } 1351 | yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; 1352 | yy_is_jam = (yy_current_state == 83); 1353 | 1354 | return yy_is_jam ? 0 : yy_current_state; 1355 | } 1356 | 1357 | static void yyunput (int c, register char * yy_bp ) 1358 | { 1359 | register char *yy_cp; 1360 | 1361 | yy_cp = (yy_c_buf_p); 1362 | 1363 | /* undo effects of setting up yytext */ 1364 | *yy_cp = (yy_hold_char); 1365 | 1366 | if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) 1367 | { /* need to shift things up to make room */ 1368 | /* +2 for EOB chars. */ 1369 | register yy_size_t number_to_move = (yy_n_chars) + 2; 1370 | register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ 1371 | YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; 1372 | register char *source = 1373 | &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; 1374 | 1375 | while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) 1376 | *--dest = *--source; 1377 | 1378 | yy_cp += (int) (dest - source); 1379 | yy_bp += (int) (dest - source); 1380 | YY_CURRENT_BUFFER_LVALUE->yy_n_chars = 1381 | (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; 1382 | 1383 | if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) 1384 | YY_FATAL_ERROR( "flex scanner push-back overflow" ); 1385 | } 1386 | 1387 | *--yy_cp = (char) c; 1388 | 1389 | if ( c == '\n' ){ 1390 | --yylineno; 1391 | } 1392 | 1393 | (yytext_ptr) = yy_bp; 1394 | (yy_hold_char) = *yy_cp; 1395 | (yy_c_buf_p) = yy_cp; 1396 | } 1397 | 1398 | #ifndef YY_NO_INPUT 1399 | #ifdef __cplusplus 1400 | static int yyinput (void) 1401 | #else 1402 | static int input (void) 1403 | #endif 1404 | 1405 | { 1406 | int c; 1407 | 1408 | *(yy_c_buf_p) = (yy_hold_char); 1409 | 1410 | if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) 1411 | { 1412 | /* yy_c_buf_p now points to the character we want to return. 1413 | * If this occurs *before* the EOB characters, then it's a 1414 | * valid NUL; if not, then we've hit the end of the buffer. 1415 | */ 1416 | if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) 1417 | /* This was really a NUL. */ 1418 | *(yy_c_buf_p) = '\0'; 1419 | 1420 | else 1421 | { /* need more input */ 1422 | yy_size_t offset = (yy_c_buf_p) - (yytext_ptr); 1423 | ++(yy_c_buf_p); 1424 | 1425 | switch ( yy_get_next_buffer( ) ) 1426 | { 1427 | case EOB_ACT_LAST_MATCH: 1428 | /* This happens because yy_g_n_b() 1429 | * sees that we've accumulated a 1430 | * token and flags that we need to 1431 | * try matching the token before 1432 | * proceeding. But for input(), 1433 | * there's no matching to consider. 1434 | * So convert the EOB_ACT_LAST_MATCH 1435 | * to EOB_ACT_END_OF_FILE. 1436 | */ 1437 | 1438 | /* Reset buffer status. */ 1439 | yyrestart(yyin ); 1440 | 1441 | /*FALLTHROUGH*/ 1442 | 1443 | case EOB_ACT_END_OF_FILE: 1444 | { 1445 | if ( yywrap( ) ) 1446 | return 0; 1447 | 1448 | if ( ! (yy_did_buffer_switch_on_eof) ) 1449 | YY_NEW_FILE; 1450 | #ifdef __cplusplus 1451 | return yyinput(); 1452 | #else 1453 | return input(); 1454 | #endif 1455 | } 1456 | 1457 | case EOB_ACT_CONTINUE_SCAN: 1458 | (yy_c_buf_p) = (yytext_ptr) + offset; 1459 | break; 1460 | } 1461 | } 1462 | } 1463 | 1464 | c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ 1465 | *(yy_c_buf_p) = '\0'; /* preserve yytext */ 1466 | (yy_hold_char) = *++(yy_c_buf_p); 1467 | 1468 | if ( c == '\n' ) 1469 | 1470 | yylineno++; 1471 | ; 1472 | 1473 | return c; 1474 | } 1475 | #endif /* ifndef YY_NO_INPUT */ 1476 | 1477 | /** Immediately switch to a different input stream. 1478 | * @param input_file A readable stream. 1479 | * 1480 | * @note This function does not reset the start condition to @c INITIAL . 1481 | */ 1482 | void yyrestart (FILE * input_file ) 1483 | { 1484 | 1485 | if ( ! YY_CURRENT_BUFFER ){ 1486 | yyensure_buffer_stack (); 1487 | YY_CURRENT_BUFFER_LVALUE = 1488 | yy_create_buffer(yyin,YY_BUF_SIZE ); 1489 | } 1490 | 1491 | yy_init_buffer(YY_CURRENT_BUFFER,input_file ); 1492 | yy_load_buffer_state( ); 1493 | } 1494 | 1495 | /** Switch to a different input buffer. 1496 | * @param new_buffer The new input buffer. 1497 | * 1498 | */ 1499 | void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) 1500 | { 1501 | 1502 | /* TODO. We should be able to replace this entire function body 1503 | * with 1504 | * yypop_buffer_state(); 1505 | * yypush_buffer_state(new_buffer); 1506 | */ 1507 | yyensure_buffer_stack (); 1508 | if ( YY_CURRENT_BUFFER == new_buffer ) 1509 | return; 1510 | 1511 | if ( YY_CURRENT_BUFFER ) 1512 | { 1513 | /* Flush out information for old buffer. */ 1514 | *(yy_c_buf_p) = (yy_hold_char); 1515 | YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); 1516 | YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); 1517 | } 1518 | 1519 | YY_CURRENT_BUFFER_LVALUE = new_buffer; 1520 | yy_load_buffer_state( ); 1521 | 1522 | /* We don't actually know whether we did this switch during 1523 | * EOF (yywrap()) processing, but the only time this flag 1524 | * is looked at is after yywrap() is called, so it's safe 1525 | * to go ahead and always set it. 1526 | */ 1527 | (yy_did_buffer_switch_on_eof) = 1; 1528 | } 1529 | 1530 | static void yy_load_buffer_state (void) 1531 | { 1532 | (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; 1533 | (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; 1534 | yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; 1535 | (yy_hold_char) = *(yy_c_buf_p); 1536 | } 1537 | 1538 | /** Allocate and initialize an input buffer state. 1539 | * @param file A readable stream. 1540 | * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. 1541 | * 1542 | * @return the allocated buffer state. 1543 | */ 1544 | YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) 1545 | { 1546 | YY_BUFFER_STATE b; 1547 | 1548 | b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); 1549 | if ( ! b ) 1550 | YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); 1551 | 1552 | b->yy_buf_size = size; 1553 | 1554 | /* yy_ch_buf has to be 2 characters longer than the size given because 1555 | * we need to put in 2 end-of-buffer characters. 1556 | */ 1557 | b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ); 1558 | if ( ! b->yy_ch_buf ) 1559 | YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); 1560 | 1561 | b->yy_is_our_buffer = 1; 1562 | 1563 | yy_init_buffer(b,file ); 1564 | 1565 | return b; 1566 | } 1567 | 1568 | /** Destroy the buffer. 1569 | * @param b a buffer created with yy_create_buffer() 1570 | * 1571 | */ 1572 | void yy_delete_buffer (YY_BUFFER_STATE b ) 1573 | { 1574 | 1575 | if ( ! b ) 1576 | return; 1577 | 1578 | if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ 1579 | YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; 1580 | 1581 | if ( b->yy_is_our_buffer ) 1582 | yyfree((void *) b->yy_ch_buf ); 1583 | 1584 | yyfree((void *) b ); 1585 | } 1586 | 1587 | /* Initializes or reinitializes a buffer. 1588 | * This function is sometimes called more than once on the same buffer, 1589 | * such as during a yyrestart() or at EOF. 1590 | */ 1591 | static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) 1592 | 1593 | { 1594 | int oerrno = errno; 1595 | 1596 | yy_flush_buffer(b ); 1597 | 1598 | b->yy_input_file = file; 1599 | b->yy_fill_buffer = 1; 1600 | 1601 | /* If b is the current buffer, then yy_init_buffer was _probably_ 1602 | * called from yyrestart() or through yy_get_next_buffer. 1603 | * In that case, we don't want to reset the lineno or column. 1604 | */ 1605 | if (b != YY_CURRENT_BUFFER){ 1606 | b->yy_bs_lineno = 1; 1607 | b->yy_bs_column = 0; 1608 | } 1609 | 1610 | b->yy_is_interactive = 0; 1611 | 1612 | errno = oerrno; 1613 | } 1614 | 1615 | /** Discard all buffered characters. On the next scan, YY_INPUT will be called. 1616 | * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. 1617 | * 1618 | */ 1619 | void yy_flush_buffer (YY_BUFFER_STATE b ) 1620 | { 1621 | if ( ! b ) 1622 | return; 1623 | 1624 | b->yy_n_chars = 0; 1625 | 1626 | /* We always need two end-of-buffer characters. The first causes 1627 | * a transition to the end-of-buffer state. The second causes 1628 | * a jam in that state. 1629 | */ 1630 | b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; 1631 | b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; 1632 | 1633 | b->yy_buf_pos = &b->yy_ch_buf[0]; 1634 | 1635 | b->yy_at_bol = 1; 1636 | b->yy_buffer_status = YY_BUFFER_NEW; 1637 | 1638 | if ( b == YY_CURRENT_BUFFER ) 1639 | yy_load_buffer_state( ); 1640 | } 1641 | 1642 | /** Pushes the new state onto the stack. The new state becomes 1643 | * the current state. This function will allocate the stack 1644 | * if necessary. 1645 | * @param new_buffer The new state. 1646 | * 1647 | */ 1648 | void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) 1649 | { 1650 | if (new_buffer == NULL) 1651 | return; 1652 | 1653 | yyensure_buffer_stack(); 1654 | 1655 | /* This block is copied from yy_switch_to_buffer. */ 1656 | if ( YY_CURRENT_BUFFER ) 1657 | { 1658 | /* Flush out information for old buffer. */ 1659 | *(yy_c_buf_p) = (yy_hold_char); 1660 | YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); 1661 | YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); 1662 | } 1663 | 1664 | /* Only push if top exists. Otherwise, replace top. */ 1665 | if (YY_CURRENT_BUFFER) 1666 | (yy_buffer_stack_top)++; 1667 | YY_CURRENT_BUFFER_LVALUE = new_buffer; 1668 | 1669 | /* copied from yy_switch_to_buffer. */ 1670 | yy_load_buffer_state( ); 1671 | (yy_did_buffer_switch_on_eof) = 1; 1672 | } 1673 | 1674 | /** Removes and deletes the top of the stack, if present. 1675 | * The next element becomes the new top. 1676 | * 1677 | */ 1678 | void yypop_buffer_state (void) 1679 | { 1680 | if (!YY_CURRENT_BUFFER) 1681 | return; 1682 | 1683 | yy_delete_buffer(YY_CURRENT_BUFFER ); 1684 | YY_CURRENT_BUFFER_LVALUE = NULL; 1685 | if ((yy_buffer_stack_top) > 0) 1686 | --(yy_buffer_stack_top); 1687 | 1688 | if (YY_CURRENT_BUFFER) { 1689 | yy_load_buffer_state( ); 1690 | (yy_did_buffer_switch_on_eof) = 1; 1691 | } 1692 | } 1693 | 1694 | /* Allocates the stack if it does not exist. 1695 | * Guarantees space for at least one push. 1696 | */ 1697 | static void yyensure_buffer_stack (void) 1698 | { 1699 | yy_size_t num_to_alloc; 1700 | 1701 | if (!(yy_buffer_stack)) { 1702 | 1703 | /* First allocation is just for 2 elements, since we don't know if this 1704 | * scanner will even need a stack. We use 2 instead of 1 to avoid an 1705 | * immediate realloc on the next call. 1706 | */ 1707 | num_to_alloc = 1; 1708 | (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc 1709 | (num_to_alloc * sizeof(struct yy_buffer_state*) 1710 | ); 1711 | if ( ! (yy_buffer_stack) ) 1712 | YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); 1713 | 1714 | memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); 1715 | 1716 | (yy_buffer_stack_max) = num_to_alloc; 1717 | (yy_buffer_stack_top) = 0; 1718 | return; 1719 | } 1720 | 1721 | if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ 1722 | 1723 | /* Increase the buffer to prepare for a possible push. */ 1724 | int grow_size = 8 /* arbitrary grow size */; 1725 | 1726 | num_to_alloc = (yy_buffer_stack_max) + grow_size; 1727 | (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc 1728 | ((yy_buffer_stack), 1729 | num_to_alloc * sizeof(struct yy_buffer_state*) 1730 | ); 1731 | if ( ! (yy_buffer_stack) ) 1732 | YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); 1733 | 1734 | /* zero only the new slots.*/ 1735 | memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); 1736 | (yy_buffer_stack_max) = num_to_alloc; 1737 | } 1738 | } 1739 | 1740 | /** Setup the input buffer state to scan directly from a user-specified character buffer. 1741 | * @param base the character buffer 1742 | * @param size the size in bytes of the character buffer 1743 | * 1744 | * @return the newly allocated buffer state object. 1745 | */ 1746 | YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) 1747 | { 1748 | YY_BUFFER_STATE b; 1749 | 1750 | if ( size < 2 || 1751 | base[size-2] != YY_END_OF_BUFFER_CHAR || 1752 | base[size-1] != YY_END_OF_BUFFER_CHAR ) 1753 | /* They forgot to leave room for the EOB's. */ 1754 | return 0; 1755 | 1756 | b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); 1757 | if ( ! b ) 1758 | YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); 1759 | 1760 | b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ 1761 | b->yy_buf_pos = b->yy_ch_buf = base; 1762 | b->yy_is_our_buffer = 0; 1763 | b->yy_input_file = 0; 1764 | b->yy_n_chars = b->yy_buf_size; 1765 | b->yy_is_interactive = 0; 1766 | b->yy_at_bol = 1; 1767 | b->yy_fill_buffer = 0; 1768 | b->yy_buffer_status = YY_BUFFER_NEW; 1769 | 1770 | yy_switch_to_buffer(b ); 1771 | 1772 | return b; 1773 | } 1774 | 1775 | /** Setup the input buffer state to scan a string. The next call to yylex() will 1776 | * scan from a @e copy of @a str. 1777 | * @param yystr a NUL-terminated string to scan 1778 | * 1779 | * @return the newly allocated buffer state object. 1780 | * @note If you want to scan bytes that may contain NUL values, then use 1781 | * yy_scan_bytes() instead. 1782 | */ 1783 | YY_BUFFER_STATE yy_scan_string (yyconst char * yystr ) 1784 | { 1785 | 1786 | return yy_scan_bytes(yystr,strlen(yystr) ); 1787 | } 1788 | 1789 | /** Setup the input buffer state to scan the given bytes. The next call to yylex() will 1790 | * scan from a @e copy of @a bytes. 1791 | * @param bytes the byte buffer to scan 1792 | * @param len the number of bytes in the buffer pointed to by @a bytes. 1793 | * 1794 | * @return the newly allocated buffer state object. 1795 | */ 1796 | YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len ) 1797 | { 1798 | YY_BUFFER_STATE b; 1799 | char *buf; 1800 | yy_size_t n, i; 1801 | 1802 | /* Get memory for full buffer, including space for trailing EOB's. */ 1803 | n = _yybytes_len + 2; 1804 | buf = (char *) yyalloc(n ); 1805 | if ( ! buf ) 1806 | YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); 1807 | 1808 | for ( i = 0; i < _yybytes_len; ++i ) 1809 | buf[i] = yybytes[i]; 1810 | 1811 | buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; 1812 | 1813 | b = yy_scan_buffer(buf,n ); 1814 | if ( ! b ) 1815 | YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); 1816 | 1817 | /* It's okay to grow etc. this buffer, and we should throw it 1818 | * away when we're done. 1819 | */ 1820 | b->yy_is_our_buffer = 1; 1821 | 1822 | return b; 1823 | } 1824 | 1825 | #ifndef YY_EXIT_FAILURE 1826 | #define YY_EXIT_FAILURE 2 1827 | #endif 1828 | 1829 | static void yy_fatal_error (yyconst char* msg ) 1830 | { 1831 | (void) fprintf( stderr, "%s\n", msg ); 1832 | exit( YY_EXIT_FAILURE ); 1833 | } 1834 | 1835 | /* Redefine yyless() so it works in section 3 code. */ 1836 | 1837 | #undef yyless 1838 | #define yyless(n) \ 1839 | do \ 1840 | { \ 1841 | /* Undo effects of setting up yytext. */ \ 1842 | int yyless_macro_arg = (n); \ 1843 | YY_LESS_LINENO(yyless_macro_arg);\ 1844 | yytext[yyleng] = (yy_hold_char); \ 1845 | (yy_c_buf_p) = yytext + yyless_macro_arg; \ 1846 | (yy_hold_char) = *(yy_c_buf_p); \ 1847 | *(yy_c_buf_p) = '\0'; \ 1848 | yyleng = yyless_macro_arg; \ 1849 | } \ 1850 | while ( 0 ) 1851 | 1852 | /* Accessor methods (get/set functions) to struct members. */ 1853 | 1854 | /** Get the current line number. 1855 | * 1856 | */ 1857 | int yyget_lineno (void) 1858 | { 1859 | 1860 | return yylineno; 1861 | } 1862 | 1863 | /** Get the input stream. 1864 | * 1865 | */ 1866 | FILE *yyget_in (void) 1867 | { 1868 | return yyin; 1869 | } 1870 | 1871 | /** Get the output stream. 1872 | * 1873 | */ 1874 | FILE *yyget_out (void) 1875 | { 1876 | return yyout; 1877 | } 1878 | 1879 | /** Get the length of the current token. 1880 | * 1881 | */ 1882 | yy_size_t yyget_leng (void) 1883 | { 1884 | return yyleng; 1885 | } 1886 | 1887 | /** Get the current token. 1888 | * 1889 | */ 1890 | 1891 | char *yyget_text (void) 1892 | { 1893 | return yytext; 1894 | } 1895 | 1896 | /** Set the current line number. 1897 | * @param line_number 1898 | * 1899 | */ 1900 | void yyset_lineno (int line_number ) 1901 | { 1902 | 1903 | yylineno = line_number; 1904 | } 1905 | 1906 | /** Set the input stream. This does not discard the current 1907 | * input buffer. 1908 | * @param in_str A readable stream. 1909 | * 1910 | * @see yy_switch_to_buffer 1911 | */ 1912 | void yyset_in (FILE * in_str ) 1913 | { 1914 | yyin = in_str ; 1915 | } 1916 | 1917 | void yyset_out (FILE * out_str ) 1918 | { 1919 | yyout = out_str ; 1920 | } 1921 | 1922 | int yyget_debug (void) 1923 | { 1924 | return yy_flex_debug; 1925 | } 1926 | 1927 | void yyset_debug (int bdebug ) 1928 | { 1929 | yy_flex_debug = bdebug ; 1930 | } 1931 | 1932 | static int yy_init_globals (void) 1933 | { 1934 | /* Initialization is the same as for the non-reentrant scanner. 1935 | * This function is called from yylex_destroy(), so don't allocate here. 1936 | */ 1937 | 1938 | /* We do not touch yylineno unless the option is enabled. */ 1939 | yylineno = 1; 1940 | 1941 | (yy_buffer_stack) = 0; 1942 | (yy_buffer_stack_top) = 0; 1943 | (yy_buffer_stack_max) = 0; 1944 | (yy_c_buf_p) = (char *) 0; 1945 | (yy_init) = 0; 1946 | (yy_start) = 0; 1947 | 1948 | /* Defined in main.c */ 1949 | #ifdef YY_STDINIT 1950 | yyin = stdin; 1951 | yyout = stdout; 1952 | #else 1953 | yyin = (FILE *) 0; 1954 | yyout = (FILE *) 0; 1955 | #endif 1956 | 1957 | /* For future reference: Set errno on error, since we are called by 1958 | * yylex_init() 1959 | */ 1960 | return 0; 1961 | } 1962 | 1963 | /* yylex_destroy is for both reentrant and non-reentrant scanners. */ 1964 | int yylex_destroy (void) 1965 | { 1966 | 1967 | /* Pop the buffer stack, destroying each element. */ 1968 | while(YY_CURRENT_BUFFER){ 1969 | yy_delete_buffer(YY_CURRENT_BUFFER ); 1970 | YY_CURRENT_BUFFER_LVALUE = NULL; 1971 | yypop_buffer_state(); 1972 | } 1973 | 1974 | /* Destroy the stack itself. */ 1975 | yyfree((yy_buffer_stack) ); 1976 | (yy_buffer_stack) = NULL; 1977 | 1978 | /* Reset the globals. This is important in a non-reentrant scanner so the next time 1979 | * yylex() is called, initialization will occur. */ 1980 | yy_init_globals( ); 1981 | 1982 | return 0; 1983 | } 1984 | 1985 | /* 1986 | * Internal utility routines. 1987 | */ 1988 | 1989 | #ifndef yytext_ptr 1990 | static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) 1991 | { 1992 | register int i; 1993 | for ( i = 0; i < n; ++i ) 1994 | s1[i] = s2[i]; 1995 | } 1996 | #endif 1997 | 1998 | #ifdef YY_NEED_STRLEN 1999 | static int yy_flex_strlen (yyconst char * s ) 2000 | { 2001 | register int n; 2002 | for ( n = 0; s[n]; ++n ) 2003 | ; 2004 | 2005 | return n; 2006 | } 2007 | #endif 2008 | 2009 | void *yyalloc (yy_size_t size ) 2010 | { 2011 | return (void *) malloc( size ); 2012 | } 2013 | 2014 | void *yyrealloc (void * ptr, yy_size_t size ) 2015 | { 2016 | /* The cast to (char *) in the following accommodates both 2017 | * implementations that use char* generic pointers, and those 2018 | * that use void* generic pointers. It works with the latter 2019 | * because both ANSI C and C++ allow castless assignment from 2020 | * any pointer type to void*, and deal with argument conversions 2021 | * as though doing an assignment. 2022 | */ 2023 | return (void *) realloc( (char *) ptr, size ); 2024 | } 2025 | 2026 | void yyfree (void * ptr ) 2027 | { 2028 | free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ 2029 | } 2030 | 2031 | #define YYTABLES_NAME "yytables" 2032 | 2033 | #line 103 "NSPlistLexer.l" 2034 | 2035 | 2036 | 2037 | -------------------------------------------------------------------------------- /src/NSPlistLexer.l: -------------------------------------------------------------------------------- 1 | //****************************************************************************** 2 | // 3 | // Copyright (c) 2015 Microsoft Corporation. All rights reserved. 4 | // 5 | // This code is licensed under the MIT License (MIT). 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 8 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 9 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 10 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 11 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 12 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 13 | // THE SOFTWARE. 14 | // 15 | //****************************************************************************** 16 | 17 | %{ 18 | #include "NSPlist.h" 19 | #include "NSPlistParser.h" 20 | #define SAVE_TOKEN yylval.string = strdup(yytext) 21 | #define UNESCAPE_STRING processEscapes(yylval.string) 22 | 23 | #ifdef DEBUG_NSPARSER 24 | #define TERMINATE_LEXER printf("Unrecognized character: %s\n", yytext); yyterminate(); 25 | #else 26 | #define TERMINATE_LEXER yyterminate(); 27 | #endif 28 | 29 | static char getUnescapedChar(char c) 30 | { 31 | switch (c) { 32 | case 't': return '\t'; 33 | case 'r': return '\r'; 34 | case 'n': return '\n'; 35 | default: return c; 36 | } 37 | } 38 | 39 | static void processEscapes(char *data) 40 | { 41 | unsigned s = 0; /* scanning index */ 42 | unsigned w = 0; /* write-back index */ 43 | char p = 0; /* previous character */ 44 | char c = 0; /* current character */ 45 | 46 | while ((c = data[s++]) != '\0') { 47 | if (p == '\\') { 48 | data[w++] = getUnescapedChar(c); 49 | } else if (c != '\\') { 50 | data[w++] = c; 51 | } 52 | p = c; 53 | } 54 | data[w] = '\0'; 55 | } 56 | 57 | %} 58 | 59 | %option noyywrap 60 | %option yylineno 61 | %option nounistd 62 | %option never-interactive 63 | %x COMMENT 64 | %x QUOTED 65 | %x DATABLOCK 66 | 67 | D [0-9] 68 | 69 | %% 70 | 71 | \/\/.*$ // eat up comment 72 | 73 | "/*" BEGIN(COMMENT); 74 | "*/" BEGIN(INITIAL); 75 | [^*]+ // eat comment in chunks 76 | "*" // eat the lone star 77 | 78 | \" BEGIN(QUOTED); return LQUOTE; 79 | \" BEGIN(INITIAL); return RQUOTE; 80 | 81 | [-]?{D}+ SAVE_TOKEN; return INTEGER; 82 | 83 | -?{D}*\.?{D}+([eE][-]?{D}+)? SAVE_TOKEN; return REAL; 84 | 85 | ([0-9a-fA-F]{2})+ SAVE_TOKEN; return HEXSTRING; 86 | 87 | [0-9a-zA-Z_\-\.\$\/]+ SAVE_TOKEN; return STRING; 88 | 89 | [+-]?{D}+ SAVE_TOKEN; return INTEGER; 90 | 91 | [+-]?{D}*\.?{D}+([eE][+-]?{D}+)? SAVE_TOKEN; return REAL; 92 | 93 | ({D}{4})(-({D}{2}){2})T({D}{2})(:({D}{2}){2})Z SAVE_TOKEN; return DATE; 94 | 95 | (\\.|[^"\\])* SAVE_TOKEN; UNESCAPE_STRING; return STRING; 96 | 97 | \{ return LBRACE; 98 | 99 | \} return RBRACE; 100 | 101 | \( return LBRACKET; 102 | 103 | \) return RBRACKET; 104 | 105 | \< BEGIN(DATABLOCK); return LCHEVRON; 106 | 107 | \> BEGIN(INITIAL); return RCHEVRON; 108 | 109 | = return EQUAL; 110 | 111 | , return COMMA; 112 | 113 | ; return SEMICOLON; 114 | 115 | [ \t\r\n]+ // eat up whitespace 116 | 117 | <*>. TERMINATE_LEXER; 118 | 119 | %% 120 | -------------------------------------------------------------------------------- /src/NSPlistParser.cpp: -------------------------------------------------------------------------------- 1 | /* original parser id follows */ 2 | /* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */ 3 | /* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */ 4 | 5 | #define YYBYACC 1 6 | #define YYMAJOR 1 7 | #define YYMINOR 9 8 | #define YYPATCH 20140422 9 | 10 | #define YYEMPTY (-1) 11 | #define yyclearin (yychar = YYEMPTY) 12 | #define yyerrok (yyerrflag = 0) 13 | #define YYRECOVERING() (yyerrflag != 0) 14 | #define YYENOMEM (-2) 15 | #define YYEOF 0 16 | #define YYPREFIX "yy" 17 | 18 | #define YYPURE 0 19 | 20 | #line 2 "NSPlistParser.y" 21 | #include 22 | #include "NSPlist.h" 23 | 24 | typedef struct yy_buffer_state* YY_BUFFER_STATE; 25 | extern YY_BUFFER_STATE yy_scan_string(const char* str); 26 | extern void yy_delete_buffer(YY_BUFFER_STATE buffer); 27 | extern int yyparse(); 28 | extern FILE* yyin; 29 | extern int yylineno; 30 | 31 | int yylex(); 32 | 33 | static NSPlistValue *plistVal; 34 | 35 | 36 | void yyerror(const char* s) 37 | { 38 | #ifdef DEBUG_NSPARSER 39 | printf("ERROR: %s, line %d\n", s, yylineno); 40 | #endif 41 | } 42 | 43 | bool loadPlistFromBuffer(const char* byteArray, NSPlistValue*& plist) 44 | { 45 | plistVal = NULL; 46 | 47 | YY_BUFFER_STATE buf = yy_scan_string(byteArray); 48 | int result = yyparse(); 49 | yy_delete_buffer(buf); 50 | 51 | if (!result) { 52 | plist = plistVal; 53 | } else { 54 | delete plistVal; 55 | plist = NULL; 56 | } 57 | 58 | return !result; 59 | } 60 | 61 | bool loadPlistFromFile(const char* filePath, NSPlistValue*& plist) 62 | { 63 | plistVal = NULL; 64 | int result = -1; 65 | 66 | yyin = fopen(filePath, "r"); 67 | if (yyin) { 68 | result = yyparse(); 69 | fclose(yyin); 70 | } 71 | 72 | if (!result) { 73 | plist = plistVal; 74 | } else { 75 | delete plistVal; 76 | plist = NULL; 77 | } 78 | 79 | return !result; 80 | } 81 | 82 | #line 65 "NSPlistParser.y" 83 | #ifdef YYSTYPE 84 | #undef YYSTYPE_IS_DECLARED 85 | #define YYSTYPE_IS_DECLARED 1 86 | #endif 87 | #ifndef YYSTYPE_IS_DECLARED 88 | #define YYSTYPE_IS_DECLARED 1 89 | typedef union { 90 | NSPlistValue* value; 91 | NSPlistString* string_val; 92 | NSPlistData* data_val; 93 | NSPlistArray* array_val; 94 | NSPlistDictionary* dict_val; 95 | char* string; 96 | } YYSTYPE; 97 | #endif /* !YYSTYPE_IS_DECLARED */ 98 | #line 99 "NSPlistParser.cpp" 99 | 100 | /* compatibility with bison */ 101 | #ifdef YYPARSE_PARAM 102 | /* compatibility with FreeBSD */ 103 | # ifdef YYPARSE_PARAM_TYPE 104 | # define YYPARSE_DECL() yyparse(YYPARSE_PARAM_TYPE YYPARSE_PARAM) 105 | # else 106 | # define YYPARSE_DECL() yyparse(void *YYPARSE_PARAM) 107 | # endif 108 | #else 109 | # define YYPARSE_DECL() yyparse(void) 110 | #endif 111 | 112 | /* Parameters sent to lex. */ 113 | #ifdef YYLEX_PARAM 114 | # define YYLEX_DECL() yylex(void *YYLEX_PARAM) 115 | # define YYLEX yylex(YYLEX_PARAM) 116 | #else 117 | # define YYLEX_DECL() yylex(void) 118 | # define YYLEX yylex() 119 | #endif 120 | 121 | /* Parameters sent to yyerror. */ 122 | #ifndef YYERROR_DECL 123 | #define YYERROR_DECL() yyerror(const char *s) 124 | #endif 125 | #ifndef YYERROR_CALL 126 | #define YYERROR_CALL(msg) yyerror(msg) 127 | #endif 128 | 129 | extern int YYPARSE_DECL(); 130 | 131 | #define INTEGER 257 132 | #define REAL 258 133 | #define DATE 259 134 | #define HEXSTRING 260 135 | #define STRING 261 136 | #define LBRACKET 262 137 | #define RBRACKET 263 138 | #define LBRACE 264 139 | #define RBRACE 265 140 | #define LCHEVRON 266 141 | #define RCHEVRON 267 142 | #define LQUOTE 268 143 | #define RQUOTE 269 144 | #define EQUAL 270 145 | #define COMMA 271 146 | #define SEMICOLON 272 147 | #define YYERRCODE 256 148 | typedef short YYINT; 149 | static const YYINT yylhs[] = { -1, 150 | 0, 3, 4, 4, 5, 5, 5, 6, 6, 7, 151 | 8, 8, 1, 1, 1, 1, 2, 2, 2, 2, 152 | 2, 2, 2, 2, 2, 153 | }; 154 | static const YYINT yylen[] = { 2, 155 | 1, 3, 5, 0, 4, 3, 2, 3, 1, 3, 156 | 2, 0, 1, 1, 1, 1, 1, 3, 1, 3, 157 | 1, 3, 1, 3, 2, 158 | }; 159 | static const YYINT yydefred[] = { 0, 160 | 17, 19, 21, 23, 0, 4, 12, 0, 0, 1, 161 | 16, 13, 14, 15, 7, 9, 0, 0, 0, 0, 162 | 0, 0, 0, 25, 6, 0, 2, 0, 11, 10, 163 | 18, 20, 22, 24, 5, 8, 0, 0, 3, 164 | }; 165 | static const YYINT yydgoto[] = { 9, 166 | 10, 11, 12, 18, 13, 17, 14, 19, 167 | }; 168 | static const YYINT yysindex[] = { -212, 169 | 0, 0, 0, 0, -239, 0, 0, -256, 0, 0, 170 | 0, 0, 0, 0, 0, 0, -259, -251, -219, -260, 171 | -258, -254, -253, 0, 0, -224, 0, -244, 0, 0, 172 | 0, 0, 0, 0, 0, 0, -212, -242, 0, 173 | }; 174 | static const YYINT yyrindex[] = { 0, 175 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 179 | }; 180 | static const YYINT yygindex[] = { 0, 181 | -5, 10, 0, 0, 0, 0, 0, 0, 182 | }; 183 | #define YYTABLESIZE 56 184 | static const YYINT yytable[] = { 16, 185 | 20, 21, 22, 25, 23, 1, 2, 3, 31, 4, 186 | 32, 26, 24, 27, 33, 34, 8, 1, 2, 3, 187 | 36, 4, 5, 15, 6, 37, 7, 28, 8, 39, 188 | 0, 38, 1, 2, 3, 0, 4, 5, 35, 6, 189 | 29, 7, 0, 8, 1, 2, 3, 30, 4, 5, 190 | 0, 6, 0, 7, 0, 8, 191 | }; 192 | static const YYINT yycheck[] = { 5, 193 | 257, 258, 259, 263, 261, 257, 258, 259, 269, 261, 194 | 269, 271, 269, 265, 269, 269, 268, 257, 258, 259, 195 | 26, 261, 262, 263, 264, 270, 266, 18, 268, 272, 196 | -1, 37, 257, 258, 259, -1, 261, 262, 263, 264, 197 | 260, 266, -1, 268, 257, 258, 259, 267, 261, 262, 198 | -1, 264, -1, 266, -1, 268, 199 | }; 200 | #define YYFINAL 9 201 | #ifndef YYDEBUG 202 | #define YYDEBUG 0 203 | #endif 204 | #define YYMAXTOKEN 272 205 | #define YYUNDFTOKEN 283 206 | #define YYTRANSLATE(a) ((a) > YYMAXTOKEN ? YYUNDFTOKEN : (a)) 207 | #if YYDEBUG 208 | static const char *const yyname[] = { 209 | 210 | "end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 211 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 212 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 213 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 214 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 215 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 216 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"INTEGER","REAL","DATE", 217 | "HEXSTRING","STRING","LBRACKET","RBRACKET","LBRACE","RBRACE","LCHEVRON", 218 | "RCHEVRON","LQUOTE","RQUOTE","EQUAL","COMMA","SEMICOLON",0,0,0,0,0,0,0,0,0,0, 219 | "illegal-symbol", 220 | }; 221 | static const char *const yyrule[] = { 222 | "$accept : plist", 223 | "plist : value", 224 | "dictionary : LBRACE assignments RBRACE", 225 | "assignments : assignments keyvalue EQUAL value SEMICOLON", 226 | "assignments :", 227 | "array : LBRACKET values COMMA RBRACKET", 228 | "array : LBRACKET values RBRACKET", 229 | "array : LBRACKET RBRACKET", 230 | "values : values COMMA value", 231 | "values : value", 232 | "data : LCHEVRON hexvalues RCHEVRON", 233 | "hexvalues : hexvalues HEXSTRING", 234 | "hexvalues :", 235 | "value : dictionary", 236 | "value : array", 237 | "value : data", 238 | "value : keyvalue", 239 | "keyvalue : INTEGER", 240 | "keyvalue : LQUOTE INTEGER RQUOTE", 241 | "keyvalue : REAL", 242 | "keyvalue : LQUOTE REAL RQUOTE", 243 | "keyvalue : DATE", 244 | "keyvalue : LQUOTE DATE RQUOTE", 245 | "keyvalue : STRING", 246 | "keyvalue : LQUOTE STRING RQUOTE", 247 | "keyvalue : LQUOTE RQUOTE", 248 | 249 | }; 250 | #endif 251 | 252 | int yydebug; 253 | int yynerrs; 254 | 255 | int yyerrflag; 256 | int yychar; 257 | YYSTYPE yyval; 258 | YYSTYPE yylval; 259 | 260 | /* define the initial stack-sizes */ 261 | #ifdef YYSTACKSIZE 262 | #undef YYMAXDEPTH 263 | #define YYMAXDEPTH YYSTACKSIZE 264 | #else 265 | #ifdef YYMAXDEPTH 266 | #define YYSTACKSIZE YYMAXDEPTH 267 | #else 268 | #define YYSTACKSIZE 10000 269 | #define YYMAXDEPTH 10000 270 | #endif 271 | #endif 272 | 273 | #define YYINITSTACKSIZE 200 274 | 275 | typedef struct { 276 | unsigned stacksize; 277 | YYINT *s_base; 278 | YYINT *s_mark; 279 | YYINT *s_last; 280 | YYSTYPE *l_base; 281 | YYSTYPE *l_mark; 282 | } YYSTACKDATA; 283 | /* variables for the parser stack */ 284 | static YYSTACKDATA yystack; 285 | 286 | #if YYDEBUG 287 | #include /* needed for printf */ 288 | #endif 289 | 290 | #include /* needed for malloc, etc */ 291 | #include /* needed for memset */ 292 | 293 | /* allocate initial stack or double stack size, up to YYMAXDEPTH */ 294 | static int yygrowstack(YYSTACKDATA *data) 295 | { 296 | int i; 297 | unsigned newsize; 298 | YYINT *newss; 299 | YYSTYPE *newvs; 300 | 301 | if ((newsize = data->stacksize) == 0) 302 | newsize = YYINITSTACKSIZE; 303 | else if (newsize >= YYMAXDEPTH) 304 | return YYENOMEM; 305 | else if ((newsize *= 2) > YYMAXDEPTH) 306 | newsize = YYMAXDEPTH; 307 | 308 | i = (int) (data->s_mark - data->s_base); 309 | newss = (YYINT *)realloc(data->s_base, newsize * sizeof(*newss)); 310 | if (newss == 0) 311 | return YYENOMEM; 312 | 313 | data->s_base = newss; 314 | data->s_mark = newss + i; 315 | 316 | newvs = (YYSTYPE *)realloc(data->l_base, newsize * sizeof(*newvs)); 317 | if (newvs == 0) 318 | return YYENOMEM; 319 | 320 | data->l_base = newvs; 321 | data->l_mark = newvs + i; 322 | 323 | data->stacksize = newsize; 324 | data->s_last = data->s_base + newsize - 1; 325 | return 0; 326 | } 327 | 328 | #if YYPURE || defined(YY_NO_LEAKS) 329 | static void yyfreestack(YYSTACKDATA *data) 330 | { 331 | free(data->s_base); 332 | free(data->l_base); 333 | memset(data, 0, sizeof(*data)); 334 | } 335 | #else 336 | #define yyfreestack(data) /* nothing */ 337 | #endif 338 | 339 | #define YYABORT goto yyabort 340 | #define YYREJECT goto yyabort 341 | #define YYACCEPT goto yyaccept 342 | #define YYERROR goto yyerrlab 343 | 344 | int 345 | YYPARSE_DECL() 346 | { 347 | int yym, yyn, yystate; 348 | #if YYDEBUG 349 | const char *yys; 350 | 351 | if ((yys = getenv("YYDEBUG")) != 0) 352 | { 353 | yyn = *yys; 354 | if (yyn >= '0' && yyn <= '9') 355 | yydebug = yyn - '0'; 356 | } 357 | #endif 358 | 359 | yynerrs = 0; 360 | yyerrflag = 0; 361 | yychar = YYEMPTY; 362 | yystate = 0; 363 | 364 | #if YYPURE 365 | memset(&yystack, 0, sizeof(yystack)); 366 | #endif 367 | 368 | if (yystack.s_base == NULL && yygrowstack(&yystack) == YYENOMEM) goto yyoverflow; 369 | yystack.s_mark = yystack.s_base; 370 | yystack.l_mark = yystack.l_base; 371 | yystate = 0; 372 | *yystack.s_mark = 0; 373 | 374 | yyloop: 375 | if ((yyn = yydefred[yystate]) != 0) goto yyreduce; 376 | if (yychar < 0) 377 | { 378 | if ((yychar = YYLEX) < 0) yychar = YYEOF; 379 | #if YYDEBUG 380 | if (yydebug) 381 | { 382 | yys = yyname[YYTRANSLATE(yychar)]; 383 | printf("%sdebug: state %d, reading %d (%s)\n", 384 | YYPREFIX, yystate, yychar, yys); 385 | } 386 | #endif 387 | } 388 | if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 && 389 | yyn <= YYTABLESIZE && yycheck[yyn] == yychar) 390 | { 391 | #if YYDEBUG 392 | if (yydebug) 393 | printf("%sdebug: state %d, shifting to state %d\n", 394 | YYPREFIX, yystate, yytable[yyn]); 395 | #endif 396 | if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM) 397 | { 398 | goto yyoverflow; 399 | } 400 | yystate = yytable[yyn]; 401 | *++yystack.s_mark = yytable[yyn]; 402 | *++yystack.l_mark = yylval; 403 | yychar = YYEMPTY; 404 | if (yyerrflag > 0) --yyerrflag; 405 | goto yyloop; 406 | } 407 | if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 && 408 | yyn <= YYTABLESIZE && yycheck[yyn] == yychar) 409 | { 410 | yyn = yytable[yyn]; 411 | goto yyreduce; 412 | } 413 | if (yyerrflag) goto yyinrecovery; 414 | 415 | YYERROR_CALL("syntax error"); 416 | 417 | goto yyerrlab; 418 | 419 | yyerrlab: 420 | ++yynerrs; 421 | 422 | yyinrecovery: 423 | if (yyerrflag < 3) 424 | { 425 | yyerrflag = 3; 426 | for (;;) 427 | { 428 | if ((yyn = yysindex[*yystack.s_mark]) && (yyn += YYERRCODE) >= 0 && 429 | yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE) 430 | { 431 | #if YYDEBUG 432 | if (yydebug) 433 | printf("%sdebug: state %d, error recovery shifting\ 434 | to state %d\n", YYPREFIX, *yystack.s_mark, yytable[yyn]); 435 | #endif 436 | if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM) 437 | { 438 | goto yyoverflow; 439 | } 440 | yystate = yytable[yyn]; 441 | *++yystack.s_mark = yytable[yyn]; 442 | *++yystack.l_mark = yylval; 443 | goto yyloop; 444 | } 445 | else 446 | { 447 | #if YYDEBUG 448 | if (yydebug) 449 | printf("%sdebug: error recovery discarding state %d\n", 450 | YYPREFIX, *yystack.s_mark); 451 | #endif 452 | if (yystack.s_mark <= yystack.s_base) goto yyabort; 453 | --yystack.s_mark; 454 | --yystack.l_mark; 455 | } 456 | } 457 | } 458 | else 459 | { 460 | if (yychar == YYEOF) goto yyabort; 461 | #if YYDEBUG 462 | if (yydebug) 463 | { 464 | yys = yyname[YYTRANSLATE(yychar)]; 465 | printf("%sdebug: state %d, error recovery discards token %d (%s)\n", 466 | YYPREFIX, yystate, yychar, yys); 467 | } 468 | #endif 469 | yychar = YYEMPTY; 470 | goto yyloop; 471 | } 472 | 473 | yyreduce: 474 | #if YYDEBUG 475 | if (yydebug) 476 | printf("%sdebug: state %d, reducing by rule %d (%s)\n", 477 | YYPREFIX, yystate, yyn, yyrule[yyn]); 478 | #endif 479 | yym = yylen[yyn]; 480 | if (yym) 481 | yyval = yystack.l_mark[1-yym]; 482 | else 483 | memset(&yyval, 0, sizeof yyval); 484 | switch (yyn) 485 | { 486 | case 1: 487 | #line 95 "NSPlistParser.y" 488 | { plistVal = yystack.l_mark[0].value; } 489 | break; 490 | case 2: 491 | #line 98 "NSPlistParser.y" 492 | { yyval.dict_val = yystack.l_mark[-1].dict_val; } 493 | break; 494 | case 3: 495 | #line 101 "NSPlistParser.y" 496 | { yystack.l_mark[-4].dict_val->insert(yystack.l_mark[-3].string_val, yystack.l_mark[-1].value); yyval.dict_val = yystack.l_mark[-4].dict_val; } 497 | break; 498 | case 4: 499 | #line 102 "NSPlistParser.y" 500 | { yyval.dict_val = new NSPlistDictionary(); } 501 | break; 502 | case 5: 503 | #line 105 "NSPlistParser.y" 504 | { yyval.array_val = yystack.l_mark[-2].array_val; } 505 | break; 506 | case 6: 507 | #line 106 "NSPlistParser.y" 508 | { yyval.array_val = yystack.l_mark[-1].array_val; } 509 | break; 510 | case 7: 511 | #line 107 "NSPlistParser.y" 512 | { yyval.array_val = new NSPlistArray(); } 513 | break; 514 | case 8: 515 | #line 110 "NSPlistParser.y" 516 | { yystack.l_mark[-2].array_val->insert(yystack.l_mark[0].value); yyval.array_val = yystack.l_mark[-2].array_val; } 517 | break; 518 | case 9: 519 | #line 111 "NSPlistParser.y" 520 | { yyval.array_val = new NSPlistArray(); yyval.array_val->insert(yystack.l_mark[0].value); } 521 | break; 522 | case 10: 523 | #line 114 "NSPlistParser.y" 524 | { yyval.data_val = yystack.l_mark[-1].data_val; } 525 | break; 526 | case 11: 527 | #line 117 "NSPlistParser.y" 528 | { yystack.l_mark[-1].data_val->insert(yystack.l_mark[0].string); yyval.data_val = yystack.l_mark[-1].data_val; } 529 | break; 530 | case 12: 531 | #line 118 "NSPlistParser.y" 532 | { yyval.data_val = new NSPlistData(); } 533 | break; 534 | case 13: 535 | #line 121 "NSPlistParser.y" 536 | { yyval.value = yystack.l_mark[0].dict_val; } 537 | break; 538 | case 14: 539 | #line 122 "NSPlistParser.y" 540 | { yyval.value = yystack.l_mark[0].array_val; } 541 | break; 542 | case 15: 543 | #line 123 "NSPlistParser.y" 544 | { yyval.value = yystack.l_mark[0].data_val; } 545 | break; 546 | case 16: 547 | #line 124 "NSPlistParser.y" 548 | { yyval.value = yystack.l_mark[0].string_val; } 549 | break; 550 | case 17: 551 | #line 127 "NSPlistParser.y" 552 | { yyval.string_val = new NSPlistString(yystack.l_mark[0].string, NSPlistIntegerString); } 553 | break; 554 | case 18: 555 | #line 128 "NSPlistParser.y" 556 | { yyval.string_val = new NSPlistString(yystack.l_mark[-1].string, NSPlistIntegerString); } 557 | break; 558 | case 19: 559 | #line 129 "NSPlistParser.y" 560 | { yyval.string_val = new NSPlistString(yystack.l_mark[0].string, NSPlistRealString); } 561 | break; 562 | case 20: 563 | #line 130 "NSPlistParser.y" 564 | { yyval.string_val = new NSPlistString(yystack.l_mark[-1].string, NSPlistRealString); } 565 | break; 566 | case 21: 567 | #line 131 "NSPlistParser.y" 568 | { yyval.string_val = new NSPlistString(yystack.l_mark[0].string, NSPlistDateString); } 569 | break; 570 | case 22: 571 | #line 132 "NSPlistParser.y" 572 | { yyval.string_val = new NSPlistString(yystack.l_mark[-1].string, NSPlistDateString); } 573 | break; 574 | case 23: 575 | #line 133 "NSPlistParser.y" 576 | { yyval.string_val = new NSPlistString(yystack.l_mark[0].string, NSPlistStringString); } 577 | break; 578 | case 24: 579 | #line 134 "NSPlistParser.y" 580 | { yyval.string_val = new NSPlistString(yystack.l_mark[-1].string, NSPlistStringString); } 581 | break; 582 | case 25: 583 | #line 135 "NSPlistParser.y" 584 | { yyval.string_val = new NSPlistString("", NSPlistStringString); } 585 | break; 586 | #line 587 "NSPlistParser.cpp" 587 | } 588 | yystack.s_mark -= yym; 589 | yystate = *yystack.s_mark; 590 | yystack.l_mark -= yym; 591 | yym = yylhs[yyn]; 592 | if (yystate == 0 && yym == 0) 593 | { 594 | #if YYDEBUG 595 | if (yydebug) 596 | printf("%sdebug: after reduction, shifting from state 0 to\ 597 | state %d\n", YYPREFIX, YYFINAL); 598 | #endif 599 | yystate = YYFINAL; 600 | *++yystack.s_mark = YYFINAL; 601 | *++yystack.l_mark = yyval; 602 | if (yychar < 0) 603 | { 604 | if ((yychar = YYLEX) < 0) yychar = YYEOF; 605 | #if YYDEBUG 606 | if (yydebug) 607 | { 608 | yys = yyname[YYTRANSLATE(yychar)]; 609 | printf("%sdebug: state %d, reading %d (%s)\n", 610 | YYPREFIX, YYFINAL, yychar, yys); 611 | } 612 | #endif 613 | } 614 | if (yychar == YYEOF) goto yyaccept; 615 | goto yyloop; 616 | } 617 | if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 && 618 | yyn <= YYTABLESIZE && yycheck[yyn] == yystate) 619 | yystate = yytable[yyn]; 620 | else 621 | yystate = yydgoto[yym]; 622 | #if YYDEBUG 623 | if (yydebug) 624 | printf("%sdebug: after reduction, shifting from state %d \ 625 | to state %d\n", YYPREFIX, *yystack.s_mark, yystate); 626 | #endif 627 | if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM) 628 | { 629 | goto yyoverflow; 630 | } 631 | *++yystack.s_mark = (YYINT) yystate; 632 | *++yystack.l_mark = yyval; 633 | goto yyloop; 634 | 635 | yyoverflow: 636 | YYERROR_CALL("yacc stack overflow"); 637 | 638 | yyabort: 639 | yyfreestack(&yystack); 640 | return (1); 641 | 642 | yyaccept: 643 | yyfreestack(&yystack); 644 | return (0); 645 | } 646 | -------------------------------------------------------------------------------- /src/NSPlistParser.h: -------------------------------------------------------------------------------- 1 | #define INTEGER 257 2 | #define REAL 258 3 | #define DATE 259 4 | #define HEXSTRING 260 5 | #define STRING 261 6 | #define LBRACKET 262 7 | #define RBRACKET 263 8 | #define LBRACE 264 9 | #define RBRACE 265 10 | #define LCHEVRON 266 11 | #define RCHEVRON 267 12 | #define LQUOTE 268 13 | #define RQUOTE 269 14 | #define EQUAL 270 15 | #define COMMA 271 16 | #define SEMICOLON 272 17 | #ifdef YYSTYPE 18 | #undef YYSTYPE_IS_DECLARED 19 | #define YYSTYPE_IS_DECLARED 1 20 | #endif 21 | #ifndef YYSTYPE_IS_DECLARED 22 | #define YYSTYPE_IS_DECLARED 1 23 | typedef union { 24 | NSPlistValue* value; 25 | NSPlistString* string_val; 26 | NSPlistData* data_val; 27 | NSPlistArray* array_val; 28 | NSPlistDictionary* dict_val; 29 | char* string; 30 | } YYSTYPE; 31 | #endif /* !YYSTYPE_IS_DECLARED */ 32 | extern YYSTYPE yylval; 33 | -------------------------------------------------------------------------------- /src/NSPlistParser.y: -------------------------------------------------------------------------------- 1 | //****************************************************************************** 2 | // 3 | // Copyright (c) 2015 Microsoft Corporation. All rights reserved. 4 | // 5 | // This code is licensed under the MIT License (MIT). 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 8 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 9 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 10 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 11 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 12 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 13 | // THE SOFTWARE. 14 | // 15 | //****************************************************************************** 16 | 17 | %{ 18 | #include 19 | #include "NSPlist.h" 20 | 21 | typedef struct yy_buffer_state* YY_BUFFER_STATE; 22 | extern YY_BUFFER_STATE yy_scan_string(const char* str); 23 | extern void yy_delete_buffer(YY_BUFFER_STATE buffer); 24 | extern int yyparse(); 25 | extern FILE* yyin; 26 | extern int yylineno; 27 | 28 | int yylex(); 29 | 30 | static NSPlistValue *plistVal; 31 | 32 | 33 | void yyerror(const char* s) 34 | { 35 | #ifdef DEBUG_NSPARSER 36 | printf("ERROR: %s, line %d\n", s, yylineno); 37 | #endif 38 | } 39 | 40 | bool loadPlistFromBuffer(const char* byteArray, NSPlistValue*& plist) 41 | { 42 | plistVal = NULL; 43 | 44 | YY_BUFFER_STATE buf = yy_scan_string(byteArray); 45 | int result = yyparse(); 46 | yy_delete_buffer(buf); 47 | 48 | if (!result) { 49 | plist = plistVal; 50 | } else { 51 | delete plistVal; 52 | plist = NULL; 53 | } 54 | 55 | return !result; 56 | } 57 | 58 | bool loadPlistFromFile(const char* filePath, NSPlistValue*& plist) 59 | { 60 | plistVal = NULL; 61 | int result = -1; 62 | 63 | yyin = fopen(filePath, "r"); 64 | if (yyin) { 65 | result = yyparse(); 66 | fclose(yyin); 67 | } 68 | 69 | if (!result) { 70 | plist = plistVal; 71 | } else { 72 | delete plistVal; 73 | plist = NULL; 74 | } 75 | 76 | return !result; 77 | } 78 | 79 | %} 80 | 81 | %union { 82 | NSPlistValue* value; 83 | NSPlistString* string_val; 84 | NSPlistData* data_val; 85 | NSPlistArray* array_val; 86 | NSPlistDictionary* dict_val; 87 | char* string; 88 | } 89 | 90 | %token INTEGER 91 | %token REAL 92 | %token DATE 93 | %token HEXSTRING 94 | %token STRING 95 | %token LBRACKET RBRACKET LBRACE RBRACE LCHEVRON RCHEVRON 96 | %token LQUOTE RQUOTE EQUAL COMMA SEMICOLON 97 | 98 | %type value 99 | %type keyvalue 100 | %type dictionary 101 | %type assignments 102 | %type array 103 | %type values 104 | %type data 105 | %type hexvalues 106 | 107 | %start plist 108 | 109 | %% 110 | 111 | plist : value { plistVal = $1; } 112 | ; 113 | 114 | dictionary : LBRACE assignments RBRACE { $$ = $2; } 115 | ; 116 | 117 | assignments : assignments keyvalue EQUAL value SEMICOLON { $1->insert($2, $4); $$ = $1; } 118 | | /* Empty */ { $$ = new NSPlistDictionary(); } 119 | ; 120 | 121 | array : LBRACKET values COMMA RBRACKET { $$ = $2; } 122 | | LBRACKET values RBRACKET { $$ = $2; } 123 | | LBRACKET RBRACKET { $$ = new NSPlistArray(); } 124 | ; 125 | 126 | values : values COMMA value { $1->insert($3); $$ = $1; } 127 | | value { $$ = new NSPlistArray(); $$->insert($1); } 128 | ; 129 | 130 | data : LCHEVRON hexvalues RCHEVRON { $$ = $2; } 131 | ; 132 | 133 | hexvalues : hexvalues HEXSTRING { $1->insert($2); $$ = $1; } 134 | | /* Empty */ { $$ = new NSPlistData(); } 135 | ; 136 | 137 | value : dictionary { $$ = $1; } 138 | | array { $$ = $1; } 139 | | data { $$ = $1; } 140 | | keyvalue { $$ = $1; } 141 | ; 142 | 143 | keyvalue : INTEGER { $$ = new NSPlistString($1, NSPlistIntegerString); } 144 | | LQUOTE INTEGER RQUOTE { $$ = new NSPlistString($2, NSPlistIntegerString); } 145 | | REAL { $$ = new NSPlistString($1, NSPlistRealString); } 146 | | LQUOTE REAL RQUOTE { $$ = new NSPlistString($2, NSPlistRealString); } 147 | | DATE { $$ = new NSPlistString($1, NSPlistDateString); } 148 | | LQUOTE DATE RQUOTE { $$ = new NSPlistString($2, NSPlistDateString); } 149 | | STRING { $$ = new NSPlistString($1, NSPlistStringString); } 150 | | LQUOTE STRING RQUOTE { $$ = new NSPlistString($2, NSPlistStringString); } 151 | | LQUOTE RQUOTE { $$ = new NSPlistString("", NSPlistStringString); } 152 | ; 153 | 154 | %% --------------------------------------------------------------------------------