From 6b2fc9c63be9d1454cf9df8c00771fdd238ba465 Mon Sep 17 00:00:00 2001 From: Jan Breuer <jan.breuer@jaybee.cz> Date: 周三, 20 3月 2013 23:00:18 +0800 Subject: [PATCH] ANSI C89 modifications --- libscpi/inc/scpi/debug.h | 4 libscpi/inc/scpi/error.h | 2 libscpi/inc/scpi/types.h | 58 ++++---- libscpi/src/ieee488.c | 12 +- libscpi/src/minimal.c | 8 libscpi/inc/scpi/ieee488.h | 32 ++-- libscpi/src/parser.c | 27 ++-- libscpi/inc/scpi/config.h | 71 +++++++++++ libscpi/src/error.c | 79 +++++++----- libscpi/src/utils.h | 5 libscpi/src/utils.c | 32 ++++ 11 files changed, 219 insertions(+), 111 deletions(-) diff --git a/libscpi/inc/scpi/config.h b/libscpi/inc/scpi/config.h new file mode 100644 index 0000000..de27110 --- /dev/null +++ b/libscpi/inc/scpi/config.h @@ -0,0 +1,71 @@ +/*- + * Copyright (c) 2012-2013 Jan Breuer, + * + * All Rights Reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file config.h + * @date Wed Mar 20 12:21:26 UTC 2013 + * + * @brief SCPI Configuration + * + * + */ + +#ifndef __SCPI_CONFIG_H_ +#define __SCPI_CONFIG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ======== test strnlen ======== */ +#ifndef HAVE_STRNLEN +#define HAVE_STRNLEN 1 +#endif +/* ======== test strncasecmp ======== */ +#ifndef HAVE_STRNCASECMP +#define HAVE_STRNCASECMP 1 +#endif + +/* define local macros depending on existance of strnlen */ +#if HAVE_STRNLEN +#define SCPI_strnlen(s, l) strnlen((s), (l)) +#else +#define SCPI_strnlen(s, l) BSD_strnlen((s), (l)) +#endif + +/* define local macros depending on existance of strncasecmp */ +#if HAVE_STRNCASECMP +#define SCPI_strncasecmp(s1, s2, l) strncasecmp((s1), (s2), (l)) +#else +#define SCPI_strncasecmp(s1, s2, l) strcasecmp((s1), (s2)) +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libscpi/inc/scpi/debug.h b/libscpi/inc/scpi/debug.h index 063d94e..e882902 100644 --- a/libscpi/inc/scpi/debug.h +++ b/libscpi/inc/scpi/debug.h @@ -44,8 +44,8 @@ #endif - //#define SCPI_DEBUG_COMMAND(a) scpi_debug_command(a) -#define SCPI_DEBUG_COMMAND(a) + /* #define SCPI_DEBUG_COMMAND(a) scpi_debug_command(a) */ + #define SCPI_DEBUG_COMMAND(a) bool_t SCPI_DebugCommand(scpi_t * context); diff --git a/libscpi/inc/scpi/error.h b/libscpi/inc/scpi/error.h index b2b7c9d..cb5b398 100644 --- a/libscpi/inc/scpi/error.h +++ b/libscpi/inc/scpi/error.h @@ -58,7 +58,7 @@ #define SCPI_ERROR_INVALID_SUFFIX -131 #define SCPI_ERROR_SUFFIX_NOT_ALLOWED -138 -#define SCPI_ERROR_EXECUTION_ERROR -200 +#define SCPI_ERROR_EXECUTION_ERROR -200 #ifdef __cplusplus } diff --git a/libscpi/inc/scpi/ieee488.h b/libscpi/inc/scpi/ieee488.h index b7eee81..b3693a1 100644 --- a/libscpi/inc/scpi/ieee488.h +++ b/libscpi/inc/scpi/ieee488.h @@ -54,24 +54,24 @@ scpi_result_t SCPI_CoreWai(scpi_t * context); -#define STB_R01 0x01 // Not used -#define STB_PRO 0x02 // Protection Event Flag -#define STB_QMA 0x04 // Error/Event queue message available -#define STB_QES 0x08 // Questionable status -#define STB_MAV 0x10 // Message Available -#define STB_ESR 0x20 // Standard Event Status Register -#define STB_SRQ 0x40 // Service Request -#define STB_OPS 0x80 // Operation Status Flag +#define STB_R01 0x01 /* Not used */ +#define STB_PRO 0x02 /* Protection Event Flag */ +#define STB_QMA 0x04 /* Error/Event queue message available */ +#define STB_QES 0x08 /* Questionable status */ +#define STB_MAV 0x10 /* Message Available */ +#define STB_ESR 0x20 /* Standard Event Status Register */ +#define STB_SRQ 0x40 /* Service Request */ +#define STB_OPS 0x80 /* Operation Status Flag */ -#define ESR_OPC 0x01 // Operation complete -#define ESR_REQ 0x02 // Request Control -#define ESR_QER 0x04 // Query Error -#define ESR_DER 0x08 // Device Dependent Error -#define ESR_EER 0x10 // Execution Error (e.g. range error) -#define ESR_CER 0x20 // Command error (e.g. syntax error) -#define ESR_URQ 0x40 // User Request -#define ESR_PON 0x80 // Power On +#define ESR_OPC 0x01 /* Operation complete */ +#define ESR_REQ 0x02 /* Request Control */ +#define ESR_QER 0x04 /* Query Error */ +#define ESR_DER 0x08 /* Device Dependent Error */ +#define ESR_EER 0x10 /* Execution Error (e.g. range error) */ +#define ESR_CER 0x20 /* Command error (e.g. syntax error) */ +#define ESR_URQ 0x40 /* User Request */ +#define ESR_PON 0x80 /* Power On */ scpi_reg_val_t SCPI_RegGet(scpi_t * context, scpi_reg_name_t name); diff --git a/libscpi/inc/scpi/types.h b/libscpi/inc/scpi/types.h index 2b24cb5..295009c 100644 --- a/libscpi/inc/scpi/types.h +++ b/libscpi/inc/scpi/types.h @@ -50,41 +50,41 @@ /* basic data types */ typedef bool bool_t; - //typedef enum { FALSE = 0, TRUE } bool_t; + /* typedef enum { FALSE = 0, TRUE } bool_t; */ /* IEEE 488.2 registers */ enum _scpi_reg_name_t { - SCPI_REG_STB = 0, // Status Byte - SCPI_REG_SRE, // Service Request Enable Register - SCPI_REG_ESR, // Standard Event Status Register (ESR, SESR) - SCPI_REG_ESE, // Event Status Enable Register - SCPI_REG_OPER, // OPERation Status Register - SCPI_REG_OPERE, // OPERation Status Enable Register - SCPI_REG_QUES, // QUEStionable status register - SCPI_REG_QUESE, // QUEStionable status Enable Register + SCPI_REG_STB = 0, /* Status Byte */ + SCPI_REG_SRE, /* Service Request Enable Register */ + SCPI_REG_ESR, /* Standard Event Status Register (ESR, SESR) */ + SCPI_REG_ESE, /* Event Status Enable Register */ + SCPI_REG_OPER, /* OPERation Status Register */ + SCPI_REG_OPERE, /* OPERation Status Enable Register */ + SCPI_REG_QUES, /* QUEStionable status register */ + SCPI_REG_QUESE, /* QUEStionable status Enable Register */ /* last definition - number of registers */ - SCPI_REG_COUNT, + SCPI_REG_COUNT }; typedef enum _scpi_reg_name_t scpi_reg_name_t; enum _scpi_ctrl_name_t { - SCPI_CTRL_SRQ = 1, // service request - SCPI_CTRL_GTL, // Go to local - SCPI_CTRL_SDC, // Selected device clear - SCPI_CTRL_PPC, // Parallel poll configure - SCPI_CTRL_GET, // Group execute trigger - SCPI_CTRL_TCT, // Take control - SCPI_CTRL_LLO, // Device clear - SCPI_CTRL_DCL, // Local lockout - SCPI_CTRL_PPU, // Parallel poll unconfigure - SCPI_CTRL_SPE, // Serial poll enable - SCPI_CTRL_SPD, // Serial poll disable - SCPI_CTRL_MLA, // My local address - SCPI_CTRL_UNL, // Unlisten - SCPI_CTRL_MTA, // My talk address - SCPI_CTRL_UNT, // Untalk - SCPI_CTRL_MSA, // My secondary address + SCPI_CTRL_SRQ = 1, /* service request */ + SCPI_CTRL_GTL, /* Go to local */ + SCPI_CTRL_SDC, /* Selected device clear */ + SCPI_CTRL_PPC, /* Parallel poll configure */ + SCPI_CTRL_GET, /* Group execute trigger */ + SCPI_CTRL_TCT, /* Take control */ + SCPI_CTRL_LLO, /* Device clear */ + SCPI_CTRL_DCL, /* Local lockout */ + SCPI_CTRL_PPU, /* Parallel poll unconfigure */ + SCPI_CTRL_SPE, /* Serial poll enable */ + SCPI_CTRL_SPD, /* Serial poll disable */ + SCPI_CTRL_MLA, /* My local address */ + SCPI_CTRL_UNL, /* Unlisten */ + SCPI_CTRL_MTA, /* My talk address */ + SCPI_CTRL_UNT, /* Untalk */ + SCPI_CTRL_MSA /* My secondary address */ }; typedef enum _scpi_ctrl_name_t scpi_ctrl_name_t; @@ -93,7 +93,7 @@ /* scpi commands */ enum _scpi_result_t { SCPI_RES_OK = 1, - SCPI_RES_ERR = -1, + SCPI_RES_ERR = -1 }; typedef enum _scpi_result_t scpi_result_t; @@ -135,7 +135,7 @@ SCPI_UNIT_OHM, SCPI_UNIT_HERTZ, SCPI_UNIT_CELSIUS, - SCPI_UNIT_SECONDS, + SCPI_UNIT_SECONDS }; typedef enum _scpi_unit_t scpi_unit_t; @@ -156,7 +156,7 @@ SCPI_NUM_DOWN, SCPI_NUM_NAN, SCPI_NUM_INF, - SCPI_NUM_NINF, + SCPI_NUM_NINF }; typedef enum _scpi_special_number_t scpi_special_number_t; diff --git a/libscpi/src/error.c b/libscpi/src/error.c index b293d8a..9577d6b 100644 --- a/libscpi/src/error.c +++ b/libscpi/src/error.c @@ -41,16 +41,18 @@ #include "scpi/error.h" #include "scpi/fifo.h" -// basic FIFO +/* basic FIFO */ static fifo_t local_error_queue; void SCPI_ErrorInit(scpi_t * context) { - //// FreeRTOS - // context->error_queue = (scpi_error_queue_t)xQueueCreate(100, sizeof(int16_t)); - - // basic FIFO + /* + * // FreeRTOS + * context->error_queue = (scpi_error_queue_t)xQueueCreate(100, sizeof(int16_t)); + */ + + /* basic FIFO */ context->error_queue = (scpi_error_queue_t)&local_error_queue; fifo_init((fifo_t *)context->error_queue); } @@ -60,10 +62,12 @@ * @param context - scpi context */ void SCPI_ErrorClear(scpi_t * context) { - //// FreeRTOS - //xQueueReset((xQueueHandle)context->error_queue); - - // basic FIFO + /* + * // FreeRTOS + * xQueueReset((xQueueHandle)context->error_queue); + */ + + /* basic FIFO */ fifo_clear((fifo_t *)context->error_queue); } @@ -74,13 +78,15 @@ */ int16_t SCPI_ErrorPop(scpi_t * context) { int16_t result = 0; - - //// FreeRTOS - //if (pdFALSE == xQueueReceive((xQueueHandle)context->error_queue, &result, 0)) { - // result = 0; - //} - - // basic FIFO + + /* + * // FreeRTOS + * if (pdFALSE == xQueueReceive((xQueueHandle)context->error_queue, &result, 0)) { + * result = 0; + * } + */ + + /* basic FIFO */ fifo_remove((fifo_t *)context->error_queue, &result); return result; @@ -93,22 +99,25 @@ */ int32_t SCPI_ErrorCount(scpi_t * context) { int16_t result = 0; - - //// FreeRTOS - //result = uxQueueMessagesWaiting((xQueueHandle)context->error_queue); - - //basic FIFO + + /* + * // FreeRTOS + * result = uxQueueMessagesWaiting((xQueueHandle)context->error_queue); + */ + + /* basic FIFO */ fifo_count((fifo_t *)context->error_queue, &result); - - + return result; } static void SCPI_ErrorAddInternal(scpi_t * context, int16_t err) { - //// FreeRTOS - //xQueueSend((xQueueHandle)context->error_queue, &err, 0); - - // basic FIFO + /* + * // FreeRTOS + * xQueueSend((xQueueHandle)context->error_queue, &err, 0); + */ + + /* basic FIFO */ fifo_add((fifo_t *)context->error_queue, err); } @@ -121,14 +130,14 @@ #define ERROR_DEFS_N 8 static const struct error_reg errs[ERROR_DEFS_N] = { - {-100, -199, ESR_CER}, // Command error (e.g. syntax error) ch 21.8.9 - {-200, -299, ESR_EER}, // Execution Error (e.g. range error) ch 21.8.10 - {-300, -399, ESR_DER}, // Device specific error -300, -399 ch 21.8.11 - {-400, -499, ESR_QER}, // Query error -400, -499 ch 21.8.12 - {-500, -599, ESR_PON}, // Power on event -500, -599 ch 21.8.13 - {-600, -699, ESR_URQ}, // User Request Event -600, -699 ch 21.8.14 - {-700, -799, ESR_REQ}, // Request Control Event -700, -799 ch 21.8.15 - {-800, -899, ESR_OPC}, // Operation Complete Event -800, -899 ch 21.8.16 + {-100, -199, ESR_CER}, /* Command error (e.g. syntax error) ch 21.8.9 */ + {-200, -299, ESR_EER}, /* Execution Error (e.g. range error) ch 21.8.10 */ + {-300, -399, ESR_DER}, /* Device specific error -300, -399 ch 21.8.11 */ + {-400, -499, ESR_QER}, /* Query error -400, -499 ch 21.8.12 */ + {-500, -599, ESR_PON}, /* Power on event -500, -599 ch 21.8.13 */ + {-600, -699, ESR_URQ}, /* User Request Event -600, -699 ch 21.8.14 */ + {-700, -799, ESR_REQ}, /* Request Control Event -700, -799 ch 21.8.15 */ + {-800, -899, ESR_OPC}, /* Operation Complete Event -800, -899 ch 21.8.16 */ }; /** diff --git a/libscpi/src/ieee488.c b/libscpi/src/ieee488.c index 855c9f1..e3f4629 100644 --- a/libscpi/src/ieee488.c +++ b/libscpi/src/ieee488.c @@ -145,11 +145,11 @@ case SCPI_REG_COUNT: - // nothing to do + /* nothing to do */ break; } - // set updated register value + /* set updated register value */ context->registers[name] = val; if (srq) { @@ -180,7 +180,7 @@ * @param context */ void SCPI_EventClear(scpi_t * context) { - // TODO + /* TODO */ SCPI_RegSet(context, SCPI_REG_ESR, 0); } @@ -260,7 +260,7 @@ * @return */ scpi_result_t SCPI_CoreOpcQ(scpi_t * context) { - // Operation is always completed + /* Operation is always completed */ SCPI_ResultInt(context, 1); return SCPI_RES_OK; } @@ -319,7 +319,7 @@ int result = 0; if (context && context->interface && context->interface->test) { result = context->interface->test(context); - } + } SCPI_ResultInt(context, result); return SCPI_RES_OK; } @@ -331,7 +331,7 @@ */ scpi_result_t SCPI_CoreWai(scpi_t * context) { (void) context; - // NOP + /* NOP */ return SCPI_RES_OK; } diff --git a/libscpi/src/minimal.c b/libscpi/src/minimal.c index c133fe6..ec4680d 100644 --- a/libscpi/src/minimal.c +++ b/libscpi/src/minimal.c @@ -102,10 +102,10 @@ * @return */ scpi_result_t SCPI_StatusQuestionableEventQ(scpi_t * context) { - // return value + /* return value */ SCPI_ResultInt(context, SCPI_RegGet(context, SCPI_REG_QUES)); - // clear register + /* clear register */ SCPI_RegSet(context, SCPI_REG_QUES, 0); return SCPI_RES_OK; @@ -117,7 +117,7 @@ * @return */ scpi_result_t SCPI_StatusQuestionableEnableQ(scpi_t * context) { - // return value + /* return value */ SCPI_ResultInt(context, SCPI_RegGet(context, SCPI_REG_QUESE)); return SCPI_RES_OK; @@ -142,7 +142,7 @@ * @return */ scpi_result_t SCPI_StatusPreset(scpi_t * context) { - // clear STATUS:... + /* clear STATUS:... */ SCPI_RegSet(context, SCPI_REG_QUES, 0); return SCPI_RES_OK; } diff --git a/libscpi/src/parser.c b/libscpi/src/parser.c index c22ae6c..2ff12c2 100644 --- a/libscpi/src/parser.c +++ b/libscpi/src/parser.c @@ -37,6 +37,7 @@ #include <ctype.h> #include <string.h> +#include "scpi/config.h" #include "scpi/parser.h" #include "utils.h" #include "scpi/error.h" @@ -183,11 +184,11 @@ int result = FALSE; const char * pattern_ptr = pattern; - int pattern_len = strlen(pattern); + int pattern_len = SCPI_strnlen(pattern, len); const char * pattern_end = pattern + pattern_len; const char * cmd_ptr = cmd; - size_t cmd_len = strnlen(cmd, len); + size_t cmd_len = SCPI_strnlen(cmd, len); const char * cmd_end = cmd + cmd_len; while (1) { @@ -199,24 +200,24 @@ cmd_ptr = cmd_ptr + cmd_sep_pos; result = TRUE; - // command is complete + /* command is complete */ if ((pattern_ptr == pattern_end) && (cmd_ptr >= cmd_end)) { break; } - // pattern complete, but command not + /* pattern complete, but command not */ if ((pattern_ptr == pattern_end) && (cmd_ptr < cmd_end)) { result = FALSE; break; } - // command complete, but pattern not + /* command complete, but pattern not */ if (cmd_ptr >= cmd_end) { result = FALSE; break; } - // both command and patter contains command separator at this position + /* both command and patter contains command separator at this position */ if ((pattern_ptr[0] == cmd_ptr[0]) && ((pattern_ptr[0] == ':') || (pattern_ptr[0] == '?'))) { pattern_ptr = pattern_ptr + 1; cmd_ptr = cmd_ptr + 1; @@ -240,7 +241,7 @@ * @param len - lenght of data to be written * @return number of bytes written */ -static inline size_t writeData(scpi_t * context, const char * data, size_t len) { +static size_t writeData(scpi_t * context, const char * data, size_t len) { return context->interface->write(context, data, len); } @@ -249,7 +250,7 @@ * @param context * @return */ -static inline int flushData(scpi_t * context) { +static int flushData(scpi_t * context) { if (context && context->interface && context->interface->flush) { return context->interface->flush(context); } else { @@ -262,7 +263,7 @@ * @param context * @return number of bytes written */ -static inline size_t writeDelimiter(scpi_t * context) { +static size_t writeDelimiter(scpi_t * context) { if (context->output_count > 0) { return writeData(context, ", ", 2); } else { @@ -275,7 +276,7 @@ * @param context * @return pocet zapsanych znaku */ -static inline size_t writeNewLine(scpi_t * context) { +static size_t writeNewLine(scpi_t * context) { if (context->output_count > 0) { size_t len; len = writeData(context, "\r\n", 2); @@ -291,14 +292,14 @@ * @param context */ static void processCommand(scpi_t * context) { + const scpi_command_t * cmd = context->paramlist.cmd; + context->cmd_error = FALSE; context->output_count = 0; context->input_count = 0; - const scpi_command_t * cmd = context->paramlist.cmd; - SCPI_DEBUG_COMMAND(context); - /* if callback exists - call command callback*/ + /* if callback exists - call command callback */ if (cmd->callback != NULL) { if ((cmd->callback(context) != SCPI_RES_OK) && !context->cmd_error) { SCPI_ErrorPush(context, SCPI_ERROR_EXECUTION_ERROR); diff --git a/libscpi/src/utils.c b/libscpi/src/utils.c index 3df0069..8880636 100644 --- a/libscpi/src/utils.c +++ b/libscpi/src/utils.c @@ -147,7 +147,7 @@ return FALSE; } - if (strncasecmp(str1, str2, len2) == 0) { + if (SCPI_strncasecmp(str1, str2, len2) == 0) { return TRUE; } @@ -160,7 +160,7 @@ STATE_TEXT, STATE_LAST_WHITESPACE, STATE_COMMA, - STATE_ERROR, + STATE_ERROR }; typedef enum _locate_text_states locate_text_states; @@ -175,7 +175,7 @@ /** * Test locate text state, if it is correct final state */ -static inline bool_t isFinalState(locate_text_states state) { +static bool_t isFinalState(locate_text_states state) { return ( ((state) == STATE_COMMA) || ((state) == STATE_LAST_WHITESPACE) @@ -189,7 +189,7 @@ * @param nfa stores automaton state * @param c current char processed */ -static inline bool_t locateTextAutomaton(locate_text_nfa * nfa, unsigned char c) { +static bool_t locateTextAutomaton(locate_text_nfa * nfa, unsigned char c) { switch(nfa->state) { /* first state locating only white spaces */ case STATE_FIRST_WHITESPACE: @@ -284,7 +284,7 @@ * @param nfa stores automaton state * @param c current char processed */ -static inline bool_t locateStrAutomaton(locate_text_nfa * nfa, unsigned char c) { +static bool_t locateStrAutomaton(locate_text_nfa * nfa, unsigned char c) { switch(nfa->state) { /* first state locating only white spaces */ case STATE_FIRST_WHITESPACE: @@ -403,3 +403,25 @@ return compareStr(pattern, pattern_len, str, str_len) || compareStr(pattern, pattern_sep_pos_short, str, str_len); } + + +#if !HAVE_STRNLEN +/* use FreeBSD strnlen */ + +/*- + * Copyright (c) 2009 David Schultz <das@FreeBSD.org> + * All rights reserved. + */ +size_t +BSD_strnlen(const char *s, size_t maxlen) +{ + size_t len; + + for (len = 0; len < maxlen; len++, s++) { + if (!*s) + break; + } + return (len); +} +#endif + diff --git a/libscpi/src/utils.h b/libscpi/src/utils.h index 37e4a7e..b1e24a0 100644 --- a/libscpi/src/utils.h +++ b/libscpi/src/utils.h @@ -38,6 +38,7 @@ #define SCPI_UTILS_H #include <stdint.h> +#include "scpi/config.h" #include "scpi/types.h" #ifdef __cplusplus @@ -57,6 +58,10 @@ size_t skipWhitespace(const char * cmd, size_t len) LOCAL; bool_t matchPattern(const char * pattern, size_t pattern_len, const char * str, size_t str_len) LOCAL; +#if !HAVE_STRNLEN + size_t BSD_strnlen(const char *s, size_t maxlen); +#endif + #define min(a, b) (((a) < (b)) ? (a) : (b)) #define max(a, b) (((a) > (b)) ? (a) : (b)) -- Gitblit v1.9.1