*/
/*
- * Copyright (C) 1998, 1999 Henry Spencer.
- *
+ * Copyright (C) 2007-2008 Andreas Steffen
+ *
+ * Hochschule fuer Technik Rapperswil
+ *
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
* License for more details.
*
+ * RCSID $Id$
*/
#include <stdio.h>
#include "optionsfrom.h"
#define MAX_USES 20 /* loop-detection limit */
-#define SOME_ARGS 10 /* first guess at how many arguments we'll need */
+#define MORE_ARGS 10 /* first guess at how many arguments we'll need */
/*
* Defined in header.
*/
-bool optionsfrom(const char *filename, int *argcp, char **argvp[], int optind)
-{
- static int nuses = 0;
+
+typedef struct private_options_t private_options_t;
+
+/**
+ * Private data of a options_t object.
+ */
+struct private_options_t {
+ /**
+ * Public interface
+ */
+ options_t public;
+
+ /**
+ * reallocated argv array
+ */
char **newargv;
+
+ /**
+ * number of free arguments in newargv
+ */
+ int room;
+
+ /**
+ * number of included option files
+ */
+ int nuses;
+
+ /**
+ * allocated space for option files
+ */
+ char *buffers[MAX_USES];
+};
+
+/**
+ * Defined in header
+ */
+bool from(private_options_t *this, char *filename, int *argcp, char **argvp[],
+ int optind)
+{
int newargc;
int next; /* place for next argument */
- int room; /* how many more new arguments we can hold */
+ char **newargv;
size_t bytes;
- chunk_t chunk, src, line, token;
+ chunk_t src, line, token;
bool good = TRUE;
int linepos = 0;
FILE *fd;
/* avoid endless loops with recursive --optionsfrom arguments */
- nuses++;
- if (nuses >= MAX_USES)
+ this->nuses++;
+ if (this->nuses >= MAX_USES)
{
- DBG1("optionsfrom called %d times - looping?", (*argvp)[0], nuses);
+ DBG1("optionsfrom called %d times by \"%s\" - looping?", this->nuses + 1, (*argvp)[0]);
return FALSE;
}
/* determine the file size */
fseek(fd, 0, SEEK_END);
- chunk.len = ftell(fd);
+ src.len = ftell(fd);
rewind(fd);
/* allocate one byte more just in case of a missing final newline */
- chunk.ptr = malloc(chunk.len + 1);
+ src.ptr = this->buffers[this->nuses] = malloc(src.len + 1);
/* read the whole file into a chunk */
- bytes = fread(chunk.ptr, 1, chunk.len, fd);
+ bytes = fread(src.ptr, 1, src.len, fd);
fclose(fd);
- newargc = *argcp + SOME_ARGS;
- newargv = malloc((newargc + 1) * sizeof(char *));
+ if (this->room)
+ {
+ newargc = *argcp;
+ newargv = malloc((newargc + 1 + this->room) * sizeof(char *));
+ }
+ else
+ {
+ newargc = *argcp + MORE_ARGS;
+ this->room = MORE_ARGS;
+ newargv = malloc((newargc + 1) * sizeof(char *));
+ }
memcpy(newargv, *argvp, optind * sizeof(char *));
- room = SOME_ARGS;
next = optind;
newargv[next] = NULL;
- /* we keep the chunk pointer so that we can still free it */
- src = chunk;
-
while (fetchline(&src, &line) && good)
{
linepos++;
}
/* do we have to allocate more memory for additional arguments? */
- if (room == 0)
+ if (this->room == 0)
{
- newargc += SOME_ARGS;
- newargv = realloc(newargv, (newargc+1) * sizeof(char *));
- room = SOME_ARGS;
+ newargc += MORE_ARGS;
+ newargv = realloc(newargv, (newargc + 1) * sizeof(char *));
+ this->room = MORE_ARGS;
}
/* terminate the token by replacing the delimiter with a null character */
/* assign the token to the next argument */
newargv[next] = token.ptr;
next++;
- room--;
+ this->room--;
}
}
- if (!good) /* error of some kind */
+ /* assign newargv to argv */
+ if (good)
{
- free(chunk.ptr);
- free(newargv);
- return FALSE;
+ memcpy(newargv + next, *argvp + optind, (*argcp + 1 - optind) * sizeof(char *));
+ *argcp += next - optind;
+ *argvp = newargv;
}
- memcpy(newargv + next, *argvp + optind, (*argcp + 1 - optind) * sizeof(char *));
- *argcp += next - optind;
- *argvp = newargv;
- return TRUE;
+ /* keep a pointer to the latest newargv and free any earlier version */
+ free(this->newargv);
+ this->newargv = newargv;
+
+ return good;
+}
+
+/**
+ * Defined in header
+ */
+void destroy(private_options_t *this)
+{
+ while (this->nuses >= 0)
+ {
+ free(this->buffers[this->nuses--]);
+ }
+ free(this->newargv);
+ free(this);
}
+/*
+ * Defined in header
+ */
+options_t *options_create(void)
+{
+ private_options_t *this = malloc_thing(private_options_t);
+
+ /* initialize */
+ this->newargv = NULL;
+ this->room = 0;
+ this->nuses = -1;
+ memset(this->buffers, '\0', MAX_USES);
+
+ /* public functions */
+ this->public.from = (bool (*) (options_t*,char*,int*,char***,int))from;
+ this->public.destroy = (void (*) (options_t*))destroy;
+
+ return &this->public;
+}
*/
/*
- * Copyright (C) 1998, 1999 Henry Spencer.
- * Copyright (C) 2007 Andreas Steffen, Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2007-2008 Andreas Steffen
+ *
+ * Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
+ *
+ * RCSID $Id$
*/
#ifndef OPTIONSFROM_H_
#define OPTIONSFROM_H_
+typedef struct options_t options_t;
+
/**
- * @brief Pick up more options from a file, in the middle of an option scan
+ * @brief options object.
*
- * @param filename file containing the options
- * @param argcp pointer to argc
- * @param argvp pointer to argv[]
- * @param optind current optind, number of next argument
- * @return TRUE if optionsfrom parsing successful
+ * @b Constructors:
+ * - options_create()
+ *
+ * @ingroup utils
+ */
+struct options_t {
+ /**
+ * @brief Check if the PKCS#7 contentType is data
+ *
+ * @param this calling object
+ * @param filename file containing the options
+ * @param argcp pointer to argc
+ * @param argvp pointer to argv[]
+ * @param optind current optind, number of next argument
+ * @return TRUE if optionsfrom parsing successful
+ */
+ bool (*from) (options_t * this, char *filename, int *argcp, char **argvp[], int optind);
+
+ /**
+ * @brief Destroys the options_t object.
+ *
+ * @param this options_t object to destroy
+ */
+ void (*destroy) (options_t *this);
+};
+
+/**
+ * @brief Create an options object.
+ *
+ * @return created options_t object
+ *
+ * @ingroup utils
*/
-bool optionsfrom(const char *filename, int *argcp, char **argvp[], int optind);
+options_t *options_create(void);
#endif /*OPTIONSFROM_H_*/