// dyOut - DYnamic string stack based OUTput // // CAUTION: Inclusion of this header will convert printfs to dyOutPrintfs!!! // This is an Experimental/Test strategy only. When dyOut is adopted, // direct calls to dyOut functions should be used and printf macros removed. // // This module relies upon a dyString based stack of buffers which accumulate output // for later printing. As a stack, only the top buffer can be filled and flushed out // (duOutFlush). When flushing, the top buffer's content is appended to the next // lower buffer, unless explicitly requested otherwise (dyOutDirectly). // If the stack is empty, dyOutPrintf will be equivalent to printf. // // Output goes to STDOUT unless a single alternative out file is registered. #ifdef DSPRINT_H // NEVER INCLUDE TWICE. ONLY INCLUDE DIRECTLY IN C FILES. #error Including dyOut.h twice! Only include directly in C files as this redefines printf !!! #else//ifndef DSPRINT_H #define DSPRINT_H #include "common.h" #include "dystring.h" int dyOutOpen(int initialBufSize); // Allocate dynamic string and puts at top of stack // returns token to be used for later stack accounting asserts int dyOutPrintf(char *format, ...); // Prints into end of the top ds buffer, and return resulting string length // If there is no current buffer, this acts like a simple printf and returns -1 #define dyOutPuts(str) dyOutPrintf("%s\n",str) #define dyOutPutc(chr) dyOutPrintf("%c",chr) #define SWAP_PRINTF #ifdef SWAP_PRINTF #define printf dyOutPrintf #define puts dyOutPuts #undef putc #define putc dyOutPutc #endif//def SWAP_PRINTF int dyOutPrintDirectly(int token,FILE *file); // Prints the contents of the top buffer directly to a file. // Will leave the filled buffer at top of stack // Returns the length printed. int dyOutFlush(int token); // Flushes the top buffer to the next lower one and empties top buffer. // If there is no lower buffer then the content is printed to STDOUT (or registered out). // Returns the length flushed. int dyOutClose(int token); // Abandons the top buffer and its content, freeing memory. // Returns the length abandoned. #define dyOutAbandon(token) dyOutClose(token) int dyOutFlushAndClose(int token); // Flushes the top buffer to the next lower one and frees the top buffer. // If there is no lower buffer then the content is printed to STDOUT (or registered out). // Returns the length flushed. int dyOutFlushAndCloseAll(); // CAUTION: Bad practice to not Open/Close levels in turn! // flushes, frees and closes all stacked buffers // returns length flushed char * dyOutContent(int token); // returns the content of the current buffer as a string, but does not flush or free it // NOTE: returned pointer is not cloned memory and will be changed by successive dyOut calls int dyOutEmpty(int token); // Empties the top buffer in stack (abandoning content), but leave buffer in place // Returns the length abandoned. #define dyOutAbandonContent(token) dyOutEmpty(token) int dyOutSize(int token); // Returns the current length of the buffer starting at the level corresponding to token. // Unlike other cases, the token does not have to correspond to the top of the stack! #define dyOutIsEmpty(token) (dyOutSize(token) == 0) int dyOutSizeAll(); // returns combined current size of all buffers #define dyOutIsAllEmpty(token) (dyOutSizeAll() == 0) int dyOutStackDepth(); // Returns the current dyOut buffer stack depth #define dyOutIsOpen() (dyOutStackDepth() > 0) void dyOutRegisterAltStream(FILE *out); // Registers an alternative to STDOUT. After registering, all dyOut out goes to this file. // NOTE: There is no stack. Register/Unregister serially. void dyOutUnregisterAltStream(FILE *out); // Unregisters the alternative to STDOUT. After unregistering all dyOut out goes to STDOUT. // NOTE: There is no stack. Register/Unregister serially. char *dyOutCannibalizeAndClose(int token); // Closes the top stack buffer returning content. Returned string should be freed. char *dyOutCannibalizeAndCloseAll(); // CAUTION: Bad practice to not Open/Close levels in turn! // Closes all stack buffers and returns a single string that is the full content. // Returned string should be freed. void *dyOutStackPop(int token); // CAUTION: Not for the faint of heart: print buffer surgery is no substitute for proper coding. // Returns a pointer which can be dyOutStackPush'd back into place. // Pop/Push is useful for inserting print immediately before a dyOutOpen'd print buffer void dyOutStackPush(int token,void *dyOutPointer); // CAUTION: Not for the faint of heart: print buffer surgery is no substitute for proper coding. // Push a previously dyOutStackPop'd print buffer back onto the stack // Pop/Push is useful for inserting print immediately before a dyOutOpen'd print buffer #ifdef NOT_NOW // Requires regex function added to dystring.c which has been successfully tested. boolean dyOutRegexReplace(int token, char *regExpression, char *replaceWith); // CAUTION: Not for the faint of heart: print buffer surgery is no substitute for proper coding. // Looks for and replaces a single instance of a wildcard match in the current dyOut print buffer // regex follows normal EXTENDED (egrep) rules except: // ^ - at beginning of the regExpression only and matches beginning of buffer (not of line) // $ - at end of regExpression only and matches end of buffer (not end of line) // \n - newlines in the body of the regExpression will match newlines in the current print buffer // Returns TRUE on success // CAUTION: Wildcards match largest sub-string [w.*d] matches all of "wild wild world" //void dyOutTest(); // Tests of dyOut functions #endif///def NOT_NOW /* Next steps: * 1) DONE WITH MACROS: in cheapCgi.c replace all printfs with dyOutPrintf * 2) DONE WITH MACROS: in hui.c replace all printfs with dyOutPrintf * 3) DONE WITH MACROS: in hgTrackUi replace all printfs with dyOutPrintf * 4) DONE: After 1-3, add opens and closes to hgTrackUi * 5) DONE: Handle boxing cfg with dyOutPrintf (successful test) * 6) Handle isConfigurable tests with dyOutPrintf and throw away results * This one will require making hgTrackUi Cfgs all lib code. */ #endif /* DSPRINT_H */