diff --git a/HSFW_management/usefull_macros.h b/HSFW_management/usefull_macros.h index 499aacf..ab968a4 100644 --- a/HSFW_management/usefull_macros.h +++ b/HSFW_management/usefull_macros.h @@ -92,7 +92,7 @@ extern void signals(int sig); */ #define ALLOC(type, var, size) type * var = ((type *)my_alloc(size, sizeof(type))) #define MALLOC(type, size) ((type *)my_alloc(size, sizeof(type))) -#define FREE(ptr) do{free(ptr); ptr = NULL;}while(0) +#define FREE(ptr) do{if(ptr){free(ptr); ptr = NULL;}}while(0) double dtime(); diff --git a/getopt/cmdlnopts/cmdlnopts.c b/getopt/cmdlnopts/cmdlnopts.c index 0d1f1d0..6837a81 100644 --- a/getopt/cmdlnopts/cmdlnopts.c +++ b/getopt/cmdlnopts/cmdlnopts.c @@ -37,79 +37,79 @@ glob_pars G; mirPar M; int rewrite_ifexists = 0, // rewrite existing files == 0 or 1 - verbose = 0; // each -v increments this value, e.g. -vvv sets it to 3 + verbose = 0; // each -v increments this value, e.g. -vvv sets it to 3 // DEFAULTS // default global parameters glob_pars const Gdefault = { - NULL, // size of initial array of surface deviations - 100, // size of interpolated S0 - 1000, // resulting image size - 10000, // amount of photons falled to one pixel of S1 by one iteration - 0, // add to mask random numbers - NULL, // amplitude of added random noice - NULL, // mirror - 0, // rest num - NULL, // rest pars - NULL, // str - NULL // filter + NULL, // size of initial array of surface deviations + 100, // size of interpolated S0 + 1000, // resulting image size + 10000, // amount of photons falled to one pixel of S1 by one iteration + 0, // add to mask random numbers + NULL, // amplitude of added random noice + NULL, // mirror + 0, // rest num + NULL, // rest pars + NULL, // str + NULL // filter }; //default mirror parameters mirPar const Mdefault = { - 6., // diameter - 24.024, // focus - 0., // inclination from Z axe (radians) - 0. // azimuth of inclination (radians) + 6., // diameter + 24.024, // focus + 0., // inclination from Z axe (radians) + 0. // azimuth of inclination (radians) }; // here are functions & definitions for complex parameters (with suboptions etc) bool get_mir_par(void *arg); const char MirPar[] = "set mirror parameters, arg=[diam=num:foc=num:Zincl=ang:Aincl=ang]\n" \ - "\t\t\tALL DEGREES ARE IN FORMAT [+-][DDd][MMm][SS.S] like -10m13.4 !\n" \ - "\t\tdiam - diameter of mirror\n" \ - "\t\tfoc - mirror focus ratio\n" \ - "\t\tZincl - inclination from Z axe\n" \ - "\t\tAincl - azimuth of inclination"; + "\t\t\tALL DEGREES ARE IN FORMAT [+-][DDd][MMm][SS.S] like -10m13.4 !\n" \ + "\t\tdiam - diameter of mirror\n" \ + "\t\tfoc - mirror focus ratio\n" \ + "\t\tZincl - inclination from Z axe\n" \ + "\t\tAincl - azimuth of inclination"; const char FilPar[] = "set filter parameters, arg=[type=type:xsz=num:ysz=num]\n" \ - "\t\ttype - filter type(med, lap, lg)\n" \ - "\t\txsz,ysz - area size (default is 3x3)"; + "\t\ttype - filter type(med, lap, lg)\n" \ + "\t\txsz,ysz - area size (default is 3x3)"; /* * Define command line options by filling structure: - * name has_arg flag val type argptr help + * name has_arg flag val type argptr help */ myoption cmdlnopts[] = { - // set 1 to param despite of its repeating number: - {"help", NO_ARGS, NULL, 'h', arg_int, APTR(&help), "show this help"}, - // simple integer parameter with obligatory arg: - {"int-size",NEED_ARG, NULL, 'i', arg_int, APTR(&G.S_interp), "size of interpolated array of surface deviations"}, - {"image-size",NEED_ARG,NULL, 'I', arg_int, APTR(&G.S_image), "resulting image size"}, - {"N-photons",NEED_ARG,NULL, 'N', arg_int, APTR(&G.N_phot), "amount of photons falled to one pixel of matrix by one iteration"}, - // parameter with suboptions parsed directly in parseargs - {"mir-parameters",NEED_ARG,NULL,'M', arg_function,APTR(&get_mir_par),MirPar}, - // another variant of setting parameter without argument - {"add-noice",NO_ARGS, &G.randMask,1, arg_none, NULL, "add random noice to mirror surface deviations"}, - {"force", NO_ARGS, &rewrite_ifexists,1,arg_none,NULL, "rewrite output file if exists"}, - // incremented parameter without args (any -v will increment value of "verbose") - {"verbose", NO_ARGS, NULL, 'v', arg_none, APTR(&verbose), "verbose level (each -v increase it)"}, - // integer parameter which can occur several times: - {"dev-size",MULT_PAR, NULL, 'd', arg_int, APTR(&G.S_dev), "size of initial array of surface deviations"}, - // double array - {"noice-amp",MULT_PAR, NULL, 'a', arg_double, APTR(&G.randAmp), "amplitude of random noice (default: 1e-8)"}, - // string array - {"str", MULT_PAR, NULL, 's', arg_string, APTR(&G.str), "some string parameters (may meets many times)"}, - // suboptions array that will be parsed outside (the same as string array): - {"filter", MULT_PAR, NULL, 'f', arg_string, APTR(&G.filter), FilPar}, - end_option + // set 1 to param despite of its repeating number: + {"help", NO_ARGS, NULL, 'h', arg_int, APTR(&help), "show this help"}, + // simple integer parameter with obligatory arg: + {"int-size",NEED_ARG, NULL, 'i', arg_int, APTR(&G.S_interp), "size of interpolated array of surface deviations"}, + {"image-size",NEED_ARG,NULL, 'I', arg_int, APTR(&G.S_image), "resulting image size"}, + {"N-photons",NEED_ARG,NULL, 'N', arg_int, APTR(&G.N_phot), "amount of photons falled to one pixel of matrix by one iteration"}, + // parameter with suboptions parsed directly in parseargs + {"mir-parameters",NEED_ARG,NULL,'M', arg_function,APTR(&get_mir_par),MirPar}, + // another variant of setting parameter without argument + {"add-noice",NO_ARGS, &G.randMask,1, arg_none, NULL, "add random noice to mirror surface deviations"}, + {"force", NO_ARGS, &rewrite_ifexists,1,arg_none,NULL, "rewrite output file if exists"}, + // incremented parameter without args (any -v will increment value of "verbose") + {"verbose", NO_ARGS, NULL, 'v', arg_none, APTR(&verbose), "verbose level (each -v increase it)"}, + // integer parameter which can occur several times: + {"dev-size",MULT_PAR, NULL, 'd', arg_int, APTR(&G.S_dev), "size of initial array of surface deviations"}, + // double array + {"noice-amp",MULT_PAR, NULL, 'a', arg_double, APTR(&G.randAmp), "amplitude of random noice (default: 1e-8)"}, + // string array + {"str", MULT_PAR, NULL, 's', arg_string, APTR(&G.str), "some string parameters (may meets many times)"}, + // suboptions array that will be parsed outside (the same as string array): + {"filter", MULT_PAR, NULL, 'f', arg_string, APTR(&G.filter), FilPar}, + end_option }; // suboptions structure for get_mirpars // in array last MUST BE {0,0,0} typedef struct{ - double *val; // pointer to result - char *par; // parameter name (CASE-INSENSITIVE!) - bool isdegr; // == TRUE if parameter is an angle in format "[+-][DDd][MMm][SS.S]" + double *val; // pointer to result + char *par; // parameter name (CASE-INSENSITIVE!) + bool isdegr; // == TRUE if parameter is an angle in format "[+-][DDd][MMm][SS.S]" } suboptions; /** @@ -120,16 +120,16 @@ typedef struct{ * @return TRUE if success */ bool myatod(double *num, const char *str){ - double res; - char *endptr; - assert(str); - res = strtod(str, &endptr); - if(endptr == str || *str == '\0' || *endptr != '\0'){ - printf("Wrong double number format!"); - return FALSE; - } - *num = res; - return TRUE; + double res; + char *endptr; + assert(str); + res = strtod(str, &endptr); + if(endptr == str || *str == '\0' || *endptr != '\0'){ + printf("Wrong double number format!"); + return FALSE; + } + *num = res; + return TRUE; } /** @@ -140,38 +140,38 @@ bool myatod(double *num, const char *str){ * @return TRUE if OK */ bool get_radians(double *ret, char *str){ - double val = 0., ftmp, sign = 1.; - char *ptr; - assert(str); - switch(*str){ // check sign - case '-': - sign = -1.; - case '+': - str++; - } - if((ptr = strchr(str, 'd'))){ // found DDD.DDd - *ptr = 0; if(!myatod(&ftmp, str)) return FALSE; - ftmp = fabs(ftmp); - if(ftmp > 360.){ - printf("Degrees should be less than 360"); - return FALSE; - } - val += ftmp; - str = ptr + 1; - } - if((ptr = strchr(str, 'm'))){ // found DDD.DDm - *ptr = 0; if(!myatod(&ftmp, str)) return FALSE; - ftmp = fabs(ftmp); - val += ftmp / 60.; - str = ptr + 1; - } - if(strlen(str)){ // there is something more - if(!myatod(&ftmp, str)) return FALSE; - ftmp = fabs(ftmp); - val += ftmp / 3600.; - } - *ret = D2R(val * sign); // convert degrees to radians - return TRUE; + double val = 0., ftmp, sign = 1.; + char *ptr; + assert(str); + switch(*str){ // check sign + case '-': + sign = -1.; + case '+': + str++; + } + if((ptr = strchr(str, 'd'))){ // found DDD.DDd + *ptr = 0; if(!myatod(&ftmp, str)) return FALSE; + ftmp = fabs(ftmp); + if(ftmp > 360.){ + printf("Degrees should be less than 360"); + return FALSE; + } + val += ftmp; + str = ptr + 1; + } + if((ptr = strchr(str, 'm'))){ // found DDD.DDm + *ptr = 0; if(!myatod(&ftmp, str)) return FALSE; + ftmp = fabs(ftmp); + val += ftmp / 60.; + str = ptr + 1; + } + if(strlen(str)){ // there is something more + if(!myatod(&ftmp, str)) return FALSE; + ftmp = fabs(ftmp); + val += ftmp / 3600.; + } + *ret = D2R(val * sign); // convert degrees to radians + return TRUE; } /** @@ -185,34 +185,34 @@ bool get_radians(double *ret, char *str){ * @return TRUE if success */ bool get_mirpars(void *arg, suboptions *V){ - char *tok, *val, *par; - int i; - tok = strtok(arg, ":,"); - do{ - if((val = strchr(tok, '=')) == NULL){ // wrong format - printf("Wrong format: no value for keyword"); - return FALSE; - } - *val++ = '\0'; - par = tok; - for(i = 0; V[i].val; i++){ - if(strcasecmp(par, V[i].par) == 0){ // found parameter - if(V[i].isdegr){ // DMS - if(!get_radians(V[i].val, val)) // wrong angle - return FALSE; - }else{ // simple double - if(!myatod(V[i].val, val)) // wrong number - return FALSE; - } - break; - } - } - if(!V[i].val){ // nothing found - wrong format - printf("Bad keyword!"); - return FALSE; - } - }while((tok = strtok(NULL, ":,"))); - return TRUE; + char *tok, *val, *par; + int i; + tok = strtok(arg, ":,"); + do{ + if((val = strchr(tok, '=')) == NULL){ // wrong format + printf("Wrong format: no value for keyword"); + return FALSE; + } + *val++ = '\0'; + par = tok; + for(i = 0; V[i].val; i++){ + if(strcasecmp(par, V[i].par) == 0){ // found parameter + if(V[i].isdegr){ // DMS + if(!get_radians(V[i].val, val)) // wrong angle + return FALSE; + }else{ // simple double + if(!myatod(V[i].val, val)) // wrong number + return FALSE; + } + break; + } + } + if(!V[i].val){ // nothing found - wrong format + printf("Bad keyword!"); + return FALSE; + } + }while((tok = strtok(NULL, ":,"))); + return TRUE; } /** @@ -225,40 +225,40 @@ bool get_mirpars(void *arg, suboptions *V){ * @return TRUE if success */ bool get_mir_par(void *arg){ - suboptions V[] = { // array of mirror parameters and string keys for cmdln pars - {&M.D, "diam", FALSE}, - {&M.F, "foc", FALSE}, - {&M.Zincl, "zincl", TRUE}, - {&M.Aincl, "aincl", TRUE}, - {0,0,0} - }; - return get_mirpars(arg, V); + suboptions V[] = { // array of mirror parameters and string keys for cmdln pars + {&M.D, "diam", FALSE}, + {&M.F, "foc", FALSE}, + {&M.Zincl, "zincl", TRUE}, + {&M.Aincl, "aincl", TRUE}, + {0,0,0} + }; + return get_mirpars(arg, V); } /** * Parse command line options and return dynamically allocated structure - * to global parameters + * to global parameters * @param argc - copy of argc from main * @param argv - copy of argv from main * @return allocated structure with global parameters */ glob_pars *parse_args(int argc, char **argv){ - int i; - void *ptr; - ptr = memcpy(&G, &Gdefault, sizeof(G)); assert(ptr); - ptr = memcpy(&M, &Mdefault, sizeof(M)); assert(ptr); - G.Mirror = &M; - // format of help: "Usage: progname [args]\n" - change_helpstring("Usage: %s [args]\n\n\tWhere args are:\n"); - // parse arguments - parseargs(&argc, &argv, cmdlnopts); - if(help) showhelp(-1, cmdlnopts); - if(argc > 0){ - G.rest_pars_num = argc; - G.rest_pars = calloc(argc, sizeof(char*)); - for (i = 0; i < argc; i++) - G.rest_pars[i] = strdup(argv[i]); - } - return &G; + int i; + void *ptr; + ptr = memcpy(&G, &Gdefault, sizeof(G)); assert(ptr); + ptr = memcpy(&M, &Mdefault, sizeof(M)); assert(ptr); + G.Mirror = &M; + // format of help: "Usage: progname [args]\n" + change_helpstring("Usage: %s [args]\n\n\tWhere args are:\n"); + // parse arguments + parseargs(&argc, &argv, cmdlnopts); + if(help) showhelp(-1, cmdlnopts); + if(argc > 0){ + G.rest_pars_num = argc; + G.rest_pars = calloc(argc, sizeof(char*)); + for (i = 0; i < argc; i++) + G.rest_pars[i] = strdup(argv[i]); + } + return &G; } diff --git a/getopt/cmdlnopts/cmdlnopts.h b/getopt/cmdlnopts/cmdlnopts.h index 72b92ab..f29d07a 100644 --- a/getopt/cmdlnopts/cmdlnopts.h +++ b/getopt/cmdlnopts/cmdlnopts.h @@ -30,24 +30,24 @@ */ // parameters of mirror typedef struct{ - double D; // diameter - double F; // focus - double Zincl; // inclination from Z axe (radians) - double Aincl; // azimuth of inclination (radians) + double D; // diameter + double F; // focus + double Zincl; // inclination from Z axe (radians) + double Aincl; // azimuth of inclination (radians) } mirPar; typedef struct{ - int **S_dev; // size of initial array of surface deviations - int S_interp; // size of interpolated S0 - int S_image; // resulting image size - int N_phot; // amount of photons falled to one pixel of S1 by one iteration - int randMask; // add to mask random numbers - double **randAmp;// amplitude of added random noice - mirPar *Mirror; // mirror parameters - int rest_pars_num;// number of rest parameters - char** rest_pars;// the rest parameters: array of char* - char **str; // string parameters - char **filter; // some filter options + int **S_dev; // size of initial array of surface deviations + int S_interp; // size of interpolated S0 + int S_image; // resulting image size + int N_phot; // amount of photons falled to one pixel of S1 by one iteration + int randMask; // add to mask random numbers + double **randAmp;// amplitude of added random noice + mirPar *Mirror; // mirror parameters + int rest_pars_num;// number of rest parameters + char** rest_pars;// the rest parameters: array of char* + char **str; // string parameters + char **filter; // some filter options } glob_pars; diff --git a/getopt/cmdlnopts/main.c b/getopt/cmdlnopts/main.c index 2bdf07e..b7155df 100644 --- a/getopt/cmdlnopts/main.c +++ b/getopt/cmdlnopts/main.c @@ -23,89 +23,89 @@ #include "cmdlnopts.h" typedef struct{ - char *filtertype; - int xsize; - int ysize; + char *filtertype; + int xsize; + int ysize; } filterpars; void signals(int signo){ - exit(signo); + exit(signo); } void parse_filter(char *pars){ - filterpars params = { 0, 3, 3}; - mysuboption filteropts[] = { - {"type", NEED_ARG, arg_string, ¶ms.filtertype}, - {"xsz", NEED_ARG, arg_int, ¶ms.xsize}, - {"ysz", NEED_ARG, arg_int, ¶ms.ysize}, - end_suboption - }; - if(!get_suboption(pars, filteropts)){ - printf("\tbad params\n"); - }else{ - printf("\tfiltertype = %s, sizes: %dx%d\n", params.filtertype, params.xsize, params.ysize); - } + filterpars params = { 0, 3, 3}; + mysuboption filteropts[] = { + {"type", NEED_ARG, arg_string, ¶ms.filtertype}, + {"xsz", NEED_ARG, arg_int, ¶ms.xsize}, + {"ysz", NEED_ARG, arg_int, ¶ms.ysize}, + end_suboption + }; + if(!get_suboption(pars, filteropts)){ + printf("\tbad params\n"); + }else{ + printf("\tfiltertype = %s, sizes: %dx%d\n", params.filtertype, params.xsize, params.ysize); + } } int main(int argc, char **argv){ - glob_pars *G = NULL; // default parameters see in cmdlnopts.c - mirPar *M = NULL; // default mirror parameters - G = parse_args(argc, argv); - M = G->Mirror; - printf("Globals:\n"); - if(!G->S_dev){ - printf("S_dev = 8 (default)\n"); - }else{ - int i = 0, **vals = G->S_dev; - while(*vals){ - printf("S_dev[%d]: %d\n", i++, **vals++); - } - } - if(!G->randAmp){ - printf("randAmp = 1e-8 (default)\n"); - }else{ - int i = 0; - double **a = G->randAmp; - while(*a){ - printf("randAmp[%d]: %g\n", i++, **a++); - } - } - if(G->str){ - printf("meet str args:\n"); - int i = 0; - char **strs = G->str; - if(!*strs) printf("fucn!\n"); - while(*strs) - printf("str[%d] = %s\n", i++, *strs++); - } - printf("S_interp = %d\n", G->S_interp); - printf("S_image = %d\n", G->S_image); - printf("N_phot = %d\n", G->N_phot); - printf("randMask = %d\n", G->randMask); - printf("Mirror =\n"); - printf("\tD = %g\n", M->D); - printf("\tF = %g\n", M->F); - printf("\tZincl = %g\n", M->Zincl); - printf("\tAincl = %g\n", M->Aincl); - printf("rewrite_ifexists = %d\n", rewrite_ifexists); - printf("verbose = %d\n", verbose); - if(G->rest_pars_num){ - int i; - printf("There's also %d free parameters:\n", G->rest_pars_num); - for(i = 0; i < G->rest_pars_num; ++i) - printf("\t%4d: %s\n", i, G->rest_pars[i]); - } - if(G->filter){ - printf("filter parameters:\n"); - char **fpars = G->filter; - int i = 0; - while(*fpars){ - printf("%d:\n", i++); - parse_filter(*fpars); - ++fpars; - } - } - return 0; + glob_pars *G = NULL; // default parameters see in cmdlnopts.c + mirPar *M = NULL; // default mirror parameters + G = parse_args(argc, argv); + M = G->Mirror; + printf("Globals:\n"); + if(!G->S_dev){ + printf("S_dev = 8 (default)\n"); + }else{ + int i = 0, **vals = G->S_dev; + while(*vals){ + printf("S_dev[%d]: %d\n", i++, **vals++); + } + } + if(!G->randAmp){ + printf("randAmp = 1e-8 (default)\n"); + }else{ + int i = 0; + double **a = G->randAmp; + while(*a){ + printf("randAmp[%d]: %g\n", i++, **a++); + } + } + if(G->str){ + printf("meet str args:\n"); + int i = 0; + char **strs = G->str; + if(!*strs) printf("fucn!\n"); + while(*strs) + printf("str[%d] = %s\n", i++, *strs++); + } + printf("S_interp = %d\n", G->S_interp); + printf("S_image = %d\n", G->S_image); + printf("N_phot = %d\n", G->N_phot); + printf("randMask = %d\n", G->randMask); + printf("Mirror =\n"); + printf("\tD = %g\n", M->D); + printf("\tF = %g\n", M->F); + printf("\tZincl = %g\n", M->Zincl); + printf("\tAincl = %g\n", M->Aincl); + printf("rewrite_ifexists = %d\n", rewrite_ifexists); + printf("verbose = %d\n", verbose); + if(G->rest_pars_num){ + int i; + printf("There's also %d free parameters:\n", G->rest_pars_num); + for(i = 0; i < G->rest_pars_num; ++i) + printf("\t%4d: %s\n", i, G->rest_pars[i]); + } + if(G->filter){ + printf("filter parameters:\n"); + char **fpars = G->filter; + int i = 0; + while(*fpars){ + printf("%d:\n", i++); + parse_filter(*fpars); + ++fpars; + } + } + return 0; } diff --git a/getopt/cmdlnopts/parseargs.c b/getopt/cmdlnopts/parseargs.c index 64bfab1..62c3808 100644 --- a/getopt/cmdlnopts/parseargs.c +++ b/getopt/cmdlnopts/parseargs.c @@ -19,15 +19,15 @@ * MA 02110-1301, USA. */ -#include // printf -#include // getopt_long -#include // calloc, exit, strtoll -#include // assert +#include // printf +#include // getopt_long +#include // calloc, exit, strtoll +#include // assert #include // strdup, strchr, strlen #include // strcasecmp #include // INT_MAX & so on #include // gettext -#include // isalpha +#include // isalpha #include "parseargs.h" #include "usefull_macros.h" @@ -39,23 +39,23 @@ char *helpstring = "%s\n"; * @param str (i) - new format */ void change_helpstring(char *s){ - int pcount = 0, scount = 0; - char *str = s; - // check `helpstring` and set it to default in case of error - for(; pcount < 2; str += 2){ - if(!(str = strchr(str, '%'))) break; - if(str[1] != '%') pcount++; // increment '%' counter if it isn't "%%" - else{ - str += 2; // pass next '%' - continue; - } - if(str[1] == 's') scount++; // increment "%s" counter - }; - if(pcount > 1 || pcount != scount){ // amount of pcount and/or scount wrong - /// "Неправильный формат строки помощи" - ERRX(_("Wrong helpstring!")); - } - helpstring = s; + int pcount = 0, scount = 0; + char *str = s; + // check `helpstring` and set it to default in case of error + for(; pcount < 2; str += 2){ + if(!(str = strchr(str, '%'))) break; + if(str[1] != '%') pcount++; // increment '%' counter if it isn't "%%" + else{ + str += 2; // pass next '%' + continue; + } + if(str[1] == 's') scount++; // increment "%s" counter + }; + if(pcount > 1 || pcount != scount){ // amount of pcount and/or scount wrong + /// "Неправильный формат строки помощи" + ERRX(_("Wrong helpstring!")); + } + helpstring = s; } /** @@ -66,54 +66,54 @@ void change_helpstring(char *s){ * @return TRUE if conversion sone without errors, FALSE otherwise */ static bool myatoll(void *num, char *str, argtype t){ - long long tmp, *llptr; - int *iptr; - char *endptr; - assert(str); - assert(num); - tmp = strtoll(str, &endptr, 0); - if(endptr == str || *str == '\0' || *endptr != '\0') - return FALSE; - switch(t){ - case arg_longlong: - llptr = (long long*) num; - *llptr = tmp; - break; - case arg_int: - default: - if(tmp < INT_MIN || tmp > INT_MAX){ - /// "Целое вне допустимого диапазона" - WARNX(_("Integer out of range")); - return FALSE; - } - iptr = (int*)num; - *iptr = (int)tmp; - } - return TRUE; + long long tmp, *llptr; + int *iptr; + char *endptr; + assert(str); + assert(num); + tmp = strtoll(str, &endptr, 0); + if(endptr == str || *str == '\0' || *endptr != '\0') + return FALSE; + switch(t){ + case arg_longlong: + llptr = (long long*) num; + *llptr = tmp; + break; + case arg_int: + default: + if(tmp < INT_MIN || tmp > INT_MAX){ + /// "Целое вне допустимого диапазона" + WARNX(_("Integer out of range")); + return FALSE; + } + iptr = (int*)num; + *iptr = (int)tmp; + } + return TRUE; } // the same as myatoll but for double // There's no NAN & INF checking here (what if they would be needed?) static bool myatod(void *num, const char *str, argtype t){ - double tmp, *dptr; - float *fptr; - char *endptr; - assert(str); - tmp = strtod(str, &endptr); - if(endptr == str || *str == '\0' || *endptr != '\0') - return FALSE; - switch(t){ - case arg_double: - dptr = (double *) num; - *dptr = tmp; - break; - case arg_float: - default: - fptr = (float *) num; - *fptr = (float)tmp; - break; - } - return TRUE; + double tmp, *dptr; + float *fptr; + char *endptr; + assert(str); + tmp = strtod(str, &endptr); + if(endptr == str || *str == '\0' || *endptr != '\0') + return FALSE; + switch(t){ + case arg_double: + dptr = (double *) num; + *dptr = tmp; + break; + case arg_float: + default: + fptr = (float *) num; + *fptr = (float)tmp; + break; + } + return TRUE; } /** @@ -123,13 +123,13 @@ static bool myatod(void *num, const char *str, argtype t){ * @return index in array */ static int get_optind(int opt, myoption *options){ - int oind; - myoption *opts = options; - assert(opts); - for(oind = 0; opts->name && opts->val != opt; oind++, opts++); - if(!opts->name || opts->val != opt) // no such parameter - showhelp(-1, options); - return oind; + int oind; + myoption *opts = options; + assert(opts); + for(oind = 0; opts->name && opts->val != opt; oind++, opts++); + if(!opts->name || opts->val != opt) // no such parameter + showhelp(-1, options); + return oind; } /** @@ -139,46 +139,46 @@ static int get_optind(int opt, myoption *options){ * @return pointer to new (next) value */ void *get_aptr(void *paptr, argtype type){ - int i = 1; - void **aptr = *((void***)paptr); - if(aptr){ // there's something in array - void **p = aptr; - while(*p++) ++i; - } - size_t sz = 0; - switch(type){ - default: - case arg_none: - /// "Не могу использовать несколько параметров без аргументов!" - ERRX("Can't use multiple args with arg_none!"); - break; - case arg_int: - sz = sizeof(int); - break; - case arg_longlong: - sz = sizeof(long long); - break; - case arg_double: - sz = sizeof(double); - break; - case arg_float: - sz = sizeof(float); - break; - case arg_string: - sz = 0; - break; - /* case arg_function: - sz = sizeof(argfn *); - break;*/ - } - aptr = realloc(aptr, (i + 1) * sizeof(void*)); - *((void***)paptr) = aptr; - aptr[i] = NULL; - if(sz){ - aptr[i - 1] = malloc(sz); - }else - aptr[i - 1] = &aptr[i - 1]; - return aptr[i - 1]; + int i = 1; + void **aptr = *((void***)paptr); + if(aptr){ // there's something in array + void **p = aptr; + while(*p++) ++i; + } + size_t sz = 0; + switch(type){ + default: + case arg_none: + /// "Не могу использовать несколько параметров без аргументов!" + ERRX("Can't use multiple args with arg_none!"); + break; + case arg_int: + sz = sizeof(int); + break; + case arg_longlong: + sz = sizeof(long long); + break; + case arg_double: + sz = sizeof(double); + break; + case arg_float: + sz = sizeof(float); + break; + case arg_string: + sz = 0; + break; + /* case arg_function: + sz = sizeof(argfn *); + break;*/ + } + aptr = realloc(aptr, (i + 1) * sizeof(void*)); + *((void***)paptr) = aptr; + aptr[i] = NULL; + if(sz){ + aptr[i - 1] = malloc(sz); + }else + aptr[i - 1] = &aptr[i - 1]; + return aptr[i - 1]; } @@ -189,145 +189,145 @@ void *get_aptr(void *paptr, argtype type){ * @param argc (io) - address of argc of main(), return value of argc stay after `getopt` * @param argv (io) - address of argv of main(), return pointer to argv stay after `getopt` * BE CAREFUL! if you wanna use full argc & argv, save their original values before - * calling this function + * calling this function * @param options (i) - array of `myoption` for arguments parcing * * @exit: in case of error this function show help & make `exit(-1)` */ void parseargs(int *argc, char ***argv, myoption *options){ - char *short_options, *soptr; - struct option *long_options, *loptr; - size_t optsize, i; - myoption *opts = options; - // check whether there is at least one options - assert(opts); - assert(opts[0].name); - // first we count how much values are in opts - for(optsize = 0; opts->name; optsize++, opts++); - // now we can allocate memory - short_options = calloc(optsize * 3 + 1, 1); // multiply by three for '::' in case of args in opts - long_options = calloc(optsize + 1, sizeof(struct option)); - opts = options; loptr = long_options; soptr = short_options; - // in debug mode check the parameters are not repeated + char *short_options, *soptr; + struct option *long_options, *loptr; + size_t optsize, i; + myoption *opts = options; + // check whether there is at least one options + assert(opts); + assert(opts[0].name); + // first we count how much values are in opts + for(optsize = 0; opts->name; optsize++, opts++); + // now we can allocate memory + short_options = calloc(optsize * 3 + 1, 1); // multiply by three for '::' in case of args in opts + long_options = calloc(optsize + 1, sizeof(struct option)); + opts = options; loptr = long_options; soptr = short_options; + // in debug mode check the parameters are not repeated #ifdef EBUG - char **longlist = MALLOC(char*, optsize); - char *shortlist = MALLOC(char, optsize); + char **longlist = MALLOC(char*, optsize); + char *shortlist = MALLOC(char, optsize); #endif - // fill short/long parameters and make a simple checking - for(i = 0; i < optsize; i++, loptr++, opts++){ - // check - assert(opts->name); // check name + // fill short/long parameters and make a simple checking + for(i = 0; i < optsize; i++, loptr++, opts++){ + // check + assert(opts->name); // check name #ifdef EBUG - longlist[i] = strdup(opts->name); + longlist[i] = strdup(opts->name); #endif - if(opts->has_arg){ - assert(opts->type != arg_none); // check error with arg type - assert(opts->argptr); // check pointer - } - if(opts->type != arg_none) // if there is a flag without arg, check its pointer - assert(opts->argptr); - // fill long_options - // don't do memcmp: what if there would be different alignment? - loptr->name = opts->name; - loptr->has_arg = (opts->has_arg < MULT_PAR) ? opts->has_arg : 1; - loptr->flag = opts->flag; - loptr->val = opts->val; - // fill short options if they are: - if(!opts->flag && opts->val){ + if(opts->has_arg){ + assert(opts->type != arg_none); // check error with arg type + assert(opts->argptr); // check pointer + } + if(opts->type != arg_none) // if there is a flag without arg, check its pointer + assert(opts->argptr); + // fill long_options + // don't do memcmp: what if there would be different alignment? + loptr->name = opts->name; + loptr->has_arg = (opts->has_arg < MULT_PAR) ? opts->has_arg : 1; + loptr->flag = opts->flag; + loptr->val = opts->val; + // fill short options if they are: + if(!opts->flag && opts->val){ #ifdef EBUG - shortlist[i] = (char) opts->val; + shortlist[i] = (char) opts->val; #endif - *soptr++ = opts->val; - if(loptr->has_arg) // add ':' if option has required argument - *soptr++ = ':'; - if(loptr->has_arg == 2) // add '::' if option has optional argument - *soptr++ = ':'; - } - } - // sort all lists & check for repeating + *soptr++ = opts->val; + if(loptr->has_arg) // add ':' if option has required argument + *soptr++ = ':'; + if(loptr->has_arg == 2) // add '::' if option has optional argument + *soptr++ = ':'; + } + } + // sort all lists & check for repeating #ifdef EBUG - int cmpstringp(const void *p1, const void *p2){ - return strcmp(* (char * const *) p1, * (char * const *) p2); - } - int cmpcharp(const void *p1, const void *p2){ - return (int)(*(char * const)p1 - *(char *const)p2); - } - qsort(longlist, optsize, sizeof(char *), cmpstringp); - qsort(shortlist,optsize, sizeof(char), cmpcharp); - char *prevl = longlist[0], prevshrt = shortlist[0]; - for(i = 1; i < optsize; ++i){ - if(longlist[i]){ - if(prevl){ - if(strcmp(prevl, longlist[i]) == 0) ERRX("double long arguments: --%s", prevl); - } - prevl = longlist[i]; - } - if(shortlist[i]){ - if(prevshrt){ - if(prevshrt == shortlist[i]) ERRX("double short arguments: -%c", prevshrt); - } - prevshrt = shortlist[i]; - } - } + int cmpstringp(const void *p1, const void *p2){ + return strcmp(* (char * const *) p1, * (char * const *) p2); + } + int cmpcharp(const void *p1, const void *p2){ + return (int)(*(char * const)p1 - *(char *const)p2); + } + qsort(longlist, optsize, sizeof(char *), cmpstringp); + qsort(shortlist,optsize, sizeof(char), cmpcharp); + char *prevl = longlist[0], prevshrt = shortlist[0]; + for(i = 1; i < optsize; ++i){ + if(longlist[i]){ + if(prevl){ + if(strcmp(prevl, longlist[i]) == 0) ERRX("double long arguments: --%s", prevl); + } + prevl = longlist[i]; + } + if(shortlist[i]){ + if(prevshrt){ + if(prevshrt == shortlist[i]) ERRX("double short arguments: -%c", prevshrt); + } + prevshrt = shortlist[i]; + } + } #endif - // now we have both long_options & short_options and can parse `getopt_long` - while(1){ - int opt; - int oindex = 0, optind = 0; // oindex - number of option in argv, optind - number in options[] - if((opt = getopt_long(*argc, *argv, short_options, long_options, &oindex)) == -1) break; - if(opt == '?'){ - opt = optopt; - optind = get_optind(opt, options); - if(options[optind].has_arg == NEED_ARG || options[optind].has_arg == MULT_PAR) - showhelp(optind, options); // need argument - } - else{ - if(opt == 0 || oindex > 0) optind = oindex; - else optind = get_optind(opt, options); - } - opts = &options[optind]; - if(opt == 0 && opts->has_arg == NO_ARGS) continue; // only long option changing integer flag - // now check option - if(opts->has_arg == NEED_ARG || opts->has_arg == MULT_PAR) - if(!optarg) showhelp(optind, options); // need argument - void *aptr; - if(opts->has_arg == MULT_PAR){ - aptr = get_aptr(opts->argptr, opts->type); - }else - aptr = opts->argptr; - bool result = TRUE; - // even if there is no argument, but argptr != NULL, think that optarg = "1" - if(!optarg) optarg = "1"; - switch(opts->type){ - default: - case arg_none: - if(opts->argptr) *((int*)aptr) += 1; // increment value - break; - case arg_int: - result = myatoll(aptr, optarg, arg_int); - break; - case arg_longlong: - result = myatoll(aptr, optarg, arg_longlong); - break; - case arg_double: - result = myatod(aptr, optarg, arg_double); - break; - case arg_float: - result = myatod(aptr, optarg, arg_float); - break; - case arg_string: - result = (*((void**)aptr) = (void*)strdup(optarg)); - break; - case arg_function: - result = ((argfn)aptr)(optarg); - break; - } - if(!result){ - showhelp(optind, options); - } - } - *argc -= optind; - *argv += optind; + // now we have both long_options & short_options and can parse `getopt_long` + while(1){ + int opt; + int oindex = 0, optind = 0; // oindex - number of option in argv, optind - number in options[] + if((opt = getopt_long(*argc, *argv, short_options, long_options, &oindex)) == -1) break; + if(opt == '?'){ + opt = optopt; + optind = get_optind(opt, options); + if(options[optind].has_arg == NEED_ARG || options[optind].has_arg == MULT_PAR) + showhelp(optind, options); // need argument + } + else{ + if(opt == 0 || oindex > 0) optind = oindex; + else optind = get_optind(opt, options); + } + opts = &options[optind]; + if(opt == 0 && opts->has_arg == NO_ARGS) continue; // only long option changing integer flag + // now check option + if(opts->has_arg == NEED_ARG || opts->has_arg == MULT_PAR) + if(!optarg) showhelp(optind, options); // need argument + void *aptr; + if(opts->has_arg == MULT_PAR){ + aptr = get_aptr(opts->argptr, opts->type); + }else + aptr = opts->argptr; + bool result = TRUE; + // even if there is no argument, but argptr != NULL, think that optarg = "1" + if(!optarg) optarg = "1"; + switch(opts->type){ + default: + case arg_none: + if(opts->argptr) *((int*)aptr) += 1; // increment value + break; + case arg_int: + result = myatoll(aptr, optarg, arg_int); + break; + case arg_longlong: + result = myatoll(aptr, optarg, arg_longlong); + break; + case arg_double: + result = myatod(aptr, optarg, arg_double); + break; + case arg_float: + result = myatod(aptr, optarg, arg_float); + break; + case arg_string: + result = (*((void**)aptr) = (void*)strdup(optarg)); + break; + case arg_function: + result = ((argfn)aptr)(optarg); + break; + } + if(!result){ + showhelp(optind, options); + } + } + *argc -= optind; + *argv += optind; } /** @@ -335,19 +335,19 @@ void parseargs(int *argc, char ***argv, myoption *options){ * first - sort by short options; second - sort arguments without sort opts (by long options) */ static int argsort(const void *a1, const void *a2){ - const myoption *o1 = (myoption*)a1, *o2 = (myoption*)a2; - const char *l1 = o1->name, *l2 = o2->name; - int s1 = o1->val, s2 = o2->val; - int *f1 = o1->flag, *f2 = o2->flag; - // check if both options has short arg - if(f1 == NULL && f2 == NULL){ // both have short arg - return (s1 - s2); - }else if(f1 != NULL && f2 != NULL){ // both don't have short arg - sort by long - return strcmp(l1, l2); - }else{ // only one have short arg -- return it - if(f2) return -1; // a1 have short - it is 'lesser' - else return 1; - } + const myoption *o1 = (myoption*)a1, *o2 = (myoption*)a2; + const char *l1 = o1->name, *l2 = o2->name; + int s1 = o1->val, s2 = o2->val; + int *f1 = o1->flag, *f2 = o2->flag; + // check if both options has short arg + if(f1 == NULL && f2 == NULL){ // both have short arg + return (s1 - s2); + }else if(f1 != NULL && f2 != NULL){ // both don't have short arg - sort by long + return strcmp(l1, l2); + }else{ // only one have short arg -- return it + if(f2) return -1; // a1 have short - it is 'lesser' + else return 1; + } } /** @@ -358,57 +358,57 @@ static int argsort(const void *a1, const void *a2){ * @exit: run `exit(-1)` !!! */ void showhelp(int oindex, myoption *options){ - int max_opt_len = 0; // max len of options substring - for right indentation - const int bufsz = 255; - char buf[bufsz+1]; - myoption *opts = options; - assert(opts); - assert(opts[0].name); // check whether there is at least one options - if(oindex > -1){ // print only one message - opts = &options[oindex]; - printf(" "); - if(!opts->flag && isalpha(opts->val)) printf("-%c, ", opts->val); - printf("--%s", opts->name); - if(opts->has_arg == 1) printf("=arg"); - else if(opts->has_arg == 2) printf("[=arg]"); - printf(" %s\n", _(opts->help)); - exit(-1); - } - // header, by default is just "progname\n" - printf("\n"); - if(strstr(helpstring, "%s")) // print progname - printf(helpstring, __progname); - else // only text - printf("%s", helpstring); - printf("\n"); - // count max_opt_len - do{ - int L = strlen(opts->name); - if(max_opt_len < L) max_opt_len = L; - }while((++opts)->name); - max_opt_len += 14; // format: '-S , --long[=arg]' - get addition 13 symbols - opts = options; - // count amount of options - int N; for(N = 0; opts->name; ++N, ++opts); - if(N == 0) exit(-2); - // Now print all help (sorted) - opts = options; - qsort(opts, N, sizeof(myoption), argsort); - do{ - int p = sprintf(buf, " "); // a little indent - if(!opts->flag && opts->val) // .val is short argument - p += snprintf(buf+p, bufsz-p, "-%c, ", opts->val); - p += snprintf(buf+p, bufsz-p, "--%s", opts->name); - if(opts->has_arg == 1) // required argument - p += snprintf(buf+p, bufsz-p, "=arg"); - else if(opts->has_arg == 2) // optional argument - p += snprintf(buf+p, bufsz-p, "[=arg]"); - assert(p < max_opt_len); // there would be magic if p >= max_opt_len - printf("%-*s%s\n", max_opt_len+1, buf, _(opts->help)); // write options & at least 2 spaces after - ++opts; - }while(--N); - printf("\n\n"); - exit(-1); + int max_opt_len = 0; // max len of options substring - for right indentation + const int bufsz = 255; + char buf[bufsz+1]; + myoption *opts = options; + assert(opts); + assert(opts[0].name); // check whether there is at least one options + if(oindex > -1){ // print only one message + opts = &options[oindex]; + printf(" "); + if(!opts->flag && isalpha(opts->val)) printf("-%c, ", opts->val); + printf("--%s", opts->name); + if(opts->has_arg == 1) printf("=arg"); + else if(opts->has_arg == 2) printf("[=arg]"); + printf(" %s\n", _(opts->help)); + exit(-1); + } + // header, by default is just "progname\n" + printf("\n"); + if(strstr(helpstring, "%s")) // print progname + printf(helpstring, __progname); + else // only text + printf("%s", helpstring); + printf("\n"); + // count max_opt_len + do{ + int L = strlen(opts->name); + if(max_opt_len < L) max_opt_len = L; + }while((++opts)->name); + max_opt_len += 14; // format: '-S , --long[=arg]' - get addition 13 symbols + opts = options; + // count amount of options + int N; for(N = 0; opts->name; ++N, ++opts); + if(N == 0) exit(-2); + // Now print all help (sorted) + opts = options; + qsort(opts, N, sizeof(myoption), argsort); + do{ + int p = sprintf(buf, " "); // a little indent + if(!opts->flag && opts->val) // .val is short argument + p += snprintf(buf+p, bufsz-p, "-%c, ", opts->val); + p += snprintf(buf+p, bufsz-p, "--%s", opts->name); + if(opts->has_arg == 1) // required argument + p += snprintf(buf+p, bufsz-p, "=arg"); + else if(opts->has_arg == 2) // optional argument + p += snprintf(buf+p, bufsz-p, "[=arg]"); + assert(p < max_opt_len); // there would be magic if p >= max_opt_len + printf("%-*s%s\n", max_opt_len+1, buf, _(opts->help)); // write options & at least 2 spaces after + ++opts; + }while(--N); + printf("\n\n"); + exit(-1); } /** @@ -418,80 +418,80 @@ void showhelp(int oindex, myoption *options){ * @return TRUE if all OK */ bool get_suboption(char *str, mysuboption *opt){ - int findsubopt(char *par, mysuboption *so){ - int idx = 0; - if(!par) return -1; - while(so[idx].name){ - if(strcasecmp(par, so[idx].name) == 0) return idx; - ++idx; - } - return -1; // badarg - } - bool opt_setarg(mysuboption *so, int idx, char *val){ - mysuboption *soptr = &so[idx]; - bool result = FALSE; - void *aptr = soptr->argptr; - switch(soptr->type){ - default: - case arg_none: - if(soptr->argptr) *((int*)aptr) += 1; // increment value - result = TRUE; - break; - case arg_int: - result = myatoll(aptr, val, arg_int); - break; - case arg_longlong: - result = myatoll(aptr, val, arg_longlong); - break; - case arg_double: - result = myatod(aptr, val, arg_double); - break; - case arg_float: - result = myatod(aptr, val, arg_float); - break; - case arg_string: - result = (*((void**)aptr) = (void*)strdup(val)); - break; - case arg_function: - result = ((argfn)aptr)(val); - break; - } - return result; - } - char *tok; - bool ret = FALSE; - char *tmpbuf; - tok = strtok_r(str, ":,", &tmpbuf); - do{ - char *val = strchr(tok, '='); - int noarg = 0; - if(val == NULL){ // no args - val = "1"; - noarg = 1; - }else{ - *val++ = '\0'; - if(!*val || *val == ':' || *val == ','){ // no argument - delimeter after = - val = "1"; noarg = 1; - } - } - int idx = findsubopt(tok, opt); - if(idx < 0){ - /// "Неправильный параметр: %s" - WARNX(_("Wrong parameter: %s"), tok); - goto returning; - } - if(noarg && opt[idx].has_arg == NEED_ARG){ - /// "%s: необходим аргумент!" - WARNX(_("%s: argument needed!"), tok); - goto returning; - } - if(!opt_setarg(opt, idx, val)){ - /// "Неправильный аргумент \"%s\" параметра \"%s\"" - WARNX(_("Wrong argument \"%s\" of parameter \"%s\""), val, tok); - goto returning; - } - }while((tok = strtok_r(NULL, ":,", &tmpbuf))); - ret = TRUE; + int findsubopt(char *par, mysuboption *so){ + int idx = 0; + if(!par) return -1; + while(so[idx].name){ + if(strcasecmp(par, so[idx].name) == 0) return idx; + ++idx; + } + return -1; // badarg + } + bool opt_setarg(mysuboption *so, int idx, char *val){ + mysuboption *soptr = &so[idx]; + bool result = FALSE; + void *aptr = soptr->argptr; + switch(soptr->type){ + default: + case arg_none: + if(soptr->argptr) *((int*)aptr) += 1; // increment value + result = TRUE; + break; + case arg_int: + result = myatoll(aptr, val, arg_int); + break; + case arg_longlong: + result = myatoll(aptr, val, arg_longlong); + break; + case arg_double: + result = myatod(aptr, val, arg_double); + break; + case arg_float: + result = myatod(aptr, val, arg_float); + break; + case arg_string: + result = (*((void**)aptr) = (void*)strdup(val)); + break; + case arg_function: + result = ((argfn)aptr)(val); + break; + } + return result; + } + char *tok; + bool ret = FALSE; + char *tmpbuf; + tok = strtok_r(str, ":,", &tmpbuf); + do{ + char *val = strchr(tok, '='); + int noarg = 0; + if(val == NULL){ // no args + val = "1"; + noarg = 1; + }else{ + *val++ = '\0'; + if(!*val || *val == ':' || *val == ','){ // no argument - delimeter after = + val = "1"; noarg = 1; + } + } + int idx = findsubopt(tok, opt); + if(idx < 0){ + /// "Неправильный параметр: %s" + WARNX(_("Wrong parameter: %s"), tok); + goto returning; + } + if(noarg && opt[idx].has_arg == NEED_ARG){ + /// "%s: необходим аргумент!" + WARNX(_("%s: argument needed!"), tok); + goto returning; + } + if(!opt_setarg(opt, idx, val)){ + /// "Неправильный аргумент \"%s\" параметра \"%s\"" + WARNX(_("Wrong argument \"%s\" of parameter \"%s\""), val, tok); + goto returning; + } + }while((tok = strtok_r(NULL, ":,", &tmpbuf))); + ret = TRUE; returning: - return ret; + return ret; } diff --git a/getopt/cmdlnopts/parseargs.h b/getopt/cmdlnopts/parseargs.h index b8351d9..a0ac099 100644 --- a/getopt/cmdlnopts/parseargs.h +++ b/getopt/cmdlnopts/parseargs.h @@ -26,11 +26,11 @@ #include #ifndef TRUE - #define TRUE true + #define TRUE true #endif #ifndef FALSE - #define FALSE false + #define FALSE false #endif // macro for argptr @@ -44,35 +44,35 @@ typedef bool(*argfn)(void *arg); * WARNING! * My function change value of flags by pointer, so if you want to use another type * make a latter conversion, example: - * char charg; - * int iarg; - * myoption opts[] = { - * {"value", 1, NULL, 'v', arg_int, &iarg, "char val"}, ..., end_option}; - * ..(parse args).. - * charg = (char) iarg; + * char charg; + * int iarg; + * myoption opts[] = { + * {"value", 1, NULL, 'v', arg_int, &iarg, "char val"}, ..., end_option}; + * ..(parse args).. + * charg = (char) iarg; */ typedef enum { - arg_none = 0, // no arg - arg_int, // integer - arg_longlong, // long long - arg_double, // double - arg_float, // float - arg_string, // char * - arg_function // parse_args will run function `bool (*fn)(char *optarg, int N)` + arg_none = 0, // no arg + arg_int, // integer + arg_longlong, // long long + arg_double, // double + arg_float, // float + arg_string, // char * + arg_function // parse_args will run function `bool (*fn)(char *optarg, int N)` } argtype; /* * Structure for getopt_long & help * BE CAREFUL: .argptr is pointer to data or pointer to function, - * conversion depends on .type + * conversion depends on .type * * ATTENTION: string `help` prints through macro PRNT(), bu default it is gettext, * but you can redefine it before `#include "parseargs.h"` * * if arg is string, then value wil be strdup'ed like that: - * char *str; - * myoption opts[] = {{"string", 1, NULL, 's', arg_string, &str, "string val"}, ..., end_option}; - * *(opts[1].str) = strdup(optarg); + * char *str; + * myoption opts[] = {{"string", 1, NULL, 's', arg_string, &str, "string val"}, ..., end_option}; + * *(opts[1].str) = strdup(optarg); * in other cases argptr should be address of some variable (or pointer to allocated memory) * * NON-NULL argptr should be written inside macro APTR(argptr) or directly: (void*)argptr @@ -81,22 +81,22 @@ typedef enum { * */ typedef enum{ - NO_ARGS = 0, // first three are the same as in getopt_long - NEED_ARG = 1, - OPT_ARG = 2, - MULT_PAR + NO_ARGS = 0, // first three are the same as in getopt_long + NEED_ARG = 1, + OPT_ARG = 2, + MULT_PAR } hasarg; typedef struct{ - // these are from struct option: - const char *name; // long option's name - hasarg has_arg; // 0 - no args, 1 - nesessary arg, 2 - optionally arg, 4 - need arg & key can repeat (args are stored in null-terminated array) - int *flag; // NULL to return val, pointer to int - to set its value of val (function returns 0) - int val; // short opt name (if flag == NULL) or flag's value - // and these are mine: - argtype type; // type of argument - void *argptr; // pointer to variable to assign optarg value or function `bool (*fn)(char *optarg, int N)` - const char *help; // help string which would be shown in function `showhelp` or NULL + // these are from struct option: + const char *name; // long option's name + hasarg has_arg; // 0 - no args, 1 - nesessary arg, 2 - optionally arg, 4 - need arg & key can repeat (args are stored in null-terminated array) + int *flag; // NULL to return val, pointer to int - to set its value of val (function returns 0) + int val; // short opt name (if flag == NULL) or flag's value + // and these are mine: + argtype type; // type of argument + void *argptr; // pointer to variable to assign optarg value or function `bool (*fn)(char *optarg, int N)` + const char *help; // help string which would be shown in function `showhelp` or NULL } myoption; /* @@ -104,10 +104,10 @@ typedef struct{ * used in parse_subopts() */ typedef struct{ - const char *name; - hasarg has_arg; - argtype type; - void *argptr; + const char *name; + hasarg has_arg; + argtype type; + void *argptr; } mysuboption; // last string of array (all zeros) diff --git a/getopt/cmdlnopts/usefull_macros.c b/getopt/cmdlnopts/usefull_macros.c index f97c181..17ddf8d 100644 --- a/getopt/cmdlnopts/usefull_macros.c +++ b/getopt/cmdlnopts/usefull_macros.c @@ -26,11 +26,11 @@ * @return double value: time in seconds */ double dtime(){ - double t; - struct timeval tv; - gettimeofday(&tv, NULL); - t = tv.tv_sec + ((double)tv.tv_usec)/1e6; - return t; + double t; + struct timeval tv; + gettimeofday(&tv, NULL); + t = tv.tv_sec + ((double)tv.tv_usec)/1e6; + return t; } /******************************************************************************\ @@ -50,22 +50,22 @@ int (*_WARN)(const char *fmt, ...); * @return number of printed symbols */ int r_pr_(const char *fmt, ...){ - va_list ar; int i; - printf(RED); - va_start(ar, fmt); - i = vprintf(fmt, ar); - va_end(ar); - printf(OLDCOLOR); - return i; + va_list ar; int i; + printf(RED); + va_start(ar, fmt); + i = vprintf(fmt, ar); + va_end(ar); + printf(OLDCOLOR); + return i; } int g_pr_(const char *fmt, ...){ - va_list ar; int i; - printf(GREEN); - va_start(ar, fmt); - i = vprintf(fmt, ar); - va_end(ar); - printf(OLDCOLOR); - return i; + va_list ar; int i; + printf(GREEN); + va_start(ar, fmt); + i = vprintf(fmt, ar); + va_end(ar); + printf(OLDCOLOR); + return i; } /* * print red error/warning messages (if output is a tty) @@ -73,20 +73,20 @@ int g_pr_(const char *fmt, ...){ * @return number of printed symbols */ int r_WARN(const char *fmt, ...){ - va_list ar; int i = 1; - fprintf(stderr, RED); - va_start(ar, fmt); - if(globErr){ - errno = globErr; - vwarn(fmt, ar); - errno = 0; - globErr = 0; - }else - i = vfprintf(stderr, fmt, ar); - va_end(ar); - i++; - fprintf(stderr, OLDCOLOR "\n"); - return i; + va_list ar; int i = 1; + fprintf(stderr, RED); + va_start(ar, fmt); + if(globErr){ + errno = globErr; + vwarn(fmt, ar); + errno = 0; + globErr = 0; + }else + i = vfprintf(stderr, fmt, ar); + va_end(ar); + i++; + fprintf(stderr, OLDCOLOR "\n"); + return i; } static const char stars[] = "****************************************"; @@ -97,49 +97,49 @@ static const char stars[] = "****************************************"; * @return number of printed symbols */ int s_WARN(const char *fmt, ...){ - va_list ar; int i; - i = fprintf(stderr, "\n%s\n", stars); - va_start(ar, fmt); - if(globErr){ - errno = globErr; - vwarn(fmt, ar); - errno = 0; - globErr = 0; - }else - i = +vfprintf(stderr, fmt, ar); - va_end(ar); - i += fprintf(stderr, "\n%s\n", stars); - i += fprintf(stderr, "\n"); - return i; + va_list ar; int i; + i = fprintf(stderr, "\n%s\n", stars); + va_start(ar, fmt); + if(globErr){ + errno = globErr; + vwarn(fmt, ar); + errno = 0; + globErr = 0; + }else + i = +vfprintf(stderr, fmt, ar); + va_end(ar); + i += fprintf(stderr, "\n%s\n", stars); + i += fprintf(stderr, "\n"); + return i; } int r_pr_notty(const char *fmt, ...){ - va_list ar; int i; - i = printf("\n%s\n", stars); - va_start(ar, fmt); - i += vprintf(fmt, ar); - va_end(ar); - i += printf("\n%s\n", stars); - return i; + va_list ar; int i; + i = printf("\n%s\n", stars); + va_start(ar, fmt); + i += vprintf(fmt, ar); + va_end(ar); + i += printf("\n%s\n", stars); + return i; } /** * Run this function in the beginning of main() to setup locale & coloured output */ void initial_setup(){ - // setup coloured output - if(isatty(STDOUT_FILENO)){ // make color output in tty - red = r_pr_; green = g_pr_; - }else{ // no colors in case of pipe - red = r_pr_notty; green = printf; - } - if(isatty(STDERR_FILENO)) _WARN = r_WARN; - else _WARN = s_WARN; - // Setup locale - setlocale(LC_ALL, ""); - setlocale(LC_NUMERIC, "C"); + // setup coloured output + if(isatty(STDOUT_FILENO)){ // make color output in tty + red = r_pr_; green = g_pr_; + }else{ // no colors in case of pipe + red = r_pr_notty; green = printf; + } + if(isatty(STDERR_FILENO)) _WARN = r_WARN; + else _WARN = s_WARN; + // Setup locale + setlocale(LC_ALL, ""); + setlocale(LC_NUMERIC, "C"); #if defined GETTEXT_PACKAGE && defined LOCALEDIR - bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR); - textdomain(GETTEXT_PACKAGE); + bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR); + textdomain(GETTEXT_PACKAGE); #endif } @@ -153,10 +153,10 @@ void initial_setup(){ * @return pointer to allocated memory area */ void *my_alloc(size_t N, size_t S){ - void *p = calloc(N, S); - if(!p) ERR("malloc"); - //assert(p); - return p; + void *p = calloc(N, S); + if(!p) ERR("malloc"); + //assert(p); + return p; } /** @@ -166,29 +166,29 @@ void *my_alloc(size_t N, size_t S){ * @return stuct with mmap'ed file or die */ mmapbuf *My_mmap(char *filename){ - int fd; - char *ptr; - size_t Mlen; - struct stat statbuf; - if(!filename) ERRX(_("No filename given!")); - if((fd = open(filename, O_RDONLY)) < 0) - ERR(_("Can't open %s for reading"), filename); - if(fstat (fd, &statbuf) < 0) - ERR(_("Can't stat %s"), filename); - Mlen = statbuf.st_size; - if((ptr = mmap (0, Mlen, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED) - ERR(_("Mmap error for input")); - if(close(fd)) ERR(_("Can't close mmap'ed file")); - mmapbuf *ret = MALLOC(mmapbuf, 1); - ret->data = ptr; - ret->len = Mlen; - return ret; + int fd; + char *ptr; + size_t Mlen; + struct stat statbuf; + if(!filename) ERRX(_("No filename given!")); + if((fd = open(filename, O_RDONLY)) < 0) + ERR(_("Can't open %s for reading"), filename); + if(fstat (fd, &statbuf) < 0) + ERR(_("Can't stat %s"), filename); + Mlen = statbuf.st_size; + if((ptr = mmap (0, Mlen, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED) + ERR(_("Mmap error for input")); + if(close(fd)) ERR(_("Can't close mmap'ed file")); + mmapbuf *ret = MALLOC(mmapbuf, 1); + ret->data = ptr; + ret->len = Mlen; + return ret; } void My_munmap(mmapbuf *b){ - if(munmap(b->data, b->len)) - ERR(_("Can't munmap")); - FREE(b); + if(munmap(b->data, b->len)) + ERR(_("Can't munmap")); + FREE(b); } @@ -199,23 +199,23 @@ static struct termios oldt, newt; // terminal flags static int console_changed = 0; // run on exit: void restore_console(){ - if(console_changed) - tcsetattr(STDIN_FILENO, TCSANOW, &oldt); // return terminal to previous state - console_changed = 0; + if(console_changed) + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); // return terminal to previous state + console_changed = 0; } // initial setup: void setup_con(){ - if(console_changed) return; - tcgetattr(STDIN_FILENO, &oldt); - newt = oldt; - newt.c_lflag &= ~(ICANON | ECHO); - if(tcsetattr(STDIN_FILENO, TCSANOW, &newt) < 0){ - WARN(_("Can't setup console")); - tcsetattr(STDIN_FILENO, TCSANOW, &oldt); - signals(0); //quit? - } - console_changed = 1; + if(console_changed) return; + tcgetattr(STDIN_FILENO, &oldt); + newt = oldt; + newt.c_lflag &= ~(ICANON | ECHO); + if(tcsetattr(STDIN_FILENO, TCSANOW, &newt) < 0){ + WARN(_("Can't setup console")); + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); + signals(0); //quit? + } + console_changed = 1; } /** @@ -223,20 +223,20 @@ void setup_con(){ * @return char readed */ int read_console(){ - int rb; - struct timeval tv; - int retval; - fd_set rfds; - FD_ZERO(&rfds); - FD_SET(STDIN_FILENO, &rfds); - tv.tv_sec = 0; tv.tv_usec = 10000; - retval = select(1, &rfds, NULL, NULL, &tv); - if(!retval) rb = 0; - else { - if(FD_ISSET(STDIN_FILENO, &rfds)) rb = getchar(); - else rb = 0; - } - return rb; + int rb; + struct timeval tv; + int retval; + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(STDIN_FILENO, &rfds); + tv.tv_sec = 0; tv.tv_usec = 10000; + retval = select(1, &rfds, NULL, NULL, &tv); + if(!retval) rb = 0; + else { + if(FD_ISSET(STDIN_FILENO, &rfds)) rb = getchar(); + else rb = 0; + } + return rb; } /** @@ -245,10 +245,10 @@ int read_console(){ * @return character readed */ int mygetchar(){ // getchar() without need of pressing ENTER - int ret; - do ret = read_console(); - while(ret == 0); - return ret; + int ret; + do ret = read_console(); + while(ret == 0); + return ret; } @@ -260,10 +260,10 @@ static int comfd = -1; // TTY fd // run on exit: void restore_tty(){ - if(comfd == -1) return; - ioctl(comfd, TCSANOW, &oldtty ); // return TTY to previous state - close(comfd); - comfd = -1; + if(comfd == -1) return; + ioctl(comfd, TCSANOW, &oldtty ); // return TTY to previous state + close(comfd); + comfd = -1; } #ifndef BAUD_RATE @@ -271,29 +271,29 @@ void restore_tty(){ #endif // init: void tty_init(char *comdev){ - DBG("\nOpen port...\n"); - if ((comfd = open(comdev,O_RDWR|O_NOCTTY|O_NONBLOCK)) < 0){ - WARN("Can't use port %s\n",comdev); - ioctl(comfd, TCSANOW, &oldtty); // return TTY to previous state - close(comfd); - signals(0); // quit? - } - DBG(" OK\nGet current settings... "); - if(ioctl(comfd,TCGETA,&oldtty) < 0){ // Get settings - WARN(_("Can't get settings")); - signals(0); - } - tty = oldtty; - tty.c_lflag = 0; // ~(ICANON | ECHO | ECHOE | ISIG) - tty.c_oflag = 0; - tty.c_cflag = BAUD_RATE|CS8|CREAD|CLOCAL; // 9.6k, 8N1, RW, ignore line ctrl - tty.c_cc[VMIN] = 0; // non-canonical mode - tty.c_cc[VTIME] = 5; - if(ioctl(comfd,TCSETA,&tty) < 0){ - WARN(_("Can't set settings")); - signals(0); - } - DBG(" OK\n"); + DBG("\nOpen port...\n"); + if ((comfd = open(comdev,O_RDWR|O_NOCTTY|O_NONBLOCK)) < 0){ + WARN("Can't use port %s\n",comdev); + ioctl(comfd, TCSANOW, &oldtty); // return TTY to previous state + close(comfd); + signals(0); // quit? + } + DBG(" OK\nGet current settings... "); + if(ioctl(comfd,TCGETA,&oldtty) < 0){ // Get settings + WARN(_("Can't get settings")); + signals(0); + } + tty = oldtty; + tty.c_lflag = 0; // ~(ICANON | ECHO | ECHOE | ISIG) + tty.c_oflag = 0; + tty.c_cflag = BAUD_RATE|CS8|CREAD|CLOCAL; // 9.6k, 8N1, RW, ignore line ctrl + tty.c_cc[VMIN] = 0; // non-canonical mode + tty.c_cc[VTIME] = 5; + if(ioctl(comfd,TCSETA,&tty) < 0){ + WARN(_("Can't set settings")); + signals(0); + } + DBG(" OK\n"); } /** * Read data from TTY @@ -302,26 +302,26 @@ void tty_init(char *comdev){ * @return amount of readed bytes */ size_t read_tty(uint8_t *buff, size_t length){ - ssize_t L = 0; - fd_set rfds; - struct timeval tv; - int retval; - FD_ZERO(&rfds); - FD_SET(comfd, &rfds); - tv.tv_sec = 0; tv.tv_usec = 50000; // wait for 50ms - retval = select(comfd + 1, &rfds, NULL, NULL, &tv); - if (!retval) return 0; - if(FD_ISSET(comfd, &rfds)){ - if((L = read(comfd, buff, length)) < 1) return 0; - } - return (size_t)L; + ssize_t L = 0; + fd_set rfds; + struct timeval tv; + int retval; + FD_ZERO(&rfds); + FD_SET(comfd, &rfds); + tv.tv_sec = 0; tv.tv_usec = 50000; // wait for 50ms + retval = select(comfd + 1, &rfds, NULL, NULL, &tv); + if (!retval) return 0; + if(FD_ISSET(comfd, &rfds)){ + if((L = read(comfd, buff, length)) < 1) return 0; + } + return (size_t)L; } int write_tty(uint8_t *buff, size_t length){ - ssize_t L = write(comfd, buff, length); - if((size_t)L != length){ - WARN("Write error!"); - return 1; - } - return 0; + ssize_t L = write(comfd, buff, length); + if((size_t)L != length){ + WARN("Write error!"); + return 1; + } + return 0; } diff --git a/getopt/cmdlnopts/usefull_macros.h b/getopt/cmdlnopts/usefull_macros.h index 499aacf..52dd4fa 100644 --- a/getopt/cmdlnopts/usefull_macros.h +++ b/getopt/cmdlnopts/usefull_macros.h @@ -38,12 +38,12 @@ * GETTEXT */ #include -#define _(String) gettext(String) -#define gettext_noop(String) String -#define N_(String) gettext_noop(String) +#define _(String) gettext(String) +#define gettext_noop(String) String +#define N_(String) gettext_noop(String) #else -#define _(String) (String) -#define N_(String) (String) +#define _(String) (String) +#define N_(String) (String) #endif #include #include @@ -59,9 +59,9 @@ /* * Coloured messages output */ -#define RED "\033[1;31;40m" -#define GREEN "\033[1;32;40m" -#define OLDCOLOR "\033[0;0;0m" +#define RED "\033[1;31;40m" +#define GREEN "\033[1;32;40m" +#define OLDCOLOR "\033[0;0;0m" /* * ERROR/WARNING messages @@ -78,13 +78,13 @@ extern void signals(int sig); * debug mode, -DEBUG */ #ifdef EBUG - #define FNAME() fprintf(stderr, "\n%s (%s, line %d)\n", __func__, __FILE__, __LINE__) - #define DBG(...) do{fprintf(stderr, "%s (%s, line %d): ", __func__, __FILE__, __LINE__); \ - fprintf(stderr, __VA_ARGS__); \ - fprintf(stderr, "\n");} while(0) + #define FNAME() fprintf(stderr, "\n%s (%s, line %d)\n", __func__, __FILE__, __LINE__) + #define DBG(...) do{fprintf(stderr, "%s (%s, line %d): ", __func__, __FILE__, __LINE__); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n");} while(0) #else - #define FNAME() do{}while(0) - #define DBG(...) do{}while(0) + #define FNAME() do{}while(0) + #define DBG(...) do{}while(0) #endif //EBUG /* @@ -92,7 +92,7 @@ extern void signals(int sig); */ #define ALLOC(type, var, size) type * var = ((type *)my_alloc(size, sizeof(type))) #define MALLOC(type, size) ((type *)my_alloc(size, sizeof(type))) -#define FREE(ptr) do{free(ptr); ptr = NULL;}while(0) +#define FREE(ptr) do{free(ptr); ptr = NULL;}while(0) double dtime(); @@ -105,8 +105,8 @@ void initial_setup(); // mmap file typedef struct{ - char *data; - size_t len; + char *data; + size_t len; } mmapbuf; mmapbuf *My_mmap(char *filename); void My_munmap(mmapbuf *b); diff --git a/usefull_macros.c b/usefull_macros.c index d6f5b2a..5eb9e7b 100644 --- a/usefull_macros.c +++ b/usefull_macros.c @@ -21,18 +21,16 @@ #include "usefull_macros.h" - -#include /** * function for different purposes that need to know time intervals * @return double value: time in seconds */ double dtime(){ - double t; - struct timeval tv; - gettimeofday(&tv, NULL); - t = tv.tv_sec + ((double)tv.tv_usec)/1e6; - return t; + double t; + struct timeval tv; + gettimeofday(&tv, NULL); + t = tv.tv_sec + ((double)tv.tv_usec)/1e6; + return t; } /******************************************************************************\ @@ -52,22 +50,22 @@ int (*_WARN)(const char *fmt, ...); * @return number of printed symbols */ int r_pr_(const char *fmt, ...){ - va_list ar; int i; - printf(RED); - va_start(ar, fmt); - i = vprintf(fmt, ar); - va_end(ar); - printf(OLDCOLOR); - return i; + va_list ar; int i; + printf(RED); + va_start(ar, fmt); + i = vprintf(fmt, ar); + va_end(ar); + printf(OLDCOLOR); + return i; } int g_pr_(const char *fmt, ...){ - va_list ar; int i; - printf(GREEN); - va_start(ar, fmt); - i = vprintf(fmt, ar); - va_end(ar); - printf(OLDCOLOR); - return i; + va_list ar; int i; + printf(GREEN); + va_start(ar, fmt); + i = vprintf(fmt, ar); + va_end(ar); + printf(OLDCOLOR); + return i; } /* * print red error/warning messages (if output is a tty) @@ -75,23 +73,23 @@ int g_pr_(const char *fmt, ...){ * @return number of printed symbols */ int r_WARN(const char *fmt, ...){ - va_list ar; int i = 1; - fprintf(stderr, RED); - va_start(ar, fmt); - if(globErr){ - errno = globErr; - vwarn(fmt, ar); - errno = 0; - globErr = 0; - }else - i = vfprintf(stderr, fmt, ar); - va_end(ar); - i++; - fprintf(stderr, OLDCOLOR "\n"); - return i; + va_list ar; int i = 1; + fprintf(stderr, RED); + va_start(ar, fmt); + if(globErr){ + errno = globErr; + vwarn(fmt, ar); + errno = 0; + globErr = 0; + }else + i = vfprintf(stderr, fmt, ar); + va_end(ar); + i++; + fprintf(stderr, OLDCOLOR "\n"); + return i; } -const char stars[] = "****************************************"; +static const char stars[] = "****************************************"; /* * notty variants of coloured printf * name: s_WARN, r_pr_notty @@ -99,48 +97,50 @@ const char stars[] = "****************************************"; * @return number of printed symbols */ int s_WARN(const char *fmt, ...){ - va_list ar; int i; - i = fprintf(stderr, "\n%s\n", stars); - va_start(ar, fmt); - if(globErr){ - errno = globErr; - vwarn(fmt, ar); - errno = 0; - globErr = 0; - }else - i = +vfprintf(stderr, fmt, ar); - va_end(ar); - i += fprintf(stderr, "\n%s\n", stars); - i += fprintf(stderr, "\n"); - return i; + va_list ar; int i; + i = fprintf(stderr, "\n%s\n", stars); + va_start(ar, fmt); + if(globErr){ + errno = globErr; + vwarn(fmt, ar); + errno = 0; + globErr = 0; + }else + i = +vfprintf(stderr, fmt, ar); + va_end(ar); + i += fprintf(stderr, "\n%s\n", stars); + i += fprintf(stderr, "\n"); + return i; } int r_pr_notty(const char *fmt, ...){ - va_list ar; int i; - i = printf("\n%s\n", stars); - va_start(ar, fmt); - i += vprintf(fmt, ar); - va_end(ar); - i += printf("\n%s\n", stars); - return i; + va_list ar; int i; + i = printf("\n%s\n", stars); + va_start(ar, fmt); + i += vprintf(fmt, ar); + va_end(ar); + i += printf("\n%s\n", stars); + return i; } /** * Run this function in the beginning of main() to setup locale & coloured output */ void initial_setup(){ - // setup coloured output - if(isatty(STDOUT_FILENO)){ // make color output in tty - red = r_pr_; green = g_pr_; - }else{ // no colors in case of pipe - red = r_pr_notty; green = printf; - } - if(isatty(STDERR_FILENO)) _WARN = r_WARN; - else _WARN = s_WARN; - // Setup locale - setlocale(LC_ALL, ""); - setlocale(LC_NUMERIC, "C"); - bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR); - textdomain(GETTEXT_PACKAGE); + // setup coloured output + if(isatty(STDOUT_FILENO)){ // make color output in tty + red = r_pr_; green = g_pr_; + }else{ // no colors in case of pipe + red = r_pr_notty; green = printf; + } + if(isatty(STDERR_FILENO)) _WARN = r_WARN; + else _WARN = s_WARN; + // Setup locale + setlocale(LC_ALL, ""); + setlocale(LC_NUMERIC, "C"); +#if defined GETTEXT_PACKAGE && defined LOCALEDIR + bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR); + textdomain(GETTEXT_PACKAGE); +#endif } /******************************************************************************\ @@ -153,17 +153,12 @@ void initial_setup(){ * @return pointer to allocated memory area */ void *my_alloc(size_t N, size_t S){ - void *p = calloc(N, S); - if(!p) ERR("malloc"); - //assert(p); - return p; + void *p = calloc(N, S); + if(!p) ERR("malloc"); + //assert(p); + return p; } -/* -#include -#include -#include -#include -*/ + /** * Mmap file to a memory area * @@ -171,53 +166,75 @@ void *my_alloc(size_t N, size_t S){ * @return stuct with mmap'ed file or die */ mmapbuf *My_mmap(char *filename){ - int fd; - char *ptr; - size_t Mlen; - struct stat statbuf; - if(!filename) ERRX(_("No filename given!")); - if((fd = open(filename, O_RDONLY)) < 0) - ERR(_("Can't open %s for reading"), filename); - if(fstat (fd, &statbuf) < 0) - ERR(_("Can't stat %s"), filename); - Mlen = statbuf.st_size; - if((ptr = mmap (0, Mlen, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED) - ERR(_("Mmap error for input")); - if(close(fd)) ERR(_("Can't close mmap'ed file")); - mmapbuf *ret = MALLOC(mmapbuf, 1); - ret->data = ptr; - ret->len = Mlen; - return ret; + int fd; + char *ptr; + size_t Mlen; + struct stat statbuf; + /// "Не задано имя файла!" + if(!filename){ + WARNX(_("No filename given!")); + return NULL; + } + if((fd = open(filename, O_RDONLY)) < 0){ + /// "Не могу открыть %s для чтения" + WARN(_("Can't open %s for reading"), filename); + return NULL; + } + if(fstat (fd, &statbuf) < 0){ + /// "Не могу выполнить stat %s" + WARN(_("Can't stat %s"), filename); + close(fd); + return NULL; + } + Mlen = statbuf.st_size; + if((ptr = mmap (0, Mlen, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED){ + /// "Ошибка mmap" + WARN(_("Mmap error for input")); + close(fd); + return NULL; + } + /// "Не могу закрыть mmap'нутый файл" + if(close(fd)) WARN(_("Can't close mmap'ed file")); + mmapbuf *ret = MALLOC(mmapbuf, 1); + ret->data = ptr; + ret->len = Mlen; + return ret; } void My_munmap(mmapbuf *b){ - if(munmap(b->data, b->len)) - ERR(_("Can't munmap")); - FREE(b); + if(munmap(b->data, b->len)){ + /// "Не могу munmap" + ERR(_("Can't munmap")); + } + FREE(b); } /******************************************************************************\ * Terminal in no-echo mode \******************************************************************************/ -struct termios oldt, newt; // terminal flags +static struct termios oldt, newt; // terminal flags +static int console_changed = 0; // run on exit: -/* -void quit(int sig){ - //... - tcsetattr(STDIN_FILENO, TCSANOW, &oldt); // return terminal to previous state - //... +void restore_console(){ + if(console_changed) + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); // return terminal to previous state + console_changed = 0; } -*/ + // initial setup: void setup_con(){ - tcgetattr(STDIN_FILENO, &oldt); - newt = oldt; - newt.c_lflag &= ~(ICANON | ECHO); - if(tcsetattr(STDIN_FILENO, TCSANOW, &newt) < 0){ - tcsetattr(STDIN_FILENO, TCSANOW, &oldt); - exit(-2); //quit? - } + if(console_changed) return; + tcgetattr(STDIN_FILENO, &oldt); + newt = oldt; + newt.c_lflag &= ~(ICANON | ECHO); + if(tcsetattr(STDIN_FILENO, TCSANOW, &newt) < 0){ + /// "Не могу настроить консоль" + WARN(_("Can't setup console")); + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); + signals(0); //quit? + } + console_changed = 1; } /** @@ -225,20 +242,20 @@ void setup_con(){ * @return char readed */ int read_console(){ - int rb; - struct timeval tv; - int retval; - fd_set rfds; - FD_ZERO(&rfds); - FD_SET(STDIN_FILENO, &rfds); - tv.tv_sec = 0; tv.tv_usec = 10000; - retval = select(1, &rfds, NULL, NULL, &tv); - if(!retval) rb = 0; - else { - if(FD_ISSET(STDIN_FILENO, &rfds)) rb = getchar(); - else rb = 0; - } - return rb; + int rb; + struct timeval tv; + int retval; + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(STDIN_FILENO, &rfds); + tv.tv_sec = 0; tv.tv_usec = 10000; + retval = select(1, &rfds, NULL, NULL, &tv); + if(!retval) rb = 0; + else { + if(FD_ISSET(STDIN_FILENO, &rfds)) rb = getchar(); + else rb = 0; + } + return rb; } /** @@ -246,50 +263,58 @@ int read_console(){ * wait until at least one character pressed * @return character readed */ -int mygetchar(){ // п╟п╫п╟п╩п╬пЁ getchar() п╠п╣п╥ п╫п╣п╬п╠я┘п╬п╢п╦п╪п╬я│я┌п╦ п╤п╟я┌я▄ Enter - int ret; - do ret = read_console(); - while(ret == 0); - return ret; +int mygetchar(){ // getchar() without need of pressing ENTER + int ret; + do ret = read_console(); + while(ret == 0); + return ret; } /******************************************************************************\ * TTY with select() \******************************************************************************/ -struct termio oldtty, tty; // TTY flags -char *comdev; // TTY device name -int comfd; // TTY fd +static struct termio oldtty, tty; // TTY flags +static int comfd = -1; // TTY fd + // run on exit: -/* -void quit(int ex_stat){ - ioctl(comfd, TCSANOW, &oldtty ); // return TTY to previous state - close(comfd); - //... +void restore_tty(){ + if(comfd == -1) return; + ioctl(comfd, TCSANOW, &oldtty ); // return TTY to previous state + close(comfd); + comfd = -1; } -*/ + #ifndef BAUD_RATE #define BAUD_RATE B9600 #endif // init: -void tty_init(){ - printf("\nOpen port...\n"); - if ((comfd = open(comdev,O_RDWR|O_NOCTTY|O_NONBLOCK)) < 0){ - fprintf(stderr,"Can't use port %s\n",comdev); - ioctl(comfd, TCSANOW, &oldtty); // return TTY to previous state - close(comfd); - exit(1); // quit? - } - printf(" OK\nGet current settings...\n"); - if(ioctl(comfd,TCGETA,&oldtty) < 0) exit(-1); // Get settings - tty = oldtty; - tty.c_lflag = 0; // ~(ICANON | ECHO | ECHOE | ISIG) - tty.c_oflag = 0; - tty.c_cflag = BAUD_RATE|CS8|CREAD|CLOCAL; // 9.6k, 8N1, RW, ignore line ctrl - tty.c_cc[VMIN] = 0; // non-canonical mode - tty.c_cc[VTIME] = 5; - if(ioctl(comfd,TCSETA,&tty) < 0) exit(-1); // set new mode - printf(" OK\n"); +void tty_init(char *comdev){ + DBG("\nOpen port...\n"); + if ((comfd = open(comdev,O_RDWR|O_NOCTTY|O_NONBLOCK)) < 0){ + WARN("Can't use port %s\n",comdev); + ioctl(comfd, TCSANOW, &oldtty); // return TTY to previous state + close(comfd); + signals(0); // quit? + } + DBG(" OK\nGet current settings... "); + if(ioctl(comfd,TCGETA,&oldtty) < 0){ // Get settings + /// "Не могу получить настройки" + WARN(_("Can't get settings")); + signals(0); + } + tty = oldtty; + tty.c_lflag = 0; // ~(ICANON | ECHO | ECHOE | ISIG) + tty.c_oflag = 0; + tty.c_cflag = BAUD_RATE|CS8|CREAD|CLOCAL; // 9.6k, 8N1, RW, ignore line ctrl + tty.c_cc[VMIN] = 0; // non-canonical mode + tty.c_cc[VTIME] = 5; + if(ioctl(comfd,TCSETA,&tty) < 0){ + /// "Не могу установить настройки" + WARN(_("Can't set settings")); + signals(0); + } + DBG(" OK\n"); } /** * Read data from TTY @@ -298,17 +323,49 @@ void tty_init(){ * @return amount of readed bytes */ size_t read_tty(uint8_t *buff, size_t length){ - ssize_t L = 0; - fd_set rfds; - struct timeval tv; - int retval; - FD_ZERO(&rfds); - FD_SET(comfd, &rfds); - tv.tv_sec = 0; tv.tv_usec = 50000; // wait for 50ms - retval = select(comfd + 1, &rfds, NULL, NULL, &tv); - if (!retval) return 0; - if(FD_ISSET(comfd, &rfds)){ - if((L = read(comfd, buff, length)) < 1) return 0; - } - return (size_t)L; + ssize_t L = 0; + fd_set rfds; + struct timeval tv; + int retval; + FD_ZERO(&rfds); + FD_SET(comfd, &rfds); + tv.tv_sec = 0; tv.tv_usec = 50000; // wait for 50ms + retval = select(comfd + 1, &rfds, NULL, NULL, &tv); + if (!retval) return 0; + if(FD_ISSET(comfd, &rfds)){ + if((L = read(comfd, buff, length)) < 1) return 0; + } + return (size_t)L; +} + +int write_tty(uint8_t *buff, size_t length){ + ssize_t L = write(comfd, buff, length); + if((size_t)L != length){ + /// "Ошибка записи!" + WARN("Write error!"); + return 1; + } + return 0; +} + + +/** + * Safely convert data from string to double + * + * @param num (o) - double number read from string + * @param str (i) - input string + * @return 1 if success, 0 if fails + */ +int str2double(double *num, const char *str){ + double res; + char *endptr; + if(!str) return 0; + res = strtod(str, &endptr); + if(endptr == str || *str == '\0' || *endptr != '\0'){ + /// "Неправильный формат числа double!" + WARNX("Wrong double number format!"); + return FALSE; + } + if(num) *num = res; // you may run it like myatod(NULL, str) to test wether str is double number + return TRUE; } diff --git a/usefull_macros.h b/usefull_macros.h index 43a6192..5f80b9f 100644 --- a/usefull_macros.h +++ b/usefull_macros.h @@ -33,7 +33,18 @@ #include #include #include +#if defined GETTEXT_PACKAGE && defined LOCALEDIR +/* + * GETTEXT + */ #include +#define _(String) gettext(String) +#define gettext_noop(String) String +#define N_(String) gettext_noop(String) +#else +#define _(String) (String) +#define N_(String) (String) +#endif #include #include #include @@ -41,12 +52,6 @@ #include #include -/* - * GETTEXT - */ -#define _(String) gettext(String) -#define gettext_noop(String) String -#define N_(String) gettext_noop(String) // unused arguments with -Wall -Werror #define _U_ __attribute__((__unused__)) @@ -54,16 +59,25 @@ /* * Coloured messages output */ -#define RED "\033[1;31;40m" -#define GREEN "\033[1;32;40m" -#define OLDCOLOR "\033[0;0;0m" +#define RED "\033[1;31;40m" +#define GREEN "\033[1;32;40m" +#define OLDCOLOR "\033[0;0;0m" + +#ifndef FALSE +#define FALSE (0) +#endif + +#ifndef TRUE +#define TRUE (1) +#endif /* * ERROR/WARNING messages */ extern int globErr; -#define ERR(...) do{globErr=errno; _WARN(__VA_ARGS__); exit(-1);}while(0) -#define ERRX(...) do{globErr=0; _WARN(__VA_ARGS__); exit(-1);}while(0) +extern void signals(int sig); +#define ERR(...) do{globErr=errno; _WARN(__VA_ARGS__); signals(9);}while(0) +#define ERRX(...) do{globErr=0; _WARN(__VA_ARGS__); signals(9);}while(0) #define WARN(...) do{globErr=errno; _WARN(__VA_ARGS__);}while(0) #define WARNX(...) do{globErr=0; _WARN(__VA_ARGS__);}while(0) @@ -72,13 +86,13 @@ extern int globErr; * debug mode, -DEBUG */ #ifdef EBUG - #define FNAME() fprintf(stderr, "\n%s (%s, line %d)\n", __func__, __FILE__, __LINE__) - #define DBG(...) do{fprintf(stderr, "%s (%s, line %d): ", __func__, __FILE__, __LINE__); \ - fprintf(stderr, __VA_ARGS__); \ - fprintf(stderr, "\n");} while(0) + #define FNAME() fprintf(stderr, "\n%s (%s, line %d)\n", __func__, __FILE__, __LINE__) + #define DBG(...) do{fprintf(stderr, "%s (%s, line %d): ", __func__, __FILE__, __LINE__); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n");} while(0) #else - #define FNAME() do{}while(0) - #define DBG(...) do{}while(0) + #define FNAME() do{}while(0) + #define DBG(...) do{}while(0) #endif //EBUG /* @@ -86,7 +100,13 @@ extern int globErr; */ #define ALLOC(type, var, size) type * var = ((type *)my_alloc(size, sizeof(type))) #define MALLOC(type, size) ((type *)my_alloc(size, sizeof(type))) -#define FREE(ptr) do{free(ptr); ptr = NULL;}while(0) +#define FREE(ptr) do{if(ptr){free(ptr); ptr = NULL;}}while(0) + +#ifndef DBL_EPSILON +#define DBL_EPSILON (2.2204460492503131e-16) +#endif + +double dtime(); // functions for color output in tty & no-color in pipes extern int (*red)(const char *fmt, ...); @@ -97,10 +117,22 @@ void initial_setup(); // mmap file typedef struct{ - char *data; - size_t len; + char *data; + size_t len; } mmapbuf; mmapbuf *My_mmap(char *filename); void My_munmap(mmapbuf *b); +void restore_console(); +void setup_con(); +int read_console(); +int mygetchar(); + +void restore_tty(); +void tty_init(char *comdev); +size_t read_tty(uint8_t *buff, size_t length); +int write_tty(uint8_t *buff, size_t length); + +int str2double(double *num, const char *str); + #endif // __USEFULL_MACROS_H__