refresh usefull_macros

This commit is contained in:
eddyem 2016-11-02 18:03:13 +03:00
parent d826925162
commit 001e61af6e
10 changed files with 1115 additions and 1026 deletions

View File

@ -92,7 +92,7 @@ extern void signals(int sig);
*/ */
#define ALLOC(type, var, size) type * var = ((type *)my_alloc(size, sizeof(type))) #define ALLOC(type, var, size) type * var = ((type *)my_alloc(size, sizeof(type)))
#define MALLOC(type, size) ((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(); double dtime();

View File

@ -37,79 +37,79 @@ glob_pars G;
mirPar M; mirPar M;
int rewrite_ifexists = 0, // rewrite existing files == 0 or 1 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 // DEFAULTS
// default global parameters // default global parameters
glob_pars const Gdefault = { glob_pars const Gdefault = {
NULL, // size of initial array of surface deviations NULL, // size of initial array of surface deviations
100, // size of interpolated S0 100, // size of interpolated S0
1000, // resulting image size 1000, // resulting image size
10000, // amount of photons falled to one pixel of S1 by one iteration 10000, // amount of photons falled to one pixel of S1 by one iteration
0, // add to mask random numbers 0, // add to mask random numbers
NULL, // amplitude of added random noice NULL, // amplitude of added random noice
NULL, // mirror NULL, // mirror
0, // rest num 0, // rest num
NULL, // rest pars NULL, // rest pars
NULL, // str NULL, // str
NULL // filter NULL // filter
}; };
//default mirror parameters //default mirror parameters
mirPar const Mdefault = { mirPar const Mdefault = {
6., // diameter 6., // diameter
24.024, // focus 24.024, // focus
0., // inclination from Z axe (radians) 0., // inclination from Z axe (radians)
0. // azimuth of inclination (radians) 0. // azimuth of inclination (radians)
}; };
// here are functions & definitions for complex parameters (with suboptions etc) // here are functions & definitions for complex parameters (with suboptions etc)
bool get_mir_par(void *arg); bool get_mir_par(void *arg);
const char MirPar[] = "set mirror parameters, arg=[diam=num:foc=num:Zincl=ang:Aincl=ang]\n" \ 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\t\tALL DEGREES ARE IN FORMAT [+-][DDd][MMm][SS.S] like -10m13.4 !\n" \
"\t\tdiam - diameter of mirror\n" \ "\t\tdiam - diameter of mirror\n" \
"\t\tfoc - mirror focus ratio\n" \ "\t\tfoc - mirror focus ratio\n" \
"\t\tZincl - inclination from Z axe\n" \ "\t\tZincl - inclination from Z axe\n" \
"\t\tAincl - azimuth of inclination"; "\t\tAincl - azimuth of inclination";
const char FilPar[] = "set filter parameters, arg=[type=type:xsz=num:ysz=num]\n" \ const char FilPar[] = "set filter parameters, arg=[type=type:xsz=num:ysz=num]\n" \
"\t\ttype - filter type(med, lap, lg)\n" \ "\t\ttype - filter type(med, lap, lg)\n" \
"\t\txsz,ysz - area size (default is 3x3)"; "\t\txsz,ysz - area size (default is 3x3)";
/* /*
* Define command line options by filling structure: * 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[] = { myoption cmdlnopts[] = {
// set 1 to param despite of its repeating number: // set 1 to param despite of its repeating number:
{"help", NO_ARGS, NULL, 'h', arg_int, APTR(&help), "show this help"}, {"help", NO_ARGS, NULL, 'h', arg_int, APTR(&help), "show this help"},
// simple integer parameter with obligatory arg: // 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"}, {"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"}, {"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"}, {"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 // parameter with suboptions parsed directly in parseargs
{"mir-parameters",NEED_ARG,NULL,'M', arg_function,APTR(&get_mir_par),MirPar}, {"mir-parameters",NEED_ARG,NULL,'M', arg_function,APTR(&get_mir_par),MirPar},
// another variant of setting parameter without argument // another variant of setting parameter without argument
{"add-noice",NO_ARGS, &G.randMask,1, arg_none, NULL, "add random noice to mirror surface deviations"}, {"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"}, {"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") // 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)"}, {"verbose", NO_ARGS, NULL, 'v', arg_none, APTR(&verbose), "verbose level (each -v increase it)"},
// integer parameter which can occur several times: // 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"}, {"dev-size",MULT_PAR, NULL, 'd', arg_int, APTR(&G.S_dev), "size of initial array of surface deviations"},
// double array // double array
{"noice-amp",MULT_PAR, NULL, 'a', arg_double, APTR(&G.randAmp), "amplitude of random noice (default: 1e-8)"}, {"noice-amp",MULT_PAR, NULL, 'a', arg_double, APTR(&G.randAmp), "amplitude of random noice (default: 1e-8)"},
// string array // string array
{"str", MULT_PAR, NULL, 's', arg_string, APTR(&G.str), "some string parameters (may meets many times)"}, {"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): // suboptions array that will be parsed outside (the same as string array):
{"filter", MULT_PAR, NULL, 'f', arg_string, APTR(&G.filter), FilPar}, {"filter", MULT_PAR, NULL, 'f', arg_string, APTR(&G.filter), FilPar},
end_option end_option
}; };
// suboptions structure for get_mirpars // suboptions structure for get_mirpars
// in array last MUST BE {0,0,0} // in array last MUST BE {0,0,0}
typedef struct{ typedef struct{
double *val; // pointer to result double *val; // pointer to result
char *par; // parameter name (CASE-INSENSITIVE!) char *par; // parameter name (CASE-INSENSITIVE!)
bool isdegr; // == TRUE if parameter is an angle in format "[+-][DDd][MMm][SS.S]" bool isdegr; // == TRUE if parameter is an angle in format "[+-][DDd][MMm][SS.S]"
} suboptions; } suboptions;
/** /**
@ -120,16 +120,16 @@ typedef struct{
* @return TRUE if success * @return TRUE if success
*/ */
bool myatod(double *num, const char *str){ bool myatod(double *num, const char *str){
double res; double res;
char *endptr; char *endptr;
assert(str); assert(str);
res = strtod(str, &endptr); res = strtod(str, &endptr);
if(endptr == str || *str == '\0' || *endptr != '\0'){ if(endptr == str || *str == '\0' || *endptr != '\0'){
printf("Wrong double number format!"); printf("Wrong double number format!");
return FALSE; return FALSE;
} }
*num = res; *num = res;
return TRUE; return TRUE;
} }
/** /**
@ -140,38 +140,38 @@ bool myatod(double *num, const char *str){
* @return TRUE if OK * @return TRUE if OK
*/ */
bool get_radians(double *ret, char *str){ bool get_radians(double *ret, char *str){
double val = 0., ftmp, sign = 1.; double val = 0., ftmp, sign = 1.;
char *ptr; char *ptr;
assert(str); assert(str);
switch(*str){ // check sign switch(*str){ // check sign
case '-': case '-':
sign = -1.; sign = -1.;
case '+': case '+':
str++; str++;
} }
if((ptr = strchr(str, 'd'))){ // found DDD.DDd if((ptr = strchr(str, 'd'))){ // found DDD.DDd
*ptr = 0; if(!myatod(&ftmp, str)) return FALSE; *ptr = 0; if(!myatod(&ftmp, str)) return FALSE;
ftmp = fabs(ftmp); ftmp = fabs(ftmp);
if(ftmp > 360.){ if(ftmp > 360.){
printf("Degrees should be less than 360"); printf("Degrees should be less than 360");
return FALSE; return FALSE;
} }
val += ftmp; val += ftmp;
str = ptr + 1; str = ptr + 1;
} }
if((ptr = strchr(str, 'm'))){ // found DDD.DDm if((ptr = strchr(str, 'm'))){ // found DDD.DDm
*ptr = 0; if(!myatod(&ftmp, str)) return FALSE; *ptr = 0; if(!myatod(&ftmp, str)) return FALSE;
ftmp = fabs(ftmp); ftmp = fabs(ftmp);
val += ftmp / 60.; val += ftmp / 60.;
str = ptr + 1; str = ptr + 1;
} }
if(strlen(str)){ // there is something more if(strlen(str)){ // there is something more
if(!myatod(&ftmp, str)) return FALSE; if(!myatod(&ftmp, str)) return FALSE;
ftmp = fabs(ftmp); ftmp = fabs(ftmp);
val += ftmp / 3600.; val += ftmp / 3600.;
} }
*ret = D2R(val * sign); // convert degrees to radians *ret = D2R(val * sign); // convert degrees to radians
return TRUE; return TRUE;
} }
/** /**
@ -185,34 +185,34 @@ bool get_radians(double *ret, char *str){
* @return TRUE if success * @return TRUE if success
*/ */
bool get_mirpars(void *arg, suboptions *V){ bool get_mirpars(void *arg, suboptions *V){
char *tok, *val, *par; char *tok, *val, *par;
int i; int i;
tok = strtok(arg, ":,"); tok = strtok(arg, ":,");
do{ do{
if((val = strchr(tok, '=')) == NULL){ // wrong format if((val = strchr(tok, '=')) == NULL){ // wrong format
printf("Wrong format: no value for keyword"); printf("Wrong format: no value for keyword");
return FALSE; return FALSE;
} }
*val++ = '\0'; *val++ = '\0';
par = tok; par = tok;
for(i = 0; V[i].val; i++){ for(i = 0; V[i].val; i++){
if(strcasecmp(par, V[i].par) == 0){ // found parameter if(strcasecmp(par, V[i].par) == 0){ // found parameter
if(V[i].isdegr){ // DMS if(V[i].isdegr){ // DMS
if(!get_radians(V[i].val, val)) // wrong angle if(!get_radians(V[i].val, val)) // wrong angle
return FALSE; return FALSE;
}else{ // simple double }else{ // simple double
if(!myatod(V[i].val, val)) // wrong number if(!myatod(V[i].val, val)) // wrong number
return FALSE; return FALSE;
} }
break; break;
} }
} }
if(!V[i].val){ // nothing found - wrong format if(!V[i].val){ // nothing found - wrong format
printf("Bad keyword!"); printf("Bad keyword!");
return FALSE; return FALSE;
} }
}while((tok = strtok(NULL, ":,"))); }while((tok = strtok(NULL, ":,")));
return TRUE; return TRUE;
} }
/** /**
@ -225,40 +225,40 @@ bool get_mirpars(void *arg, suboptions *V){
* @return TRUE if success * @return TRUE if success
*/ */
bool get_mir_par(void *arg){ bool get_mir_par(void *arg){
suboptions V[] = { // array of mirror parameters and string keys for cmdln pars suboptions V[] = { // array of mirror parameters and string keys for cmdln pars
{&M.D, "diam", FALSE}, {&M.D, "diam", FALSE},
{&M.F, "foc", FALSE}, {&M.F, "foc", FALSE},
{&M.Zincl, "zincl", TRUE}, {&M.Zincl, "zincl", TRUE},
{&M.Aincl, "aincl", TRUE}, {&M.Aincl, "aincl", TRUE},
{0,0,0} {0,0,0}
}; };
return get_mirpars(arg, V); return get_mirpars(arg, V);
} }
/** /**
* Parse command line options and return dynamically allocated structure * Parse command line options and return dynamically allocated structure
* to global parameters * to global parameters
* @param argc - copy of argc from main * @param argc - copy of argc from main
* @param argv - copy of argv from main * @param argv - copy of argv from main
* @return allocated structure with global parameters * @return allocated structure with global parameters
*/ */
glob_pars *parse_args(int argc, char **argv){ glob_pars *parse_args(int argc, char **argv){
int i; int i;
void *ptr; void *ptr;
ptr = memcpy(&G, &Gdefault, sizeof(G)); assert(ptr); ptr = memcpy(&G, &Gdefault, sizeof(G)); assert(ptr);
ptr = memcpy(&M, &Mdefault, sizeof(M)); assert(ptr); ptr = memcpy(&M, &Mdefault, sizeof(M)); assert(ptr);
G.Mirror = &M; G.Mirror = &M;
// format of help: "Usage: progname [args]\n" // format of help: "Usage: progname [args]\n"
change_helpstring("Usage: %s [args]\n\n\tWhere args are:\n"); change_helpstring("Usage: %s [args]\n\n\tWhere args are:\n");
// parse arguments // parse arguments
parseargs(&argc, &argv, cmdlnopts); parseargs(&argc, &argv, cmdlnopts);
if(help) showhelp(-1, cmdlnopts); if(help) showhelp(-1, cmdlnopts);
if(argc > 0){ if(argc > 0){
G.rest_pars_num = argc; G.rest_pars_num = argc;
G.rest_pars = calloc(argc, sizeof(char*)); G.rest_pars = calloc(argc, sizeof(char*));
for (i = 0; i < argc; i++) for (i = 0; i < argc; i++)
G.rest_pars[i] = strdup(argv[i]); G.rest_pars[i] = strdup(argv[i]);
} }
return &G; return &G;
} }

