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 "jerryscript-ext/handler.h"
17425bb815Sopenharmony_ci#include "jerryscript-port.h"
18425bb815Sopenharmony_ci#include "jerryscript-debugger.h"
19425bb815Sopenharmony_ci
20425bb815Sopenharmony_ci/**
21425bb815Sopenharmony_ci * Provide a 'print' implementation for scripts.
22425bb815Sopenharmony_ci *
23425bb815Sopenharmony_ci * The routine converts all of its arguments to strings and outputs them
24425bb815Sopenharmony_ci * char-by-char using jerry_port_print_char.
25425bb815Sopenharmony_ci *
26425bb815Sopenharmony_ci * The NUL character is output as "\u0000", other characters are output
27425bb815Sopenharmony_ci * bytewise.
28425bb815Sopenharmony_ci *
29425bb815Sopenharmony_ci * Note:
30425bb815Sopenharmony_ci *      This implementation does not use standard C `printf` to print its
31425bb815Sopenharmony_ci *      output. This allows more flexibility but also extends the core
32425bb815Sopenharmony_ci *      JerryScript engine port API. Applications that want to use
33425bb815Sopenharmony_ci *      `jerryx_handler_print` must ensure that their port implementation also
34425bb815Sopenharmony_ci *      provides `jerry_port_print_char`.
35425bb815Sopenharmony_ci *
36425bb815Sopenharmony_ci * @return undefined - if all arguments could be converted to strings,
37425bb815Sopenharmony_ci *         error - otherwise.
38425bb815Sopenharmony_ci */
39425bb815Sopenharmony_cijerry_value_t
40425bb815Sopenharmony_cijerryx_handler_print (const jerry_value_t func_obj_val, /**< function object */
41425bb815Sopenharmony_ci                      const jerry_value_t this_p, /**< this arg */
42425bb815Sopenharmony_ci                      const jerry_value_t args_p[], /**< function arguments */
43425bb815Sopenharmony_ci                      const jerry_length_t args_cnt) /**< number of function arguments */
44425bb815Sopenharmony_ci{
45425bb815Sopenharmony_ci  (void) func_obj_val; /* unused */
46425bb815Sopenharmony_ci  (void) this_p; /* unused */
47425bb815Sopenharmony_ci
48425bb815Sopenharmony_ci  const char * const null_str = "\\u0000";
49425bb815Sopenharmony_ci
50425bb815Sopenharmony_ci  jerry_value_t ret_val = jerry_create_undefined ();
51425bb815Sopenharmony_ci
52425bb815Sopenharmony_ci  for (jerry_length_t arg_index = 0; arg_index < args_cnt; arg_index++)
53425bb815Sopenharmony_ci  {
54425bb815Sopenharmony_ci    jerry_value_t str_val;
55425bb815Sopenharmony_ci
56425bb815Sopenharmony_ci    if (jerry_value_is_symbol (args_p[arg_index]))
57425bb815Sopenharmony_ci    {
58425bb815Sopenharmony_ci      str_val = jerry_get_symbol_descriptive_string (args_p[arg_index]);
59425bb815Sopenharmony_ci    }
60425bb815Sopenharmony_ci    else
61425bb815Sopenharmony_ci    {
62425bb815Sopenharmony_ci      str_val = jerry_value_to_string (args_p[arg_index]);
63425bb815Sopenharmony_ci    }
64425bb815Sopenharmony_ci
65425bb815Sopenharmony_ci    if (jerry_value_is_error (str_val))
66425bb815Sopenharmony_ci    {
67425bb815Sopenharmony_ci      /* There is no need to free the undefined value. */
68425bb815Sopenharmony_ci      ret_val = str_val;
69425bb815Sopenharmony_ci      break;
70425bb815Sopenharmony_ci    }
71425bb815Sopenharmony_ci
72425bb815Sopenharmony_ci    jerry_length_t length = jerry_get_utf8_string_length (str_val);
73425bb815Sopenharmony_ci    jerry_length_t substr_pos = 0;
74425bb815Sopenharmony_ci    jerry_char_t substr_buf[256];
75425bb815Sopenharmony_ci
76425bb815Sopenharmony_ci    do
77425bb815Sopenharmony_ci    {
78425bb815Sopenharmony_ci      jerry_size_t substr_size = jerry_substring_to_utf8_char_buffer (str_val,
79425bb815Sopenharmony_ci                                                                      substr_pos,
80425bb815Sopenharmony_ci                                                                      length,
81425bb815Sopenharmony_ci                                                                      substr_buf,
82425bb815Sopenharmony_ci                                                                      256 - 1);
83425bb815Sopenharmony_ci
84425bb815Sopenharmony_ci      jerry_char_t *buf_end_p = substr_buf + substr_size;
85425bb815Sopenharmony_ci
86425bb815Sopenharmony_ci      /* Update start position by the number of utf-8 characters. */
87425bb815Sopenharmony_ci      for (jerry_char_t *buf_p = substr_buf; buf_p < buf_end_p; buf_p++)
88425bb815Sopenharmony_ci      {
89425bb815Sopenharmony_ci        /* Skip intermediate utf-8 octets. */
90425bb815Sopenharmony_ci        if ((*buf_p & 0xc0) != 0x80)
91425bb815Sopenharmony_ci        {
92425bb815Sopenharmony_ci          substr_pos++;
93425bb815Sopenharmony_ci        }
94425bb815Sopenharmony_ci      }
95425bb815Sopenharmony_ci
96425bb815Sopenharmony_ci      if (substr_pos == length)
97425bb815Sopenharmony_ci      {
98425bb815Sopenharmony_ci        *buf_end_p++ = (arg_index < args_cnt - 1) ? ' ' : '\n';
99425bb815Sopenharmony_ci      }
100425bb815Sopenharmony_ci
101425bb815Sopenharmony_ci      for (jerry_char_t *buf_p = substr_buf; buf_p < buf_end_p; buf_p++)
102425bb815Sopenharmony_ci      {
103425bb815Sopenharmony_ci        char chr = (char) *buf_p;
104425bb815Sopenharmony_ci
105425bb815Sopenharmony_ci        if (chr != '\0')
106425bb815Sopenharmony_ci        {
107425bb815Sopenharmony_ci          jerry_port_print_char (chr);
108425bb815Sopenharmony_ci          continue;
109425bb815Sopenharmony_ci        }
110425bb815Sopenharmony_ci
111425bb815Sopenharmony_ci        for (jerry_size_t null_index = 0; null_str[null_index] != '\0'; null_index++)
112425bb815Sopenharmony_ci        {
113425bb815Sopenharmony_ci          jerry_port_print_char (null_str[null_index]);
114425bb815Sopenharmony_ci        }
115425bb815Sopenharmony_ci      }
116425bb815Sopenharmony_ci    }
117425bb815Sopenharmony_ci    while (substr_pos < length);
118425bb815Sopenharmony_ci
119425bb815Sopenharmony_ci    jerry_release_value (str_val);
120425bb815Sopenharmony_ci  }
121425bb815Sopenharmony_ci
122425bb815Sopenharmony_ci  if (args_cnt == 0 || jerry_value_is_error (ret_val))
123425bb815Sopenharmony_ci  {
124425bb815Sopenharmony_ci    jerry_port_print_char ('\n');
125425bb815Sopenharmony_ci  }
126425bb815Sopenharmony_ci
127425bb815Sopenharmony_ci  return ret_val;
128425bb815Sopenharmony_ci} /* jerryx_handler_print */
129