All new argument parser.

This commit is contained in:
Scott Duensing 2020-02-04 19:44:15 -06:00
parent 7cba775e18
commit c54101b14b
27 changed files with 2585 additions and 146 deletions

View file

@ -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

View file

@ -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';
files[count].videoHandle = videoLoadWithAudio(files[count].filename, audio, indexPath, stretchVideo, renderer); if (utilFileExists(audio)) {
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;
@ -210,30 +230,48 @@ 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;
FrameFileT *f = NULL; int32_t found = -1;
FrameFileT *f = NULL;
// Get our framefile structure // Get our framefile structure
HASH_FIND_INT(_frameFileHash, &frameFileHandle, f); HASH_FIND_INT(_frameFileHash, &frameFileHandle, f);
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)))) {
// Frame is in this video found = i;
*actualFrame = seekFrame - f->files[i].frame; break;
f->files[i].lastFramePlayed = *actualFrame;
videoSeek(f->files[i].videoHandle, *actualFrame);
// Is this a different video from the previous one?
if (*videoHandle != f->files[i].videoHandle) {
// Yes
_transferProperties(*videoHandle, f->files[i].videoHandle);
*videoHandle = f->files[i].videoHandle;
}
return 0;
} }
} }
if (found >= 0) {
// Frame is in this video
*actualFrame = seekFrame - f->files[found].frame;
//utilSay("Frame %ld found in file %d - %s at %ld", seekFrame, found, f->files[found].filename, *actualFrame);
f->files[found].lastFramePlayed = *actualFrame;
videoSeek(f->files[found].videoHandle, *actualFrame);
// Is this a different video from the previous one?
if (*videoHandle != f->files[found].videoHandle) {
// Yes
_transferProperties(*videoHandle, f->files[found].videoHandle);
*videoHandle = f->files[found].videoHandle;
}
return 0;
}
// Didn't find it // Didn't find it
*videoHandle = -1; *videoHandle = -1;
*actualFrame = -1; *actualFrame = -1;

View file

@ -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;

View file

@ -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

View file

@ -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 \

View file

@ -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

View file

@ -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
View file

@ -0,0 +1 @@
Arg_parser was written by Antonio Diaz Diaz.

17
singe/thirdparty/arg_parser/COPYING vendored Normal file
View 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
View 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
View 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
View 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
View 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.

View 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 ) );
}

View 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_;
}
};

View 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 "";
}

View 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
View 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
View 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."

View 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.

View 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
*************
[index]
* Menu:
* argument syntax: Argument syntax. (line 6)
* bugs: Problems. (line 6)
* C version: C version. (line 6)
* getting help: Problems. (line 6)
* initialization: Initialization. (line 6)
* introduction: Introduction. (line 6)
* using Arg_parser: Using Arg_parser. (line 6)

Tag Table:
Node: Top221
Node: Introduction946
Node: Argument syntax1837
Node: Initialization4077
Ref: struct Option4610
Node: Using Arg_parser6549
Node: C version7738
Node: Problems10603
Node: Concept index11156

End Tag Table

Local Variables:
coding: iso-8859-15
End:

View file

