#include #include #include #include "arguments.h" #include "concurrency.h" arguments_t* arguments_init(arguments_t* arguments) { assert(arguments); arguments->error = 0; arguments->help_asked = false; arguments->version_asked = false; arguments->dir_count = 0; arguments->recursive = false; arguments->workers = (size_t)concurrency_cpu_count(); arguments->quiet = false; arguments->silent = false; arguments->unicode = false; arguments->lev_impl = lev_pthreads_guo; return arguments; } int arguments_print_version(void) { printf("levdist v2.3 [2018-oct-18] Jeisson Hidalgo \n"); printf("This is free software with no warranties. Use it at your own risk.\n"); return 0; } int arguments_print_usage(void) { printf("Usage: levdist [-qrsu][-a[dgrs]][-w W] DIRS|FILES\n"); printf("Finds most similar files using Levenshtein distance\n"); printf("\n"); printf("Options:\n"); printf(" --help Prints this help\n"); printf(" --version Prints information about this command\n"); printf(" -ad, --pthreads-diagonal Multi-threaded diagonal comparisons\n"); printf(" -ag, --pthreads-guo Multi-threaded (Guo et al. 2013) algorithm\n"); printf(" -ar, --pthreads-rows Multi-threaded rows comparisons\n"); printf(" -as, --serial Make single-threaded serial comparisons (default)\n"); printf(" -q, --quiet Do not print elapsed time (e.g: for testing)\n"); printf(" -Q, --silent Do not generate output at all (for testing)\n"); printf(" -r, --recursive Analyze files in subdirectories\n"); printf(" -u, --unicode Enable Unicode, otherwise ASCII is used\n"); printf(" -w W Use W workers (threads)\n"); return 0; } arguments_t arguments_analyze(int argc, char* argv[]) { arguments_t arguments; arguments_init(&arguments); for ( int current = 1; current < argc; ++current ) { const char* arg = argv[current]; // Check for an option if ( *arg == '-' ) { // Check for a long --argument if ( arg[1] == '-' ) { if ( strcmp(arg, "--help") == 0 ) arguments.help_asked = true; if ( strcmp(arg, "--version") == 0 ) arguments.version_asked = true; if ( strcmp(arg, "--recursive") == 0 ) arguments.recursive = true; if ( strcmp(arg, "--quiet") == 0 ) arguments.quiet = true; if ( strcmp(arg, "--silent") == 0 ) arguments.silent = true; if ( strcmp(arg, "--unicode") == 0 ) arguments.unicode = true; if ( strcmp(arg, "--serial") == 0 ) arguments.lev_impl = lev_serial; if ( strcmp(arg, "--pthreads-rows") == 0 ) arguments.lev_impl = lev_pthreads_byrows; if ( strcmp(arg, "--pthreads-guo") == 0 ) arguments.lev_impl = lev_pthreads_guo; if ( strcmp(arg, "--pthreads-diagonal") == 0 ) arguments.lev_impl = lev_pthreads_diagonal; } else { // Short argument provided, e.g: -q switch ( arg[1] ) { case 'r': arguments.recursive = true; break; case 'q': arguments.quiet = true; break; case 'Q': arguments.silent = true; break; case 'u': arguments.unicode = true; break; case 'a': { switch ( arg[2] ) { case 'd': arguments.lev_impl = lev_pthreads_diagonal; break; case 'g': arguments.lev_impl = lev_pthreads_guo; break; case 'r': arguments.lev_impl = lev_pthreads_byrows; break; case 's': arguments.lev_impl = lev_serial; break; default: fprintf(stderr, "levdist: error: unknown Levenshtein implementation: %s\n", arg); arguments.error = 4; } break; } case 'w': if ( current < argc - 1 ) { char* str = argv[++current]; long workers = 0; if ( sscanf(str, "%ld", &workers ) == 1 && workers > 0 ) arguments.workers = (size_t)workers; else { fprintf(stderr, "levdist: error: invalid number of workers: %s\n", str); arguments.error = 2; } // Avoid considering this argument as a directory later *str = '-'; } else { fprintf(stderr, "levdist: error: missing number of workers\n"); arguments.error = 3; } break; // Unknown option default: fprintf(stderr, "levdist: error: unknown argument: %s\n", arg); arguments.error = 1; break; } } } else { // It is not an option, assume a directory ++arguments.dir_count; } } return arguments; }