fits_headers

This commit is contained in:
eddyem 2016-09-21 21:33:21 +03:00
parent 53f125383b
commit 8f5337f5d3
5 changed files with 834 additions and 0 deletions

25
fits_headers/Makefile Normal file
View File

@ -0,0 +1,25 @@
# run `make DEF=...` to add extra defines
PROGRAM = getangle
LDFLAGS = -lm
SRCS = $(wildcard *.c)
CC = gcc
DEFINES = $(DEF) -D_XOPEN_SOURCE=1111
#CXX = gcc
CFLAGS = -Wall -Werror -Wextra $(DEFINES)
OBJS = $(SRCS:.c=.o)
all : $(PROGRAM)
$(PROGRAM) : $(OBJS)
$(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) -o $(PROGRAM)
# some addition dependencies
# %.o: %.c
# $(CC) $(CFLAGS) $< -o $@
#$(SRCS) : %.c : %.h $(INDEPENDENT_HEADERS)
# @touch $@
#
#%.h: ;
clean:
/bin/rm -f *.o *~
depend:
$(CC) -MM $(SRCS)

50
fits_headers/README Normal file
View File

@ -0,0 +1,50 @@
Calculate camera rotation angle relative to BTA P2 angle
Rotation
Coordinates in FITS are relative to some reference pixel location. This doesn't need to be at the center or corner of the pixel or on the image; it's just a place where we tie a coordinate on the sky to a coordinate in pixel space.
In pixel space, this location is given by CRPIX1 and CRPIX2 (in horizontal "i" and vertical "j" directions). On the sky this location is at CRVAL1 and CRVAL2 coordinates in the native image coordinate system (e.g. RA, Dec).
This reference pixel also has size (i.e. the extent of the pixel on the sky) given by CDELT1 and CDELT2.
The first step in projecting a pixel location onto the sky is to convert the pixel (i,j) coordinate to an angular scale (i.e. psuedo-degrees still on the image plane surface).
If there were no rotation, this would be simply
x' = CDELT1 * (i - CRPIX1)
y' = CDELT2 * (j - CRPIX2)
The oldest approach to dealing with rotation used a simple rotation angle, CROTA2, to indicate how much the y' axis was rotated relative to North. Therefore the true (x,y) needed for input into projection formulae was
x = x' * cos(CROTA2) - y' * sin(CROTA2)
y = x' * sin(CROTA2) + y' * cos(CROTA2)
or
x = CDELT1*(i-CRPIX1)*cos(CROTA2) - CDELT2*(j-CRPIX2)*sin(CROTA2)
y = CDELT1*(i-CRPIX1)*sin(CROTA2) + CDELT2*(j-CRPIX2)*cos(CROTA2)
This approach doesn't allow for skewed pixels, etc. and no version of it based on, for instance, CROTA1 was ever widely used (if at all).
Instead, there are two alternative approaches which recognize that the above is essentially a matrix transform. One approach replaces the above with
x = (i-CRPIX1)*CD1_1 + (j-CRPIX2)*CD1_2
y = (i-CRPIX1)*CD2_1 + (j-CRPIX2)*CD2_2
The CD matrix elements here absorb both the CDELT values and the sin()/cos() of the rotation angle.
The second approach (which is the preferred one in the standard) keeps the CDELT values distinct:
x = CDELT1*(i-CRPIX1)*PC1_1 + CDELT2*(j-CRPIX2)*PC1_2
y = CDELT1*(i-CRPIX1)*PC2_1 + CDELT2*(j-CRPIX2)*PC2_2
RA = x + CRVAL1
DEC = y + CRVAL2
In the case where the CDELT values are equal, the PC matrix is a pure rotation.
Any of these three approaches are valid (two CDELTs and CROTA2, a CD matrix, or two CDELTs and a PC matrix) though the first relies on a parameter (CROTA2) which has been deprecated in the standard (and which cannot handle skewed pixels).
Montage relies on the WCS library from SAO (Doug Mink, incorporating the work of Calabretta) and this library carefully checks for all the possible historical variations above. However, this library (and therefore Montage) does not enforce any standards but instead does its best to interpret the intent of the data supplier. However, not all software is this conscientious and some confusion may arise if certain combinations of keywords are used. Therefore care should be taken in constructing headers for Montage use.

265
fits_headers/main.c Normal file
View File

