| 1 Overview | 
	
		| 1.1 CTrace Manual Version | 
	
		| 
		Version: 1.2
		 
		Author: Cal McPherson
		 
		Comments: Initial revision of the document.
		 | 
	
		| 1.2 What is CTrace? | 
	
		| 
		CTrace is a fast, lightweight trace/debug C library.
		It was specifically written for use in a multi-threaded
		application, though it will work just fine 
		in a single threaded C application.
		A trace/debug library has an interface of macros or functions 
		which outputs the contents of program variables as the application
		is running.  The trace calls may be made at certain user-defined levels.
		It may also be required to have
		trace functions only called on a particular thread or logical unit
		of the application.
		 
		Isn't that what debuggers are for?  Well, yes,
		though debuggers can be kind of tricky to use when an application
		is running across multiple threads.  Also, once an application is
		deployed, for example on an embedded system, using debuggers becomes
		impractical.  In this case, a remote protocol could turn tracing on
		for parts of the application, and the results may be returned either
		as a stream, or output to a file on the remote system, and collected
		via ftp.
		 | 
	
		| 1.3 CTrace Features | 
	
		| 
		 
		Fast, ligthweight tracingSupport for turning tracing on and off as requiredSupport for turning trace levels on and off independantlySupport for adding and removing trace threadsAbility to turn individual thread traces on and off in isolationAbility to trace logical software units in isolation 
		CTrace is distributed under the GNU General Public License and is free
		for use 
		 | 
	
		| 2 Reference | 
	
		| 2.1 Trace Library Initialisation and Cleanup | 
	
		| 
		Before the trace library is used, it must first be initialised
		by calling either the TRC_INIT_DEFAULT or the TRC_INIT macro.  
		Initialisation should normally take place upon startup of the 
		application, for example after entry of the program's main() function.
		 
		 
		Note there is a difference between enabling and disabling tracing
		and turning tracing on and off.
		 
		The trace library is made up of
		macros which call functions in the trace library.  In a deployed 
		system we do not want these functions being called if 
		we are not currently tracing anything.
		Disabling the trace libraries prevents the underlying
		calls to the trace library.  It is recommended to initialise the
		trace library with the TRC_DISABLED flag for normal(non-traced)
		running of your application.
		 
		Because the trace library allows multiple threads and for threads
		to be traced in isolation, it is neccessary to have an additional
		flag for turning tracing on and off at the thread level.  For this 
		reason, if you are using the trace library in a single-threaded
		application, you need to both enable tracing with the TRC_ENABLED
		flag, and turn tracing on with the TRC_ON flag for tracing to occur.
		 
		Finally, immediately prior to exiting your program you should call
		TRC_END() to cleanup data structures and close threads associated
		with the trace library.
		 
		 | 
	
		| 2.1.1 TRC_INIT_DEFAULT() | 
	
		| 
		Arguments:  void
		 
		Return Value:
		 
		 
		Description:
		 
		Initialise the trace library for use with default settings.
		 
		Example:
		 
		TRC_INIT_DEFAULT();
		 
		Initialise trace library with the following values:
		 
			_STDOUT - send output to standard output streamTRC_DISABLED - disable tracingTRC_ON - turn tracing on for all threadsTRC_ERR - turn on error tracing only for all trace levels100 - reserve space for 100 logical software units TRC_SERV_OFF - run tracing inside the thread being traced 
 
		 | 
	
		| 2.1.2 TRC_INIT(a,b,c,d,e) | 
	
		| Arguments: 
		 
			
				| Name | Type | Description |  
				| a | const char * | Default output stream for tracing: 
				 
					
						| NULL | standard output |  
						| "stdout" | standard output |  
						| "stderr" | standard error |  
					| "filename" | output to "filename" |  |  
				| b | t_enable_t | Trace enabled flag |  
				| c | t_on_t | Trace on/off flag |  
				| d | t_level_t | Trace levels to default to |  
				| e | unsigned int | Number of logical software units to allocate space for |  
				| f | t_server_t | Run trace as separate server thread |  
		Return Value:
		 
		 
		Description:
		 
		Initialise the trace library for use.
		 
		Example:
		 
		TRC_INIT(NULL, TRC_ENABLED, TRC_ON, TRC_ALL, 100, TRC_SERV_OFF);
		 
		Initialise trace library with the following values:
		 
			NULL - send output to standard output streamTRC_ENABLED - enable tracingTRC_ON - turn tracing on for all threadsTRC_ALL - turn tracing on for all trace levels100 - allocate space for 100 logical software unitsTRC_SERV_OFF - run tracing inside the thread being traced 
 | 
	
		| 2.1.1 TRC_END() | 
	
		| 
		Arguments:  void
		 
		Return Value:  void
		 
		Description:
		 
		Cleanup trace library data structures and threads.
		 
		Example:
		 
		TRC_END();
		 | 
	
		| 2.2 Trace Calls | 
	
		| 
		The trace calls are the meat and potatoes of the CTrace library.
		They send the tracing information to the output stream.
		 
		TRC_ENTER() displays the procedure or function name and the 
		values of the arguments passed into it as parameters.  It 
		should be called immediately upon entering a procedure or function.
		 
		TRC_RETURN() displays the function return value and then
		performs function return.  TRC_VOID_RETURN() displays and performs
		procedure return.
		 
		TRC_TRACE() is used to display any general trace information, in 
		the format of keyword/value pairs.
		 
		Finally, TRC_ERROR displays error information, once again in the
		format of keyword/value pairs.  TRC_ERROR calls will occur when
		the TRC_ERR tlevel_t flag is set.
		 | 
	
		| 2.2.1 TRC_ENTER(a,b,c) | 
	
		| Arguments: 
		 
			
				| Name | Type | Description |  
				| a | unsigned int | software unit identifier |  
				| b | t_level_t | trace level |  
				| c | char * | Formatted vararglist of fn argument values |  
		Return Value: void
		 
		Description:
		 
		Write trace enter function/procedure line to output stream.
		Argument <c> takes the form ("%d, %s", 1, "string") as 
		per the vararglist format of fprintf and printf C functions.
		 
		Example:
		 
		void myfunction(int myfn_arg1, char *myfn_arg2){TRC_ENTER(UNIT_FOO, TRC0, (%d, %s", myfn_arg1, myfn_arg2));
 ...
 
		Show that "myfunction" has been entered with argument values "myfn_arg1", "myfn_arg2".
		 
 | 
	
		| 2.2.2 TRC_RETURN(a,b,c,d) | 
	
		| Arguments: 
		 
			
				| Name | Type | Description |  
				| a | unsigned int | software unit identifier |  
				| b | t_level_t | trace level |  
				| c | char * | Formatted vararglist showing return value |  
				| d | void | Return value |  
		Return Value: void
		 
		Description:
		 
		Write trace return from function line to output stream.
		Argument <c> takes the form ("%d, %s", 1) as 
		per the vararglist format of fprintf and printf C functions.
		Note this function performs function return.  The function
		return value is passed as argument <d> to the macro.
		 
		Example:
		 
		    ...TRC_RETURN(UNIT_FOO, TRC0, (%d", retval), retval);
 }
 
		Show that function return has taken place returning value "retval".  Also
		performs function return.
		 
 | 
	
		| 2.2.3 TRC_VOID_RETURN(a,b) | 
	
		| Arguments: 
		 
			
				| Name | Type | Description |  
				| a | unsigned int | software unit identifier |  
				| b | t_level_t | trace level |  
		Return Value: void
		 
		Description:
		 
		Write trace return from procedure line to output stream.
		Note this macro performs procedure return.  
		 
		Example:
		 
		    ...TRC_VOID_RETURN(UNIT_FOO, TRC0);
 }
 
		Show that procedure return has taken place.  Also
		performs procedure return.
		 
 | 
	
		| 2.2.4 TRC_PRINT(a,b,c,d) | 
	
		| Arguments: 
		 
			
				| Name | Type | Description |  
				| a | unsigned int | software unit identifier |  
				| b | t_level_t | trace level |  
				| c | char * | Formatted vararglist of fn argument values |  
		Return Value: void
		 
		Description:
		 
		Write trace print line to output stream.
		Argument <c> takes the form ("%d, %s", 1, "string") as 
		per the vararglist format of fprintf and printf C functions.
		 
		Example:
		 
		TRC_PRINT(UNIT_FOO, TRC0, ("i=%d", 0));	
		 
 | 
	
		| 2.2.5 TRC_ERROR(a,b) | 
	
		| Arguments: 
		 
			
				| Name | Type | Description |  
				| a | unsigned int | software unit identifier |  
				| b | char * | Formatted vararglist of fn argument values |  
		Return Value: void
		 
		Description:
		 
		Write trace print line to output stream.
		Argument <b> takes the form ("%d, %s", 1, "string") as 
		per the vararglist format of fprintf and printf C functions.
		Trace level flag TRC_ERR needs to be set for TRC_ERROR output
		lines to be send to the output stream. 
		 
		Example:
		 
		TRC_ERROR(UNIT_FOO, ("s=%s", "your rooted"));
		 
 | 
	
		| 2.3 Turn Tracing On/Off | 
	
		| 
		TRC_ENABLE() and TRC_DISABLE() are used to disable and enable
		tracing.  Upon entry to every trace macro a flag is checked to
		determine if tracing is enabled.  If tracing is enabled, the
		underlying trace function and procedure calls are made.  Tracing
		may or may not occur dependant upon other trace flags, but 
		this is expensive and undesirable if tracing is not being used.
		Keep tracing disabled by default.
		 
		The trace library allows turning tracing on and off at the
		thread level.  Each thread can be turned on and off in isolation.
		In addition, the macros TRC_TURN_ON() and TRC_TURN_OF() provide
		blanket calls to turn tracing on and off for all trace threads.
		Somehow, a trace thread needs to have tracing turned on in order
		for trace output calls to send trace information to the output
		stream.  
		 | 
	
		| 2.3.1 TRC_ENABLE() | 
	
		| 
		Arguments:  void
		 
		Return Value:  void
		 
		Description:
		 
		Enable tracing calls.  Causes trace output macro calls(
		TRC_ENTER, TRC_RETURN, TRC_VOID_RETURN, TRC_PRINT, TRC_ERROR)
		to call their underlying library functions. 
		Tracing must also be turned on for the traced
		thread with TRC_TURN_ON(all threads) or TRC_TURN_THREAD_ON macro for
		tracing to occur.
		 
		Example:
		 
		TRC_ENABLE();
		 
 | 
	
		| 2.3.2 TRC_DISABLE() | 
	
		| 
		Arguments:  void
		 
		Return Value:  void
		 
		Description:
		 
		Disable tracing calls.  Stops trace output macro calls(
		TRC_ENTER, TRC_RETURN, TRC_VOID_RETURN, TRC_PRINT, TRC_ERROR)
		calling their underlying library functions. If a real-time
		system(or any system) is not being traced, we do not want
		redundant function calls taking up processor time.  For this
		reason, you should set TRC_DISABLED flag as default in the TRC_INIT()
		macro for normal(non-traced) program execution.
		 
		Example:
		 
		TRC_DISABLE();
		 
 | 
	
		| 2.3.3 TRC_TURN_ON() | 
	
		| 
		Arguments:  void
		 
		Return Value: void
		 
		Description:
		 
		Turn tracing on for all trace threads.  If tracing is not turned
		on for a thread(this includes the main() program thread)
		tracing will not occur.
		 
		Example:
		 
		TRC_TURN_ON();
		 
 
		 | 
	
		| 2.3.4 TRC_TURN_OFF() | 
	
		| 
		Arguments:  void
		 
		Return Value: void
		 
		Description:
		 
		Turn tracing off for all trace threads.
		 
		Example:
		 
		TRC_TURN_OFF();
		 | 
	
		| 2.4 The Trace Output Stream | 
	
		| 
		Use the TRC_FILE() macro to set the trace output stream for 
		the trace calls.  Trace information can be directed to stdout(default),
		stderr, or to a file.
		 | 
	
		| 2.4.1 TRC_FILE(a) | 
	
		| Arguments: 
		 
			
				| Name | Type | Description |  
				| a | const char * | trace output stream: 
				 
					
						| NULL | standard output |  
						| "stdout" | standard output |  
						| "stderr" | standard error |  
					| "filename" | output to "filename" |  |  
		Return Value:
		 
		 
		Description:
		 
		New output stream for trace library becomes <a>
		 
		Example:
		 
		TRC_FILE("myfile.trc");
		 
		Send all trace output to the file "myfile.trc".
		 | 
	
		| 2.5 Working With Trace Threads | 
	
		| 
		CTrace provides independant tracing for multiple program
		threads.  Before tracing can occur on any thread(including
		the main() program thread in a single threaded application)
		the thread needs to be added to the trace library using the
		TRC_ADD_THREAD() macro.  It can later be removed using the
		TRC_REMOVE_THREAD() macro.
		 
		Once a thread has been added to the trace library, it can 
		have tracing turned on and off for it using the 
		TRC_TURN_THREAD_ON() and TRC_TURN_THREAD_OFF() macros.
		 | 
	
		| 2.5.1 TRC_ADD_THREAD(a,b) | 
	
		| Arguments: 
		 
			
				| Name | Type | Description |  
				| a | const char * | Trace output thread name |  
				| b | tid_t | Thread id |  
		Return Value:
		 
		 
		Description:
		 
		Add thread with display name <a> and id <b> to trace library.
		If <b> equals 0 thread id defaults to the calling thread of this macro.
		The CTrace library keeps a data structure in memory for each tracable thread.
		For this reason, even the main() program
		thread must be added with TRC_ADD_THREAD(argv[0], 0).
		 
		Example:
		 
		TRC_ADD_THREAD("thread1", 0);
		 
		Add the calling thread of the macro to the trace library.
		Refer to it as "thread1" in the output stream.
		 
 | 
	
		| 2.5.2 TRC_REMOVE_THREAD(a) | 
	
		| Arguments: 
		 
			
				| Name | Type | Description |  
				| a | tid_t | Thread id |  
		Return Value:
		 
		 
		Description:
		 
		Remove thread with id <a> from trace library.
		If <a> equals 0 thread id defaults to the calling thread of this macro.
		 
		Example:
		 
		TRC_REMOVE_THREAD(0);
		 
		Remove the calling thread of the macro from the trace library.  
		 
 | 
	
		| 2.5.3 TRC_TURN_THREAD_ON(a) | 
	
		| Arguments: 
		 
			
				| Name | Type | Description |  
				| a | tid_t | Thread id |  
		Return Value:
		 
		 
		Description:
		 
		Turn tracing on for thread with id <a>.
		If <a> equals 0 thread id defaults to the calling thread of this macro.
		 
		Example:
		 
		TRC_TURN_THREAD_ON(0);
		 
		Turn tracing on for the calling thread of the macro.  
		 
 | 
	
		| 2.5.4 TRC_TURN_THREAD_OFF(a) | 
	
		| Arguments: 
		 
			
				| Name | Type | Description |  
				| a | tid_t | Thread id |  
		Return Value:
		 
		 
		Description:
		 
		Turn tracing off for thread with id <a>.
		If <a> equals 0 thread id defaults to the calling thread of this macro.
		 
		Example:
		 
		TRC_TURN_THREAD_OFF(0);
		 
		Turn tracing off for the calling thread of the macro.  
		 
 | 
	
		| 2.6 Working With Trace Levels | 
	
		| 
		Every trace output call(TRC_ENTER, TRC_RETURN, TRC_VOID_RETURN,
		TRC_TRACE) except TRC_ERROR is passed a tlevel_t argument.
		This argument tells the trace library which level(s) the 
		trace output call should operate on.  TRC_ERROR operates
		on tlevel_t TRC_ERR by default.
		 
		Therefore, when the program starts up, every trace output
		call embedded in it has a predefined hard-coded trace 
		level(s).  TRC_SET_LEVEL(), TRC_ADD_LEVEL() and TRC_REMOVE_LEVEL()
		macros effectively activate or deactivate these tracing levels.
		The "SET" macros perform a blanket overwrite of all currently
		activated levels with the new level(s) passed in as the parameter.
		The "ADD" and "REMOVE" macros enable finer granularity by retaining
		any existing levels that dont confict with the level(s) passed in
		as the parameter.
		 | 
	
		| 2.6.1 TRC_SET_LEVEL(a) | 
	
		| Arguments: 
		 
			
				| Name | Type | Description |  
				| a | tlevel_t | trace level(s) |  
		Return Value:
		 
		 
		Description:
		 
		Set level <a> in all added trace threads.
		<a> may be any legal tlevel_t including an Ored 
		combination of any legal tlevel_t, eg TRC1|TRC2.
		Any previous level settings will be made obsolete.
		 
		Example:
		 
		TRC_SET_LEVEL(TRC1|TRC2);
		 
		Set tracing at levels TRC1 and TRC2.  
		 
 | 
	
		| 2.6.2  TRC_ADD_LEVEL(a) | 
	
		| Arguments: 
		 
			
				| Name | Type | Description |  
				| a | tlevel_t | trace level(s) |  
		Return Value:
		 
		 
		Description:
		 
		Add level <a> to all added trace threads.
		<a> may be any legal tlevel_t including an Ored 
		combination of any legal tlevel_t, eg TRC1|TRC2.
		Any previous level settings not conflicting with
		<a> will be retained.
		 
		Example:
		 
		TRC_ADD_LEVEL(TRC4);
		 
		Add level TRC4 to existing tracing levels.  
		 
 | 
	
		| 2.6.3 TRC_REMOVE_LEVEL(a) | 
	
		| Arguments: 
		 
			
				| Name | Type | Description |  
				| a | tlevel_t | trace level(s) |  
		Return Value:
		 
		 
		Description:
		 
		Remove level <a> from all added trace threads.
		<a> may be any legal tlevel_t including an Ored 
		combination of any legal tlevel_t, eg TRC1|TRC2.
		Any previous level settings not conflicting with
		<a> will be retained.
		 
		Example:
		 
		TRC_REMOVE_LEVEL(TRC4);
		 
		Remove level TRC4 from existing tracing levels.  
		 
 | 
	
		| 2.6.4 TRC_SET_THREAD_LEVEL(a,b) | 
	
		| Arguments: 
		 
			
				| Name | Type | Description |  
				| a | tlevel_t | trace level(s) |  
				| b | tid_t | thread id |  
		Return Value:
		 
		 
		Description:
		 
		Set level <a> in thread <b>.
		<a> may be any legal tlevel_t including an Ored 
		combination of any legal tlevel_t, eg TRC1|TRC2.
		Any previous level settings will be made obsolete.
		If <b> equals 0 thread id defaults to the 
		calling thread of this macro.
		 
		Example:
		 
		TRC_SET_THREAD_LEVEL(TRC_ALL, 0);
		 
		Set tracing at all levels for the calling thread of this macro.  
		 
 | 
	
		| 2.6.5 TRC_ADD_THREAD_LEVEL(a,b) | 
	
		| Arguments: 
		 
			
				| Name | Type | Description |  
				| a | tlevel_t | trace level(s) |  
				| b | tid_t | thread id |  
		Return Value:
		 
		 
		Description:
		 
		Add level <a> to thread <b>.
		<a> may be any legal tlevel_t including an Ored 
		combination of any legal tlevel_t, eg TRC1|TRC2.
		Any previous level settings not conflicting with
		<a> will be retained.
		If <b> equals 0 thread id defaults to the 
		calling thread of this macro.
		 
		Example:
		 
		TRC_ADD_THREAD_LEVEL(TRC4, 23);
		 
		Add level TRC4 to existing tracing levels in thread with id 23.  
		 
 | 
	
		| 2.6.6 TRC_REMOVE_THREAD_LEVEL(a,b) | 
	
		| Arguments: 
		 
			
				| Name | Type | Description |  
				| a | tlevel_t | trace level(s) |  
				| b | tid_t | thread id |  
		Return Value:
		 
		 
		Description:
		 
		Remove level <a> from thread <b>.
		<a> may be any legal tlevel_t including an Ored 
		combination of any legal tlevel_t, eg TRC1|TRC2.
		Any previous level settings not conflicting with
		<a> will be retained.
		If <b> equals 0 thread id defaults to the 
		calling thread of this macro.
		 
		Example:
		 
		TRC_REMOVE_THREAD_LEVEL(TRC4, 23);
		 
		Remove level TRC4 from existing tracing levels in thread with id 23.  
		 
 | 
	
		| 2.7 Performing a Software Unit Trace | 
	
		| 
		Every trace output call
		is passed an unsigned int argument.
		This argument represents a user-defined logical software unit of
		the program.  
		Therefore, when the program starts up, every trace output
		call belongs to a software unit(unless this field is set to 0). 
		 
		Because the value 0 is reserved to indicate software unit tracing
                is not required, legal identifier values must start from 1. CTrace needs
		to be told how many software units are required during initialisation so it
		can allocate the appropriate memory.  The number
		of software units required is passed to TRC_INIT(), or defaults to 100
		if using TRC_INIT_DEFAULT(). 
		TRC_TURN_UNIT_ON(), TRC_TURN_UNIT_OFF() 
		macros effectively activate or deactivate tracing calls for the software
                unit passed in as the parameter. 
		TRC_SET_UNIT_LEVEL(), TRC_ADD_UNIT_LEVE(), TRC_REMOVE_UNIT_LEVEL()
		macros provide a finer level of granularity over unit tracing. | 
	
		| 2.7.1 TRC_TURN_UNIT_ON(a) | 
	
		| Arguments: 
		 
			
				| Name | Type | Description |  
				| a | unsigned int | software unit identifier |  
		Return Value:
		 
		 
		Description:
		 
		Turn tracing on for <a>.
		A logical software unit will share the same
		tunit_t variable.  When a tunit_t flag is set, 
		tracing of this local software unit may be performed
		in isolation.
		 
		Example:
		 
		TRC_TURN_UNIT_ON(UNIT_FOO);
		 
		Turn tracing on for the logical software unit sharing
		the identifier UNIT_FOO).
		 
 | 
	
		| 2.7.2 TRC_TURN_UNIT_OFF(a) | 
	
		| Arguments: 
		 
			
				| Name | Type | Description |  
				| a | unsigned int | software unit identifier |  
		Return Value:
		 
		 
		Description:
		 
		Turn tracing off for <a>.
		A logical software unit will share the same
		tunit_t variable.  When a tunit_t flag is set, 
		tracing of this software unit may be performed
		in isolation.
		 
		Example:
		 
		TRC_TURN_UNIT_OFF(UNIT_FOO);
		 
		Turn tracing off for the logical software unit sharing
		the identifier UNIT_FOO.
		 
 | 
	
		| 2.7.3 TRC_SET_UNIT_LEVEL(a,b) | 
	
		| Arguments: 
		 
			
				| Name | Type | Description |  
				| a | unsigned int | software unit identifier |  
				| b | tlevel_t | trace level(s) |  
		Return Value:
		 
		 
		Description:
		 
		Set level <b> in <a>.
		<b> may be any legal tlevel_t including an Ored 
		combination of any legal tlevel_t, eg TRC1|TRC2.
		Any previous level settings will be made obsolete.
		 
		Example:
		 
		TRC_SET_UNIT_LEVEL(UNIT_FOO, TRC_ERROR);
		 
		Set tracing to show TRC_ERROR calls only 
		for the logical software unit sharing
		the identifier UNIT_FOO.
		 
 | 
	
		| 2.7.4 TRC_ADD_UNIT_LEVEL(a,b) | 
	
		| Arguments: 
		 
			
				| Name | Type | Description |  
				| a | unsigned int | software unit identifier |  
				| b | tlevel_t | trace level(s) |  
		Return Value:
		 
		 
		Description:
		 
		Add level <b> to <a>.
		<b> may be any legal tlevel_t including an Ored 
		combination of any legal tlevel_t, eg TRC1|TRC2.
		Any previous level settings not conflicting with <b&bt
		will be retained.
		 
		Example:
		 
		TRC_ADD_UNIT_LEVEL(UNIT_FOO, TRC4);
		 
		Add tracing level TRC4 to the existing levels
		for the logical software unit sharing
		the identifier UNIT_FOO.
		 
 | 
	
		| 2.7.5 TRC_REMOVE_UNIT_LEVEL(a,b) | 
	
		| Arguments: 
		 
			
				| Name | Type | Description |  
				| a | unsigned int | software unit identifier |  
				| b | tlevel_t | trace level(s) |  
		Return Value:
		 
		 
		Description:
		 
		Remove level <b> from <a>.
		<b> may be any legal tlevel_t including an Ored 
		combination of any legal tlevel_t, eg TRC1|TRC2.
		Any previous level settings not conflicting with <b&bt
		will be retained.
		 
		Example:
		 
		TRC_REMOVE_UNIT_LEVEL(UNIT_FOO, TRC4);
		 
		Remove tracing level TRC4 from the existing levels
		for the logical software unit sharing
		the identifier UNIT_FOO.
		 
 |