Twain_DSM  1.0
log.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * TWAIN Data Source Manager version 2.1
3  * Manages image acquisition data sources used by a machine.
4  * Copyright © 2007 TWAIN Working Group:
5  * Adobe Systems Incorporated,AnyDoc Software Inc., Eastman Kodak Company,
6  * Fujitsu Computer Products of America, JFL Peripheral Solutions Inc.,
7  * Ricoh Corporation, and Xerox Corporation.
8  * All rights reserved.
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23  *
24  * Contact the TWAIN Working Group by emailing the Technical Subcommittee at
25  * twainwg@twain.org or mailing us at 13090 Hwy 9, Suite 3, Boulder Creek, CA 95006.
26  *
27  ***************************************************************************/
28 
37 #include "dsm.h"
38 
39 
40 
45 #define kLOGENV "TWAINDSM_LOG"
46 
53 #define kLOGMODEENV "TWAINDSM_LOGMODE"
54 
59 #define TWNDSM_MAX_MSG 1024
60 
61 
62 
67 {
68  public:
71  {
72  memset(&pod,0,sizeof(pod));
73  }
74 
75  public:
76  // If you add a class in future, (and I can't imagine why you
77  // would) declare it here and not in the pod, or the memset
78  // we do in the constructor will ruin your day...
79 
84  struct _pod
85  {
86  FILE *m_plog;
87  char *m_message;
88  char m_logpath[FILENAME_MAX];
89  char m_logmode[16];
90  int m_nIndent;
91  } pod;
92 };
93 
94 
95 
107 {
108  // Init stuff...
110 
111  // see if a logfile is to be used
113 
114  // If we have a path, then get our mode...
116  {
118  if (!m_ptwndsmlogimpl->pod.m_logmode[0])
119  {
120  // The default is to wipe the log clean...
122  }
123 
124  // Only bother to allocate a buffer if logging is on...
125  m_ptwndsmlogimpl->pod.m_message = (char*)calloc(TWNDSM_MAX_MSG,1);
127  {
128  kPANIC("Unable to allocate a buffer for logging...");
129  }
130  }
131 }
132 
133 
134 
140 {
141  if (m_ptwndsmlogimpl)
142  {
144  {
145  fclose(m_ptwndsmlogimpl->pod.m_plog);
146  }
148  {
150  }
151  delete m_ptwndsmlogimpl;
152  m_ptwndsmlogimpl = 0;
153  }
154 }
155 
156 
157 
173 void CTwnDsmLog::Log(const int _doassert,
174  const char* const _file,
175  const int _line,
176  const char* const _format,
177  ...)
178 {
179  // We've nothing to do, so bail...
180  if (0 == m_ptwndsmlogimpl->pod.m_logpath[0])
181  {
182  return;
183  }
184 
185  // Okay, now use the stack...
186  UINT nError = 0;
187  UINT nChars = 0;
188  char *message = NULL;
189  const char *file = NULL;
190 
191  // Grab the system error, this can be really useful...
192  #if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
193  nError = GetLastError();
194  if (nError == 0)
195  {
196  // Yeah, yeah...this is dumb, but I like a clean prefast log... :)
197  nError = 0;
198  }
199  #elif (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
200  nError = errno;
201  #else
202  #error Sorry, we do not recognize this system...
203  #endif
204 
205  // If we have no log yet, try to get one...
206  if (0 == m_ptwndsmlogimpl->pod.m_plog)
207  {
209  if (0 == m_ptwndsmlogimpl->pod.m_plog)
210  {
211  fprintf(stderr,"DSM: Error - logging has been disabled because logfile could not be opened: file=<%s>, mode=<%s>, errno=%d\r\n",m_ptwndsmlogimpl->pod.m_logpath,m_ptwndsmlogimpl->pod.m_logmode,errno);
213  }
214  return;
215  }
216 
217  // Trim the filename down to just the filename, no path...
218  file = 0;
219  #if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
220  // Only look for this on Windows...
221  file = strrchr(_file,'\\');
222  #endif
223  if (!file)
224  {
225  // If we didn't find a backslash, try a forward slash...
226  file = strrchr(_file,'/');
227  }
228  if (file)
229  {
230  // skip the slash...
231  file = &file[1];
232  }
233  else
234  {
235  // Couldn't find any slashes...
236  file = (char*)_file;
237  }
238 
239  // Build the message header...
240  #if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
241  SYSTEMTIME st;
242  GetLocalTime(&st);
245  #if (TWNDSM_CMP_VERSION >= 1400)
247  #endif
248  "[%02d%02d%02d%03d %-8s %4d %5u %p] %.*s",
249  (int)st.wHour, (int)st.wMinute, (int)st.wSecond,(int)st.wMilliseconds,
250  file, (int)_line,
251  nError,
252  (void*)(UINT_PTR)GETTHREADID(),
253  m_ptwndsmlogimpl->pod.m_nIndent*2, " ");
254  #elif (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
255  timeval tv;
256  tm tm;
257  gettimeofday(&tv,NULL);
258  tzset();
259  localtime_r(&tv.tv_sec,&tm);
262  "[%02d%02d%02d%03d %-8s %4d %5d %p] %.*s",
263  tm.tm_hour,tm.tm_min,tm.tm_sec,(int)(tv.tv_usec / 1000),
264  file,_line,
265  nError,
266  (void*)GETTHREADID(),
267  m_ptwndsmlogimpl->pod.m_nIndent*2, " ");
268 
269  #else
270  #error Sorry, we do not recognize this system...
271  #endif
272 
273  // This is the room remaining in the buffer, with room for a null...
274  nChars = (TWNDSM_MAX_MSG - nChars) - 1;
276 
277  // Finally, tack on the user portion of the message...
278  va_list valist;
279  va_start(valist,_format);
280  #if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP) && (TWNDSM_CMP_VERSION >= 1400)
281  _vsnprintf_s(message,nChars,nChars,_format,valist);
282  #elif (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
283  _vsnprintf(message,nChars,_format,valist);
284  #elif (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
285  vsnprintf(message,nChars,_format,valist);
286  #else
287  #error Sorry, we do not recognize this system...
288  #endif
289  va_end(valist);
290 
291  // Write the message...
293  fflush(m_ptwndsmlogimpl->pod.m_plog);
294 
295  // Do the assert, if asked for...
296  if (_doassert)
297  {
298  assert(0);
299  }
300 }
301 
302 void CTwnDsmLog::Indent(int nChange)
303 {
304  m_ptwndsmlogimpl->pod.m_nIndent += nChange;
305 }
dsm.h
Everything we need to make our .cpp files happy.
FOPEN
#define FOPEN(pf, name, mode)
Definition: dsm.h:300
SNPRINTF
#define SNPRINTF
OS abstraction macro that calls system _snprintf function.
Definition: dsm.h:292
CTwnDsmLogImpl
Our implementation class where we hide our attributes...
Definition: log.cpp:67
CTwnDsmLogImpl::_pod
We use a pod system because it help prevents us from making dumb initialization mistakes....
Definition: log.cpp:85
CTwnDsmLog::Log
void Log(const int _doassert, const char *const _file, const int _line, const char *const _format,...)
The logging function.
Definition: log.cpp:173
SGETENV
#define SGETENV(d, z, n)
Secure Get enviroment varable.
Definition: dsm.h:404
GETTHREADID
#define GETTHREADID
get the thread ID
Definition: dsm.h:299
CTwnDsmLogImpl::pod
struct CTwnDsmLogImpl::_pod pod
Pieces of data for CTwnDsmAppsImpl.
kLOGENV
#define kLOGENV
Enviroment varible of path to where to write the LogFile name.
Definition: log.cpp:45
CTwnDsmLogImpl::_pod::m_logpath
char m_logpath[FILENAME_MAX]
where we put the file.
Definition: log.cpp:88
CTwnDsmLog::CTwnDsmLog
CTwnDsmLog()
The CTwnDsmLog constructor.
Definition: log.cpp:106
CTwnDsmLog::~CTwnDsmLog
~CTwnDsmLog()
The CTwnDsmLog destructor.
Definition: log.cpp:139
SSTRCPY
#define SSTRCPY(d, z, s)
Secure String copy.
Definition: dsm.h:401
kPANIC
#define kPANIC(msg)
Display message to user.
Definition: dsm.h:508
CTwnDsmLogImpl::_pod::m_logmode
char m_logmode[16]
how we fopen the file.
Definition: log.cpp:89
CTwnDsmLogImpl::CTwnDsmLogImpl
CTwnDsmLogImpl()
Make sure we're squeaky clean...
Definition: log.cpp:70
CTwnDsmLogImpl::_pod::m_nIndent
int m_nIndent
how far to indent the log message
Definition: log.cpp:90
CTwnDsmLog::Indent
void Indent(int nChange)
Indent the logging to help with seeing recursive calls param[in] nChange Either +1 or -1.
Definition: log.cpp:302
CTwnDsmLog::m_ptwndsmlogimpl
CTwnDsmLogImpl * m_ptwndsmlogimpl
The implementation pointer helps with encapulation.
Definition: dsm.h:592
CTwnDsmLogImpl::_pod::m_message
char * m_message
buffer for our messages.
Definition: log.cpp:87
CTwnDsmLogImpl::_pod::m_plog
FILE * m_plog
where we'll dump information.
Definition: log.cpp:86
kLOGMODEENV
#define kLOGMODEENV
Enviroment varible of the fopen logmode to use (if you need to grow the log).
Definition: log.cpp:53
TWNDSM_MAX_MSG
#define TWNDSM_MAX_MSG
Maximum message length we can handle...
Definition: log.cpp:59
NCHARS
#define NCHARS(s)
The number of characters in a charter array.
Definition: dsm.h:285
TWNDSM_CMP_VERSION
#define TWNDSM_CMP_VERSION
The version of the compliler used.
Definition: dsm.h:114