Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
Third Party Musl
提交
503dfc5a
T
Third Party Musl
项目概览
OpenHarmony
/
Third Party Musl
1 年多 前同步成功
通知
37
Star
125
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
T
Third Party Musl
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
未验证
提交
503dfc5a
编写于
7月 26, 2022
作者:
O
openharmony_ci
提交者:
Gitee
7月 26, 2022
浏览文件
操作
浏览文件
下载
差异文件
!417 musl支持Hilog输出
Merge pull request !417 from dhy308/branch_musl_hilog
上级
e4b0a488
03c6f68e
变更
11
显示空白变更内容
内联
并排
Showing
11 changed file
with
1881 addition
and
9 deletion
+1881
-9
musl_config.gni
musl_config.gni
+4
-0
musl_src.gni
musl_src.gni
+7
-0
musl_template.gni
musl_template.gni
+4
-0
porting/linux/user/ldso/ld_log.h
porting/linux/user/ldso/ld_log.h
+6
-4
porting/linux/user/src/hilog/hilog_adapter.c
porting/linux/user/src/hilog/hilog_adapter.c
+122
-0
porting/linux/user/src/hilog/hilog_common.h
porting/linux/user/src/hilog/hilog_common.h
+54
-0
porting/linux/user/src/hilog/output_p.inl
porting/linux/user/src/hilog/output_p.inl
+1300
-0
porting/linux/user/src/hilog/vsnprintf_s_p.c
porting/linux/user/src/hilog/vsnprintf_s_p.c
+290
-0
porting/linux/user/src/hilog/vsnprintf_s_p.h
porting/linux/user/src/hilog/vsnprintf_s_p.h
+38
-0
porting/linux/user/src/internal/hilog_adapter.h
porting/linux/user/src/internal/hilog_adapter.h
+49
-0
porting/linux/user/src/internal/musl_log.h
porting/linux/user/src/internal/musl_log.h
+7
-5
未找到文件。
musl_config.gni
浏览文件 @
503dfc5a
...
...
@@ -49,3 +49,7 @@ declare_args() {
# musl_linker_extension
# }
}
declare_args() {
enable_musl_log = false
}
musl_src.gni
浏览文件 @
503dfc5a
...
...
@@ -327,6 +327,8 @@ musl_src_file = [
"src/internal/syscall_ret.c",
"src/internal/vdso.c",
"src/internal/version.c",
"src/hilog/hilog_adapter.c",
"src/hilog/vsnprintf_s_p.c",
"src/ipc/ftok.c",
"src/ipc/msgctl.c",
"src/ipc/msgget.c",
...
...
@@ -1876,6 +1878,9 @@ musl_src_porting_file = [
"include/unistd.h",
"include/dlfcn.h",
"include/dlfcn_ext.h",
"src/hilog/hilog_common.h",
"src/hilog/vsnprintf_s_p.h",
"src/internal/hilog_adapter.h",
"src/internal/musl_log.h",
"src/info/application_target_sdk_version.c",
"src/info/device_api_version.c",
...
...
@@ -1931,6 +1936,8 @@ musl_src_porting_file = [
"src/signal/signal.c",
"include/langinfo.h",
"include/locale.h",
"src/hilog/hilog_adapter.c",
"src/hilog/vsnprintf_s_p.c",
"src/internal/libc.h",
"src/locale/dcngettext.c",
"src/locale/locale_map.c",
...
...
musl_template.gni
浏览文件 @
503dfc5a
...
...
@@ -185,6 +185,10 @@ template("musl_libs") {
defines += [ "OHOS_DNS_PROXY_BY_NETSYS=1" ]
}
if (enable_musl_log) {
defines += [ "ENABLE_MUSL_LOG" ]
}
dynamic_list =
rebase_path("${target_out_dir}/${musl_ported_dir}/dynamic.list")
...
...
porting/linux/user/ldso/ld_log.h
浏览文件 @
503dfc5a
...
...
@@ -25,26 +25,28 @@
#define LD_LOG_LEVEL (LD_LOG_ERROR | LD_LOG_WARNING)
#define LD_LOG_TAG "MUSL-LDSO"
#if (LD_LOG_LEVEL & LD_LOG_ERROR)
#define LD_LOGE(...)
MUSL_LOGE(...
)
#define LD_LOGE(...)
((void)HiLogAdapterPrint(MUSL_LOG_TYPE, LOG_ERROR, MUSL_LOG_DOMAIN, LD_LOG_TAG, __VA_ARGS__)
)
#else
#define LD_LOGE(...)
#endif
#if (LD_LOG_LEVEL & LD_LOG_WARNING)
#define LD_LOGW(...)
MUSL_LOGW(...
)
#define LD_LOGW(...)
((void)HiLogAdapterPrint(MUSL_LOG_TYPE, LOG_WARN, MUSL_LOG_DOMAIN, LD_LOG_TAG, __VA_ARGS__)
)
#else
#define LD_LOGW(...)
#endif
#if (LD_LOG_LEVEL & LD_LOG_INFO)
#define LD_LOGI(...)
MUSL_LOGI(...
)
#define LD_LOGI(...)
((void)HiLogAdapterPrint(MUSL_LOG_TYPE, LOG_INFO, MUSL_LOG_DOMAIN, LD_LOG_TAG, __VA_ARGS__)
)
#else
#define LD_LOGI(...)
#endif
#if (LD_LOG_LEVEL & LD_LOG_DEBUG)
#define LD_LOGD(...)
MUSL_LOGD(...
)
#define LD_LOGD(...)
((void)HiLogAdapterPrint(MUSL_LOG_TYPE, LOG_DEBUG, MUSL_LOG_DOMAIN, LD_LOG_TAG, __VA_ARGS__)
)
#else
#define LD_LOGD(...)
#endif
...
...
porting/linux/user/src/hilog/hilog_adapter.c
0 → 100644
浏览文件 @
503dfc5a
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* 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.
*/
#define _GNU_SOURCE
#include <hilog_adapter.h>
#include "hilog_common.h"
#include "vsnprintf_s_p.h"
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <time.h>
#include <sys/time.h>
#include <sys/uio.h>
#include <sys/un.h>
#include <unistd.h>
#define LOG_LEN 3
#define ERROR_FD 2
const
int
SOCKET_TYPE
=
SOCK_DGRAM
|
SOCK_NONBLOCK
|
SOCK_CLOEXEC
;
const
int
INVALID_SOCKET
=
-
1
;
const
struct
sockaddr_un
SOCKET_ADDR
=
{
AF_UNIX
,
SOCKET_FILE_DIR
INPUT_SOCKET_NAME
};
static
int
SendMessage
(
HilogMsg
*
header
,
const
char
*
tag
,
uint16_t
tagLen
,
const
char
*
fmt
,
uint16_t
fmtLen
)
{
int
socketFd
=
TEMP_FAILURE_RETRY
(
socket
(
AF_UNIX
,
SOCKET_TYPE
,
0
));
if
(
socketFd
<
0
)
{
dprintf
(
ERROR_FD
,
"%s %d Can't create socket! Errno: %d
\n
"
,
__FILE__
,
__LINE__
,
errno
);
return
socketFd
;
}
long
int
result
=
TEMP_FAILURE_RETRY
(
connect
(
socketFd
,
(
const
struct
sockaddr
*
)(
&
SOCKET_ADDR
),
sizeof
(
SOCKET_ADDR
)));
if
(
result
<
0
)
{
dprintf
(
ERROR_FD
,
"%s %d Can't connect to server. Errno: %d
\n
"
,
__FILE__
,
__LINE__
,
errno
);
if
(
socketFd
>=
0
)
{
close
(
socketFd
);
}
return
result
;
}
struct
timespec
ts
=
{
0
};
(
void
)
clock_gettime
(
CLOCK_REALTIME
,
&
ts
);
struct
timespec
ts_mono
=
{
0
};
(
void
)
clock_gettime
(
CLOCK_MONOTONIC
,
&
ts_mono
);
header
->
tv_sec
=
(
uint32_t
)(
ts
.
tv_sec
);
header
->
tv_nsec
=
(
uint32_t
)(
ts
.
tv_nsec
);
header
->
mono_sec
=
(
uint32_t
)(
ts_mono
.
tv_sec
);
header
->
len
=
sizeof
(
HilogMsg
)
+
tagLen
+
fmtLen
;
header
->
tag_len
=
tagLen
;
struct
iovec
vec
[
LOG_LEN
]
=
{
0
};
vec
[
0
].
iov_base
=
header
;
// 0 : index of hos log header
vec
[
0
].
iov_len
=
sizeof
(
HilogMsg
);
// 0 : index of hos log header
vec
[
1
].
iov_base
=
(
void
*
)((
char
*
)(
tag
));
// 1 : index of log tag
vec
[
1
].
iov_len
=
tagLen
;
// 1 : index of log tag
vec
[
2
].
iov_base
=
(
void
*
)((
char
*
)(
fmt
));
// 2 : index of log content
vec
[
2
].
iov_len
=
fmtLen
;
// 2 : index of log content
int
ret
=
TEMP_FAILURE_RETRY
(
writev
(
socketFd
,
vec
,
LOG_LEN
));
if
(
socketFd
>=
0
)
{
close
(
socketFd
);
}
return
ret
;
}
static
int
HiLogAdapterPrintArgs
(
const
LogType
type
,
const
LogLevel
level
,
const
unsigned
int
domain
,
const
char
*
tag
,
const
char
*
fmt
,
va_list
ap
)
{
if
(
!
HiLogAdapterIsLoggable
(
domain
,
tag
,
level
))
{
return
-
1
;
}
char
buf
[
MAX_LOG_LEN
]
=
{
0
};
vsnprintfp_s
(
buf
,
MAX_LOG_LEN
,
MAX_LOG_LEN
-
1
,
true
,
fmt
,
ap
);
size_t
tagLen
=
strnlen
(
tag
,
MAX_TAG_LEN
-
1
);
size_t
logLen
=
strnlen
(
buf
,
MAX_LOG_LEN
-
1
);
HilogMsg
header
=
{
0
};
header
.
type
=
type
;
header
.
level
=
level
;
#ifndef __RECV_MSG_WITH_UCRED_
header
.
pid
=
getpid
();
#endif
header
.
tid
=
(
uint32_t
)(
gettid
());
header
.
domain
=
domain
;
return
SendMessage
(
&
header
,
tag
,
tagLen
+
1
,
buf
,
logLen
+
1
);
}
int
HiLogAdapterPrint
(
LogType
type
,
LogLevel
level
,
unsigned
int
domain
,
const
char
*
tag
,
const
char
*
fmt
,
...)
{
int
ret
;
va_list
ap
;
va_start
(
ap
,
fmt
);
ret
=
HiLogAdapterPrintArgs
(
type
,
level
,
domain
,
tag
,
fmt
,
ap
);
va_end
(
ap
);
return
ret
;
}
bool
HiLogAdapterIsLoggable
(
unsigned
int
domain
,
const
char
*
tag
,
LogLevel
level
)
{
if
((
level
<=
LOG_LEVEL_MIN
)
||
(
level
>=
LOG_LEVEL_MAX
)
||
tag
==
NULL
)
{
return
false
;
}
return
true
;
}
porting/linux/user/src/hilog/hilog_common.h
0 → 100644
浏览文件 @
503dfc5a
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* 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.
*/
#ifndef HILOG_COMMON_H
#define HILOG_COMMON_H
#include <stdint.h>
#include <stddef.h>
#define SOCKET_FILE_DIR "/dev/unix/socket/"
#define INPUT_SOCKET_NAME "hilogInput"
#define MAX_LOG_LEN 1024
/* maximum length of a log, include '\0' */
#define MAX_TAG_LEN 32
/* log tag size, include '\0' */
/*
* header of log message from libhilog to hilogd
*/
typedef
struct
__attribute__
((
__packed__
))
{
uint16_t
len
;
uint16_t
version
:
3
;
uint16_t
type
:
4
;
/* APP,CORE,INIT,SEC etc */
uint16_t
level
:
3
;
uint16_t
tag_len
:
6
;
/* include '\0' */
uint32_t
tv_sec
;
uint32_t
tv_nsec
;
uint32_t
mono_sec
;
uint32_t
pid
;
uint32_t
tid
;
uint32_t
domain
;
char
tag
[];
/* shall be end with '\0' */
}
HilogMsg
;
#if defined(__GNUC__) && (__GNUC__ >= 4)
#define HILOG_PUBLIC_API __attribute__((visibility("default")))
#define HILOG_LOCAL_API __attribute__((visibility("hidden")))
#else
#define HILOG_PUBLIC_API
#define HILOG_LOCAL_API
#endif
#endif
/* HILOG_COMMON_H */
porting/linux/user/src/hilog/output_p.inl
0 → 100644
浏览文件 @
503dfc5a
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* 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.
*/
/* [Standardize-exceptions] Use unsafe function: Portability
* [reason] Use unsafe function to implement security function to maintain platform compatibility.
* And sufficient input validation is performed before calling
*/
#ifndef OUTPUT_P_INL_2B263E9C_43D8_44BB_B17A_6D2033DECEE5
#define OUTPUT_P_INL_2B263E9C_43D8_44BB_B17A_6D2033DECEE5
#define SECUREC_FLOAT_BUFSIZE (309+40) /* max float point value */
#define SECUREC_FLOAT_BUFSIZE_LB (4932+40) /* max long double value */
#define SECUREC_INT_MAX 2147483647
#define SECUREC_MUL10(x) ((((x) << 2) + (x)) << 1)
#define SECUREC_INT_MAX_DIV_TEN 21474836
#define SECUREC_MUL10_ADD_BEYOND_MAX(val) (((val) > SECUREC_INT_MAX_DIV_TEN))
#ifdef SECUREC_STACK_SIZE_LESS_THAN_1K
#define SECUREC_FMT_STR_LEN (8)
#else
#define SECUREC_FMT_STR_LEN (16)
#endif
typedef struct {
unsigned int flags;
int fldWidth;
int precision;
int bufferIsWide; /* flag for buffer contains wide chars */
int dynWidth; /* %* 1 width from variable parameter ;0 not */
int dynPrecision; /* %.* 1 precision from variable parameter ;0 not */
} SecFormatAttr;
typedef union {
char *str; /* not a null terminated string */
wchar_t *wStr;
} SecFormatBuf;
typedef union {
char str[SECUREC_BUFFER_SIZE + 1];
#ifdef SECUREC_FOR_WCHAR
wchar_t wStr[SECUREC_BUFFER_SIZE + 1];
#endif
} SecBuffer;
static int SecIndirectSprintf(char *strDest, const char *format, ...)
{
int ret; /* If initialization causes e838 */
va_list arglist;
va_start(arglist, format);
SECUREC_MASK_MSVC_CRT_WARNING
ret = vsprintf(strDest, format, arglist);
SECUREC_END_MASK_MSVC_CRT_WARNING
va_end(arglist);
(void)arglist; /* to clear e438 last value assigned not used , the compiler will optimize this code */
return ret;
}
#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
/* to clear e506 warning */
static int SecIsSameSize(size_t sizeA, size_t sizeB)
{
return sizeA == sizeB;
}
#endif
#define SECUREC_SPECIAL(_val, Base) \
case Base: \
do { \
*--formatBuf.str = digits[_val % Base]; \
}while ((_val /= Base) != 0)
#define SECUREC_SAFE_WRITE_PREFIX(src, txtLen, _stream, outChars) do { \
for (ii = 0; ii < txtLen; ++ii) { \
*((SecChar *)(void *)(_stream->cur)) = *(src); \
_stream->cur += sizeof(SecChar); \
++(src); \
} \
_stream->count -= txtLen * (int)(sizeof(SecChar)); \
*(outChars) = *(outChars) + (txtLen); \
} SECUREC_WHILE_ZERO
#define SECUREC_SAFE_WRITE_STR(src, txtLen, _stream, outChars) do { \
if (txtLen < 12 /* for mobile number length */) { \
for (ii = 0; ii < txtLen; ++ii) { \
*((SecChar *)(void *)(_stream->cur)) = *(src); \
_stream->cur += sizeof(SecChar); \
++(src); \
} \
} else { \
(void)memcpy(_stream->cur, src, ((size_t)(unsigned int)txtLen * (sizeof(SecChar)))); \
_stream->cur += (size_t)(unsigned int)txtLen * (sizeof(SecChar)); \
} \
_stream->count -= txtLen * (int)(sizeof(SecChar)); \
*(outChars) = *(outChars) + (txtLen); \
} SECUREC_WHILE_ZERO
#define SECUREC_SAFE_WRITE_CHAR(_ch, _stream, outChars) do { \
*((SecChar *)(void *)(_stream->cur)) = (SecChar)_ch; \
_stream->cur += sizeof(SecChar); \
_stream->count -= (int)(sizeof(SecChar)); \
*(outChars) = *(outChars) + 1; \
} SECUREC_WHILE_ZERO
#define SECUREC_SAFE_PADDING(padChar, padLen, _stream, outChars) do { \
for (ii = 0; ii < padLen; ++ii) { \
*((SecChar *)(void *)(_stream->cur)) = (SecChar)padChar; \
_stream->cur += sizeof(SecChar); \
} \
_stream->count -= padLen * (int)(sizeof(SecChar)); \
*(outChars) = *(outChars) + (padLen); \
} SECUREC_WHILE_ZERO
/* The count variable can be reduced to 0, and the external function complements the \0 terminator. */
#define SECUREC_IS_REST_BUF_ENOUGH(needLen) ((int)(stream->count - (int)needLen * (int)(sizeof(SecChar))) >= 0)
#define SECUREC_FMT_STATE_OFFSET 256
#ifdef SECUREC_FOR_WCHAR
#define SECUREC_FMT_TYPE(c,fmtTable) ((((unsigned int)(int)(c)) <= (unsigned int)(int)SECUREC_CHAR('~')) ? \
(fmtTable[(unsigned char)(c)]) : 0)
#define SECUREC_DECODE_STATE(c,fmtTable,laststate) (SecFmtState)(((fmtTable[(SECUREC_FMT_TYPE(c,fmtTable)) * \
((unsigned char)STAT_INVALID + 1) + \
(unsigned char)(laststate) + \
SECUREC_FMT_STATE_OFFSET])))
#else
#define SECUREC_DECODE_STATE(c,fmtTable,laststate) (SecFmtState)((fmtTable[(fmtTable[(unsigned char)(c)]) * \
((unsigned char)STAT_INVALID + 1) + \
(unsigned char)(laststate) + \
SECUREC_FMT_STATE_OFFSET]))
#endif
#define PUBLIC_FLAG_LEN 8
#define PRIVATE_FLAG_LEN 9
#define PUBLIC_FLAG "{public}"
#define PRIVATE_FLAG "{private}"
static void SecWritePrivateStr(SecPrintfStream *stream, int *pCharsOut)
{
int ii = 0;
#define PRIVATE_STR_LEN (9)
#ifndef SECUREC_FOR_WCHAR
static const char privacyString[] = "<private>";
const char *pPrivStr = privacyString;
if (SECUREC_IS_REST_BUF_ENOUGH(PRIVATE_STR_LEN)) {
SECUREC_SAFE_WRITE_STR(pPrivStr, PRIVATE_STR_LEN, stream, pCharsOut);
} else {
SECUREC_WRITE_STRING(pPrivStr, PRIVATE_STR_LEN, stream, pCharsOut);
}
#else
static const wchar_t wprivacyString[] = { L'<', L'p', L'r', L'i', L'v', L'a', L't', L'e', L'>', L'\0' };
const wchar_t *pwPrivStr = wprivacyString;
if (SECUREC_IS_REST_BUF_ENOUGH(PRIVATE_STR_LEN)) {
SECUREC_SAFE_WRITE_STR(pwPrivStr, PRIVATE_STR_LEN, stream, pCharsOut);
} else {
SECUREC_WRITE_STRING(pwPrivStr, PRIVATE_STR_LEN, stream, pCharsOut);
}
#endif
}
static void SecDecodeFlags(SecChar ch, SecFormatAttr *attr)
{
switch (ch) {
case SECUREC_CHAR(' '):
attr->flags |= SECUREC_FLAG_SIGN_SPACE;
break;
case SECUREC_CHAR('+'):
attr->flags |= SECUREC_FLAG_SIGN;
break;
case SECUREC_CHAR('-'):
attr->flags |= SECUREC_FLAG_LEFT;
break;
case SECUREC_CHAR('0'):
attr->flags |= SECUREC_FLAG_LEADZERO; /* add zero th the front */
break;
case SECUREC_CHAR('#'):
attr->flags |= SECUREC_FLAG_ALTERNATE; /* output %x with 0x */
break;
default:
break;
}
return;
}
static int SecDecodeSize(SecChar ch, SecFormatAttr *attr, const SecChar **format)
{
switch (ch) {
#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
case SECUREC_CHAR('j'):
attr->flags |= SECUREC_FLAG_INTMAX;
break;
#endif
case SECUREC_CHAR('q'):
case SECUREC_CHAR('L'):
attr->flags |= SECUREC_FLAG_LONGLONG | SECUREC_FLAG_LONG_DOUBLE;
break;
case SECUREC_CHAR('l'):
if (**format == SECUREC_CHAR('l')) {
++(*format);
attr->flags |= SECUREC_FLAG_LONGLONG; /* long long */
} else {
attr->flags |= SECUREC_FLAG_LONG; /* long int or wchar_t */
}
break;
case SECUREC_CHAR('t'):
attr->flags |= SECUREC_FLAG_PTRDIFF;
break;
#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
case SECUREC_CHAR('z'):
attr->flags |= SECUREC_FLAG_SIZE;
break;
case SECUREC_CHAR('Z'):
attr->flags |= SECUREC_FLAG_SIZE;
break;
#endif
case SECUREC_CHAR('I'):
#ifdef SECUREC_ON_64BITS
attr->flags |= SECUREC_FLAG_I64; /* %I to INT64 */
#endif
if ((**format == SECUREC_CHAR('6')) && (*((*format) + 1) == SECUREC_CHAR('4'))) {
(*format) += 2;
attr->flags |= SECUREC_FLAG_I64; /* %I64 to INT64 */
} else if ((**format == SECUREC_CHAR('3')) && (*((*format) + 1) == SECUREC_CHAR('2'))) {
(*format) += 2;
attr->flags &= ~SECUREC_FLAG_I64; /* %I64 to INT32 */
} else if ((**format == SECUREC_CHAR('d')) || (**format == SECUREC_CHAR('i')) ||
(**format == SECUREC_CHAR('o')) || (**format == SECUREC_CHAR('u')) ||
(**format == SECUREC_CHAR('x')) || (**format == SECUREC_CHAR('X'))) {
/* do nothing */
} else {
/* Compatibility code for "%I" just print I */
return -1;
}
break;
case SECUREC_CHAR('h'):
if (**format == SECUREC_CHAR('h'))
attr->flags |= SECUREC_FLAG_CHAR; /* char */
else
attr->flags |= SECUREC_FLAG_SHORT; /* short int */
break;
case SECUREC_CHAR('w'):
attr->flags |= SECUREC_FLAG_WIDECHAR; /* wide char */
break;
default:
break;
}
return 0;
}
static int SecDecodeTypeC(SecFormatAttr *attr, unsigned int cValue, SecFormatBuf *formatBuf, SecBuffer *buffer)
{
int textLen;
wchar_t wchar;
#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT)) && !(defined(__hpux)) && !(defined(SECUREC_ON_SOLARIS))
attr->flags &= ~SECUREC_FLAG_LEADZERO;
#endif
#ifdef SECUREC_FOR_WCHAR
attr->bufferIsWide = 1;
wchar = (wchar_t)cValue;
if (attr->flags & SECUREC_FLAG_SHORT) {
/* multibyte character to wide character */
char tempchar[2];
tempchar[0] = (char)(wchar & 0x00ff);
tempchar[1] = '\0';
if (mbtowc(buffer->wStr, tempchar, sizeof(tempchar)) < 0) {
return -1;
}
} else {
buffer->wStr[0] = wchar;
}
formatBuf->wStr = buffer->wStr;
textLen = 1; /* only 1 wide character */
#else
attr->bufferIsWide = 0;
if (attr->flags & (SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR)) {
wchar = (wchar_t)cValue;
/* wide character to multibyte character */
SECUREC_MASK_MSVC_CRT_WARNING
textLen = wctomb(buffer->str, wchar);
SECUREC_END_MASK_MSVC_CRT_WARNING
if (textLen < 0) {
return -1;
}
} else {
/* get multibyte character from argument */
unsigned short temp;
temp = (unsigned short)cValue;
buffer->str[0] = (char)temp;
textLen = 1;
}
formatBuf->str = buffer->str;
#endif
return textLen;
}
static int SecDecodeTypeS(SecFormatAttr *attr, char *argPtr, SecFormatBuf *formatBuf)
{
/* literal string to print null ptr, define it on stack rather than const text area
is to avoid gcc warning with pointing const text with variable */
static char strNullString[8] = "(null)";
static wchar_t wStrNullString[8] = { L'(', L'n', L'u', L'l', L'l', L')', L'\0', L'\0' };
int finalPrecision;
char *strEnd = NULL;
wchar_t *wStrEnd = NULL;
int textLen;
#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT)) && (!defined(SECUREC_ON_UNIX))
attr->flags &= ~SECUREC_FLAG_LEADZERO;
#endif
finalPrecision = (attr->precision == -1) ? SECUREC_INT_MAX : attr->precision;
formatBuf->str = argPtr;
#ifdef SECUREC_FOR_WCHAR
#if defined(SECUREC_COMPATIBLE_LINUX_FORMAT)
if (!(attr->flags & SECUREC_FLAG_LONG)) {
attr->flags |= SECUREC_FLAG_SHORT;
}
#endif
if (attr->flags & SECUREC_FLAG_SHORT) {
if (formatBuf->str == NULL) { /* NULL passed, use special string */
formatBuf->str = strNullString;
}
strEnd = formatBuf->str;
for (textLen = 0; textLen < finalPrecision && *strEnd; textLen++) {
++strEnd;
}
/* textLen now contains length in multibyte chars */
} else {
if (formatBuf->wStr == NULL) { /* NULL passed, use special string */
formatBuf->wStr = wStrNullString;
}
attr->bufferIsWide = 1;
wStrEnd = formatBuf->wStr;
while (finalPrecision-- && *wStrEnd) {
++wStrEnd;
}
textLen = (int)(wStrEnd - formatBuf->wStr); /* in wchar_ts */
/* textLen now contains length in wide chars */
}
#else /* SECUREC_FOR_WCHAR */
if (attr->flags & (SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR)) {
if (formatBuf->wStr == NULL) { /* NULL passed, use special string */
formatBuf->wStr = wStrNullString;
}
attr->bufferIsWide = 1;
wStrEnd = formatBuf->wStr;
while (finalPrecision-- && *wStrEnd) {
++wStrEnd;
}
textLen = (int)(wStrEnd - formatBuf->wStr);
} else {
if (formatBuf->str == NULL) { /* meet NULL, use special string */
formatBuf->str = strNullString;
}
if (finalPrecision == SECUREC_INT_MAX) {
/* precision NOT assigned */
/* The strlen performance is high when the string length is greater than 32 */
textLen = (int)strlen(formatBuf->str);
} else {
/* precision assigned */
strEnd = formatBuf->str;
while (finalPrecision-- && *strEnd) {
++strEnd;
}
textLen = (int)(strEnd - formatBuf->str); /* length of the string */
}
}
#endif /* SECUREC_FOR_WCHAR */
return textLen;
}
HILOG_LOCAL_API
int SecOutputPS(SecPrintfStream *stream, int priv, const char *cformat, va_list arglist)
{
const SecChar *format = cformat;
char *floatBuf = NULL;
SecFormatBuf formatBuf;
static const char *itoaUpperDigits = "0123456789ABCDEFX";
static const char *itoaLowerDigits = "0123456789abcdefx";
const char *digits = itoaUpperDigits;
int ii = 0;
unsigned int radix;
int charsOut; /* characters written */
int prefixLen = 0;
int padding = 0;
int textLen; /* length of the text */
int bufferSize = 0; /* size of formatBuf.str */
int noOutput = 0;
SecFmtState state;
SecFmtState laststate;
SecChar prefix[2] = { 0 };
SecChar ch; /* currently read character */
static const unsigned char fmtCharTable[337] = {
/* type 0: nospecial meaning;
1: '%';
2: '.'
3: '*'
4: '0'
5: '1' ... '9'
6: ' ', '+', '-', '#'
7: 'h', 'l', 'L', 'F', 'w' , 'N','z','q','t','j'
8: 'd','o','u','i','x','X','e','f','g'
*/
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x06, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x06, 0x00, 0x06, 0x02, 0x00,
0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x08, 0x08, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00,
0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x08, 0x07, 0x00, 0x07, 0x00, 0x00, 0x08,
0x08, 0x07, 0x00, 0x08, 0x07, 0x08, 0x00, 0x07, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
/* fill zero for normal char 128 byte for 0x80 - 0xff */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* state 0: normal
1: percent
2: flag
3: width
4: dot
5: precis
6: size
7: type
8: invalid
*/
0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x01, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08,
0x01, 0x00, 0x00, 0x04, 0x04, 0x04, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x03, 0x03, 0x08, 0x05,
0x08, 0x08, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x05, 0x05, 0x08, 0x00, 0x00, 0x00, 0x03, 0x03,
0x03, 0x05, 0x05, 0x08, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x00,
0x00
};
SecFormatAttr formatAttr;
SecBuffer buffer;
formatAttr.flags = 0;
formatAttr.bufferIsWide = 0; /* flag for buffer contains wide chars */
formatAttr.fldWidth = 0;
formatAttr.precision = 0;
formatAttr.dynWidth = 0;
formatAttr.dynPrecision = 0;
charsOut = 0;
textLen = 0;
state = STAT_NORMAL; /* starting state */
formatBuf.str = NULL;
int isPrivacy = 1; /*whether show private string*/
/* loop each format character */
/* remove format != NULL */
while ((ch = *format++) != SECUREC_CHAR('\0') && charsOut >= 0) {
laststate = state;
state = SECUREC_DECODE_STATE(ch, fmtCharTable, laststate);
switch (state) {
case STAT_NORMAL:
NORMAL_CHAR:
/* normal state, write character */
if (SECUREC_IS_REST_BUF_ENOUGH(1 /* only one char */ )) {
SECUREC_SAFE_WRITE_CHAR(ch, stream, &charsOut); /* char * cast to wchar * */
} else {
#ifdef SECUREC_FOR_WCHAR
SECUREC_WRITE_CHAR(ch, stream, &charsOut);
#else
/* optimize function call to code */
charsOut = -1;
stream->count = -1;
#endif
}
continue;
case STAT_PERCENT:
/* set default values */
prefixLen = 0;
noOutput = 0;
formatAttr.flags = 0;
formatAttr.fldWidth = 0;
formatAttr.precision = -1;
formatAttr.bufferIsWide = 0;
if (*format == SECUREC_CHAR('{')) {
if (strncmp(format, PUBLIC_FLAG, PUBLIC_FLAG_LEN) == 0) {
isPrivacy = 0;
format += PUBLIC_FLAG_LEN;
}
else if (strncmp(format, PRIVATE_FLAG, PRIVATE_FLAG_LEN) == 0) {
isPrivacy = 1;
format += PRIVATE_FLAG_LEN;
}
}
else {
isPrivacy = 1;
}
if (0 == priv) {
isPrivacy = 0;
}
break;
case STAT_FLAG:
/* set flag based on which flag character */
SecDecodeFlags(ch, &formatAttr);
break;
case STAT_WIDTH:
/* update width value */
if (ch == SECUREC_CHAR('*')) {
/* get width */
formatAttr.fldWidth = (int)va_arg(arglist, int);
if (formatAttr.fldWidth < 0) {
formatAttr.flags |= SECUREC_FLAG_LEFT;
formatAttr.fldWidth = -formatAttr.fldWidth;
}
formatAttr.dynWidth = 1;
} else {
if (laststate != STAT_WIDTH) {
formatAttr.fldWidth = 0;
}
if (SECUREC_MUL10_ADD_BEYOND_MAX(formatAttr.fldWidth)) {
return -1;
}
formatAttr.fldWidth = (int)SECUREC_MUL10((unsigned int)formatAttr.fldWidth) + (ch - SECUREC_CHAR('0'));
formatAttr.dynWidth = 0;
}
break;
case STAT_DOT:
formatAttr.precision = 0;
break;
case STAT_PRECIS:
/* update precision value */
if (ch == SECUREC_CHAR('*')) {
/* get precision from arg list */
formatAttr.precision = (int)va_arg(arglist, int);
if (formatAttr.precision < 0) {
formatAttr.precision = -1;
}
formatAttr.dynPrecision = 1;
} else {
/* add digit to current precision */
if (SECUREC_MUL10_ADD_BEYOND_MAX(formatAttr.precision)) {
return -1;
}
formatAttr.precision =
(int)SECUREC_MUL10((unsigned int)formatAttr.precision) + (ch - SECUREC_CHAR('0'));
formatAttr.dynPrecision = 0;
}
break;
case STAT_SIZE:
/* read a size specifier, set the formatAttr.flags based on it */
if (SecDecodeSize(ch, &formatAttr, &format) != 0) {
/* Compatibility code for "%I" just print I */
state = STAT_NORMAL;
goto NORMAL_CHAR;
}
break;
case STAT_TYPE:
switch (ch) {
case SECUREC_CHAR('C'):
/* wide char */
if (!(formatAttr.flags & (SECUREC_FLAG_SHORT | SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR))) {
#ifdef SECUREC_FOR_WCHAR
formatAttr.flags |= SECUREC_FLAG_SHORT;
#else
formatAttr.flags |= SECUREC_FLAG_WIDECHAR;
#endif
}
/* fall-through */
/* FALLTHRU */
case SECUREC_CHAR('c'):
{
unsigned int cValue = (unsigned int)va_arg(arglist, int);
/*if it's a private arg, just write <priate> to stream*/
if (isPrivacy == 1) {
break;
}
textLen = SecDecodeTypeC(&formatAttr, cValue, &formatBuf, &buffer);
if (textLen < 0) {
noOutput = 1;
}
}
break;
case SECUREC_CHAR('S'): /* wide char string */
#ifndef SECUREC_FOR_WCHAR
if (!(formatAttr.flags & (SECUREC_FLAG_SHORT | SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR))) {
formatAttr.flags |= SECUREC_FLAG_WIDECHAR;
}
#else
if (!(formatAttr.flags & (SECUREC_FLAG_SHORT | SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR))) {
formatAttr.flags |= SECUREC_FLAG_SHORT;
}
#endif
/* fall-through */
/* FALLTHRU */
case SECUREC_CHAR('s'):
{
char *argPtr = (char *)va_arg(arglist, char *);
/*if it's a private arg, just write <priate> to stream*/
if (isPrivacy == 1) {
break;
}
textLen = SecDecodeTypeS(&formatAttr, argPtr, &formatBuf);
}
break;
case SECUREC_CHAR('n'):
/* higher risk disable it */
return -1;
case SECUREC_CHAR('E'): /* fall-through */ /* FALLTHRU */
case SECUREC_CHAR('F'): /* fall-through */ /* FALLTHRU */
case SECUREC_CHAR('G'): /* fall-through */ /* FALLTHRU */
case SECUREC_CHAR('A'): /* fall-through */ /* FALLTHRU */
/* convert format char to lower , use Explicit conversion to clean up compilation warning */
ch = (SecChar) (ch + ((SecChar) (SECUREC_CHAR('a')) - (SECUREC_CHAR('A'))));
/* fall-through */
/* FALLTHRU */
case SECUREC_CHAR('e'): /* fall-through */ /* FALLTHRU */
case SECUREC_CHAR('f'): /* fall-through */ /* FALLTHRU */
case SECUREC_CHAR('g'): /* fall-through */ /* FALLTHRU */
case SECUREC_CHAR('a'):
{
/*if it's a private arg, just write <priate> to stream*/
if (isPrivacy == 1) {
#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
if (formatAttr.flags & SECUREC_FLAG_LONG_DOUBLE) {
(void)va_arg(arglist, long double);
} else
#endif
{
(void)va_arg(arglist, double);
}
break;
}
/* floating point conversion */
formatBuf.str = buffer.str; /* output buffer for float string with default size */
/* compute the precision value */
if (formatAttr.precision < 0) {
formatAttr.precision = 6;
} else if (formatAttr.precision == 0 && ch == SECUREC_CHAR('g')) {
formatAttr.precision = 1;
}
/* calc buffer size to store long double value */
if (formatAttr.flags & SECUREC_FLAG_LONG_DOUBLE) {
if (formatAttr.precision > (SECUREC_INT_MAX - SECUREC_FLOAT_BUFSIZE_LB)) {
noOutput = 1;
break;
}
bufferSize = SECUREC_FLOAT_BUFSIZE_LB + formatAttr.precision;
} else {
if (formatAttr.precision > (SECUREC_INT_MAX - SECUREC_FLOAT_BUFSIZE)) {
noOutput = 1;
break;
}
bufferSize = SECUREC_FLOAT_BUFSIZE + formatAttr.precision;
}
if (formatAttr.fldWidth > bufferSize) {
bufferSize = formatAttr.fldWidth;
}
if (bufferSize >= SECUREC_BUFFER_SIZE) {
/* the current value of SECUREC_BUFFER_SIZE could NOT store the formatted float string */
/* size include '+' and '\0' */
floatBuf = (char *)SECUREC_MALLOC(((size_t)(unsigned int)bufferSize + (size_t)2));
if (floatBuf != NULL) {
formatBuf.str = floatBuf;
} else {
noOutput = 1;
break;
}
}
{
/* add following code to call system sprintf API for float number */
const SecChar *pFltFmt = format - 2; /* point to the position before 'f' or 'g' */
int k;
int fltFmtStrLen;
char fltFmtBuf[SECUREC_FMT_STR_LEN];
char *fltFmtStr = fltFmtBuf;
char *fltFmtHeap = NULL; /* to clear warning */
/* must meet '%' (normal format) or '}'(with{private} or{public} format)*/
while (SECUREC_CHAR('%') != *pFltFmt && SECUREC_CHAR('}') != *pFltFmt) {
--pFltFmt;
}
fltFmtStrLen = (int)((format - pFltFmt) + 1); /* with ending terminator */
if (fltFmtStrLen > SECUREC_FMT_STR_LEN) {
/* if SECUREC_FMT_STR_LEN is NOT enough, alloc a new buffer */
fltFmtHeap = (char *)SECUREC_MALLOC((size_t)((unsigned int)fltFmtStrLen));
if (fltFmtHeap == NULL) {
noOutput = 1;
break;
} else {
fltFmtHeap[0] = '%';
for (k = 1; k < fltFmtStrLen - 1; ++k) {
/* convert wchar to char */
fltFmtHeap[k] = (char)(pFltFmt[k]); /* copy the format string */
}
fltFmtHeap[k] = '\0';
fltFmtStr = fltFmtHeap;
}
} else {
/* purpose of the repeat code is to solve the tool alarm Redundant_Null_Check */
fltFmtBuf[0] = '%';
for (k = 1; k < fltFmtStrLen - 1; ++k) {
/* convert wchar to char */
fltFmtBuf[k] = (char)(pFltFmt[k]); /* copy the format string */
}
fltFmtBuf[k] = '\0';
}
#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
if (formatAttr.flags & SECUREC_FLAG_LONG_DOUBLE) {
long double tmp = (long double)va_arg(arglist, long double);
/* call system sprintf to format float value */
if (formatAttr.dynWidth && formatAttr.dynPrecision) {
textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr,
formatAttr.fldWidth,formatAttr.precision, tmp);
} else if (formatAttr.dynWidth) {
textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr,
formatAttr.fldWidth, tmp);
} else if (formatAttr.dynPrecision) {
textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr,
formatAttr.precision, tmp);
} else {
textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, tmp);
}
} else
#endif
{
double tmp = (double)va_arg(arglist, double);
if (formatAttr.dynWidth && formatAttr.dynPrecision) {
textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, formatAttr.fldWidth,
formatAttr.precision, tmp);
} else if (formatAttr.dynWidth) {
textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, formatAttr.fldWidth,
tmp);
} else if (formatAttr.dynPrecision) {
textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, formatAttr.precision,
tmp);
} else {
textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, tmp);
}
}
if (fltFmtHeap != NULL) {
/* if buffer is allocated on heap, free it */
SECUREC_FREE(fltFmtHeap);
fltFmtHeap = NULL;
/* to clear e438 last value assigned not used , the compiler will optimize this code */
(void)fltFmtHeap;
}
if (textLen < 0) {
/* bufferSize is large enough,just validation the return value */
noOutput = 1;
break;
}
formatAttr.fldWidth = textLen; /* no padding ,this variable to calculate amount of padding */
prefixLen = 0; /* no padding ,this variable to calculate amount of padding */
formatAttr.flags = 0; /* clear all internal formatAttr.flags */
break;
}
}
case SECUREC_CHAR('p'):
/* print a pointer */
#if defined(SECUREC_COMPATIBLE_WIN_FORMAT)
formatAttr.flags &= ~SECUREC_FLAG_LEADZERO;
#else
formatAttr.flags |= SECUREC_FLAG_POINTER;
#endif
#ifdef SECUREC_ON_64BITS
formatAttr.flags |= SECUREC_FLAG_I64; /* converting an int64 */
#else
formatAttr.flags |= SECUREC_FLAG_LONG; /* converting a long */
#endif
#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) || defined(SECUREC_VXWORKS_PLATFORM)) && (!defined(SECUREC_ON_UNIX))
#if defined(SECUREC_VXWORKS_PLATFORM)
formatAttr.precision = 1;
#else
formatAttr.precision = 0;
#endif
formatAttr.flags |= SECUREC_FLAG_ALTERNATE; /* "0x" is not default prefix in UNIX */
digits = itoaLowerDigits;
goto OUTPUT_HEX;
#else
/* not linux vxwoks */
#if defined(_AIX) || defined(SECUREC_ON_SOLARIS)
formatAttr.precision = 1;
#else
formatAttr.precision = 2 * sizeof(void *);
#endif
#endif
#if defined(SECUREC_ON_UNIX)
digits = itoaLowerDigits;
goto OUTPUT_HEX;
#endif
/* fall-through */
/* FALLTHRU */
case SECUREC_CHAR('X'):
/* unsigned upper hex output */
digits = itoaUpperDigits;
goto OUTPUT_HEX;
case SECUREC_CHAR('x'):
/* unsigned lower hex output */
digits = itoaLowerDigits;
OUTPUT_HEX:
radix = 16;
if (formatAttr.flags & SECUREC_FLAG_ALTERNATE) {
/* alternate form means '0x' prefix */
prefix[0] = SECUREC_CHAR('0');
prefix[1] = (SecChar) (digits[16]); /* 'x' or 'X' */
#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) || defined(SECUREC_VXWORKS_PLATFORM))
if (ch == 'p') {
prefix[1] = SECUREC_CHAR('x');
}
#endif
#if defined(_AIX) || defined(SECUREC_ON_SOLARIS)
if (ch == 'p') {
prefixLen = 0;
} else {
prefixLen = 2;
}
#else
prefixLen = 2;
#endif
}
goto OUTPUT_INT;
case SECUREC_CHAR('i'): /* fall-through */ /* FALLTHRU */
case SECUREC_CHAR('d'): /* fall-through */ /* FALLTHRU */
/* signed decimal output */
formatAttr.flags |= SECUREC_FLAG_SIGNED;
/* fall-through */
/* FALLTHRU */
case SECUREC_CHAR('u'):
radix = 10;
goto OUTPUT_INT;
case SECUREC_CHAR('o'):
/* unsigned octal output */
radix = 8;
if (formatAttr.flags & SECUREC_FLAG_ALTERNATE) {
/* alternate form means force a leading 0 */
formatAttr.flags |= SECUREC_FLAG_FORCE_OCTAL;
}
OUTPUT_INT:
{
SecUnsignedInt64 number = 0; /* number to convert */
SecInt64 l; /* temp long value */
unsigned char tch;
#if defined(SECUREC_VXWORKS_VERSION_5_4) && !defined(SECUREC_ON_64BITS)
SecUnsignedInt32 digit = 0; /* ascii value of digit */
SecUnsignedInt32 quotientHigh = 0;
SecUnsignedInt32 quotientLow = 0;
#endif
/* read argument into variable l */
if (formatAttr.flags & SECUREC_FLAG_I64) {
l = (SecInt64)va_arg(arglist, SecInt64);
} else if (formatAttr.flags & SECUREC_FLAG_LONGLONG) {
l = (SecInt64)va_arg(arglist, SecInt64);
} else
#ifdef SECUREC_ON_64BITS
if (formatAttr.flags & SECUREC_FLAG_LONG) {
l = (long)va_arg(arglist, long);
} else
#endif /* SECUREC_ON_64BITS */
if (formatAttr.flags & SECUREC_FLAG_CHAR) {
if (formatAttr.flags & SECUREC_FLAG_SIGNED) {
l = (char)va_arg(arglist, int); /* sign extend */
if (l >= 128) { /* on some platform, char is always unsigned */
SecUnsignedInt64 tmpL = (SecUnsignedInt64)l;
formatAttr.flags |= SECUREC_FLAG_NEGATIVE;
tch = (unsigned char)(~(tmpL));
l = tch + 1;
}
} else {
l = (unsigned char)va_arg(arglist, int); /* zero-extend */
}
} else if (formatAttr.flags & SECUREC_FLAG_SHORT) {
if (formatAttr.flags & SECUREC_FLAG_SIGNED) {
l = (short)va_arg(arglist, int); /* sign extend */
} else {
l = (unsigned short)va_arg(arglist, int); /* zero-extend */
}
}
#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
else if (formatAttr.flags & SECUREC_FLAG_PTRDIFF) {
l = (ptrdiff_t)va_arg(arglist, ptrdiff_t); /* sign extend */
} else if (formatAttr.flags & SECUREC_FLAG_SIZE) {
if (formatAttr.flags & SECUREC_FLAG_SIGNED) {
/* No suitable macros were found to handle the branch */
if (SecIsSameSize(sizeof(size_t), sizeof(long))) {
l = va_arg(arglist, long); /* sign extend */
} else if (SecIsSameSize(sizeof(size_t), sizeof(long long))) {
l = va_arg(arglist, long long); /* sign extend */
} else {
l = va_arg(arglist, int); /* sign extend */
}
} else {
l = (SecInt64)(size_t)va_arg(arglist, size_t); /* sign extend */
}
} else if (formatAttr.flags & SECUREC_FLAG_INTMAX) {
if (formatAttr.flags & SECUREC_FLAG_SIGNED) {
l = va_arg(arglist, SecInt64); /* sign extend */
} else {
l = (SecInt64)(SecUnsignedInt64)va_arg(arglist, SecUnsignedInt64); /* sign extend */
}
}
#endif
else {
if (formatAttr.flags & SECUREC_FLAG_SIGNED) {
l = va_arg(arglist, int); /* sign extend */
} else {
l = (unsigned int)va_arg(arglist, int); /* zero-extend */
}
}
/*if it's a private arg, just write <priate> to stream*/
if (isPrivacy == 1) {
break;
}
/* check for negative; copy into number */
if ((formatAttr.flags & SECUREC_FLAG_SIGNED) && l < 0) {
number = (SecUnsignedInt64)(-l);
formatAttr.flags |= SECUREC_FLAG_NEGATIVE;
} else {
number = (SecUnsignedInt64)l;
}
if (((formatAttr.flags & SECUREC_FLAG_I64) == 0) &&
#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
((formatAttr.flags & SECUREC_FLAG_INTMAX) == 0) &&
#endif
#ifdef SECUREC_ON_64BITS
((formatAttr.flags & SECUREC_FLAG_PTRDIFF) == 0) &&
((formatAttr.flags & SECUREC_FLAG_SIZE) == 0) &&
#if !defined(SECUREC_COMPATIBLE_WIN_FORMAT) /* on window 64 system sizeof long is 32bit */
((formatAttr.flags & SECUREC_FLAG_LONG) == 0) &&
#endif
#endif
((formatAttr.flags & SECUREC_FLAG_LONGLONG) == 0)) {
number &= 0xffffffff;
}
/* check precision value for default */
if (formatAttr.precision < 0) {
formatAttr.precision = 1; /* default precision */
} else {
#if defined(SECUREC_COMPATIBLE_WIN_FORMAT)
formatAttr.flags &= ~SECUREC_FLAG_LEADZERO;
#else
if (!(formatAttr.flags & SECUREC_FLAG_POINTER)) {
formatAttr.flags &= ~SECUREC_FLAG_LEADZERO;
}
#endif
if (formatAttr.precision > SECUREC_MAX_PRECISION) {
formatAttr.precision = SECUREC_MAX_PRECISION;
}
}
/* Check if data is 0; if so, turn off hex prefix,if 'p',add 0x prefix,else not add prefix */
if (number == 0) {
#if !(defined(SECUREC_VXWORKS_PLATFORM)||defined(__hpux))
prefixLen = 0;
#else
if ((ch == 'p') && (formatAttr.flags & SECUREC_FLAG_ALTERNATE))
prefixLen = 2;
else
prefixLen = 0;
#endif
}
/* Convert data to ASCII */
formatBuf.str = &buffer.str[SECUREC_BUFFER_SIZE];
if (number > 0) {
#ifdef SECUREC_ON_64BITS
switch (radix) {
/* the compiler will optimize each one */
SECUREC_SPECIAL(number, 10);
break;
SECUREC_SPECIAL(number, 16);
break;
SECUREC_SPECIAL(number, 8);
break;
default:
break;
}
#else /* for 32 bits system */
if (number <= 0xFFFFFFFFUL) {
/* in most case, the value to be converted is small value */
SecUnsignedInt32 n32Tmp = (SecUnsignedInt32)number;
switch (radix) {
SECUREC_SPECIAL(n32Tmp, 16);
break;
SECUREC_SPECIAL(n32Tmp, 8);
break;
#ifdef _AIX
/* the compiler will optimize div 10 */
SECUREC_SPECIAL(n32Tmp, 10);
break;
#else
case 10:
{
/* fast div 10 */
SecUnsignedInt32 q;
SecUnsignedInt32 r;
do {
*--formatBuf.str = digits[n32Tmp % 10];
q = (n32Tmp >> 1) + (n32Tmp >> 2);
q = q + (q >> 4);
q = q + (q >> 8);
q = q + (q >> 16);
q = q >> 3;
r = n32Tmp - (((q << 2) + q) << 1);
n32Tmp = (r > 9) ? (q + 1) : q;
} while (n32Tmp != 0);
}
break;
#endif
default:
break;
} /* end switch */
} else {
/* the value to be converted is greater than 4G */
#if defined(SECUREC_VXWORKS_VERSION_5_4)
do {
if (0 != SecU64Div32((SecUnsignedInt32)((number >> 16) >> 16),
(SecUnsignedInt32)number,
(SecUnsignedInt32)radix, "ientHigh, "ientLow, &digit)) {
noOutput = 1;
break;
}
*--formatBuf.str = digits[digit];
number = (SecUnsignedInt64)quotientHigh;
number = (number << 32) + quotientLow;
} while (number != 0);
#else
switch (radix) {
/* the compiler will optimize div 10 */
SECUREC_SPECIAL(number, 10);
break;
SECUREC_SPECIAL(number, 16);
break;
SECUREC_SPECIAL(number, 8);
break;
default:
break;
}
#endif
}
#endif
} /* END if (number > 0) */
/* compute length of number,.if textLen > 0, then formatBuf.str must be in buffer.str */
textLen = (int)((char *)&buffer.str[SECUREC_BUFFER_SIZE] - formatBuf.str);
if (formatAttr.precision > textLen) {
for (ii = 0; ii < formatAttr.precision - textLen; ++ii) {
*--formatBuf.str = '0';
}
textLen = formatAttr.precision;
}
/* Force a leading zero if FORCEOCTAL flag set */
if ((formatAttr.flags & SECUREC_FLAG_FORCE_OCTAL) && (textLen == 0 || formatBuf.str[0] != '0')) {
*--formatBuf.str = '0';
++textLen; /* add a zero */
}
}
break;
default:
break;
}
/*if it's a private arg, just write <priate> to stream*/
if (isPrivacy == 1) {
SecWritePrivateStr(stream, &charsOut);
break;
}
if (noOutput == 0) {
if (formatAttr.flags & SECUREC_FLAG_SIGNED) {
if (formatAttr.flags & SECUREC_FLAG_NEGATIVE) {
/* prefix is a '-' */
prefix[0] = SECUREC_CHAR('-');
prefixLen = 1;
} else if (formatAttr.flags & SECUREC_FLAG_SIGN) {
/* prefix is '+' */
prefix[0] = SECUREC_CHAR('+');
prefixLen = 1;
} else if (formatAttr.flags & SECUREC_FLAG_SIGN_SPACE) {
/* prefix is ' ' */
prefix[0] = SECUREC_CHAR(' ');
prefixLen = 1;
}
}
#if defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && (!defined(SECUREC_ON_UNIX))
if ((formatAttr.flags & SECUREC_FLAG_POINTER) && (0 == textLen)) {
formatAttr.flags &= ~SECUREC_FLAG_LEADZERO;
formatBuf.str = &buffer.str[SECUREC_BUFFER_SIZE - 1];
*formatBuf.str-- = '\0';
*formatBuf.str-- = ')';
*formatBuf.str-- = 'l';
*formatBuf.str-- = 'i';
*formatBuf.str-- = 'n';
*formatBuf.str = '(';
textLen = 5;
}
#endif
/* calculate amount of padding */
padding = (formatAttr.fldWidth - textLen) - prefixLen;
/* put out the padding, prefix, and text, in the correct order */
if (!(formatAttr.flags & (SECUREC_FLAG_LEFT | SECUREC_FLAG_LEADZERO)) && padding > 0) {
/* pad on left with blanks */
if (SECUREC_IS_REST_BUF_ENOUGH(padding)) {
/* char * cast to wchar * */
SECUREC_SAFE_PADDING(SECUREC_CHAR(' '), padding, stream, &charsOut);
} else {
SECUREC_WRITE_MULTI_CHAR(SECUREC_CHAR(' '), padding, stream, &charsOut);
}
}
/* write prefix */
if (prefixLen > 0) {
SecChar *pPrefix = prefix;
if (SECUREC_IS_REST_BUF_ENOUGH(prefixLen)) {
/* max prefix len is 2, use loop copy */ /* char * cast to wchar * */
SECUREC_SAFE_WRITE_PREFIX(pPrefix, prefixLen, stream, &charsOut);
} else {
SECUREC_WRITE_STRING(prefix, prefixLen, stream, &charsOut);
}
}
if ((formatAttr.flags & SECUREC_FLAG_LEADZERO) && !(formatAttr.flags & SECUREC_FLAG_LEFT)
&& padding > 0) {
/* write leading zeros */
if (SECUREC_IS_REST_BUF_ENOUGH(padding)) {
/* char * cast to wchar * */
SECUREC_SAFE_PADDING(SECUREC_CHAR('0'), padding, stream, &charsOut);
} else {
SECUREC_WRITE_MULTI_CHAR(SECUREC_CHAR('0'), padding, stream, &charsOut);
}
}
/* write text */
#ifndef SECUREC_FOR_WCHAR
if (formatAttr.bufferIsWide && (textLen > 0)) {
wchar_t *p = formatBuf.wStr;
int count = textLen;
while (count--) {
char tmpBuf[SECUREC_MB_LEN + 1];
SECUREC_MASK_MSVC_CRT_WARNING
int retVal = wctomb(tmpBuf, *p++);
SECUREC_END_MASK_MSVC_CRT_WARNING
if (retVal <= 0) {
charsOut = -1;
break;
}
SECUREC_WRITE_STRING(tmpBuf, retVal, stream, &charsOut);
}
} else {
if (SECUREC_IS_REST_BUF_ENOUGH(textLen)) {
SECUREC_SAFE_WRITE_STR(formatBuf.str, textLen, stream, &charsOut);
} else {
SECUREC_WRITE_STRING(formatBuf.str, textLen, stream, &charsOut);
}
}
#else /* SECUREC_FOR_WCHAR */
if (formatAttr.bufferIsWide == 0 && textLen > 0) {
int count = textLen;
char *p = formatBuf.str;
while (count > 0) {
wchar_t wchar = L'\0';
int retVal = mbtowc(&wchar, p, (size_t)MB_CUR_MAX);
if (retVal <= 0) {
charsOut = -1;
break;
}
SECUREC_WRITE_CHAR(wchar, stream, &charsOut);
p += retVal;
count -= retVal;
}
} else {
if (SECUREC_IS_REST_BUF_ENOUGH(textLen)) {
SECUREC_SAFE_WRITE_STR(formatBuf.wStr, textLen, stream, &charsOut); /* char * cast to wchar * */
} else {
SECUREC_WRITE_STRING(formatBuf.wStr, textLen, stream, &charsOut);
}
}
#endif /* SECUREC_FOR_WCHAR */
if (charsOut >= 0 && (formatAttr.flags & SECUREC_FLAG_LEFT) && padding > 0) {
/* pad on right with blanks */
if (SECUREC_IS_REST_BUF_ENOUGH(padding)) {
/* char * cast to wchar * */
SECUREC_SAFE_PADDING(SECUREC_CHAR(' '), padding, stream, &charsOut);
} else {
SECUREC_WRITE_MULTI_CHAR(SECUREC_CHAR(' '), padding, stream, &charsOut);
}
}
/* we're done! */
}
if (floatBuf != NULL) {
SECUREC_FREE(floatBuf);
floatBuf = NULL;
}
break;
case STAT_INVALID:
return -1;
default:
return -1; /* input format is wrong, directly return */
}
}
if (state != STAT_NORMAL && state != STAT_TYPE) {
return -1;
}
return charsOut; /* the number of characters written */
} /* arglist must not be declare as const */
#endif /* OUTPUT_P_INL_2B263E9C_43D8_44BB_B17A_6D2033DECEE5 */
porting/linux/user/src/hilog/vsnprintf_s_p.c
0 → 100644
浏览文件 @
503dfc5a
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* 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 "vsnprintf_s_p.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
/* Define the max length of the string */
#ifndef SECUREC_STRING_MAX_LEN
#define SECUREC_STRING_MAX_LEN 0x7fffffffUL
#endif
#if SECUREC_STRING_MAX_LEN > 0x7fffffffUL
#error "max string is 2G"
#endif
#if defined(_DEBUG) || defined(DEBUG)
#if defined(SECUREC_ERROR_HANDLER_BY_ASSERT)
#define SECUREC_ERROR_INVALID_PARAMTER(msg) assert( msg "invalid argument" == NULL)
#define SECUREC_ERROR_INVALID_RANGE(msg) assert( msg "invalid dest buffer size" == NULL)
#elif defined(SECUREC_ERROR_HANDLER_BY_PRINTF)
#if SECUREC_IN_KERNEL
#define SECUREC_ERROR_INVALID_PARAMTER(msg) printk( "%s invalid argument\n",msg)
#define SECUREC_ERROR_INVALID_RANGE(msg) printk( "%s invalid dest buffer size\n", msg)
#else
#define SECUREC_ERROR_INVALID_PARAMTER(msg) printf( "%s invalid argument\n",msg)
#define SECUREC_ERROR_INVALID_RANGE(msg) printf( "%s invalid dest buffer size\n", msg)
#endif
#elif defined(SECUREC_ERROR_HANDLER_BY_FILE_LOG)
#define SECUREC_ERROR_INVALID_PARAMTER(msg) LogSecureCRuntimeError(msg " EINVAL\n")
#define SECUREC_ERROR_INVALID_RANGE(msg) LogSecureCRuntimeError(msg " ERANGE\n")
#else
#define SECUREC_ERROR_INVALID_PARAMTER(msg) ((void)0)
#define SECUREC_ERROR_INVALID_RANGE(msg) ((void)0)
#endif
#else
#define SECUREC_ERROR_INVALID_PARAMTER(msg) ((void)0)
#define SECUREC_ERROR_INVALID_RANGE(msg) ((void)0)
#define SECUREC_ERROR_BUFFER_OVERLAP(msg) ((void)0)
#endif
#define SECUREC_PRINTF_TRUNCATE (-2)
typedef
struct
{
int
count
;
char
*
cur
;
}
SecPrintfStream
;
#ifdef SECUREC_STACK_SIZE_LESS_THAN_1K
/* SECUREC_BUFFER_SIZE Can not be less than 23 ,
*the length of the octal representation of 64-bit integers with zero lead
*/
#define SECUREC_BUFFER_SIZE 256
#else
#define SECUREC_BUFFER_SIZE 512
#endif
#define SECUREC_MAX_PRECISION SECUREC_BUFFER_SIZE
/* max. # bytes in multibyte char ,see MB_LEN_MAX */
#define SECUREC_MB_LEN 16
#if (defined(_MSC_VER)) && (_MSC_VER >= 1400)
#define SECUREC_MASK_MSVC_CRT_WARNING __pragma(warning(push)) \
__pragma(warning(disable:4996 4127))
#define SECUREC_END_MASK_MSVC_CRT_WARNING __pragma(warning(pop))
#else
#define SECUREC_MASK_MSVC_CRT_WARNING
#define SECUREC_END_MASK_MSVC_CRT_WARNING
#endif
#define SECUREC_WHILE_ZERO SECUREC_MASK_MSVC_CRT_WARNING while (0) SECUREC_END_MASK_MSVC_CRT_WARNING
/* flag definitions */
/* Using macros instead of enumerations is because some of the enumerated types under the compiler are 16bit. */
#define SECUREC_FLAG_SIGN 0x00001U
#define SECUREC_FLAG_SIGN_SPACE 0x00002U
#define SECUREC_FLAG_LEFT 0x00004U
#define SECUREC_FLAG_LEADZERO 0x00008U
#define SECUREC_FLAG_LONG 0x00010U
#define SECUREC_FLAG_SHORT 0x00020U
#define SECUREC_FLAG_SIGNED 0x00040U
#define SECUREC_FLAG_ALTERNATE 0x00080U
#define SECUREC_FLAG_NEGATIVE 0x00100U
#define SECUREC_FLAG_FORCE_OCTAL 0x00200U
#define SECUREC_FLAG_LONG_DOUBLE 0x00400U
#define SECUREC_FLAG_WIDECHAR 0x00800U
#define SECUREC_FLAG_LONGLONG 0x01000U
#define SECUREC_FLAG_CHAR 0x02000U
#define SECUREC_FLAG_POINTER 0x04000U
#define SECUREC_FLAG_I64 0x08000U
#define SECUREC_FLAG_PTRDIFF 0x10000U
#define SECUREC_FLAG_SIZE 0x20000U
#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
#define SECUREC_FLAG_INTMAX 0x40000U
#endif
/* put a char to output */
#define SECUREC_PUTC(_c,_stream) ((--(_stream)->count >= 0) ? ((*(_stream)->cur++ = (char)(_c)) & 0xff) : EOF)
/* to clear e835 */
#define SECUREC_PUTC_ZERO(_stream) ((--(_stream)->count >= 0) ? ((*(_stream)->cur++ = (char)('\0'))) : EOF)
/* state definitions */
typedef
enum
{
STAT_NORMAL
,
STAT_PERCENT
,
STAT_FLAG
,
STAT_WIDTH
,
STAT_DOT
,
STAT_PRECIS
,
STAT_SIZE
,
STAT_TYPE
,
STAT_INVALID
}
SecFmtState
;
#ifndef HILOG_PROHIBIT_ALLOCATION
#ifndef SECUREC_MALLOC
#define SECUREC_MALLOC(x) malloc((size_t)(x))
#endif
#ifndef SECUREC_FREE
#define SECUREC_FREE(x) free((void *)(x))
#endif
#else
#define SECUREC_MALLOC(x) (nullptr)
#define SECUREC_FREE(x) { printf("Malloc is not allowed, so free should not be possible to execute!"); std::abort(); }
#endif
#if (defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER)) || defined(__ARMCC_VERSION)
typedef
__int64
SecInt64
;
typedef
unsigned
__int64
SecUnsignedInt64
;
#if defined(__ARMCC_VERSION)
typedef
int
SecInt32
;
typedef
unsigned
int
SecUnsignedInt32
;
#else
typedef
__int32
SecInt32
;
typedef
unsigned
__int32
SecUnsignedInt32
;
#endif
#else
typedef
int
SecInt32
;
typedef
unsigned
int
SecUnsignedInt32
;
typedef
long
long
SecInt64
;
typedef
unsigned
long
long
SecUnsignedInt64
;
#endif
static
inline
void
SecWriteString
(
const
char
*
string
,
int
len
,
SecPrintfStream
*
f
,
int
*
pnumwritten
)
{
const
char
*
str
=
string
;
int
count
=
len
;
while
(
count
--
>
0
)
{
if
(
SECUREC_PUTC
(
*
str
,
f
)
==
EOF
)
{
*
pnumwritten
=
-
1
;
break
;
}
else
{
++
(
*
pnumwritten
);
++
str
;
}
}
}
static
inline
void
SecWriteMultiChar
(
char
ch
,
int
num
,
SecPrintfStream
*
f
,
int
*
pnumwritten
)
{
int
count
=
num
;
while
(
count
--
>
0
)
{
if
(
SECUREC_PUTC
(
ch
,
f
)
==
EOF
)
{
*
pnumwritten
=
-
1
;
break
;
}
else
{
++
(
*
pnumwritten
);
}
}
}
static
inline
int
SecVsnprintfPImpl
(
char
*
string
,
size_t
count
,
int
priv
,
const
char
*
format
,
va_list
arglist
);
/*******************************************************************************
* <FUNCTION DESCRIPTION>
* The vsnprintf_s function is equivalent to the vsnprintf function
* except for the parameter destMax/count and the explicit runtime-constraints violation
* The vsnprintf_s function takes a pointer to an argument list, then formats
* and writes up to count characters of the given data to the memory pointed
* to by strDest and appends a terminating null.
*
* <INPUT PARAMETERS>
* strDest Storage location for the output.
* destMax The size of the strDest for output.
* count Maximum number of character to write(not including
* the terminating NULL)
* priv_on whether print <private> for not-public args
* format Format-control string.
* arglist pointer to list of arguments.
*
* <OUTPUT PARAMETERS>
* strDest is updated
*
* <RETURN VALUE>
* return the number of characters written, not including the terminating null
* return -1 if an error occurs.
* return -1 if count < destMax and the output string has been truncated
*
* If there is a runtime-constraint violation, strDest[0] will be set to the '\0' when strDest and destMax valid
*******************************************************************************
*/
HILOG_LOCAL_API
int
vsnprintfp_s
(
char
*
strDest
,
size_t
destMax
,
size_t
count
,
int
priv
,
const
char
*
format
,
va_list
arglist
)
{
int
retVal
;
if
(
format
==
NULL
||
strDest
==
NULL
||
destMax
==
0
||
destMax
>
SECUREC_STRING_MAX_LEN
||
(
count
>
(
SECUREC_STRING_MAX_LEN
-
1
)
&&
count
!=
(
size_t
)
-
1
))
{
if
(
strDest
!=
NULL
&&
destMax
>
0
)
{
strDest
[
0
]
=
'\0'
;
}
SECUREC_ERROR_INVALID_PARAMTER
(
"vsnprintfp_s"
);
return
-
1
;
}
if
(
destMax
>
count
)
{
retVal
=
SecVsnprintfPImpl
(
strDest
,
count
+
1
,
priv
,
format
,
arglist
);
if
(
retVal
==
SECUREC_PRINTF_TRUNCATE
)
{
/* lsd add to keep dest buffer not destroyed 2014.2.18 */
/* the string has been truncated, return -1 */
return
-
1
;
/* to skip error handler, return strlen(strDest) or -1 */
}
}
else
{
/* destMax <= count */
retVal
=
SecVsnprintfPImpl
(
strDest
,
destMax
,
priv
,
format
,
arglist
);
#ifdef SECUREC_COMPATIBLE_WIN_FORMAT
if
(
retVal
==
SECUREC_PRINTF_TRUNCATE
&&
count
==
(
size_t
)
-
1
)
{
return
-
1
;
}
#endif
}
if
(
retVal
<
0
)
{
strDest
[
0
]
=
'\0'
;
/* empty the dest strDest */
if
(
retVal
==
SECUREC_PRINTF_TRUNCATE
)
{
/* Buffer too small */
SECUREC_ERROR_INVALID_RANGE
(
"vsnprintfp_s"
);
}
SECUREC_ERROR_INVALID_PARAMTER
(
"vsnprintfp_s"
);
return
-
1
;
}
return
retVal
;
}
#ifdef SECUREC_FOR_WCHAR
#undef SECUREC_FOR_WCHAR
#endif
typedef
char
SecChar
;
#define SECUREC_CHAR(x) x
#define SECUREC_WRITE_MULTI_CHAR SecWriteMultiChar
#define SECUREC_WRITE_STRING SecWriteString
#include "output_p.inl"
static
inline
int
SecVsnprintfPImpl
(
char
*
string
,
size_t
count
,
int
priv
,
const
char
*
format
,
va_list
arglist
)
{
SecPrintfStream
str
;
int
retVal
;
str
.
count
=
(
int
)
count
;
/* this count include \0 character */
str
.
cur
=
string
;
retVal
=
SecOutputPS
(
&
str
,
priv
,
format
,
arglist
);
if
((
retVal
>=
0
)
&&
(
SECUREC_PUTC_ZERO
(
&
str
)
!=
EOF
))
{
return
(
retVal
);
}
else
if
(
str
.
count
<
0
)
{
/* the buffer was too small; we return truncation */
string
[
count
-
1
]
=
0
;
return
SECUREC_PRINTF_TRUNCATE
;
}
return
-
1
;
}
porting/linux/user/src/hilog/vsnprintf_s_p.h
0 → 100644
浏览文件 @
503dfc5a
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* 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.
*/
#ifndef __VSNPRINTFP_S_H__
#define __VSNPRINTFP_S_H__
#include "hilog_common.h"
#include <stddef.h>
#include <stdarg.h>
/**
* @Description: The vsnprintfp_s function is equivalent to the vsnprintf function except for the parameter destMax/count
* and the explicit runtime-constraints violation
* @param strDest - produce output according to a format ,write to the character string strDest
* @param destMax - The maximum length of destination buffer(including the terminating null byte ('\0'))
* @param count - do not write more than count bytes to strDest(not including the terminating null byte ('\0'))
* @param priv_on - if true, any not %{public} prefix formatter arguments will be printed as "<private>"
* @param format - format string
* @param arglist - instead of a variable number of arguments
* @return:return the number of characters printed(not including the terminating null byte ('\0')),
* If an error occurred return -1.Pay special attention to returning -1 when truncation occurs
*/
HILOG_LOCAL_API
int
vsnprintfp_s
(
char
*
strDest
,
size_t
destMax
,
size_t
count
,
int
priv
,
const
char
*
format
,
va_list
arglist
);
#endif
/* __VSNPRINTFP_S_H__ */
porting/linux/user/src/internal/hilog_adapter.h
0 → 100644
浏览文件 @
503dfc5a
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* 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.
*/
#ifndef MUSL_HILOG_ADAPTER_H
#define MUSL_HILOG_ADAPTER_H
#include <stdarg.h>
#include <stdbool.h>
// Log type
typedef
enum
{
LOG_TYPE_MIN
=
0
,
LOG_APP
=
0
,
// Log to kmsg, only used by init phase.
LOG_INIT
=
1
,
// Used by core service, framework.
LOG_CORE
=
3
,
LOG_KMSG
=
4
,
LOG_TYPE_MAX
}
LogType
;
// Log level
typedef
enum
{
LOG_LEVEL_MIN
=
0
,
LOG_DEBUG
=
3
,
LOG_INFO
=
4
,
LOG_WARN
=
5
,
LOG_ERROR
=
6
,
LOG_FATAL
=
7
,
LOG_LEVEL_MAX
,
}
LogLevel
;
int
HiLogAdapterPrint
(
LogType
type
,
LogLevel
level
,
unsigned
int
domain
,
const
char
*
tag
,
const
char
*
fmt
,
...)
__attribute__
((
__format__
(
os_log
,
5
,
6
)));
bool
HiLogAdapterIsLoggable
(
unsigned
int
domain
,
const
char
*
tag
,
LogLevel
level
);
#endif // MUSL_HILOG_ADAPTER_H
porting/linux/user/src/internal/musl_log.h
浏览文件 @
503dfc5a
...
...
@@ -16,19 +16,21 @@
#ifndef _MUSL_LOG_H
#define _MUSL_LOG_H
#include <hilog_adapter.h>
#ifdef __cplusplus
extern
"C"
{
#endif
#define MUSL_LOG_TYPE LOG_CORE
#define MUSL_LOG_DOMAIN 0xD003F00
#define MUSL_LOG_TAG "
musl_linker
"
#define MUSL_LOG_TAG "
MUSL
"
#ifdef ENABLE_MUSL_LOG
#define MUSL_LOGE(...) ((void)HiLog
Base
Print(MUSL_LOG_TYPE, LOG_ERROR, MUSL_LOG_DOMAIN, MUSL_LOG_TAG, __VA_ARGS__))
#define MUSL_LOGW(...) ((void)HiLog
Base
Print(MUSL_LOG_TYPE, LOG_WARN, MUSL_LOG_DOMAIN, MUSL_LOG_TAG, __VA_ARGS__))
#define MUSL_LOGI(...) ((void)HiLog
Base
Print(MUSL_LOG_TYPE, LOG_INFO, MUSL_LOG_DOMAIN, MUSL_LOG_TAG, __VA_ARGS__))
#define MUSL_LOGD(...) ((void)HiLog
Base
Print(MUSL_LOG_TYPE, LOG_DEBUG, MUSL_LOG_DOMAIN, MUSL_LOG_TAG, __VA_ARGS__))
#define MUSL_LOGE(...) ((void)HiLog
Adapter
Print(MUSL_LOG_TYPE, LOG_ERROR, MUSL_LOG_DOMAIN, MUSL_LOG_TAG, __VA_ARGS__))
#define MUSL_LOGW(...) ((void)HiLog
Adapter
Print(MUSL_LOG_TYPE, LOG_WARN, MUSL_LOG_DOMAIN, MUSL_LOG_TAG, __VA_ARGS__))
#define MUSL_LOGI(...) ((void)HiLog
Adapter
Print(MUSL_LOG_TYPE, LOG_INFO, MUSL_LOG_DOMAIN, MUSL_LOG_TAG, __VA_ARGS__))
#define MUSL_LOGD(...) ((void)HiLog
Adapter
Print(MUSL_LOG_TYPE, LOG_DEBUG, MUSL_LOG_DOMAIN, MUSL_LOG_TAG, __VA_ARGS__))
#else
#define MUSL_LOGE(...)
#define MUSL_LOGW(...)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录