# HG changeset patch # User Matti Hamalainen # Date 1317645822 -10800 # Node ID 7c28f38cb6dd7d872490ecf2aff26ce4e302b6fc # Parent 727ce827482bf133e20c9a0a6bf8bdbd2b8c652e Update to use new th-libs from the subrepo. diff -r 727ce827482b -r 7c28f38cb6dd .hgsubstate --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgsubstate Mon Oct 03 15:43:42 2011 +0300 @@ -0,0 +1,1 @@ +598609fb49b06e34f96230f464fef400bafeb2d8 th-libs diff -r 727ce827482b -r 7c28f38cb6dd Makefile.gen --- a/Makefile.gen Mon Oct 03 15:43:01 2011 +0300 +++ b/Makefile.gen Mon Oct 03 15:43:42 2011 +0300 @@ -23,11 +23,14 @@ # all: $(NONBUILD) $(TARGETS) -$(OBJPATH)%.o: %.c %.h +$(OBJPATH)%.o: th-libs/%.c th-libs/%.h $(CC) $(CFLAGS) -c -o $@ $< +$(OBJPATH)%.o: %.c %.h + $(CC) $(CFLAGS) -c -o $@ $< -Ith-libs/ + $(NNCHAT_BIN): nnchat.c $(OBJPATH)libnnchat.o $(OBJPATH)th_util.o $(OBJPATH)th_string.o $(OBJPATH)th_args.o $(OBJPATH)th_config.o $(EXTRAOBJS) VERSION - $(CC) $(CFLAGS) -o $@ $(filter %.c %.o,$+) $(LDFLAGS) -DNN_VERSION=\"$(NN_VERSION)\" + $(CC) $(CFLAGS) -o $@ $(filter %.c %.o,$+) $(LDFLAGS) -DNN_VERSION=\"$(NN_VERSION)\" -Ith-libs/ # # Special targets diff -r 727ce827482b -r 7c28f38cb6dd nnchat.c --- a/nnchat.c Mon Oct 03 15:43:01 2011 +0300 +++ b/nnchat.c Mon Oct 03 15:43:42 2011 +0300 @@ -105,8 +105,10 @@ void argShowHelp(void) { - th_args_help(stdout, optList, optListN, th_prog_name, + th_print_banner(stdout, th_prog_name, "[options] "); + + th_args_help(stdout, optList, optListN); } diff -r 727ce827482b -r 7c28f38cb6dd th_args.c --- a/th_args.c Mon Oct 03 15:43:01 2011 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,431 +0,0 @@ -/* - * Simple commandline argument processing - * Programmed and designed by Matti 'ccr' Hamalainen - * (C) Copyright 2002-2008 Tecnic Software productions (TNSP) - * - * Please read file 'COPYING' for information on license and distribution. - */ -/* -Description -=========== -Structures and functions for simple commandline argument processing, -option argument handling (short and long forms supported). - -Output function for printing out short on-line help for said options -and program commandline usage. - - -Format for typical commandline: - -$ program -a -b -c --long-d -e argument-for-e --long-f="argument for f" - -where -a, -b and -c are short options without required arguments; ---long-d is a long option without argument; -e is short option with -argument and finally --long-f is long option with argument. - - -Introduction -============ -Handling of commandline options in th_args_process() has various -options, which effect how an option is handled. Also the error -situations (unknown option/no required argument) can be handled -in different ways. - -Typically th_args_process() is called as follows: - -BOOL optionHandlerCallback(int optionNumber, char *optionArgument, char *optionName) -{ - if (option is OK) - return TRUE; - else - return FALSE; -} - -BOOL nonoptionHandlerCallback(char *argumentString) -{ - // return value same as in optionHandlerCallback -} - - -int main(int argc, char *argv[]) -{ - if (th_args_process(argc, argv, optList, optListN, - optionHandlerCallback, nonoptionHandlerCallback)) { - ... arguments OK ... - } else { - ... arguments invalid or required arguments missing ... - } -} - - -NOTICE! -------- -The return value from handler callbacks affects the return value of -th_args_process(). Additionally, a failure in callback (returns FALSE) -effects the argument processing if bailOut argument of th_args_process() -is TRUE! - -If bailOut is TRUE, any error/failure in argument processing (including -callbacks) immediately stops the argument processing and FALSE is -returned from th_args_process(). - -If bailOut is FALSE, most errors are "ignored", but FALSE is still returned -if any errors occured. - - -NOTICE #2! ----------- -A small temporary buffer of N*sizeof(BOOL) (where N is number of -options in optList[]) is allocated for processing required options. -If this allocation fails, the program is immediately exited with -code 128. - - -Examples -======== -Example of different options, in a fictional optionlist struct: - -optarg_t optList[] = { - // Option without arguments - { 0, '?', "help", "Show this help", OPT_NONE }, - - // Option with a required argument - { 1, 'o', "output", "Output file name", OPT_ARGREQ }, - - // Option with optional argument - { 2, 'f', "foobar", "Use foobar, with optional string", OPT_ARGOPT }, - - // This option is required to be given, though without other flags - // it may not make much sense. - { 4, 'S', "stupid", "You must give this option", OPT_REQUIRED }, - - // The flags can be combined with OR operator: this option is both - // required to be specified, and also requires argument (the filename) - { 5, 'i', "input", "Input file name", OPT_REQUIRED | OPT_ARGREQ }, - - - // Option with only long form - { 0, 0, "only-long", "Long option", OPT_NONE }, - - // Option with only short form - { 0, 's', NULL, "Short option", OPT_NONE }, - -}; - -const int optListN = (sizeof(optList) / sizeof(optarg_t)); - - -*/ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include "th_util.h" -#include "th_args.h" -#include "th_string.h" - - -/* Check if option requires an argument - */ -static BOOL th_args_check_arg(optarg_t *o, char *optArg) -{ - if ((o->optFlags & OPT_ARGMASK) == OPT_ARGREQ && optArg == NULL) - { - if (o->optShort != 0 && o->optLong != NULL) - { - THERR("Option '-%c ARG' (--%s=ARG) requires an argument!\n", - o->optShort, o->optLong); - } - else if (o->optShort != 0) - { - THERR("Option '-%c ARG' requires an argument!\n", o->optShort); - } - else if (o->optLong != NULL) - { - THERR("Option --%s=ARG requires an argument!\n", o->optLong); - } - - return FALSE; - } - else - return TRUE; -} - - -/* Handle short options - */ -static BOOL th_args_process_short(char *currArg, int *newArgIndex, - BOOL *wasGiven, int argc, char *argv[], - optarg_t optList[], int optListN, - BOOL(*handleOpt) (int, char *, char *)) -{ - char *tmpArg = currArg, *optArg; - int optN; - BOOL isFound; - - /* Short options can be combined: -a -b -c == -abc */ - while (*tmpArg) - { - for (optN = 0, isFound = FALSE; (optN < optListN) && !isFound; optN++) - if (*tmpArg == optList[optN].optShort) - { - /* Get possible option argument, if needed */ - if ((optList[optN].optFlags & OPT_ARGMASK) != 0 - && (++(*newArgIndex) < argc)) - optArg = argv[*newArgIndex]; - else - optArg = NULL; - - /* Check if option argument is required */ - if (!th_args_check_arg(&optList[optN], optArg)) - return FALSE; - else - { - char tmpStr[2] = { 0, 0 }; - - /* Option was given succesfully, try to handle it */ - wasGiven[optN] = TRUE; - - tmpStr[0] = *tmpArg; - - if (!handleOpt(optList[optN].optID, optArg, tmpStr)) - return FALSE; - } - - isFound = TRUE; - } - - if (!isFound) - { - THERR("Unknown short option '%c' in argument '-%s'\n", - *tmpArg, currArg); - return FALSE; - } - - tmpArg++; - } - - return TRUE; -} - - -/* Handle long options - */ -static BOOL th_args_process_long(char *currArg, int *newArgIndex, - BOOL *wasGiven, int argc, char *argv[], - optarg_t optList[], int optListN, - BOOL(*handleOpt) (int, char *, char *)) -{ - int optN, optLen, i; - char *optArg; - - (void) argc; - (void) argv; - (void) newArgIndex; - - /* Long option */ - for (optN = -1, optLen = i = 0; (i < optListN) && (optN < 0); i++) - if (optList[i].optLong) - { - optLen = strlen(optList[i].optLong); - if (strncmp(currArg, optList[i].optLong, optLen) == 0) - optN = i; - } - - /* Get possible option argument, if needed */ - if (optN >= 0) - { - if ((optList[optN].optFlags & OPT_ARGMASK) != 0) - { - if (currArg[optLen] == '=') - optArg = &currArg[optLen + 1]; - else - optArg = NULL; - } - else - optArg = NULL; - - /* Check if option argument is required */ - if (!th_args_check_arg(&optList[optN], optArg)) - return FALSE; - else - { - /* Option was given succesfully, try to handle it */ - wasGiven[optN] = TRUE; - if (!handleOpt(optList[optN].optID, optArg, currArg)) - return FALSE; - } - } - else - { - THERR("Unknown long option '--%s'\n", currArg); - return FALSE; - } - - return TRUE; -} - - -/* Process arguments, handling short and long options by - * calling the given callback functions. - */ -BOOL th_args_process(int argc, char *argv[], - optarg_t optList[], int optListN, - BOOL(*handleOpt) (int, char *, char *), - BOOL(*handleNonOption) (char *), BOOL bailOut) -{ - BOOL endOptions, optionsOK; - int argIndex, newArgIndex, i; - char *currArg; - BOOL *wasGiven; - - /* Allocate wasGiven */ - wasGiven = (BOOL *) th_calloc(optListN, sizeof(BOOL)); - if (!wasGiven) - { - THERR - ("FATAL ERROR! Could not allocate wasGiven in th_args_process()!\n"); - exit(128); - } - - /* Parse arguments */ - argIndex = 1; - optionsOK = TRUE; - endOptions = FALSE; - while (argIndex < argc) - { - currArg = argv[argIndex]; - if ((currArg[0] == '-') && !endOptions) - { - newArgIndex = argIndex; - currArg++; - if (*currArg == '-') - { - /* Check for "--", which ends the options-list */ - currArg++; - if (*currArg == 0) - { - endOptions = TRUE; - continue; - } - - /* Long options */ - if (!th_args_process_long(currArg, &newArgIndex, - wasGiven, argc, argv, optList, - optListN, handleOpt)) - optionsOK = FALSE; - } - else - { - /* Short options */ - if (!th_args_process_short(currArg, &newArgIndex, - wasGiven, argc, argv, optList, - optListN, handleOpt)) - optionsOK = FALSE; - } - - argIndex = newArgIndex; - } - else - { - /* Was not option argument */ - if (handleNonOption == NULL - || (handleNonOption != NULL && !handleNonOption(currArg))) - { - THERR("Invalid argument '%s'\n", currArg); - optionsOK = FALSE; - } - } - - /* Check if we bail out on invalid argument */ - if (!optionsOK && bailOut) - { - th_free(wasGiven); - return FALSE; - } - - argIndex++; - } - - /* Check wasGiven by isRequired */ - for (i = 0; i < optListN; i++) - if ((optList[i].optFlags & OPT_REQUIRED) != 0 && !wasGiven[i]) - { - THERR("Option -%s (--%s) is required.\n", - optList[i].optShort, optList[i].optLong); - - optionsOK = FALSE; - if (bailOut) - break; - } - - th_free(wasGiven); - return optionsOK; -} - - -/* Print help for commandline arguments/options - */ -void th_args_help(FILE *outFile, - optarg_t optList[], int optListN, - char *progName, char *progUsage) -{ - int i, nrequired; - - fprintf(outFile, - "\n%s v%s (%s)\n" - "%s\n" - "%s\n" - "Usage: %s %s\n", - th_prog_name, th_prog_version, th_prog_fullname, - th_prog_author, th_prog_license, progName, progUsage); - - - for (i = nrequired = 0; i < optListN; i++) - { - optarg_t *o = &optList[i]; - - /* Print short option */ - if (o->optShort != 0) - fprintf(outFile, " -%c, ", o->optShort); - else - fprintf(outFile, " "); - - /* Print long option */ - if (o->optLong) - { - char tmpStr[64], *p; - - if ((o->optFlags & OPT_ARGMASK) == OPT_ARGOPT) - { - snprintf(tmpStr, sizeof(tmpStr), "%s[=ARG]", - optList[i].optLong); - p = tmpStr; - } - else if ((o->optFlags & OPT_ARGMASK) == OPT_ARGREQ) - { - snprintf(tmpStr, sizeof(tmpStr), "%s=ARG", - optList[i].optLong); - p = tmpStr; - } - else - p = o->optLong; - - fprintf(outFile, "--%-15s", p); - } - else - fprintf(outFile, " "); - - fprintf(outFile, " %s.", optList[i].optDesc); - - if (o->optFlags & OPT_REQUIRED) - { - fprintf(outFile, " [*]\n"); - nrequired++; - } - else - fprintf(outFile, "\n"); - } - - if (nrequired > 0) - fprintf(outFile, "(Options marked with [*] are required)\n"); -} diff -r 727ce827482b -r 7c28f38cb6dd th_args.h --- a/th_args.h Mon Oct 03 15:43:01 2011 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ -/* - * Simple commandline argument processing function - * Programmed and designed by Matti 'ccr' Hamalainen - * (C) Copyright 2002-2008 Tecnic Software productions (TNSP) - * - * Please read file 'COPYING' for information on license and distribution. - */ -#ifndef _TH_ARGS -#define _TH_ARGS - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include "th_util.h" - - -/* Option flags - */ -#define OPT_NONE (0) /* Simple option with no arguments */ -#define OPT_ARGREQ (1) /* Option's argument is required */ -#define OPT_ARGOPT (3) /* Option's argument is optional */ -#define OPT_ARGMASK (3) /* Mask for option argument flags */ -#define OPT_REQUIRED (4) /* This option is required to be given */ - - -typedef struct { - int optID; - char optShort; - char *optLong; - char *optDesc; - int optFlags; -} optarg_t; - - -BOOL th_args_process(int argc, char *argv[], - optarg_t argList[], int argListN, - BOOL (*handleOpt)(int, char *, char *), - BOOL (*handleFile)(char *), BOOL); - -void th_args_help(FILE *, optarg_t optList[], int optListN, char *, char *); - -#ifdef __cplusplus -} -#endif -#endif /* _TH_ARGS */ diff -r 727ce827482b -r 7c28f38cb6dd th_config.c --- a/th_config.c Mon Oct 03 15:43:01 2011 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,847 +0,0 @@ -/* - * Very simple configuration handling functions - * Programmed and designed by Matti 'ccr' Hamalainen - * (C) Copyright 2004-2010 Tecnic Software productions (TNSP) - * - * Please read file 'COPYING' for information on license and distribution. - */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include -#include -#include "th_config.h" -#include "th_util.h" -#include "th_string.h" - -#define SET_MAX_BUF (8192) - - -/* Free a given configuration (the values are not free'd) - */ -void th_cfg_free(cfgitem_t *cfg) -{ - cfgitem_t *curr = cfg; - - while (curr != NULL) - { - cfgitem_t *next = curr->next; - - if (curr->type == ITEM_SECTION) - th_cfg_free((cfgitem_t *) curr->v.data); - - th_free(curr->name); - th_free(curr); - curr = next; - } -} - - -/* Allocate and add new item to configuration - */ -static cfgitem_t *th_cfg_add(cfgitem_t **cfg, const char *name, - const int type, void *data) -{ - cfgitem_t *node; - - if (cfg == NULL) - return NULL; - - /* Allocate new item */ - node = (cfgitem_t *) th_calloc(1, sizeof(cfgitem_t)); - if (node == NULL) - return NULL; - - /* Set values */ - node->type = type; - node->v.data = data; - node->name = th_strdup(name); - - /* Insert into linked list */ - if (*cfg != NULL) - { - node->prev = (*cfg)->prev; - (*cfg)->prev->next = node; - (*cfg)->prev = node; - } - else - { - *cfg = node; - node->prev = node; - } - node->next = NULL; - - return node; -} - - -/* Add integer type setting into give configuration - */ -int th_cfg_add_int(cfgitem_t **cfg, char *name, int *itemData, int itemDef) -{ - cfgitem_t *node; - - node = th_cfg_add(cfg, name, ITEM_INT, (void *) itemData); - if (node == NULL) - return -1; - - *itemData = itemDef; - - return 0; -} - - -int th_cfg_add_hexvalue(cfgitem_t **cfg, char *name, - int *itemData, int itemDef) -{ - cfgitem_t *node; - - node = th_cfg_add(cfg, name, ITEM_HEX_TRIPLET, (void *) itemData); - if (node == NULL) - return -1; - - *itemData = itemDef; - - return 0; -} - - -/* Add unsigned integer type setting into give configuration - */ -int th_cfg_add_uint(cfgitem_t **cfg, char *name, - unsigned int *itemData, unsigned int itemDef) -{ - cfgitem_t *node; - - node = th_cfg_add(cfg, name, ITEM_UINT, (void *) itemData); - if (node == NULL) - return -1; - - *itemData = itemDef; - - return 0; -} - - -/* Add strint type setting into given configuration - */ -int th_cfg_add_string(cfgitem_t **cfg, char *name, - char **itemData, char *itemDef) -{ - cfgitem_t *node; - - node = th_cfg_add(cfg, name, ITEM_STRING, (void *) itemData); - if (node == NULL) - return -1; - - *itemData = th_strdup(itemDef); - - return 0; -} - - -/* Add boolean type setting into given configuration - */ -int th_cfg_add_bool(cfgitem_t **cfg, char *name, - BOOL *itemData, BOOL itemDef) -{ - cfgitem_t *node; - - node = th_cfg_add(cfg, name, ITEM_BOOL, (void *) itemData); - if (node == NULL) - return -1; - - *itemData = itemDef; - - return 0; -} - - -/* Add implicit comment - */ -int th_cfg_add_comment(cfgitem_t **cfg, char *comment) -{ - cfgitem_t *node; - - node = th_cfg_add(cfg, comment, ITEM_COMMENT, NULL); - if (node == NULL) - return -1; - - return 0; -} - - -/* Add new section - */ -int th_cfg_add_section(cfgitem_t **cfg, char *name, cfgitem_t *data) -{ - cfgitem_t *node; - - node = th_cfg_add(cfg, name, ITEM_SECTION, (void *) data); - if (node == NULL) - return -1; - - return 0; -} - - -int th_cfg_add_string_list(cfgitem_t **cfg, char *name, qlist_t **data) -{ - cfgitem_t *node; - - if (data == NULL) - return -5; - - node = th_cfg_add(cfg, name, ITEM_STRING_LIST, (void *) data); - if (node == NULL) - return -1; - - return 0; -} - - -/* Read a given file into configuration structure and variables - */ -enum -{ - PM_EOF, - PM_ERROR, - PM_NORMAL, - PM_COMMENT, - PM_NEXT, - PM_KEYNAME, - PM_KEYSET, - PM_STRING, - PM_INT, - PM_BOOL, - PM_SECTION, - PM_ARRAY -}; - -#define VADDCH(ch) if (strPos < SET_MAX_BUF) { tmpStr[strPos++] = ch; } -#define VISEND(ch) (ch == '\r' || ch == '\n' || ch == ';' || th_isspace(c) || ch == '#') - -typedef struct -{ - FILE *file; - char *filename; - size_t line; -} conffile_t; - - -static void th_cfg_error(conffile_t *f, const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - fprintf(stderr, "%s: '%s', line #%d: ", th_prog_name, f->filename, - (unsigned int) f->line); - vfprintf(stderr, fmt, ap); - va_end(ap); -} - - -static int th_cfg_read_sect(conffile_t *f, cfgitem_t *cfg, int nesting) -{ - cfgitem_t *item = NULL; - char tmpStr[SET_MAX_BUF + 1]; - size_t strPos; - int c, parseMode, prevMode, nextMode, tmpCh; - BOOL isFound, isStart, isError, validError; - - /* Initialize values */ - tmpCh = 0; - strPos = 0; - c = -1; - isFound = isStart = isError = validError = FALSE; - nextMode = prevMode = parseMode = PM_NORMAL; - - /* Parse the configuration */ - while (parseMode != PM_EOF && parseMode != PM_ERROR) - { - if (c == -1) - { - /* Get next character */ - switch (c = fgetc(f->file)) - { - case EOF: - if (parseMode != PM_NORMAL) - { - th_cfg_error(f, "Unexpected end of file.\n"); - parseMode = PM_ERROR; - } - else - parseMode = PM_EOF; - break; - - case '\n': - f->line++; - } - } - - switch (parseMode) - { - case PM_COMMENT: - /* Comment parsing mode */ - if (c == '\n') - { - /* End of line, end of comment */ - parseMode = prevMode; - prevMode = PM_COMMENT; - } - c = -1; - break; - - case PM_NORMAL: - /* Normal parsing mode */ - if (c == '#') - { - prevMode = parseMode; - parseMode = PM_COMMENT; - c = -1; - } - else if (VISEND(c)) - { - c = -1; - } - else if (c == '}') - { - if (nesting > 0) - { - /* Check for validation errors */ - return (validError) ? 1 : 0; - } - else - { - th_cfg_error(f, - "Invalid nesting sequence encountered.\n"); - parseMode = PM_ERROR; - } - } - else if (th_isalpha(c)) - { - /* Start of key name found */ - prevMode = parseMode; - parseMode = PM_KEYNAME; - strPos = 0; - } - else - { - /* Error! Invalid character found */ - th_cfg_error(f, "Unexpected character '%c'.\n", c); - parseMode = PM_ERROR; - } - break; - - case PM_KEYNAME: - /* Configuration KEY name parsing mode */ - if (c == '#') - { - /* Start of comment */ - prevMode = parseMode; - parseMode = PM_COMMENT; - c = -1; - } - else if (th_iscrlf(c) || th_isspace(c) || c == '=') - { - /* End of key name */ - prevMode = parseMode; - parseMode = PM_NEXT; - nextMode = PM_KEYSET; - } - else if (th_isalnum(c) || c == '_') - { - /* Add to key name string */ - VADDCH(c) - else - { - /* Error! Key name string too long! */ - th_cfg_error(f, "Config key name too long!"); - parseMode = PM_ERROR; - } - c = -1; - } - else - { - /* Error! Invalid character found */ - tmpStr[strPos] = 0; - th_cfg_error(f, - "Unexpected character '%c' in key name '%s'.\n", - c, tmpStr); - parseMode = PM_ERROR; - } - break; - - case PM_KEYSET: - if (c == '=') - { - /* Find key from configuration */ - tmpStr[strPos] = 0; - isFound = FALSE; - item = cfg; - while (item != NULL && !isFound) - { - if (item->name != NULL && strcmp(item->name, tmpStr) == 0) - isFound = TRUE; - else - item = item->next; - } - - /* Check if key was found */ - if (isFound) - { - /* Okay, set next mode */ - switch (item->type) - { - case ITEM_HEX_TRIPLET: - case ITEM_STRING: - nextMode = PM_STRING; - break; - - case ITEM_STRING_LIST: - nextMode = PM_ARRAY; - break; - - case ITEM_INT: - case ITEM_UINT: - nextMode = PM_INT; - break; - - case ITEM_BOOL: - nextMode = PM_BOOL; - break; - - case ITEM_SECTION: - nextMode = PM_SECTION; - break; - } - - prevMode = parseMode; - parseMode = PM_NEXT; - isStart = TRUE; - strPos = 0; - } - else - { - /* Error! No configuration key by this name found */ - th_cfg_error(f, - "No such configuration setting ('%s')\n", - tmpStr); - parseMode = PM_ERROR; - } - - c = -1; - } - else - { - /* Error! '=' expected! */ - th_cfg_error(f, - "Unexpected character '%c', assignation '=' was expected.\n", - c); - parseMode = PM_ERROR; - } - break; - - case PM_NEXT: - /* Search next item parsing mode */ - if (c == '#') - { - /* Start of comment */ - prevMode = parseMode; - parseMode = PM_COMMENT; - } - else if (th_isspace(c) || th_iscrlf(c)) - { - /* Ignore whitespaces and linechanges */ - c = -1; - } - else - { - /* Next item found */ - prevMode = parseMode; - parseMode = nextMode; - } - break; - - case PM_ARRAY: - if (isStart) - { - switch (item->type) - { - case ITEM_STRING_LIST: - prevMode = parseMode; - parseMode = PM_STRING; - break; - } - } - else if (c == ',') - { - switch (item->type) - { - case ITEM_STRING_LIST: - c = -1; - isStart = TRUE; - prevMode = parseMode; - parseMode = PM_NEXT; - nextMode = PM_STRING; - break; - } - } - else - { - prevMode = parseMode; - parseMode = PM_NORMAL; - } - break; - - case PM_SECTION: - /* Section parsing mode */ - if (c != '{') - { - /* Error! Section start '{' expected! */ - th_cfg_error(f, - "Unexpected character '%c', section start '{' was expected.\n", - c); - parseMode = PM_ERROR; - } - else - { - int res = th_cfg_read_sect(f, item->v.section, nesting + 1); - c = -1; - if (res > 0) - validError = TRUE; - else if (res < 0) - parseMode = PM_ERROR; - else - { - prevMode = parseMode; - parseMode = PM_NORMAL; - } - } - break; - - case PM_STRING: - /* String parsing mode */ - if (isStart) - { - /* Start of string, get delimiter */ - tmpCh = c; - isStart = FALSE; - strPos = 0; - } - else if (c == tmpCh) - { - /* End of string, set the value */ - tmpStr[strPos] = 0; - - switch (item->type) - { - case ITEM_HEX_TRIPLET: - *(item->v.val_int) = th_get_hex_triplet(tmpStr); - prevMode = parseMode; - parseMode = PM_NORMAL; - break; - case ITEM_STRING: - th_pstrcpy(item->v.val_str, tmpStr); - prevMode = parseMode; - parseMode = PM_NORMAL; - break; - case ITEM_STRING_LIST: - th_llist_append(item->v.list, th_strdup(tmpStr)); - prevMode = parseMode; - parseMode = PM_NEXT; - nextMode = PM_ARRAY; - break; - } - - } - else - { - /* Add character to string */ - VADDCH(c) - else - { - /* Error! String too long! */ - th_cfg_error(f, - "String too long! Maximum is %d characters.", - SET_MAX_BUF); - parseMode = PM_ERROR; - } - } - - c = -1; - break; - - case PM_INT: - /* Integer parsing mode */ - if (isStart && item->type == ITEM_UINT && c == '-') - { - /* Error! Negative values not allowed for unsigned ints */ - th_cfg_error(f, - "Negative value specified for %s, unsigned value expected.", - item->name); - parseMode = PM_ERROR; - } - else if (isStart && (c == '-' || c == '+')) - { - VADDCH(c) - else - isError = TRUE; - } - else if (th_isdigit(c)) - { - VADDCH(c) - else - isError = TRUE; - } - else if (VISEND(c)) - { - /* End of integer parsing mode */ - tmpStr[strPos] = 0; - switch (item->type) - { - case ITEM_INT: - *(item->v.val_int) = atoi(tmpStr); - break; - - case ITEM_UINT: - *(item->v.val_uint) = atol(tmpStr); - break; - } - - prevMode = parseMode; - parseMode = PM_NORMAL; - } - else - { - /* Error! Unexpected character. */ - th_cfg_error(f, - "Unexpected character '%c' for integer setting '%s'.", - c, item->name); - parseMode = PM_ERROR; - } - - if (isError) - { - /* Error! String too long! */ - th_cfg_error(f, "String too long! Maximum is %d characters.", - SET_MAX_BUF); - parseMode = PM_ERROR; - } - - isStart = FALSE; - c = -1; - break; - - case PM_BOOL: - /* Boolean parsing mode */ - if (isStart) - { - tmpCh = c; - isStart = FALSE; - } - else if (VISEND(c)) - { - BOOL tmpBool = FALSE; - - /* End of boolean parsing */ - switch (tmpCh) - { - case 'Y': - case 'y': - case 'T': - case 't': - case '1': - tmpBool = TRUE; - break; - - case 'N': - case 'n': - case 'F': - case 'f': - case '0': - tmpBool = FALSE; - break; - - default: - isError = TRUE; - } - - if (isError) - { - th_cfg_error(f, "Invalid boolean value for '%s'.\n", - item->name); - parseMode = PM_ERROR; - } - else - { - *(item->v.val_bool) = tmpBool; - - prevMode = parseMode; - parseMode = PM_NORMAL; - } - } - c = -1; - break; - } - } - - /* Check for validation errors */ - if (validError) - return 1; - - /* Return result */ - if (parseMode == PM_ERROR) - return -2; - else - return 0; -} - - -int th_cfg_read(FILE *inFile, char *filename, cfgitem_t *cfg) -{ - conffile_t f; - - f.file = inFile; - f.filename = filename; - f.line = 1; - - return th_cfg_read_sect(&f, cfg, 0); -} - - -/* Write a configuration into file - */ -static void th_print_indent(conffile_t *f, int nesting) -{ - int i; - for (i = 0; i < nesting * 2; i++) - fputc(' ', f->file); -} - - -static int th_cfg_write_sect(conffile_t *f, cfgitem_t *item, int nesting) -{ - while (item != NULL) - { - if (item->type == ITEM_COMMENT) - { - th_print_indent(f, nesting); - if (fprintf - (f->file, "# %s\n", - (item->name != NULL) ? item->name : "") < 0) - return -1; - } - else if (item->name != NULL) - { - th_print_indent(f, nesting); - - switch (item->type) - { - case ITEM_STRING: - if (*(item->v.val_str) == NULL) - { - if (fprintf(f->file, "#%s = \"\"\n", item->name) < 0) - return -3; - } - else - { - if (fprintf(f->file, "%s = \"%s\"\n", - item->name, *(item->v.val_str)) < 0) - return -3; - } - break; - - case ITEM_STRING_LIST: - if (*(item->v.list) == NULL) - { - if (fprintf(f->file, "#%s = \"\", \"\"\n", item->name) < - 0) - return -3; - } - else - { - qlist_t *node = *(item->v.list); - size_t n = th_llist_length(node); - if (fprintf(f->file, "%s = ", item->name) < 0) - return -3; - - while (node != NULL) - { - if (node->data != NULL) - fprintf(f->file, "\"%s\"", (char *) node->data); - - if (--n > 0) - { - fprintf(f->file, ",\n"); - th_print_indent(f, nesting); - } - node = node->next; - } - - if (fprintf(f->file, "\n") < 0) - return -3; - } - break; - - case ITEM_INT: - if (fprintf(f->file, "%s = %i\n", - item->name, *(item->v.val_int)) < 0) - return -4; - break; - - case ITEM_UINT: - if (fprintf(f->file, "%s = %d\n", - item->name, *(item->v.val_uint)) < 0) - return -5; - break; - - case ITEM_BOOL: - if (fprintf(f->file, "%s = %s\n", - item->name, - *(item->v.val_bool) ? "yes" : "no") < 0) - return -6; - break; - - case ITEM_SECTION: - { - int res; - if (fprintf(f->file, "%s = {\n", item->name) < 0) - return -7; - res = th_cfg_write_sect(f, item->v.section, nesting + 1); - if (res != 0) - return res; - if (fprintf(f->file, "}\n\n") < 0) - return -8; - } - break; - - case ITEM_HEX_TRIPLET: - if (fprintf(f->file, "%s = \"%06x\"\n", - item->name, *(item->v.val_int)) < 0) - return -6; - break; - } - } - item = item->next; - } - - return 0; -} - - -int th_cfg_write(FILE *outFile, char *filename, cfgitem_t *cfg) -{ - conffile_t f; - - if (cfg == NULL) - return -1; - - f.file = outFile; - f.filename = filename; - f.line = 1; - - fprintf(outFile, "# Configuration written by %s %s\n\n", - th_prog_fullname, th_prog_version); - - return th_cfg_write_sect(&f, cfg, 0); -} diff -r 727ce827482b -r 7c28f38cb6dd th_config.h --- a/th_config.h Mon Oct 03 15:43:01 2011 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -/* - * Very simple configuration file handling - * Programmed and designed by Matti 'ccr' Hamalainen - * (C) Copyright 2004-2008 Tecnic Software productions (TNSP) - * - * Please read file 'COPYING' for information on license and distribution. - */ -#ifndef _TH_CONFIG_H -#define _TH_CONFIG_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "th_util.h" -#include - - -/* Definitions - */ -enum ITEM_TYPE { - ITEM_SECTION = 1, - ITEM_COMMENT, - ITEM_STRING, - ITEM_INT, - ITEM_UINT, - ITEM_BOOL, - ITEM_FLOAT, - ITEM_HEX_TRIPLET, - - ITEM_STRING_LIST, - ITEM_HEX_TRIPLET_LIST -}; - - -typedef struct _cfgitem_t { - int type; - char *name; - union { - int *val_int; - unsigned int *val_uint; - char **val_str; - BOOL *val_bool; - - void *data; - qlist_t **list; - struct _cfgitem_t *section; - } v; - - struct _cfgitem_t *next, *prev; -} cfgitem_t; - - -/* Functions - */ -int th_cfg_read(FILE *, char *, cfgitem_t *); -void th_cfg_free(cfgitem_t *); -int th_cfg_write(FILE *, char *, cfgitem_t *); - -int th_cfg_add_section(cfgitem_t **cfg, char *name, cfgitem_t *data); -int th_cfg_add_comment(cfgitem_t **cfg, char *comment); -int th_cfg_add_int(cfgitem_t **cfg, char *name, int *data, int itemDef); -int th_cfg_add_uint(cfgitem_t **cfg, char *name, unsigned int *data, unsigned int itemDef); -int th_cfg_add_string(cfgitem_t **cfg, char *name, char **data, char *itemDef); -int th_cfg_add_bool(cfgitem_t **cfg, char *name, BOOL *data, BOOL itemDef); -int th_cfg_add_float(cfgitem_t **cfg, char *name, float *data, float itemDef); -int th_cfg_add_hexvalue(cfgitem_t **cfg, char *name, int *data, int itemDef); - -int th_cfg_add_string_list(cfgitem_t **cfg, char *name, qlist_t **list); - -#ifdef __cplusplus -} -#endif -#endif /* _TH_CONFIG_H */ diff -r 727ce827482b -r 7c28f38cb6dd th_string.c --- a/th_string.c Mon Oct 03 15:43:01 2011 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,577 +0,0 @@ -/* - * Miscellaneous string-handling related utility-functions - * Programmed and designed by Matti 'ccr' Hamalainen - * (C) Copyright 2002-2008 Tecnic Software productions (TNSP) - * - * Please read file 'COPYING' for information on license and distribution. - */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include "th_string.h" - -/* strdup with a NULL check - */ -char *th_strdup(const char *s) -{ - char *res; - if (s == NULL) - return NULL; - - if ((res = th_malloc(strlen(s) + 1)) == NULL) - return NULL; - - strcpy(res, s); - return res; -} - - -char *th_strncpy(char *dst, const char *src, const size_t n) -{ - const char *s = src; - char *d = dst; - size_t i; - assert(src != NULL); - assert(dst != NULL); - - /* Copy to the destination */ - i = n; - while (*s && i > 0) - { - *(d++) = *(s++); - i--; - } - - /* Fill rest of space with zeros */ - while (i > 0) - { - *(d++) = 0; - i--; - } - - /* Ensure that last is always zero */ - dst[n - 1] = 0; - - return dst; -} - - -/* Simulate a sprintf() that allocates memory - */ -char *th_strdup_vprintf(const char *fmt, va_list args) -{ - int size = 64; - char *buf, *nbuf = NULL; - - if ((buf = th_malloc(size)) == NULL) - return NULL; - - while (1) - { - int n; - va_list ap; - va_copy(ap, args); - n = vsnprintf(buf, size, fmt, ap); - va_end(ap); - - if (n > -1 && n < size) - return buf; - if (n > -1) - size = n + 1; - else - size *= 2; - - if ((nbuf = th_realloc(nbuf, size)) == NULL) - { - th_free(buf); - return NULL; - } - - buf = nbuf; - } -} - - -char *th_strdup_printf(const char *fmt, ...) -{ - char *res; - va_list ap; - - va_start(ap, fmt); - res = th_strdup_vprintf(fmt, ap); - va_end(ap); - - return res; -} - - -void th_pstr_vprintf(char **buf, const char *fmt, va_list ap) -{ - char *tmp = th_strdup_vprintf(fmt, ap); - th_free(*buf); - *buf = tmp; -} - - -void th_pstr_printf(char **buf, const char *fmt, ...) -{ - char *tmp; - va_list ap; - - va_start(ap, fmt); - tmp = th_strdup_vprintf(fmt, ap); - va_end(ap); - - th_free(*buf); - *buf = tmp; -} - -/* Compare two strings ignoring case [strcasecmp, strncasecmp] - */ -int th_strcasecmp(const char *str1, const char *str2) -{ - const char *s1 = str1, *s2 = str2; - assert(str1 != NULL); - assert(str2 != NULL); - - if (str1 == str2) - return 0; - - while (*s1 && *s2 && th_tolower(*s1) == th_tolower(*s2)) - { - s1++; - s2++; - } - - return (th_tolower(*s1) - th_tolower(*s2)); -} - - -int th_strncasecmp(const char *str1, const char *str2, size_t n) -{ - const char *s1 = str1, *s2 = str2; - assert(str1 != NULL); - assert(str2 != NULL); - - if (str1 == str2) - return 0; - - while (n > 0 && *s1 && *s2 && th_tolower(*s1) == th_tolower(*s2)) - { - s1++; - s2++; - n--; - } - - return n > 0 ? (th_tolower(*s1) - th_tolower(*s2)) : 0; -} - - -/* Remove all occurences of control characters, in-place. - * Resulting string is always shorter or same length than original. - */ -void th_strip_ctrlchars(char *str) -{ - char *i, *j; - assert(str != NULL); - - i = str; - j = str; - while (*i) - { - if (!th_iscntrl(*i)) - *(j++) = *i; - i++; - } - - *j = 0; -} - - -/* Copy a given string over in *result. - */ -int th_pstrcpy(char **result, const char *str) -{ - assert(result != NULL); - - if (str == NULL) - return -1; - - th_free(*result); - if ((*result = th_malloc(strlen(str) + 1)) == NULL) - return -2; - - strcpy(*result, str); - return 0; -} - - -/* Concatenates a given string into string pointed by *result. - */ -int th_pstrcat(char **result, const char *str) -{ - assert(result != NULL); - - if (str == NULL) - return -1; - - if (*result != NULL) - { - *result = th_realloc(*result, strlen(*result) + strlen(str) + 1); - if (*result == NULL) - return -1; - - strcat(*result, str); - } - else - { - *result = th_malloc(strlen(str) + 1); - if (*result == NULL) - return -1; - - strcpy(*result, str); - } - - return 0; -} - - -/* Find next non-whitespace character in string. - * Updates iPos into the position of such character and - * returns pointer to the string. - */ -const char *th_findnext(const char *str, size_t *pos) -{ - assert(str != NULL); - - /* Terminating NULL-character is not whitespace! */ - while (th_isspace(str[*pos])) - (*pos)++; - - return &str[*pos]; -} - - -/* Find next sep-character from string - */ -const char *th_findsep(const char *str, size_t *pos, char sep) -{ - assert(str != NULL); - - while (str[*pos] && str[*pos] != sep) - (*pos)++; - - return &str[*pos]; -} - - -/* Find next sep- or whitespace from string - */ -const char *th_findseporspace(const char *str, size_t *pos, char sep) -{ - assert(str != NULL); - - while (!th_isspace(str[*pos]) && str[*pos] != sep) - (*pos)++; - - return &str[*pos]; -} - - -/* Compare a string to a pattern. Case-SENSITIVE version. - * The matching pattern can consist of any normal characters plus - * wildcards ? and *. "?" matches any character and "*" matches - * any number of characters. - */ -BOOL th_strmatch(const char *str, const char *pattern) -{ - BOOL didMatch = TRUE, isAnyMode = FALSE, isEnd = FALSE; - const char *tmpPattern = NULL; - - /* Check given pattern and string */ - if (str == NULL || pattern == NULL) - return FALSE; - - /* Start comparision */ - do - { - didMatch = FALSE; - switch (*pattern) - { - case '?': - /* Any single character matches */ - if (*str) - { - didMatch = TRUE; - pattern++; - str++; - } - break; - - case '*': - didMatch = TRUE; - pattern++; - if (!*pattern) - isEnd = TRUE; - isAnyMode = TRUE; - tmpPattern = pattern; - break; - - case 0: - if (isAnyMode) - { - if (*str) - str++; - else - isEnd = TRUE; - } - else - { - if (*str) - { - if (tmpPattern) - { - isAnyMode = TRUE; - pattern = tmpPattern; - } - else - didMatch = FALSE; - } - else - isEnd = TRUE; - } - break; - default: - if (isAnyMode) - { - if (*pattern == *str) - { - isAnyMode = FALSE; - didMatch = TRUE; - } - else - { - if (*str) - { - didMatch = TRUE; - str++; - } - } - } - else - { - if (*pattern == *str) - { - didMatch = TRUE; - if (*pattern) - pattern++; - if (*str) - str++; - } - else - { - if (tmpPattern) - { - didMatch = TRUE; - isAnyMode = TRUE; - pattern = tmpPattern; - } - } - } - - if (!*str && !*pattern) - isEnd = TRUE; - break; - - } /* switch */ - - } - while (didMatch && !isEnd); - - return didMatch; -} - - -/* Compare a string to a pattern. Case-INSENSITIVE version. - */ -BOOL th_strcasematch(const char *str, const char *pattern) -{ - BOOL didMatch = TRUE, isAnyMode = FALSE, isEnd = FALSE; - const char *tmpPattern = NULL; - - /* Check given pattern and string */ - if (str == NULL || pattern == NULL) - return FALSE; - - /* Start comparision */ - do - { - switch (*pattern) - { - case '?': - /* Any single character matches */ - if (*str) - { - pattern++; - str++; - } - else - didMatch = FALSE; - break; - - case '*': - pattern++; - if (!*pattern || *pattern == '?') - isEnd = TRUE; - isAnyMode = TRUE; - tmpPattern = pattern; - break; - - case 0: - if (isAnyMode) - { - if (*str) - str++; - else - isEnd = TRUE; - } - else - { - if (*str) - { - if (tmpPattern) - { - isAnyMode = TRUE; - pattern = tmpPattern; - } - else - didMatch = FALSE; - } - else - isEnd = TRUE; - } - break; - - default: - if (isAnyMode) - { - if (th_tolower(*pattern) == th_tolower(*str)) - { - isAnyMode = FALSE; - } - else - { - if (*str) - str++; - else - didMatch = FALSE; - } - } - else - { - if (th_tolower(*pattern) == th_tolower(*str)) - { - if (*pattern) - pattern++; - if (*str) - str++; - } - else - { - if (tmpPattern) - { - isAnyMode = TRUE; - pattern = tmpPattern; - } - else - didMatch = FALSE; - } - } - - if (!*str && !*pattern) - isEnd = TRUE; - - break; - - } /* switch */ - - } - while (didMatch && !isEnd); - - return didMatch; -} - - -int th_get_hex_triplet(const char *str) -{ - const char *p = str; - int len, val = 0; - - for (len = 0; *p && len < 6; p++, len++) - { - if (*p >= '0' && *p <= '9') - { - val *= 16; - val += (*p - '0'); - } - else if (*p >= 'A' && *p <= 'F') - { - val *= 16; - val += (*p - 'A') + 10; - } - else if (*p >= 'a' && *p <= 'f') - { - val *= 16; - val += (*p - 'a') + 10; - } - else - return -1; - } - - return (len == 6) ? val : -1; -} - - -BOOL th_growbuf(char **buf, size_t *bufsize, size_t *len, size_t grow) -{ - if (*buf == NULL) - *bufsize = *len = 0; - - if (*buf == NULL || *len + grow >= *bufsize) - { - *bufsize += grow + TH_BUFGROW; - *buf = (char *) th_realloc(*buf, *bufsize); - if (*buf == NULL) - return FALSE; - } - return TRUE; -} - - -BOOL th_vputch(char **buf, size_t *bufsize, size_t *len, const char ch) -{ - if (!th_growbuf(buf, bufsize, len, 1)) - return FALSE; - - (*buf)[*len] = ch; - (*len)++; - - return TRUE; -} - - -BOOL th_vputs(char **buf, size_t *bufsize, size_t *len, const char *str) -{ - size_t slen; - if (str == NULL) - return FALSE; - - slen = strlen(str); - if (!th_growbuf(buf, bufsize, len, slen)) - return FALSE; - - strcpy(*buf + *len, str); - (*len) += slen; - - return TRUE; -} diff -r 727ce827482b -r 7c28f38cb6dd th_string.h --- a/th_string.h Mon Oct 03 15:43:01 2011 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +0,0 @@ -/* - * Miscellaneous string-handling related utility-functions - * Programmed and designed by Matti 'ccr' Hamalainen - * (C) Copyright 2002-2011 Tecnic Software productions (TNSP) - * - * Please read file 'COPYING' for information on license and distribution. - */ -#ifndef _TH_STRING_H -#define _TH_STRING_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "th_util.h" -#include -#include -#include - -/* Macros - */ -#define th_isalnum(c) isalnum((int)(unsigned char) c) -#define th_isalpha(c) isalpha((int)(unsigned char) c) -#define th_isascii(c) isascii((int)(unsigned char) c) -#define th_isblank(c) isblank((int)(unsigned char) c) -#define th_iscntrl(c) iscntrl((int)(unsigned char) c) -#define th_isdigit(c) isdigit((int)(unsigned char) c) -#define th_isgraph(c) isgraph((int)(unsigned char) c) -#define th_islower(c) islower((int)(unsigned char) c) -#define th_isprint(c) isprint((int)(unsigned char) c) -#define th_ispunct(c) ispunct((int)(unsigned char) c) -#define th_isspace(c) isspace((int)(unsigned char) c) -#define th_isupper(c) isupper((int)(unsigned char) c) -#define th_isxdigit(c) isxdigit((int)(unsigned char) c) -#define th_iscrlf(c) ((c=='\r')||(c=='\n')) - -#define th_isspecial(q) (((q >= 0x5b) && (q <= 0x60)) || ((q >= 0x7b) && (q <= 0x7d))) - -#define th_tolower(c) tolower((int)(unsigned char) c) -#define th_toupper(c) toupper((int)(unsigned char) c) - - -/* Normal NUL-terminated string functions - */ -char *th_strncpy(char *, const char *, size_t); -int th_strcasecmp(const char *, const char *); -int th_strncasecmp(const char *, const char *, size_t); -void th_strip_ctrlchars(char *); - -char *th_strdup_vprintf(const char *, va_list); -char *th_strdup_printf(const char *, ...); - -void th_pstr_vprintf(char **, const char *, va_list); -void th_pstr_printf(char **, const char *, ...); - -char *th_strdup(const char *); -int th_pstrcpy(char **, const char *); -int th_pstrcat(char **, const char *); - -const char *th_findnext(const char *, size_t *); -const char *th_findsep(const char *, size_t *, char); -const char *th_findseporspace(const char *, size_t *, char); - -BOOL th_strmatch(const char *, const char *); -BOOL th_strcasematch(const char *, const char *); - -int th_get_hex_triplet(const char *); - - -BOOL th_growbuf(char **buf, size_t *bufsize, size_t *len, size_t grow); -BOOL th_vputch(char **buf, size_t *bufsize, size_t *len, const char ch); -BOOL th_vputs(char **buf, size_t *bufsize, size_t *len, const char *str); - -#define TH_BUFGROW (32) - -#ifdef __cplusplus -} -#endif -#endif /* _TH_STRING_H */ diff -r 727ce827482b -r 7c28f38cb6dd th_types.h --- a/th_types.h Mon Oct 03 15:43:01 2011 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,104 +0,0 @@ -/* - * Type definations - * Programmed and designed by Matti 'ccr' Hamalainen - * (C) Copyright 2002-2008 Tecnic Software productions (TNSP) - * - * Please read file 'COPYING' for information on license and distribution. - */ -/* If your code uses "config.h", you need to #include - * it before including this header. - */ -#ifndef _TH_TYPES_H -#define _TH_TYPES_H - -#ifdef HAVE_STDINT_H -#include -#ifndef HAVE_INT_TYPES -#define HAVE_INT_TYPES 1 -#endif -#endif - -#ifdef HAVE_SYS_TYPES_H -#include -#ifndef HAVE_INT_TYPES -#define HAVE_INT_TYPES 1 -#endif -#endif - -/* Shorthand types */ -typedef unsigned long int ulint_t; -typedef signed long int lint_t; -#ifndef HAVE_UINT_T -typedef unsigned int uint_t; -#endif - -/* Default assumptions for these types should be ok for most 32bit platforms... - * feel free to define TH_TYPE_* if necessary to remedy - */ -#ifdef TH_TYPE_I8 -typedef unsigned TH_TYPE_I8 uint8_t; /* 8 bits, unsigned */ -typedef signed TH_TYPE_I8 int8_t; /* 8 bits, signed */ -#else -#ifndef HAVE_INT_TYPES -typedef unsigned char uint8_t; -typedef signed char int8_t; -#endif -#endif - - -#ifdef TH_TYPE_I16 -typedef unsigned TH_TYPE_I16 uint16_t; /* 16 bits, unsigned == 2 BYTEs */ -typedef signed TH_TYPE_I16 int16_t; /* 16 bits, signed */ -#else -#ifndef HAVE_INT_TYPES -typedef unsigned short int uint16_t; -typedef signed short int int16_t; -#endif -#endif - -#ifdef TH_TYPE_I32 -typedef unsigned TH_TYPE_I32 uint32_t; /* 32 bits, unsigned == 4 BYTES == 2 WORDs */ -typedef signed TH_TYPE_I32 int32_t; /* 32 bits, signed */ -#else -#ifndef HAVE_INT_TYPES -typedef unsigned int uint32_t; -typedef signed int int32_t; -#endif -#endif - -#ifdef TH_TYPE_I64 -typedef unsigned TH_TYPE_I64 uint64_t; /* 64 bits, unsigned == 8 BYTES == 2 DWORDs */ -typedef signed TH_TYPE_I64 int64_t; /* 64 bits, signed */ -#else -#ifndef HAVE_INT_TYPES -typedef unsigned long long uint64_t; -typedef signed long long int64_t; -#endif -#endif - - -/* This is the character type used in all string-related routines of - * th_libs. Currently it is set to be equivalent of basetype "char", - * but under some platforms it may be necessary to use - * "unsigned char" instead. - * - * Also in future this type may be changed to hold 32-bit UNICODE - */ -typedef char char_t; - - -/* Define a boolean type - */ -#if !defined(FALSE) && !defined(TRUE) && !defined(BOOL) -typedef enum { FALSE = 0, TRUE = 1 } BOOL; -#endif - -#ifndef BOOL -#ifdef bool -#define BOOL bool -#else -#define BOOL int -#endif -#endif - -#endif /* _TH_TYPES_H */ diff -r 727ce827482b -r 7c28f38cb6dd th_util.c --- a/th_util.c Mon Oct 03 15:43:01 2011 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,448 +0,0 @@ -/* - * Generic utility-functions, macros and defaults - * Programmed and designed by Matti 'ccr' Hamalainen - * (C) Copyright 2002-2010 Tecnic Software productions (TNSP) - * - * Please read file 'COPYING' for information on license and distribution. - */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include "th_util.h" -#include - -/* Default settings - */ -static BOOL th_initialized = FALSE; -int th_verbosityLevel = 2; -char *th_prog_name = NULL, - *th_prog_fullname = NULL, - *th_prog_version = NULL, - *th_prog_author = NULL, - *th_prog_license = NULL; - - -/* Initialize th_util-library and global variables - */ -void th_init(char *progName, char *progFullName, char *progVersion, - char *progAuthor, char *progLicense) -{ - th_prog_name = progName; - th_prog_fullname = progFullName; - th_prog_version = progVersion; - - if (progAuthor) - th_prog_author = progAuthor; - else - th_prog_author = TH_PROG_AUTHOR; - - if (progLicense) - th_prog_license = progLicense; - else - th_prog_license = TH_PROG_LICENSE; - - th_initialized = TRUE; -} - - -/* Print formatted error, warning and information messages - * TODO: Implement th_vfprintf() and friends? - */ -void THERR_V(const char *fmt, va_list ap) -{ - assert(th_initialized == TRUE); - - fprintf(stderr, "%s: ", th_prog_name); - vfprintf(stderr, fmt, ap); -} - - -void THMSG_V(int level, const char *fmt, va_list ap) -{ - assert(th_initialized == TRUE); - - if (th_verbosityLevel >= level) { - fprintf(stderr, "%s: ", th_prog_name); - vfprintf(stderr, fmt, ap); - } -} - - -void THPRINT_V(int level, const char *fmt, va_list ap) -{ - assert(th_initialized == TRUE); - - if (th_verbosityLevel >= level) { - vfprintf(stderr, fmt, ap); - } -} - - -void THERR(const char *fmt, ...) -{ - va_list ap; - assert(th_initialized == TRUE); - - va_start(ap, fmt); - THERR_V(fmt, ap); - va_end(ap); -} - - -void THMSG(int level, const char *fmt, ...) -{ - va_list ap; - assert(th_initialized == TRUE); - - va_start(ap, fmt); - THMSG_V(level, fmt, ap); - va_end(ap); -} - - -void THPRINT(int level, const char *fmt, ...) -{ - va_list ap; - assert(th_initialized == TRUE); - - va_start(ap, fmt); - THPRINT_V(level, fmt, ap); - va_end(ap); -} - - -/* Memory handling routines - */ -void *th_malloc(size_t l) -{ - return malloc(l); -} - - -void *th_calloc(size_t n, size_t l) -{ - return calloc(n, l); -} - - -void *th_realloc(void *p, size_t l) -{ - return realloc(p, l); -} - - -void th_free(void *p) -{ - /* Check for NULL pointers for portability due to some libc - * implementations not handling free(NULL) too well. - */ - if (p) free(p); -} - - -#ifndef HAVE_MEMSET -void *th_memset(void *p, int c, size_t n) -{ - unsigned char *dp = (unsigned char *) p; - - while (n--) - *(dp++) = c; - - return p; -} -#endif - - -/* Doubly linked list handling - * - * In this implementation first node's prev points to last node of the list, - * and last node's next is NULL. This way we can semi-efficiently traverse to - * beginning and end of the list, assuming user does not do weird things. - */ -qlist_t * th_llist_new(void *data) -{ - qlist_t *res = th_calloc(sizeof(qlist_t), 1); - res->data = data; - return res; -} - -void th_llist_free_func(qlist_t *list, void (*freefunc)(void *data)) -{ - qlist_t *curr = list; - - while (curr != NULL) { - qlist_t *next = curr->next; - if (freefunc != NULL && curr->data != NULL) - freefunc(curr->data); - th_free(curr); - curr = next; - } -} - - -void th_llist_free(qlist_t *list) -{ - th_llist_free_func(list, NULL); -} - -void th_llist_append_node(qlist_t **list, qlist_t *node) -{ - if (*list != NULL) { - node->prev = (*list)->prev; - (*list)->prev->next = node; - (*list)->prev = node; - (*list)->num++; - } else { - *list = node; - node->prev = *list; - (*list)->num = 1; - } - - node->next = NULL; -} - - -qlist_t *th_llist_append(qlist_t **list, void *data) -{ - qlist_t *node = th_llist_new(data); - - th_llist_append_node(list, node); - - return node; -} - - -void th_llist_prepend_node(qlist_t **list, qlist_t *node) -{ - if (*list != NULL) { - node->prev = (*list)->prev; - node->next = *list; - (*list)->prev = node; - node->num = (*list)->num + 1; - *list = node; - } else { - *list = node->prev = node; - node->next = NULL; - (*list)->num = 1; - } - -} - - -qlist_t *th_llist_prepend(qlist_t **list, void *data) -{ - qlist_t *node = th_llist_new(data); - - th_llist_prepend_node(list, node); - - return node; -} - -/* -1) Remove a middle node - - node0->prev->next = node->next (node1) - node0->next->prev = node->prev (list) - - node2 <- list <=> node0 <=> node1 <=> node2 -> NULL - node2 <- list <=> node1 <=> node2 -> NULL - -2) Remove first node when many items - - - node2 <- list <=> node0 <=> node1 <=> node2 -> NULL - node2 <- node0 <=> node1 <=> node2 -> NULL - - *list = node0 - -3) Remove last node in list - - if (node->next == NULL) { - list->prev = node->prev; - node->prev->next = NULL; - } - - node2 <- list <=> node0 <=> node1 <=> node2 -> NULL - node1 <- list <=> node0 <=> node1 -> NULL - -4) Remove last - - list <- list -> NULL - - -*/ -static void th_llist_delete_node_fast(qlist_t **list, qlist_t *node) -{ - if (node == *list) { - /* First node in list */ - qlist_t *tmp = (*list)->next; - if (tmp != NULL) { - tmp->num = (*list)->num - 1; - tmp->prev = (*list)->prev; - } - *list = tmp; - } else { - /* Somewhere in middle or end */ - if (node->prev != NULL) - node->prev->next = node->next; - - if (node->next != NULL) - node->next->prev = node->prev; - else - (*list)->prev = node; /* Last node */ - - (*list)->num--; - } - - node->next = node->prev = NULL; -} - - -void th_llist_delete_node(qlist_t **list, qlist_t *node) -{ - qlist_t *curr = *list; - - while (curr != NULL) { - qlist_t *next = curr->next; - if (curr == node) { - th_llist_delete_node_fast(list, curr); - th_free(node); - break; - } - curr = next; - } -} - - -void th_llist_delete(qlist_t **list, const void *data) -{ - qlist_t *curr = *list; - - while (curr != NULL) { - qlist_t *next = curr->next; - if (curr->data == data) { - th_llist_delete_node_fast(list, curr); - th_free(curr); - break; - } - curr = next; - } -} - - -qlist_t * th_llist_get_nth(qlist_t *list, const size_t n) -{ - qlist_t *curr = list; - size_t i; - - for (i = 0; curr != NULL && i < n; curr = curr->next, i++); - - return curr; -} - - -size_t th_llist_length(const qlist_t *list) -{ - if (list == NULL) - return 0; - else - return list->num; -} - - -ssize_t th_llist_position(const qlist_t *list, const qlist_t *node) -{ - const qlist_t *curr = list; - ssize_t i = 0; - - while (curr != NULL) { - if (curr == node) - return i; - else - i++; - - curr = curr->next; - } - - return -1; -} - - -qlist_t * th_llist_find(qlist_t *list, const void *data) -{ - qlist_t *curr = list; - - while (curr != NULL) { - if (curr->data == data) - return curr; - curr = curr->next; - } - - return NULL; -} - - -qlist_t * th_llist_find_func(qlist_t *list, const void *userdata, int (compare)(const void *, const void *)) -{ - qlist_t *curr = list; - - while (curr != NULL) { - if (compare(curr->data, userdata) == 0) - return curr; - curr = curr->next; - } - - return NULL; -} - - -/* - * Ringbuffers - */ -qringbuf_t * th_ringbuf_new(const size_t size, void (*mdeallocator)(void *data)) -{ - qringbuf_t *res = th_calloc(1, sizeof(qringbuf_t)); - - res->data = (char **) th_calloc(size, sizeof(char *)); - res->size = size; - res->n = 0; - res->deallocator = mdeallocator; - - return res; -} - - -BOOL th_ringbuf_grow(qringbuf_t *buf, const size_t n) -{ - buf->data = (char **) th_realloc(buf->data, (buf->size + n) * sizeof(char *)); - if (buf->data != NULL) { - memset(buf->data + buf->size, 0, sizeof(char *) * n); - buf->size += n; - return TRUE; - } else - return FALSE; -} - - -void th_ringbuf_free(qringbuf_t *buf) -{ - int i; - - for (i = 0; i < buf->size; i++) - if (buf->data[i] != NULL) - buf->deallocator(buf->data[i]); - - th_free(buf->data); - th_free(buf); -} - - -void th_ringbuf_add(qringbuf_t *buf, void *ptr) -{ - if (buf->n < buf->size) - buf->n++; - - th_free(buf->data[0]); - memmove(&(buf->data[0]), &(buf->data[1]), (buf->size - 1) * sizeof(void *)); - buf->data[buf->size - 1] = ptr; -} diff -r 727ce827482b -r 7c28f38cb6dd th_util.h --- a/th_util.h Mon Oct 03 15:43:01 2011 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,131 +0,0 @@ -/* - * Generic utility-functions, macros and defaults - * Programmed and designed by Matti 'ccr' Hamalainen - * (C) Copyright 2002-2010 Tecnic Software productions (TNSP) - * - * Please read file 'COPYING' for information on license and distribution. - */ -#ifndef _TH_UTIL_H -#define _TH_UTIL_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "th_types.h" -#include -#include -#include -#ifndef HAVE_NO_ASSERT -#include -#endif - -#ifdef HAVE_STRING_H -#include -#define HAVE_MEMSET 1 -#else -#ifdef HAVE_STRINGS_H -#include -#endif -#endif - -#ifdef HAVE_MEMORY_H -#include -#endif - - -#ifdef TH_NO_DEFAULTS -#define TH_PROG_AUTHOR NULL -#define TH_PROG_LICENSE NULL -#else -#define TH_PROG_AUTHOR "By Matti 'ccr' Hämäläinen (C) Copyright 2011 TNSP" -#define TH_PROG_LICENSE "This software is licensed under GNU GPL version 2" -#endif - - -/* Replacement for assert() */ -#ifdef HAVE_NO_ASSERT -# ifdef NDEBUG -# define assert(NEXPR) /* stub */ -# else -# define assert(NEXPR) do { if (!(NEXPR)) { fprintf(stderr, "[%s:%d] assert(" # NEXPR ") failed!\n", __FILE__, __LINE__); abort(); } } while (0) -# endif -#endif - -/* Global variables - */ -extern int th_verbosityLevel; -extern char *th_prog_name, - *th_prog_fullname, - *th_prog_version, - *th_prog_author, - *th_prog_license; - -/* Functions - */ -void th_init(char *progName, char *progFullName, char *progVersion, - char *progAuthor, char *progLicense); -void THERR(const char *, ...); -void THMSG(int, const char *, ...); -void THPRINT(int, const char *, ...); - -void THERR_V(const char *, va_list); -void THMSG_V(int, const char *, va_list); -void THPRINT_V(int, const char *, va_list); - -void *th_malloc(size_t); -void *th_calloc(size_t, size_t); -void *th_realloc(void *, size_t); -void th_free(void *); - -#ifdef HAVE_MEMSET -#define th_memset memset -#else -void *th_memset(void *, int, size_t); -#endif - - -/* Doubly linked list handling - */ -typedef struct _qlist_t { - void *data; - size_t num; - struct _qlist_t *prev, *next; -} qlist_t; - - -qlist_t * th_llist_new(void *data); -void th_llist_free(qlist_t *list); -void th_llist_free_func(qlist_t *list, void (*freefunc)(void *data)); - -qlist_t * th_llist_append(qlist_t **list, void *data); -qlist_t * th_llist_prepend(qlist_t **list, void *data); -void th_llist_delete(qlist_t **list, const void *data); -void th_llist_delete_node(qlist_t **list, qlist_t *node); - -qlist_t * th_llist_get_nth(qlist_t *list, const size_t n); -size_t th_llist_length(const qlist_t *list); -ssize_t th_llist_position(const qlist_t *list, const qlist_t *node); - -qlist_t * th_llist_find(qlist_t *list, const void *data); -qlist_t * th_llist_find_func(qlist_t *list, const void *userdata, int (compare)(const void *, const void *)); - - -/* Ringbuffer implementation - */ -typedef struct { - char **data; - int n, size; - void (*deallocator)(void *); -} qringbuf_t; - -qringbuf_t * th_ringbuf_new(const size_t size, void (*mdeallocator)(void *)); -BOOL th_ringbuf_grow(qringbuf_t *buf, const size_t n); -void th_ringbuf_free(qringbuf_t *buf); -void th_ringbuf_add(qringbuf_t *buf, void *ptr); - - -#ifdef __cplusplus -} -#endif -#endif /* _TH_UTIL_H */