forked from xuos/xiuos
				
			
		
			
				
	
	
		
			340 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			340 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			C
		
	
	
	
| /* Copyright JS Foundation and other contributors, http://js.foundation
 | |
|  *
 | |
|  * Licensed under the Apache License, Version 2.0 (the "License");
 | |
|  * you may not use this file except in compliance with the License.
 | |
|  * You may obtain a copy of the License at
 | |
|  *
 | |
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | |
|  *
 | |
|  * Unless required by applicable law or agreed to in writing, software
 | |
|  * distributed under the License is distributed on an "AS IS" BASIS
 | |
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
|  * See the License for the specific language governing permissions and
 | |
|  * limitations under the License.
 | |
|  */
 | |
| 
 | |
| #include <assert.h>
 | |
| #include <stdio.h>
 | |
| #include <stdlib.h>
 | |
| #include <string.h>
 | |
| 
 | |
| #include "jerryscript.h"
 | |
| #include "jerryscript-ext/debugger.h"
 | |
| #include "jerryscript-ext/handler.h"
 | |
| #include "jerryscript-port.h"
 | |
| #include "jerryscript-port-default.h"
 | |
| 
 | |
| #include "main-utils.h"
 | |
| #include "main-options.h"
 | |
| 
 | |
| /**
 | |
|  * Temporal buffer size.
 | |
|  */
 | |
| #define JERRY_BUFFER_SIZE 256u
 | |
| 
 | |
| #if defined (JERRY_EXTERNAL_CONTEXT) && (JERRY_EXTERNAL_CONTEXT == 1)
 | |
| /**
 | |
|  * The alloc function passed to jerry_create_context
 | |
|  */
 | |
| static void *
 | |
| context_alloc (size_t size,
 | |
|                void *cb_data_p)
 | |
| {
 | |
|   (void) cb_data_p; /* unused */
 | |
|   return malloc (size);
 | |
| } /* context_alloc */
 | |
| #endif /* defined (JERRY_EXTERNAL_CONTEXT) && (JERRY_EXTERNAL_CONTEXT == 1) */
 | |
| 
 | |
| int
 | |
| main (int argc,
 | |
|       char **argv)
 | |