View File

@ -30,24 +30,24 @@
*/ */
// parameters of mirror // parameters of mirror
typedef struct{ typedef struct{
double D; // diameter double D; // diameter
double F; // focus double F; // focus
double Zincl; // inclination from Z axe (radians) double Zincl; // inclination from Z axe (radians)
double Aincl; // azimuth of inclination (radians) double Aincl; // azimuth of inclination (radians)
} mirPar; } mirPar;
typedef struct{ typedef struct{
int **S_dev; // size of initial array of surface deviations int **S_dev; // size of initial array of surface deviations
int S_interp; // size of interpolated S0 int S_interp; // size of interpolated S0
int S_image; // resulting image size int S_image; // resulting image size
int N_phot; // amount of photons falled to one pixel of S1 by one iteration int N_phot; // amount of photons falled to one pixel of S1 by one iteration
int randMask; // add to mask random numbers int randMask; // add to mask random numbers
double **randAmp;// amplitude of added random noice double **randAmp;// amplitude of added random noice
mirPar *Mirror; // mirror parameters mirPar *Mirror; // mirror parameters
int rest_pars_num;// number of rest parameters int rest_pars_num;// number of rest parameters
char** rest_pars;// the rest parameters: array of char* char** rest_pars;// the rest parameters: array of char*
char **str; // string parameters char **str; // string parameters
char **filter; // some filter options char **filter; // some filter options
} glob_pars; } glob_pars;

View File

@ -23,89 +23,89 @@
#include "cmdlnopts.h" #include "cmdlnopts.h"
typedef struct{ typedef struct{
char *filtertype; char *filtertype;
int xsize; int xsize;
int ysize; int ysize;
} filterpars; } filterpars;
void signals(int signo){ void signals(int signo){
exit(signo); exit(signo);
} }
void parse_filter(char *pars){ void parse_filter(char *pars){
filterpars params = { 0, 3, 3}; filterpars params = { 0, 3, 3};
mysuboption filteropts[] = { mysuboption filteropts[] = {
{"type", NEED_ARG, arg_string, &params.filtertype}, {"type", NEED_ARG, arg_string, &params.filtertype},
{"xsz", NEED_ARG, arg_int, &params.xsize}, {"xsz", NEED_ARG, arg_int, &params.xsize},
{"ysz", NEED_ARG, arg_int, &params.ysize}, {"ysz", NEED_ARG, arg_int, &params.ysize},
end_suboption end_suboption
}; };
if(!get_suboption(pars, filteropts)){ if(!get_suboption(pars, filteropts)){
printf("\tbad params\n"); printf("\tbad params\n");
}else{ }else{
printf("\tfiltertype = %s, sizes: %dx%d\n", params.filtertype, params.xsize, params.ysize); printf("\tfiltertype = %s, sizes: %dx%d\n", params.filtertype, params.xsize, params.ysize);
} }
} }
int main(int argc, char **argv){ int main(int argc, char **argv){
glob_pars *G = NULL; // default parameters see in cmdlnopts.c glob_pars *G = NULL; // default parameters see in cmdlnopts.c
mirPar *M = NULL; // default mirror parameters mirPar *M = NULL; // default mirror parameters
G = parse_args(argc, argv); G = parse_args(argc, argv);
M = G->Mirror; M = G->Mirror;
printf("Globals:\n"); printf("Globals:\n");
if(!G->S_dev){ if(!G->S_dev){
printf("S_dev = 8 (default)\n"); printf("S_dev = 8 (default)\n");
}else{ }else{
int i = 0, **vals = G->S_dev; int i = 0, **vals = G->S_dev;
while(*vals){ while(*vals){
printf("S_dev[%d]: %d\n", i++, **vals++); printf("S_dev[%d]: %d\n", i++, **vals++);
} }
} }
if(!G->randAmp){ if(!G->randAmp){
printf("randAmp = 1e-8 (default)\n"); printf("randAmp = 1e-8 (default)\n");
}else{ }else{
int i = 0; int i = 0;
double **a = G->randAmp; double **a = G->randAmp;
while(*a){ while(*a){
printf("randAmp[%d]: %g\n", i++, **a++); printf("randAmp[%d]: %g\n", i++, **a++);
} }
} }
if(G->str){ if(G->str){
printf("meet str args:\n"); printf("meet str args:\n");
int i = 0; int i = 0;
char **strs = G->str; char **strs = G->str;
if(!*strs) printf("fucn!\n"); if(!*strs) printf("fucn!\n");
while(*strs) while(*strs)
printf("str[%d] = %s\n", i++, *strs++); printf("str[%d] = %s\n", i++, *strs++);
} }
printf("S_interp = %d\n", G->S_interp); printf("S_interp = %d\n", G->S_interp);
printf("S_image = %d\n", G->S_image); printf("S_image = %d\n", G->S_image);
printf("N_phot = %d\n", G->N_phot); printf("N_phot = %d\n", G->N_phot);
printf("randMask = %d\n", G->randMask); printf("randMask = %d\n", G->randMask);
printf("Mirror =\n"); printf("Mirror =\n");
printf("\tD = %g\n", M->D); printf("\tD = %g\n", M->D);
printf("\tF = %g\n", M->F); printf("\tF = %g\n", M->F);
printf("\tZincl = %g\n", M->Zincl); printf("\tZincl = %g\n", M->Zincl);
printf("\tAincl = %g\n", M->Aincl); printf("\tAincl = %g\n", M->Aincl);
printf("rewrite_ifexists = %d\n", rewrite_ifexists); printf("rewrite_ifexists = %d\n", rewrite_ifexists);
printf("verbose = %d\n", verbose); printf("verbose = %d\n", verbose);
if(G->rest_pars_num){ if(G->rest_pars_num){
int i; int i;
printf("There's also %d free parameters:\n", G->rest_pars_num); printf("There's also %d free parameters:\n", G->rest_pars_num);
for(i = 0; i < G->rest_pars_num; ++i) for(i = 0; i < G->rest_pars_num; ++i)
printf("\t%4d: %s\n", i, G->rest_pars[i]); printf("\t%4d: %s\n", i, G->rest_pars[i]);
} }
if(G->filter){ if(G->filter){
printf("filter parameters:\n"); printf("filter parameters:\n");
char **fpars = G->filter; char **fpars = G->filter;
int i = 0; int i = 0;
while(*fpars){ while(*fpars){
printf("%d:\n", i++); printf("%d:\n", i++);
parse_filter(*fpars); parse_filter(*fpars);
++fpars; ++fpars;
} }
} }
return 0; return 0;
} }

View File

