#include <stdio.h>
#include <stdlib.h>
#ifdef sparc
#include <malloc.h>
#include <memory.h>
#endif
#include <string.h>
#include "fitsio2.h"
#include "grparser.h"
NGP_RAW_LINE ngp_curline = { NULL, NULL, NULL, NGP_TTYPE_UNKNOWN, NULL, NGP_FORMAT_OK, 0 };
NGP_RAW_LINE ngp_prevline = { NULL, NULL, NULL, NGP_TTYPE_UNKNOWN, NULL, NGP_FORMAT_OK, 0 };
int ngp_inclevel = 0;
int ngp_grplevel = 0;
FILE *ngp_fp[NGP_MAX_INCLUDE];
int ngp_keyidx = NGP_TOKEN_UNKNOWN;
NGP_TOKEN ngp_linkey;
char ngp_master_dir[NGP_MAX_FNAME];
NGP_TKDEF ngp_tkdef[] =
{ { "\\INCLUDE", NGP_TOKEN_INCLUDE },
{ "\\GROUP", NGP_TOKEN_GROUP },
{ "\\END", NGP_TOKEN_END },
{ "XTENSION", NGP_TOKEN_XTENSION },
{ "SIMPLE", NGP_TOKEN_SIMPLE },
{ NULL, NGP_TOKEN_UNKNOWN }
};
int master_grp_idx = 1;
int ngp_extver_tab_size = 0;
NGP_EXTVER_TAB *ngp_extver_tab = NULL;
int ngp_get_extver(char *extname, int *version)
{ NGP_EXTVER_TAB *p;
char *p2;
int i;
if ((NULL == extname) || (NULL == version)) return(NGP_BAD_ARG);
if ((NULL == ngp_extver_tab) && (ngp_extver_tab_size > 0)) return(NGP_BAD_ARG);
if ((NULL != ngp_extver_tab) && (ngp_extver_tab_size <= 0)) return(NGP_BAD_ARG);
for (i=0; i<ngp_extver_tab_size; i++)
{ if (0 == strcmp(extname, ngp_extver_tab[i].extname))
{ *version = (++ngp_extver_tab[i].version);
return(NGP_OK);
}
}
if (NULL == ngp_extver_tab)
{ p = (NGP_EXTVER_TAB *)ngp_alloc(sizeof(NGP_EXTVER_TAB)); }
else
{ p = (NGP_EXTVER_TAB *)ngp_realloc(ngp_extver_tab, (ngp_extver_tab_size + 1) * sizeof(NGP_EXTVER_TAB)); }
if (NULL == p) return(NGP_NO_MEMORY);
p2 = ngp_alloc(strlen(extname) + 1);
if (NULL == p2)
{ ngp_free(p);
return(NGP_NO_MEMORY);
}
strcpy(p2, extname);
ngp_extver_tab = p;
ngp_extver_tab[ngp_extver_tab_size].extname = p2;
*version = ngp_extver_tab[ngp_extver_tab_size].version = 1;
ngp_extver_tab_size++;
return(NGP_OK);
}
int ngp_set_extver(char *extname, int version)
{ NGP_EXTVER_TAB *p;
char *p2;
int i;
if (NULL == extname) return(NGP_BAD_ARG);
if ((NULL == ngp_extver_tab) && (ngp_extver_tab_size > 0)) return(NGP_BAD_ARG);
if ((NULL != ngp_extver_tab) && (ngp_extver_tab_size <= 0)) return(NGP_BAD_ARG);
for (i=0; i<ngp_extver_tab_size; i++)
{ if (0 == strcmp(extname, ngp_extver_tab[i].extname))
{ if (version > ngp_extver_tab[i].version) ngp_extver_tab[i].version = version;
return(NGP_OK);
}
}
if (NULL == ngp_extver_tab)
{ p = (NGP_EXTVER_TAB *)ngp_alloc(sizeof(NGP_EXTVER_TAB)); }
else
{ p = (NGP_EXTVER_TAB *)ngp_realloc(ngp_extver_tab, (ngp_extver_tab_size + 1) * sizeof(NGP_EXTVER_TAB)); }
if (NULL == p) return(NGP_NO_MEMORY);
p2 = ngp_alloc(strlen(extname) + 1);
if (NULL == p2)
{ ngp_free(p);
return(NGP_NO_MEMORY);
}
strcpy(p2, extname);
ngp_extver_tab = p;
ngp_extver_tab[ngp_extver_tab_size].extname = p2;
ngp_extver_tab[ngp_extver_tab_size].version = version;
ngp_extver_tab_size++;
return(NGP_OK);
}
int ngp_delete_extver_tab(void)
{ int i;
if ((NULL == ngp_extver_tab) && (ngp_extver_tab_size > 0)) return(NGP_BAD_ARG);
if ((NULL != ngp_extver_tab) && (ngp_extver_tab_size <= 0)) return(NGP_BAD_ARG);
if ((NULL == ngp_extver_tab) && (0 == ngp_extver_tab_size)) return(NGP_OK);
for (i=0; i<ngp_extver_tab_size; i++)
{ if (NULL != ngp_extver_tab[i].extname)
{ ngp_free(ngp_extver_tab[i].extname);
ngp_extver_tab[i].extname = NULL;
}
ngp_extver_tab[i].version = 0;
}
ngp_free(ngp_extver_tab);
ngp_extver_tab = NULL;
ngp_extver_tab_size = 0;
return(NGP_OK);
}
int ngp_line_from_file(FILE *fp, char **p)
{ int c, r, llen, allocsize, alen;
char *p2;
if (NULL == fp) return(NGP_NUL_PTR);
if (NULL == p) return(NGP_NUL_PTR);
r = NGP_OK;
llen = 0;
*p = (char *)ngp_alloc(1);
allocsize = 1;
if (NULL == *p) return(NGP_NO_MEMORY);
for (;;)
{ c = getc(fp);
if ('\r' == c) continue;
if (EOF == c)
{
if (ferror(fp)) r = NGP_READ_ERR;
if (0 == llen) return(NGP_EOF);
break;
}
if ('\n' == c) break;
llen++;
alen = ((llen + NGP_ALLOCCHUNK) / NGP_ALLOCCHUNK) * NGP_ALLOCCHUNK;
if (alen > allocsize)
{ p2 = (char *)ngp_realloc(*p, alen);
if (NULL == p2)
{ r = NGP_NO_MEMORY;
break;
}
*p = p2;
allocsize = alen;
}
(*p)[llen - 1] = c;
}
llen++;
if (llen != allocsize)
{ p2 = (char *)ngp_realloc(*p, llen);
if (NULL == p2) r = NGP_NO_MEMORY;
else
{ *p = p2;
(*p)[llen - 1] = 0;
}
}
else
{ (*p)[llen - 1] = 0;
}
if ((NGP_EOF != r) && (NGP_OK != r))
{ ngp_free(*p);
*p = NULL;
}
return(r);
}
int ngp_free_line(void)
{
if (NULL != ngp_curline.line)
{ ngp_free(ngp_curline.line);
ngp_curline.line = NULL;
ngp_curline.name = NULL;
ngp_curline.value = NULL;
ngp_curline.comment = NULL;
ngp_curline.type = NGP_TTYPE_UNKNOWN;
ngp_curline.format = NGP_FORMAT_OK;
ngp_curline.flags = 0;
}
return(NGP_OK);
}
int ngp_free_prevline(void)
{
if (NULL != ngp_prevline.line)
{ ngp_free(ngp_prevline.line);
ngp_prevline.line = NULL;
ngp_prevline.name = NULL;
ngp_prevline.value = NULL;
ngp_prevline.comment = NULL;
ngp_prevline.type = NGP_TTYPE_UNKNOWN;
ngp_prevline.format = NGP_FORMAT_OK;
ngp_prevline.flags = 0;
}
return(NGP_OK);
}
int ngp_read_line_buffered(FILE *fp)
{
ngp_free_line();
if (NULL != ngp_prevline.line)
{ ngp_curline = ngp_prevline;
ngp_prevline.line = NULL;
ngp_prevline.name = NULL;
ngp_prevline.value = NULL;
ngp_prevline.comment = NULL;
ngp_prevline.type = NGP_TTYPE_UNKNOWN;
ngp_prevline.format = NGP_FORMAT_OK;
ngp_prevline.flags = 0;
ngp_curline.flags = NGP_LINE_REREAD;
return(NGP_OK);
}
ngp_curline.flags = 0;
return(ngp_line_from_file(fp, &(ngp_curline.line)));
}
int ngp_unread_line(void)
{
if (NULL == ngp_curline.line)
return(NGP_EMPTY_CURLINE);
if (NULL != ngp_prevline.line)
return(NGP_UNREAD_QUEUE_FULL);
ngp_prevline = ngp_curline;
ngp_curline.line = NULL;
return(NGP_OK);
}
int ngp_extract_tokens(NGP_RAW_LINE *cl)
{ char *p, *s;
int cl_flags, i;
p = cl->line;
if (NULL == p) return(NGP_NUL_PTR);
cl->name = cl->value = cl->comment = NULL;
cl->type = NGP_TTYPE_UNKNOWN;
cl->format = NGP_FORMAT_OK;
cl_flags = 0;
for (i=0;; i++)
{ if ((0 == *p) || ('\n' == *p))
{
cl->line[0] = 0;
cl->comment = cl->name = cl->line;
cl->type = NGP_TTYPE_RAW;
return(NGP_OK);
}
if ((' ' != *p) && ('\t' != *p)) break;
if (i >= 7)
{
cl->comment = p + 1;
for (s = cl->comment;; s++)
{ if ('\n' == *s) *s = 0;
if (0 == *s) break;
}
cl->line[0] = 0;
cl->name = cl->line;
cl->type = NGP_TTYPE_RAW;
return(NGP_OK);
}
p++;
}
cl->name = p;
for (;;)
{ if ((0 == *p) || ('\n' == *p))
{ *p = 0;
break;
}
if( fits_strncasecmp("HIERARCH",p,strlen("HIERARCH")) == 0 )
{
char * const eqsi=strchr(p,'=') ;
if( eqsi )
{
cl_flags |= NGP_FOUND_EQUAL_SIGN ;
p=eqsi ;
break ;
}
}
if ((' ' == *p) || ('\t' == *p)) break;
if ('=' == *p)
{ cl_flags |= NGP_FOUND_EQUAL_SIGN;
break;
}
p++;
}
if (*p) *(p++) = 0;
if ((!fits_strcasecmp("HISTORY", cl->name))
|| (!fits_strcasecmp("COMMENT", cl->name))
|| (!fits_strcasecmp("CONTINUE", cl->name)))
{ cl->comment = p;
for (s = cl->comment;; s++)
{ if ('\n' == *s) *s = 0;
if (0 == *s) break;
}
cl->type = NGP_TTYPE_RAW;
return(NGP_OK);
}
if (!fits_strcasecmp("\\INCLUDE", cl->name))
{
for (;; p++) if ((' ' != *p) && ('\t' != *p)) break;
cl->value = p;
for (s = cl->value;; s++)
{ if ('\n' == *s) *s = 0;
if (0 == *s) break;
}
cl->type = NGP_TTYPE_UNKNOWN;
return(NGP_OK);
}
for (;; p++)
{ if ((0 == *p) || ('\n' == *p)) return(NGP_OK);
if ((' ' == *p) || ('\t' == *p)) continue;
if (cl_flags & NGP_FOUND_EQUAL_SIGN) break;
if ('=' != *p) break;
cl_flags |= NGP_FOUND_EQUAL_SIGN;
}
if ('/' == *p)
{ p++;
if ((' ' == *p) || ('\t' == *p)) p++;
cl->comment = p;
for (s = cl->comment;; s++)
{ if ('\n' == *s) *s = 0;
if (0 == *s) break;
}
return(NGP_OK);
}
if ('\'' == *p)
{ cl->value = s = ++p;
cl->type = NGP_TTYPE_STRING;
for (;;)
{ if ((0 == *p) || ('\n' == *p))
{ *s = 0; return(NGP_OK); }
if ('\'' == *p)
{ if ((0 == p[1]) || ('\n' == p[1]))
{ *s = 0; return(NGP_OK); }
if (('\t' == p[1]) || (' ' == p[1]))
{ *s = 0; p++; break; }
if ('\'' == p[1]) p++;
}
*(s++) = *(p++);
}
}
else
{
cl->value = p;
cl->type = NGP_TTYPE_UNKNOWN;
for (;; p++)
{ if ((0 == *p) || ('\n' == *p))
{ *p = 0; return(NGP_OK); }
if ((' ' == *p) || ('\t' == *p)) break;
}
if (*p) *(p++) = 0;
}
for (;; p++)
{ if ((0 == *p) || ('\n' == *p)) return(NGP_OK);
if ((' ' != *p) && ('\t' != *p)) break;
}
if ('/' == *p)
{ p++;
if ((' ' == *p) || ('\t' == *p)) p++;
cl->comment = p;
for (s = cl->comment;; s++)
{ if ('\n' == *s) *s = 0;
if (0 == *s) break;
}
return(NGP_OK);
}
cl->format = NGP_FORMAT_ERROR;
return(NGP_OK);
}
int ngp_include_file(char *fname)
{ char *p, *p2, *cp, *envar, envfiles[NGP_MAX_ENVFILES];
char *saveptr;
if (NULL == fname) return(NGP_NUL_PTR);
if (ngp_inclevel >= NGP_MAX_INCLUDE)
return(NGP_INC_NESTING);
if (NULL == (ngp_fp[ngp_inclevel] = fopen(fname, "r")))
{
envar = getenv("CFITSIO_INCLUDE_FILES");
if (NULL != envar)
{ strncpy(envfiles, envar, NGP_MAX_ENVFILES - 1);
envfiles[NGP_MAX_ENVFILES - 1] = 0;
for (p2 = ffstrtok(envfiles, ":",&saveptr); NULL != p2; p2 = ffstrtok(NULL, ":",&saveptr))
{
cp = (char *)ngp_alloc(strlen(fname) + strlen(p2) + 2);
if (NULL == cp) return(NGP_NO_MEMORY);
strcpy(cp, p2);
#ifdef MSDOS
strcat(cp, "\\");
#else
strcat(cp, "/");
#endif
strcat(cp, fname);
ngp_fp[ngp_inclevel] = fopen(cp, "r");
ngp_free(cp);
if (NULL != ngp_fp[ngp_inclevel]) break;
}
}
if (NULL == ngp_fp[ngp_inclevel])
{
#ifdef MSDOS
if ('\\' == fname[0]) return(NGP_ERR_FOPEN);
#else
if ('/' == fname[0]) return(NGP_ERR_FOPEN);
#endif
if (0 == ngp_master_dir[0]) return(NGP_ERR_FOPEN);
p = ngp_alloc(strlen(fname) + strlen(ngp_master_dir) + 1);
if (NULL == p) return(NGP_NO_MEMORY);
strcpy(p, ngp_master_dir);
strcat(p, fname);
ngp_fp[ngp_inclevel] = fopen(p, "r");
ngp_free(p);
if (NULL == ngp_fp[ngp_inclevel])
return(NGP_ERR_FOPEN);
}
}
ngp_inclevel++;
return(NGP_OK);
}
int ngp_read_line(int ignore_blank_lines)
{ int r, nc, savec;
unsigned k;
if (ngp_inclevel <= 0)
{ ngp_keyidx = NGP_TOKEN_EOF;
return(NGP_OK);
}
if (ngp_inclevel > NGP_MAX_INCLUDE) return(NGP_INC_NESTING);
if (NULL == ngp_fp[ngp_inclevel - 1]) return(NGP_NUL_PTR);
for (;;)
{ switch (r = ngp_read_line_buffered(ngp_fp[ngp_inclevel - 1]))
{ case NGP_EOF:
ngp_inclevel--;
if (ngp_fp[ngp_inclevel])
fclose(ngp_fp[ngp_inclevel]);
ngp_fp[ngp_inclevel] = NULL;
if (ngp_inclevel <= 0)
{ ngp_keyidx = NGP_TOKEN_EOF;
return(NGP_OK);
}
continue;
case NGP_OK:
if (ngp_curline.flags & NGP_LINE_REREAD) return(r);
break;
default:
return(r);
}
switch (ngp_curline.line[0])
{ case 0: if (0 == ignore_blank_lines) break;
case '#': continue;
}
r = ngp_extract_tokens(&ngp_curline);
if (NGP_OK != r) return(r);
if (NULL == ngp_curline.name) continue;
for (k = 0; k < strlen(ngp_curline.name); k++)
{ if ((ngp_curline.name[k] >= 'a') && (ngp_curline.name[k] <= 'z'))
ngp_curline.name[k] += 'A' - 'a';
if (k == 7) break;
}
for (k=0;; k++)
{ if (NGP_TOKEN_UNKNOWN == ngp_tkdef[k].code) break;
if (0 == strcmp(ngp_curline.name, ngp_tkdef[k].name)) break;
}
ngp_keyidx = ngp_tkdef[k].code;
if (NGP_TOKEN_INCLUDE == ngp_keyidx)
{ if (NGP_OK != (r = ngp_include_file(ngp_curline.value))) return(r);
continue;
}
ngp_linkey.type = NGP_TTYPE_UNKNOWN;
if (NULL != ngp_curline.value)
{ if (NGP_TTYPE_STRING == ngp_curline.type)
{ ngp_linkey.type = NGP_TTYPE_STRING;
ngp_linkey.value.s = ngp_curline.value;
}
if (NGP_TTYPE_UNKNOWN == ngp_linkey.type)
{ if ((!fits_strcasecmp("T", ngp_curline.value)) || (!fits_strcasecmp("F", ngp_curline.value)))
{ ngp_linkey.type = NGP_TTYPE_BOOL;
ngp_linkey.value.b = (fits_strcasecmp("T", ngp_curline.value) ? 0 : 1);
}
}
if (NGP_TTYPE_UNKNOWN == ngp_linkey.type)
{ if (2 == sscanf(ngp_curline.value, "(%lg,%lg)%n", &(ngp_linkey.value.c.re), &(ngp_linkey.value.c.im), &nc))
{ if ((' ' == ngp_curline.value[nc]) || ('\t' == ngp_curline.value[nc])
|| ('\n' == ngp_curline.value[nc]) || (0 == ngp_curline.value[nc]))
{ ngp_linkey.type = NGP_TTYPE_COMPLEX;
}
}
}
if (NGP_TTYPE_UNKNOWN == ngp_linkey.type)
{ if (strchr(ngp_curline.value, '.') && (1 == sscanf(ngp_curline.value, "%lg%n", &(ngp_linkey.value.d), &nc)))
{
if ('D' == ngp_curline.value[nc]) {
savec = nc;
ngp_curline.value[nc] = 'E';
sscanf(ngp_curline.value, "%lg%n", &(ngp_linkey.value.d), &nc);
if ((' ' == ngp_curline.value[nc]) || ('\t' == ngp_curline.value[nc])
|| ('\n' == ngp_curline.value[nc]) || (0 == ngp_curline.value[nc])) {
ngp_linkey.type = NGP_TTYPE_REAL;
} else {
ngp_curline.value[savec] = 'D';
}
} else {
if ((' ' == ngp_curline.value[nc]) || ('\t' == ngp_curline.value[nc])
|| ('\n' == ngp_curline.value[nc]) || (0 == ngp_curline.value[nc]))
{ ngp_linkey.type = NGP_TTYPE_REAL;
}
}
}
}
if (NGP_TTYPE_UNKNOWN == ngp_linkey.type)
{ if (1 == sscanf(ngp_curline.value, "%d%n", &(ngp_linkey.value.i), &nc))
{ if ((' ' == ngp_curline.value[nc]) || ('\t' == ngp_curline.value[nc])
|| ('\n' == ngp_curline.value[nc]) || (0 == ngp_curline.value[nc]))
{ ngp_linkey.type = NGP_TTYPE_INT;
}
}
}
if (NGP_TTYPE_UNKNOWN == ngp_linkey.type)
{ ngp_linkey.type = NGP_TTYPE_STRING;
ngp_linkey.value.s = ngp_curline.value;
}
}
else
{ if (NGP_TTYPE_RAW == ngp_curline.type) ngp_linkey.type = NGP_TTYPE_RAW;
else ngp_linkey.type = NGP_TTYPE_NULL;
}
if (NULL != ngp_curline.comment)
{ strncpy(ngp_linkey.comment, ngp_curline.comment, NGP_MAX_COMMENT);
ngp_linkey.comment[NGP_MAX_COMMENT - 1] = 0;
}
else
{ ngp_linkey.comment[0] = 0;
}
strncpy(ngp_linkey.name, ngp_curline.name, NGP_MAX_NAME);
ngp_linkey.name[NGP_MAX_NAME - 1] = 0;
if (strlen(ngp_linkey.name) > FLEN_KEYWORD)
{
return(NGP_BAD_ARG);
}
return(NGP_OK);
}
}
int ngp_keyword_is_write(NGP_TOKEN *ngp_tok)
{ int i, j, l, spc;
static char *nm[] = { "NAXIS", "TFORM", "TTYPE", NULL } ;
static char *nmni[] = { "SIMPLE", "XTENSION", "BITPIX", "NAXIS", "PCOUNT",
"GCOUNT", "TFIELDS", "THEAP", "EXTEND", "EXTVER",
NULL } ;
if (NULL == ngp_tok) return(NGP_NUL_PTR);
for (j = 0; ; j++)
{ if (NULL == nmni[j]) break;
if (0 == strcmp(nmni[j], ngp_tok->name)) return(NGP_BAD_ARG);
}
for (j = 0; ; j++)
{ if (NULL == nm[j]) return(NGP_OK);
l = strlen(nm[j]);
if ((l < 1) || (l > 5)) continue;
if (0 == strncmp(nm[j], ngp_tok->name, l)) break;
}
if ((ngp_tok->name[l] < '1') || (ngp_tok->name[l] > '9')) return(NGP_OK);
spc = 0;
for (i = l + 1; i < 8; i++)
{ if (spc) { if (' ' != ngp_tok->name[i]) return(NGP_OK); }
else
{ if ((ngp_tok->name[i] >= '0') && (ngp_tok->name[i] <= '9')) continue;
if (' ' == ngp_tok->name[i]) { spc = 1; continue; }
if (0 == ngp_tok->name[i]) break;
return(NGP_OK);
}
}
return(NGP_BAD_ARG);
}
int ngp_keyword_all_write(NGP_HDU *ngph, fitsfile *ffp, int mode)
{ int i, r, ib;
char buf[200];
long l;
if (NULL == ngph) return(NGP_NUL_PTR);
if (NULL == ffp) return(NGP_NUL_PTR);
r = NGP_OK;
for (i=0; i<ngph->tokcnt; i++)
{ r = ngp_keyword_is_write(&(ngph->tok[i]));
if ((NGP_REALLY_ALL & mode) || (NGP_OK == r))
{ switch (ngph->tok[i].type)
{ case NGP_TTYPE_BOOL:
ib = ngph->tok[i].value.b;
fits_write_key(ffp, TLOGICAL, ngph->tok[i].name, &ib, ngph->tok[i].comment, &r);
break;
case NGP_TTYPE_STRING:
fits_write_key_longstr(ffp, ngph->tok[i].name, ngph->tok[i].value.s, ngph->tok[i].comment, &r);
break;
case NGP_TTYPE_INT:
l = ngph->tok[i].value.i;
fits_write_key(ffp, TLONG, ngph->tok[i].name, &l, ngph->tok[i].comment, &r);
break;
case NGP_TTYPE_REAL:
fits_write_key(ffp, TDOUBLE, ngph->tok[i].name, &(ngph->tok[i].value.d), ngph->tok[i].comment, &r);
break;
case NGP_TTYPE_COMPLEX:
fits_write_key(ffp, TDBLCOMPLEX, ngph->tok[i].name, &(ngph->tok[i].value.c), ngph->tok[i].comment, &r);
break;
case NGP_TTYPE_NULL:
fits_write_key_null(ffp, ngph->tok[i].name, ngph->tok[i].comment, &r);
break;
case NGP_TTYPE_RAW:
if (0 == strcmp("HISTORY", ngph->tok[i].name))
{ fits_write_history(ffp, ngph->tok[i].comment, &r);
break;
}
if (0 == strcmp("COMMENT", ngph->tok[i].name))
{ fits_write_comment(ffp, ngph->tok[i].comment, &r);
break;
}
snprintf(buf,200, "%-8.8s%s", ngph->tok[i].name, ngph->tok[i].comment);
fits_write_record(ffp, buf, &r);
break;
}
}
else if (NGP_BAD_ARG == r)
{ r = NGP_OK;
if (ngph->tok[i].comment && *ngph->tok[i].comment)
{ fits_modify_comment(ffp, ngph->tok[i].name, ngph->tok[i].comment, &r);
}
}
else
{ r = NGP_OK;
}
if (r) return(r);
}
fits_set_hdustruc(ffp, &r);
return(r);
}
int ngp_hdu_init(NGP_HDU *ngph)
{ if (NULL == ngph) return(NGP_NUL_PTR);
ngph->tok = NULL;
ngph->tokcnt = 0;
return(NGP_OK);
}
int ngp_hdu_clear(NGP_HDU *ngph)
{ int i;
if (NULL == ngph) return(NGP_NUL_PTR);
for (i=0; i<ngph->tokcnt; i++)
{ if (NGP_TTYPE_STRING == ngph->tok[i].type)
if (NULL != ngph->tok[i].value.s)
{ ngp_free(ngph->tok[i].value.s);
ngph->tok[i].value.s = NULL;
}
}
if (NULL != ngph->tok) ngp_free(ngph->tok);
ngph->tok = NULL;
ngph->tokcnt = 0;
return(NGP_OK);
}
int ngp_hdu_insert_token(NGP_HDU *ngph, NGP_TOKEN *newtok)
{ NGP_TOKEN *tkp;
if (NULL == ngph) return(NGP_NUL_PTR);
if (NULL == newtok) return(NGP_NUL_PTR);
if (0 == ngph->tokcnt)
tkp = (NGP_TOKEN *)ngp_alloc((ngph->tokcnt + 1) * sizeof(NGP_TOKEN));
else
tkp = (NGP_TOKEN *)ngp_realloc(ngph->tok, (ngph->tokcnt + 1) * sizeof(NGP_TOKEN));
if (NULL == tkp) return(NGP_NO_MEMORY);
ngph->tok = tkp;
ngph->tok[ngph->tokcnt] = *newtok;
if (NGP_TTYPE_STRING == newtok->type)
{ if (NULL != newtok->value.s)
{ ngph->tok[ngph->tokcnt].value.s = (char *)ngp_alloc(1 + strlen(newtok->value.s));
if (NULL == ngph->tok[ngph->tokcnt].value.s) return(NGP_NO_MEMORY);
strcpy(ngph->tok[ngph->tokcnt].value.s, newtok->value.s);
}
}
ngph->tokcnt++;
return(NGP_OK);
}
int ngp_append_columns(fitsfile *ff, NGP_HDU *ngph, int aftercol)
{ int r, i, j, exitflg, ngph_i;
char *my_tform, *my_ttype;
char ngph_ctmp;
if (NULL == ff) return(NGP_NUL_PTR);
if (NULL == ngph) return(NGP_NUL_PTR);
if (0 == ngph->tokcnt) return(NGP_OK);
r = NGP_OK;
exitflg = 0;
for (j=aftercol; j<NGP_MAX_ARRAY_DIM; j++)
{
my_tform = NULL;
my_ttype = "";
for (i=0; ; i++)
{ if (1 == sscanf(ngph->tok[i].name, "TFORM%d%c", &ngph_i, &ngph_ctmp))
{ if ((NGP_TTYPE_STRING == ngph->tok[i].type) && (ngph_i == (j + 1)))
{ my_tform = ngph->tok[i].value.s;
}
}
else if (1 == sscanf(ngph->tok[i].name, "TTYPE%d%c", &ngph_i, &ngph_ctmp))
{ if ((NGP_TTYPE_STRING == ngph->tok[i].type) && (ngph_i == (j + 1)))
{ my_ttype = ngph->tok[i].value.s;
}
}
if ((NULL != my_tform) && (my_ttype[0])) break;
if (i < (ngph->tokcnt - 1)) continue;
exitflg = 1;
break;
}
if ((NGP_OK == r) && (NULL != my_tform))
fits_insert_col(ff, j + 1, my_ttype, my_tform, &r);
if ((NGP_OK != r) || exitflg) break;
}
return(r);
}
int ngp_read_xtension(fitsfile *ff, int parent_hn, int simple_mode)
{ int r, exflg, l, my_hn, tmp0, incrementor_index, i, j;
int ngph_dim, ngph_bitpix, ngph_node_type, my_version;
char incrementor_name[NGP_MAX_STRING], ngph_ctmp;
char *ngph_extname = 0;
long ngph_size[NGP_MAX_ARRAY_DIM];
NGP_HDU ngph;
long lv;
incrementor_name[0] = 0;
incrementor_index = 0;
if (NGP_OK != (r = ngp_hdu_init(&ngph))) return(r);
if (NGP_OK != (r = ngp_read_line(0))) return(r);
switch (NGP_XTENSION_SIMPLE & simple_mode)
{
case 0: if (NGP_TOKEN_XTENSION != ngp_keyidx) return(NGP_TOKEN_NOT_EXPECT);
break;
default: if (NGP_TOKEN_SIMPLE != ngp_keyidx) return(NGP_TOKEN_NOT_EXPECT);
break;
}
if (NGP_OK != (r = ngp_hdu_insert_token(&ngph, &ngp_linkey))) return(r);
for (;;)
{ if (NGP_OK != (r = ngp_read_line(0))) return(r);
exflg = 0;
switch (ngp_keyidx)
{
case NGP_TOKEN_SIMPLE:
r = NGP_TOKEN_NOT_EXPECT;
break;
case NGP_TOKEN_END:
case NGP_TOKEN_XTENSION:
case NGP_TOKEN_GROUP:
r = ngp_unread_line();
case NGP_TOKEN_EOF:
exflg = 1;
break;
default: l = strlen(ngp_linkey.name);
if ((l >= 2) && (l <= 6))
{ if ('#' == ngp_linkey.name[l - 1])
{ if (0 == incrementor_name[0])
{ memcpy(incrementor_name, ngp_linkey.name, l - 1);
incrementor_name[l - 1] = 0;
}
if (((l - 1) == (int)strlen(incrementor_name)) && (0 == memcmp(incrementor_name, ngp_linkey.name, l - 1)))
{ incrementor_index++;
}
snprintf(ngp_linkey.name + l - 1, NGP_MAX_NAME-l+1,"%d", incrementor_index);
}
}
r = ngp_hdu_insert_token(&ngph, &ngp_linkey);
break;
}
if ((NGP_OK != r) || exflg) break;
}
if (NGP_OK == r)
{
ngph_node_type = NGP_NODE_INVALID;
ngph_bitpix = 0;
ngph_extname = NULL;
for (i=0; i<NGP_MAX_ARRAY_DIM; i++) ngph_size[i] = 0;
ngph_dim = 0;
for (i=0; i<ngph.tokcnt; i++)
{ if (!strcmp("XTENSION", ngph.tok[i].name))
{ if (NGP_TTYPE_STRING == ngph.tok[i].type)
{ if (!fits_strncasecmp("BINTABLE", ngph.tok[i].value.s,8)) ngph_node_type = NGP_NODE_BTABLE;
if (!fits_strncasecmp("TABLE", ngph.tok[i].value.s,5)) ngph_node_type = NGP_NODE_ATABLE;
if (!fits_strncasecmp("IMAGE", ngph.tok[i].value.s,5)) ngph_node_type = NGP_NODE_IMAGE;
}
}
else if (!strcmp("SIMPLE", ngph.tok[i].name))
{ if (NGP_TTYPE_BOOL == ngph.tok[i].type)
{ if (ngph.tok[i].value.b) ngph_node_type = NGP_NODE_IMAGE;
}
}
else if (!strcmp("BITPIX", ngph.tok[i].name))
{ if (NGP_TTYPE_INT == ngph.tok[i].type) ngph_bitpix = ngph.tok[i].value.i;
}
else if (!strcmp("NAXIS", ngph.tok[i].name))
{ if (NGP_TTYPE_INT == ngph.tok[i].type) ngph_dim = ngph.tok[i].value.i;
}
else if (!strcmp("EXTNAME", ngph.tok[i].name))
{ if (NGP_TTYPE_STRING == ngph.tok[i].type) ngph_extname = ngph.tok[i].value.s;
}
else if (1 == sscanf(ngph.tok[i].name, "NAXIS%d%c", &j, &ngph_ctmp))
{ if (NGP_TTYPE_INT == ngph.tok[i].type)
if ((j>=1) && (j <= NGP_MAX_ARRAY_DIM))
{ ngph_size[j - 1] = ngph.tok[i].value.i;
}
}
}
switch (ngph_node_type)
{ case NGP_NODE_IMAGE:
if (NGP_XTENSION_FIRST == ((NGP_XTENSION_FIRST | NGP_XTENSION_SIMPLE) & simple_mode))
{
fits_create_img(ff, 16, 0, NULL, &r);
}
fits_create_img(ff, ngph_bitpix, ngph_dim, ngph_size, &r);
if (NGP_OK == r) r = ngp_keyword_all_write(&ngph, ff, NGP_NON_SYSTEM_ONLY);
break;
case NGP_NODE_ATABLE:
case NGP_NODE_BTABLE:
fits_create_tbl(ff, ((NGP_NODE_ATABLE == ngph_node_type)
? ASCII_TBL : BINARY_TBL),
0, 0, NULL, NULL, NULL, NULL, &r);
if (NGP_OK != r) break;
r = ngp_append_columns(ff, &ngph, 0);
if (NGP_OK != r) break;
r = ngp_keyword_all_write(&ngph, ff, NGP_NON_SYSTEM_ONLY);
if (NGP_OK != r) break;
if (ngph_size[1] > 0) fits_insert_rows(ff, 0, ngph_size[1], &r);
break;
default: r = NGP_BAD_ARG;
break;
}
}
if ((NGP_OK == r) && (NULL != ngph_extname))
{ r = ngp_get_extver(ngph_extname, &my_version);
lv = my_version;
fits_write_key(ff, TLONG, "EXTVER", &lv, "auto assigned by template parser", &r);
}
if (NGP_OK == r)
{ if (parent_hn > 0)
{ fits_get_hdu_num(ff, &my_hn);
fits_movabs_hdu(ff, parent_hn, &tmp0, &r);
fits_add_group_member(ff, NULL, my_hn, &r);
fits_movabs_hdu(ff, my_hn, &tmp0, &r);
if (NGP_OK != r) return(r);
}
}
if (NGP_OK != r)
{ tmp0 = 0;
fits_delete_hdu(ff, NULL, &tmp0);
}
ngp_hdu_clear(&ngph);
return(r);
}
int ngp_read_group(fitsfile *ff, char *grpname, int parent_hn)
{ int r, exitflg, l, my_hn, tmp0, incrementor_index;
char grnm[NGP_MAX_STRING];
char incrementor_name[NGP_MAX_STRING];
NGP_HDU ngph;
incrementor_name[0] = 0;
incrementor_index = 6;
ngp_grplevel++;
if (NGP_OK != (r = ngp_hdu_init(&ngph))) return(r);
r = NGP_OK;
if (NGP_OK != (r = fits_create_group(ff, grpname, GT_ID_ALL_URI, &r))) return(r);
fits_get_hdu_num(ff, &my_hn);
if (parent_hn > 0)
{ fits_movabs_hdu(ff, parent_hn, &tmp0, &r);
fits_add_group_member(ff, NULL, my_hn, &r);
fits_movabs_hdu(ff, my_hn, &tmp0, &r);
if (NGP_OK != r) return(r);
}
for (exitflg = 0; 0 == exitflg;)
{ if (NGP_OK != (r = ngp_read_line(0))) break;
switch (ngp_keyidx)
{
case NGP_TOKEN_SIMPLE:
case NGP_TOKEN_EOF:
r = NGP_TOKEN_NOT_EXPECT;
break;
case NGP_TOKEN_END:
ngp_grplevel--;
exitflg = 1;
break;
case NGP_TOKEN_GROUP:
if (NGP_TTYPE_STRING == ngp_linkey.type)
{ strncpy(grnm, ngp_linkey.value.s, NGP_MAX_STRING);
}
else
{ snprintf(grnm, NGP_MAX_STRING,"DEFAULT_GROUP_%d", master_grp_idx++);
}
grnm[NGP_MAX_STRING - 1] = 0;
r = ngp_read_group(ff, grnm, my_hn);
break;
case NGP_TOKEN_XTENSION:
r = ngp_unread_line();
if (NGP_OK != r) break;
r = ngp_read_xtension(ff, my_hn, 0);
break;
default: l = strlen(ngp_linkey.name);
if ((l >= 2) && (l <= 6))
{ if ('#' == ngp_linkey.name[l - 1])
{ if (0 == incrementor_name[0])
{ memcpy(incrementor_name, ngp_linkey.name, l - 1);
incrementor_name[l - 1] = 0;
}
if (((l - 1) == (int)strlen(incrementor_name)) && (0 == memcmp(incrementor_name, ngp_linkey.name, l - 1)))
{ incrementor_index++;
}
snprintf(ngp_linkey.name + l - 1, NGP_MAX_NAME-l+1,"%d", incrementor_index);
}
}
r = ngp_hdu_insert_token(&ngph, &ngp_linkey);
break;
}
if (NGP_OK != r) break;
}
fits_movabs_hdu(ff, my_hn, &tmp0, &r);
if (NGP_OK == r)
r = ngp_append_columns(ff, &ngph, 6);
if (NGP_OK == r)
r = ngp_keyword_all_write(&ngph, ff, NGP_NON_SYSTEM_ONLY);
if (NGP_OK != r)
{ tmp0 = 0;
fits_remove_group(ff, OPT_RM_GPT, &tmp0);
}
ngp_hdu_clear(&ngph);
return(r);
}
int fits_execute_template(fitsfile *ff, char *ngp_template, int *status)
{ int r, exit_flg, first_extension, i, my_hn, tmp0, keys_exist, more_keys, used_ver;
char grnm[NGP_MAX_STRING], used_name[NGP_MAX_STRING];
long luv;
if (NULL == status) return(NGP_NUL_PTR);
if (NGP_OK != *status) return(*status);
FFLOCK;
if ((NULL == ff) || (NULL == ngp_template))
{ *status = NGP_NUL_PTR;
FFUNLOCK;
return(*status);
}
ngp_inclevel = 0;
ngp_grplevel = 0;
master_grp_idx = 1;
exit_flg = 0;
ngp_master_dir[0] = 0;
first_extension = 1;
if (NGP_OK != (r = ngp_delete_extver_tab()))
{ *status = r;
FFUNLOCK;
return(r);
}
fits_get_hdu_num(ff, &my_hn);
if (my_hn <= 1)
{ fits_movabs_hdu(ff, 1, &tmp0, status);
fits_get_hdrspace(ff, &keys_exist, &more_keys, status);
fits_movabs_hdu(ff, my_hn, &tmp0, status);
if (NGP_OK != *status)
{
FFUNLOCK;
return(*status);
}
if (keys_exist > 0) first_extension = 0;
}
else
{ first_extension = 0;
for (i = 2; i<= my_hn; i++)
{ *status = NGP_OK;
fits_movabs_hdu(ff, 1, &tmp0, status);
if (NGP_OK != *status) break;
fits_read_key(ff, TSTRING, "EXTNAME", used_name, NULL, status);
if (NGP_OK != *status) continue;
fits_read_key(ff, TLONG, "EXTVER", &luv, NULL, status);
used_ver = luv;
if (VALUE_UNDEFINED == *status)
{ used_ver = 1;
*status = NGP_OK;
}
if (NGP_OK == *status) *status = ngp_set_extver(used_name, used_ver);
}
fits_movabs_hdu(ff, my_hn, &tmp0, status);
}
if (NGP_OK != *status) {
FFUNLOCK;
return(*status);
}
if (NGP_OK != (*status = ngp_include_file(ngp_template))) {
FFUNLOCK;
return(*status);
}
for (i = strlen(ngp_template) - 1; i >= 0; i--)
{
#ifdef MSDOS
if ('\\' == ngp_template[i]) break;
#else
if ('/' == ngp_template[i]) break;
#endif
}
i++;
if (i > (NGP_MAX_FNAME - 1)) i = NGP_MAX_FNAME - 1;
if (i > 0)
{ memcpy(ngp_master_dir, ngp_template, i);
ngp_master_dir[i] = 0;
}
for (;;)
{ if (NGP_OK != (r = ngp_read_line(1))) break;
switch (ngp_keyidx)
{
case NGP_TOKEN_SIMPLE:
if (0 == first_extension)
{ r = NGP_TOKEN_NOT_EXPECT;
break;
}
if (NGP_OK != (r = ngp_unread_line())) break;
r = ngp_read_xtension(ff, 0, NGP_XTENSION_SIMPLE | NGP_XTENSION_FIRST);
first_extension = 0;
break;
case NGP_TOKEN_XTENSION:
if (NGP_OK != (r = ngp_unread_line())) break;
r = ngp_read_xtension(ff, 0, (first_extension ? NGP_XTENSION_FIRST : 0));
first_extension = 0;
break;
case NGP_TOKEN_GROUP:
if (NGP_TTYPE_STRING == ngp_linkey.type)
{ strncpy(grnm, ngp_linkey.value.s, NGP_MAX_STRING); }
else
{ snprintf(grnm,NGP_MAX_STRING, "DEFAULT_GROUP_%d", master_grp_idx++); }
grnm[NGP_MAX_STRING - 1] = 0;
r = ngp_read_group(ff, grnm, 0);
first_extension = 0;
break;
case NGP_TOKEN_EOF:
exit_flg = 1;
break;
default: r = NGP_TOKEN_NOT_EXPECT;
break;
}
if (exit_flg || (NGP_OK != r)) break;
}
ngp_free_line();
ngp_free_prevline();
ngp_delete_extver_tab();
*status = r;
FFUNLOCK;
return(r);
}