Initial checkin. Start of UDF image building app.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5456 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Tyler Dauwalder
2003-11-23 12:25:49 +00:00
parent 642d90775a
commit ca84d5aff2
6 changed files with 681 additions and 0 deletions
+329
View File
@@ -0,0 +1,329 @@
//----------------------------------------------------------------------
// This software is part of the OpenBeOS distribution and is covered
// by the OpenBeOS license.
//
// This version copyright (c) 2003 Tyler Dauwalder, [email protected]
// Initial version copyright (c) 2002 Axel Dörfler, [email protected]
//----------------------------------------------------------------------
/*! \file Debug.cpp
Support code for handy debugging macros.
*/
#include "Debug.h"
#include <KernelExport.h>
#include <TLS.h>
//----------------------------------------------------------------------
// Long-winded overview of the debug output macros:
//----------------------------------------------------------------------
/*! \def DEBUG_INIT()
\brief Increases the indentation level, prints out the enclosing function's
name, and creates a \c DebugHelper object on the stack to automatically
decrease the indentation level upon function exit.
This macro should be called at the very beginning of any function in
which you wish to use any of the other debugging macros.
If DEBUG is undefined, does nothing.
*/
//----------------------------------------------------------------------
/*! \def PRINT(x)
\brief Prints out the enclosing function's name followed by the contents
of \a x at the current indentation level.
\param x A printf-style format string enclosed in an extra set of parenteses,
e.g. PRINT(("%d\n", 0));
If DEBUG is undefined, does nothing.
*/
//----------------------------------------------------------------------
/*! \def LPRINT(x)
\brief Identical to \c PRINT(x), except that the line number in the source
file at which the macro is invoked is also printed.
\param x A printf-style format string enclosed in an extra set of parenteses,
e.g. PRINT(("%d\n", 0));
If DEBUG is undefined, does nothing.
*/
//----------------------------------------------------------------------
/*! \def SIMPLE_PRINT(x)
\brief Directly prints the contents of \a x with no extra formatting or
information included (just like a straight \c printf() call).
\param x A printf-style format string enclosed in an extra set of parenteses,
e.g. PRINT(("%d\n", 0));
If DEBUG is undefined, does nothing.
*/
//----------------------------------------------------------------------
/*! \def PRINT_INDENT()
\brief Prints out enough indentation characters to indent the current line
to the current indentation level (assuming the cursor was flush left to
begin with...).
This function is called by the other \c *PRINT* macros, and isn't really
intended for general consumption, but you might find it useful.
If DEBUG is undefined, does nothing.
*/
//----------------------------------------------------------------------
/*! \def REPORT_ERROR(error)
\brief Calls \c LPRINT(x) with a format string listing the error
code in \c error (assumed to be a \c status_t value) and the
corresponding text error code returned by a call to \c strerror().
This function is called by the \c RETURN* macros, and isn't really
intended for general consumption, but you might find it useful.
\param error A \c status_t error code to report.
If DEBUG is undefined, does nothing.
*/
//----------------------------------------------------------------------
/*! \def RETURN_ERROR(error)
\brief Calls \c REPORT_ERROR(error) if error is a an error code (i.e.
negative), otherwise remains silent. In either case, the enclosing
function is then exited with a call to \c "return error;".
\param error A \c status_t error code to report (if negative) and return.
If DEBUG is undefined, silently returns the value in \c error.
*/
//----------------------------------------------------------------------
/*! \def RETURN(error)
\brief Prints out a description of the error code being returned
(which, in this case, may be either "erroneous" or "successful")
and then exits the enclosing function with a call to \c "return error;".
\param error A \c status_t error code to report and return.
If DEBUG is undefined, silently returns the value in \c error.
*/
//----------------------------------------------------------------------
/*! \def FATAL(x)
\brief Prints out a fatal error message.
This one's still a work in progress...
\param x A printf-style format string enclosed in an extra set of parenteses,
e.g. PRINT(("%d\n", 0));
If DEBUG is undefined, does nothing.
*/
//----------------------------------------------------------------------
/*! \def INFORM(x)
\brief Directly prints the contents of \a x with no extra formatting or
information included (just like a straight \c printf() call). Does so
whether \c DEBUG is defined or not.
\param x A printf-style format string enclosed in an extra set of parenteses,
e.g. PRINT(("%d\n", 0));
I'll say it again: Prints its output regardless to DEBUG being defined or
undefined.
*/
//----------------------------------------------------------------------
/*! \def DBG(x)
\brief If debug is defined, \a x is passed along to the code and
executed unmodified. If \c DEBUG is undefined, the contents of
\a x disappear into the ether.
\param x Damn near anything resembling valid C\C++.
*/
//----------------------------------------------------------------------
/*! \def DIE(x)
\brief Drops the user into the appropriate debugger (user or kernel)
after printing out the handy message bundled in the parenthesee
enclosed printf-style format string found in \a x.
\param x A printf-style format string enclosed in an extra set of parenteses,
e.g. PRINT(("%d\n", 0));
*/
//----------------------------------------------------------------------
// declarations
//----------------------------------------------------------------------
static void indent(uint8 tabCount);
static void unindent(uint8 tabCount);
static int32 get_tls_handle();
//! Used to keep the tls handle from being allocated more than once.
vint32 tls_spinlock = 0;
/*! \brief Used to flag whether the tls handle has been allocated yet.
Not sure if this really needs to be \c volatile or not...
*/
volatile bool tls_handle_initialized = false;
//! The tls handle of the tls var used to store indentation info.
int32 tls_handle = 0;
//----------------------------------------------------------------------
// public functions
//----------------------------------------------------------------------
/*! \brief Returns the current debug indentation level for the
current thread.
NOTE: indentation is currently unsupported for R5::kernelland due
to lack of thread local storage support.
*/
int32
_get_debug_indent_level()
{
return (int32)tls_get(get_tls_handle());
}
//----------------------------------------------------------------------
// static functions
//----------------------------------------------------------------------
/*! \brief Increases the current debug indentation level for
the current thread by 1.
*/
void
indent(uint8 tabCount)
{
tls_set(get_tls_handle(), (void*)(_get_debug_indent_level()+tabCount));
}
/*! \brief Decreases the current debug indentation level for
the current thread by 1.
*/
void
unindent(uint8 tabCount)
{
tls_set(get_tls_handle(), (void*)(_get_debug_indent_level()-tabCount));
}
/*! \brief Returns the thread local storage handle used to store
indentation information, allocating the handle first if
necessary.
*/
int32
get_tls_handle()
{
// Init the tls handle if this is the first call.
if (!tls_handle_initialized) {
if (atomic_or(&tls_spinlock, 1) == 0) {
// First one in gets to init
tls_handle = tls_allocate();
tls_handle_initialized = true;
atomic_and(&tls_spinlock, 0);
} else {
// All others must wait patiently
while (!tls_handle_initialized) {
snooze(1);
}
}
}
return tls_handle;
}
/*! \brief Helper class for initializing the debugging output
file.
Note that this hummer isn't threadsafe, but it doesn't really
matter for our concerns, since the worst it'll result in is
a dangling file descriptor, and that would be in the case of
two or more volumes being mounted almost simultaneously...
not too big of a worry.
*/
class DebugOutputFile {
public:
DebugOutputFile(const char *filename = NULL)
: fFile(-1)
{
Init(filename);
}
~DebugOutputFile() {
if (fFile >= 0)
close(fFile);
}
void Init(const char *filename) {
if (fFile < 0 && filename)
fFile = open(filename, O_RDWR | O_CREAT | O_TRUNC);
}
int File() const { return fFile; }
private:
int fFile;
};
DebugOutputFile *out = NULL;
/*! \brief It doesn't appear that the constructor for the global
\c out variable is called when built as an R5 filesystem add-on,
so this function needs to be called in udf_mount to let the
magic happen.
*/
void initialize_debugger(const char *filename)
{
#if DEBUG_TO_FILE
if (!out) {
out = new DebugOutputFile(filename);
dbg_printf("out was NULL!\n");
} else {
DebugOutputFile *temp = out;
out = new DebugOutputFile(filename);
dbg_printf("out was %p!\n", temp);
}
#endif
}
// dbg_printf, stolen from Ingo's ReiserFS::Debug.cpp.
void
dbg_printf(const char *format,...)
{
#if DEBUG_TO_FILE
if (!out)
return;
char buffer[1024];
va_list args;
va_start(args, format);
// no vsnprintf() on PPC
#if defined(__INTEL__)
vsnprintf(buffer, sizeof(buffer) - 1, format, args);
#endif
va_end(args);
buffer[sizeof(buffer) - 1] = '\0';
write(out->File(), buffer, strlen(buffer));
#endif
}
//----------------------------------------------------------------------
// DebugHelper
//----------------------------------------------------------------------
/*! \brief Increases the current indentation level.
*/
DebugHelper::DebugHelper(const char *className, uint8 tabCount)
: fTabCount(tabCount)
, fClassName(NULL)
{
indent(fTabCount);
if (className) {
fClassName = (char*)malloc(strlen(className)+1);
if (fClassName)
strcpy(fClassName, className);
}
}
/*! \brief Decreases the current indentation level.
*/
DebugHelper::~DebugHelper()
{
unindent(fTabCount);
free(fClassName);
}
+227
View File
@@ -0,0 +1,227 @@
//----------------------------------------------------------------------
// This software is part of the OpenBeOS distribution and is covered
// by the OpenBeOS license.
//
// This version copyright (c) 2003 Tyler Dauwalder, [email protected]
// Initial version copyright (c) 2002 Axel Dörfler, [email protected]
// dbg_printf() function copyright (c) 2003 Ingo Weinhold, [email protected]
//----------------------------------------------------------------------
#ifndef MY_DEBUG_H
#define MY_DEBUG_H
/*! \file Debug.h
Handy debugging macros.
*/
#include <KernelExport.h>
#include <OS.h>
#ifdef DEBUG
# include <string.h>
#endif
#include <unistd.h>
#define DEBUG_TO_FILE 0
#if DEBUG_TO_FILE
# include <stdio.h>
# include <fcntl.h>
# define __out dbg_printf
void dbg_printf(const char *format,...);
void initialize_debugger(const char *filename);
#else
# include <stdio.h>
# include <malloc.h>
# define __out printf
#endif
class DebugHelper;
int32 _get_debug_indent_level();
/*! \brief Helper class that is allocated on the stack by
the \c DEBUG_INIT() macro. On creation, it increases the
current indentation level by the amount specified via its
constructor's \c tabCount parameter; on destruction, it
decreases it.
*/
class DebugHelper
{
public:
DebugHelper(const char *className = NULL, uint8 tabCount = 1);
~DebugHelper();
uint8 TabCount() const { return fTabCount; }
const char* ClassName() const { return fClassName; }
private:
uint8 fTabCount;
char *fClassName;
};
//----------------------------------------------------------------------
// NOTE: See Debug.cpp for complete descriptions of the following
// debug macros.
//----------------------------------------------------------------------
//----------------------------------------------------------------------
// DEBUG-independent macros
//----------------------------------------------------------------------
#define INFORM(x) { __out("mkudf: "); __out x; }
#ifdef USER
# define DIE(x) debugger x
#else
# define DIE(x) kernel_debugger x
#endif
//----------------------------------------------------------------------
// DEBUG-dependent macros
//----------------------------------------------------------------------
#ifdef DEBUG
#if DEBUG_TO_FILE
#define INITIALIZE_DEBUGGING_OUTPUT_FILE(filename) initialize_debugger(filename);
#else
#define INITIALIZE_DEBUGGING_OUTPUT_FILE(filename) ;
#endif
#define DEBUG_INIT_SILENT(className) \
DebugHelper _debugHelper(className, 2);
#define DEBUG_INIT(className) \
DEBUG_INIT_SILENT(className); \
PRINT(("\n"));
#define DEBUG_INIT_ETC(className, arguments) \
DEBUG_INIT_SILENT(className) \
{ \
PRINT_INDENT(); \
if (_debugHelper.ClassName()) { \
__out("mkudf: %s::%s(", \
_debugHelper.ClassName(), __FUNCTION__); \
} else { \
__out("mkudf: %s(", __FUNCTION__); \
} \
__out arguments; \
__out("):\n"); \
}
#define DUMP_INIT(categoryFlags, className) \
DEBUG_INIT_SILENT(className);
#define PRINT(x) { \
{ \
PRINT_INDENT(); \
if (_debugHelper.ClassName()) { \
__out("mkudf: %s::%s(): ", \
_debugHelper.ClassName(), __FUNCTION__); \
} else { \
__out("mkudf: %s(): ", __FUNCTION__); \
} \
__out x; \
} \
}
#define LPRINT(x) { \
{ \
PRINT_INDENT(); \
if (_debugHelper.ClassName()) { \
__out("mkudf: %s::%s(): line %d: ", \
_debugHelper.ClassName(), __FUNCTION__, __LINE__); \
} else { \
__out("mkudf: %s(): line %d: ", \
__FUNCTION__, __LINE__); \
} \
__out x; \
} \
}
#define SIMPLE_PRINT(x) { \
{ \
__out x; \
} \
}
#define PRINT_INDENT() { \
{ \
int32 _level = _get_debug_indent_level(); \
for (int32 i = 0; i < _level-_debugHelper.TabCount(); i++) { \
__out(" "); \
} \
} \
}
#define PRINT_DIVIDER() \
PRINT_INDENT(); \
SIMPLE_PRINT(("------------------------------------------------------------\n"));
#define DUMP(object) \
{ \
(object).dump(); \
}
#define PDUMP(objectPointer) \
{ \
(objectPointer)->dump(); \
}
#define REPORT_ERROR(error) { \
LPRINT(("returning error 0x%lx, `%s'\n", error, strerror(error))); \
}
#define RETURN_ERROR(error) { \
status_t _status = error; \
if (_status < (status_t)B_OK) \
REPORT_ERROR(_status); \
return _status; \
}
#define RETURN(error) { \
status_t _status = error; \
if (_status < (status_t)B_OK) { \
REPORT_ERROR(_status); \
} else if (_status == (status_t)B_OK) { \
LPRINT(("returning B_OK\n")); \
} else { \
LPRINT(("returning 0x%lx = %ld\n", _status, _status)); \
} \
return _status; \
}
#define FATAL(x) { \
PRINT(("fatal error: ")); SIMPLE_PRINT(x); \
}
#define DBG(x) x ;
#else // ifdef DEBUG
#define INITIALIZE_DEBUGGING_OUTPUT_FILE(filename) ;
#define DEBUG_INIT_SILENT(className) ;
#define DEBUG_INIT(className) ;
#define DEBUG_INIT_ETC(className, arguments) ;
#define DUMP_INIT(className) ;
#define PRINT(x) ;
#define LPRINT(x) ;
#define SIMPLE_PRINT(x) ;
#define PRINT_INDENT(x) ;
#define PRINT_DIVIDER() ;
#define DUMP(object) ;
#define PDUMP(objectPointer) ;
#define REPORT_ERROR(status) ;
#define RETURN_ERROR(status) return status;
#define RETURN(status) return status;
#define FATAL(x) { __out("mkudf: fatal error: "); __out x; }
#define DBG(x) ;
#define DUMP(x) ;
#endif // ifdef DEBUG else
#define TRACE(x) DBG(dprintf x)
// These macros turn on or off extensive and generally unnecessary
// debugging output regarding table of contents parsing
//#define WARN(x) (dprintf x)
//#define WARN(x)
#define WARN(x) DBG(dprintf x)
#endif // MY_DEBUG_H
+10
View File
@@ -0,0 +1,10 @@
SubDir OBOS_TOP src apps bin makeudfimage ;
BinCommand makeudfimage
: makeudfimage.cpp
Debug.cpp
Shell.cpp
: stdc++.r4
;
+66
View File
@@ -0,0 +1,66 @@
//----------------------------------------------------------------------
// This software is part of the OpenBeOS distribution and is covered
// by the OpenBeOS license.
//
// Copyright (c) 2003 Tyler Dauwalder, [email protected]
//----------------------------------------------------------------------
/*! \file Shell.cpp
Command-line shell for makeudfimage
*/
#include "Shell.h"
#include <stdio.h>
#include "Debug.h"
Shell::Shell()
{
}
void
Shell::Run(int argc, char *argv[])
{
DEBUG_INIT("Shell");
_ProcessArguments(argc, argv);
PRINT(("finished\n"));
}
status_t
Shell::_ProcessArguments(int argc, char *argv[]) {
DEBUG_INIT_ETC("Shell", ("argc: %d", argc));
// If we're given no parameters, the default settings
// will do just fine
if (argc < 2)
return B_OK;
// Handle each command line argument (skipping the first
// which is just the app name)
for (int i = 1; i < argc; i++) {
std::string str(argv[i]);
status_t error = _ProcessArgument(str, argc, argv);
if (error)
RETURN(error);
}
RETURN(B_OK);
}
status_t
Shell::_ProcessArgument(std::string arg, int argc, char *argv[]) {
DEBUG_INIT_ETC("Shell", ("arg: `%s'", arg.c_str()));
if (arg == "--help") {
_PrintHelp();
RETURN(B_ERROR);
}
RETURN(B_ERROR);
}
void
Shell::_PrintHelp() {
printf("usage: makeudfimage\n");
}
+29
View File
@@ -0,0 +1,29 @@
//----------------------------------------------------------------------
// This software is part of the OpenBeOS distribution and is covered
// by the OpenBeOS license.
//
// Copyright (c) 2003 Tyler Dauwalder, [email protected]
//----------------------------------------------------------------------
/*! \file Shell.h
*/
#ifndef _SHELL_H
#define _SHELL_H
#include <string>
#include "SupportDefs.h"
class Shell {
public:
Shell();
void Run(int argc, char *argv[]);
private:
status_t _ProcessArguments(int argc, char *argv[]);
status_t _ProcessArgument(std::string arg, int argc, char *argv[]);
void _PrintHelp();
};
#endif // _SHELL_H
@@ -0,0 +1,20 @@
//----------------------------------------------------------------------
// This software is part of the OpenBeOS distribution and is covered
// by the OpenBeOS license.
//
// Copyright (c) 2003 Tyler Dauwalder, [email protected]
//----------------------------------------------------------------------
/*! \file makeudfimage.cpp
UDF image builder.
*/
#include "Shell.h"
int main(int argc, char *argv[])
{
Shell shell;
shell.Run(argc, argv);
return 0;
}