@ -19,15 +19,15 @@
* MA 02110-1301, USA. * MA 02110-1301, USA.
*/ */
#include <stdio.h> // printf #include <stdio.h> // printf
#include <getopt.h> // getopt_long #include <getopt.h> // getopt_long
#include <stdlib.h> // calloc, exit, strtoll #include <stdlib.h> // calloc, exit, strtoll
#include <assert.h> // assert #include <assert.h> // assert
#include <string.h> // strdup, strchr, strlen #include <string.h> // strdup, strchr, strlen
#include <strings.h>// strcasecmp #include <strings.h>// strcasecmp
#include <limits.h> // INT_MAX & so on #include <limits.h> // INT_MAX & so on
#include <libintl.h>// gettext #include <libintl.h>// gettext
#include <ctype.h> // isalpha #include <ctype.h> // isalpha
#include "parseargs.h" #include "parseargs.h"
#include "usefull_macros.h" #include "usefull_macros.h"
@ -39,23 +39,23 @@ char *helpstring = "%s\n";
* @param str (i) - new format * @param str (i) - new format
*/ */
void change_helpstring(char *s){ void change_helpstring(char *s){
int pcount = 0, scount = 0; int pcount = 0, scount = 0;
char *str = s; char *str = s;
// check `helpstring` and set it to default in case of error // check `helpstring` and set it to default in case of error
for(; pcount < 2; str += 2){ for(; pcount < 2; str += 2){
if(!(str = strchr(str, '%'))) break; if(!(str = strchr(str, '%'))) break;
if(str[1] != '%') pcount++; // increment '%' counter if it isn't "%%" if(str[1] != '%') pcount++; // increment '%' counter if it isn't "%%"
else{ else{
str += 2; // pass next '%' str += 2; // pass next '%'
continue; continue;
} }
if(str[1] == 's') scount++; // increment "%s" counter if(str[1] == 's') scount++; // increment "%s" counter
}; };
if(pcount > 1 || pcount != scount){ // amount of pcount and/or scount wrong if(pcount > 1 || pcount != scount){ // amount of pcount and/or scount wrong
/// "îÅÐÒÁ×ÉÌØÎÙÊ ÆÏÒÍÁÔ ÓÔÒÏËÉ ÐÏÍÏÝÉ" /// "îÅÐÒÁ×ÉÌØÎÙÊ ÆÏÒÍÁÔ ÓÔÒÏËÉ ÐÏÍÏÝÉ"
ERRX(_("Wrong helpstring!")); ERRX(_("Wrong helpstring!"));
} }
helpstring = s; helpstring = s;
} }
/** /**
@ -66,54 +66,54 @@ void change_helpstring(char *s){
* @return TRUE if conversion sone without errors, FALSE otherwise * @return TRUE if conversion sone without errors, FALSE otherwise
*/ */
static bool myatoll(void *num, char *str, argtype t){ static bool myatoll(void *num, char *str, argtype t){
long long tmp, *llptr; long long tmp, *llptr;
int *iptr; int *iptr;
char *endptr; char *endptr;
assert(str); assert(str);
assert(num); assert(num);
tmp = strtoll(str, &endptr, 0); tmp = strtoll(str, &endptr, 0);
if(endptr == str || *str == '\0' || *endptr != '\0') if(endptr == str || *str == '\0' || *endptr != '\0')
return FALSE; return FALSE;
switch(t){ switch(t){
case arg_longlong: case arg_longlong:
llptr = (long long*) num; llptr = (long long*) num;
*llptr = tmp; *llptr = tmp;
break; break;
case arg_int: case arg_int:
default: default:
if(tmp < INT_MIN || tmp > INT_MAX){ if(tmp < INT_MIN || tmp > INT_MAX){
/// "ãÅÌÏÅ ×ÎÅ ÄÏÐÕÓÔÉÍÏÇÏ ÄÉÁÐÁÚÏÎÁ" /// "ãÅÌÏÅ ×ÎÅ ÄÏÐÕÓÔÉÍÏÇÏ ÄÉÁÐÁÚÏÎÁ"
WARNX(_("Integer out of range")); WARNX(_("Integer out of range"));
return FALSE; return FALSE;
} }
iptr = (int*)num; iptr = (int*)num;
*iptr = (int)tmp; *iptr = (int)tmp;
} }
return TRUE; return TRUE;
} }
// the same as myatoll but for double // the same as myatoll but for double
// There's no NAN & INF checking here (what if they would be needed?) // There's no NAN & INF checking here (what if they would be needed?)
static bool myatod(void *num, const char *str, argtype t){ static bool myatod(void *num, const char *str, argtype t){
double tmp, *dptr; double tmp, *dptr;
float *fptr; float *fptr;
char *endptr; char *endptr;
assert(str); assert(str);
tmp = strtod(str, &endptr); tmp = strtod(str, &endptr);
if(endptr == str || *str == '\0' || *endptr != '\0') if(endptr == str || *str == '\0' || *endptr != '\0')
return FALSE; return FALSE;
switch(t){ switch(t){
case arg_double: case arg_double:
dptr = (double *) num; dptr = (double *) num;
*dptr = tmp; *dptr = tmp;
break; break;
case arg_float: case arg_float:
default: default:
fptr = (float *) num; fptr = (float *) num;
*fptr = (float)tmp; *fptr = (float)tmp;
break; break;
} }
return TRUE; return TRUE;
} }
/** /**
@ -123,13 +123,13 @@ static bool myatod(void *num, const char *str, argtype t){
* @return index in array * @return index in array
*/ */
static int get_optind(int opt, myoption *options){ static int get_optind(int opt, myoption *options){
int oind; int oind;
myoption *opts = options; myoption *opts = options;
assert(opts); assert(opts);
for(oind = 0; opts->name && opts->val != opt; oind++, opts++); for(oind = 0; opts->name && opts->val != opt; oind++, opts++);
if(!opts->name || opts->val != opt) // no such parameter if(!opts->name || opts->val != opt) // no such parameter
showhelp(-1, options); showhelp(-1, options);
return oind; return oind;
} }
/** /**
@ -139,46 +139,46 @@ static int get_optind(int opt, myoption *options){
* @return pointer to new (next) value * @return pointer to new (next) value
*/ */
void *get_aptr(void *paptr, argtype type){ void *get_aptr(void *paptr, argtype type){
int i = 1; int i = 1;
void **aptr = *((void***)paptr); void **aptr = *((void***)paptr);
if(aptr){ // there's something in array if(aptr){ // there's something in array
void **p = aptr; void **p = aptr;
while(*p++) ++i; while(*p++) ++i;
} }
size_t sz = 0; size_t sz = 0;
switch(type){ switch(type){
default: default:
case arg_none: case arg_none:
/// "îÅ ÍÏÇÕ ÉÓÐÏÌØÚÏ×ÁÔØ ÎÅÓËÏÌØËÏ ÐÁÒÁÍÅÔÒÏ× ÂÅÚ ÁÒÇÕÍÅÎÔÏ×!" /// "îÅ ÍÏÇÕ ÉÓÐÏÌØÚÏ×ÁÔØ ÎÅÓËÏÌØËÏ ÐÁÒÁÍÅÔÒÏ× ÂÅÚ ÁÒÇÕÍÅÎÔÏ×!"
ERRX("Can't use multiple args with arg_none!"); ERRX("Can't use multiple args with arg_none!");
break; break;
case arg_int: case arg_int:
sz = sizeof(int); sz = sizeof(int);
break; break;
case arg_longlong: case arg_longlong:
sz = sizeof(long long); sz = sizeof(long long);
break; break;
case arg_double: case arg_double:
sz = sizeof(double); sz = sizeof(double);
break; break;
case arg_float: case arg_float:
sz = sizeof(float); sz = sizeof(float);
break; break;
case arg_string: case arg_string:
sz = 0; sz = 0;
break; break;
/* case arg_function: /* case arg_function:
sz = sizeof(argfn *); sz = sizeof(argfn *);
break;*/ break;*/
} }
aptr = realloc(aptr, (i + 1) * sizeof(void*)); aptr = realloc(aptr, (i + 1) * sizeof(void*));
*((void***)paptr) = aptr; *((void***)paptr) = aptr;
aptr[i] = NULL; aptr[i] = NULL;
if(sz){ if(sz){
aptr[i - 1] = malloc(sz); aptr[i - 1] = malloc(sz);
}else }else
aptr[i - 1] = &aptr[i - 1]; aptr[i - 1] = &aptr[i - 1];
return 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 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` * @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 * 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 * @param options (i) - array of `myoption` for arguments parcing
* *
* @exit: in case of error this function show help & make `exit(-1)` * @exit: in case of error this function show help & make `exit(-1)`
*/ */
void parseargs(int *argc, char ***argv, myoption *options){ void parseargs(int *argc, char ***argv, myoption *options){
char *short_options, *soptr; char *short_options, *soptr;
struct option *long_options, *loptr; struct option *long_options, *loptr;
size_t optsize, i; size_t optsize, i;
myoption *opts = options; myoption *opts = options;
// check whether there is at least one options // check whether there is at least one options
assert(opts); assert(opts);
assert(opts[0].name); assert(opts[0].name);
// first we count how much values are in opts // first we count how much values are in opts
for(optsize = 0; opts->name; optsize++, opts++); for(optsize = 0; opts->name; optsize++, opts++);
// now we can allocate memory // now we can allocate memory
short_options = calloc(optsize * 3 + 1, 1); // multiply by three for '::' in case of args in opts 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)); long_options = calloc(optsize + 1, sizeof(struct option));
opts = options; loptr = long_options; soptr = short_options; opts = options; loptr = long_options; soptr = short_options;
// in debug mode check the parameters are not repeated // in debug mode check the parameters are not repeated
#ifdef EBUG #ifdef EBUG
char **longlist = MALLOC(char*, optsize); char **longlist = MALLOC(char*, optsize);
char *shortlist = MALLOC(char, optsize); char *shortlist = MALLOC(char, optsize);
#endif #endif
// fill short/long parameters and make a simple checking // fill short/long parameters and make a simple checking
for(i = 0; i < optsize; i++, loptr++, opts++){ for(i = 0; i < optsize; i++, loptr++, opts++){
// check // check
assert(opts->name); // check name assert(opts->name); // check name
#ifdef EBUG #ifdef EBUG
longlist[i] = strdup(opts->name); longlist[i] = strdup(opts->name);
#endif #endif
if(opts->has_arg){ if(opts->has_arg){
assert(opts->type != arg_none); // check error with arg type assert(opts->type != arg_none); // check error with arg type
assert(opts->argptr); // check pointer assert(opts->argptr); // check pointer
} }
if(opts->type != arg_none) // if there is a flag without arg, check its pointer if(opts->type != arg_none) // if there is a flag without arg, check its pointer
assert(opts->argptr); assert(opts->argptr);
// fill long_options // fill long_options
// don't do memcmp: what if there would be different alignment? // don't do memcmp: what if there would be different alignment?
loptr->name = opts->name; loptr->name = opts->name;
loptr->has_arg = (opts->has_arg < MULT_PAR) ? opts->has_arg : 1; loptr->has_arg = (opts->has_arg < MULT_PAR) ? opts->has_arg : 1;
loptr->flag = opts->flag; loptr->flag = opts->flag;
loptr->val = opts->val; loptr->val = opts->val;
// fill short options if they are: // fill short options if they are:
if(!opts->flag && opts->val){ if(!opts->flag && opts->val){
#ifdef EBUG #ifdef EBUG
shortlist[i] = (char) opts->val; shortlist[i] = (char) opts->val;
#endif #endif
*soptr++ = opts->val; *soptr++ = opts->val;
if(loptr->has_arg) // add ':' if option has required argument if(loptr->has_arg) // add ':' if option has required argument
*soptr++ = ':'; *soptr++ = ':';
if(loptr->has_arg == 2) // add '::' if option has optional argument if(loptr->has_arg == 2) // add '::' if option has optional argument
*soptr++ = ':'; *soptr++ = ':';
} }
} }
// sort all lists & check for repeating // sort all lists & check for repeating
#ifdef EBUG #ifdef EBUG
int cmpstringp(const void *p1, const void *p2){ int cmpstringp(const void *p1, const void *p2){
return strcmp(* (char * const *) p1, * (char * const *) p2); return strcmp(* (char * const *) p1, * (char * const *) p2);
} }
int cmpcharp(const void *p1, const void *p2){ int cmpcharp(const void *p1, const void *p2){
return (int)(*(char * const)p1 - *(char *const)p2); return (int)(*(char * const)p1 - *(char *const)p2);
} }
qsort(longlist, optsize, sizeof(char *), cmpstringp); qsort(longlist, optsize, sizeof(char *), cmpstringp);
qsort(shortlist,optsize, sizeof(char), cmpcharp); qsort(shortlist,optsize, sizeof(char), cmpcharp);
char *prevl = longlist[0], prevshrt = shortlist[0]; char *prevl = longlist[0], prevshrt = shortlist[0];
for(i = 1; i < optsize; ++i){ for(i = 1; i < optsize; ++i){
if(longlist[i]){ if(longlist[i]){
if(prevl){ if(prevl){
if(strcmp(prevl, longlist[i]) == 0) ERRX("double long arguments: --%s", prevl); if(strcmp(prevl, longlist[i]) == 0) ERRX("double long arguments: --%s", prevl);
} }
prevl = longlist[i]; prevl = longlist[i];
} }
if(shortlist[i]){ if(shortlist[i]){
if(prevshrt){ if(prevshrt){
if(prevshrt == shortlist[i]) ERRX("double short arguments: -%c", prevshrt); if(prevshrt == shortlist[i]) ERRX("double short arguments: -%c", prevshrt);
} }
prevshrt = shortlist[i]; prevshrt = shortlist[i];
} }
} }
#endif #endif
// now we have both long_options & short_options and can parse `getopt_long` // now we have both long_options & short_options and can parse `getopt_long`
while(1){ while(1){
int opt; int opt;
int oindex = 0, optind = 0; // oindex - number of option in argv, optind - number in options[] 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 = getopt_long(*argc, *argv, short_options, long_options, &oindex)) == -1) break;
if(opt == '?'){ if(opt == '?'){
opt = optopt; opt = optopt;
optind = get_optind(opt, options); optind = get_optind(opt, options);
if(options[optind].has_arg == NEED_ARG || options[optind].has_arg == MULT_PAR) if(options[optind].has_arg == NEED_ARG || options[optind].has_arg == MULT_PAR)
showhelp(optind, options); // need argument showhelp(optind, options); // need argument
} }
else{ else{
if(opt == 0 || oindex > 0) optind = oindex; if(opt == 0 || oindex > 0) optind = oindex;
else optind = get_optind(opt, options); else optind = get_optind(opt, options);
} }
opts = &options[optind]; opts = &options[optind];
if(opt == 0 && opts->has_arg == NO_ARGS) continue; // only long option changing integer flag if(opt == 0 && opts->has_arg == NO_ARGS) continue; // only long option changing integer flag
// now check option // now check option
if(opts->has_arg == NEED_ARG || opts->has_arg == MULT_PAR) if(opts->has_arg == NEED_ARG || opts->has_arg == MULT_PAR)
if(!optarg) showhelp(optind, options); // need argument if(!optarg) showhelp(optind, options); // need argument
void *aptr; void *aptr;
if(opts->has_arg == MULT_PAR){ if(opts->has_arg == MULT_PAR){
aptr = get_aptr(opts->argptr, opts->type); aptr = get_aptr(opts->argptr, opts->type);
}else }else
aptr = opts->argptr; aptr = opts->argptr;
bool result = TRUE; bool result = TRUE;
// even if there is no argument, but argptr != NULL, think that optarg = "1" // even if there is no argument, but argptr != NULL, think that optarg = "1"
if(!optarg) optarg = "1"; if(!optarg) optarg = "1";
switch(opts->type){ switch(opts->type){
default: default:
case arg_none: case arg_none:
if(opts->argptr) *((int*)aptr) += 1; // increment value if(opts->argptr) *((int*)aptr) += 1; // increment value
break; break;
case arg_int: case arg_int:
result = myatoll(aptr, optarg, arg_int); result = myatoll(aptr, optarg, arg_int);
break; break;
case arg_longlong: case arg_longlong:
result = myatoll(aptr, optarg, arg_longlong); result = myatoll(aptr, optarg, arg_longlong);
break; break;
case arg_double: case arg_double:
result = myatod(aptr, optarg, arg_double); result = myatod(aptr, optarg, arg_double);
break; break;
case arg_float: case arg_float:
result = myatod(aptr, optarg, arg_float); result = myatod(aptr, optarg, arg_float);
break; break;
case arg_string: case arg_string:
result = (*((void**)aptr) = (void*)strdup(optarg)); result = (*((void**)aptr) = (void*)strdup(optarg));
break; break;
case arg_function: case arg_function:
result = ((argfn)aptr)(optarg); result = ((argfn)aptr)(optarg);
break; break;
} }
if(!result){ if(!result){
showhelp(optind, options); showhelp(optind, options);
} }
} }
*argc -= optind; *argc -= optind;
*argv += 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) * first - sort by short options; second - sort arguments without sort opts (by long options)
*/ */
static int argsort(const void *a1, const void *a2){ static int argsort(const void *a1, const void *a2){
const myoption *o1 = (myoption*)a1, *o2 = (myoption*)a2; const myoption *o1 = (myoption*)a1, *o2 = (myoption*)a2;
const char *l1 = o1->name, *l2 = o2->name; const char *l1 = o1->name, *l2 = o2->name;
int s1 = o1->val, s2 = o2->val; int s1 = o1->val, s2 = o2->val;
int *f1 = o1->flag, *f2 = o2->flag; int *f1 = o1->flag, *f2 = o2->flag;
// check if both options has short arg // check if both options has short arg
if(f1 == NULL && f2 == NULL){ // both have short arg if(f1 == NULL && f2 == NULL){ // both have short arg
return (s1 - s2); return (s1 - s2);
}else if(f1 != NULL && f2 != NULL){ // both don't have short arg - sort by long }else if(f1 != NULL && f2 != NULL){ // both don't have short arg - sort by long
return strcmp(l1, l2); return strcmp(l1, l2);
}else{ // only one have short arg -- return it }else{ // only one have short arg -- return it
if(f2) return -1; // a1 have short - it is 'lesser' if(f2) return -1; // a1 have short - it is 'lesser'
else return 1; else return 1;
} }
} }
/** /**
@ -358,57 +358,57 @@ static int argsort(const void *a1, const void *a2){
* @exit: run `exit(-1)` !!! * @exit: run `exit(-1)` !!!
*/ */
void showhelp(int oindex, myoption *options){ void showhelp(int oindex, myoption *options){
int max_opt_len = 0; // max len of options substring - for right indentation int max_opt_len = 0; // max len of options substring - for right indentation
const int bufsz = 255; const int bufsz = 255;
char buf[bufsz+1]; char buf[bufsz+1];
myoption *opts = options; myoption *opts = options;
assert(opts); assert(opts);
assert(opts[0].name); // check whether there is at least one options assert(opts[0].name); // check whether there is at least one options
if(oindex > -1){ // print only one message if(oindex > -1){ // print only one message
opts = &options[oindex]; opts = &options[oindex];
printf(" "); printf(" ");
if(!opts->flag && isalpha(opts->val)) printf("-%c, ", opts->val); if(!opts->flag && isalpha(opts->val)) printf("-%c, ", opts->val);
printf("--%s", opts->name); printf("--%s", opts->name);
if(opts->has_arg == 1) printf("=arg"); if(opts->has_arg == 1) printf("=arg");
else if(opts->has_arg == 2) printf("[=arg]"); else if(opts->has_arg == 2) printf("[=arg]");
printf(" %s\n", _(opts->help)); printf(" %s\n", _(opts->help));
exit(-1); exit(-1);
} }
// header, by default is just "progname\n" // header, by default is just "progname\n"
printf("\n"); printf("\n");
if(strstr(helpstring, "%s")) // print progname if(strstr(helpstring, "%s")) // print progname
printf(helpstring, __progname); printf(helpstring, __progname);
else // only text else // only text
printf("%s", helpstring); printf("%s", helpstring);
printf("\n"); printf("\n");
// count max_opt_len // count max_opt_len
do{ do{
int L = strlen(opts->name); int L = strlen(opts->name);
if(max_opt_len < L) max_opt_len = L; if(max_opt_len < L) max_opt_len = L;
}while((++opts)->name); }while((++opts)->name);
max_opt_len += 14; // format: '-S , --long[=arg]' - get addition 13 symbols max_opt_len += 14; // format: '-S , --long[=arg]' - get addition 13 symbols
opts = options; opts = options;
// count amount of options // count amount of options
int N; for(N = 0; opts->name; ++N, ++opts); int N; for(N = 0; opts->name; ++N, ++opts);
if(N == 0) exit(-2); if(N == 0) exit(-2);
// Now print all help (sorted) // Now print all help (sorted)
opts = options; opts = options;
qsort(opts, N, sizeof(myoption), argsort); qsort(opts, N, sizeof(myoption), argsort);
do{ do{
int p = sprintf(buf, " "); // a little indent int p = sprintf(buf, " "); // a little indent
if(!opts->flag && opts->val) // .val is short argument if(!opts->flag && opts->val) // .val is short argument
p += snprintf(buf+p, bufsz-p, "-%c, ", opts->val); p += snprintf(buf+p, bufsz-p, "-%c, ", opts->val);
p += snprintf(buf+p, bufsz-p, "--%s", opts->name); p += snprintf(buf+p, bufsz-p, "--%s", opts->name);
if(opts->has_arg == 1) // required argument if(opts->has_arg == 1) // required argument
p += snprintf(buf+p, bufsz-p, "=arg"); p += snprintf(buf+p, bufsz-p, "=arg");
else if(opts->has_arg == 2) // optional argument else if(opts->has_arg == 2) // optional argument
p += snprintf(buf+p, bufsz-p, "[=arg]"); p += snprintf(buf+p, bufsz-p, "[=arg]");
assert(p < max_opt_len); // there would be magic if p >= max_opt_len 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 printf("%-*s%s\n", max_opt_len+1, buf, _(opts->help)); // write options & at least 2 spaces after
++opts; ++opts;
}while(--N); }while(--N);
printf("\n\n"); printf("\n\n");
exit(-1); exit(-1);
} }
/** /**
@ -418,80 +418,80 @@ void showhelp(int oindex, myoption *options){
* @return TRUE if all OK * @return TRUE if all OK
*/ */
bool get_suboption(char *str, mysuboption *opt){ bool get_suboption(char *str, mysuboption *opt){
int findsubopt(char *par, mysuboption *so){ int findsubopt(char *par, mysuboption *so){
int idx = 0; int idx = 0;
if(!par) return -1; if(!par) return -1;
while(so[idx].name){ while(so[idx].name){
if(strcasecmp(par, so[idx].name) == 0) return idx; if(strcasecmp(par, so[idx].name) == 0) return idx;
++idx; ++idx;
} }
return -1; // badarg return -1; // badarg
} }
bool opt_setarg(mysuboption *so, int idx, char *val){ bool opt_setarg(mysuboption *so, int idx, char *val){
mysuboption *soptr = &so[idx]; mysuboption *soptr = &so[idx];
bool result = FALSE; bool result = FALSE;
void *aptr = soptr->argptr; void *aptr = soptr->argptr;
switch(soptr->type){ switch(soptr->type){
default: default:
case arg_none: case arg_none:
if(soptr->argptr) *((int*)aptr) += 1; // increment value if(soptr->argptr) *((int*)aptr) += 1; // increment value
result = TRUE; result = TRUE;
break; break;
case arg_int: case arg_int:
result = myatoll(aptr, val, arg_int); result = myatoll(aptr, val, arg_int);
break; break;
case arg_longlong: case arg_longlong:
result = myatoll(aptr, val, arg_longlong); result = myatoll(aptr, val, arg_longlong);
break; break;
case arg_double: case arg_double:
result = myatod(aptr, val, arg_double); result = myatod(aptr, val, arg_double);
break; break;
case arg_float: case arg_float:
result = myatod(aptr, val, arg_float); result = myatod(aptr, val, arg_float);
break; break;
case arg_string: case arg_string:
result = (*((void**)aptr) = (void*)strdup(val)); result = (*((void**)aptr) = (void*)strdup(val));
break; break;
case arg_function: case arg_function:
result = ((argfn)aptr)(val); result = ((argfn)aptr)(val);
break; break;
} }
return result; return result;
} }
char *tok; char *tok;
bool ret = FALSE; bool ret = FALSE;
char *tmpbuf; char *tmpbuf;
tok = strtok_r(str, ":,", &tmpbuf); tok = strtok_r(str, ":,", &tmpbuf);
do{ do{
char *val = strchr(tok, '='); char *val = strchr(tok, '=');
int noarg = 0; int noarg = 0;
if(val == NULL){ // no args if(val == NULL){ // no args
val = "1"; val = "1";
noarg = 1; noarg = 1;
}else{ }else{
*val++ = '\0'; *val++ = '\0';
if(!*val || *val == ':' || *val == ','){ // no argument - delimeter after = if(!*val || *val == ':' || *val == ','){ // no argument - delimeter after =
val = "1"; noarg = 1; val = "1"; noarg = 1;
} }
} }
int idx = findsubopt(tok, opt); int idx = findsubopt(tok, opt);
if(idx < 0){ if(idx < 0){
/// "îÅÐÒÁ×ÉÌØÎÙÊ ÐÁÒÁÍÅÔÒ: %s" /// "îÅÐÒÁ×ÉÌØÎÙÊ ÐÁÒÁÍÅÔÒ: %s"
WARNX(_("Wrong parameter: %s"), tok); WARNX(_("Wrong parameter: %s"), tok);
goto returning; goto returning;
} }
if(noarg && opt[idx].has_arg == NEED_ARG){ if(noarg && opt[idx].has_arg == NEED_ARG){
/// "%s: ÎÅÏÂÈÏÄÉÍ ÁÒÇÕÍÅÎÔ!" /// "%s: ÎÅÏÂÈÏÄÉÍ ÁÒÇÕÍÅÎÔ!"
WARNX(_("%s: argument needed!"), tok); WARNX(_("%s: argument needed!"), tok);
goto returning; goto returning;
} }
if(!opt_setarg(opt, idx, val)){ if(!opt_setarg(opt, idx, val)){
/// "îÅÐÒÁ×ÉÌØÎÙÊ ÁÒÇÕÍÅÎÔ \"%s\" ÐÁÒÁÍÅÔÒÁ \"%s\"" /// "îÅÐÒÁ×ÉÌØÎÙÊ ÁÒÇÕÍÅÎÔ \"%s\" ÐÁÒÁÍÅÔÒÁ \"%s\""
WARNX(_("Wrong argument \"%s\" of parameter \"%s\""), val, tok); WARNX(_("Wrong argument \"%s\" of parameter \"%s\""), val, tok);
goto returning; goto returning;
} }
}while((tok = strtok_r(NULL, ":,", &tmpbuf))); }while((tok = strtok_r(NULL, ":,", &tmpbuf)));
ret = TRUE; ret = TRUE;
returning: returning:
return ret; return ret;
} }

View File

@ -26,11 +26,11 @@
#include <stdlib.h> #include <stdlib.h>
#ifndef TRUE #ifndef TRUE
#define TRUE true #define TRUE true
#endif #endif
#ifndef FALSE #ifndef FALSE
#define FALSE false #define FALSE false
#endif #endif
// macro for argptr // macro for argptr
@ -44,35 +44,35 @@ typedef bool(*argfn)(void *arg);
* WARNING! * WARNING!
* My function change value of flags by pointer, so if you want to use another type * My function change value of flags by pointer, so if you want to use another type
* make a latter conversion, example: * make a latter conversion, example:
* char charg; * char charg;
* int iarg; * int iarg;
* myoption opts[] = { * myoption opts[] = {
* {"value", 1, NULL, 'v', arg_int, &iarg, "char val"}, ..., end_option}; * {"value", 1, NULL, 'v', arg_int, &iarg, "char val"}, ..., end_option};
* ..(parse args).. * ..(parse args)..
* charg = (char) iarg; * charg = (char) iarg;
*/ */
typedef enum { typedef enum {
arg_none = 0, // no arg arg_none = 0, // no arg
arg_int, // integer arg_int, // integer
arg_longlong, // long long arg_longlong, // long long
arg_double, // double arg_double, // double
arg_float, // float arg_float, // float
arg_string, // char * arg_string, // char *
arg_function // parse_args will run function `bool (*fn)(char *optarg, int N)` arg_function // parse_args will run function `bool (*fn)(char *optarg, int N)`
} argtype; } argtype;
/* /*
* Structure for getopt_long & help * Structure for getopt_long & help
* BE CAREFUL: .argptr is pointer to data or pointer to function, * 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, * ATTENTION: string `help` prints through macro PRNT(), bu default it is gettext,
* but you can redefine it before `#include "parseargs.h"` * but you can redefine it before `#include "parseargs.h"`
* *
* if arg is string, then value wil be strdup'ed like that: * if arg is string, then value wil be strdup'ed like that:
* char *str; * char *str;
* myoption opts[] = {{"string", 1, NULL, 's', arg_string, &str, "string val"}, ..., end_option}; * myoption opts[] = {{"string", 1, NULL, 's', arg_string, &str, "string val"}, ..., end_option};
* *(opts[1].str) = strdup(optarg); * *(opts[1].str) = strdup(optarg);
* in other cases argptr should be address of some variable (or pointer to allocated memory) * 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 * NON-NULL argptr should be written inside macro APTR(argptr) or directly: (void*)argptr
@ -81,22 +81,22 @@ typedef enum {
* *
*/ */
typedef enum{ typedef enum{
NO_ARGS = 0, // first three are the same as in getopt_long NO_ARGS = 0, // first three are the same as in getopt_long
NEED_ARG = 1, NEED_ARG = 1,
OPT_ARG = 2, OPT_ARG = 2,
MULT_PAR MULT_PAR
} hasarg; } hasarg;
typedef struct{ typedef struct{
// these are from struct option: // these are from struct option:
const char *name; // long option's name 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) 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 *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 int val; // short opt name (if flag == NULL) or flag's value
// and these are mine: // and these are mine:
argtype type; // type of argument argtype type; // type of argument
void *argptr; // pointer to variable to assign optarg value or function `bool (*fn)(char *optarg, int N)` 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 const char *help; // help string which would be shown in function `showhelp` or NULL
} myoption; } myoption;
/* /*
@ -104,10 +104,10 @@ typedef struct{
* used in parse_subopts() * used in parse_subopts()
*/ */
typedef struct{ typedef struct{
const char *name; const char *name;
hasarg has_arg; hasarg has_arg;
argtype type; argtype type;
void *argptr; void *argptr;
} mysuboption; } mysuboption;
// last string of array (all zeros) // last string of array (all zeros)

View File

@ -26,11 +26,11 @@
* @return double value: time in seconds * @return double value: time in seconds
*/ */
double dtime(){ double dtime(){
double t; double t;
struct timeval tv; struct timeval tv;
gettimeofday(&tv, NULL); gettimeofday(&tv, NULL);
t = tv.tv_sec + ((double)tv.tv_usec)/1e6; t = tv.tv_sec + ((double)tv.tv_usec)/1e6;
return t; return t;
} }
/******************************************************************************\ /******************************************************************************\
@ -50,22 +50,22 @@ int (*_WARN)(const char *fmt, ...);
* @return number of printed symbols * @return number of printed symbols
*/ */
int r_pr_(const char *fmt, ...){ int r_pr_(const char *fmt, ...){
va_list ar; int i; va_list ar; int i;
printf(RED); printf(RED);
va_start(ar, fmt); va_start(ar, fmt);
i = vprintf(fmt, ar); i = vprintf(fmt, ar);
va_end(ar); va_end(ar);
printf(OLDCOLOR); printf(OLDCOLOR);
return i; return i;
} }
int g_pr_(const char *fmt, ...){ int g_pr_(const char *fmt, ...){
va_list ar; int i; va_list ar; int i;
printf(GREEN); printf(GREEN);
va_start(ar, fmt); va_start(ar, fmt);
i = vprintf(fmt, ar); i = vprintf(fmt, ar);
va_end(ar); va_end(ar);
printf(OLDCOLOR); printf(OLDCOLOR);
return i; return i;
} }
/* /*
* print red error/warning messages (if output is a tty) * 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 * @return number of printed symbols
*/ */
int r_WARN(const char *fmt, ...){ int r_WARN(const char *fmt, ...){
va_list ar; int i = 1; va_list ar; int i = 1;
fprintf(stderr, RED); fprintf(stderr, RED);
va_start(ar, fmt); va_start(ar, fmt);
if(globErr){ if(globErr){
errno = globErr; errno = globErr;
vwarn(fmt, ar); vwarn(fmt, ar);
errno = 0; errno = 0;
globErr = 0; globErr = 0;
}else }else
i = vfprintf(stderr, fmt, ar); i = vfprintf(stderr, fmt, ar);
va_end(ar); va_end(ar);
i++; i++;
fprintf(stderr, OLDCOLOR "\n"); fprintf(stderr, OLDCOLOR "\n");
return i; return i;
} }
static const char stars[] = "****************************************"; static const char stars[] = "****************************************";
@ -97,49 +97,49 @@ static const char stars[] = "****************************************";
* @return number of printed symbols * @return number of printed symbols
*/ */
int s_WARN(const char *fmt, ...){ int s_WARN(const char *fmt, ...){
va_list ar; int i; va_list ar; int i;
i = fprintf(stderr, "\n%s\n", stars); i = fprintf(stderr, "\n%s\n", stars);
va_start(ar, fmt); va_start(ar, fmt);
if(globErr){ if(globErr){
errno = globErr; errno = globErr;
vwarn(fmt, ar); vwarn(fmt, ar);
errno = 0; errno = 0;
globErr = 0; globErr = 0;
}else }else
i = +vfprintf(stderr, fmt, ar); i = +vfprintf(stderr, fmt, ar);
va_end(ar); va_end(ar);
i += fprintf(stderr, "\n%s\n", stars); i += fprintf(stderr, "\n%s\n", stars);
i += fprintf(stderr, "\n"); i += fprintf(stderr, "\n");
return i; return i;
} }
int r_pr_notty(const char *fmt, ...){ int r_pr_notty(const char *fmt, ...){
va_list ar; int i; va_list ar; int i;
i = printf("\n%s\n", stars); i = printf("\n%s\n", stars);
va_start(ar, fmt); va_start(ar, fmt);
i += vprintf(fmt, ar); i += vprintf(fmt, ar);
va_end(ar); va_end(ar);
i += printf("\n%s\n", stars); i += printf("\n%s\n", stars);
return i; return i;
} }
/** /**
* Run this function in the beginning of main() to setup locale & coloured output * Run this function in the beginning of main() to setup locale & coloured output
*/ */
void initial_setup(){ void initial_setup(){
// setup coloured output // setup coloured output
if(isatty(STDOUT_FILENO)){ // make color output in tty if(isatty(STDOUT_FILENO)){ // make color output in tty
red = r_pr_; green = g_pr_; red = r_pr_; green = g_pr_;
}else{ // no colors in case of pipe }else{ // no colors in case of pipe
red = r_pr_notty; green = printf; red = r_pr_notty; green = printf;
} }
if(isatty(STDERR_FILENO)) _WARN = r_WARN; if(isatty(STDERR_FILENO)) _WARN = r_WARN;
else _WARN = s_WARN; else _WARN = s_WARN;
// Setup locale // Setup locale
setlocale(LC_ALL, ""); setlocale(LC_ALL, "");
setlocale(LC_NUMERIC, "C"); setlocale(LC_NUMERIC, "C");
#if defined GETTEXT_PACKAGE && defined LOCALEDIR #if defined GETTEXT_PACKAGE && defined LOCALEDIR
bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR); bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
textdomain(GETTEXT_PACKAGE); textdomain(GETTEXT_PACKAGE);
#endif #endif
} }
@ -153,10 +153,10 @@ void initial_setup(){
* @return pointer to allocated memory area * @return pointer to allocated memory area
*/ */
void *my_alloc(size_t N, size_t S){ void *my_alloc(size_t N, size_t S){
void *p = calloc(N, S); void *p = calloc(N, S);
if(!p) ERR("malloc"); if(!p) ERR("malloc");
//assert(p); //assert(p);
return p; return p;
} }
/** /**
@ -166,29 +166,29 @@ void *my_alloc(size_t N, size_t S){
* @return stuct with mmap'ed file or die * @return stuct with mmap'ed file or die
*/ */
mmapbuf *My_mmap(char *filename){ mmapbuf *My_mmap(char *filename){
int fd; int fd;
char *ptr; char *ptr;
size_t Mlen; size_t Mlen;
struct stat statbuf; struct stat statbuf;
if(!filename) ERRX(_("No filename given!")); if(!filename) ERRX(_("No filename given!"));
if((fd = open(filename, O_RDONLY)) < 0) if((fd = open(filename, O_RDONLY)) < 0)
ERR(_("Can't open %s for reading"), filename); ERR(_("Can't open %s for reading"), filename);
if(fstat (fd, &statbuf) < 0) if(fstat (fd, &statbuf) < 0)
ERR(_("Can't stat %s"), filename); ERR(_("Can't stat %s"), filename);
Mlen = statbuf.st_size; Mlen = statbuf.st_size;
if((ptr = mmap (0, Mlen, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED) if((ptr = mmap (0, Mlen, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED)
ERR(_("Mmap error for input")); ERR(_("Mmap error for input"));
if(close(fd)) ERR(_("Can't close mmap'ed file")); if(close(fd)) ERR(_("Can't close mmap'ed file"));
mmapbuf *ret = MALLOC(mmapbuf, 1); mmapbuf *ret = MALLOC(mmapbuf, 1);
ret->data = ptr; ret->data = ptr;
ret->len = Mlen; ret->len = Mlen;
return ret; return ret;
} }
void My_munmap(mmapbuf *b){ void My_munmap(mmapbuf *b){
if(munmap(b->data, b->len)) if(munmap(b->data, b->len))
ERR(_("Can't munmap")); ERR(_("Can't munmap"));
FREE(b); FREE(b);
} }
@ -199,23 +199,23 @@ static struct termios oldt, newt; // terminal flags
static int console_changed = 0; static int console_changed = 0;
// run on exit: // run on exit:
void restore_console(){ void restore_console(){
if(console_changed) if(console_changed)
tcsetattr(STDIN_FILENO, TCSANOW, &oldt); // return terminal to previous state tcsetattr(STDIN_FILENO, TCSANOW, &oldt); // return terminal to previous state
console_changed = 0; console_changed = 0;
} }
// initial setup: // initial setup:
void setup_con(){ void setup_con(){
if(console_changed) return; if(console_changed) return;
tcgetattr(STDIN_FILENO, &oldt); tcgetattr(STDIN_FILENO, &oldt);
newt = oldt; newt = oldt;
newt.c_lflag &= ~(ICANON | ECHO); newt.c_lflag &= ~(ICANON | ECHO);
if(tcsetattr(STDIN_FILENO, TCSANOW, &newt) < 0){ if(tcsetattr(STDIN_FILENO, TCSANOW, &newt) < 0){
WARN(_("Can't setup console")); WARN(_("Can't setup console"));
tcsetattr(STDIN_FILENO, TCSANOW, &oldt); tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
signals(0); //quit? signals(0); //quit?
} }
console_changed = 1; console_changed = 1;
} }
/** /**
@ -223,20 +223,20 @@ void setup_con(){
* @return char readed * @return char readed
*/ */
int read_console(){ int read_console(){
int rb; int rb;
struct timeval tv; struct timeval tv;
int retval; int retval;
fd_set rfds; fd_set rfds;
FD_ZERO(&rfds); FD_ZERO(&rfds);
FD_SET(STDIN_FILENO, &rfds); FD_SET(STDIN_FILENO, &rfds);
tv.tv_sec = 0; tv.tv_usec = 10000; tv.tv_sec = 0; tv.tv_usec = 10000;
retval = select(1, &rfds, NULL, NULL, &tv); retval = select(1, &rfds, NULL, NULL, &tv);
if(!retval) rb = 0; if(!retval) rb = 0;
else { else {
if(FD_ISSET(STDIN_FILENO, &rfds)) rb = getchar(); if(FD_ISSET(STDIN_FILENO, &rfds)) rb = getchar();
else rb = 0; else rb = 0;
} }
return rb; return rb;
} }
/** /**
@ -245,10 +245,10 @@ int read_console(){
* @return character readed * @return character readed
*/ */
int mygetchar(){ // getchar() without need of pressing ENTER int mygetchar(){ // getchar() without need of pressing ENTER
int ret; int ret;
do ret = read_console(); do ret = read_console();
while(ret == 0); while(ret == 0);
return ret; return ret;
} }
@ -260,10 +260,10 @@ static int comfd = -1; // TTY fd
// run on exit: // run on exit:
void restore_tty(){ void restore_tty(){
if(comfd == -1) return; if(comfd == -1) return;
ioctl(comfd, TCSANOW, &oldtty ); // return TTY to previous state ioctl(comfd, TCSANOW, &oldtty ); // return TTY to previous state
close(comfd); close(comfd);
comfd = -1; comfd = -1;
} }
#ifndef BAUD_RATE #ifndef BAUD_RATE
@ -271,29 +271,29 @@ void restore_tty(){
#endif #endif
// init: // init:
void tty_init(char *comdev){ void tty_init(char *comdev){
DBG("\nOpen port...\n"); DBG("\nOpen port...\n");
if ((comfd = open(comdev,O_RDWR|O_NOCTTY|O_NONBLOCK)) < 0){ if ((comfd = open(comdev,O_RDWR|O_NOCTTY|O_NONBLOCK)) < 0){
WARN("Can't use port %s\n",comdev); WARN("Can't use port %s\n",comdev);
ioctl(comfd, TCSANOW, &oldtty); // return TTY to previous state ioctl(comfd, TCSANOW, &oldtty); // return TTY to previous state
close(comfd); close(comfd);
signals(0); // quit? signals(0); // quit?
} }
DBG(" OK\nGet current settings... "); DBG(" OK\nGet current settings... ");
if(ioctl(comfd,TCGETA,&oldtty) < 0){ // Get settings if(ioctl(comfd,TCGETA,&oldtty) < 0){ // Get settings
WARN(_("Can't get settings")); WARN(_("Can't get settings"));
signals(0); signals(0);
} }
tty = oldtty; tty = oldtty;
tty.c_lflag = 0; // ~(ICANON | ECHO | ECHOE | ISIG) tty.c_lflag = 0; // ~(ICANON | ECHO | ECHOE | ISIG)
tty.c_oflag = 0; tty.c_oflag = 0;
tty.c_cflag = BAUD_RATE|CS8|CREAD|CLOCAL; // 9.6k, 8N1, RW, ignore line ctrl 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[VMIN] = 0; // non-canonical mode
tty.c_cc[VTIME] = 5; tty.c_cc[VTIME] = 5;
if(ioctl(comfd,TCSETA,&tty) < 0){ if(ioctl(comfd,TCSETA,&tty) < 0){
WARN(_("Can't set settings")); WARN(_("Can't set settings"));
signals(0); signals(0);
} }
DBG(" OK\n"); DBG(" OK\n");
} }
/** /**
* Read data from TTY * Read data from TTY
@ -302,26 +302,26 @@ void tty_init(char *comdev){
* @return amount of readed bytes * @return amount of readed bytes
*/ */
size_t read_tty(uint8_t *buff, size_t length){ size_t read_tty(uint8_t *buff, size_t length){
ssize_t L = 0; ssize_t L = 0;
fd_set rfds; fd_set rfds;
struct timeval tv; struct timeval tv;
int retval; int retval;
FD_ZERO(&rfds); FD_ZERO(&rfds);
FD_SET(comfd, &rfds); FD_SET(comfd, &rfds);
tv.tv_sec = 0; tv.tv_usec = 50000; // wait for 50ms tv.tv_sec = 0; tv.tv_usec = 50000; // wait for 50ms
retval = select(comfd + 1, &rfds, NULL, NULL, &tv); retval = select(comfd + 1, &rfds, NULL, NULL, &tv);
if (!retval) return 0; if (!retval) return 0;
if(FD_ISSET(comfd, &rfds)){ if(FD_ISSET(comfd, &rfds)){
if((L = read(comfd, buff, length)) < 1) return 0; if((L = read(comfd, buff, length)) < 1) return 0;
} }
return (size_t)L; return (size_t)L;
} }
int write_tty(uint8_t *buff, size_t length){ int write_tty(uint8_t *buff, size_t length){
ssize_t L = write(comfd, buff, length); ssize_t L = write(comfd, buff, length);
if((size_t)L != length){ if((size_t)L != length){
WARN("Write error!"); WARN("Write error!");
return 1; return 1;
} }
return 0; return 0;
} }

View File

@ -38,12 +38,12 @@
* GETTEXT * GETTEXT
*/ */
#include <libintl.h> #include <libintl.h>
#define _(String) gettext(String) #define _(String) gettext(String)
#define gettext_noop(String) String #define gettext_noop(String) String
#define N_(String) gettext_noop(String) #define N_(String) gettext_noop(String)
#else #else
#define _(String) (String) #define _(String) (String)
#define N_(String) (String) #define N_(String) (String)
#endif #endif
#include <stdlib.h> #include <stdlib.h>
#include <termios.h> #include <termios.h>
@ -59,9 +59,9 @@
/* /*
* Coloured messages output * Coloured messages output
*/ */
#define RED "\033[1;31;40m" #define RED "\033[1;31;40m"
#define GREEN "\033[1;32;40m" #define GREEN "\033[1;32;40m"
#define OLDCOLOR "\033[0;0;0m" #define OLDCOLOR "\033[0;0;0m"
/* /*
* ERROR/WARNING messages * ERROR/WARNING messages
@ -78,13 +78,13 @@ extern void signals(int sig);
* debug mode, -DEBUG * debug mode, -DEBUG
*/ */
#ifdef EBUG #ifdef EBUG
#define FNAME() fprintf(stderr, "\n%s (%s, line %d)\n", __func__, __FILE__, __LINE__) #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__); \ #define DBG(...) do{fprintf(stderr, "%s (%s, line %d): ", __func__, __FILE__, __LINE__); \
fprintf(stderr, __VA_ARGS__); \ fprintf(stderr, __VA_ARGS__); \
fprintf(stderr, "\n");} while(0) fprintf(stderr, "\n");} while(0)
#else #else
#define FNAME() do{}while(0) #define FNAME() do{}while(0)
#define DBG(...) do{}while(0) #define DBG(...) do{}while(0)
#endif //EBUG #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 ALLOC(type, var, size) type * var = ((type *)my_alloc(size, sizeof(type)))
#define MALLOC(type, size) ((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(); double dtime();
@ -105,8 +105,8 @@ void initial_setup();
// mmap file // mmap file
typedef struct{ typedef struct{
char *data; char *data;
size_t len; size_t len;
} mmapbuf; } mmapbuf;
mmapbuf *My_mmap(char *filename); mmapbuf *My_mmap(char *filename);
void My_munmap(mmapbuf *b); void My_munmap(mmapbuf *b);

View File

@ -21,18 +21,16 @@
#include "usefull_macros.h" #include "usefull_macros.h"
#include <sys/time.h>
/** /**
* function for different purposes that need to know time intervals * function for different purposes that need to know time intervals
* @return double value: time in seconds * @return double value: time in seconds
*/ */
double dtime(){ double dtime(){
double t; double t;
struct timeval tv; struct timeval tv;
gettimeofday(&tv, NULL); gettimeofday(&tv, NULL);
t = tv.tv_sec + ((double)tv.tv_usec)/1e6; t = tv.tv_sec + ((double)tv.tv_usec)/1e6;
return t; return t;
} }
/******************************************************************************\ /******************************************************************************\
@ -52,22 +50,22 @@ int (*_WARN)(const char *fmt, ...);
* @return number of printed symbols * @return number of printed symbols
*/ */
int r_pr_(const char *fmt, ...){ int r_pr_(const char *fmt, ...){
va_list ar; int i; va_list ar; int i;
printf(RED); printf(RED);
va_start(ar, fmt); va_start(ar, fmt);
i = vprintf(fmt, ar); i = vprintf(fmt, ar);
va_end(ar); va_end(ar);
printf(OLDCOLOR); printf(OLDCOLOR);
return i; return i;
} }
int g_pr_(const char *fmt, ...){ int g_pr_(const char *fmt, ...){
va_list ar; int i; va_list ar; int i;
printf(GREEN); printf(GREEN);
va_start(ar, fmt); va_start(ar, fmt);
i = vprintf(fmt, ar); i = vprintf(fmt, ar);
va_end(ar); va_end(ar);
printf(OLDCOLOR); printf(OLDCOLOR);
return i; return i;
} }
/* /*
* print red error/warning messages (if output is a tty) * 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 * @return number of printed symbols
*/ */
int r_WARN(const char *fmt, ...){ int r_WARN(const char *fmt, ...){
va_list ar; int i = 1; va_list ar; int i = 1;
fprintf(stderr, RED); fprintf(stderr, RED);
va_start(ar, fmt); va_start(ar, fmt);
if(globErr){ if(globErr){
errno = globErr; errno = globErr;
vwarn(fmt, ar); vwarn(fmt, ar);
errno = 0; errno = 0;
globErr = 0; globErr = 0;
}else }else
i = vfprintf(stderr, fmt, ar); i = vfprintf(stderr, fmt, ar);
va_end(ar); va_end(ar);
i++; i++;
fprintf(stderr, OLDCOLOR "\n"); fprintf(stderr, OLDCOLOR "\n");
return i; return i;
} }
const char stars[] = "****************************************"; static const char stars[] = "****************************************";
/* /*
* notty variants of coloured printf * notty variants of coloured printf
* name: s_WARN, r_pr_notty * name: s_WARN, r_pr_notty
@ -99,48 +97,50 @@ const char stars[] = "****************************************";
* @return number of printed symbols * @return number of printed symbols
*/ */
int s_WARN(const char *fmt, ...){ int s_WARN(const char *fmt, ...){
va_list ar; int i; va_list ar; int i;
i = fprintf(stderr, "\n%s\n", stars); i = fprintf(stderr, "\n%s\n", stars);
va_start(ar, fmt); va_start(ar, fmt);
if(globErr){ if(globErr){
errno = globErr; errno = globErr;
vwarn(fmt, ar); vwarn(fmt, ar);
errno = 0; errno = 0;
globErr = 0; globErr = 0;
}else }else
i = +vfprintf(stderr, fmt, ar); i = +vfprintf(stderr, fmt, ar);
va_end(ar); va_end(ar);
i += fprintf(stderr, "\n%s\n", stars); i += fprintf(stderr, "\n%s\n", stars);
i += fprintf(stderr, "\n"); i += fprintf(stderr, "\n");
return i; return i;
} }
int r_pr_notty(const char *fmt, ...){ int r_pr_notty(const char *fmt, ...){
va_list ar; int i; va_list ar; int i;
i = printf("\n%s\n", stars); i = printf("\n%s\n", stars);
va_start(ar, fmt); va_start(ar, fmt);
i += vprintf(fmt, ar); i += vprintf(fmt, ar);
va_end(ar); va_end(ar);
i += printf("\n%s\n", stars); i += printf("\n%s\n", stars);
return i; return i;
} }
/** /**
* Run this function in the beginning of main() to setup locale & coloured output * Run this function in the beginning of main() to setup locale & coloured output
*/ */
void initial_setup(){ void initial_setup(){
// setup coloured output // setup coloured output
if(isatty(STDOUT_FILENO)){ // make color output in tty if(isatty(STDOUT_FILENO)){ // make color output in tty
red = r_pr_; green = g_pr_; red = r_pr_; green = g_pr_;
}else{ // no colors in case of pipe }else{ // no colors in case of pipe
red = r_pr_notty; green = printf; red = r_pr_notty; green = printf;
} }
if(isatty(STDERR_FILENO)) _WARN = r_WARN; if(isatty(STDERR_FILENO)) _WARN = r_WARN;
else _WARN = s_WARN; else _WARN = s_WARN;
// Setup locale // Setup locale
setlocale(LC_ALL, ""); setlocale(LC_ALL, "");
setlocale(LC_NUMERIC, "C"); setlocale(LC_NUMERIC, "C");
bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR); #if defined GETTEXT_PACKAGE && defined LOCALEDIR
textdomain(GETTEXT_PACKAGE); bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
textdomain(GETTEXT_PACKAGE);
#endif
} }
/******************************************************************************\ /******************************************************************************\
@ -153,17 +153,12 @@ void initial_setup(){
* @return pointer to allocated memory area * @return pointer to allocated memory area
*/ */
void *my_alloc(size_t N, size_t S){ void *my_alloc(size_t N, size_t S){
void *p = calloc(N, S); void *p = calloc(N, S);
if(!p) ERR("malloc"); if(!p) ERR("malloc");
//assert(p); //assert(p);
return p; return p;
} }
/*
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
*/
/** /**
* Mmap file to a memory area * 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 * @return stuct with mmap'ed file or die
*/ */
mmapbuf *My_mmap(char *filename){ mmapbuf *My_mmap(char *filename){
int fd; int fd;
char *ptr; char *ptr;
size_t Mlen; size_t Mlen;
struct stat statbuf; struct stat statbuf;
if(!filename) ERRX(_("No filename given!")); /// "îÅ ÚÁÄÁÎÏ ÉÍÑ ÆÁÊÌÁ!"
if((fd = open(filename, O_RDONLY)) < 0) if(!filename){
ERR(_("Can't open %s for reading"), filename); WARNX(_("No filename given!"));
if(fstat (fd, &statbuf) < 0) return NULL;
ERR(_("Can't stat %s"), filename); }
Mlen = statbuf.st_size; if((fd = open(filename, O_RDONLY)) < 0){
if((ptr = mmap (0, Mlen, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED) /// "îÅ ÍÏÇÕ ÏÔËÒÙÔØ %s ÄÌÑ ÞÔÅÎÉÑ"
ERR(_("Mmap error for input")); WARN(_("Can't open %s for reading"), filename);
if(close(fd)) ERR(_("Can't close mmap'ed file")); return NULL;
mmapbuf *ret = MALLOC(mmapbuf, 1); }
ret->data = ptr; if(fstat (fd, &statbuf) < 0){
ret->len = Mlen; /// "îÅ ÍÏÇÕ ×ÙÐÏÌÎÉÔØ stat %s"
return ret; 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){ void My_munmap(mmapbuf *b){
if(munmap(b->data, b->len)) if(munmap(b->data, b->len)){
ERR(_("Can't munmap")); /// "îÅ ÍÏÇÕ munmap"
FREE(b); ERR(_("Can't munmap"));
}
FREE(b);
} }
/******************************************************************************\ /******************************************************************************\
* Terminal in no-echo mode * 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: // run on exit:
/* void restore_console(){
void quit(int sig){ if(console_changed)
//... tcsetattr(STDIN_FILENO, TCSANOW, &oldt); // return terminal to previous state
tcsetattr(STDIN_FILENO, TCSANOW, &oldt); // return terminal to previous state console_changed = 0;
//...
} }
*/
// initial setup: // initial setup:
void setup_con(){ void setup_con(){
tcgetattr(STDIN_FILENO, &oldt); if(console_changed) return;
newt = oldt; tcgetattr(STDIN_FILENO, &oldt);
newt.c_lflag &= ~(ICANON | ECHO); newt = oldt;
if(tcsetattr(STDIN_FILENO, TCSANOW, &newt) < 0){ newt.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &oldt); if(tcsetattr(STDIN_FILENO, TCSANOW, &newt) < 0){
exit(-2); //quit? /// "îÅ ÍÏÇÕ ÎÁÓÔÒÏÉÔØ ËÏÎÓÏÌØ"
} 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 * @return char readed
*/ */
int read_console(){ int read_console(){
int rb; int rb;
struct timeval tv; struct timeval tv;
int retval; int retval;
fd_set rfds; fd_set rfds;
FD_ZERO(&rfds); FD_ZERO(&rfds);
FD_SET(STDIN_FILENO, &rfds); FD_SET(STDIN_FILENO, &rfds);
tv.tv_sec = 0; tv.tv_usec = 10000; tv.tv_sec = 0; tv.tv_usec = 10000;
retval = select(1, &rfds, NULL, NULL, &tv); retval = select(1, &rfds, NULL, NULL, &tv);
if(!retval) rb = 0; if(!retval) rb = 0;
else { else {
if(FD_ISSET(STDIN_FILENO, &rfds)) rb = getchar(); if(FD_ISSET(STDIN_FILENO, &rfds)) rb = getchar();
else rb = 0; else rb = 0;
} }
return rb; return rb;
} }
/** /**
@ -246,50 +263,58 @@ int read_console(){
* wait until at least one character pressed * wait until at least one character pressed
* @return character readed * @return character readed
*/ */
int mygetchar(){ // аналог getchar() без необходимости жать Enter int mygetchar(){ // getchar() without need of pressing ENTER
int ret; int ret;
do ret = read_console(); do ret = read_console();
while(ret == 0); while(ret == 0);
return ret; return ret;
} }
/******************************************************************************\ /******************************************************************************\
* TTY with select() * TTY with select()
\******************************************************************************/ \******************************************************************************/
struct termio oldtty, tty; // TTY flags static struct termio oldtty, tty; // TTY flags
char *comdev; // TTY device name static int comfd = -1; // TTY fd
int comfd; // TTY fd
// run on exit: // run on exit:
/* void restore_tty(){
void quit(int ex_stat){ if(comfd == -1) return;
ioctl(comfd, TCSANOW, &oldtty ); // return TTY to previous state ioctl(comfd, TCSANOW, &oldtty ); // return TTY to previous state
close(comfd); close(comfd);
//... comfd = -1;
} }
*/
#ifndef BAUD_RATE #ifndef BAUD_RATE
#define BAUD_RATE B9600 #define BAUD_RATE B9600
#endif #endif
// init: // init:
void tty_init(){ void tty_init(char *comdev){
printf("\nOpen port...\n"); DBG("\nOpen port...\n");
if ((comfd = open(comdev,O_RDWR|O_NOCTTY|O_NONBLOCK)) < 0){ if ((comfd = open(comdev,O_RDWR|O_NOCTTY|O_NONBLOCK)) < 0){
fprintf(stderr,"Can't use port %s\n",comdev); WARN("Can't use port %s\n",comdev);
ioctl(comfd, TCSANOW, &oldtty); // return TTY to previous state ioctl(comfd, TCSANOW, &oldtty); // return TTY to previous state
close(comfd); close(comfd);
exit(1); // quit? signals(0); // quit?
} }
printf(" OK\nGet current settings...\n"); DBG(" OK\nGet current settings... ");
if(ioctl(comfd,TCGETA,&oldtty) < 0) exit(-1); // Get settings if(ioctl(comfd,TCGETA,&oldtty) < 0){ // Get settings
tty = oldtty; /// "îÅ ÍÏÇÕ ÐÏÌÕÞÉÔØ ÎÁÓÔÒÏÊËÉ"
tty.c_lflag = 0; // ~(ICANON | ECHO | ECHOE | ISIG) WARN(_("Can't get settings"));
tty.c_oflag = 0; signals(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 = oldtty;
tty.c_cc[VTIME] = 5; tty.c_lflag = 0; // ~(ICANON | ECHO | ECHOE | ISIG)
if(ioctl(comfd,TCSETA,&tty) < 0) exit(-1); // set new mode tty.c_oflag = 0;
printf(" OK\n"); 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 * Read data from TTY
@ -298,17 +323,49 @@ void tty_init(){
* @return amount of readed bytes * @return amount of readed bytes
*/ */
size_t read_tty(uint8_t *buff, size_t length){ size_t read_tty(uint8_t *buff, size_t length){
ssize_t L = 0; ssize_t L = 0;
fd_set rfds; fd_set rfds;
struct timeval tv; struct timeval tv;
int retval; int retval;
FD_ZERO(&rfds); FD_ZERO(&rfds);
FD_SET(comfd, &rfds); FD_SET(comfd, &rfds);
tv.tv_sec = 0; tv.tv_usec = 50000; // wait for 50ms tv.tv_sec = 0; tv.tv_usec = 50000; // wait for 50ms
retval = select(comfd + 1, &rfds, NULL, NULL, &tv); retval = select(comfd + 1, &rfds, NULL, NULL, &tv);
if (!retval) return 0; if (!retval) return 0;
if(FD_ISSET(comfd, &rfds)){ if(FD_ISSET(comfd, &rfds)){
if((L = read(comfd, buff, length)) < 1) return 0; if((L = read(comfd, buff, length)) < 1) return 0;
} }
return (size_t)L; 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;
} }

View File

@ -33,7 +33,18 @@
#include <errno.h> #include <errno.h>
#include <err.h> #include <err.h>
#include <locale.h> #include <locale.h>
#if defined GETTEXT_PACKAGE && defined LOCALEDIR
/*
* GETTEXT
*/
#include <libintl.h> #include <libintl.h>
#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 <stdlib.h> #include <stdlib.h>
#include <termios.h> #include <termios.h>
#include <termio.h> #include <termio.h>
@ -41,12 +52,6 @@
#include <sys/types.h> #include <sys/types.h>
#include <stdint.h> #include <stdint.h>
/*
* GETTEXT
*/
#define _(String) gettext(String)
#define gettext_noop(String) String
#define N_(String) gettext_noop(String)
// unused arguments with -Wall -Werror // unused arguments with -Wall -Werror
#define _U_ __attribute__((__unused__)) #define _U_ __attribute__((__unused__))
@ -54,16 +59,25 @@
/* /*
* Coloured messages output * Coloured messages output
*/ */
#define RED "\033[1;31;40m" #define RED "\033[1;31;40m"
#define GREEN "\033[1;32;40m" #define GREEN "\033[1;32;40m"
#define OLDCOLOR "\033[0;0;0m" #define OLDCOLOR "\033[0;0;0m"
#ifndef FALSE
#define FALSE (0)
#endif
#ifndef TRUE
#define TRUE (1)
#endif
/* /*
* ERROR/WARNING messages * ERROR/WARNING messages
*/ */
extern int globErr; extern int globErr;
#define ERR(...) do{globErr=errno; _WARN(__VA_ARGS__); exit(-1);}while(0) extern void signals(int sig);
#define ERRX(...) do{globErr=0; _WARN(__VA_ARGS__); exit(-1);}while(0) #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 WARN(...) do{globErr=errno; _WARN(__VA_ARGS__);}while(0)
#define WARNX(...) do{globErr=0; _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 * debug mode, -DEBUG
*/ */
#ifdef EBUG #ifdef EBUG
#define FNAME() fprintf(stderr, "\n%s (%s, line %d)\n", __func__, __FILE__, __LINE__) #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__); \ #define DBG(...) do{fprintf(stderr, "%s (%s, line %d): ", __func__, __FILE__, __LINE__); \
fprintf(stderr, __VA_ARGS__); \ fprintf(stderr, __VA_ARGS__); \
fprintf(stderr, "\n");} while(0) fprintf(stderr, "\n");} while(0)
#else #else
#define FNAME() do{}while(0) #define FNAME() do{}while(0)
#define DBG(...) do{}while(0) #define DBG(...) do{}while(0)
#endif //EBUG #endif //EBUG
/* /*
@ -86,7 +100,13 @@ extern int globErr;
*/ */
#define ALLOC(type, var, size) type * var = ((type *)my_alloc(size, sizeof(type))) #define ALLOC(type, var, size) type * var = ((type *)my_alloc(size, sizeof(type)))
#define MALLOC(type, size) ((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 // functions for color output in tty & no-color in pipes
extern int (*red)(const char *fmt, ...); extern int (*red)(const char *fmt, ...);
@ -97,10 +117,22 @@ void initial_setup();
// mmap file // mmap file
typedef struct{ typedef struct{
char *data; char *data;
size_t len; size_t len;
} mmapbuf; } mmapbuf;
mmapbuf *My_mmap(char *filename); mmapbuf *My_mmap(char *filename);
void My_munmap(mmapbuf *b); 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__ #endif // __USEFULL_MACROS_H__