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