1251881Speter/*
2251881Speter * debug.c :  small functions to help SVN developers
3251881Speter *
4251881Speter * ====================================================================
5251881Speter *    Licensed to the Apache Software Foundation (ASF) under one
6251881Speter *    or more contributor license agreements.  See the NOTICE file
7251881Speter *    distributed with this work for additional information
8251881Speter *    regarding copyright ownership.  The ASF licenses this file
9251881Speter *    to you under the Apache License, Version 2.0 (the
10251881Speter *    "License"); you may not use this file except in compliance
11251881Speter *    with the License.  You may obtain a copy of the License at
12251881Speter *
13251881Speter *      http://www.apache.org/licenses/LICENSE-2.0
14251881Speter *
15251881Speter *    Unless required by applicable law or agreed to in writing,
16251881Speter *    software distributed under the License is distributed on an
17251881Speter *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18251881Speter *    KIND, either express or implied.  See the License for the
19251881Speter *    specific language governing permissions and limitations
20251881Speter *    under the License.
21251881Speter * ====================================================================
22251881Speter */
23251881Speter
24251881Speter/* These functions are only available to SVN developers and should never
25251881Speter   be used in release code. One of the reasons to avoid this code in release
26251881Speter   builds is that this code is not thread-safe. */
27251881Speter#include <stdarg.h>
28251881Speter#include <assert.h>
29251881Speter
30251881Speter#include <apr_pools.h>
31251881Speter#include <apr_strings.h>
32251881Speter#include "svn_types.h"
33251881Speter#include "svn_string.h"
34251881Speter
35251881Speter#ifndef SVN_DBG__PROTOTYPES
36251881Speter#define SVN_DBG__PROTOTYPES
37251881Speter#endif
38251881Speter#include "private/svn_debug.h"
39251881Speter
40251881Speter
41251881Speter#define DBG_FLAG "DBG: "
42251881Speter
43251881Speter/* This will be tweaked by the preamble code.  */
44251881Speterstatic const char *debug_file = NULL;
45251881Speterstatic long debug_line = 0;
46251881Speterstatic FILE * volatile debug_output = NULL;
47251881Speter
48251881Speter
49251881Speterstatic svn_boolean_t
50251881Speterquiet_mode(void)
51251881Speter{
52251881Speter  return getenv("SVN_DBG_QUIET") != NULL;
53251881Speter}
54251881Speter
55251881Speter
56251881Spetervoid
57251881Spetersvn_dbg__preamble(const char *file, long line, FILE *output)
58251881Speter{
59251881Speter  debug_output = output;
60251881Speter
61251881Speter  if (output != NULL && !quiet_mode())
62251881Speter    {
63251881Speter      /* Quick and dirty basename() code.  */
64251881Speter      const char *slash = strrchr(file, '/');
65251881Speter
66251881Speter      if (slash == NULL)
67251881Speter        slash = strrchr(file, '\\');
68251881Speter      if (slash)
69251881Speter        debug_file = slash + 1;
70251881Speter      else
71251881Speter        debug_file = file;
72251881Speter    }
73251881Speter  debug_line = line;
74251881Speter}
75251881Speter
76251881Speter
77251881Speter/* Print a formatted string using format FMT and argument-list AP,
78251881Speter * prefixing each line of output with a debug header. */
79251881Speterstatic void
80251881Speterdebug_vprintf(const char *fmt, va_list ap)
81251881Speter{
82251881Speter  FILE *output = debug_output;
83251881Speter  char prefix[80], buffer[1000];
84251881Speter  char *s = buffer;
85251881Speter  int n;
86251881Speter
87251881Speter  if (output == NULL || quiet_mode())
88251881Speter    return;
89251881Speter
90251881Speter  n = apr_snprintf(prefix, sizeof(prefix), DBG_FLAG "%s:%4ld: ",
91251881Speter                   debug_file, debug_line);
92251881Speter  assert(n < sizeof(prefix) - 1);
93251881Speter  n = apr_vsnprintf(buffer, sizeof(buffer), fmt, ap);
94251881Speter  assert(n < sizeof(buffer) - 1);
95251881Speter  do
96251881Speter    {
97251881Speter      char *newline = strchr(s, '\n');
98251881Speter      if (newline)
99251881Speter        *newline = '\0';
100251881Speter
101251881Speter      fputs(prefix, output);
102251881Speter      fputs(s, output);
103251881Speter      fputc('\n', output);
104251881Speter
105251881Speter      if (! newline)
106251881Speter        break;
107251881Speter      s = newline + 1;
108251881Speter    }
109251881Speter  while (*s);  /* print another line, except after a final newline */
110251881Speter}
111251881Speter
112251881Speter
113251881Spetervoid
114251881Spetersvn_dbg__printf(const char *fmt, ...)
115251881Speter{
116251881Speter  va_list ap;
117251881Speter
118251881Speter  va_start(ap, fmt);
119251881Speter  debug_vprintf(fmt, ap);
120251881Speter  va_end(ap);
121251881Speter}
122251881Speter
123251881Speter
124251881Spetervoid
125251881Spetersvn_dbg__print_props(apr_hash_t *props,
126251881Speter                     const char *header_fmt,
127251881Speter                     ...)
128251881Speter{
129251881Speter/* We only build this code if SVN_DEBUG is defined. */
130251881Speter#ifdef SVN_DEBUG
131251881Speter
132251881Speter  apr_hash_index_t *hi;
133251881Speter  va_list ap;
134251881Speter
135251881Speter  va_start(ap, header_fmt);
136251881Speter  debug_vprintf(header_fmt, ap);
137251881Speter  va_end(ap);
138251881Speter
139251881Speter  if (props == NULL)
140251881Speter    {
141251881Speter      svn_dbg__printf("    (null)\n");
142251881Speter      return;
143251881Speter    }
144251881Speter
145251881Speter  for (hi = apr_hash_first(apr_hash_pool_get(props), props); hi;
146251881Speter        hi = apr_hash_next(hi))
147251881Speter    {
148251881Speter      const char *name = svn__apr_hash_index_key(hi);
149251881Speter      svn_string_t *val = svn__apr_hash_index_val(hi);
150251881Speter
151251881Speter      svn_dbg__printf("    '%s' -> '%s'\n", name, val->data);
152251881Speter    }
153251881Speter#endif /* SVN_DEBUG */
154251881Speter}
155251881Speter
156