1425bb815Sopenharmony_ci/* Copyright JS Foundation and other contributors, http://js.foundation 2425bb815Sopenharmony_ci * 3425bb815Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4425bb815Sopenharmony_ci * you may not use this file except in compliance with the License. 5425bb815Sopenharmony_ci * You may obtain a copy of the License at 6425bb815Sopenharmony_ci * 7425bb815Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8425bb815Sopenharmony_ci * 9425bb815Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10425bb815Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS 11425bb815Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12425bb815Sopenharmony_ci * See the License for the specific language governing permissions and 13425bb815Sopenharmony_ci * limitations under the License. 14425bb815Sopenharmony_ci */ 15425bb815Sopenharmony_ci 16425bb815Sopenharmony_ci#include "js-parser-internal.h" 17425bb815Sopenharmony_ci 18425bb815Sopenharmony_ci#if ENABLED (JERRY_PARSER) 19425bb815Sopenharmony_ci 20425bb815Sopenharmony_ci/** \addtogroup mem Memory allocation 21425bb815Sopenharmony_ci * @{ 22425bb815Sopenharmony_ci * 23425bb815Sopenharmony_ci * \addtogroup mem_parser Parser memory manager 24425bb815Sopenharmony_ci * @{ 25425bb815Sopenharmony_ci */ 26425bb815Sopenharmony_ci 27425bb815Sopenharmony_ci/**********************************************************************/ 28425bb815Sopenharmony_ci/* Memory allocation */ 29425bb815Sopenharmony_ci/**********************************************************************/ 30425bb815Sopenharmony_ci 31425bb815Sopenharmony_ci/** 32425bb815Sopenharmony_ci * Allocate memory. 33425bb815Sopenharmony_ci * 34425bb815Sopenharmony_ci * @return allocated memory. 35425bb815Sopenharmony_ci */ 36425bb815Sopenharmony_civoid * 37425bb815Sopenharmony_ciparser_malloc (parser_context_t *context_p, /**< context */ 38425bb815Sopenharmony_ci size_t size) /**< size of the memory block */ 39425bb815Sopenharmony_ci{ 40425bb815Sopenharmony_ci void *result; 41425bb815Sopenharmony_ci 42425bb815Sopenharmony_ci JERRY_ASSERT (size > 0); 43425bb815Sopenharmony_ci result = jmem_heap_alloc_block_null_on_error (size); 44425bb815Sopenharmony_ci 45425bb815Sopenharmony_ci if (result == NULL) 46425bb815Sopenharmony_ci { 47425bb815Sopenharmony_ci parser_raise_error (context_p, PARSER_ERR_OUT_OF_MEMORY); 48425bb815Sopenharmony_ci } 49425bb815Sopenharmony_ci return result; 50425bb815Sopenharmony_ci} /* parser_malloc */ 51425bb815Sopenharmony_ci 52425bb815Sopenharmony_ci/** 53425bb815Sopenharmony_ci * Free memory allocated by parser_malloc. 54425bb815Sopenharmony_ci */ 55425bb815Sopenharmony_ciinline void JERRY_ATTR_ALWAYS_INLINE 56425bb815Sopenharmony_ciparser_free (void *ptr, /**< pointer to free */ 57425bb815Sopenharmony_ci size_t size) /**< size of the memory block */ 58425bb815Sopenharmony_ci{ 59425bb815Sopenharmony_ci jmem_heap_free_block (ptr, size); 60425bb815Sopenharmony_ci} /* parser_free */ 61425bb815Sopenharmony_ci 62425bb815Sopenharmony_ci/** 63425bb815Sopenharmony_ci * Allocate local memory for short term use. 64425bb815Sopenharmony_ci * 65425bb815Sopenharmony_ci * @return allocated memory. 66425bb815Sopenharmony_ci */ 67425bb815Sopenharmony_civoid * 68425bb815Sopenharmony_ciparser_malloc_local (parser_context_t *context_p, /**< context */ 69425bb815Sopenharmony_ci size_t size) /**< size of the memory */ 70425bb815Sopenharmony_ci{ 71425bb815Sopenharmony_ci void *result; 72425bb815Sopenharmony_ci 73425bb815Sopenharmony_ci JERRY_ASSERT (size > 0); 74425bb815Sopenharmony_ci result = jmem_heap_alloc_block (size); 75425bb815Sopenharmony_ci if (result == 0) 76425bb815Sopenharmony_ci { 77425bb815Sopenharmony_ci parser_raise_error (context_p, PARSER_ERR_OUT_OF_MEMORY); 78425bb815Sopenharmony_ci } 79425bb815Sopenharmony_ci return result; 80425bb815Sopenharmony_ci} /* parser_malloc_local */ 81425bb815Sopenharmony_ci 82425bb815Sopenharmony_ci/** 83425bb815Sopenharmony_ci * Free memory allocated by parser_malloc_local. 84425bb815Sopenharmony_ci */ 85425bb815Sopenharmony_civoid 86425bb815Sopenharmony_ciparser_free_local (void *ptr, /**< pointer to free */ 87425bb815Sopenharmony_ci size_t size) /**< size of the memory */ 88425bb815Sopenharmony_ci{ 89425bb815Sopenharmony_ci jmem_heap_free_block (ptr, size); 90425bb815Sopenharmony_ci} /* parser_free_local */ 91425bb815Sopenharmony_ci 92425bb815Sopenharmony_ci/** 93425bb815Sopenharmony_ci * Free the dynamically allocated buffer stored in the context 94425bb815Sopenharmony_ci */ 95425bb815Sopenharmony_ciinline void JERRY_ATTR_ALWAYS_INLINE 96425bb815Sopenharmony_ciparser_free_allocated_buffer (parser_context_t *context_p) /**< context */ 97425bb815Sopenharmony_ci{ 98425bb815Sopenharmony_ci if (context_p->u.allocated_buffer_p != NULL) 99425bb815Sopenharmony_ci { 100425bb815Sopenharmony_ci parser_free_local (context_p->u.allocated_buffer_p, 101425bb815Sopenharmony_ci context_p->allocated_buffer_size); 102425bb815Sopenharmony_ci context_p->u.allocated_buffer_p = NULL; 103425bb815Sopenharmony_ci } 104425bb815Sopenharmony_ci} /* parser_free_allocated_buffer */ 105425bb815Sopenharmony_ci 106425bb815Sopenharmony_ci/**********************************************************************/ 107425bb815Sopenharmony_ci/* Parser data management functions */ 108425bb815Sopenharmony_ci/**********************************************************************/ 109425bb815Sopenharmony_ci 110425bb815Sopenharmony_ci/** 111425bb815Sopenharmony_ci * Initialize parse data. 112425bb815Sopenharmony_ci */ 113425bb815Sopenharmony_cistatic void 114425bb815Sopenharmony_ciparser_data_init (parser_mem_data_t *data_p, /**< memory manager */ 115425bb815Sopenharmony_ci uint32_t page_size) /**< size of each page */ 116425bb815Sopenharmony_ci{ 117425bb815Sopenharmony_ci data_p->first_p = NULL; 118425bb815Sopenharmony_ci data_p->last_p = NULL; 119425bb815Sopenharmony_ci data_p->last_position = page_size; 120425bb815Sopenharmony_ci} /* parser_data_init */ 121425bb815Sopenharmony_ci 122425bb815Sopenharmony_ci/** 123425bb815Sopenharmony_ci * Free parse data. 124425bb815Sopenharmony_ci */ 125425bb815Sopenharmony_cistatic void 126425bb815Sopenharmony_ciparser_data_free (parser_mem_data_t *data_p, /**< memory manager */ 127425bb815Sopenharmony_ci uint32_t page_size) /**< size of each page */ 128425bb815Sopenharmony_ci{ 129425bb815Sopenharmony_ci parser_mem_page_t *page_p = data_p->first_p; 130425bb815Sopenharmony_ci 131425bb815Sopenharmony_ci while (page_p != NULL) 132425bb815Sopenharmony_ci { 133425bb815Sopenharmony_ci parser_mem_page_t *next_p = page_p->next_p; 134425bb815Sopenharmony_ci 135425bb815Sopenharmony_ci parser_free (page_p, page_size); 136425bb815Sopenharmony_ci page_p = next_p; 137425bb815Sopenharmony_ci } 138425bb815Sopenharmony_ci} /* parser_data_free */ 139425bb815Sopenharmony_ci 140425bb815Sopenharmony_ci/**********************************************************************/ 141425bb815Sopenharmony_ci/* Parser byte stream management functions */ 142425bb815Sopenharmony_ci/**********************************************************************/ 143425bb815Sopenharmony_ci 144425bb815Sopenharmony_ci/** 145425bb815Sopenharmony_ci * Initialize byte stream. 146425bb815Sopenharmony_ci */ 147425bb815Sopenharmony_civoid 148425bb815Sopenharmony_ciparser_cbc_stream_init (parser_mem_data_t *data_p) /**< memory manager */ 149425bb815Sopenharmony_ci{ 150425bb815Sopenharmony_ci parser_data_init (data_p, PARSER_CBC_STREAM_PAGE_SIZE); 151425bb815Sopenharmony_ci} /* parser_cbc_stream_init */ 152425bb815Sopenharmony_ci 153425bb815Sopenharmony_ci/** 154425bb815Sopenharmony_ci * Free byte stream. 155425bb815Sopenharmony_ci */ 156425bb815Sopenharmony_civoid 157425bb815Sopenharmony_ciparser_cbc_stream_free (parser_mem_data_t *data_p) /**< memory manager */ 158425bb815Sopenharmony_ci{ 159425bb815Sopenharmony_ci parser_data_free (data_p, 160425bb815Sopenharmony_ci sizeof (parser_mem_page_t *) + PARSER_CBC_STREAM_PAGE_SIZE); 161425bb815Sopenharmony_ci} /* parser_cbc_stream_free */ 162425bb815Sopenharmony_ci 163425bb815Sopenharmony_ci/** 164425bb815Sopenharmony_ci * Appends a byte at the end of the byte stream. 165425bb815Sopenharmony_ci */ 166425bb815Sopenharmony_civoid 167425bb815Sopenharmony_ciparser_cbc_stream_alloc_page (parser_context_t *context_p, /**< context */ 168425bb815Sopenharmony_ci parser_mem_data_t *data_p) /**< memory manager */ 169425bb815Sopenharmony_ci{ 170425bb815Sopenharmony_ci size_t size = sizeof (parser_mem_page_t *) + PARSER_CBC_STREAM_PAGE_SIZE; 171425bb815Sopenharmony_ci parser_mem_page_t *page_p = (parser_mem_page_t *) parser_malloc (context_p, size); 172425bb815Sopenharmony_ci 173425bb815Sopenharmony_ci page_p->next_p = NULL; 174425bb815Sopenharmony_ci data_p->last_position = 0; 175425bb815Sopenharmony_ci 176425bb815Sopenharmony_ci if (data_p->last_p != NULL) 177425bb815Sopenharmony_ci { 178425bb815Sopenharmony_ci data_p->last_p->next_p = page_p; 179425bb815Sopenharmony_ci } 180425bb815Sopenharmony_ci else 181425bb815Sopenharmony_ci { 182425bb815Sopenharmony_ci data_p->first_p = page_p; 183425bb815Sopenharmony_ci } 184425bb815Sopenharmony_ci data_p->last_p = page_p; 185425bb815Sopenharmony_ci} /* parser_cbc_stream_alloc_page */ 186425bb815Sopenharmony_ci 187425bb815Sopenharmony_ci/**********************************************************************/ 188425bb815Sopenharmony_ci/* Parser list management functions */ 189425bb815Sopenharmony_ci/**********************************************************************/ 190425bb815Sopenharmony_ci 191425bb815Sopenharmony_ci/** 192425bb815Sopenharmony_ci * Initialize parser list. 193425bb815Sopenharmony_ci */ 194425bb815Sopenharmony_civoid 195425bb815Sopenharmony_ciparser_list_init (parser_list_t *list_p, /**< parser list */ 196425bb815Sopenharmony_ci uint32_t item_size, /**< size for each page */ 197425bb815Sopenharmony_ci uint32_t item_count) /**< number of items on each page */ 198425bb815Sopenharmony_ci{ 199425bb815Sopenharmony_ci /* Align to pointer size. */ 200425bb815Sopenharmony_ci item_size = (uint32_t) (((item_size) + sizeof (void *) - 1) & ~(sizeof (void *) - 1)); 201425bb815Sopenharmony_ci parser_data_init (&list_p->data, item_size * item_count); 202425bb815Sopenharmony_ci list_p->page_size = item_size * item_count; 203425bb815Sopenharmony_ci list_p->item_size = item_size; 204425bb815Sopenharmony_ci list_p->item_count = item_count; 205425bb815Sopenharmony_ci} /* parser_list_init */ 206425bb815Sopenharmony_ci 207425bb815Sopenharmony_ci/** 208425bb815Sopenharmony_ci * Free parser list. 209425bb815Sopenharmony_ci */ 210425bb815Sopenharmony_civoid 211425bb815Sopenharmony_ciparser_list_free (parser_list_t *list_p) /**< parser list */ 212425bb815Sopenharmony_ci{ 213425bb815Sopenharmony_ci parser_data_free (&list_p->data, 214425bb815Sopenharmony_ci (uint32_t) (sizeof (parser_mem_page_t *) + list_p->page_size)); 215425bb815Sopenharmony_ci} /* parser_list_free */ 216425bb815Sopenharmony_ci 217425bb815Sopenharmony_ci/** 218425bb815Sopenharmony_ci * Reset parser list. 219425bb815Sopenharmony_ci */ 220425bb815Sopenharmony_civoid 221425bb815Sopenharmony_ciparser_list_reset (parser_list_t *list_p) /**< parser list */ 222425bb815Sopenharmony_ci{ 223425bb815Sopenharmony_ci parser_data_init (&list_p->data, list_p->page_size); 224425bb815Sopenharmony_ci} /* parser_list_reset */ 225425bb815Sopenharmony_ci 226425bb815Sopenharmony_ci/** 227425bb815Sopenharmony_ci * Allocate space for the next item. 228425bb815Sopenharmony_ci * 229425bb815Sopenharmony_ci * @return pointer to the appended item. 230425bb815Sopenharmony_ci */ 231425bb815Sopenharmony_civoid * 232425bb815Sopenharmony_ciparser_list_append (parser_context_t *context_p, /**< context */ 233425bb815Sopenharmony_ci parser_list_t *list_p) /**< parser list */ 234425bb815Sopenharmony_ci{ 235425bb815Sopenharmony_ci parser_mem_page_t *page_p = list_p->data.last_p; 236425bb815Sopenharmony_ci void *result; 237425bb815Sopenharmony_ci 238425bb815Sopenharmony_ci if (list_p->data.last_position + list_p->item_size > list_p->page_size) 239425bb815Sopenharmony_ci { 240425bb815Sopenharmony_ci size_t size = sizeof (parser_mem_page_t *) + list_p->page_size; 241425bb815Sopenharmony_ci 242425bb815Sopenharmony_ci page_p = (parser_mem_page_t *) parser_malloc (context_p, size); 243425bb815Sopenharmony_ci 244425bb815Sopenharmony_ci page_p->next_p = NULL; 245425bb815Sopenharmony_ci list_p->data.last_position = 0; 246425bb815Sopenharmony_ci 247425bb815Sopenharmony_ci if (list_p->data.last_p != NULL) 248425bb815Sopenharmony_ci { 249425bb815Sopenharmony_ci list_p->data.last_p->next_p = page_p; 250425bb815Sopenharmony_ci } 251425bb815Sopenharmony_ci else 252425bb815Sopenharmony_ci { 253425bb815Sopenharmony_ci list_p->data.first_p = page_p; 254425bb815Sopenharmony_ci } 255425bb815Sopenharmony_ci list_p->data.last_p = page_p; 256425bb815Sopenharmony_ci } 257425bb815Sopenharmony_ci 258425bb815Sopenharmony_ci result = page_p->bytes + list_p->data.last_position; 259425bb815Sopenharmony_ci list_p->data.last_position += list_p->item_size; 260425bb815Sopenharmony_ci return result; 261425bb815Sopenharmony_ci} /* parser_list_append */ 262425bb815Sopenharmony_ci 263425bb815Sopenharmony_ci/** 264425bb815Sopenharmony_ci * Return the nth item of the list. 265425bb815Sopenharmony_ci * 266425bb815Sopenharmony_ci * @return pointer to the item. 267425bb815Sopenharmony_ci */ 268425bb815Sopenharmony_civoid * 269425bb815Sopenharmony_ciparser_list_get (parser_list_t *list_p, /**< parser list */ 270425bb815Sopenharmony_ci size_t index) /**< item index */ 271425bb815Sopenharmony_ci{ 272425bb815Sopenharmony_ci size_t item_count = list_p->item_count; 273425bb815Sopenharmony_ci parser_mem_page_t *page_p = list_p->data.first_p; 274425bb815Sopenharmony_ci 275425bb815Sopenharmony_ci while (index >= item_count) 276425bb815Sopenharmony_ci { 277425bb815Sopenharmony_ci JERRY_ASSERT (page_p != NULL); 278425bb815Sopenharmony_ci page_p = page_p->next_p; 279425bb815Sopenharmony_ci index -= item_count; 280425bb815Sopenharmony_ci } 281425bb815Sopenharmony_ci 282425bb815Sopenharmony_ci JERRY_ASSERT (page_p != NULL); 283425bb815Sopenharmony_ci JERRY_ASSERT (page_p != list_p->data.last_p 284425bb815Sopenharmony_ci || (index * list_p->item_size < list_p->data.last_position)); 285425bb815Sopenharmony_ci return page_p->bytes + (index * list_p->item_size); 286425bb815Sopenharmony_ci} /* parser_list_get */ 287425bb815Sopenharmony_ci 288425bb815Sopenharmony_ci/** 289425bb815Sopenharmony_ci * Initialize a parser list iterator. 290425bb815Sopenharmony_ci */ 291425bb815Sopenharmony_civoid 292425bb815Sopenharmony_ciparser_list_iterator_init (parser_list_t *list_p, /**< parser list */ 293425bb815Sopenharmony_ci parser_list_iterator_t *iterator_p) /**< iterator */ 294425bb815Sopenharmony_ci{ 295425bb815Sopenharmony_ci iterator_p->list_p = list_p; 296425bb815Sopenharmony_ci iterator_p->current_p = list_p->data.first_p; 297425bb815Sopenharmony_ci iterator_p->current_position = 0; 298425bb815Sopenharmony_ci} /* parser_list_iterator_init */ 299425bb815Sopenharmony_ci 300425bb815Sopenharmony_ci/** 301425bb815Sopenharmony_ci * Next iterator step. 302425bb815Sopenharmony_ci * 303425bb815Sopenharmony_ci * @return the address of the current item, or NULL at the end. 304425bb815Sopenharmony_ci */ 305425bb815Sopenharmony_civoid * 306425bb815Sopenharmony_ciparser_list_iterator_next (parser_list_iterator_t *iterator_p) /**< iterator */ 307425bb815Sopenharmony_ci{ 308425bb815Sopenharmony_ci void *result; 309425bb815Sopenharmony_ci 310425bb815Sopenharmony_ci if (iterator_p->current_p == NULL) 311425bb815Sopenharmony_ci { 312425bb815Sopenharmony_ci return NULL; 313425bb815Sopenharmony_ci } 314425bb815Sopenharmony_ci 315425bb815Sopenharmony_ci result = iterator_p->current_p->bytes + iterator_p->current_position; 316425bb815Sopenharmony_ci iterator_p->current_position += iterator_p->list_p->item_size; 317425bb815Sopenharmony_ci 318425bb815Sopenharmony_ci if (iterator_p->current_p->next_p == NULL) 319425bb815Sopenharmony_ci { 320425bb815Sopenharmony_ci if (iterator_p->current_position >= iterator_p->list_p->data.last_position) 321425bb815Sopenharmony_ci { 322425bb815Sopenharmony_ci iterator_p->current_p = NULL; 323425bb815Sopenharmony_ci iterator_p->current_position = 0; 324425bb815Sopenharmony_ci } 325425bb815Sopenharmony_ci } 326425bb815Sopenharmony_ci else if (iterator_p->current_position >= iterator_p->list_p->page_size) 327425bb815Sopenharmony_ci { 328425bb815Sopenharmony_ci iterator_p->current_p = iterator_p->current_p->next_p; 329425bb815Sopenharmony_ci iterator_p->current_position = 0; 330425bb815Sopenharmony_ci } 331425bb815Sopenharmony_ci return result; 332425bb815Sopenharmony_ci} /* parser_list_iterator_next */ 333425bb815Sopenharmony_ci 334425bb815Sopenharmony_ci/**********************************************************************/ 335425bb815Sopenharmony_ci/* Parser stack management functions */ 336425bb815Sopenharmony_ci/**********************************************************************/ 337425bb815Sopenharmony_ci 338425bb815Sopenharmony_ci/* Stack is a reversed storage. */ 339425bb815Sopenharmony_ci 340425bb815Sopenharmony_ci/** 341425bb815Sopenharmony_ci * Initialize parser stack. 342425bb815Sopenharmony_ci */ 343425bb815Sopenharmony_civoid 344425bb815Sopenharmony_ciparser_stack_init (parser_context_t *context_p) /**< context */ 345425bb815Sopenharmony_ci{ 346425bb815Sopenharmony_ci parser_data_init (&context_p->stack, PARSER_STACK_PAGE_SIZE); 347425bb815Sopenharmony_ci context_p->free_page_p = NULL; 348425bb815Sopenharmony_ci} /* parser_stack_init */ 349425bb815Sopenharmony_ci 350425bb815Sopenharmony_ci/** 351425bb815Sopenharmony_ci * Free parser stack. 352425bb815Sopenharmony_ci */ 353425bb815Sopenharmony_civoid 354425bb815Sopenharmony_ciparser_stack_free (parser_context_t *context_p) /**< context */ 355425bb815Sopenharmony_ci{ 356425bb815Sopenharmony_ci parser_data_free (&context_p->stack, 357425bb815Sopenharmony_ci sizeof (parser_mem_page_t *) + PARSER_STACK_PAGE_SIZE); 358425bb815Sopenharmony_ci 359425bb815Sopenharmony_ci if (context_p->free_page_p != NULL) 360425bb815Sopenharmony_ci { 361425bb815Sopenharmony_ci parser_free (context_p->free_page_p, 362425bb815Sopenharmony_ci sizeof (parser_mem_page_t *) + PARSER_STACK_PAGE_SIZE); 363425bb815Sopenharmony_ci } 364425bb815Sopenharmony_ci} /* parser_stack_free */ 365425bb815Sopenharmony_ci 366425bb815Sopenharmony_ci/** 367425bb815Sopenharmony_ci * Pushes an uint8_t value onto the stack. 368425bb815Sopenharmony_ci */ 369425bb815Sopenharmony_civoid 370425bb815Sopenharmony_ciparser_stack_push_uint8 (parser_context_t *context_p, /**< context */ 371425bb815Sopenharmony_ci uint8_t uint8_value) /**< value pushed onto the stack */ 372425bb815Sopenharmony_ci{ 373425bb815Sopenharmony_ci parser_mem_page_t *page_p = context_p->stack.first_p; 374425bb815Sopenharmony_ci 375425bb815Sopenharmony_ci /* This assert might trigger false positive valgrind errors, when 376425bb815Sopenharmony_ci * parser_stack_push() pushes not fully initialized structures. 377425bb815Sopenharmony_ci * More precisely when the last byte of the structure is uninitialized. */ 378425bb815Sopenharmony_ci JERRY_ASSERT (page_p == NULL 379425bb815Sopenharmony_ci || context_p->stack_top_uint8 == page_p->bytes[context_p->stack.last_position - 1]); 380425bb815Sopenharmony_ci 381425bb815Sopenharmony_ci if (context_p->stack.last_position >= PARSER_STACK_PAGE_SIZE) 382425bb815Sopenharmony_ci { 383425bb815Sopenharmony_ci if (context_p->free_page_p != NULL) 384425bb815Sopenharmony_ci { 385425bb815Sopenharmony_ci page_p = context_p->free_page_p; 386425bb815Sopenharmony_ci context_p->free_page_p = NULL; 387425bb815Sopenharmony_ci } 388425bb815Sopenharmony_ci else 389425bb815Sopenharmony_ci { 390425bb815Sopenharmony_ci size_t size = sizeof (parser_mem_page_t *) + PARSER_STACK_PAGE_SIZE; 391425bb815Sopenharmony_ci page_p = (parser_mem_page_t *) parser_malloc (context_p, size); 392425bb815Sopenharmony_ci } 393425bb815Sopenharmony_ci 394425bb815Sopenharmony_ci page_p->next_p = context_p->stack.first_p; 395425bb815Sopenharmony_ci context_p->stack.last_position = 0; 396425bb815Sopenharmony_ci context_p->stack.first_p = page_p; 397425bb815Sopenharmony_ci } 398425bb815Sopenharmony_ci 399425bb815Sopenharmony_ci page_p->bytes[context_p->stack.last_position++] = uint8_value; 400425bb815Sopenharmony_ci context_p->stack_top_uint8 = uint8_value; 401425bb815Sopenharmony_ci} /* parser_stack_push_uint8 */ 402425bb815Sopenharmony_ci 403425bb815Sopenharmony_ci/** 404425bb815Sopenharmony_ci * Pops the last uint8_t value from the stack. 405425bb815Sopenharmony_ci */ 406425bb815Sopenharmony_civoid 407425bb815Sopenharmony_ciparser_stack_pop_uint8 (parser_context_t *context_p) /**< context */ 408425bb815Sopenharmony_ci{ 409425bb815Sopenharmony_ci parser_mem_page_t *page_p = context_p->stack.first_p; 410425bb815Sopenharmony_ci 411425bb815Sopenharmony_ci JERRY_ASSERT (page_p != NULL 412425bb815Sopenharmony_ci && context_p->stack_top_uint8 == page_p->bytes[context_p->stack.last_position - 1]); 413425bb815Sopenharmony_ci 414425bb815Sopenharmony_ci context_p->stack.last_position--; 415425bb815Sopenharmony_ci 416425bb815Sopenharmony_ci if (context_p->stack.last_position == 0) 417425bb815Sopenharmony_ci { 418425bb815Sopenharmony_ci context_p->stack.first_p = page_p->next_p; 419425bb815Sopenharmony_ci context_p->stack.last_position = PARSER_STACK_PAGE_SIZE; 420425bb815Sopenharmony_ci 421425bb815Sopenharmony_ci if (context_p->free_page_p == NULL) 422425bb815Sopenharmony_ci { 423425bb815Sopenharmony_ci context_p->free_page_p = page_p; 424425bb815Sopenharmony_ci } 425425bb815Sopenharmony_ci else 426425bb815Sopenharmony_ci { 427425bb815Sopenharmony_ci parser_free (page_p, 428425bb815Sopenharmony_ci sizeof (parser_mem_page_t *) + PARSER_STACK_PAGE_SIZE); 429425bb815Sopenharmony_ci } 430425bb815Sopenharmony_ci 431425bb815Sopenharmony_ci page_p = context_p->stack.first_p; 432425bb815Sopenharmony_ci 433425bb815Sopenharmony_ci JERRY_ASSERT (page_p != NULL); 434425bb815Sopenharmony_ci } 435425bb815Sopenharmony_ci 436425bb815Sopenharmony_ci context_p->stack_top_uint8 = page_p->bytes[context_p->stack.last_position - 1]; 437425bb815Sopenharmony_ci} /* parser_stack_pop_uint8 */ 438425bb815Sopenharmony_ci 439425bb815Sopenharmony_ci/** 440425bb815Sopenharmony_ci * Pushes an uint16_t value onto the stack. 441425bb815Sopenharmony_ci */ 442425bb815Sopenharmony_civoid 443425bb815Sopenharmony_ciparser_stack_push_uint16 (parser_context_t *context_p, /**< context */ 444425bb815Sopenharmony_ci uint16_t uint16_value) /**< value pushed onto the stack */ 445425bb815Sopenharmony_ci{ 446425bb815Sopenharmony_ci if (context_p->stack.last_position + 2 <= PARSER_STACK_PAGE_SIZE) 447425bb815Sopenharmony_ci { 448425bb815Sopenharmony_ci parser_mem_page_t *page_p = context_p->stack.first_p; 449425bb815Sopenharmony_ci 450425bb815Sopenharmony_ci JERRY_ASSERT (page_p != NULL 451425bb815Sopenharmony_ci && context_p->stack_top_uint8 == page_p->bytes[context_p->stack.last_position - 1]); 452425bb815Sopenharmony_ci 453425bb815Sopenharmony_ci page_p->bytes[context_p->stack.last_position++] = (uint8_t) (uint16_value >> 8); 454425bb815Sopenharmony_ci page_p->bytes[context_p->stack.last_position++] = (uint8_t) uint16_value; 455425bb815Sopenharmony_ci context_p->stack_top_uint8 = (uint8_t) uint16_value; 456425bb815Sopenharmony_ci } 457425bb815Sopenharmony_ci else 458425bb815Sopenharmony_ci { 459425bb815Sopenharmony_ci parser_stack_push_uint8 (context_p, (uint8_t) (uint16_value >> 8)); 460425bb815Sopenharmony_ci parser_stack_push_uint8 (context_p, (uint8_t) uint16_value); 461425bb815Sopenharmony_ci } 462425bb815Sopenharmony_ci} /* parser_stack_push_uint16 */ 463425bb815Sopenharmony_ci 464425bb815Sopenharmony_ci/** 465425bb815Sopenharmony_ci * Pops the last uint16_t value from the stack. 466425bb815Sopenharmony_ci * 467425bb815Sopenharmony_ci * @return the value popped from the stack. 468425bb815Sopenharmony_ci */ 469425bb815Sopenharmony_ciuint16_t 470425bb815Sopenharmony_ciparser_stack_pop_uint16 (parser_context_t *context_p) /**< context */ 471425bb815Sopenharmony_ci{ 472425bb815Sopenharmony_ci uint32_t value = context_p->stack_top_uint8; 473425bb815Sopenharmony_ci 474425bb815Sopenharmony_ci if (context_p->stack.last_position >= 3) 475425bb815Sopenharmony_ci { 476425bb815Sopenharmony_ci parser_mem_page_t *page_p = context_p->stack.first_p; 477425bb815Sopenharmony_ci 478425bb815Sopenharmony_ci JERRY_ASSERT (page_p != NULL 479425bb815Sopenharmony_ci && context_p->stack_top_uint8 == page_p->bytes[context_p->stack.last_position - 1]); 480425bb815Sopenharmony_ci 481425bb815Sopenharmony_ci value |= ((uint32_t) page_p->bytes[context_p->stack.last_position - 2]) << 8; 482425bb815Sopenharmony_ci context_p->stack_top_uint8 = page_p->bytes[context_p->stack.last_position - 3]; 483425bb815Sopenharmony_ci context_p->stack.last_position -= 2; 484425bb815Sopenharmony_ci } 485425bb815Sopenharmony_ci else 486425bb815Sopenharmony_ci { 487425bb815Sopenharmony_ci parser_stack_pop_uint8 (context_p); 488425bb815Sopenharmony_ci value |= ((uint32_t) context_p->stack_top_uint8) << 8; 489425bb815Sopenharmony_ci parser_stack_pop_uint8 (context_p); 490425bb815Sopenharmony_ci } 491425bb815Sopenharmony_ci return (uint16_t) value; 492425bb815Sopenharmony_ci} /* parser_stack_pop_uint16 */ 493425bb815Sopenharmony_ci 494425bb815Sopenharmony_ci/** 495425bb815Sopenharmony_ci * Pushes a data onto the stack. 496425bb815Sopenharmony_ci */ 497425bb815Sopenharmony_civoid 498425bb815Sopenharmony_ciparser_stack_push (parser_context_t *context_p, /**< context */ 499425bb815Sopenharmony_ci const void *data_p, /**< data pushed onto the stack */ 500425bb815Sopenharmony_ci uint32_t length) /**< length of the data */ 501425bb815Sopenharmony_ci{ 502425bb815Sopenharmony_ci uint32_t fragment_length = PARSER_STACK_PAGE_SIZE - context_p->stack.last_position; 503425bb815Sopenharmony_ci const uint8_t *bytes_p = (const uint8_t *) data_p; 504425bb815Sopenharmony_ci parser_mem_page_t *page_p; 505425bb815Sopenharmony_ci 506425bb815Sopenharmony_ci JERRY_ASSERT (length < PARSER_STACK_PAGE_SIZE && length > 0); 507425bb815Sopenharmony_ci 508425bb815Sopenharmony_ci context_p->stack_top_uint8 = bytes_p[length - 1]; 509425bb815Sopenharmony_ci 510425bb815Sopenharmony_ci if (fragment_length > 0) 511425bb815Sopenharmony_ci { 512425bb815Sopenharmony_ci /* Fill the remaining bytes. */ 513425bb815Sopenharmony_ci if (fragment_length > length) 514425bb815Sopenharmony_ci { 515425bb815Sopenharmony_ci fragment_length = length; 516425bb815Sopenharmony_ci } 517425bb815Sopenharmony_ci 518425bb815Sopenharmony_ci memcpy (context_p->stack.first_p->bytes + context_p->stack.last_position, 519425bb815Sopenharmony_ci bytes_p, 520425bb815Sopenharmony_ci fragment_length); 521425bb815Sopenharmony_ci 522425bb815Sopenharmony_ci if (fragment_length == length) 523425bb815Sopenharmony_ci { 524425bb815Sopenharmony_ci context_p->stack.last_position += length; 525425bb815Sopenharmony_ci return; 526425bb815Sopenharmony_ci } 527425bb815Sopenharmony_ci 528425bb815Sopenharmony_ci bytes_p += fragment_length; 529425bb815Sopenharmony_ci length -= fragment_length; 530425bb815Sopenharmony_ci } 531425bb815Sopenharmony_ci 532425bb815Sopenharmony_ci if (context_p->free_page_p != NULL) 533425bb815Sopenharmony_ci { 534425bb815Sopenharmony_ci page_p = context_p->free_page_p; 535425bb815Sopenharmony_ci context_p->free_page_p = NULL; 536425bb815Sopenharmony_ci } 537425bb815Sopenharmony_ci else 538425bb815Sopenharmony_ci { 539425bb815Sopenharmony_ci size_t size = sizeof (parser_mem_page_t *) + PARSER_STACK_PAGE_SIZE; 540425bb815Sopenharmony_ci 541425bb815Sopenharmony_ci page_p = (parser_mem_page_t *) parser_malloc (context_p, size); 542425bb815Sopenharmony_ci } 543425bb815Sopenharmony_ci 544425bb815Sopenharmony_ci page_p->next_p = context_p->stack.first_p; 545425bb815Sopenharmony_ci 546425bb815Sopenharmony_ci context_p->stack.first_p = page_p; 547425bb815Sopenharmony_ci 548425bb815Sopenharmony_ci memcpy (page_p->bytes, bytes_p, length); 549425bb815Sopenharmony_ci context_p->stack.last_position = length; 550425bb815Sopenharmony_ci} /* parser_stack_push */ 551425bb815Sopenharmony_ci 552425bb815Sopenharmony_ci/** 553425bb815Sopenharmony_ci * Pop bytes from the top of the stack. 554425bb815Sopenharmony_ci */ 555425bb815Sopenharmony_civoid 556425bb815Sopenharmony_ciparser_stack_pop (parser_context_t *context_p, /**< context */ 557425bb815Sopenharmony_ci void *data_p, /**< destination buffer, can be NULL */ 558425bb815Sopenharmony_ci uint32_t length) /**< length of the data */ 559425bb815Sopenharmony_ci{ 560425bb815Sopenharmony_ci uint8_t *bytes_p = (uint8_t *) data_p; 561425bb815Sopenharmony_ci parser_mem_page_t *page_p = context_p->stack.first_p; 562425bb815Sopenharmony_ci 563425bb815Sopenharmony_ci JERRY_ASSERT (length < PARSER_STACK_PAGE_SIZE && length > 0); 564425bb815Sopenharmony_ci 565425bb815Sopenharmony_ci if (context_p->stack.last_position > length) 566425bb815Sopenharmony_ci { 567425bb815Sopenharmony_ci context_p->stack.last_position -= length; 568425bb815Sopenharmony_ci context_p->stack_top_uint8 = page_p->bytes[context_p->stack.last_position - 1]; 569425bb815Sopenharmony_ci 570425bb815Sopenharmony_ci if (bytes_p != NULL) 571425bb815Sopenharmony_ci { 572425bb815Sopenharmony_ci memcpy (bytes_p, context_p->stack.first_p->bytes + context_p->stack.last_position, length); 573425bb815Sopenharmony_ci } 574425bb815Sopenharmony_ci return; 575425bb815Sopenharmony_ci } 576425bb815Sopenharmony_ci 577425bb815Sopenharmony_ci JERRY_ASSERT (page_p->next_p != NULL); 578425bb815Sopenharmony_ci 579425bb815Sopenharmony_ci length -= context_p->stack.last_position; 580425bb815Sopenharmony_ci 581425bb815Sopenharmony_ci if (bytes_p != NULL) 582425bb815Sopenharmony_ci { 583425bb815Sopenharmony_ci memcpy (bytes_p + length, page_p->bytes, context_p->stack.last_position); 584425bb815Sopenharmony_ci } 585425bb815Sopenharmony_ci 586425bb815Sopenharmony_ci context_p->stack.first_p = page_p->next_p; 587425bb815Sopenharmony_ci context_p->stack.last_position = PARSER_STACK_PAGE_SIZE - length; 588425bb815Sopenharmony_ci context_p->stack_top_uint8 = page_p->next_p->bytes[context_p->stack.last_position - 1]; 589425bb815Sopenharmony_ci 590425bb815Sopenharmony_ci if (bytes_p != NULL && length > 0) 591425bb815Sopenharmony_ci { 592425bb815Sopenharmony_ci memcpy (bytes_p, page_p->next_p->bytes + context_p->stack.last_position, length); 593425bb815Sopenharmony_ci } 594425bb815Sopenharmony_ci 595425bb815Sopenharmony_ci JERRY_ASSERT (context_p->stack.last_position > 0); 596425bb815Sopenharmony_ci 597425bb815Sopenharmony_ci if (context_p->free_page_p == NULL) 598425bb815Sopenharmony_ci { 599425bb815Sopenharmony_ci context_p->free_page_p = page_p; 600425bb815Sopenharmony_ci } 601425bb815Sopenharmony_ci else 602425bb815Sopenharmony_ci { 603425bb815Sopenharmony_ci parser_free (page_p, 604425bb815Sopenharmony_ci sizeof (parser_mem_page_t *) + PARSER_STACK_PAGE_SIZE); 605425bb815Sopenharmony_ci } 606425bb815Sopenharmony_ci} /* parser_stack_pop */ 607425bb815Sopenharmony_ci 608425bb815Sopenharmony_ci/** 609425bb815Sopenharmony_ci * Skip the next n bytes of the stack. 610425bb815Sopenharmony_ci */ 611425bb815Sopenharmony_civoid 612425bb815Sopenharmony_ciparser_stack_iterator_skip (parser_stack_iterator_t *iterator, /**< iterator */ 613425bb815Sopenharmony_ci size_t length) /**< number of skipped bytes */ 614425bb815Sopenharmony_ci{ 615425bb815Sopenharmony_ci JERRY_ASSERT (length < PARSER_STACK_PAGE_SIZE && length > 0); 616425bb815Sopenharmony_ci 617425bb815Sopenharmony_ci if (length < iterator->current_position) 618425bb815Sopenharmony_ci { 619425bb815Sopenharmony_ci iterator->current_position -= length; 620425bb815Sopenharmony_ci } 621425bb815Sopenharmony_ci else 622425bb815Sopenharmony_ci { 623425bb815Sopenharmony_ci iterator->current_position = PARSER_STACK_PAGE_SIZE - (length - iterator->current_position); 624425bb815Sopenharmony_ci iterator->current_p = iterator->current_p->next_p; 625425bb815Sopenharmony_ci } 626425bb815Sopenharmony_ci} /* parser_stack_iterator_skip */ 627425bb815Sopenharmony_ci 628425bb815Sopenharmony_ci/** 629425bb815Sopenharmony_ci * Read bytes from the stack. 630425bb815Sopenharmony_ci */ 631425bb815Sopenharmony_civoid 632425bb815Sopenharmony_ciparser_stack_iterator_read (parser_stack_iterator_t *iterator, /**< iterator */ 633425bb815Sopenharmony_ci void *data_p, /**< destination buffer */ 634425bb815Sopenharmony_ci size_t length) /**< length of the data */ 635425bb815Sopenharmony_ci{ 636425bb815Sopenharmony_ci uint8_t *bytes_p = (uint8_t *) data_p; 637425bb815Sopenharmony_ci 638425bb815Sopenharmony_ci JERRY_ASSERT (length < PARSER_STACK_PAGE_SIZE && length > 0); 639425bb815Sopenharmony_ci 640425bb815Sopenharmony_ci if (length <= iterator->current_position) 641425bb815Sopenharmony_ci { 642425bb815Sopenharmony_ci memcpy (bytes_p, 643425bb815Sopenharmony_ci iterator->current_p->bytes + iterator->current_position - length, 644425bb815Sopenharmony_ci length); 645425bb815Sopenharmony_ci } 646425bb815Sopenharmony_ci else 647425bb815Sopenharmony_ci { 648425bb815Sopenharmony_ci JERRY_ASSERT (iterator->current_p->next_p != NULL); 649425bb815Sopenharmony_ci 650425bb815Sopenharmony_ci length -= iterator->current_position; 651425bb815Sopenharmony_ci memcpy (bytes_p + length, 652425bb815Sopenharmony_ci iterator->current_p->bytes, 653425bb815Sopenharmony_ci iterator->current_position); 654425bb815Sopenharmony_ci memcpy (bytes_p, 655425bb815Sopenharmony_ci iterator->current_p->next_p->bytes + PARSER_STACK_PAGE_SIZE - length, 656425bb815Sopenharmony_ci length); 657425bb815Sopenharmony_ci } 658425bb815Sopenharmony_ci} /* parser_stack_iterator_read */ 659425bb815Sopenharmony_ci 660425bb815Sopenharmony_ci/** 661425bb815Sopenharmony_ci * Write bytes onto the stack. 662425bb815Sopenharmony_ci */ 663425bb815Sopenharmony_civoid 664425bb815Sopenharmony_ciparser_stack_iterator_write (parser_stack_iterator_t *iterator, /**< iterator */ 665425bb815Sopenharmony_ci const void *data_p, /**< destination buffer */ 666425bb815Sopenharmony_ci size_t length) /**< length of the data */ 667425bb815Sopenharmony_ci{ 668425bb815Sopenharmony_ci const uint8_t *bytes_p = (const uint8_t *) data_p; 669425bb815Sopenharmony_ci 670425bb815Sopenharmony_ci JERRY_ASSERT (length < PARSER_STACK_PAGE_SIZE && length > 0); 671425bb815Sopenharmony_ci 672425bb815Sopenharmony_ci if (length <= iterator->current_position) 673425bb815Sopenharmony_ci { 674425bb815Sopenharmony_ci memcpy (iterator->current_p->bytes + iterator->current_position - length, 675425bb815Sopenharmony_ci bytes_p, 676425bb815Sopenharmony_ci length); 677425bb815Sopenharmony_ci } 678425bb815Sopenharmony_ci else 679425bb815Sopenharmony_ci { 680425bb815Sopenharmony_ci JERRY_ASSERT (iterator->current_p->next_p != NULL); 681425bb815Sopenharmony_ci 682425bb815Sopenharmony_ci length -= iterator->current_position; 683425bb815Sopenharmony_ci memcpy (iterator->current_p->bytes, 684425bb815Sopenharmony_ci bytes_p + length, 685425bb815Sopenharmony_ci iterator->current_position); 686425bb815Sopenharmony_ci memcpy (iterator->current_p->next_p->bytes + PARSER_STACK_PAGE_SIZE - length, 687425bb815Sopenharmony_ci bytes_p, 688425bb815Sopenharmony_ci length); 689425bb815Sopenharmony_ci } 690425bb815Sopenharmony_ci} /* parser_stack_iterator_write */ 691425bb815Sopenharmony_ci 692425bb815Sopenharmony_ci/** 693425bb815Sopenharmony_ci * @} 694425bb815Sopenharmony_ci * @} 695425bb815Sopenharmony_ci */ 696425bb815Sopenharmony_ci 697425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_PARSER) */ 698