@ -0,0 +1,265 @@
/*
* Read WCS FITS headers from files given in list and calculate median values of
* CROTA2 and CDELT1/CDELT2
* main.c
*
* Copyright 2016 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include "usefull_macros.h"
#include <math.h>
#ifndef DBL_EPSILON
#define DBL_EPSILON (2.2204460492503131e-16)
#endif
void signals(int sig){ exit(sig); }
/**
* return pointer to first symbol after '=' of key found or NULL
*/
char* get_key(double *keyval, char *keyname, char *hdu){
char *found = strstr(hdu, keyname);
if(!found) return NULL;
if(found[8] != '=') return NULL;
found += 9;
if(!keyval) return found;
char *eptr;
*keyval = strtod(found, &eptr);
if(eptr == found) return NULL;
return found;
}
/* convert angle ang to [0..360] */
double rev360(double ang){
while(ang < 0.) ang += 360.;
while(ang > 360.) ang -= 360.;
return ang;
}
/* convert angle ang to [-180..180] */
double rev180(double ang){
while(ang < -180.) ang += 360.;
while(ang > 180.) ang -= 360.;
return ang;
}
typedef double Item;
#define ELEM_SWAP(a, b) {register Item t = a; a = b; b = t;}
#define PIX_SORT(a, b) {if (a > b) ELEM_SWAP(a, b);}
/**
* quick select - algo for approximate median calculation for array idata of size n
*/
Item quick_select(Item *idata, int n){
int low, high;
int median;
int middle, ll, hh;
Item *arr = MALLOC(Item, n);
memcpy(arr, idata, n*sizeof(Item));
low = 0 ; high = n-1 ; median = (low + high) / 2;
for(;;){
if(high <= low) // One element only
break;
if(high == low + 1){ // Two elements only
PIX_SORT(arr[low], arr[high]) ;
break;
}
// Find median of low, middle and high items; swap into position low
middle = (low + high) / 2;
PIX_SORT(arr[middle], arr[high]) ;
PIX_SORT(arr[low], arr[high]) ;
PIX_SORT(arr[middle], arr[low]) ;
// Swap low item (now in position middle) into position (low+1)
ELEM_SWAP(arr[middle], arr[low+1]) ;
// Nibble from each end towards middle, swapping items when stuck
ll = low + 1;
hh = high;
for(;;){
do ll++; while (arr[low] > arr[ll]);
do hh--; while (arr[hh] > arr[low]);
if(hh < ll) break;
ELEM_SWAP(arr[ll], arr[hh]) ;
}
// Swap middle item (in position low) back into correct position
ELEM_SWAP(arr[low], arr[hh]) ;
// Re-set active partition
if (hh <= median) low = ll;
if (hh >= median) high = hh - 1;
}
Item ret = arr[median];
FREE(arr);
return ret;
}
#undef PIX_SORT
#undef ELEM_SWAP
// calculate standard deviation between array `arr` and value `val`, N - length of `arr`
double get_std(double *arr, double val, int N){
double diff = 0.;
int i;
for(i = 0; i < N; ++i, ++arr){
double d = *arr - val;
diff += d*d; // SUM(X - val)^2
}
DBG("diff: %g", diff);
return sqrt(diff/N); // AVER[(X - val)^2]
}
/**
* Remove data outliers (>3RMS) & do correction for angles near 360degr
* @param buf (io) - buffer with data
* @param N (io) - data length
* @param med - median data value
* @param std - RMS of data values
*/
void rm_outliers(double **buf, int *N, double med, double std){
if(std > med/2.) std = med/2.; // standard deviation can't be so large
std *= 3.;
int L = 0, i, oN = *N;
double *ret = MALLOC(double, oN), *rptr = ret, *iptr = *buf;
for(i = 0; i < oN; ++i, ++iptr){
double d = *iptr;
if(fabs(d - med) > std){
if(fabs(d - 360.) < std && med < std) // angle near 360 and median near 0
d -= 360.;
else if(d < std && fabs(med - 360.) < std) // vice versa
d += 360.;
}
if(fabs(d - med) < std){
*rptr++ = d;
++L;
}else printf("Outlier: %g (median=%g, 3RMS=%g)\n", d, med, std);
}
if(L != *N) printf("%d outliers removed (from %d)\n\n", *N-L, *N);
free(*buf);
*buf = ret;
*N = L;
}
int main(int argc, char **argv){
initial_setup();
if(argc == 1)
ERRX("Usage: %s <filename[s]>\n", argv[0]);
int c, N = 0;
double *arr = MALLOC(double, argc-1), *curdata = arr;
double *scales = MALLOC(double, argc-1), *curscale = scales;
for(c = 1; c < argc; ++c){
green("\nFile: %s\n", argv[c]);
mmapbuf *map = My_mmap(argv[c]);
if(!map) goto unm;
char *hdr = map->data;
char hdrend[81] = {'E', 'N', 'D'};
int i,j;
for(i = 3; i < 81; ++i) hdrend[i] = ' ';
hdrend[80] = 0;
char *e = strstr(hdr, hdrend);
if(!e){
WARNX("Can't find HDU end");
goto unm;
}
size_t sz = e - hdr + 1;
DBG("len = %zd", sz);
char *header = MALLOC(char, sz);
memcpy(header, hdr, sz);
double parangle, rotangle, CD[3][3];
if(get_key(&parangle, "PARANGLE", header))
printf("PARANGLE=%g\n", parangle);
else goto unm;
if((header = get_key(&rotangle, "ROTANGLE", header))){
double r = rotangle;
if((get_key(&rotangle, "ROTANGLE", header))){
printf("ROTANGLE=%g\n", rotangle);
}else{
if(fabs(r-parangle) > DBL_EPSILON){
rotangle = r;
printf("ROTANGLE=%g\n", rotangle);
}
else goto unm;
}
}else goto unm;
for(i = 1; i < 3; ++i) for(j = 1; j < 3; ++j){
char val[9];
snprintf(val, 8, "CD%d_%d", i,j);
if(!get_key(&CD[i][j], val, header)) goto unm;
printf("CD[%d][%d]=%g\n", i,j, CD[i][j]);
}
double angle = atan2(CD[2][1], CD[2][2])*180/M_PI;
int dir = 1;
if(CD[1][1]*CD[2][2] < 0. || CD[1][2] * CD[2][1] > 0.) dir = -1; // left-sided
// shortest transit from DEC axis to RA axis: counter-clock wise or clock-wise
printf("angle: %g, dir: %s\n", angle, dir > 0 ? "CW" : "CCW");
double R0;
if(dir < 0){
R0 = rev360(angle + rotangle - parangle);
printf("angle + ROTANGLE - PARANGLE = %g\n", R0);
}else{
R0 = rev360(angle - rotangle + parangle);
printf("angle - ROTANGLE + PARANGLE = %g\n", R0);
}
*curdata++ = R0;
++N;
double sc0;
// who is nearest to 1: sin or cos?
double an = fabs(rev180(angle));
if(an > 135. || an < 45.){ // sin - CD[1][2]
sc0 = fabs(CD[1][2]*3600./sin(angle*M_PI/180));
DBG("sin");
}else{ // cos - CD[1][1]
sc0 = fabs(CD[1][1]*3600./cos(angle*M_PI/180));
DBG("cos");
}
printf("Scale: %g''/pix\n", sc0);
*curscale++ = sc0;
unm:
My_munmap(map);
}
if(N > 1){
printf("\n\n");
double R0 = 1., scale = 1., Rstd = 0., scstd = 0.;
int badsR = 0, badssc = 0, k, Nsc = N, Nr = N;
for(k = 0; k < 3; ++k){ // twice remove outliers
if(badsR || Rstd > 0.05*R0){
rm_outliers(&arr, &Nr, R0, Rstd);
badsR = 0;
}
if(badssc || scstd > 0.05*scale){
rm_outliers(&scales, &Nsc, scale, scstd);
badssc = 0;
}
R0 = quick_select(arr, Nr);
scale = quick_select(scales, Nsc);
curdata = arr; curscale = scales;
Rstd = get_std(arr, R0, Nr);
scstd = 3.*get_std(scales, scale, Nsc);
double _3Rstd = 3.*Rstd, _3scstd = 3.*scstd;
for(c = 0; c < Nr; ++c, ++curdata)
if(fabs(*curdata - R0) > _3Rstd){
++badsR;
}
for(c = 0; c < Nsc; ++c, ++curscale){
if(fabs(*curscale - scale) > _3scstd) ++badssc;
}
}
green("Median values: ROT0=%g (%d values > 3std), std=%g), CDELT1/CDELT2=%g (%d values > 3std), std=%g\n", R0, badsR,
Rstd, scale, badssc, scstd);
if(badsR > Nr/2) WARNX("Very bad statistics for ROT0, not safe value!");
if(badssc > Nsc/2) WARNX("Very bad statistics for CDELT, not safe value!");
}
return 0;
}

