You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
266 lines
6.3 KiB
C
266 lines
6.3 KiB
C
/*
|
|
* optstr.c
|
|
*
|
|
* Copyright (C) Tilmann Bitterberg 2003
|
|
*
|
|
* Description: A general purpose option string parser
|
|
*
|
|
* Usage: see optstr.h, please
|
|
*
|
|
* This file is part of transcode, a video stream processing tool
|
|
*
|
|
* transcode is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2, or (at your option)
|
|
* any later version.
|
|
*
|
|
* transcode is distributed in the hope that it will be useful,
|
|
* but 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.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with GNU Make; see the file COPYING. If not, write to
|
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
|
|
/* for vsscanf */
|
|
#ifdef HAVE_VSSCANF
|
|
# define _GNU_SOURCE
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdarg.h>
|
|
#include "optstr.h"
|
|
#include "libtc.h"
|
|
|
|
const char* optstr_lookup(const char *haystack, const char *needle)
|
|
{
|
|
const char *ch = haystack;
|
|
int found = 0;
|
|
size_t len = strlen(needle);
|
|
|
|
while (!found) {
|
|
ch = strstr(ch, needle);
|
|
|
|
/* not in string */
|
|
if (!ch) {
|
|
break;
|
|
}
|
|
|
|
/* do we want this hit? ie is it exact? */
|
|
if (ch[len] == '\0' || ch[len] == '=' || ch[len] == ARG_SEP) {
|
|
found = 1;
|
|
} else {
|
|
/* go a little further */
|
|
ch++;
|
|
}
|
|
}
|
|
|
|
return ch;
|
|
}
|
|
|
|
int optstr_get(const char *options, const char *name, const char *fmt, ...)
|
|
{
|
|
va_list ap; /* points to each unnamed arg in turn */
|
|
int num_args = 0, n = 0;
|
|
size_t pos, fmt_len = strlen(fmt);
|
|
const char *ch = NULL;
|
|
|
|
#ifndef HAVE_VSSCANF
|
|
void *temp[ARG_MAXIMUM];
|
|
#endif
|
|
|
|
ch = optstr_lookup(options, name);
|
|
if (!ch) {
|
|
return -1;
|
|
}
|
|
|
|
/* name IS in options */
|
|
|
|
/* Find how many arguments we expect */
|
|
for (pos = 0; pos < fmt_len; pos++) {
|
|
if (fmt[pos] == '%') {
|
|
++num_args;
|
|
/* is this one quoted with '%%' */
|
|
if (pos + 1 < fmt_len && fmt[pos + 1] == '%') {
|
|
--num_args;
|
|
++pos;
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifndef HAVE_VSSCANF
|
|
if (num_args > ARG_MAXIMUM) {
|
|
fprintf (stderr,
|
|
"(%s:%d) Internal Overflow; redefine ARG_MAXIMUM (%d) to something higher\n",
|
|
__FILE__, __LINE__, ARG_MAXIMUM);
|
|
return -2;
|
|
}
|
|
#endif
|
|
|
|
n = num_args;
|
|
/* Bool argument */
|
|
if (num_args <= 0) {
|
|
return 0;
|
|
}
|
|
|
|
/* skip the `=' (if it is one) */
|
|
ch += strlen( name );
|
|
if( *ch == '=' )
|
|
ch++;
|
|
|
|
if( !*ch )
|
|
return 0;
|
|
|
|
va_start(ap, fmt);
|
|
|
|
#ifndef HAVE_VSSCANF
|
|
while (--n >= 0) {
|
|
temp[num_args - n - 1] = va_arg(ap, void *);
|
|
}
|
|
|
|
n = sscanf(ch, fmt,
|
|
temp[0], temp[1], temp[2], temp[3], temp[4],
|
|
temp[5], temp[6], temp[7], temp[8], temp[9],
|
|
temp[10], temp[11], temp[12], temp[13], temp[14],
|
|
temp[15]);
|
|
|
|
#else
|
|
/* this would be very nice instead of the above,
|
|
* but it does not seem portable
|
|
*/
|
|
n = vsscanf(ch, fmt, ap);
|
|
#endif
|
|
|
|
va_end(ap);
|
|
|
|
return n;
|
|
}
|
|
|
|
static int optstr_is_string_arg(const char *fmt)
|
|
{
|
|
if (!fmt) {
|
|
return 0;
|
|
}
|
|
if (!strlen(fmt)) {
|
|
return 0;
|
|
}
|
|
if (strchr(fmt, 's')) {
|
|
return 1;
|
|
}
|
|
if (strchr(fmt, '[') && strchr(fmt, ']')) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
int optstr_filter_desc(char *buf,
|
|
const char *filter_name,
|
|
const char *filter_comment,
|
|
const char *filter_version,
|
|
const char *filter_author,
|
|
const char *capabilities,
|
|
const char *frames_needed)
|
|
{
|
|
int len = strlen(buf);
|
|
if (tc_snprintf(buf + len, ARG_CONFIG_LEN - len,
|
|
"\"%s\", \"%s\", \"%s\", \"%s\", \"%s\", \"%s\"\n",
|
|
filter_name,filter_comment,filter_version,
|
|
filter_author, capabilities, frames_needed) <= 0) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int optstr_frames_needed(const char *filter_desc, int *needed_frames)
|
|
{
|
|
const char *s = NULL;
|
|
|
|
if ((s = strrchr(filter_desc, ',')) == NULL) {
|
|
return 1;
|
|
}
|
|
if ((s = strchr(s, '\"')) == NULL) {
|
|
return 1;
|
|
}
|
|
|
|
*needed_frames = strtol(s + 1, NULL, 0);
|
|
return 0;
|
|
}
|
|
|
|
int optstr_param(char *buf,
|
|
const char *name,
|
|
const char *comment,
|
|
const char *fmt,
|
|
const char *val,
|
|
...) /* char *valid_from1, char *valid_to1, ... */
|
|
{
|
|
va_list ap;
|
|
int n = 0, res = 0, num_args=0;
|
|
size_t buf_len = strlen(buf), fmt_len = strlen(fmt), pos = 0;
|
|
|
|
res = tc_snprintf(buf + buf_len, ARG_CONFIG_LEN - buf_len,
|
|
"\"%s\", \"%s\", \"%s\", \"%s\"",
|
|
name, comment, fmt, val);
|
|
if(res <= 0) {
|
|
return 1;
|
|
}
|
|
n += res;
|
|
|
|
/* count format strings */
|
|
for (pos = 0; pos < fmt_len; pos++) {
|
|
if (fmt[pos] == '%') {
|
|
++num_args;
|
|
/* is this one quoted with '%%' */
|
|
if (pos + 1 < fmt_len && fmt[pos + 1] == '%') {
|
|
--num_args;
|
|
++pos;
|
|
}
|
|
}
|
|
}
|
|
num_args *= 2;
|
|
|
|
if (num_args && optstr_is_string_arg(fmt)) {
|
|
num_args = 0;
|
|
}
|
|
|
|
va_start(ap, val);
|
|
while (num_args--) {
|
|
res = tc_snprintf(buf + buf_len + n,
|
|
ARG_CONFIG_LEN - buf_len - n,
|
|
", \"%s\"", va_arg(ap, char *));
|
|
if (res <= 0) {
|
|
return 1;
|
|
}
|
|
n += res;
|
|
}
|
|
va_end(ap);
|
|
|
|
res = tc_snprintf(buf + buf_len + n, ARG_CONFIG_LEN - buf_len - n, "\n");
|
|
if (res <= 0 ) {
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*************************************************************************/
|
|
|
|
/*
|
|
* Local variables:
|
|
* c-file-style: "stroustrup"
|
|
* c-file-offsets: ((case-label . *) (statement-case-intro . *))
|
|
* indent-tabs-mode: nil
|
|
* End:
|
|
*
|
|
* vim: expandtab shiftwidth=4:
|
|
*/
|