1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     dbg_Logger.cpp
4 
5   Copyright (C)2009 Nintendo Co., Ltd.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Rev: 22730 $
14  *---------------------------------------------------------------------------*/
15 
16 #include <nn/types.h>
17 #include <nn/dbg/dbg_Logger.h>
18 #include <nn/nstd.h>
19 #include <cstring>
20 #include <cstdio>
21 #include <algorithm>
22 
23 /****************************************************************************/
24 namespace nn {
25 namespace dbg {
26 namespace detail {
27 /****************************************************************************/
28 
29 char8* Logger::s_LevelStrings[] = {
30     "DEBUG",
31     "INFO",
32     "WARN",
33     "ERROR",
34     "FATAL",
35     "FORCE"
36 };
37 
38 u32 Logger::s_UpperLevel    = Logger::LEVEL_FATAL;
39 u32 Logger::s_LowerLevel    = NN_LOG_LEVEL;
40 bool Logger::s_Initialized  = false;
41 u8 Logger::s_ShowFlag       = 0;
42 
MakeFuncName(const char8 * src,char8 * dest,size_t length)43 size_t Logger::MakeFuncName(const char8* src, char8* dest, size_t length)
44 {
45 	// TODO: srcのNULLチェック
46 	// TODO: destのNULLチェック
47     char8* pSrcTop = const_cast<char8*>(src);
48     char8* pSrcSigHead = ::std::strrchr(pSrcTop, '(');
49     // 末尾を決定
50     // ENABLE_SIGNATURE ならば、srcの末尾
51     // そうでないなら、関数の ( の位置
52     char8* pSrcLast = (s_ShowFlag & ENABLE_SIGNATURE) ?
53                 pSrcTop + ::std::strlen(src) :
54                 pSrcSigHead;
55 
56     // 先頭を決定
57     // ENABLE_NAMESPACE ならば、srcの先頭、そうでなければ、
58     // 後ろから3つ目の:の位置 + 1
59     if(!(s_ShowFlag & ENABLE_NAMESPACE))
60     {
61         pSrcTop = pSrcSigHead;
62         for(int count = 0;pSrcTop != src && count < 3; pSrcTop--)
63         {
64             count = (*pSrcTop == ':') ? count + 1 : count;
65         }
66         pSrcTop += 2;
67     }
68     size_t copyLength = ::std::min<size_t>(pSrcLast - pSrcTop, length - 1);
69     ::std::memcpy(dest, pSrcTop, copyLength);
70     dest[copyLength] = '\0';
71     return copyLength;
72 }
73 
PrintLog(const u32 level,const char8 * funcName,const char8 * fileName,const int line,const char8 * fmt,...)74 void Logger::PrintLog(const u32 level, const char8* funcName, const char8* fileName, const int line,
75                             const char8* fmt, ...)
76 {
77 #ifndef NN_SWITCH_DISABLE_DEBUG_PRINT
78 //    static int count = 0;
79     // 設定レベル範囲外ならすぐ抜ける
80     if(!s_Initialized)
81     {
82         s_LowerLevel = NN_LOG_LEVEL;
83     }
84 
85     if(level != LEVEL_FORCE && (level < s_LowerLevel || s_UpperLevel < level))
86     {
87         return;
88     }
89 
90     {
91         // funcNameを処理
92         char8 prefix[BUF_SIZE];
93         size_t len = std::min<size_t>(::std::snprintf(prefix, sizeof(prefix), "[%s] ", s_LevelStrings[level]), sizeof(prefix));
94 
95         len += MakeFuncName(funcName, &prefix[len], BUF_SIZE - len - 3);
96 
97         ::std::strncat(&prefix[len], " : ", BUF_SIZE - len - 3);
98         len += 3;
99 
100         prefix[len] = '\0';
101 
102         //nn::dbg::PrintfDebugString(prefix);
103         //nn::dbg::PrintfDebugString("%s", prefix);
104         //nn::dbg::detail::Printf("%s", prefix);
105         nn::dbg::detail::PutString(prefix, len);
106     }
107 
108     {
109         char8 userMessage[BUF_SIZE];
110 
111         // ログメッセージを展開
112         va_list vlist;
113         va_start(vlist, fmt);
114         size_t len = std::min<size_t>(nn::nstd::TVSNPrintf(userMessage, sizeof(userMessage), fmt, vlist), sizeof(userMessage));
115         va_end(vlist);
116 
117         // userMessageの末尾に\nが入っている場合、削除する
118         for (; len > 0 && userMessage[len - 1] == '\n'; --len)
119         {
120             userMessage[len - 1] = '\0';
121         }
122 
123         //nn::dbg::OutputDebugString(userMessage);
124         //nn::dbg::PrintfDebugString("%s", userMessage);
125         nn::dbg::detail::PutString(userMessage, len);
126     }
127 
128     {
129         // fileNameを処理
130         char8* pFileNameTop = NULL;
131         if(!(s_ShowFlag & ENABLE_LONGPATH))
132         {
133             pFileNameTop = (char8*)::std::strrchr(fileName, '\\');
134             if(pFileNameTop)
135             {
136                 pFileNameTop++;
137             }
138         }
139         if(!pFileNameTop)
140         {
141             pFileNameTop = (char8*)fileName;
142         }
143 
144         // sprintf で出力文字列を作成
145         //nn::dbg::PrintfDebugString(" (%s:%d)\n",  pFileNameTop, line);
146         nn::dbg::detail::Printf(" (%s:%d)\n",  pFileNameTop, line);
147     }
148 #else
149     NN_UNUSED_VAR(level);
150     NN_UNUSED_VAR(funcName);
151     NN_UNUSED_VAR(fileName);
152     NN_UNUSED_VAR(line);
153     NN_UNUSED_VAR(fmt);
154 #endif
155 }
156 
157 /****************************************************************************/
158 
159 
160 /****************************************************************************/
161 }
162 }  // namespace dbg
163 }  // namespace nn
164