diff --git a/jerry-core/CMakeLists.txt b/jerry-core/CMakeLists.txt index 52c774f1f..aa58a3d0f 100644 --- a/jerry-core/CMakeLists.txt +++ b/jerry-core/CMakeLists.txt @@ -300,6 +300,7 @@ set(SOURCE_CORE_FILES jmem/jmem-heap.c jmem/jmem-poolman.c jrt/jrt-fatals.c + jrt/jrt-logging.c lit/lit-char-helpers.c lit/lit-magic-strings.c lit/lit-strings.c diff --git a/jerry-core/api/jerryscript.c b/jerry-core/api/jerryscript.c index f559df615..75022c7f4 100644 --- a/jerry-core/api/jerryscript.c +++ b/jerry-core/api/jerryscript.c @@ -5154,7 +5154,7 @@ jerry_validate_string (const jerry_char_t *buffer_p, /**< string buffer */ void jerry_log_set_level (jerry_log_level_t level) { - JERRY_CONTEXT (log_level) = level; + jerry_jrt_set_log_level (level); } /* jerry_log_set_level */ /** @@ -5184,25 +5184,106 @@ jerry_log_string (const char *str_p) } /* jerry_log_string */ /** - * Log an unsigned number. + * Log a fixed-size string message. * - * @param num: number - * @param buffer_p: buffer used to construct the number string + * @param str_p: message + * @param size: size + * @param buffer_p: buffer to use */ static void -jerry_log_unsigned (unsigned int num, char *buffer_p) +jerry_log_string_fixed (const char *str_p, size_t size, char *buffer_p) { - char *cursor_p = buffer_p + JERRY_LOG_BUFFER_SIZE; - *(--cursor_p) = '\0'; + const size_t batch_size = JERRY_LOG_BUFFER_SIZE - 1; - while (num > 0) + while (size > batch_size) { - *(--cursor_p) = (char) ((num % 10) + '0'); - num /= 10; + memcpy (buffer_p, str_p, batch_size); + buffer_p[batch_size] = '\0'; + jerry_log_string (buffer_p); + + str_p += batch_size; + size -= batch_size; } - jerry_log_string (cursor_p); -} /* jerry_log_unsigned */ + memcpy (buffer_p, str_p, size); + buffer_p[size] = '\0'; + jerry_log_string (buffer_p); +} /* jerry_log_string_fixed */ + +/** + * Format an unsigned number. + * + * @param num: number + * @param width: minimum width of the number + * @param padding: padding to be used when extending to minimum width + * @param radix: number radix + * @param buffer_p: buffer used to construct the number string + * + * @return formatted number as string + */ +static char * +jerry_format_unsigned (unsigned int num, uint8_t width, char padding, uint8_t radix, char *buffer_p) +{ + static const char digits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + char *cursor_p = buffer_p + JERRY_LOG_BUFFER_SIZE; + *(--cursor_p) = '\0'; + uint8_t count = 0; + + do + { + *(--cursor_p) = digits[num % radix]; + num /= radix; + count++; + } while (num > 0); + + while (count < width) + { + *(--cursor_p) = padding; + count++; + } + + return cursor_p; +} /* jerry_format_unsigned */ + +/** + * Format an integer number. + * + * @param num: number + * @param width: minimum width of the number + * @param padding: padding to be used when extending to minimum width + * @param buffer_p: buffer used to construct the number string + * + * @return formatted number as string + */ +static char * +jerry_format_int (int num, uint8_t width, char padding, char *buffer_p) +{ + if (num >= 0) + { + return jerry_format_unsigned ((unsigned) num, width, padding, 10, buffer_p); + } + + num = -num; + + if (padding == '0' && width > 0) + { + char *cursor_p = jerry_format_unsigned ((unsigned) num, --width, padding, 10, buffer_p); + *(--cursor_p) = '-'; + return cursor_p; + } + + char *cursor_p = jerry_format_unsigned ((unsigned) num, 0, ' ', 10, buffer_p); + *(--cursor_p) = '-'; + + char *indent_p = buffer_p + JERRY_LOG_BUFFER_SIZE - width - 1; + + while (cursor_p > indent_p) + { + *(--cursor_p) = ' '; + } + + return cursor_p; +} /* jerry_foramt_int */ /** * Log a zero-terminated formatted message with the specified log level. @@ -5210,7 +5291,11 @@ jerry_log_unsigned (unsigned int num, char *buffer_p) * Supported format specifiers: * %s: zero-terminated string * %c: character - * %u: unsigned int + * %u: unsigned integer + * %d: decimal integer + * %x: unsigned hexadecimal + * + * Width and padding sub-modifiers are also supported. * * @param format_p: format string * @param level: message log level @@ -5218,7 +5303,7 @@ jerry_log_unsigned (unsigned int num, char *buffer_p) void jerry_log (jerry_log_level_t level, const char *format_p, ...) { - if (level > JERRY_CONTEXT (log_level)) + if (level > jerry_jrt_get_log_level ()) { return; } @@ -5245,6 +5330,31 @@ jerry_log (jerry_log_level_t level, const char *format_p, ...) } ++cursor_p; + uint8_t width = 0; + size_t precision = 0; + char padding = ' '; + + if (*cursor_p == '0') + { + padding = '0'; + cursor_p++; + } + + if (lit_char_is_decimal_digit ((ecma_char_t) *cursor_p)) + { + width = (uint8_t) (*cursor_p - '0'); + cursor_p++; + } + else if (*cursor_p == '*') + { + width = (uint8_t) JERRY_MAX (va_arg (vl, int), 10); + cursor_p++; + } + else if (*cursor_p == '.' && *(cursor_p + 1) == '*') + { + precision = (size_t) va_arg (vl, int); + cursor_p += 2; + } if (*cursor_p == '\0') { @@ -5252,11 +5362,20 @@ jerry_log (jerry_log_level_t level, const char *format_p, ...) break; } + /* The buffer is always flushed before a substitution, and can be reused to for formatting. */ switch (*cursor_p++) { case 's': { - jerry_log_string (va_arg (vl, char *)); + char *str_p = va_arg (vl, char *); + + if (precision == 0) + { + jerry_log_string (str_p); + break; + } + + jerry_log_string_fixed (str_p, precision, buffer_p); break; } case 'c': @@ -5265,10 +5384,19 @@ jerry_log (jerry_log_level_t level, const char *format_p, ...) buffer_p[buffer_index++] = (char) va_arg (vl, int); break; } + case 'd': + { + jerry_log_string (jerry_format_int (va_arg (vl, int), width, padding, buffer_p)); + break; + } case 'u': { - /* The buffer is always flushed before a substitution, and can be reused to print the number. */ - jerry_log_unsigned (va_arg (vl, unsigned int), buffer_p); + jerry_log_string (jerry_format_unsigned (va_arg (vl, unsigned int), width, padding, 10, buffer_p)); + break; + } + case 'x': + { + jerry_log_string (jerry_format_unsigned (va_arg (vl, unsigned int), width, padding, 16, buffer_p)); break; } default: diff --git a/jerry-core/jcontext/jcontext.h b/jerry-core/jcontext/jcontext.h index 139526147..de49d97bd 100644 --- a/jerry-core/jcontext/jcontext.h +++ b/jerry-core/jcontext/jcontext.h @@ -169,7 +169,6 @@ struct jerry_context_t uint32_t lit_magic_string_ex_count; /**< external magic strings count */ uint32_t jerry_init_flags; /**< run-time configuration flags */ uint32_t status_flags; /**< run-time flags (the top 8 bits are used for passing class parsing options) */ - jerry_log_level_t log_level; /**< current log level */ #if (JERRY_GC_MARK_LIMIT != 0) uint32_t ecma_gc_mark_recursion_limit; /**< GC mark recursion limit */ diff --git a/jerry-core/jmem/jmem-heap.c b/jerry-core/jmem/jmem-heap.c index d800376cf..ce790a49a 100644 --- a/jerry-core/jmem/jmem-heap.c +++ b/jerry-core/jmem/jmem-heap.c @@ -738,32 +738,20 @@ jmem_heap_stats_print (void) JERRY_DEBUG_MSG ("Heap stats:\n"); #if !JERRY_SYSTEM_ALLOCATOR - JERRY_DEBUG_MSG (" Heap size = %zu bytes\n", heap_stats->size); + JERRY_DEBUG_MSG (" Heap size = %u bytes\n", (unsigned) heap_stats->size); #endif /* !JERRY_SYSTEM_ALLOCATOR */ - JERRY_DEBUG_MSG (" Allocated = %zu bytes\n" - " Peak allocated = %zu bytes\n" - " Waste = %zu bytes\n" - " Peak waste = %zu bytes\n" - " Allocated byte code data = %zu bytes\n" - " Peak allocated byte code data = %zu bytes\n" - " Allocated string data = %zu bytes\n" - " Peak allocated string data = %zu bytes\n" - " Allocated object data = %zu bytes\n" - " Peak allocated object data = %zu bytes\n" - " Allocated property data = %zu bytes\n" - " Peak allocated property data = %zu bytes\n", - heap_stats->allocated_bytes, - heap_stats->peak_allocated_bytes, - heap_stats->waste_bytes, - heap_stats->peak_waste_bytes, - heap_stats->byte_code_bytes, - heap_stats->peak_byte_code_bytes, - heap_stats->string_bytes, - heap_stats->peak_string_bytes, - heap_stats->object_bytes, - heap_stats->peak_object_bytes, - heap_stats->property_bytes, - heap_stats->peak_property_bytes); + JERRY_DEBUG_MSG (" Allocated = %u bytes\n", (unsigned) heap_stats->allocated_bytes); + JERRY_DEBUG_MSG (" Peak allocated = %u bytes\n", (unsigned) heap_stats->peak_allocated_bytes); + JERRY_DEBUG_MSG (" Waste = %u bytes\n", (unsigned) heap_stats->waste_bytes); + JERRY_DEBUG_MSG (" Peak waste = %u bytes\n", (unsigned) heap_stats->peak_waste_bytes); + JERRY_DEBUG_MSG (" Allocated byte code data = %u bytes\n", (unsigned) heap_stats->byte_code_bytes); + JERRY_DEBUG_MSG (" Peak allocated byte code data = %u bytes\n", (unsigned) heap_stats->peak_byte_code_bytes); + JERRY_DEBUG_MSG (" Allocated string data = %u bytes\n", (unsigned) heap_stats->string_bytes); + JERRY_DEBUG_MSG (" Peak allocated string data = %u bytes\n", (unsigned) heap_stats->peak_string_bytes); + JERRY_DEBUG_MSG (" Allocated object data = %u bytes\n", (unsigned) heap_stats->object_bytes); + JERRY_DEBUG_MSG (" Peak allocated object data = %u bytes\n", (unsigned) heap_stats->peak_object_bytes); + JERRY_DEBUG_MSG (" Allocated property data = %u bytes\n", (unsigned) heap_stats->property_bytes); + JERRY_DEBUG_MSG (" Peak allocated property data = %u bytes\n", (unsigned) heap_stats->peak_property_bytes); } /* jmem_heap_stats_print */ /** diff --git a/jerry-core/jrt/jrt-logging.c b/jerry-core/jrt/jrt-logging.c new file mode 100644 index 000000000..78ff2c5e9 --- /dev/null +++ b/jerry-core/jrt/jrt-logging.c @@ -0,0 +1,40 @@ +/* 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 + +static jerry_log_level_t jerry_log_level = JERRY_LOG_LEVEL_ERROR; + +/** + * Get current log level + * + * @return log level + */ +jerry_log_level_t +jerry_jrt_get_log_level (void) +{ + return jerry_log_level; +} /* jerry_jrt_get_log_level */ + +/** + * Set log level + * + * @param level: new log level + */ +void +jerry_jrt_set_log_level (jerry_log_level_t level) +{ + jerry_log_level = level; +} /* jerry_jrt_set_log_level */ diff --git a/jerry-core/jrt/jrt.h b/jerry-core/jrt/jrt.h index 6d4447208..973d4fc3d 100644 --- a/jerry-core/jrt/jrt.h +++ b/jerry-core/jrt/jrt.h @@ -117,6 +117,9 @@ void JERRY_ATTR_NORETURN jerry_unreachable (const char *file, const char *functi */ void JERRY_ATTR_NORETURN jerry_fatal (jerry_fatal_code_t code); +jerry_log_level_t jerry_jrt_get_log_level (void); +void jerry_jrt_set_log_level (jerry_log_level_t level); + /* * Logging */