| {
 | |
|   union
 | |
|   {
 | |
|     double d;
 | |
|     unsigned u;
 | |
|   } now = { .d = jerry_port_get_current_time () };
 | |
|   srand (now.u);
 | |
| 
 | |
|   JERRY_VLA (main_source_t, sources_p, argc);
 | |
| 
 | |
|   main_args_t arguments;
 | |
|   arguments.sources_p = sources_p;
 | |
| 
 | |
|   main_parse_args (argc, argv, &arguments);
 | |
| 
 | |
| #if defined (JERRY_EXTERNAL_CONTEXT) && (JERRY_EXTERNAL_CONTEXT == 1)
 | |
|   jerry_context_t *context_p = jerry_create_context (JERRY_GLOBAL_HEAP_SIZE * 1024, context_alloc, NULL);
 | |
|   jerry_port_default_set_current_context (context_p);
 | |
| #endif /* defined (JERRY_EXTERNAL_CONTEXT) && (JERRY_EXTERNAL_CONTEXT == 1) */
 | |
| 
 | |
| restart:
 | |
|   main_init_engine (&arguments);
 | |
|   int return_code = JERRY_STANDALONE_EXIT_CODE_FAIL;
 | |
|   jerry_value_t ret_value;
 | |
| 
 | |
|   for (uint32_t source_index = 0; source_index < arguments.source_count; source_index++)
 | |
|   {
 | |
|     main_source_t *source_file_p = sources_p + source_index;
 | |
|     const char *file_path_p = argv[source_file_p->path_index];
 | |
| 
 | |
|     size_t source_size;
 | |
|     uint8_t *source_p = jerry_port_read_source (file_path_p, &source_size);
 | |
| 
 | |
|     if (source_p == NULL)
 | |
|     {
 | |
|       goto exit;
 | |
|     }
 | |
| 
 | |
|     uint32_t parse_opts = JERRY_PARSE_NO_OPTS;
 | |
| 
 | |
|     switch (source_file_p->type)
 | |
|     {
 | |
|       case SOURCE_SNAPSHOT:
 | |
|       {
 | |
|         ret_value = jerry_exec_snapshot ((uint32_t *) source_p,
 | |
|                                          source_size,
 | |
|                                          source_file_p->snapshot_index,
 | |
|                                          JERRY_SNAPSHOT_EXEC_COPY_DATA);
 | |
| 
 | |
|         jerry_port_release_source (source_p);
 | |
|         break;
 | |
|       }
 | |
|       case SOURCE_MODULE:
 | |
|       {
 | |
|         parse_opts = JERRY_PARSE_MODULE;
 | |
|         /* FALLTHRU */
 | |
|       }
 | |
|       default:
 | |
|       {
 | |
|         assert (source_file_p->type == SOURCE_SCRIPT
 | |
|                 || source_file_p->type == SOURCE_MODULE);
 | |
| 
 | |
|         if (!jerry_is_valid_utf8_string ((jerry_char_t *) source_p, (jerry_size_t) source_size))
 | |
|         {
 | |
|           jerry_port_release_source (source_p);
 | |
|           jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Input must be a valid UTF-8 string.");
 | |
|           goto exit;
 | |
|         }
 | |
| 
 | |
|         ret_value = jerry_parse ((jerry_char_t *) file_path_p,
 | |
|                                  strlen (file_path_p),
 | |
|                                  source_p,
 | |
|                                  source_size,
 | |
|                                  parse_opts);
 | |
| 
 | |
|         jerry_port_release_source (source_p);
 | |
| 
 | |
|         if (!jerry_value_is_error (ret_value) && !(arguments.option_flags & OPT_FLAG_PARSE_ONLY))
 | |
|         {
 | |
|           jerry_value_t func_val = ret_value;
 | |
|           ret_value = jerry_run (func_val);
 | |
|           jerry_release_value (func_val);
 | |
|         }
 | |
| 
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if (jerry_value_is_error (ret_value))
 | |
|     {
 | |
|       if (main_is_value_reset (ret_value))
 | |
|       {
 | |
|         jerry_cleanup ();
 | |
| 
 | |
|         goto restart;
 | |
|       }
 | |
| 
 | |
|       main_print_unhandled_exception (ret_value);
 | |
|       goto exit;
 | |
|     }
 | |
| 
 | |
|     jerry_release_value (ret_value);
 | |
|   }
 | |
| 
 | |
|   if (arguments.option_flags & OPT_FLAG_WAIT_SOURCE)
 | |
|   {
 | |
|     while (true)
 | |
|     {
 | |
|       jerry_debugger_wait_for_source_status_t receive_status;
 | |
|       receive_status = jerry_debugger_wait_for_client_source (main_wait_for_source_callback,
 | |
|                                                               NULL,
 | |
|                                                               &ret_value);
 | |
| 
 | |
|       if (receive_status == JERRY_DEBUGGER_SOURCE_RECEIVE_FAILED)
 | |
|       {
 | |
|         jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Connection aborted before source arrived.");
 | |
|         goto exit;
 | |
|       }
 | |
| 
 | |
|       if (receive_status == JERRY_DEBUGGER_SOURCE_END)
 | |
|       {
 | |
|         jerry_port_log (JERRY_LOG_LEVEL_DEBUG, "No more client source.\n");
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       assert (receive_status == JERRY_DEBUGGER_CONTEXT_RESET_RECEIVED
 | |
|               || receive_status == JERRY_DEBUGGER_SOURCE_RECEIVED);
 | |
| 
 | |
|       if (receive_status == JERRY_DEBUGGER_CONTEXT_RESET_RECEIVED
 | |
|           || main_is_value_reset (ret_value))
 | |
|       {
 | |
|         jerry_cleanup ();
 | |
|         goto restart;
 | |
|       }
 | |
| 
 | |
|       assert (receive_status == JERRY_DEBUGGER_SOURCE_RECEIVED);
 | |
|       jerry_release_value (ret_value);
 | |
|     }
 | |
|   }
 | |
|   else if (arguments.option_flags & OPT_FLAG_USE_STDIN)
 | |
|   {
 | |
|     char buffer[JERRY_BUFFER_SIZE];
 | |
|     char *source_p = NULL;
 | |
|     size_t source_size = 0;
 | |
| 
 | |
|     while (!feof (stdin))
 | |
|     {
 | |
|       size_t read_bytes = fread (buffer, 1u, JERRY_BUFFER_SIZE, stdin);
 | |
| 
 | |
|       size_t new_size = source_size + read_bytes;
 | |
|       source_p = realloc (source_p, new_size);
 | |
| 
 | |
|       memcpy (source_p + source_size, buffer, read_bytes);
 | |
|       source_size = new_size;
 | |
|     }
 | |
| 
 | |
|     ret_value = jerry_parse (NULL, 0, (jerry_char_t *) source_p, source_size, JERRY_PARSE_NO_OPTS);
 | |
|     free (source_p);
 | |
| 
 | |
|     if (jerry_value_is_error (ret_value))
 | |
|     {
 | |
|       main_print_unhandled_exception (ret_value);
 | |
|       goto exit;
 | |
|     }
 | |
| 
 | |
|     jerry_value_t func_val = ret_value;
 | |
|     ret_value = jerry_run (func_val);
 | |
|     jerry_release_value (func_val);
 | |
| 
 | |
|     if (jerry_value_is_error (ret_value))
 | |
|     {
 | |
|       main_print_unhandled_exception (ret_value);
 | |
|       goto exit;
 | |
|     }
 | |
| 
 | |
|     jerry_release_value (ret_value);
 | |
|   }
 | |
|   else if (arguments.source_count == 0)
 | |
|   {
 | |
|     const char *prompt = (arguments.option_flags & OPT_FLAG_NO_PROMPT) ? "" : "jerry> ";
 | |
|     char buffer[JERRY_BUFFER_SIZE];
 | |
| 
 | |
|     while (true)
 | |
|     {
 | |
|       printf ("%s", prompt);
 | |
|       char *str_p = fgets (buffer, JERRY_BUFFER_SIZE, stdin);
 | |
| 
 | |
|       if (str_p == NULL)
 | |
|       {
 | |
|         printf ("\n");
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       size_t len = strlen (str_p);
 | |
| 
 | |
|       if (len == 0)
 | |
|       {
 | |
|         continue;
 | |
|       }
 | |
| 
 | |
|       if (!jerry_is_valid_utf8_string ((jerry_char_t *) str_p, (jerry_size_t) len))
 | |
|       {
 | |
|         jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Input must be a valid UTF-8 string.\n");
 | |
|         continue;
 | |
|       }
 | |
| 
 | |
|       ret_value = jerry_parse (NULL, 0, (jerry_char_t *) str_p, len, JERRY_PARSE_NO_OPTS);
 | |
| 
 | |
|       if (jerry_value_is_error (ret_value))
 | |
|       {
 | |
|         main_print_unhandled_exception (ret_value);
 | |
|         continue;
 | |
|       }
 | |
| 
 | |
|       jerry_value_t func_val = ret_value;
 | |
|       ret_value = jerry_run (func_val);
 | |
|       jerry_release_value (func_val);
 | |
| 
 | |
|       if (jerry_value_is_error (ret_value))
 | |
|       {
 | |
|         main_print_unhandled_exception (ret_value);
 | |
|         continue;
 | |
|       }
 | |
| 
 | |
|       const jerry_value_t args[] = { ret_value };
 | |
|       jerry_value_t ret_val_print = jerryx_handler_print (jerry_create_undefined (),
 | |
|                                                           jerry_create_undefined (),
 | |
|                                                           args,
 | |
|                                                           1);
 | |
|       jerry_release_value (ret_val_print);
 | |
|       jerry_release_value (ret_value);
 | |
|       ret_value = jerry_run_all_enqueued_jobs ();
 | |
| 
 | |
|       if (jerry_value_is_error (ret_value))
 | |
|       {
 | |
|         main_print_unhandled_exception (ret_value);
 | |
|         continue;
 | |
|       }
 | |
| 
 | |
|       jerry_release_value (ret_value);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   ret_value = jerry_run_all_enqueued_jobs ();
 | |
| 
 | |
|   if (jerry_value_is_error (ret_value))
 | |
|   {
 | |
|     main_print_unhandled_exception (ret_value);
 | |
|     goto exit;
 | |
|   }
 | |
| 
 | |
|   jerry_release_value (ret_value);
 | |
| 
 | |
|   if (arguments.exit_cb_name_p != NULL)
 | |
|   {
 | |
|     jerry_value_t global = jerry_get_global_object ();
 | |
|     jerry_value_t name_str = jerry_create_string ((jerry_char_t *) arguments.exit_cb_name_p);
 | |
|     jerry_value_t callback_fn = jerry_get_property (global, name_str);
 | |
| 
 | |
|     jerry_release_value (global);
 | |
|     jerry_release_value (name_str);
 | |
| 
 | |
|     if (jerry_value_is_function (callback_fn))
 | |
|     {
 | |
|       ret_value = jerry_call_function (callback_fn, jerry_create_undefined (), NULL, 0);
 | |
| 
 | |
|       if (jerry_value_is_error (ret_value))
 | |
|       {
 | |
|         main_print_unhandled_exception (ret_value);
 | |
|         goto exit;
 | |
|       }
 | |
| 
 | |
|       jerry_release_value (ret_value);
 | |
|     }
 | |
| 
 | |
|     jerry_release_value (callback_fn);
 | |
|   }
 | |
| 
 | |
|   return_code = JERRY_STANDALONE_EXIT_CODE_OK;
 | |
| 
 | |
| exit:
 | |
|   jerry_cleanup ();
 | |
| 
 | |
| #if defined (JERRY_EXTERNAL_CONTEXT) && (JERRY_EXTERNAL_CONTEXT == 1)
 | |
|   free (context_p);
 | |
| #endif /* defined (JERRY_EXTERNAL_CONTEXT) && (JERRY_EXTERNAL_CONTEXT == 1) */
 | |
| 
 | |
|   return return_code;
 | |
| } /* main */
 |