All new argument parser.
This commit is contained in:
parent
7cba775e18
commit
c54101b14b
27 changed files with 2585 additions and 146 deletions
|
@ -70,7 +70,7 @@ CROSS="x86_64-linux-gnu"
|
||||||
EXTRA_CFLAGS="-O2"
|
EXTRA_CFLAGS="-O2"
|
||||||
EXTRA_OFILES=""
|
EXTRA_OFILES=""
|
||||||
EXTRA_LD_FLAGS="-l:everything.a -lpthread -lXv -lX11 -lXext -lm -ldl -lrt"
|
EXTRA_LD_FLAGS="-l:everything.a -lpthread -lXv -lX11 -lXext -lm -ldl -lrt"
|
||||||
doBuild Singe-Linux-x86_64 linux 64
|
#doBuild Singe-Linux-x86_64 linux 64
|
||||||
|
|
||||||
# 64 Bit Windows
|
# 64 Bit Windows
|
||||||
CROSS="x86_64-w64-mingw32"
|
CROSS="x86_64-w64-mingw32"
|
||||||
|
@ -79,14 +79,14 @@ EXTRA_OFILES="/tmp/singe.res"
|
||||||
EXTRA_LD_FLAGS="-mwindows -static -lmingw32 -l:everything.a -lm -lbcrypt -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lsetupapi -lversion -luuid -Dmain=SDL_main"
|
EXTRA_LD_FLAGS="-mwindows -static -lmingw32 -l:everything.a -lm -lbcrypt -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lsetupapi -lversion -luuid -Dmain=SDL_main"
|
||||||
icotool -c -o /tmp/icon.ico icon.png
|
icotool -c -o /tmp/icon.ico icon.png
|
||||||
x86_64-w64-mingw32-windres singe.rc -O coff -o /tmp/singe.res
|
x86_64-w64-mingw32-windres singe.rc -O coff -o /tmp/singe.res
|
||||||
doBuild Singe-Windows-x86_64 mingw 64 .exe
|
#doBuild Singe-Windows-x86_64 mingw 64 .exe
|
||||||
rm /tmp/icon.ico
|
rm /tmp/icon.ico
|
||||||
rm /tmp/singe.res
|
rm /tmp/singe.res
|
||||||
|
|
||||||
# 32 Bit Raspbian - ***TODO*** Should we provide libsamplerate ourselves?
|
# 32 Bit Raspbian
|
||||||
SYSROOT="/opt/cross/pi/buster"
|
SYSROOT="/opt/cross/pi/buster"
|
||||||
CROSS="/opt/cross/pi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf"
|
CROSS="/opt/cross/pi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf"
|
||||||
EXTRA_CFLAGS="-O2 --sysroot ${SYSROOT}"
|
EXTRA_CFLAGS="-O2 --sysroot ${SYSROOT}"
|
||||||
EXTRA_OFILES=""
|
EXTRA_OFILES=""
|
||||||
EXTRA_LD_FLAGS="--sysroot ${SYSROOT} -l:everything.a -Wl,-rpath-link,${SYSROOT}/opt/vc/lib -L${SYSROOT}/opt/vc/lib -lbcm_host -lasound -lpthread -lXv -lX11 -lXext -lXi -lm -ldl -lrt -lsndio -lXcursor -lXinerama -lXrandr -lXss -lXxf86vm -lmmal_core -lmmal_util -lmmal_vc_client -lvdpau -ldrm -lgbm -lsamplerate"
|
EXTRA_LD_FLAGS="--sysroot ${SYSROOT} -l:everything.a -Wl,-rpath-link,${SYSROOT}/opt/vc/lib -L${SYSROOT}/opt/vc/lib -lbcm_host -lasound -lpthread -lm -ldl -lsndio -lmmal_core -lmmal_util -lmmal_vc_client -lvdpau -ldrm -lgbm -lX11 -lsamplerate"
|
||||||
doBuild Singe-Pi-armv6 pi 32
|
doBuild Singe-Pi-armv6 pi 32
|
||||||
|
|
|
@ -105,6 +105,7 @@ int32_t frameFileLoad(char *filename, char *indexPath, bool stretchVideo, SDL_Re
|
||||||
int32_t result = 0;
|
int32_t result = 0;
|
||||||
int32_t count = 0;
|
int32_t count = 0;
|
||||||
int64_t frame = 0;
|
int64_t frame = 0;
|
||||||
|
int64_t next = 0;
|
||||||
size_t bytes = 0;
|
size_t bytes = 0;
|
||||||
char *audio = NULL;
|
char *audio = NULL;
|
||||||
char *data = NULL;
|
char *data = NULL;
|
||||||
|
@ -141,6 +142,10 @@ int32_t frameFileLoad(char *filename, char *indexPath, bool stretchVideo, SDL_Re
|
||||||
|
|
||||||
// Read frame offsets and filenames - silently ignore bad lines
|
// Read frame offsets and filenames - silently ignore bad lines
|
||||||
while ((frameLine = utilReadLine(data, bytes, &offset)) != NULL) {
|
while ((frameLine = utilReadLine(data, bytes, &offset)) != NULL) {
|
||||||
|
// Covert tabs to spaces
|
||||||
|
for (next=0; next<(int64_t)strlen(frameLine); next++) {
|
||||||
|
if (frameLine[next] == 9) frameLine[next] = 32;
|
||||||
|
}
|
||||||
// Find first space in this file.
|
// Find first space in this file.
|
||||||
space = strstr(frameLine, " ");
|
space = strstr(frameLine, " ");
|
||||||
if (space) {
|
if (space) {
|
||||||
|
@ -153,7 +158,7 @@ int32_t frameFileLoad(char *filename, char *indexPath, bool stretchVideo, SDL_Re
|
||||||
if (endptr == space) {
|
if (endptr == space) {
|
||||||
// Got an integer. Point at filename.
|
// Got an integer. Point at filename.
|
||||||
space++;
|
space++;
|
||||||
while ((space[0] == 32) || (space[0] == 9)) {
|
while (space[0] == 32) {
|
||||||
space++;
|
space++;
|
||||||
}
|
}
|
||||||
// Copy frame number and filename into array
|
// Copy frame number and filename into array
|
||||||
|
@ -170,7 +175,11 @@ int32_t frameFileLoad(char *filename, char *indexPath, bool stretchVideo, SDL_Re
|
||||||
audio[strlen(audio) - 3] = 'o';
|
audio[strlen(audio) - 3] = 'o';
|
||||||
audio[strlen(audio) - 2] = 'g';
|
audio[strlen(audio) - 2] = 'g';
|
||||||
audio[strlen(audio) - 1] = 'g';
|
audio[strlen(audio) - 1] = 'g';
|
||||||
|
if (utilFileExists(audio)) {
|
||||||
files[count].videoHandle = videoLoadWithAudio(files[count].filename, audio, indexPath, stretchVideo, renderer);
|
files[count].videoHandle = videoLoadWithAudio(files[count].filename, audio, indexPath, stretchVideo, renderer);
|
||||||
|
} else {
|
||||||
|
files[count].videoHandle = videoLoadWithAudio(files[count].filename, NULL, indexPath, stretchVideo, renderer);
|
||||||
|
}
|
||||||
free(audio);
|
free(audio);
|
||||||
audio = NULL;
|
audio = NULL;
|
||||||
} else {
|
} else {
|
||||||
|
@ -197,12 +206,23 @@ int32_t frameFileLoad(char *filename, char *indexPath, bool stretchVideo, SDL_Re
|
||||||
if (_confShowCalculated) {
|
if (_confShowCalculated) {
|
||||||
// 00000000011111111112222222222333333333344444444445555555555666666666677777777778
|
// 00000000011111111112222222222333333333344444444445555555555666666666677777777778
|
||||||
// 12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
// 12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||||
|
utilSay("Existing Framefile:\n");
|
||||||
utilSay(" Start Length End File");
|
utilSay(" Start Length End File");
|
||||||
utilSay("-------- -------- -------- -------------------------------------------------");
|
utilSay("-------- -------- -------- -------------------------------------------------");
|
||||||
for (count=0; count<frameFile->count; count++) {
|
for (count=0; count<frameFile->count; count++) {
|
||||||
frame = videoGetFrameCount(frameFile->files[count].videoHandle);
|
frame = videoGetFrameCount(frameFile->files[count].videoHandle);
|
||||||
utilSay("%8ld %8ld %8ld %s", frameFile->files[count].frame, frame, frameFile->files[count].frame + frame, frameFile->files[count].filename);
|
utilSay("%8ld %8ld %8ld %s", frameFile->files[count].frame, frame, frameFile->files[count].frame + frame, frameFile->files[count].filename);
|
||||||
}
|
}
|
||||||
|
next = 0;
|
||||||
|
utilSay("\nIdeal Framefile:\n");
|
||||||
|
utilSay(" Start File");
|
||||||
|
utilSay("-------- ---------------------------------------------------------------------");
|
||||||
|
for (count=0; count<frameFile->count; count++) {
|
||||||
|
frame = videoGetFrameCount(frameFile->files[count].videoHandle);
|
||||||
|
utilSay("%8ld %s", next, frameFile->files[count].filename);
|
||||||
|
next += frame + 1;
|
||||||
|
}
|
||||||
|
utilSay("");
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -211,6 +231,7 @@ int32_t frameFileLoad(char *filename, char *indexPath, bool stretchVideo, SDL_Re
|
||||||
|
|
||||||
int32_t frameFileSeek(int32_t frameFileHandle, int64_t seekFrame, int32_t *videoHandle, int64_t *actualFrame) {
|
int32_t frameFileSeek(int32_t frameFileHandle, int64_t seekFrame, int32_t *videoHandle, int64_t *actualFrame) {
|
||||||
int32_t i = 0;
|
int32_t i = 0;
|
||||||
|
int32_t found = -1;
|
||||||
FrameFileT *f = NULL;
|
FrameFileT *f = NULL;
|
||||||
|
|
||||||
// Get our framefile structure
|
// Get our framefile structure
|
||||||
|
@ -218,21 +239,38 @@ int32_t frameFileSeek(int32_t frameFileHandle, int64_t seekFrame, int32_t *video
|
||||||
if (!f) utilDie("No framefile at index %d in frameFileSeek.", frameFileHandle);
|
if (!f) utilDie("No framefile at index %d in frameFileSeek.", frameFileHandle);
|
||||||
|
|
||||||
// Search through loaded video segments
|
// Search through loaded video segments
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Daphne-like framefile searching
|
||||||
|
for (i=f->count - 1; i>=0; i--) {
|
||||||
|
if (seekFrame <= f->files[i].frame) {
|
||||||
|
found = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Strict framefile searching
|
||||||
for (i=0; i<f->count; i++) {
|
for (i=0; i<f->count; i++) {
|
||||||
if ((seekFrame >= f->files[i].frame) && (seekFrame <= (f->files[i].frame + videoGetFrameCount(f->files[i].videoHandle)))) {
|
if ((seekFrame >= f->files[i].frame) && (seekFrame <= (f->files[i].frame + videoGetFrameCount(f->files[i].videoHandle)))) {
|
||||||
|
found = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found >= 0) {
|
||||||
// Frame is in this video
|
// Frame is in this video
|
||||||
*actualFrame = seekFrame - f->files[i].frame;
|
*actualFrame = seekFrame - f->files[found].frame;
|
||||||
f->files[i].lastFramePlayed = *actualFrame;
|
//utilSay("Frame %ld found in file %d - %s at %ld", seekFrame, found, f->files[found].filename, *actualFrame);
|
||||||
videoSeek(f->files[i].videoHandle, *actualFrame);
|
f->files[found].lastFramePlayed = *actualFrame;
|
||||||
|
videoSeek(f->files[found].videoHandle, *actualFrame);
|
||||||
// Is this a different video from the previous one?
|
// Is this a different video from the previous one?
|
||||||
if (*videoHandle != f->files[i].videoHandle) {
|
if (*videoHandle != f->files[found].videoHandle) {
|
||||||
// Yes
|
// Yes
|
||||||
_transferProperties(*videoHandle, f->files[i].videoHandle);
|
_transferProperties(*videoHandle, f->files[found].videoHandle);
|
||||||
*videoHandle = f->files[i].videoHandle;
|
*videoHandle = f->files[found].videoHandle;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Didn't find it
|
// Didn't find it
|
||||||
*videoHandle = -1;
|
*videoHandle = -1;
|
||||||
|
|
265
singe/main.c
265
singe/main.c
|
@ -20,17 +20,18 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
// -c -v singe/ActionMax/frame_SonicFury.txt singe/ActionMax/SonicFury.singe
|
// -c -x 720 -y 480 -d data/maddog_dvd -v maddog_dvd/frame_maddog_dvd.txt maddog_dvd/maddog_dvd.singe
|
||||||
// -v singe/ActionMax/BlueThunder.mp4 singe/test.singe
|
// -c -x 640 -y 480 -v ActionMax/frame_SonicFury.txt ActionMax/SonicFury.singe
|
||||||
|
// -v ActionMax/BlueThunder.mp4 test.singe
|
||||||
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <getopt.h>
|
|
||||||
|
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
#include <SDL2/SDL_image.h>
|
#include <SDL2/SDL_image.h>
|
||||||
#include <SDL2/SDL_mixer.h>
|
#include <SDL2/SDL_mixer.h>
|
||||||
#include <SDL2/SDL_ttf.h>
|
#include <SDL2/SDL_ttf.h>
|
||||||
|
#include <carg_parser.h>
|
||||||
#include <manymouse.h>
|
#include <manymouse.h>
|
||||||
|
|
||||||
#include "stddclmr.h"
|
#include "stddclmr.h"
|
||||||
|
@ -75,25 +76,25 @@ void showUsage(char *name, char *message) {
|
||||||
utilSay("");
|
utilSay("");
|
||||||
utilSay("Usage: %s [OPTIONS] scriptName{.singe}", utilGetLastPathComponent(name));
|
utilSay("Usage: %s [OPTIONS] scriptName{.singe}", utilGetLastPathComponent(name));
|
||||||
utilSay("");
|
utilSay("");
|
||||||
utilSay(" -v, --framefile=FILENAME use an alternate video file");
|
utilSay(" -a, --aspect=N:D force aspect ratio");
|
||||||
|
utilSay(" -c, --showcalculated show calculated framefile values for debugging");
|
||||||
utilSay(" -d, --datadir=PATHNAME alternate location for written files");
|
utilSay(" -d, --datadir=PATHNAME alternate location for written files");
|
||||||
|
utilSay(" -e, --volume_nonvldp=PERCENT specify sound effects volume in percent");
|
||||||
|
utilSay(" -f, --fullscreen run in full screen mode");
|
||||||
|
utilSay(" -g, --sindengun=PARAMS enable Sinden Light Gun support");
|
||||||
|
utilSay(" -h, --help this display");
|
||||||
|
utilSay(" -l, --volume_vldp=PERCENT specify laserdisc volume in percent");
|
||||||
utilSay(" -m, --nomouse disable mouse");
|
utilSay(" -m, --nomouse disable mouse");
|
||||||
//utilSay(" -n, --noserversend do not send usage statistics");
|
//utilSay(" -n, --noserversend do not send usage statistics");
|
||||||
utilSay(" -s, --nosound, --mutesound mutes all sound");
|
|
||||||
utilSay(" -f, --fullscreen run in full screen mode");
|
|
||||||
utilSay(" -w, --fullscreen_window run in windowed full screen mode");
|
|
||||||
utilSay(" -l, --volume_vldp=PERCENT specify laserdisc volume in percent");
|
|
||||||
utilSay(" -e, --volume_nonvldp=PERCENT specify sound effects volume in percent");
|
|
||||||
utilSay(" -o, --scalefactor=PERCENT reduce screen size for overscan compensation");
|
utilSay(" -o, --scalefactor=PERCENT reduce screen size for overscan compensation");
|
||||||
utilSay(" -g, --sindengun=PARAMS enable Sinden Light Gun support");
|
utilSay(" -s, --nosound, --mutesound mutes all sound");
|
||||||
utilSay(" -a, --aspect=N:D force aspect ratio");
|
utilSay(" -t, --trace trace script execution to screen and file");
|
||||||
utilSay(" -u, --stretch use ugly stretched video");
|
utilSay(" -u, --stretch use ugly stretched video");
|
||||||
|
utilSay(" -v, --framefile=FILENAME use an alternate video file");
|
||||||
|
utilSay(" -w, --fullscreen_window run in windowed full screen mode");
|
||||||
utilSay(" -x, --xresolution=VALUE specify horizontal resolution");
|
utilSay(" -x, --xresolution=VALUE specify horizontal resolution");
|
||||||
utilSay(" -y, --yresolution=VALUE specify vertical resolution");
|
utilSay(" -y, --yresolution=VALUE specify vertical resolution");
|
||||||
utilSay(" -t, --trace trace script execution to screen and file");
|
|
||||||
utilSay(" -c, --showcalculated show calculated framefile values for debugging");
|
|
||||||
utilSay(" -z, --noconsole zero console output, no splash screens");
|
utilSay(" -z, --noconsole zero console output, no splash screens");
|
||||||
utilSay(" -h, --help this display");
|
|
||||||
utilSay("");
|
utilSay("");
|
||||||
if (message) {
|
if (message) {
|
||||||
utilSay("Error: %s", message);
|
utilSay("Error: %s", message);
|
||||||
|
@ -107,16 +108,19 @@ void showUsage(char *name, char *message) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, const char *argv[]) {
|
||||||
|
|
||||||
int32_t x = 0;
|
int32_t x = 0;
|
||||||
int32_t err = 0;
|
int32_t err = 0;
|
||||||
int32_t flags = 0;
|
int32_t flags = 0;
|
||||||
int32_t optionIndex = 0;
|
|
||||||
int32_t bestResIndex = -1;
|
int32_t bestResIndex = -1;
|
||||||
int32_t bestRatioIndex = -1;
|
int32_t bestRatioIndex = -1;
|
||||||
int32_t aspectNum = -1;
|
int32_t aspectNum = -1;
|
||||||
int32_t aspectDom = -1;
|
int32_t aspectDom = -1;
|
||||||
|
int32_t argCount = 0;
|
||||||
|
int32_t argIndex = 0;
|
||||||
|
int32_t code = 0;
|
||||||
|
char *exeName = NULL;
|
||||||
char *temp = NULL;
|
char *temp = NULL;
|
||||||
char *aspectString = NULL;
|
char *aspectString = NULL;
|
||||||
char *sindenString = NULL;
|
char *sindenString = NULL;
|
||||||
|
@ -127,28 +131,29 @@ int main(int argc, char *argv[]) {
|
||||||
SDL_Renderer *renderer = NULL;
|
SDL_Renderer *renderer = NULL;
|
||||||
SDL_Surface *icon = NULL;
|
SDL_Surface *icon = NULL;
|
||||||
SDL_DisplayMode mode;
|
SDL_DisplayMode mode;
|
||||||
static struct option options[] = {
|
const char *arg = NULL;
|
||||||
{ "nomouse", no_argument, NULL, 'm' },
|
struct Arg_parser parser;
|
||||||
// { "noserversend", no_argument, NULL, 'n' },
|
static struct ap_Option options[] = {
|
||||||
{ "nosound", no_argument, NULL, 's' },
|
{ 'a', "aspect", ap_yes },
|
||||||
{ "mutesound", no_argument, NULL, 's' },
|
{ 'c', "showcalculated", ap_no },
|
||||||
{ "fullscreen", no_argument, NULL, 'f' },
|
{ 'd', "datadir", ap_yes },
|
||||||
{ "fullscreen_window", no_argument, NULL, 'w' },
|
{ 'e', "volume_nonlvdp", ap_yes },
|
||||||
{ "stretch", no_argument, NULL, 'u' },
|
{ 'f', "fullscreen", ap_no },
|
||||||
{ "datadir", optional_argument, NULL, 'd' },
|
{ 'g', "sindengun", ap_yes },
|
||||||
{ "framefile", optional_argument, NULL, 'v' },
|
{ 'h', "help", ap_no },
|
||||||
{ "volume_vldp", optional_argument, NULL, 'l' },
|
{ 'l', "volume_vldp", ap_yes },
|
||||||
{ "volume_nonlvdp", optional_argument, NULL, 'e' },
|
{ 'm', "nomouse", ap_no },
|
||||||
{ "scalefactor", optional_argument, NULL, 'o' },
|
// { 'n', "noserversend", ap_no },
|
||||||
{ "sindengun", optional_argument, NULL, 'g' },
|
{ 'o', "scalefactor", ap_yes },
|
||||||
{ "aspect", optional_argument, NULL, 'a' },
|
{ 's', "nosound", ap_no },
|
||||||
{ "xresolution", optional_argument, NULL, 'x' },
|
{ 't', "trace", ap_no },
|
||||||
{ "yresolution", optional_argument, NULL, 'y' },
|
{ 'u', "stretch", ap_no },
|
||||||
{ "help", no_argument, NULL, 'h' },
|
{ 'v', "framefile", ap_yes },
|
||||||
{ "trace", no_argument, NULL, 't' },
|
{ 'w', "fullscreenwindow", ap_no },
|
||||||
{ "showcalculated", no_argument, NULL, 'c' },
|
{ 'x', "xresolution", ap_yes },
|
||||||
{ "noconsole", no_argument, NULL, 'z' },
|
{ 'y', "yresolution", ap_yes },
|
||||||
{ NULL, 0, NULL, 0 }
|
{ 'z', "noconsole", ap_no },
|
||||||
|
{ 0, 0, ap_no }
|
||||||
};
|
};
|
||||||
static ModeT modes[] = {
|
static ModeT modes[] = {
|
||||||
{ { 4, 3 }, { 640, 480 } },
|
{ { 4, 3 }, { 640, 480 } },
|
||||||
|
@ -179,20 +184,77 @@ int main(int argc, char *argv[]) {
|
||||||
{ { 0, 0 }, { 0, 0 } }
|
{ { 0, 0 }, { 0, 0 } }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exeName = (char *)argv[0];
|
||||||
|
|
||||||
// For that dumb OS
|
// For that dumb OS
|
||||||
utilRedirectConsole();
|
utilRedirectConsole();
|
||||||
|
|
||||||
// Parse command line
|
if (!ap_init(&parser, argc, argv, options, 0)) {
|
||||||
while (true) {
|
utilDie("Out of memory parsing arguments.");
|
||||||
optionIndex = 0;
|
}
|
||||||
opterr = 0;
|
if (ap_error(&parser)) {
|
||||||
x = getopt_long(argc, argv, "cmnsfwhza:d:v:l:e:x:y:o:g:", options, &optionIndex);
|
utilDie("%s", ap_error(&parser));
|
||||||
|
}
|
||||||
|
|
||||||
// Out of options?
|
// Parse command line
|
||||||
if (x == -1) break;
|
argCount = ap_arguments(&parser);
|
||||||
|
for (argIndex=0; argIndex < ap_arguments(&parser); ++argIndex) {
|
||||||
|
|
||||||
|
code = ap_code(&parser, argIndex);
|
||||||
|
if (!code) break;
|
||||||
|
arg = ap_argument(&parser, argIndex);
|
||||||
|
|
||||||
// Handle options
|
// Handle options
|
||||||
switch (x) {
|
switch (code) {
|
||||||
|
|
||||||
|
// Aspect
|
||||||
|
case 'a':
|
||||||
|
if (aspectString) free(aspectString);
|
||||||
|
aspectString = strdup(arg);
|
||||||
|
argCount++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Show Calculated Frame File Values
|
||||||
|
case 'c':
|
||||||
|
_confShowCalculated = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Data Dir
|
||||||
|
case 'd':
|
||||||
|
if (_confDataDir) free(_confDataDir);
|
||||||
|
_confDataDir = strdup(arg);
|
||||||
|
argCount++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Effects Volume
|
||||||
|
case 'e':
|
||||||
|
_confVolumeNonVldp = atoi(arg);
|
||||||
|
argCount++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Full Screen
|
||||||
|
case 'f':
|
||||||
|
_confFullScreen = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Sinden Light Gun
|
||||||
|
case 'g':
|
||||||
|
if (sindenString) free(sindenString);
|
||||||
|
sindenString = strdup(arg);
|
||||||
|
argCount++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Help
|
||||||
|
case 'h':
|
||||||
|
showUsage(exeName, NULL);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Video Volume
|
||||||
|
case 'l':
|
||||||
|
_confVolumeVldp = atoi(arg);
|
||||||
|
argCount++;
|
||||||
|
break;
|
||||||
|
|
||||||
// No Mouse
|
// No Mouse
|
||||||
case 'm':
|
case 'm':
|
||||||
_confNoMouse = true;
|
_confNoMouse = true;
|
||||||
|
@ -203,19 +265,20 @@ int main(int argc, char *argv[]) {
|
||||||
_confNoStats = true;
|
_confNoStats = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// Overscan Zoom
|
||||||
|
case 'o':
|
||||||
|
_confScaleFactor = atoi(arg);
|
||||||
|
argCount++;
|
||||||
|
break;
|
||||||
|
|
||||||
// No Sound
|
// No Sound
|
||||||
case 's':
|
case 's':
|
||||||
_confNoSound = true;
|
_confNoSound = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Full Screen
|
// Trace
|
||||||
case 'f':
|
case 't':
|
||||||
_confFullScreen = true;
|
tracing = true;
|
||||||
break;
|
|
||||||
|
|
||||||
// Full Screen Windowed
|
|
||||||
case 'w':
|
|
||||||
_confFullScreenWindow = true;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Ugly Stretched Video
|
// Ugly Stretched Video
|
||||||
|
@ -226,60 +289,25 @@ int main(int argc, char *argv[]) {
|
||||||
// Video File
|
// Video File
|
||||||
case 'v':
|
case 'v':
|
||||||
if (_confVideoFile) free(_confVideoFile);
|
if (_confVideoFile) free(_confVideoFile);
|
||||||
_confVideoFile = strdup(optarg);
|
_confVideoFile = strdup(arg);
|
||||||
|
argCount++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Data Dir
|
// Full Screen Windowed
|
||||||
case 'd':
|
case 'w':
|
||||||
if (_confDataDir) free(_confDataDir);
|
_confFullScreenWindow = true;
|
||||||
_confDataDir = strdup(optarg);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Video Volume
|
|
||||||
case 'l':
|
|
||||||
_confVolumeVldp = atoi(optarg);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Effects Volume
|
|
||||||
case 'e':
|
|
||||||
_confVolumeNonVldp = atoi(optarg);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Overscan Zoom
|
|
||||||
case 'o':
|
|
||||||
_confScaleFactor = atoi(optarg);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Sinden Light Gun
|
|
||||||
case 'g':
|
|
||||||
if (sindenString) free(sindenString);
|
|
||||||
sindenString = strdup(optarg);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Aspect
|
|
||||||
case 'a':
|
|
||||||
if (aspectString) free(aspectString);
|
|
||||||
aspectString = strdup(optarg);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// X Resolution
|
// X Resolution
|
||||||
case 'x':
|
case 'x':
|
||||||
_confXResolution = atoi(optarg);
|
_confXResolution = atoi(arg);
|
||||||
|
argCount++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Y Resolution
|
// Y Resolution
|
||||||
case 'y':
|
case 'y':
|
||||||
_confYResolution = atoi(optarg);
|
_confYResolution = atoi(arg);
|
||||||
break;
|
argCount++;
|
||||||
|
|
||||||
// Help
|
|
||||||
case 'h':
|
|
||||||
showUsage(argv[0], NULL);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Trace
|
|
||||||
case 't':
|
|
||||||
tracing = true;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// No console output or splash screens
|
// No console output or splash screens
|
||||||
|
@ -287,15 +315,6 @@ int main(int argc, char *argv[]) {
|
||||||
_confNoConsole = true;
|
_confNoConsole = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Show Calculated Frame File Values
|
|
||||||
case 'c':
|
|
||||||
_confShowCalculated = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '?':
|
|
||||||
showUsage(argv[0], "Unknown option.");
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
abort(); // Something bad happened
|
abort(); // Something bad happened
|
||||||
break;
|
break;
|
||||||
|
@ -303,8 +322,8 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Did we get a filename or path to open?
|
// Did we get a filename or path to open?
|
||||||
if (optind != (argc - 1)) showUsage(argv[0], "No script file specified.");
|
if ((argc - argCount) != 1) showUsage(exeName, "No script file specified.");
|
||||||
_confScriptFile = strdup(argv[optind]);
|
_confScriptFile = strdup(argv[argCount]);
|
||||||
// Exists?
|
// Exists?
|
||||||
if (!utilFileExists(_confScriptFile)) {
|
if (!utilFileExists(_confScriptFile)) {
|
||||||
// Missing. Is a path?
|
// Missing. Is a path?
|
||||||
|
@ -327,7 +346,7 @@ int main(int argc, char *argv[]) {
|
||||||
_confScriptFile = NULL;
|
_confScriptFile = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!_confScriptFile) showUsage(argv[0], "Unable to locate script.");
|
if (!_confScriptFile) showUsage(exeName, "Unable to locate script.");
|
||||||
|
|
||||||
// Do we need to generate a video name?
|
// Do we need to generate a video name?
|
||||||
if (_confVideoFile) {
|
if (_confVideoFile) {
|
||||||
|
@ -363,7 +382,7 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!_confVideoFile) showUsage(argv[0], "Unable to locate video.");
|
if (!_confVideoFile) showUsage(exeName, "Unable to locate video.");
|
||||||
// Is it a framefile?
|
// Is it a framefile?
|
||||||
if (strncmp(utilGetFileExtension(_confVideoFile), "txt", 3) == 0) {
|
if (strncmp(utilGetFileExtension(_confVideoFile), "txt", 3) == 0) {
|
||||||
_confIsFrameFile = true;
|
_confIsFrameFile = true;
|
||||||
|
@ -390,7 +409,7 @@ int main(int argc, char *argv[]) {
|
||||||
free(temp);
|
free(temp);
|
||||||
temp = NULL;
|
temp = NULL;
|
||||||
}
|
}
|
||||||
if (!_confDataDir) showUsage(argv[0], "Unable to locate data directory.");
|
if (!_confDataDir) showUsage(exeName, "Unable to locate data directory.");
|
||||||
utilFixPathSeparators(&_confDataDir);
|
utilFixPathSeparators(&_confDataDir);
|
||||||
|
|
||||||
// Do they want tracing?
|
// Do they want tracing?
|
||||||
|
@ -402,18 +421,18 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do the full screen options make sense?
|
// Do the full screen options make sense?
|
||||||
if (_confFullScreen && _confFullScreenWindow) showUsage(argv[0], "Full Screen or Full Screen Windowed. Pick one.");
|
if (_confFullScreen && _confFullScreenWindow) showUsage(exeName, "Full Screen or Full Screen Windowed. Pick one.");
|
||||||
|
|
||||||
// Sane volume values?
|
// Sane volume values?
|
||||||
if ((_confVolumeVldp < 0) || (_confVolumeVldp > 100)) showUsage(argv[0], "Laserdisc volume must be between 0 and 100 percent.");
|
if ((_confVolumeVldp < 0) || (_confVolumeVldp > 100)) showUsage(exeName, "Laserdisc volume must be between 0 and 100 percent.");
|
||||||
if ((_confVolumeNonVldp < 0) || (_confVolumeNonVldp > 100)) showUsage(argv[0], "Effects volume must be between 0 and 100 percent.");
|
if ((_confVolumeNonVldp < 0) || (_confVolumeNonVldp > 100)) showUsage(exeName, "Effects volume must be between 0 and 100 percent.");
|
||||||
|
|
||||||
// Sane scale factor?
|
// Sane scale factor?
|
||||||
if ((_confScaleFactor < 50) || (_confScaleFactor > 100)) showUsage(argv[0], "Display scale must be between 50 and 100 percent.");
|
if ((_confScaleFactor < 50) || (_confScaleFactor > 100)) showUsage(exeName, "Display scale must be between 50 and 100 percent.");
|
||||||
|
|
||||||
// Sinden light gun?
|
// Sinden light gun?
|
||||||
if (sindenString) {
|
if (sindenString) {
|
||||||
if (_confScaleFactor != 100) showUsage(argv[0], "Cannot use --sindengun and --scalefactor together.");
|
if (_confScaleFactor != 100) showUsage(exeName, "Cannot use --sindengun and --scalefactor together.");
|
||||||
// Was it wrapped in quotes?
|
// Was it wrapped in quotes?
|
||||||
if ((sindenString[0] == '"') || (sindenString[0] == '\'')) {
|
if ((sindenString[0] == '"') || (sindenString[0] == '\'')) {
|
||||||
sindenString[0] = ' ';
|
sindenString[0] = ' ';
|
||||||
|
@ -428,10 +447,10 @@ int main(int argc, char *argv[]) {
|
||||||
while (temp != NULL) {
|
while (temp != NULL) {
|
||||||
_confSindenArgv[_confSindenArgc++] = atoi(temp);
|
_confSindenArgv[_confSindenArgc++] = atoi(temp);
|
||||||
temp = strtok(NULL, " ");
|
temp = strtok(NULL, " ");
|
||||||
if ((temp != NULL) && (_confSindenArgc > SINDEN_OPTION_COUNT)) showUsage(argv[0], "Too many arguments to --sindengun.");
|
if ((temp != NULL) && (_confSindenArgc > SINDEN_OPTION_COUNT)) showUsage(exeName, "Too many arguments to --sindengun.");
|
||||||
}
|
}
|
||||||
// Did we get a sane number of arguments?
|
// Did we get a sane number of arguments?
|
||||||
if ((_confSindenArgc != SINDEN_WHITE) && (_confSindenArgc != SINDEN_WHITE_BLACK) && (_confSindenArgc != SINDEN_CUSTOM_WHITE) && (_confSindenArgc != SINDEN_CUSTOM_WHITE_BLACK) && (_confSindenArgc != SINDEN_CUSTOM_WHITE_CUSTOM_BLACK)) showUsage(argv[0], "Bad argument count to --sindengun.");
|
if ((_confSindenArgc != SINDEN_WHITE) && (_confSindenArgc != SINDEN_WHITE_BLACK) && (_confSindenArgc != SINDEN_CUSTOM_WHITE) && (_confSindenArgc != SINDEN_CUSTOM_WHITE_BLACK) && (_confSindenArgc != SINDEN_CUSTOM_WHITE_CUSTOM_BLACK)) showUsage(exeName, "Bad argument count to --sindengun.");
|
||||||
free(sindenString);
|
free(sindenString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -474,7 +493,7 @@ int main(int argc, char *argv[]) {
|
||||||
x++;
|
x++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (bestRatioIndex < 0) showUsage(argv[0], "Unknown aspect ratio.");
|
if (bestRatioIndex < 0) showUsage(exeName, "Unknown aspect ratio.");
|
||||||
x = 0;
|
x = 0;
|
||||||
// Were both resolutions not specified?
|
// Were both resolutions not specified?
|
||||||
if ((_confXResolution <= 0) && (_confYResolution <= 0)) {
|
if ((_confXResolution <= 0) && (_confYResolution <= 0)) {
|
||||||
|
@ -523,9 +542,9 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Did we end up with a valid resolution?
|
// Did we end up with a valid resolution?
|
||||||
if (_confXResolution <= 0) showUsage(argv[0], "Unable to determine X resolution. (Is the Y value sane?)");
|
if (_confXResolution <= 0) showUsage(exeName, "Unable to determine X resolution. (Is the Y value sane?)");
|
||||||
if (_confYResolution <= 0) showUsage(argv[0], "Unable to determine Y resolution. (Is the X value sane?)");
|
if (_confYResolution <= 0) showUsage(exeName, "Unable to determine Y resolution. (Is the X value sane?)");
|
||||||
if ((_confXResolution > mode.w) || (_confYResolution > mode.h)) showUsage(argv[0], "Specified resolution is larger than the display.");
|
if ((_confXResolution > mode.w) || (_confYResolution > mode.h)) showUsage(exeName, "Specified resolution is larger than the display.");
|
||||||
|
|
||||||
// Init SDL_mixer ***FIX***
|
// Init SDL_mixer ***FIX***
|
||||||
flags = /* MIX_INIT_FLAC | */ MIX_INIT_MOD | /* MIX_INIT_MP3 | */ MIX_INIT_OGG | MIX_INIT_MID | MIX_INIT_OPUS;
|
flags = /* MIX_INIT_FLAC | */ MIX_INIT_MOD | /* MIX_INIT_MP3 | */ MIX_INIT_OGG | MIX_INIT_MID | MIX_INIT_OPUS;
|
||||||
|
|
|
@ -407,7 +407,7 @@ if [[ "${G_PLATFORM}" == "pi" ]]; then
|
||||||
MORE_LIBS="-Wl,-rpath-link,${G_SYSROOT}/opt/vc/lib -L${G_SYSROOT}/opt/vc/lib -lbcm_host -lpthread -lm -ldl -lrt"
|
MORE_LIBS="-Wl,-rpath-link,${G_SYSROOT}/opt/vc/lib -L${G_SYSROOT}/opt/vc/lib -lbcm_host -lpthread -lm -ldl -lrt"
|
||||||
PKG_CONFIG_PATH="${G_SYSROOT}/usr/lib/arm-linux-gnueabihf/pkgconfig" \
|
PKG_CONFIG_PATH="${G_SYSROOT}/usr/lib/arm-linux-gnueabihf/pkgconfig" \
|
||||||
PKG_CONFIG_SYSROOT_DIR="${G_SYSROOT}" \
|
PKG_CONFIG_SYSROOT_DIR="${G_SYSROOT}" \
|
||||||
autoBuild libSDL2.a SDL2 "--enable-video-kmsdrm" # --disable-video-x11 --disable-video-rpi --disable-video-opengl"
|
autoBuild libSDL2.a SDL2 "--enable-video-kmsdrm --disable-video-x11 --disable-video-rpi --disable-video-opengl --disable-video-wayland"
|
||||||
else
|
else
|
||||||
autoBuild libSDL2.a SDL2
|
autoBuild libSDL2.a SDL2
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -66,6 +66,17 @@ static {
|
||||||
QMAKE_EXTRA_TARGETS += BUILDTHIRD
|
QMAKE_EXTRA_TARGETS += BUILDTHIRD
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# === Arg_Parser ===
|
||||||
|
|
||||||
|
ARGPARSER_INCLUDES = \
|
||||||
|
$$PWD/thirdparty/arg_parser
|
||||||
|
|
||||||
|
ARGPARSER_HEADERS = \
|
||||||
|
$$PWD/thirdparty/arg_parser/carg_parser.h
|
||||||
|
|
||||||
|
ARGPARSER_SOURCES = \
|
||||||
|
$$PWD/thirdparty/arg_parser/carg_parser.c
|
||||||
|
|
||||||
# === ManyMouse ===
|
# === ManyMouse ===
|
||||||
|
|
||||||
MANYMOUSE_INCLUDES = \
|
MANYMOUSE_INCLUDES = \
|
||||||
|
@ -85,6 +96,7 @@ MANYMOUSE_SOURCES = \
|
||||||
# === SINGE ===
|
# === SINGE ===
|
||||||
|
|
||||||
QMAKE_CFLAGS += \
|
QMAKE_CFLAGS += \
|
||||||
|
-isystem $$ARGPARSER_INCLUDES \
|
||||||
-isystem $$MANYMOUSE_INCLUDES \
|
-isystem $$MANYMOUSE_INCLUDES \
|
||||||
-isystem $$PWD/../thirdparty-build/$$PLATFORM/$$BITNESS/installed/include
|
-isystem $$PWD/../thirdparty-build/$$PLATFORM/$$BITNESS/installed/include
|
||||||
|
|
||||||
|
@ -95,6 +107,7 @@ dynamic {
|
||||||
}
|
}
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
|
$$ARGPARSER_HEADERS \
|
||||||
$$MANYMOUSE_HEADERS \
|
$$MANYMOUSE_HEADERS \
|
||||||
frameFile.h \
|
frameFile.h \
|
||||||
stddclmr.h \
|
stddclmr.h \
|
||||||
|
@ -109,6 +122,7 @@ HEADERS += \
|
||||||
kangarooPunchLogo.h
|
kangarooPunchLogo.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
|
$$ARGPARSER_SOURCES \
|
||||||
$$MANYMOUSE_SOURCES \
|
$$MANYMOUSE_SOURCES \
|
||||||
frameFile.c \
|
frameFile.c \
|
||||||
util.c \
|
util.c \
|
||||||
|
|
|
@ -395,8 +395,8 @@ maintainer-clean-generic:
|
||||||
@echo "This command is intended for maintainers to use"
|
@echo "This command is intended for maintainers to use"
|
||||||
@echo "it deletes files that may require special tools to rebuild."
|
@echo "it deletes files that may require special tools to rebuild."
|
||||||
@HAVE_DOXYGEN_FALSE@uninstall-local:
|
@HAVE_DOXYGEN_FALSE@uninstall-local:
|
||||||
@HAVE_DOXYGEN_FALSE@clean-local:
|
|
||||||
@HAVE_DOXYGEN_FALSE@install-data-local:
|
@HAVE_DOXYGEN_FALSE@install-data-local:
|
||||||
|
@HAVE_DOXYGEN_FALSE@clean-local:
|
||||||
clean: clean-am
|
clean: clean-am
|
||||||
|
|
||||||
clean-am: clean-generic clean-libtool clean-local mostlyclean-am
|
clean-am: clean-generic clean-libtool clean-local mostlyclean-am
|
||||||
|
|
|
@ -1019,8 +1019,8 @@ maintainer-clean-generic:
|
||||||
@echo "This command is intended for maintainers to use"
|
@echo "This command is intended for maintainers to use"
|
||||||
@echo "it deletes files that may require special tools to rebuild."
|
@echo "it deletes files that may require special tools to rebuild."
|
||||||
@HAVE_DOXYGEN_FALSE@clean-local:
|
@HAVE_DOXYGEN_FALSE@clean-local:
|
||||||
@HAVE_DOXYGEN_FALSE@install-data-local:
|
|
||||||
@HAVE_DOXYGEN_FALSE@uninstall-local:
|
@HAVE_DOXYGEN_FALSE@uninstall-local:
|
||||||
|
@HAVE_DOXYGEN_FALSE@install-data-local:
|
||||||
clean: clean-am
|
clean: clean-am
|
||||||
|
|
||||||
clean-am: clean-generic clean-libLTLIBRARIES clean-libtool clean-local \
|
clean-am: clean-generic clean-libLTLIBRARIES clean-libtool clean-local \
|
||||||
|
|
1
singe/thirdparty/arg_parser/AUTHORS
vendored
Normal file
1
singe/thirdparty/arg_parser/AUTHORS
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Arg_parser was written by Antonio Diaz Diaz.
|
17
singe/thirdparty/arg_parser/COPYING
vendored
Normal file
17
singe/thirdparty/arg_parser/COPYING
vendored
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
Arg_parser - POSIX/GNU command line argument parser.
|
||||||
|
Copyright (C) Antonio Diaz Diaz.
|
||||||
|
|
||||||
|
This library is free software. 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 library 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.
|
107
singe/thirdparty/arg_parser/ChangeLog
vendored
Normal file
107
singe/thirdparty/arg_parser/ChangeLog
vendored
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
2019-01-01 Antonio Diaz Diaz <antonio@gnu.org>
|
||||||
|
|
||||||
|
* Version 1.14 released.
|
||||||
|
* The output of '--help' and the man pages have been expanded.
|
||||||
|
* configure: Accept appending to CFLAGS, 'CFLAGS+=OPTIONS'.
|
||||||
|
* configure: Accept appending to CXXFLAGS, 'CXXFLAGS+=OPTIONS'.
|
||||||
|
|
||||||
|
2017-03-19 Antonio Diaz Diaz <antonio@gnu.org>
|
||||||
|
|
||||||
|
* Version 1.13 released.
|
||||||
|
* arg_parser.h (Record): Added constructor for non-option arguments.
|
||||||
|
* arg_parser.cc (Arg_parser): Use 'const char *' for non_options.
|
||||||
|
|
||||||
|
2016-03-16 Antonio Diaz Diaz <antonio@gnu.org>
|
||||||
|
|
||||||
|
* Version 1.12 released.
|
||||||
|
* License changed to "2-clause BSD".
|
||||||
|
* configure: Avoid warning on some shells when testing for gcc.
|
||||||
|
* Makefile.in: Detect the existence of install-info.
|
||||||
|
|
||||||
|
2015-03-26 Antonio Diaz Diaz <antonio@gnu.org>
|
||||||
|
|
||||||
|
* Version 1.11 released.
|
||||||
|
* arg_parser.texi: C functions have been documented.
|
||||||
|
* Makefile.in: Added new targets 'install*-compress'.
|
||||||
|
|
||||||
|
2014-06-27 Antonio Diaz Diaz <antonio@gnu.org>
|
||||||
|
|
||||||
|
* Version 1.10 released.
|
||||||
|
* License changed to "GPL version 2 or later with link exception".
|
||||||
|
|
||||||
|
2014-05-26 Antonio Diaz Diaz <antonio@gnu.org>
|
||||||
|
|
||||||
|
* Version 1.9 released.
|
||||||
|
* configure: Options now accept a separate argument.
|
||||||
|
* arg_parser.texinfo: Renamed to arg_parser.texi.
|
||||||
|
|
||||||
|
2013-02-19 Antonio Diaz Diaz <ant_diaz@teleline.es>
|
||||||
|
|
||||||
|
* Version 1.8 released.
|
||||||
|
* Makefile.in: Added new target 'install-bin'.
|
||||||
|
|
||||||
|
2012-02-24 Antonio Diaz Diaz <ant_diaz@teleline.es>
|
||||||
|
|
||||||
|
* Version 1.7 released.
|
||||||
|
* Minor fixes.
|
||||||
|
* Changed quote characters in messages as advised by GNU Standards.
|
||||||
|
* configure: 'datadir' renamed to 'datarootdir'.
|
||||||
|
|
||||||
|
2012-01-01 Antonio Diaz Diaz <ant_diaz@teleline.es>
|
||||||
|
|
||||||
|
* Version 1.6 released.
|
||||||
|
* Minor fixes.
|
||||||
|
|
||||||
|
2011-01-12 Antonio Diaz Diaz <ant_diaz@teleline.es>
|
||||||
|
|
||||||
|
* Version 1.5 released.
|
||||||
|
* Minor fixes.
|
||||||
|
* C version: C99 style comments '//' have been converted to C89
|
||||||
|
style comments '/* */'.
|
||||||
|
* New files testsuite/check.sh, testsuite/test.txt.
|
||||||
|
|
||||||
|
2010-03-11 Antonio Diaz Diaz <ant_diaz@teleline.es>
|
||||||
|
|
||||||
|
* Version 1.4 released.
|
||||||
|
* carg_parser.h: Removed 'typedefs' from C version.
|
||||||
|
* Added link exception to license.
|
||||||
|
* The manual has been improved.
|
||||||
|
* Makefile.in: Added '--name' option to help2man invocation.
|
||||||
|
|
||||||
|
2009-07-10 Antonio Diaz Diaz <ant_diaz@teleline.es>
|
||||||
|
|
||||||
|
* Version 1.3 released.
|
||||||
|
* carg_parser.c (ap_resize_buffer): Return 'void*' instead of 'char'.
|
||||||
|
|
||||||
|
2009-01-15 Antonio Diaz Diaz <ant_diaz@teleline.es>
|
||||||
|
|
||||||
|
* Version 1.2 released.
|
||||||
|
* arg_parser.cc (parse_short_option): Rename 'code' to 'c'.
|
||||||
|
* carg_parser.c (ap_resize_buffer): Change 'char**' arg to 'void*'.
|
||||||
|
|
||||||
|
2008-02-24 Antonio Diaz Diaz <ant_diaz@teleline.es>
|
||||||
|
|
||||||
|
* Version 1.1 released.
|
||||||
|
* Added C version.
|
||||||
|
* Options requiring an argument no longer accept an empty argument.
|
||||||
|
|
||||||
|
2007-06-29 Antonio Diaz Diaz <ant_diaz@teleline.es>
|
||||||
|
|
||||||
|
* Version 1.0 released.
|
||||||
|
* License updated to "GPL version 3 or later with link exception".
|
||||||
|
|
||||||
|
2006-11-04 Antonio Diaz Diaz <ant_diaz@teleline.es>
|
||||||
|
|
||||||
|
* Version 0.2 released.
|
||||||
|
* Some fixes made to 'configure' script.
|
||||||
|
|
||||||
|
2006-03-29 Antonio Diaz Diaz <ant_diaz@teleline.es>
|
||||||
|
|
||||||
|
* Version 0.1 released.
|
||||||
|
|
||||||
|
|
||||||
|
Copyright (C) 2006-2019 Antonio Diaz Diaz.
|
||||||
|
|
||||||
|
This file is a collection of facts, and thus it is not copyrightable,
|
||||||
|
but just in case, you have unlimited permission to copy, distribute and
|
||||||
|
modify it.
|
64
singe/thirdparty/arg_parser/INSTALL
vendored
Normal file
64
singe/thirdparty/arg_parser/INSTALL
vendored
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
Requirements
|
||||||
|
------------
|
||||||
|
You will need a C++ compiler and a C compiler.
|
||||||
|
I use gcc 5.3.0 and 4.1.2, but the code should compile with any standards
|
||||||
|
compliant compiler.
|
||||||
|
Gcc is available at http://gcc.gnu.org.
|
||||||
|
|
||||||
|
|
||||||
|
Procedure
|
||||||
|
---------
|
||||||
|
1. Unpack the archive if you have not done so already:
|
||||||
|
|
||||||
|
tar -xf arg_parser[version].tar.lz
|
||||||
|
or
|
||||||
|
lzip -cd arg_parser[version].tar.lz | tar -xf -
|
||||||
|
|
||||||
|
This creates the directory ./arg_parser[version] containing the source from
|
||||||
|
the main archive.
|
||||||
|
|
||||||
|
2. Change to arg_parser directory and run configure.
|
||||||
|
(Try 'configure --help' for usage instructions).
|
||||||
|
|
||||||
|
cd arg_parser[version]
|
||||||
|
./configure
|
||||||
|
|
||||||
|
3. Run make.
|
||||||
|
|
||||||
|
make
|
||||||
|
|
||||||
|
4. Optionally, type 'make check' to run the tests that come with arg_parser.
|
||||||
|
|
||||||
|
5. Type 'make install' to install the program and any data files and
|
||||||
|
documentation.
|
||||||
|
|
||||||
|
Or type 'make install-compress', which additionally compresses the
|
||||||
|
info manual and the man page after installation. (Installing
|
||||||
|
compressed docs may become the default in the future).
|
||||||
|
|
||||||
|
You can install only the program, the info manual or the man page by
|
||||||
|
typing 'make install-bin', 'make install-info' or 'make install-man'
|
||||||
|
respectively.
|
||||||
|
|
||||||
|
|
||||||
|
Another way
|
||||||
|
-----------
|
||||||
|
You can also compile arg_parser into a separate directory.
|
||||||
|
To do this, you must use a version of 'make' that supports the 'VPATH'
|
||||||
|
variable, such as GNU 'make'. 'cd' to the directory where you want the
|
||||||
|
object files and executables to go and run the 'configure' script.
|
||||||
|
'configure' automatically checks for the source code in '.', in '..' and
|
||||||
|
in the directory that 'configure' is in.
|
||||||
|
|
||||||
|
'configure' recognizes the option '--srcdir=DIR' to control where to
|
||||||
|
look for the sources. Usually 'configure' can determine that directory
|
||||||
|
automatically.
|
||||||
|
|
||||||
|
After running 'configure', you can run 'make' and 'make install' as
|
||||||
|
explained above.
|
||||||
|
|
||||||
|
|
||||||
|
Copyright (C) 2006-2019 Antonio Diaz Diaz.
|
||||||
|
|
||||||
|
This file is free documentation: you have unlimited permission to copy,
|
||||||
|
distribute and modify it.
|
9
singe/thirdparty/arg_parser/NEWS
vendored
Normal file
9
singe/thirdparty/arg_parser/NEWS
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
Changes in version 1.14:
|
||||||
|
|
||||||
|
The output of '--help' and the man pages have been expanded.
|
||||||
|
|
||||||
|
The configure script now accepts appending options to CFLAGS using the
|
||||||
|
syntax 'CFLAGS+=OPTIONS'.
|
||||||
|
|
||||||
|
The configure script now accepts appending options to CXXFLAGS using the
|
||||||
|
syntax 'CXXFLAGS+=OPTIONS'.
|
32
singe/thirdparty/arg_parser/README
vendored
Normal file
32
singe/thirdparty/arg_parser/README
vendored
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
Description
|
||||||
|
|
||||||
|
Arg_parser is an argument parser that follows POSIX and GNU conventions for
|
||||||
|
command line arguments. There exist C++ and C versions of Arg_parser. The
|
||||||
|
C++ version is implemented as a C++ class, while the C version is
|
||||||
|
implemented as a single struct plus associated functions. Both are simpler,
|
||||||
|
easier to use, and safer than 'getopt_long'.
|
||||||
|
|
||||||
|
For maximum stability, Arg_parser is self-contained. It extracts all the
|
||||||
|
information it needs from its arguments to avoid refering to them later.
|
||||||
|
This avoids index-out-of-bounds errors.
|
||||||
|
|
||||||
|
Arg_parser does not modify its arguments, nor uses any global variables. So
|
||||||
|
you may create more than one parser in your program if you need or want to.
|
||||||
|
|
||||||
|
The C++ version of Arg_parser can also parse options from configuration
|
||||||
|
files.
|
||||||
|
|
||||||
|
To use Arg_parser in your own programs simply copy the files 'arg_parser.h'
|
||||||
|
and 'arg_parser.cc' (or 'carg_parser.h' and 'carg_parser.c' for the
|
||||||
|
C version) in your source tree. See also the file 'main.cc' ('cmain.c') for
|
||||||
|
an example of use.
|
||||||
|
|
||||||
|
|
||||||
|
Copyright (C) 2006-2019 Antonio Diaz Diaz.
|
||||||
|
|
||||||
|
This file is free documentation: you have unlimited permission to copy,
|
||||||
|
distribute and modify it.
|
||||||
|
|
||||||
|
The file Makefile.in is a data file used by configure to produce the
|
||||||
|
Makefile. It has the same copyright owner and permissions that configure
|
||||||
|
itself.
|
196
singe/thirdparty/arg_parser/arg_parser.cc
vendored
Normal file
196
singe/thirdparty/arg_parser/arg_parser.cc
vendored
Normal file
|
@ -0,0 +1,196 @@
|
||||||
|
/* Arg_parser - POSIX/GNU command line argument parser. (C++ version)
|
||||||
|
Copyright (C) 2006-2019 Antonio Diaz Diaz.
|
||||||
|
|
||||||
|
This library is free software. 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 library 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "arg_parser.h"
|
||||||
|
|
||||||
|
|
||||||
|
bool Arg_parser::parse_long_option( const char * const opt, const char * const arg,
|
||||||
|
const Option options[], int & argind )
|
||||||
|
{
|
||||||
|
unsigned len;
|
||||||
|
int index = -1;
|
||||||
|
bool exact = false, ambig = false;
|
||||||
|
|
||||||
|
for( len = 0; opt[len+2] && opt[len+2] != '='; ++len ) ;
|
||||||
|
|
||||||
|
// Test all long options for either exact match or abbreviated matches.
|
||||||
|
for( int i = 0; options[i].code != 0; ++i )
|
||||||
|
if( options[i].name && std::strncmp( options[i].name, &opt[2], len ) == 0 )
|
||||||
|
{
|
||||||
|
if( std::strlen( options[i].name ) == len ) // Exact match found
|
||||||
|
{ index = i; exact = true; break; }
|
||||||
|
else if( index < 0 ) index = i; // First nonexact match found
|
||||||
|
else if( options[index].code != options[i].code ||
|
||||||
|
options[index].has_arg != options[i].has_arg )
|
||||||
|
ambig = true; // Second or later nonexact match found
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ambig && !exact )
|
||||||
|
{
|
||||||
|
error_ = "option '"; error_ += opt; error_ += "' is ambiguous";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( index < 0 ) // nothing found
|
||||||
|
{
|
||||||
|
error_ = "unrecognized option '"; error_ += opt; error_ += '\'';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
++argind;
|
||||||
|
data.push_back( Record( options[index].code ) );
|
||||||
|
|
||||||
|
if( opt[len+2] ) // '--<long_option>=<argument>' syntax
|
||||||
|
{
|
||||||
|
if( options[index].has_arg == no )
|
||||||
|
{
|
||||||
|
error_ = "option '--"; error_ += options[index].name;
|
||||||
|
error_ += "' doesn't allow an argument";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if( options[index].has_arg == yes && !opt[len+3] )
|
||||||
|
{
|
||||||
|
error_ = "option '--"; error_ += options[index].name;
|
||||||
|
error_ += "' requires an argument";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
data.back().argument = &opt[len+3];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( options[index].has_arg == yes )
|
||||||
|
{
|
||||||
|
if( !arg || !arg[0] )
|
||||||
|
{
|
||||||
|
error_ = "option '--"; error_ += options[index].name;
|
||||||
|
error_ += "' requires an argument";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
++argind; data.back().argument = arg;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Arg_parser::parse_short_option( const char * const opt, const char * const arg,
|
||||||
|
const Option options[], int & argind )
|
||||||
|
{
|
||||||
|
int cind = 1; // character index in opt
|
||||||
|
|
||||||
|
while( cind > 0 )
|
||||||
|
{
|
||||||
|
int index = -1;
|
||||||
|
const unsigned char c = opt[cind];
|
||||||
|
|
||||||
|
if( c != 0 )
|
||||||
|
for( int i = 0; options[i].code; ++i )
|
||||||
|
if( c == options[i].code )
|
||||||
|
{ index = i; break; }
|
||||||
|
|
||||||
|
if( index < 0 )
|
||||||
|
{
|
||||||
|
error_ = "invalid option -- '"; error_ += c; error_ += '\'';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.push_back( Record( c ) );
|
||||||
|
if( opt[++cind] == 0 ) { ++argind; cind = 0; } // opt finished
|
||||||
|
|
||||||
|
if( options[index].has_arg != no && cind > 0 && opt[cind] )
|
||||||
|
{
|
||||||
|
data.back().argument = &opt[cind]; ++argind; cind = 0;
|
||||||
|
}
|
||||||
|
else if( options[index].has_arg == yes )
|
||||||
|
{
|
||||||
|
if( !arg || !arg[0] )
|
||||||
|
{
|
||||||
|
error_ = "option requires an argument -- '"; error_ += c;
|
||||||
|
error_ += '\'';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
data.back().argument = arg; ++argind; cind = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Arg_parser::Arg_parser( const int argc, const char * const argv[],
|
||||||
|
const Option options[], const bool in_order )
|
||||||
|
{
|
||||||
|
if( argc < 2 || !argv || !options ) return;
|
||||||
|
|
||||||
|
std::vector< const char * > non_options; // skipped non-options
|
||||||
|
int argind = 1; // index in argv
|
||||||
|
|
||||||
|
while( argind < argc )
|
||||||
|
{
|
||||||
|
const unsigned char ch1 = argv[argind][0];
|
||||||
|
const unsigned char ch2 = ch1 ? argv[argind][1] : 0;
|
||||||
|
|
||||||
|
if( ch1 == '-' && ch2 ) // we found an option
|
||||||
|
{
|
||||||
|
const char * const opt = argv[argind];
|
||||||
|
const char * const arg = ( argind + 1 < argc ) ? argv[argind+1] : 0;
|
||||||
|
if( ch2 == '-' )
|
||||||
|
{
|
||||||
|
if( !argv[argind][2] ) { ++argind; break; } // we found "--"
|
||||||
|
else if( !parse_long_option( opt, arg, options, argind ) ) break;
|
||||||
|
}
|
||||||
|
else if( !parse_short_option( opt, arg, options, argind ) ) break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( in_order ) data.push_back( Record( argv[argind++] ) );
|
||||||
|
else non_options.push_back( argv[argind++] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( error_.size() ) data.clear();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for( unsigned i = 0; i < non_options.size(); ++i )
|
||||||
|
data.push_back( Record( non_options[i] ) );
|
||||||
|
while( argind < argc )
|
||||||
|
data.push_back( Record( argv[argind++] ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Arg_parser::Arg_parser( const char * const opt, const char * const arg,
|
||||||
|
const Option options[] )
|
||||||
|
{
|
||||||
|
if( !opt || !opt[0] || !options ) return;
|
||||||
|
|
||||||
|
if( opt[0] == '-' && opt[1] ) // we found an option
|
||||||
|
{
|
||||||
|
int argind = 1; // dummy
|
||||||
|
if( opt[1] == '-' )
|
||||||
|
{ if( opt[2] ) parse_long_option( opt, arg, options, argind ); }
|
||||||
|
else
|
||||||
|
parse_short_option( opt, arg, options, argind );
|
||||||
|
if( error_.size() ) data.clear();
|
||||||
|
}
|
||||||
|
else data.push_back( Record( opt ) );
|
||||||
|
}
|
98
singe/thirdparty/arg_parser/arg_parser.h
vendored
Normal file
98
singe/thirdparty/arg_parser/arg_parser.h
vendored
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
/* Arg_parser - POSIX/GNU command line argument parser. (C++ version)
|
||||||
|
Copyright (C) 2006-2019 Antonio Diaz Diaz.
|
||||||
|
|
||||||
|
This library is free software. 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 library 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Arg_parser reads the arguments in 'argv' and creates a number of
|
||||||
|
option codes, option arguments and non-option arguments.
|
||||||
|
|
||||||
|
In case of error, 'error' returns a non-empty error message.
|
||||||
|
|
||||||
|
'options' is an array of 'struct Option' terminated by an element
|
||||||
|
containing a code which is zero. A null name means a short-only
|
||||||
|
option. A code value outside the unsigned char range means a
|
||||||
|
long-only option.
|
||||||
|
|
||||||
|
Arg_parser normally makes it appear as if all the option arguments
|
||||||
|
were specified before all the non-option arguments for the purposes
|
||||||
|
of parsing, even if the user of your program intermixed option and
|
||||||
|
non-option arguments. If you want the arguments in the exact order
|
||||||
|
the user typed them, call 'Arg_parser' with 'in_order' = true.
|
||||||
|
|
||||||
|
The argument '--' terminates all options; any following arguments are
|
||||||
|
treated as non-option arguments, even if they begin with a hyphen.
|
||||||
|
|
||||||
|
The syntax for optional option arguments is '-<short_option><argument>'
|
||||||
|
(without whitespace), or '--<long_option>=<argument>'.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Arg_parser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum Has_arg { no, yes, maybe };
|
||||||
|
|
||||||
|
struct Option
|
||||||
|
{
|
||||||
|
int code; // Short option letter or code ( code != 0 )
|
||||||
|
const char * name; // Long option name (maybe null)
|
||||||
|
Has_arg has_arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct Record
|
||||||
|
{
|
||||||
|
int code;
|
||||||
|
std::string argument;
|
||||||
|
explicit Record( const int c ) : code( c ) {}
|
||||||
|
explicit Record( const char * const arg ) : code( 0 ), argument( arg ) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string error_;
|
||||||
|
std::vector< Record > data;
|
||||||
|
|
||||||
|
bool parse_long_option( const char * const opt, const char * const arg,
|
||||||
|
const Option options[], int & argind );
|
||||||
|
bool parse_short_option( const char * const opt, const char * const arg,
|
||||||
|
const Option options[], int & argind );
|
||||||
|
|
||||||
|
public:
|
||||||
|
Arg_parser( const int argc, const char * const argv[],
|
||||||
|
const Option options[], const bool in_order = false );
|
||||||
|
|
||||||
|
// Restricted constructor. Parses a single token and argument (if any)
|
||||||
|
Arg_parser( const char * const opt, const char * const arg,
|
||||||
|
const Option options[] );
|
||||||
|
|
||||||
|
const std::string & error() const { return error_; }
|
||||||
|
|
||||||
|
// The number of arguments parsed (may be different from argc)
|
||||||
|
int arguments() const { return data.size(); }
|
||||||
|
|
||||||
|
// If code( i ) is 0, argument( i ) is a non-option.
|
||||||
|
// Else argument( i ) is the option's argument (or empty).
|
||||||
|
int code( const int i ) const
|
||||||
|
{
|
||||||
|
if( i >= 0 && i < arguments() ) return data[i].code;
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string & argument( const int i ) const
|
||||||
|
{
|
||||||
|
if( i >= 0 && i < arguments() ) return data[i].argument;
|
||||||
|
else return error_;
|
||||||
|
}
|
||||||
|
};
|
285
singe/thirdparty/arg_parser/carg_parser.c
vendored
Normal file
285
singe/thirdparty/arg_parser/carg_parser.c
vendored
Normal file
|
@ -0,0 +1,285 @@
|
||||||
|
/* Arg_parser - POSIX/GNU command line argument parser. (C version)
|
||||||
|
Copyright (C) 2006-2019 Antonio Diaz Diaz.
|
||||||
|
|
||||||
|
This library is free software. 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 library 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "carg_parser.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* assure at least a minimum size for buffer 'buf' */
|
||||||
|
static void * ap_resize_buffer( void * buf, const int min_size )
|
||||||
|
{
|
||||||
|
if( buf ) buf = realloc( buf, min_size );
|
||||||
|
else buf = malloc( min_size );
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char push_back_record( struct Arg_parser * const ap,
|
||||||
|
const int code, const char * const argument )
|
||||||
|
{
|
||||||
|
const int len = strlen( argument );
|
||||||
|
struct ap_Record * p;
|
||||||
|
void * tmp = ap_resize_buffer( ap->data,
|
||||||
|
( ap->data_size + 1 ) * sizeof (struct ap_Record) );
|
||||||
|
if( !tmp ) return 0;
|
||||||
|
ap->data = (struct ap_Record *)tmp;
|
||||||
|
p = &(ap->data[ap->data_size]);
|
||||||
|
p->code = code;
|
||||||
|
p->argument = 0;
|
||||||
|
tmp = ap_resize_buffer( p->argument, len + 1 );
|
||||||
|
if( !tmp ) return 0;
|
||||||
|
p->argument = (char *)tmp;
|
||||||
|
strncpy( p->argument, argument, len + 1 );
|
||||||
|
++ap->data_size;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char add_error( struct Arg_parser * const ap, const char * const msg )
|
||||||
|
{
|
||||||
|
const int len = strlen( msg );
|
||||||
|
void * tmp = ap_resize_buffer( ap->error, ap->error_size + len + 1 );
|
||||||
|
if( !tmp ) return 0;
|
||||||
|
ap->error = (char *)tmp;
|
||||||
|
strncpy( ap->error + ap->error_size, msg, len + 1 );
|
||||||
|
ap->error_size += len;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void free_data( struct Arg_parser * const ap )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for( i = 0; i < ap->data_size; ++i ) free( ap->data[i].argument );
|
||||||
|
if( ap->data ) { free( ap->data ); ap->data = 0; }
|
||||||
|
ap->data_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char parse_long_option( struct Arg_parser * const ap,
|
||||||
|
const char * const opt, const char * const arg,
|
||||||
|
const struct ap_Option options[],
|
||||||
|
int * const argindp )
|
||||||
|
{
|
||||||
|
unsigned len;
|
||||||
|
int index = -1, i;
|
||||||
|
char exact = 0, ambig = 0;
|
||||||
|
|
||||||
|
for( len = 0; opt[len+2] && opt[len+2] != '='; ++len ) ;
|
||||||
|
|
||||||
|
/* Test all long options for either exact match or abbreviated matches. */
|
||||||
|
for( i = 0; options[i].code != 0; ++i )
|
||||||
|
if( options[i].name && strncmp( options[i].name, &opt[2], len ) == 0 )
|
||||||
|
{
|
||||||
|
if( strlen( options[i].name ) == len ) /* Exact match found */
|
||||||
|
{ index = i; exact = 1; break; }
|
||||||
|
else if( index < 0 ) index = i; /* First nonexact match found */
|
||||||
|
else if( options[index].code != options[i].code ||
|
||||||
|
options[index].has_arg != options[i].has_arg )
|
||||||
|
ambig = 1; /* Second or later nonexact match found */
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ambig && !exact )
|
||||||
|
{
|
||||||
|
add_error( ap, "option '" ); add_error( ap, opt );
|
||||||
|
add_error( ap, "' is ambiguous" );
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( index < 0 ) /* nothing found */
|
||||||
|
{
|
||||||
|
add_error( ap, "unrecognized option '" ); add_error( ap, opt );
|
||||||
|
add_error( ap, "'" );
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
++*argindp;
|
||||||
|
|
||||||
|
if( opt[len+2] ) /* '--<long_option>=<argument>' syntax */
|
||||||
|
{
|
||||||
|
if( options[index].has_arg == ap_no )
|
||||||
|
{
|
||||||
|
add_error( ap, "option '--" ); add_error( ap, options[index].name );
|
||||||
|
add_error( ap, "' doesn't allow an argument" );
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if( options[index].has_arg == ap_yes && !opt[len+3] )
|
||||||
|
{
|
||||||
|
add_error( ap, "option '--" ); add_error( ap, options[index].name );
|
||||||
|
add_error( ap, "' requires an argument" );
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return push_back_record( ap, options[index].code, &opt[len+3] );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( options[index].has_arg == ap_yes )
|
||||||
|
{
|
||||||
|
if( !arg || !arg[0] )
|
||||||
|
{
|
||||||
|
add_error( ap, "option '--" ); add_error( ap, options[index].name );
|
||||||
|
add_error( ap, "' requires an argument" );
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
++*argindp;
|
||||||
|
return push_back_record( ap, options[index].code, arg );
|
||||||
|
}
|
||||||
|
|
||||||
|
return push_back_record( ap, options[index].code, "" );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char parse_short_option( struct Arg_parser * const ap,
|
||||||
|
const char * const opt, const char * const arg,
|
||||||
|
const struct ap_Option options[],
|
||||||
|
int * const argindp )
|
||||||
|
{
|
||||||
|
int cind = 1; /* character index in opt */
|
||||||
|
|
||||||
|
while( cind > 0 )
|
||||||
|
{
|
||||||
|
int index = -1, i;
|
||||||
|
const unsigned char code = opt[cind];
|
||||||
|
char code_str[2];
|
||||||
|
code_str[0] = code; code_str[1] = 0;
|
||||||
|
|
||||||
|
if( code != 0 )
|
||||||
|
for( i = 0; options[i].code; ++i )
|
||||||
|
if( code == options[i].code )
|
||||||
|
{ index = i; break; }
|
||||||
|
|
||||||
|
if( index < 0 )
|
||||||
|
{
|
||||||
|
add_error( ap, "invalid option -- '" ); add_error( ap, code_str );
|
||||||
|
add_error( ap, "'" );
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( opt[++cind] == 0 ) { ++*argindp; cind = 0; } /* opt finished */
|
||||||
|
|
||||||
|
if( options[index].has_arg != ap_no && cind > 0 && opt[cind] )
|
||||||
|
{
|
||||||
|
if( !push_back_record( ap, code, &opt[cind] ) ) return 0;
|
||||||
|
++*argindp; cind = 0;
|
||||||
|
}
|
||||||
|
else if( options[index].has_arg == ap_yes )
|
||||||
|
{
|
||||||
|
if( !arg || !arg[0] )
|
||||||
|
{
|
||||||
|
add_error( ap, "option requires an argument -- '" );
|
||||||
|
add_error( ap, code_str ); add_error( ap, "'" );
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
++*argindp; cind = 0;
|
||||||
|
if( !push_back_record( ap, code, arg ) ) return 0;
|
||||||
|
}
|
||||||
|
else if( !push_back_record( ap, code, "" ) ) return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char ap_init( struct Arg_parser * const ap,
|
||||||
|
const int argc, const char * const argv[],
|
||||||
|
const struct ap_Option options[], const char in_order )
|
||||||
|
{
|
||||||
|
const char ** non_options = 0; /* skipped non-options */
|
||||||
|
int non_options_size = 0; /* number of skipped non-options */
|
||||||
|
int argind = 1; /* index in argv */
|
||||||
|
int i;
|
||||||
|
|
||||||
|
ap->data = 0;
|
||||||
|
ap->error = 0;
|
||||||
|
ap->data_size = 0;
|
||||||
|
ap->error_size = 0;
|
||||||
|
if( argc < 2 || !argv || !options ) return 1;
|
||||||
|
|
||||||
|
while( argind < argc )
|
||||||
|
{
|
||||||
|
const unsigned char ch1 = argv[argind][0];
|
||||||
|
const unsigned char ch2 = ch1 ? argv[argind][1] : 0;
|
||||||
|
|
||||||
|
if( ch1 == '-' && ch2 ) /* we found an option */
|
||||||
|
{
|
||||||
|
const char * const opt = argv[argind];
|
||||||
|
const char * const arg = ( argind + 1 < argc ) ? argv[argind+1] : 0;
|
||||||
|
if( ch2 == '-' )
|
||||||
|
{
|
||||||
|
if( !argv[argind][2] ) { ++argind; break; } /* we found "--" */
|
||||||
|
else if( !parse_long_option( ap, opt, arg, options, &argind ) ) return 0;
|
||||||
|
}
|
||||||
|
else if( !parse_short_option( ap, opt, arg, options, &argind ) ) return 0;
|
||||||
|
if( ap->error ) break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( in_order )
|
||||||
|
{ if( !push_back_record( ap, 0, argv[argind++] ) ) return 0; }
|
||||||
|
else
|
||||||
|
{
|
||||||
|
void * tmp = ap_resize_buffer( non_options,
|
||||||
|
( non_options_size + 1 ) * sizeof *non_options );
|
||||||
|
if( !tmp ) return 0;
|
||||||
|
non_options = (const char **)tmp;
|
||||||
|
non_options[non_options_size++] = argv[argind++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( ap->error ) free_data( ap );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for( i = 0; i < non_options_size; ++i )
|
||||||
|
if( !push_back_record( ap, 0, non_options[i] ) ) return 0;
|
||||||
|
while( argind < argc )
|
||||||
|
if( !push_back_record( ap, 0, argv[argind++] ) ) return 0;
|
||||||
|
}
|
||||||
|
if( non_options ) free( non_options );
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ap_free( struct Arg_parser * const ap )
|
||||||
|
{
|
||||||
|
free_data( ap );
|
||||||
|
if( ap->error ) { free( ap->error ); ap->error = 0; }
|
||||||
|
ap->error_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char * ap_error( const struct Arg_parser * const ap )
|
||||||
|
{ return ap->error; }
|
||||||
|
|
||||||
|
|
||||||
|
int ap_arguments( const struct Arg_parser * const ap )
|
||||||
|
{ return ap->data_size; }
|
||||||
|
|
||||||
|
|
||||||
|
int ap_code( const struct Arg_parser * const ap, const int i )
|
||||||
|
{
|
||||||
|
if( i >= 0 && i < ap_arguments( ap ) ) return ap->data[i].code;
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char * ap_argument( const struct Arg_parser * const ap, const int i )
|
||||||
|
{
|
||||||
|
if( i >= 0 && i < ap_arguments( ap ) ) return ap->data[i].argument;
|
||||||
|
else return "";
|
||||||
|
}
|
93
singe/thirdparty/arg_parser/carg_parser.h
vendored
Normal file
93
singe/thirdparty/arg_parser/carg_parser.h
vendored
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
/* Arg_parser - POSIX/GNU command line argument parser. (C version)
|
||||||
|
Copyright (C) 2006-2019 Antonio Diaz Diaz.
|
||||||
|
|
||||||
|
This library is free software. 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 library 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Arg_parser reads the arguments in 'argv' and creates a number of
|
||||||
|
option codes, option arguments and non-option arguments.
|
||||||
|
|
||||||
|
In case of error, 'ap_error' returns a non-null pointer to an error
|
||||||
|
message.
|
||||||
|
|
||||||
|
'options' is an array of 'struct ap_Option' terminated by an element
|
||||||
|
containing a code which is zero. A null name means a short-only
|
||||||
|
option. A code value outside the unsigned char range means a
|
||||||
|
long-only option.
|
||||||
|
|
||||||
|
Arg_parser normally makes it appear as if all the option arguments
|
||||||
|
were specified before all the non-option arguments for the purposes
|
||||||
|
of parsing, even if the user of your program intermixed option and
|
||||||
|
non-option arguments. If you want the arguments in the exact order
|
||||||
|
the user typed them, call 'ap_init' with 'in_order' = true.
|
||||||
|
|
||||||
|
The argument '--' terminates all options; any following arguments are
|
||||||
|
treated as non-option arguments, even if they begin with a hyphen.
|
||||||
|
|
||||||
|
The syntax for optional option arguments is '-<short_option><argument>'
|
||||||
|
(without whitespace), or '--<long_option>=<argument>'.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum ap_Has_arg { ap_no, ap_yes, ap_maybe };
|
||||||
|
|
||||||
|
struct ap_Option
|
||||||
|
{
|
||||||
|
int code; /* Short option letter or code ( code != 0 ) */
|
||||||
|
const char * name; /* Long option name (maybe null) */
|
||||||
|
enum ap_Has_arg has_arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct ap_Record
|
||||||
|
{
|
||||||
|
int code;
|
||||||
|
char * argument;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct Arg_parser
|
||||||
|
{
|
||||||
|
struct ap_Record * data;
|
||||||
|
char * error;
|
||||||
|
int data_size;
|
||||||
|
int error_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
char ap_init( struct Arg_parser * const ap,
|
||||||
|
const int argc, const char * const argv[],
|
||||||
|
const struct ap_Option options[], const char in_order );
|
||||||
|
|
||||||
|
void ap_free( struct Arg_parser * const ap );
|
||||||
|
|
||||||
|
const char * ap_error( const struct Arg_parser * const ap );
|
||||||
|
|
||||||
|
/* The number of arguments parsed (may be different from argc) */
|
||||||
|
int ap_arguments( const struct Arg_parser * const ap );
|
||||||
|
|
||||||
|
/* If ap_code( i ) is 0, ap_argument( i ) is a non-option.
|
||||||
|
Else ap_argument( i ) is the option's argument (or empty). */
|
||||||
|
int ap_code( const struct Arg_parser * const ap, const int i );
|
||||||
|
|
||||||
|
const char * ap_argument( const struct Arg_parser * const ap, const int i );
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
182
singe/thirdparty/arg_parser/cmain.c
vendored
Normal file
182
singe/thirdparty/arg_parser/cmain.c
vendored
Normal file
|
@ -0,0 +1,182 @@
|
||||||
|
/* Arg_parser - POSIX/GNU command line argument parser. (C version)
|
||||||
|
Copyright (C) 2006-2019 Antonio Diaz Diaz.
|
||||||
|
|
||||||
|
This program is free software: you have unlimited permission to
|
||||||
|
copy, distribute and modify it.
|
||||||
|
|
||||||
|
This program 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.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
Exit status: 0 for a normal exit, 1 for environmental problems
|
||||||
|
(file not found, invalid flags, I/O errors, etc), 2 to indicate a
|
||||||
|
corrupt or invalid input file, 3 for an internal consistency error
|
||||||
|
(eg, bug) which caused arg_parser to panic.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "carg_parser.h"
|
||||||
|
|
||||||
|
|
||||||
|
static const char * const program_name = "arg_parser";
|
||||||
|
static const char * const program_year = "2019";
|
||||||
|
static const char * invocation_name = 0;
|
||||||
|
|
||||||
|
|
||||||
|
void show_help( const char verbose )
|
||||||
|
{
|
||||||
|
printf( "Arg_parser - POSIX/GNU command line argument parser. (C version)\n"
|
||||||
|
"\nArg_parser is an argument parser that follows POSIX and GNU conventions for\n"
|
||||||
|
"command line arguments. There exist C++ and C versions of Arg_parser. The\n"
|
||||||
|
"C++ version is implemented as a C++ class, while the C version is\n"
|
||||||
|
"implemented as a single struct plus associated functions. Both are simpler,\n"
|
||||||
|
"easier to use, and safer than 'getopt_long'.\n"
|
||||||
|
"\nFor maximum stability, Arg_parser is self-contained. It extracts all the\n"
|
||||||
|
"information it needs from its arguments to avoid refering to them later.\n"
|
||||||
|
"This avoids index-out-of-bounds errors.\n"
|
||||||
|
"\nArg_parser does not modify its arguments, nor uses any global variables. So\n"
|
||||||
|
"you may create more than one parser in your program if you need or want to.\n"
|
||||||
|
"\nThe C++ version of Arg_parser can also parse options from configuration\n"
|
||||||
|
"files.\n"
|
||||||
|
"\nTo use Arg_parser in your own programs simply copy the files 'carg_parser.h'\n"
|
||||||
|
"and 'carg_parser.c' in your source tree. See also the file 'cmain.c' for an\n"
|
||||||
|
"example of use.\n"
|
||||||
|
"\nUsage: %s [options]\n", invocation_name );
|
||||||
|
printf( "\nOptions:\n"
|
||||||
|
" -h, --help display this help and exit\n"
|
||||||
|
" -V, --version output version information and exit\n"
|
||||||
|
" -a, --append example of option with no argument\n"
|
||||||
|
" -b, --block=<arg> example of option with required argument\n"
|
||||||
|
" -c, --casual[=<arg>] example of option with optional argument\n"
|
||||||
|
" -o <arg> example of short only option\n"
|
||||||
|
" --orphan example of long only option\n"
|
||||||
|
" -q, --quiet quiet operation\n"
|
||||||
|
" -u, --uncaught example of intentional bug\n"
|
||||||
|
" -v, --verbose verbose operation\n" );
|
||||||
|
if( verbose )
|
||||||
|
{
|
||||||
|
printf( " -H, --hidden example of hidden option (shown with -v -h)\n" );
|
||||||
|
}
|
||||||
|
printf( "\nReport bugs to arg-parser-bug@nongnu.org\n"
|
||||||
|
"Arg_parser home page: http://www.nongnu.org/arg-parser/arg_parser.html\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void show_version()
|
||||||
|
{
|
||||||
|
printf( "%s %s\n", program_name, PROGVERSION );
|
||||||
|
printf( "Copyright (C) %s Antonio Diaz Diaz.\n", program_year );
|
||||||
|
printf( "License 2-clause BSD.\n"
|
||||||
|
"This is free software: you are free to change and redistribute it.\n"
|
||||||
|
"There is NO WARRANTY, to the extent permitted by law.\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void show_error( const char * const msg, const int errcode, const char help )
|
||||||
|
{
|
||||||
|
if( msg && msg[0] )
|
||||||
|
fprintf( stderr, "%s: %s%s%s\n", program_name, msg,
|
||||||
|
( errcode > 0 ) ? ": " : "",
|
||||||
|
( errcode > 0 ) ? strerror( errcode ) : "" );
|
||||||
|
if( help )
|
||||||
|
fprintf( stderr, "Try '%s --help' for more information.\n",
|
||||||
|
invocation_name );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void internal_error( const char * const msg )
|
||||||
|
{
|
||||||
|
fprintf( stderr, "%s: internal error: %s\n", program_name, msg );
|
||||||
|
exit( 3 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char * optname( const int code, const struct ap_Option options[] )
|
||||||
|
{
|
||||||
|
static char buf[2] = "?";
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if( code != 0 )
|
||||||
|
for( i = 0; options[i].code; ++i )
|
||||||
|
if( code == options[i].code )
|
||||||
|
{ if( options[i].name ) return options[i].name; else break; }
|
||||||
|
if( code > 0 && code < 256 ) buf[0] = code; else buf[0] = '?';
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main( const int argc, const char * const argv[] )
|
||||||
|
{
|
||||||
|
char verbose = 0;
|
||||||
|
const struct ap_Option options[] =
|
||||||
|
{
|
||||||
|
{ 'a', "append", ap_no },
|
||||||
|
{ 'b', "block", ap_yes },
|
||||||
|
{ 'c', "casual", ap_maybe },
|
||||||
|
{ 'h', "help", ap_no },
|
||||||
|
{ 'H', "hidden", ap_no },
|
||||||
|
{ 'o', 0, ap_yes },
|
||||||
|
{ 'q', "quiet", ap_no },
|
||||||
|
{ 'u', "uncaught", ap_no },
|
||||||
|
{ 'v', "verbose", ap_no },
|
||||||
|
{ 'V', "version", ap_no },
|
||||||
|
{ 256, "orphan", ap_no },
|
||||||
|
{ 0, 0, ap_no } };
|
||||||
|
|
||||||
|
struct Arg_parser parser;
|
||||||
|
int argind;
|
||||||
|
invocation_name = argv[0];
|
||||||
|
|
||||||
|
if( !ap_init( &parser, argc, argv, options, 0 ) )
|
||||||
|
{ show_error( "Not enough memory.", 0, 0 ); return 1; }
|
||||||
|
if( ap_error( &parser ) ) /* bad option */
|
||||||
|
{ show_error( ap_error( &parser ), 0, 1 ); return 1; }
|
||||||
|
|
||||||
|
for( argind = 0; argind < ap_arguments( &parser ); ++argind )
|
||||||
|
{
|
||||||
|
const int code = ap_code( &parser, argind );
|
||||||
|
if( !code ) break; /* no more options */
|
||||||
|
switch( code )
|
||||||
|
{
|
||||||
|
case 'a': break; /* example, do nothing */
|
||||||
|
case 'b': break; /* example, do nothing */
|
||||||
|
case 'c': break; /* example, do nothing */
|
||||||
|
case 'h': show_help( verbose ); return 0;
|
||||||
|
case 'H': break; /* example, do nothing */
|
||||||
|
case 'o': break; /* example, do nothing */
|
||||||
|
case 'q': verbose = 0; break;
|
||||||
|
/* case 'u': break; */ /* intentionally not caught */
|
||||||
|
case 'v': verbose = 1; break;
|
||||||
|
case 'V': show_version(); return 0;
|
||||||
|
case 256: break; /* example, do nothing */
|
||||||
|
default : internal_error( "uncaught option." );
|
||||||
|
}
|
||||||
|
} /* end process options */
|
||||||
|
|
||||||
|
for( argind = 0; argind < ap_arguments( &parser ); ++argind )
|
||||||
|
{
|
||||||
|
const int code = ap_code( &parser, argind );
|
||||||
|
const char * const arg = ap_argument( &parser, argind );
|
||||||
|
if( code ) /* option */
|
||||||
|
{
|
||||||
|
const char * const name = optname( code, options );
|
||||||
|
if( !name[1] )
|
||||||
|
printf( "option '-%c'", name[0] );
|
||||||
|
else
|
||||||
|
printf( "option '--%s'", name );
|
||||||
|
if( arg[0] )
|
||||||
|
printf( " with argument '%s'", arg );
|
||||||
|
}
|
||||||
|
else /* non-option */
|
||||||
|
printf( "non-option argument '%s'", arg );
|
||||||
|
fputc( '\n', stdout );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !ap_arguments( &parser ) ) fputs( "Hello, world!\n", stdout );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
215
singe/thirdparty/arg_parser/configure
vendored
Executable file
215
singe/thirdparty/arg_parser/configure
vendored
Executable file
|
@ -0,0 +1,215 @@
|
||||||
|
#! /bin/sh
|
||||||
|
# configure script for Arg_parser - POSIX/GNU command line argument parser.
|
||||||
|
# Copyright (C) 2006-2019 Antonio Diaz Diaz.
|
||||||
|
#
|
||||||
|
# This configure script is free software: you have unlimited permission
|
||||||
|
# to copy, distribute and modify it.
|
||||||
|
|
||||||
|
pkgname=arg_parser
|
||||||
|
pkgversion=1.14
|
||||||
|
progname=arg_parser
|
||||||
|
srctrigger=doc/${pkgname}.texi
|
||||||
|
|
||||||
|
# clear some things potentially inherited from environment.
|
||||||
|
LC_ALL=C
|
||||||
|
export LC_ALL
|
||||||
|
srcdir=
|
||||||
|
prefix=/usr/local
|
||||||
|
exec_prefix='$(prefix)'
|
||||||
|
bindir='$(exec_prefix)/bin'
|
||||||
|
datarootdir='$(prefix)/share'
|
||||||
|
infodir='$(datarootdir)/info'
|
||||||
|
mandir='$(datarootdir)/man'
|
||||||
|
CC=gcc
|
||||||
|
CXX=g++
|
||||||
|
CPPFLAGS=
|
||||||
|
CFLAGS='-Wall -W -O2'
|
||||||
|
CXXFLAGS='-Wall -W -O2'
|
||||||
|
LDFLAGS=
|
||||||
|
|
||||||
|
# checking whether we are using GNU C.
|
||||||
|
/bin/sh -c "${CC} --version" > /dev/null 2>&1 ||
|
||||||
|
{
|
||||||
|
CC=cc
|
||||||
|
CFLAGS=-O2
|
||||||
|
}
|
||||||
|
|
||||||
|
# checking whether we are using GNU C++.
|
||||||
|
/bin/sh -c "${CXX} --version" > /dev/null 2>&1 ||
|
||||||
|
{
|
||||||
|
CXX=c++
|
||||||
|
CXXFLAGS=-O2
|
||||||
|
}
|
||||||
|
|
||||||
|
# Loop over all args
|
||||||
|
args=
|
||||||
|
no_create=
|
||||||
|
while [ $# != 0 ] ; do
|
||||||
|
|
||||||
|
# Get the first arg, and shuffle
|
||||||
|
option=$1 ; arg2=no
|
||||||
|
shift
|
||||||
|
|
||||||
|
# Add the argument quoted to args
|
||||||
|
args="${args} \"${option}\""
|
||||||
|
|
||||||
|
# Split out the argument for options that take them
|
||||||
|
case ${option} in
|
||||||
|
*=*) optarg=`echo ${option} | sed -e 's,^[^=]*=,,;s,/$,,'` ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Process the options
|
||||||
|
case ${option} in
|
||||||
|
--help | -h)
|
||||||
|
echo "Usage: $0 [OPTION]... [VAR=VALUE]..."
|
||||||
|
echo
|
||||||
|
echo "To assign makefile variables (e.g., CC, CXX...), specify them as"
|
||||||
|
echo "arguments to configure in the form VAR=VALUE."
|
||||||
|
echo
|
||||||
|
echo "Options and variables: [defaults in brackets]"
|
||||||
|
echo " -h, --help display this help and exit"
|
||||||
|
echo " -V, --version output version information and exit"
|
||||||
|
echo " --srcdir=DIR find the sources in DIR [. or ..]"
|
||||||
|
echo " --prefix=DIR install into DIR [${prefix}]"
|
||||||
|
echo " --exec-prefix=DIR base directory for arch-dependent files [${exec_prefix}]"
|
||||||
|
echo " --bindir=DIR user executables directory [${bindir}]"
|
||||||
|
echo " --datarootdir=DIR base directory for doc and data [${datarootdir}]"
|
||||||
|
echo " --infodir=DIR info files directory [${infodir}]"
|
||||||
|
echo " --mandir=DIR man pages directory [${mandir}]"
|
||||||
|
echo " CC=COMPILER C compiler to use [${CC}]"
|
||||||
|
echo " CXX=COMPILER C++ compiler to use [${CXX}]"
|
||||||
|
echo " CPPFLAGS=OPTIONS command line options for the preprocessor [${CPPFLAGS}]"
|
||||||
|
echo " CFLAGS=OPTIONS command line options for the C compiler [${CFLAGS}]"
|
||||||
|
echo " CFLAGS+=OPTIONS append options to the current value of CFLAGS"
|
||||||
|
echo " CXXFLAGS=OPTIONS command line options for the C++ compiler [${CXXFLAGS}]"
|
||||||
|
echo " CXXFLAGS+=OPTIONS append options to the current value of CXXFLAGS"
|
||||||
|
echo " LDFLAGS=OPTIONS command line options for the linker [${LDFLAGS}]"
|
||||||
|
echo
|
||||||
|
exit 0 ;;
|
||||||
|
--version | -V)
|
||||||
|
echo "Configure script for ${pkgname} version ${pkgversion}"
|
||||||
|
exit 0 ;;
|
||||||
|
--srcdir) srcdir=$1 ; arg2=yes ;;
|
||||||
|
--prefix) prefix=$1 ; arg2=yes ;;
|
||||||
|
--exec-prefix) exec_prefix=$1 ; arg2=yes ;;
|
||||||
|
--bindir) bindir=$1 ; arg2=yes ;;
|
||||||
|
--datarootdir) datarootdir=$1 ; arg2=yes ;;
|
||||||
|
--infodir) infodir=$1 ; arg2=yes ;;
|
||||||
|
--mandir) mandir=$1 ; arg2=yes ;;
|
||||||
|
|
||||||
|
--srcdir=*) srcdir=${optarg} ;;
|
||||||
|
--prefix=*) prefix=${optarg} ;;
|
||||||
|
--exec-prefix=*) exec_prefix=${optarg} ;;
|
||||||
|
--bindir=*) bindir=${optarg} ;;
|
||||||
|
--datarootdir=*) datarootdir=${optarg} ;;
|
||||||
|
--infodir=*) infodir=${optarg} ;;
|
||||||
|
--mandir=*) mandir=${optarg} ;;
|
||||||
|
--no-create) no_create=yes ;;
|
||||||
|
|
||||||
|
CC=*) CC=${optarg} ;;
|
||||||
|
CXX=*) CXX=${optarg} ;;
|
||||||
|
CPPFLAGS=*) CPPFLAGS=${optarg} ;;
|
||||||
|
CFLAGS=*) CFLAGS=${optarg} ;;
|
||||||
|
CFLAGS+=*) CFLAGS="${CFLAGS} ${optarg}" ;;
|
||||||
|
CXXFLAGS=*) CXXFLAGS=${optarg} ;;
|
||||||
|
CXXFLAGS+=*) CXXFLAGS="${CXXFLAGS} ${optarg}" ;;
|
||||||
|
LDFLAGS=*) LDFLAGS=${optarg} ;;
|
||||||
|
|
||||||
|
--*)
|
||||||
|
echo "configure: WARNING: unrecognized option: '${option}'" 1>&2 ;;
|
||||||
|
*=* | *-*-*) ;;
|
||||||
|
*)
|
||||||
|
echo "configure: unrecognized option: '${option}'" 1>&2
|
||||||
|
echo "Try 'configure --help' for more information." 1>&2
|
||||||
|
exit 1 ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Check if the option took a separate argument
|
||||||
|
if [ "${arg2}" = yes ] ; then
|
||||||
|
if [ $# != 0 ] ; then args="${args} \"$1\"" ; shift
|
||||||
|
else echo "configure: Missing argument to '${option}'" 1>&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Find the source files, if location was not specified.
|
||||||
|
srcdirtext=
|
||||||
|
if [ -z "${srcdir}" ] ; then
|
||||||
|
srcdirtext="or . or .." ; srcdir=.
|
||||||
|
if [ ! -r "${srcdir}/${srctrigger}" ] ; then srcdir=.. ; fi
|
||||||
|
if [ ! -r "${srcdir}/${srctrigger}" ] ; then
|
||||||
|
## the sed command below emulates the dirname command
|
||||||
|
srcdir=`echo $0 | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -r "${srcdir}/${srctrigger}" ] ; then
|
||||||
|
echo "configure: Can't find sources in ${srcdir} ${srcdirtext}" 1>&2
|
||||||
|
echo "configure: (At least ${srctrigger} is missing)." 1>&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set srcdir to . if that's what it is.
|
||||||
|
if [ "`pwd`" = "`cd "${srcdir}" ; pwd`" ] ; then srcdir=. ; fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
if [ -z "${no_create}" ] ; then
|
||||||
|
echo "creating config.status"
|
||||||
|
rm -f config.status
|
||||||
|
cat > config.status << EOF
|
||||||
|
#! /bin/sh
|
||||||
|
# This file was generated automatically by configure. Don't edit.
|
||||||
|
# Run this file to recreate the current configuration.
|
||||||
|
#
|
||||||
|
# This script is free software: you have unlimited permission
|
||||||
|
# to copy, distribute and modify it.
|
||||||
|
|
||||||
|
exec /bin/sh $0 ${args} --no-create
|
||||||
|
EOF
|
||||||
|
chmod +x config.status
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "creating Makefile"
|
||||||
|
echo "VPATH = ${srcdir}"
|
||||||
|
echo "prefix = ${prefix}"
|
||||||
|
echo "exec_prefix = ${exec_prefix}"
|
||||||
|
echo "bindir = ${bindir}"
|
||||||
|
echo "datarootdir = ${datarootdir}"
|
||||||
|
echo "infodir = ${infodir}"
|
||||||
|
echo "mandir = ${mandir}"
|
||||||
|
echo "CC = ${CC}"
|
||||||
|
echo "CXX = ${CXX}"
|
||||||
|
echo "CPPFLAGS = ${CPPFLAGS}"
|
||||||
|
echo "CFLAGS = ${CFLAGS}"
|
||||||
|
echo "CXXFLAGS = ${CXXFLAGS}"
|
||||||
|
echo "LDFLAGS = ${LDFLAGS}"
|
||||||
|
rm -f Makefile
|
||||||
|
cat > Makefile << EOF
|
||||||
|
# Makefile for Arg_parser - POSIX/GNU command line argument parser.
|
||||||
|
# Copyright (C) 2006-2019 Antonio Diaz Diaz.
|
||||||
|
# This file was generated automatically by configure. Don't edit.
|
||||||
|
#
|
||||||
|
# This Makefile is free software: you have unlimited permission
|
||||||
|
# to copy, distribute and modify it.
|
||||||
|
|
||||||
|
pkgname = ${pkgname}
|
||||||
|
pkgversion = ${pkgversion}
|
||||||
|
progname = ${progname}
|
||||||
|
VPATH = ${srcdir}
|
||||||
|
prefix = ${prefix}
|
||||||
|
exec_prefix = ${exec_prefix}
|
||||||
|
bindir = ${bindir}
|
||||||
|
datarootdir = ${datarootdir}
|
||||||
|
infodir = ${infodir}
|
||||||
|
mandir = ${mandir}
|
||||||
|
CC = ${CC}
|
||||||
|
CXX = ${CXX}
|
||||||
|
CPPFLAGS = ${CPPFLAGS}
|
||||||
|
CFLAGS = ${CFLAGS}
|
||||||
|
CXXFLAGS = ${CXXFLAGS}
|
||||||
|
LDFLAGS = ${LDFLAGS}
|
||||||
|
EOF
|
||||||
|
cat "${srcdir}/Makefile.in" >> Makefile
|
||||||
|
|
||||||
|
echo "OK. Now you can run make."
|
82
singe/thirdparty/arg_parser/doc/arg_parser.1
vendored
Normal file
82
singe/thirdparty/arg_parser/doc/arg_parser.1
vendored
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.1.
|
||||||
|
.TH ARG_PARSER "1" "January 2019" "arg_parser 1.14" "User Commands"
|
||||||
|
.SH NAME
|
||||||
|
arg_parser \- test program for the Arg_parser argument parser
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B arg_parser
|
||||||
|
[\fI\,options\/\fR]
|
||||||
|
.SH DESCRIPTION
|
||||||
|
Arg_parser \- POSIX/GNU command line argument parser. (C++ version)
|
||||||
|
.PP
|
||||||
|
Arg_parser is an argument parser that follows POSIX and GNU conventions for
|
||||||
|
command line arguments. There exist C++ and C versions of Arg_parser. The
|
||||||
|
C++ version is implemented as a C++ class, while the C version is
|
||||||
|
implemented as a single struct plus associated functions. Both are simpler,
|
||||||
|
easier to use, and safer than 'getopt_long'.
|
||||||
|
.PP
|
||||||
|
For maximum stability, Arg_parser is self\-contained. It extracts all the
|
||||||
|
information it needs from its arguments to avoid refering to them later.
|
||||||
|
This avoids index\-out\-of\-bounds errors.
|
||||||
|
.PP
|
||||||
|
Arg_parser does not modify its arguments, nor uses any global variables. So
|
||||||
|
you may create more than one parser in your program if you need or want to.
|
||||||
|
.PP
|
||||||
|
The C++ version of Arg_parser can also parse options from configuration
|
||||||
|
files.
|
||||||
|
.PP
|
||||||
|
To use Arg_parser in your own programs simply copy the files 'arg_parser.h'
|
||||||
|
and 'arg_parser.cc' in your source tree. See also the file 'main.cc' for an
|
||||||
|
example of use.
|
||||||
|
.SH OPTIONS
|
||||||
|
.TP
|
||||||
|
\fB\-h\fR, \fB\-\-help\fR
|
||||||
|
display this help and exit
|
||||||
|
.TP
|
||||||
|
\fB\-V\fR, \fB\-\-version\fR
|
||||||
|
output version information and exit
|
||||||
|
.TP
|
||||||
|
\fB\-a\fR, \fB\-\-append\fR
|
||||||
|
example of option with no argument
|
||||||
|
.TP
|
||||||
|
\fB\-b\fR, \fB\-\-block=\fR<arg>
|
||||||
|
example of option with required argument
|
||||||
|
.TP
|
||||||
|
\fB\-c\fR, \fB\-\-casual[=\fR<arg>]
|
||||||
|
example of option with optional argument
|
||||||
|
.TP
|
||||||
|
\fB\-o\fR <arg>
|
||||||
|
example of short only option
|
||||||
|
.TP
|
||||||
|
\fB\-\-orphan\fR
|
||||||
|
example of long only option
|
||||||
|
.TP
|
||||||
|
\fB\-q\fR, \fB\-\-quiet\fR
|
||||||
|
quiet operation
|
||||||
|
.TP
|
||||||
|
\fB\-u\fR, \fB\-\-uncaught\fR
|
||||||
|
example of intentional bug
|
||||||
|
.TP
|
||||||
|
\fB\-v\fR, \fB\-\-verbose\fR
|
||||||
|
verbose operation
|
||||||
|
.SH "REPORTING BUGS"
|
||||||
|
Report bugs to arg\-parser\-bug@nongnu.org
|
||||||
|
.br
|
||||||
|
Arg_parser home page: http://www.nongnu.org/arg\-parser/arg_parser.html
|
||||||
|
.SH COPYRIGHT
|
||||||
|
Copyright \(co 2019 Antonio Diaz Diaz.
|
||||||
|
License 2\-clause BSD.
|
||||||
|
.br
|
||||||
|
This is free software: you are free to change and redistribute it.
|
||||||
|
There is NO WARRANTY, to the extent permitted by law.
|
||||||
|
.SH "SEE ALSO"
|
||||||
|
The full documentation for
|
||||||
|
.B arg_parser
|
||||||
|
is maintained as a Texinfo manual. If the
|
||||||
|
.B info
|
||||||
|
and
|
||||||
|
.B arg_parser
|
||||||
|
programs are properly installed at your site, the command
|
||||||
|
.IP
|
||||||
|
.B info arg_parser
|
||||||
|
.PP
|
||||||
|
should give you access to the complete manual.
|
309
singe/thirdparty/arg_parser/doc/arg_parser.info
vendored
Normal file
309
singe/thirdparty/arg_parser/doc/arg_parser.info
vendored
Normal file
|
@ -0,0 +1,309 @@
|
||||||
|
This is arg_parser.info, produced by makeinfo version 4.13+ from
|
||||||
|
arg_parser.texi.
|
||||||
|
|
||||||
|
INFO-DIR-SECTION Basics
|
||||||
|
START-INFO-DIR-ENTRY
|
||||||
|
* Arg_parser: (arg_parser). A POSIX/GNU command line argument parser
|
||||||
|
END-INFO-DIR-ENTRY
|
||||||
|
|
||||||
|
|
||||||
|
File: arg_parser.info, Node: Top, Next: Introduction, Up: (dir)
|
||||||
|
|
||||||
|
Arg_parser Manual
|
||||||
|
*****************
|
||||||
|
|
||||||
|
This manual is for Arg_parser (version 1.14, 1 January 2019).
|
||||||
|
|
||||||
|
* Menu:
|
||||||
|
|
||||||
|
* Introduction:: Purpose and features of Arg_parser
|
||||||
|
* Argument syntax:: By convention, options start with a hyphen
|
||||||
|
* Initialization:: Parsing arguments and reporting errors
|
||||||
|
* Using Arg_parser:: Reading the parsed options and arguments
|
||||||
|
* C version:: Using the C version of Arg_parser
|
||||||
|
* Problems:: Reporting bugs
|
||||||
|
* Concept index:: Index of concepts
|
||||||
|
|
||||||
|
|
||||||
|
Copyright (C) 2006-2019 Antonio Diaz Diaz.
|
||||||
|
|
||||||
|
This manual is free documentation: you have unlimited permission to
|
||||||
|
copy, distribute and modify it.
|
||||||
|
|
||||||
|
|
||||||
|
File: arg_parser.info, Node: Introduction, Next: Argument syntax, Prev: Top, Up: Top
|
||||||
|
|
||||||
|
1 Introduction
|
||||||
|
**************
|
||||||
|
|
||||||
|
Arg_parser is an argument parser that follows POSIX and GNU conventions
|
||||||
|
for command line arguments. There exist C++ and C versions of
|
||||||
|
Arg_parser. The C++ version is implemented as a C++ class, while the C
|
||||||
|
version is implemented as a single struct plus associated functions.
|
||||||
|
Both are simpler, easier to use, and safer than 'getopt_long'.
|
||||||
|
|
||||||
|
For maximum stability, Arg_parser is self-contained. It extracts all
|
||||||
|
the information it needs from its arguments to avoid refering to them
|
||||||
|
later. This avoids index-out-of-bounds errors.
|
||||||
|
|
||||||
|
Arg_parser does not modify its arguments, nor uses any global
|
||||||
|
variables. So you may create more than one parser in your program if
|
||||||
|
you need or want to.
|
||||||
|
|
||||||
|
The C++ version of Arg_parser can also parse options from
|
||||||
|
configuration files.
|
||||||
|
|
||||||
|
|
||||||
|
File: arg_parser.info, Node: Argument syntax, Next: Initialization, Prev: Introduction, Up: Top
|
||||||
|
|
||||||
|
2 Syntax of command line arguments
|
||||||
|
**********************************
|
||||||
|
|
||||||
|
POSIX recommends these conventions for command line arguments.
|
||||||
|
'Arg_parser' makes it easy to implement them.
|
||||||
|
|
||||||
|
* A command line argument is a option if it begins with a hyphen
|
||||||
|
delimiter ('-').
|
||||||
|
|
||||||
|
* Multiple options may follow a hyphen delimiter in a single token
|
||||||
|
if the options don't take arguments. Thus, '-abc' is equivalent to
|
||||||
|
'-a -b -c'.
|
||||||
|
|
||||||
|
* Option names are single alphanumeric characters.
|
||||||
|
|
||||||
|
* Certain options require an argument.
|
||||||
|
|
||||||
|
* An option and its argument may or may not appear as separate
|
||||||
|
tokens. (In other words, the whitespace separating them is
|
||||||
|
optional). Thus, '-o foo' and '-ofoo' are equivalent.
|
||||||
|
|
||||||
|
* Options typically precede other non-option arguments.
|
||||||
|
|
||||||
|
'Arg_parser' normally makes it appear as if all the option
|
||||||
|
arguments were specified before all the non-option arguments for
|
||||||
|
the purposes of parsing, even if the user of your program
|
||||||
|
intermixed option and non-option arguments. If you want the
|
||||||
|
arguments in the exact order the user typed them, call
|
||||||
|
'Arg_parser' with IN_ORDER = true.
|
||||||
|
|
||||||
|
* The argument '--' terminates all options; any following arguments
|
||||||
|
are treated as non-option arguments, even if they begin with a
|
||||||
|
hyphen.
|
||||||
|
|
||||||
|
* A token consisting of a single hyphen character is interpreted as
|
||||||
|
an ordinary non-option argument. By convention, it is used to
|
||||||
|
specify input from or output to the standard input and output
|
||||||
|
streams.
|
||||||
|
|
||||||
|
* Options may be supplied in any order, or appear multiple times.
|
||||||
|
The interpretation is left up to the particular application
|
||||||
|
program.
|
||||||
|
|
||||||
|
* GNU adds "long options" to these conventions. Long options consist
|
||||||
|
of '--' followed by a name made of alphanumeric characters and
|
||||||
|
hyphens. Option names are typically one to three words long, with
|
||||||
|
hyphens to separate words. Users can abbreviate the option names
|
||||||
|
as long as the abbreviations are unique.
|
||||||
|
|
||||||
|
* The syntax for optional option arguments is
|
||||||
|
'-<short_option><argument>' (without whitespace), or
|
||||||
|
'--<long_option>=<argument>'.
|
||||||
|
|
||||||
|
|
||||||
|
File: arg_parser.info, Node: Initialization, Next: Using Arg_parser, Prev: Argument syntax, Up: Top
|
||||||
|
|
||||||
|
3 Parsing arguments and reporting errors
|
||||||
|
****************************************
|
||||||
|
|
||||||
|
To use Arg_parser in your own programs first copy the files
|
||||||
|
'arg_parser.h' and 'arg_parser.cc' in your source tree. See also the
|
||||||
|
file 'main.cc' for an example of use.
|
||||||
|
|
||||||
|
The Arg_parser class has two constructors; one to parse command line
|
||||||
|
arguments from ARGV, and the other to parse a single token from a
|
||||||
|
configuration file or other source.
|
||||||
|
|
||||||
|
-- Data Type: struct Option
|
||||||
|
This structure describes a single option for the sake of
|
||||||
|
'Arg_parser'. The argument OPTIONS must be an array of these
|
||||||
|
structures, one for each option. Terminate the array with an
|
||||||
|
element containing a code which is zero.
|
||||||
|
|
||||||
|
'struct Option' has the following members:
|
||||||
|
|
||||||
|
'int code'
|
||||||
|
This member is the code that identifies the option, normally
|
||||||
|
the short-option character. Must be different from 0. A code
|
||||||
|
value outside the unsigned char range means a long-only
|
||||||
|
option.
|
||||||
|
|
||||||
|
'const char * name'
|
||||||
|
This member is the long option name. It is a zero-terminated
|
||||||
|
string. A null or empty name means a short-only option.
|
||||||
|
|
||||||
|
'enum Has_arg has_arg'
|
||||||
|
This member says whether the option takes an argument. It has
|
||||||
|
three valid values: 'no', 'yes' and 'maybe'.
|
||||||
|
|
||||||
|
-- Function: Arg_parser ( const int ARGC, const char * const ARGV[],
|
||||||
|
const Option OPTIONS[], const bool IN_ORDER = false )
|
||||||
|
Reads the arguments in ARGV and parses all options, option
|
||||||
|
arguments and non-option arguments contained in them. In case of
|
||||||
|
error, 'error().size()' will be non-zero.
|
||||||
|
|
||||||
|
-- Function: Arg_parser ( const char * const OPT, const char * const
|
||||||
|
ARG, const Option OPTIONS[] )
|
||||||
|
Restricted constructor. Parses a single token (plus an optional
|
||||||
|
second token in case an argument is needed for a parsed option).
|
||||||
|
Can be used to parse options from a configuration file one at a
|
||||||
|
time. Be warned that a single token may produce an undefined
|
||||||
|
number of short options. In case of error, 'error().size()' will
|
||||||
|
be non-zero.
|
||||||
|
|
||||||
|
-- Function: const std::string & error () const
|
||||||
|
Use this funtion to verify that the arguments have been correctly
|
||||||
|
parsed by the constructor. If there was an error parsing the
|
||||||
|
arguments, 'error' returns a non-empty error message explaining
|
||||||
|
the cause.
|
||||||
|
|
||||||
|
|
||||||
|
File: arg_parser.info, Node: Using Arg_parser, Next: C version, Prev: Initialization, Up: Top
|
||||||
|
|
||||||
|
4 Using the 'Arg_parser' class
|
||||||
|
******************************
|
||||||
|
|
||||||
|
After a successful call to the constructor, which must be verified by
|
||||||
|
calling 'error', the parsed options and arguments can be accessed by
|
||||||
|
means of the following functions:
|
||||||
|
|
||||||
|
-- Function: int arguments () const
|
||||||
|
This function returns the number of options and non-option
|
||||||
|
arguments parsed. This number is normally different from argc.
|
||||||
|
|
||||||
|
-- Function: int code ( const int I ) const
|
||||||
|
This function returns the code of the option at position I. Valid
|
||||||
|
values for I range from 0 to 'arguments() - 1'. If the returned
|
||||||
|
code is non-zero, 'argument(I)' is the option's argument (or is
|
||||||
|
empty if the option does not have an argument). If the returned
|
||||||
|
code is zero, 'argument(I)' is a non-option argument.
|
||||||
|
|
||||||
|
-- Function: const std::string & argument ( const int I ) const
|
||||||
|
This function returns the argument at position I. It may be the
|
||||||
|
argument of an option or a non-option argument, depending on the
|
||||||
|
value returned by 'code(I)'. Valid values for I range from 0 to
|
||||||
|
'arguments() - 1'.
|
||||||
|
|
||||||
|
|
||||||
|
File: arg_parser.info, Node: C version, Next: Problems, Prev: Using Arg_parser, Up: Top
|
||||||
|
|
||||||
|
5 Using the C version of Arg_parser
|
||||||
|
***********************************
|
||||||
|
|
||||||
|
To use the C version of Arg_parser in your own programs first copy the
|
||||||
|
files 'carg_parser.h' and 'carg_parser.c' in your source tree. See
|
||||||
|
also the file 'cmain.c' for an example of use.
|
||||||
|
|
||||||
|
Then you need to declare a variable of type 'struct Arg_parser',
|
||||||
|
pass its address to 'ap_init' to initialize it, and verify that
|
||||||
|
'ap_error' returns 0.
|
||||||
|
|
||||||
|
'struct ap_Option' is identical to 'struct Option', except that
|
||||||
|
'Has_arg' becomes 'ap_Has_arg', and the names of its three values are
|
||||||
|
also prefixed with 'ap_'. *Note struct Option::, for details about the
|
||||||
|
members.
|
||||||
|
|
||||||
|
-- Function: char ap_init ( struct Arg_parser * const AP, const int
|
||||||
|
ARGC, const char * const ARGV[], const struct ap_Option
|
||||||
|
OPTIONS[], const char IN_ORDER )
|
||||||
|
Reads the arguments in ARGV and parses all options, option
|
||||||
|
arguments and non-option arguments contained in them. Returns 0 if
|
||||||
|
there is not enough memory, else 1. In case of error, 'ap_error'
|
||||||
|
will return a non-null pointer.
|
||||||
|
|
||||||
|
-- Function: void ap_free ( struct Arg_parser * const AP )
|
||||||
|
Frees all dynamically allocated data structures.
|
||||||
|
|
||||||
|
-- Function: const char * ap_error ( const struct Arg_parser * const
|
||||||
|
AP )
|
||||||
|
Use this funtion to verify that the arguments have been correctly
|
||||||
|
parsed by 'ap_init'. If there was an error parsing the arguments,
|
||||||
|
'ap_error' returns a pointer to an error message explaining the
|
||||||
|
cause, else it returns a null pointer.
|
||||||
|
|
||||||
|
After a successful call to 'ap_init', which must be verified by
|
||||||
|
calling 'ap_error', the parsed options and arguments can be accessed by
|
||||||
|
means of the following functions:
|
||||||
|
|
||||||
|
-- Function: int ap_arguments ( const struct Arg_parser * const AP )
|
||||||
|
This function returns the number of options and non-option
|
||||||
|
arguments parsed. This number is normally different from argc.
|
||||||
|
|
||||||
|
-- Function: int ap_code ( const struct Arg_parser * const AP, const
|
||||||
|
int I )
|
||||||
|
This function returns the code of the option at position I. Valid
|
||||||
|
values for I range from 0 to 'ap_arguments() - 1'. If the returned
|
||||||
|
code is non-zero, 'ap_argument(I)' is the option's argument (or is
|
||||||
|
empty if the option does not have an argument). If the returned
|
||||||
|
code is zero, 'ap_argument(I)' is a non-option argument.
|
||||||
|
|
||||||
|
-- Function: const char * ap_argument ( const struct Arg_parser *
|
||||||
|
const AP, const int I )
|
||||||
|
This function returns the argument at position I. It may be the
|
||||||
|
argument of an option or a non-option argument, depending on the
|
||||||
|
value returned by 'ap_code(I)'. Valid values for I range from 0 to
|
||||||
|
'ap_arguments() - 1'.
|
||||||
|
|
||||||
|
When you are finished, you should free all dynamically allocated data
|
||||||
|
structures by calling 'ap_free'.
|
||||||
|
|
||||||
|
|
||||||
|
File: arg_parser.info, Node: Problems, Next: Concept index, Prev: C version, Up: Top
|
||||||
|
|
||||||
|
6 Reporting bugs
|
||||||
|
****************
|
||||||
|
|
||||||
|
There are probably bugs in Arg_parser. There are certainly errors and
|
||||||
|
omissions in this manual. If you report them, they will get fixed. If
|
||||||
|
you don't, no one will ever know about them and they will remain unfixed
|
||||||
|
for all eternity, if not longer.
|
||||||
|
|
||||||
|
If you find a bug in Arg_parser, please send electronic mail to
|
||||||
|
<arg-parser-bug@nongnu.org>. Include the version number, which you can
|
||||||
|
find by running 'arg_parser --version'.
|
||||||
|
|
||||||
|
|
||||||
|
File: arg_parser.info, Node: Concept index, Prev: Problems, Up: Top
|
||||||
|
|
||||||
|
Concept index
|
||||||
|
*************
|
||||||
|
|
||||||
|
|