@ -0,0 +1,301 @@
\input texinfo @c -*-texinfo-*-
@c %**start of header
@setfilename arg_parser.info
@documentencoding ISO-8859-15
@settitle Arg_parser Manual
@finalout
@c %**end of header
@set UPDATED 1 January 2019
@set VERSION 1.14
@dircategory Basics
@direntry
* Arg_parser: (arg_parser). A POSIX/GNU command line argument parser
@end direntry
@ifnothtml
@titlepage
@title Arg_parser
@subtitle A POSIX/GNU command line argument parser
@subtitle for Arg_parser version @value{VERSION}, @value{UPDATED}
@author by Antonio Diaz Diaz
@page
@vskip 0pt plus 1filll
@end titlepage
@contents
@end ifnothtml
@node Top
@top
This manual is for Arg_parser (version @value{VERSION}, @value{UPDATED}).
@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
@end menu
@sp 1
Copyright @copyright{} 2006-2019 Antonio Diaz Diaz.
This manual is free documentation: you have unlimited permission
to copy, distribute and modify it.
@node Introduction
@chapter Introduction
@cindex 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 @code{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.
@node Argument syntax
@chapter Syntax of command line arguments
@cindex argument syntax
POSIX recommends these conventions for command line arguments.
@code{Arg_parser} makes it easy to implement them.
@itemize @bullet
@item A command line argument is a option if it begins with a hyphen
delimiter (@code{-}).
@item Multiple options may follow a hyphen delimiter in a single token
if the options don't take arguments. Thus, @code{-abc} is equivalent to
@w{@code{-a -b -c}}.
@item Option names are single alphanumeric characters.
@item Certain options require an argument.
@item An option and its argument may or may not appear as separate
tokens. (In other words, the whitespace separating them is optional).
Thus, @w{@code{-o foo}} and @code{-ofoo} are equivalent.
@item Options typically precede other non-option arguments.
@code{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 @code{Arg_parser} with @var{in_order} = true.
@item The argument @code{--} terminates all options; any following
arguments are treated as non-option arguments, even if they begin with a
hyphen.
@item 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.
@item Options may be supplied in any order, or appear multiple times.
The interpretation is left up to the particular application program.
@item GNU adds @dfn{long options} to these conventions. Long options
consist of @code{--} 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.
@item The syntax for optional option arguments is
@code{-<short_option><argument>} (without whitespace), or
@code{--<long_option>=<argument>}.
@end itemize
@node Initialization
@chapter Parsing arguments and reporting errors
@cindex initialization
To use Arg_parser in your own programs first copy the files
@samp{arg_parser.h} and @samp{arg_parser.cc} in your source tree. See also
the file @samp{main.cc} for an example of use.
The Arg_parser class has two constructors; one to parse command line
arguments from @var{argv}, and the other to parse a single token from a
configuration file or other source.
@anchor{struct Option}
@deffn {Data Type} struct Option
This structure describes a single option for the sake of
@code{Arg_parser}. The argument @var{options} must be an array of these
structures, one for each option. Terminate the array with an element
containing a code which is zero.
@code{struct Option} has the following members:
@table @code
@item 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.
@item 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.
@item enum Has_arg has_arg
This member says whether the option takes an argument. It has three
valid values: @code{no}, @code{yes} and @code{maybe}.
@end table
@end deffn
@defun Arg_parser ( const int @var{argc}, const char * const @var{argv}[], const Option @var{options}[], const bool @var{in_order} = false )
Reads the arguments in @var{argv} and parses all options, option
arguments and non-option arguments contained in them. In case of error,
@code{error().size()} will be non-zero.
@end defun
@defun Arg_parser ( const char * const @var{opt}, const char * const @var{arg}, const Option @var{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, @code{error().size()} will be non-zero.
@end defun
@deftypefun {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,
@code{error} returns a non-empty error message explaining the cause.
@end deftypefun
@node Using Arg_parser
@chapter Using the @code{Arg_parser} class
@cindex using Arg_parser
After a successful call to the constructor, which must be verified by
calling @code{error}, the parsed options and arguments can be accessed
by means of the following functions:
@deftypefun int arguments () const
This function returns the number of options and non-option arguments
parsed. This number is normally different from argc.
@end deftypefun
@deftypefun int code ( const int @var{i} ) const
This function returns the code of the option at position @var{i}. Valid
values for @var{i} range from 0 to @w{@code{arguments() - 1}}. If the
returned code is non-zero, @code{argument(@var{i})} is the option's
argument (or is empty if the option does not have an argument). If the
returned code is zero, @code{argument(@var{i})} is a non-option
argument.
@end deftypefun
@deftypefun {const std::string &} argument ( const int @var{i} ) const
This function returns the argument at position @var{i}. It may be the
argument of an option or a non-option argument, depending on the value
returned by @code{code(@var{i})}. Valid values for @var{i} range from 0
to @w{@code{arguments() - 1}}.
@end deftypefun
@node C version
@chapter Using the C version of Arg_parser
@cindex C version
To use the C version of Arg_parser in your own programs first copy the
files @samp{carg_parser.h} and @samp{carg_parser.c} in your source tree.
See also the file @samp{cmain.c} for an example of use.
Then you need to declare a variable of type @code{struct Arg_parser},
pass its address to @code{ap_init} to initialize it, and verify that
@code{ap_error} returns 0.
@code{struct ap_Option} is identical to @code{struct Option}, except
that @code{Has_arg} becomes @code{ap_Has_arg}, and the names of its
three values are also prefixed with @code{ap_}. @xref{struct Option},
for details about the members.
@deftypefun char ap_init ( struct Arg_parser * const @var{ap}, const int @var{argc}, const char * const @var{argv}[], const struct ap_Option @var{options}[], const char @var{in_order} )
Reads the arguments in @var{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, @code{ap_error} will
return a non-null pointer.
@end deftypefun
@deftypefun void ap_free ( struct Arg_parser * const @var{ap} )
Frees all dynamically allocated data structures.
@end deftypefun
@deftypefun {const char *} ap_error ( const struct Arg_parser * const @var{ap} )
Use this funtion to verify that the arguments have been correctly parsed
by @code{ap_init}. If there was an error parsing the arguments,
@code{ap_error} returns a pointer to an error message explaining the
cause, else it returns a null pointer.
@end deftypefun
After a successful call to @code{ap_init}, which must be verified by
calling @code{ap_error}, the parsed options and arguments can be
accessed by means of the following functions:
@deftypefun int ap_arguments ( const struct Arg_parser * const @var{ap} )
This function returns the number of options and non-option arguments
parsed. This number is normally different from argc.
@end deftypefun
@deftypefun int ap_code ( const struct Arg_parser * const @var{ap}, const int @var{i} )
This function returns the code of the option at position @var{i}. Valid
values for @var{i} range from 0 to @w{@code{ap_arguments() - 1}}. If the
returned code is non-zero, @code{ap_argument(@var{i})} is the option's
argument (or is empty if the option does not have an argument). If the
returned code is zero, @code{ap_argument(@var{i})} is a non-option
argument.
@end deftypefun
@deftypefun {const char *} ap_argument ( const struct Arg_parser * const @var{ap}, const int @var{i} )
This function returns the argument at position @var{i}. It may be the
argument of an option or a non-option argument, depending on the value
returned by @code{ap_code(@var{i})}. Valid values for @var{i} range from
0 to @w{@code{ap_arguments() - 1}}.
@end deftypefun
When you are finished, you should free all dynamically allocated data
structures by calling @code{ap_free}.
@node Problems
@chapter Reporting bugs
@cindex bugs
@cindex getting help
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
@email{arg-parser-bug@@nongnu.org}. Include the version number, which
you can find by running @w{@code{arg_parser --version}}.
@node Concept index
@unnumbered Concept index
@printindex cp
@bye

View 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 carg_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 'carg_parser.h'
and 'carg_parser.c' in your source tree. See also the file 'cmain.c' 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.

185
singe/thirdparty/arg_parser/main.cc vendored Normal file
View file

@ -0,0 +1,185 @@
/* 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 <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#include "arg_parser.h"
namespace {
const char * const program_name = "arg_parser";
const char * const program_year = "2019";
const char * invocation_name = 0;
void show_help( const bool verbose )
{
std::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 'arg_parser.h'\n"
"and 'arg_parser.cc' in your source tree. See also the file 'main.cc' for an\n"
"example of use.\n"
"\nUsage: %s [options]\n", invocation_name );
std::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 )
{
std::printf( " -H, --hidden example of hidden option (shown with -v -h)\n" );
}
std::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()
{
std::printf( "%s %s\n", program_name, PROGVERSION );
std::printf( "Copyright (C) %s Antonio Diaz Diaz.\n", program_year );
std::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 = 0,
const bool help = false )
{
if( msg && msg[0] )
std::fprintf( stderr, "%s: %s%s%s\n", program_name, msg,
( errcode > 0 ) ? ": " : "",
( errcode > 0 ) ? std::strerror( errcode ) : "" );
if( help )
std::fprintf( stderr, "Try '%s --help' for more information.\n",
invocation_name );
}
void internal_error( const char * const msg )
{
std::fprintf( stderr, "%s: internal error: %s\n", program_name, msg );
std::exit( 3 );
}
const char * optname( const int code, const Arg_parser::Option options[] )
{
static char buf[2] = "?";
if( code != 0 )
for( int 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;
}
} // end namespace
int main( const int argc, const char * const argv[] )
{
bool verbose = false;
invocation_name = argv[0];
const Arg_parser::Option options[] =
{
{ 'a', "append", Arg_parser::no },
{ 'b', "block", Arg_parser::yes },
{ 'c', "casual", Arg_parser::maybe },
{ 'h', "help", Arg_parser::no },
{ 'H', "hidden", Arg_parser::no },
{ 'o', 0, Arg_parser::yes },
{ 'q', "quiet", Arg_parser::no },
{ 'u', "uncaught", Arg_parser::no },
{ 'v', "verbose", Arg_parser::no },
{ 'V', "version", Arg_parser::no },
{ 256, "orphan", Arg_parser::no },
{ 0, 0, Arg_parser::no } };
const Arg_parser parser( argc, argv, options );
if( parser.error().size() ) // bad option
{ show_error( parser.error().c_str(), 0, true ); return 1; }
for( int argind = 0; argind < parser.arguments(); ++argind )
{
const int code = parser.code( 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 = false; break;
// case 'u': break; // intentionally not caught
case 'v': verbose = true; break;
case 'V': show_version(); return 0;
case 256: break; // example, do nothing
default : internal_error( "uncaught option." );
}
} // end process options
for( int argind = 0; argind < parser.arguments(); ++argind )
{
const int code = parser.code( argind );
const char * const arg = parser.argument( argind ).c_str();
if( code ) // option
{
const char * const name = optname( code, options );
if( !name[1] )
std::printf( "option '-%c'", name[0] );
else
std::printf( "option '--%s'", name );
if( arg[0] )
std::printf( " with argument '%s'", arg );
}
else // non-option
std::printf( "non-option argument '%s'", arg );
std::fputc( '\n', stdout );
}
if( !parser.arguments() ) std::fputs( "Hello, world!\n", stdout );
return 0;
}

101
singe/thirdparty/arg_parser/testsuite/check.sh vendored Executable file
View file

@ -0,0 +1,101 @@
#! /bin/sh
# check script for Arg_parser - POSIX/GNU command line argument parser.
# Copyright (C) 2011-2019 Antonio Diaz Diaz.
#
# This script is free software: you have unlimited permission
# to copy, distribute and modify it.
LC_ALL=C
export LC_ALL
objdir=`pwd`
testdir=`cd "$1" ; pwd`
PARSER="${objdir}"/arg_parser
CPARSER="${objdir}"/carg_parser
framework_failure() { echo "failure in testing framework" ; exit 1 ; }
if [ ! -f "${PARSER}" ] || [ ! -x "${PARSER}" ] ; then
echo "${PARSER}: cannot execute"
exit 1
fi
if [ ! -f "${CPARSER}" ] || [ ! -x "${CPARSER}" ] ; then
echo "${CPARSER}: cannot execute"
exit 1
fi
if [ -d tmp ] ; then rm -rf tmp ; fi
mkdir tmp
cd "${objdir}"/tmp || framework_failure
in="${testdir}"/test.txt
fail=0
test_failed() { fail=1 ; printf "\n$1" ; [ -z "$2" ] || printf "($2)" ; }
printf "testing arg_parser-%s..." "$2"
for i in "${PARSER}" "${CPARSER}" ; do
"$i" -h > /dev/null || test_failed $LINENO "$i"
"$i" --help > /dev/null || test_failed $LINENO "$i"
"$i" -V > /dev/null || test_failed $LINENO "$i"
"$i" --version > /dev/null || test_failed $LINENO "$i"
"$i" -h -v > /dev/null || test_failed $LINENO "$i"
"$i" -v -h > /dev/null || test_failed $LINENO "$i"
"$i" -a -b 5 -c -carg -o file --orphan --verbose file1 file2 > out ||
test_failed $LINENO "$i"
cmp ${in} out || test_failed $LINENO "$i"
"$i" -ab5 -c -carg -ofile file1 --orphan file2 --verbos > out ||
test_failed $LINENO "$i"
cmp ${in} out || test_failed $LINENO "$i"
"$i" --append file1 --block 5 --casual file2 --casual=arg -o file --orphan --verbo > out ||
test_failed $LINENO "$i"
cmp ${in} out || test_failed $LINENO "$i"
"$i" --append --block=5 --casual= file1 --casual=arg -ofile --orphan --verb file2 > out ||
test_failed $LINENO "$i"
cmp ${in} out || test_failed $LINENO "$i"
done
printf "\ntesting bad input..."
for i in "${PARSER}" "${CPARSER}" ; do
"$i" --v 2> /dev/null # ambiguous option
[ $? = 1 ] || test_failed $LINENO "$i"
"$i" --ve 2> /dev/null
[ $? = 1 ] || test_failed $LINENO "$i"
"$i" --ver 2> /dev/null
[ $? = 1 ] || test_failed $LINENO "$i"
"$i" --unrecognized 2> /dev/null # unrecognized option
[ $? = 1 ] || test_failed $LINENO "$i"
"$i" -x 2> /dev/null # invalid option
[ $? = 1 ] || test_failed $LINENO "$i"
"$i" -aARG 2> /dev/null # argument not allowed
[ $? = 1 ] || test_failed $LINENO "$i"
"$i" -b 2> /dev/null # argument required
[ $? = 1 ] || test_failed $LINENO "$i"
"$i" --block 2> /dev/null
[ $? = 1 ] || test_failed $LINENO "$i"
"$i" --block= 2> /dev/null
[ $? = 1 ] || test_failed $LINENO "$i"
"$i" -u 2> /dev/null # uncaught option
[ $? = 3 ] || test_failed $LINENO "$i"
done
echo
if [ ${fail} = 0 ] ; then
echo "tests completed successfully."
cd "${objdir}" && rm -r tmp
else
echo "tests failed."
fi
exit ${fail}

View file

@ -0,0 +1,9 @@
option '--append'
option '--block' with argument '5'
option '--casual'
option '--casual' with argument 'arg'
option '-o' with argument 'file'
option '--orphan'
option '--verbose'
non-option argument 'file1'
non-option argument 'file2'

View file

@ -580,7 +580,7 @@ int32_t videoUpdate(int32_t playerHandle, SDL_Texture **texture) {
// Used to determine if we should play two frames rapidly to catch up to audio // Used to determine if we should play two frames rapidly to catch up to audio
v->audioDelta = labs(v->audioPosition - (int64_t)((double)v->timestamp * 0.001 * (double)v->audioProps->SampleRate)); v->audioDelta = labs(v->audioPosition - (int64_t)((double)v->timestamp * 0.001 * (double)v->audioProps->SampleRate));
utilSay("D %ld T %ld A %f", v->audioDelta, threshold, v->audioAdjustment); //utilSay("D %ld T %ld A %f", v->audioDelta, threshold, v->audioAdjustment);
v->frameData = FFMS_GetFrame(v->videoSource, v->frame, &v->errInfo); v->frameData = FFMS_GetFrame(v->videoSource, v->frame, &v->errInfo);
if (v->frameData == NULL) utilDie("%s", v->errInfo.Buffer); if (v->frameData == NULL) utilDie("%s", v->errInfo.Buffer);