View File

@ -0,0 +1,360 @@
/*
* usefull_macros.h - a set of usefull functions: memory, color etc
*
* Copyright 2013 Edward V. Emelianoff <eddy@sao.ru>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include "usefull_macros.h"
/**
* 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;
}
/******************************************************************************\
* Coloured terminal
\******************************************************************************/
int globErr = 0; // errno for WARN/ERR
// pointers to coloured output printf
int (*red)(const char *fmt, ...);
int (*green)(const char *fmt, ...);
int (*_WARN)(const char *fmt, ...);
/*
* format red / green messages
* name: r_pr_, g_pr_
* @param fmt ... - printf-like format
* @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;
}
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;
}
/*
* print red error/warning messages (if output is a tty)
* @param fmt ... - printf-like format
* @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;
}
static const char stars[] = "****************************************";
/*
* notty variants of coloured printf
* name: s_WARN, r_pr_notty
* @param fmt ... - printf-like format
* @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;
}
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;
}
/**
* 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");
#if defined GETTEXT_PACKAGE && defined LOCALEDIR
bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
textdomain(GETTEXT_PACKAGE);
#endif
}
/******************************************************************************\
* Memory
\******************************************************************************/
/*
* safe memory allocation for macro ALLOC
* @param N - number of elements to allocate
* @param S - size of single element (typically sizeof)
* @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;
}
/**
* Mmap file to a memory area
*
* @param filename (i) - name of file to mmap
* @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)
/// "îÅ ÍÏÇÕ ÏÔËÒÙÔØ %s ÄÌÑ ÞÔÅÎÉÑ"
ERR(_("Can't open %s for reading"), filename);
if(fstat (fd, &statbuf) < 0)
/// "îÅ ÍÏÇÕ ×ÙÐÏÌÎÉÔØ stat %s"
ERR(_("Can't stat %s"), filename);
Mlen = statbuf.st_size;
if((ptr = mmap (0, Mlen, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED)
/// "ïÛÉÂËÁ mmap"
ERR(_("Mmap error for input"));
/// "îÅ ÍÏÇÕ ÚÁËÒÙÔØ mmap'ÎÕÔÙÊ ÆÁÊÌ"
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)){
/// "îÅ ÍÏÇÕ munmap"
ERR(_("Can't munmap"));
}
FREE(b);
}
/******************************************************************************\
* Terminal in no-echo mode
\******************************************************************************/
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;
}
// 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;
}
/**
* Read character from console without echo
* @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;
}
/**
* getchar() without echo
* wait until at least one character pressed
* @return character readed
*/
int mygetchar(){ // getchar() without need of pressing ENTER
int ret;
do ret = read_console();
while(ret == 0);
return ret;
}
/******************************************************************************\
* TTY with select()
\******************************************************************************/
static struct termio oldtty, tty; // TTY flags
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;
}
#ifndef BAUD_RATE
#define BAUD_RATE B9600
#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");
}
/**
* Read data from TTY
* @param buff (o) - buffer for data read
* @param length - buffer len
* @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;
}
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

@ -0,0 +1,134 @@
/*
* usefull_macros.h - a set of usefull macros: memory, color etc
*
* Copyright 2013 Edward V. Emelianoff <eddy@sao.ru>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#pragma once
#ifndef __USEFULL_MACROS_H__
#define __USEFULL_MACROS_H__
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <errno.h>
#include <err.h>
#include <locale.h>
#if defined GETTEXT_PACKAGE && defined LOCALEDIR
/*
* GETTEXT
*/
#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 <termios.h>
#include <termio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <stdint.h>
// unused arguments with -Wall -Werror
#define _U_ __attribute__((__unused__))
/*
* Coloured messages output
*/
#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;
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)
/*
* print function name, debug messages
* 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)
#else
#define FNAME() do{}while(0)
#define DBG(...) do{}while(0)
#endif //EBUG
/*
* Memory allocation
*/
#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{if(ptr){free(ptr); ptr = NULL;}}while(0)
double dtime();
// functions for color output in tty & no-color in pipes
extern int (*red)(const char *fmt, ...);
extern int (*_WARN)(const char *fmt, ...);
extern int (*green)(const char *fmt, ...);
void * my_alloc(size_t N, size_t S);
void initial_setup();
// mmap file
typedef struct{
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__