diff --git a/singe/buildRelease.sh b/singe/buildRelease.sh index 64a39efda..ecdbf4a56 100755 --- a/singe/buildRelease.sh +++ b/singe/buildRelease.sh @@ -70,7 +70,7 @@ CROSS="x86_64-linux-gnu" EXTRA_CFLAGS="-O2" EXTRA_OFILES="" 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 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" icotool -c -o /tmp/icon.ico icon.png 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/singe.res -# 32 Bit Raspbian - ***TODO*** Should we provide libsamplerate ourselves? +# 32 Bit Raspbian SYSROOT="/opt/cross/pi/buster" CROSS="/opt/cross/pi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf" EXTRA_CFLAGS="-O2 --sysroot ${SYSROOT}" 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 diff --git a/singe/frameFile.c b/singe/frameFile.c index 2dba54466..f3eb9bc1c 100644 --- a/singe/frameFile.c +++ b/singe/frameFile.c @@ -105,6 +105,7 @@ int32_t frameFileLoad(char *filename, char *indexPath, bool stretchVideo, SDL_Re int32_t result = 0; int32_t count = 0; int64_t frame = 0; + int64_t next = 0; size_t bytes = 0; char *audio = 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 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. space = strstr(frameLine, " "); if (space) { @@ -153,7 +158,7 @@ int32_t frameFileLoad(char *filename, char *indexPath, bool stretchVideo, SDL_Re if (endptr == space) { // Got an integer. Point at filename. space++; - while ((space[0] == 32) || (space[0] == 9)) { + while (space[0] == 32) { space++; } // 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) - 2] = '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); audio = NULL; } else { @@ -197,12 +206,23 @@ int32_t frameFileLoad(char *filename, char *indexPath, bool stretchVideo, SDL_Re if (_confShowCalculated) { // 00000000011111111112222222222333333333344444444445555555555666666666677777777778 // 12345678901234567890123456789012345678901234567890123456789012345678901234567890 + utilSay("Existing Framefile:\n"); utilSay(" Start Length End File"); utilSay("-------- -------- -------- -------------------------------------------------"); for (count=0; countcount; count++) { 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); } + next = 0; + utilSay("\nIdeal Framefile:\n"); + utilSay(" Start File"); + utilSay("-------- ---------------------------------------------------------------------"); + for (count=0; countcount; count++) { + frame = videoGetFrameCount(frameFile->files[count].videoHandle); + utilSay("%8ld %s", next, frameFile->files[count].filename); + next += frame + 1; + } + utilSay(""); } 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 i = 0; - FrameFileT *f = NULL; + int32_t i = 0; + int32_t found = -1; + FrameFileT *f = NULL; // Get our framefile structure HASH_FIND_INT(_frameFileHash, &frameFileHandle, f); if (!f) utilDie("No framefile at index %d in frameFileSeek.", frameFileHandle); // 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; icount; i++) { if ((seekFrame >= f->files[i].frame) && (seekFrame <= (f->files[i].frame + videoGetFrameCount(f->files[i].videoHandle)))) { - // Frame is in this video - *actualFrame = seekFrame - f->files[i].frame; - 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; + found = i; + break; } } + 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 *videoHandle = -1; *actualFrame = -1; diff --git a/singe/main.c b/singe/main.c index abde248ad..bf4857919 100644 --- a/singe/main.c +++ b/singe/main.c @@ -20,17 +20,18 @@ */ -// -c -v singe/ActionMax/frame_SonicFury.txt singe/ActionMax/SonicFury.singe -// -v singe/ActionMax/BlueThunder.mp4 singe/test.singe +// -c -x 720 -y 480 -d data/maddog_dvd -v maddog_dvd/frame_maddog_dvd.txt maddog_dvd/maddog_dvd.singe +// -c -x 640 -y 480 -v ActionMax/frame_SonicFury.txt ActionMax/SonicFury.singe +// -v ActionMax/BlueThunder.mp4 test.singe #include -#include #include #include #include #include +#include #include #include "stddclmr.h" @@ -75,25 +76,25 @@ void showUsage(char *name, char *message) { utilSay(""); utilSay("Usage: %s [OPTIONS] scriptName{.singe}", utilGetLastPathComponent(name)); 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(" -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(" -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(" -g, --sindengun=PARAMS enable Sinden Light Gun support"); - utilSay(" -a, --aspect=N:D force aspect ratio"); + utilSay(" -s, --nosound, --mutesound mutes all sound"); + utilSay(" -t, --trace trace script execution to screen and file"); 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(" -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(" -h, --help this display"); utilSay(""); if (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 err = 0; int32_t flags = 0; - int32_t optionIndex = 0; int32_t bestResIndex = -1; int32_t bestRatioIndex = -1; int32_t aspectNum = -1; int32_t aspectDom = -1; + int32_t argCount = 0; + int32_t argIndex = 0; + int32_t code = 0; + char *exeName = NULL; char *temp = NULL; char *aspectString = NULL; char *sindenString = NULL; @@ -127,28 +131,29 @@ int main(int argc, char *argv[]) { SDL_Renderer *renderer = NULL; SDL_Surface *icon = NULL; SDL_DisplayMode mode; - static struct option options[] = { - { "nomouse", no_argument, NULL, 'm' }, -// { "noserversend", no_argument, NULL, 'n' }, - { "nosound", no_argument, NULL, 's' }, - { "mutesound", no_argument, NULL, 's' }, - { "fullscreen", no_argument, NULL, 'f' }, - { "fullscreen_window", no_argument, NULL, 'w' }, - { "stretch", no_argument, NULL, 'u' }, - { "datadir", optional_argument, NULL, 'd' }, - { "framefile", optional_argument, NULL, 'v' }, - { "volume_vldp", optional_argument, NULL, 'l' }, - { "volume_nonlvdp", optional_argument, NULL, 'e' }, - { "scalefactor", optional_argument, NULL, 'o' }, - { "sindengun", optional_argument, NULL, 'g' }, - { "aspect", optional_argument, NULL, 'a' }, - { "xresolution", optional_argument, NULL, 'x' }, - { "yresolution", optional_argument, NULL, 'y' }, - { "help", no_argument, NULL, 'h' }, - { "trace", no_argument, NULL, 't' }, - { "showcalculated", no_argument, NULL, 'c' }, - { "noconsole", no_argument, NULL, 'z' }, - { NULL, 0, NULL, 0 } + const char *arg = NULL; + struct Arg_parser parser; + static struct ap_Option options[] = { + { 'a', "aspect", ap_yes }, + { 'c', "showcalculated", ap_no }, + { 'd', "datadir", ap_yes }, + { 'e', "volume_nonlvdp", ap_yes }, + { 'f', "fullscreen", ap_no }, + { 'g', "sindengun", ap_yes }, + { 'h', "help", ap_no }, + { 'l', "volume_vldp", ap_yes }, + { 'm', "nomouse", ap_no }, +// { 'n', "noserversend", ap_no }, + { 'o', "scalefactor", ap_yes }, + { 's', "nosound", ap_no }, + { 't', "trace", ap_no }, + { 'u', "stretch", ap_no }, + { 'v', "framefile", ap_yes }, + { 'w', "fullscreenwindow", ap_no }, + { 'x', "xresolution", ap_yes }, + { 'y', "yresolution", ap_yes }, + { 'z', "noconsole", ap_no }, + { 0, 0, ap_no } }; static ModeT modes[] = { { { 4, 3 }, { 640, 480 } }, @@ -179,20 +184,77 @@ int main(int argc, char *argv[]) { { { 0, 0 }, { 0, 0 } } }; + exeName = (char *)argv[0]; + // For that dumb OS utilRedirectConsole(); - // Parse command line - while (true) { - optionIndex = 0; - opterr = 0; - x = getopt_long(argc, argv, "cmnsfwhza:d:v:l:e:x:y:o:g:", options, &optionIndex); + if (!ap_init(&parser, argc, argv, options, 0)) { + utilDie("Out of memory parsing arguments."); + } + if (ap_error(&parser)) { + utilDie("%s", ap_error(&parser)); + } - // Out of options? - if (x == -1) break; + // Parse command line + 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 - 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 case 'm': _confNoMouse = true; @@ -203,19 +265,20 @@ int main(int argc, char *argv[]) { _confNoStats = true; break; + // Overscan Zoom + case 'o': + _confScaleFactor = atoi(arg); + argCount++; + break; + // No Sound case 's': _confNoSound = true; break; - // Full Screen - case 'f': - _confFullScreen = true; - break; - - // Full Screen Windowed - case 'w': - _confFullScreenWindow = true; + // Trace + case 't': + tracing = true; break; // Ugly Stretched Video @@ -226,60 +289,25 @@ int main(int argc, char *argv[]) { // Video File case 'v': if (_confVideoFile) free(_confVideoFile); - _confVideoFile = strdup(optarg); + _confVideoFile = strdup(arg); + argCount++; break; - // Data Dir - case 'd': - if (_confDataDir) free(_confDataDir); - _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); + // Full Screen Windowed + case 'w': + _confFullScreenWindow = true; break; // X Resolution case 'x': - _confXResolution = atoi(optarg); + _confXResolution = atoi(arg); + argCount++; break; // Y Resolution case 'y': - _confYResolution = atoi(optarg); - break; - - // Help - case 'h': - showUsage(argv[0], NULL); - break; - - // Trace - case 't': - tracing = true; + _confYResolution = atoi(arg); + argCount++; break; // No console output or splash screens @@ -287,15 +315,6 @@ int main(int argc, char *argv[]) { _confNoConsole = true; break; - // Show Calculated Frame File Values - case 'c': - _confShowCalculated = true; - break; - - case '?': - showUsage(argv[0], "Unknown option."); - break; - default: abort(); // Something bad happened break; @@ -303,8 +322,8 @@ int main(int argc, char *argv[]) { } // Did we get a filename or path to open? - if (optind != (argc - 1)) showUsage(argv[0], "No script file specified."); - _confScriptFile = strdup(argv[optind]); + if ((argc - argCount) != 1) showUsage(exeName, "No script file specified."); + _confScriptFile = strdup(argv[argCount]); // Exists? if (!utilFileExists(_confScriptFile)) { // Missing. Is a path? @@ -327,7 +346,7 @@ int main(int argc, char *argv[]) { _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? 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? if (strncmp(utilGetFileExtension(_confVideoFile), "txt", 3) == 0) { _confIsFrameFile = true; @@ -390,7 +409,7 @@ int main(int argc, char *argv[]) { free(temp); temp = NULL; } - if (!_confDataDir) showUsage(argv[0], "Unable to locate data directory."); + if (!_confDataDir) showUsage(exeName, "Unable to locate data directory."); utilFixPathSeparators(&_confDataDir); // Do they want tracing? @@ -402,18 +421,18 @@ int main(int argc, char *argv[]) { } // 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? - if ((_confVolumeVldp < 0) || (_confVolumeVldp > 100)) showUsage(argv[0], "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 ((_confVolumeVldp < 0) || (_confVolumeVldp > 100)) showUsage(exeName, "Laserdisc 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? - 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? 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? if ((sindenString[0] == '"') || (sindenString[0] == '\'')) { sindenString[0] = ' '; @@ -428,10 +447,10 @@ int main(int argc, char *argv[]) { while (temp != NULL) { _confSindenArgv[_confSindenArgc++] = atoi(temp); 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? - 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); } @@ -474,7 +493,7 @@ int main(int argc, char *argv[]) { x++; } } - if (bestRatioIndex < 0) showUsage(argv[0], "Unknown aspect ratio."); + if (bestRatioIndex < 0) showUsage(exeName, "Unknown aspect ratio."); x = 0; // Were both resolutions not specified? if ((_confXResolution <= 0) && (_confYResolution <= 0)) { @@ -523,9 +542,9 @@ int main(int argc, char *argv[]) { } } // 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 (_confYResolution <= 0) showUsage(argv[0], "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 <= 0) showUsage(exeName, "Unable to determine X resolution. (Is the Y 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(exeName, "Specified resolution is larger than the display."); // Init SDL_mixer ***FIX*** flags = /* MIX_INIT_FLAC | */ MIX_INIT_MOD | /* MIX_INIT_MP3 | */ MIX_INIT_OGG | MIX_INIT_MID | MIX_INIT_OPUS; diff --git a/singe/preBuild.sh b/singe/preBuild.sh index 687e463c4..8b448b7eb 100755 --- a/singe/preBuild.sh +++ b/singe/preBuild.sh @@ -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" PKG_CONFIG_PATH="${G_SYSROOT}/usr/lib/arm-linux-gnueabihf/pkgconfig" \ 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 autoBuild libSDL2.a SDL2 fi diff --git a/singe/singe.pro b/singe/singe.pro index 421ded255..fccd4138f 100644 --- a/singe/singe.pro +++ b/singe/singe.pro @@ -66,6 +66,17 @@ static { 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_INCLUDES = \ @@ -85,6 +96,7 @@ MANYMOUSE_SOURCES = \ # === SINGE === QMAKE_CFLAGS += \ + -isystem $$ARGPARSER_INCLUDES \ -isystem $$MANYMOUSE_INCLUDES \ -isystem $$PWD/../thirdparty-build/$$PLATFORM/$$BITNESS/installed/include @@ -95,6 +107,7 @@ dynamic { } HEADERS += \ + $$ARGPARSER_HEADERS \ $$MANYMOUSE_HEADERS \ frameFile.h \ stddclmr.h \ @@ -109,6 +122,7 @@ HEADERS += \ kangarooPunchLogo.h SOURCES += \ + $$ARGPARSER_SOURCES \ $$MANYMOUSE_SOURCES \ frameFile.c \ util.c \ diff --git a/singe/thirdparty/SDL2_mixer/external/opus-1.3.1/doc/Makefile.in b/singe/thirdparty/SDL2_mixer/external/opus-1.3.1/doc/Makefile.in index e6957b6d8..354da2ad2 100644 --- a/singe/thirdparty/SDL2_mixer/external/opus-1.3.1/doc/Makefile.in +++ b/singe/thirdparty/SDL2_mixer/external/opus-1.3.1/doc/Makefile.in @@ -395,8 +395,8 @@ maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." @HAVE_DOXYGEN_FALSE@uninstall-local: -@HAVE_DOXYGEN_FALSE@clean-local: @HAVE_DOXYGEN_FALSE@install-data-local: +@HAVE_DOXYGEN_FALSE@clean-local: clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am diff --git a/singe/thirdparty/SDL2_mixer/external/opusfile-0.11/Makefile.in b/singe/thirdparty/SDL2_mixer/external/opusfile-0.11/Makefile.in index a4164a16a..2ce5de6c0 100644 --- a/singe/thirdparty/SDL2_mixer/external/opusfile-0.11/Makefile.in +++ b/singe/thirdparty/SDL2_mixer/external/opusfile-0.11/Makefile.in @@ -1019,8 +1019,8 @@ maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." @HAVE_DOXYGEN_FALSE@clean-local: -@HAVE_DOXYGEN_FALSE@install-data-local: @HAVE_DOXYGEN_FALSE@uninstall-local: +@HAVE_DOXYGEN_FALSE@install-data-local: clean: clean-am clean-am: clean-generic clean-libLTLIBRARIES clean-libtool clean-local \ diff --git a/singe/thirdparty/arg_parser/AUTHORS b/singe/thirdparty/arg_parser/AUTHORS new file mode 100644 index 000000000..e913a2d7c --- /dev/null +++ b/singe/thirdparty/arg_parser/AUTHORS @@ -0,0 +1 @@ +Arg_parser was written by Antonio Diaz Diaz. diff --git a/singe/thirdparty/arg_parser/COPYING b/singe/thirdparty/arg_parser/COPYING new file mode 100644 index 000000000..38d93a414 --- /dev/null +++ b/singe/thirdparty/arg_parser/COPYING @@ -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. diff --git a/singe/thirdparty/arg_parser/ChangeLog b/singe/thirdparty/arg_parser/ChangeLog new file mode 100644 index 000000000..0e3504559 --- /dev/null +++ b/singe/thirdparty/arg_parser/ChangeLog @@ -0,0 +1,107 @@ +2019-01-01 Antonio Diaz Diaz + + * 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 + + * 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 + + * 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 + + * 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 + + * Version 1.10 released. + * License changed to "GPL version 2 or later with link exception". + +2014-05-26 Antonio Diaz Diaz + + * 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 + + * Version 1.8 released. + * Makefile.in: Added new target 'install-bin'. + +2012-02-24 Antonio Diaz Diaz + + * 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 + + * Version 1.6 released. + * Minor fixes. + +2011-01-12 Antonio Diaz Diaz + + * 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 + + * 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 + + * Version 1.3 released. + * carg_parser.c (ap_resize_buffer): Return 'void*' instead of 'char'. + +2009-01-15 Antonio Diaz Diaz + + * 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 + + * Version 1.1 released. + * Added C version. + * Options requiring an argument no longer accept an empty argument. + +2007-06-29 Antonio Diaz Diaz + + * Version 1.0 released. + * License updated to "GPL version 3 or later with link exception". + +2006-11-04 Antonio Diaz Diaz + + * Version 0.2 released. + * Some fixes made to 'configure' script. + +2006-03-29 Antonio Diaz Diaz + + * 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. diff --git a/singe/thirdparty/arg_parser/INSTALL b/singe/thirdparty/arg_parser/INSTALL new file mode 100644 index 000000000..0cb8c8ff9 --- /dev/null +++ b/singe/thirdparty/arg_parser/INSTALL @@ -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. diff --git a/singe/thirdparty/arg_parser/NEWS b/singe/thirdparty/arg_parser/NEWS new file mode 100644 index 000000000..730a871c3 --- /dev/null +++ b/singe/thirdparty/arg_parser/NEWS @@ -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'. diff --git a/singe/thirdparty/arg_parser/README b/singe/thirdparty/arg_parser/README new file mode 100644 index 000000000..28189b288 --- /dev/null +++ b/singe/thirdparty/arg_parser/README @@ -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. diff --git a/singe/thirdparty/arg_parser/arg_parser.cc b/singe/thirdparty/arg_parser/arg_parser.cc new file mode 100644 index 000000000..ea32fde7d --- /dev/null +++ b/singe/thirdparty/arg_parser/arg_parser.cc @@ -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 +#include +#include + +#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] ) // '--=' 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 ) ); + } diff --git a/singe/thirdparty/arg_parser/arg_parser.h b/singe/thirdparty/arg_parser/arg_parser.h new file mode 100644 index 000000000..ceb993339 --- /dev/null +++ b/singe/thirdparty/arg_parser/arg_parser.h @@ -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 '-' + (without whitespace), or '--='. +*/ + +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_; + } + }; diff --git a/singe/thirdparty/arg_parser/carg_parser.c b/singe/thirdparty/arg_parser/carg_parser.c new file mode 100644 index 000000000..ce01d7b74 --- /dev/null +++ b/singe/thirdparty/arg_parser/carg_parser.c @@ -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 +#include + +#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] ) /* '--=' 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 ""; + } diff --git a/singe/thirdparty/arg_parser/carg_parser.h b/singe/thirdparty/arg_parser/carg_parser.h new file mode 100644 index 000000000..dcae2de08 --- /dev/null +++ b/singe/thirdparty/arg_parser/carg_parser.h @@ -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 '-' + (without whitespace), or '--='. +*/ + +#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 diff --git a/singe/thirdparty/arg_parser/cmain.c b/singe/thirdparty/arg_parser/cmain.c new file mode 100644 index 000000000..5ceeb437f --- /dev/null +++ b/singe/thirdparty/arg_parser/cmain.c @@ -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 +#include +#include + +#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= example of option with required argument\n" + " -c, --casual[=] example of option with optional argument\n" + " -o 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; + } diff --git a/singe/thirdparty/arg_parser/configure b/singe/thirdparty/arg_parser/configure new file mode 100755 index 000000000..22a6cfcbc --- /dev/null +++ b/singe/thirdparty/arg_parser/configure @@ -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." diff --git a/singe/thirdparty/arg_parser/doc/arg_parser.1 b/singe/thirdparty/arg_parser/doc/arg_parser.1 new file mode 100644 index 000000000..19fa2d605 --- /dev/null +++ b/singe/thirdparty/arg_parser/doc/arg_parser.1 @@ -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 +example of option with required argument +.TP +\fB\-c\fR, \fB\-\-casual[=\fR] +example of option with optional argument +.TP +\fB\-o\fR +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. diff --git a/singe/thirdparty/arg_parser/doc/arg_parser.info b/singe/thirdparty/arg_parser/doc/arg_parser.info new file mode 100644 index 000000000..89a9dce3d --- /dev/null +++ b/singe/thirdparty/arg_parser/doc/arg_parser.info @@ -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 + '-' (without whitespace), or + '--='. + + +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 +. 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: diff --git a/singe/thirdparty/arg_parser/doc/arg_parser.texi b/singe/thirdparty/arg_parser/doc/arg_parser.texi new file mode 100644 index 000000000..da4d2d5b4 --- /dev/null +++ b/singe/thirdparty/arg_parser/doc/arg_parser.texi @@ -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{-} (without whitespace), or +@code{--=}. +@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 diff --git a/singe/thirdparty/arg_parser/doc/carg_parser.1 b/singe/thirdparty/arg_parser/doc/carg_parser.1 new file mode 100644 index 000000000..f5e3af1e9 --- /dev/null +++ b/singe/thirdparty/arg_parser/doc/carg_parser.1 @@ -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 +example of option with required argument +.TP +\fB\-c\fR, \fB\-\-casual[=\fR] +example of option with optional argument +.TP +\fB\-o\fR +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. diff --git a/singe/thirdparty/arg_parser/main.cc b/singe/thirdparty/arg_parser/main.cc new file mode 100644 index 000000000..f1c66ca55 --- /dev/null +++ b/singe/thirdparty/arg_parser/main.cc @@ -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 +#include +#include +#include +#include + +#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= example of option with required argument\n" + " -c, --casual[=] example of option with optional argument\n" + " -o 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; + } diff --git a/singe/thirdparty/arg_parser/testsuite/check.sh b/singe/thirdparty/arg_parser/testsuite/check.sh new file mode 100755 index 000000000..a891cda22 --- /dev/null +++ b/singe/thirdparty/arg_parser/testsuite/check.sh @@ -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} diff --git a/singe/thirdparty/arg_parser/testsuite/test.txt b/singe/thirdparty/arg_parser/testsuite/test.txt new file mode 100644 index 000000000..992107bc9 --- /dev/null +++ b/singe/thirdparty/arg_parser/testsuite/test.txt @@ -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' diff --git a/singe/videoPlayer.c b/singe/videoPlayer.c index a0112a991..f9a3a176b 100644 --- a/singe/videoPlayer.c +++ b/singe/videoPlayer.c @@ -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 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); if (v->frameData == NULL) utilDie("%s", v->errInfo.Buffer);