/* @(#)tz1.c 17.1.1.1 (ES0-DMD) 01/25/02 17:36:45 */ /*=========================================================================== Copyright (C) 1995 European Southern Observatory (ESO) 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., 675 Massachusetss Ave, Cambridge, MA 02139, USA. Corresponding concerning ESO-MIDAS should be addressed as follows: Internet e-mail: midas@eso.org Postal address: European Southern Observatory Data Management Division Karl-Schwarzschild-Strasse 2 D 85748 Garching bei Muenchen GERMANY ===========================================================================*/ /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .TYPE Module .NAME TZ1.C .LANGUAGE C .AUTHOR J.D.Ponz IPG-ESO Garching .CATEGORY table interface (Design 2.0) low level routines. .COMMENTS This module contains the lower level routines handling tables. The module includes the functions: - Filename checking. - Low level error handling. - Format, label and type checking. - Logical to physical column correspondences. .VERSION 1.0 25-Mar-1987 Implementation JDP .VERSION 1.1 20-Oct-1987 Modify calling sequence .VERSION 1.2 05-Jun-1989 Add integer data type .VERSION 3.0 01-Jul-1990 Extracted from tz2 ------------------------------------------------------------*/ #include /* General MIDAS Symbols */ #include /* Table System parameters */ #include /* Symbols used for Tables */ #include /* List of Table Errors */ #include /* Character classification */ #include /* Classical Macros */ char *osmmget(); #ifdef __STDC__ static char *atype(int ttype) #else static char *atype(ttype) /*+++++++++++ .PURPOSE Convert table numeric datatype into understandable ones .RETURNS The data-type --------------*/ int ttype; /* IN: The numeric datatype */ #endif { static char fmt[20]; char *p; switch(TBL_ElementType(ttype)) { case TBL_D_A1: p = "C*%d"; break; case TBL_D_I1: p = "I*1(%d)"; break; case TBL_D_I2: p = "I*2(%d)"; break; case TBL_D_I4: p = "I*4(%d)"; break; case TBL_D_A2: p = "L*2(%d)"; break; case TBL_D_A4: p = "L*4(%d)"; break; case TBL_D_R4: p = "R*4(%d)"; break; case TBL_D_R8: p = "R*8(%d)"; break; } sprintf(fmt, p, TBL_Items(ttype)); return(fmt); } /*==========================================================================*/ int TBL_offset(tp, row, col) /*+++++++++++ .PURPOSE Compute position in table from row + col .RETURNS Offset in bytes --------------*/ TABLE *tp; /* IN: Table concerned */ int row; /* IN: Row */ int col; /* IN: Column */ { int o; int i, j; i = row-1; j = col-1; if (col > 0) { if (tp->swise == F_RECORD ) o = tp->offset[j] + i * tp->reclen; else o = tp->offset[j] * tp->arows + i * tp->bytes[j]; } else { /* Selection Column */ if (tp->swise == F_RECORD) o = i * tp->reclen; else o = i * 4; } return (o); } /*==========================================================================*/ char *TBL_Dlab(col) /*++++++++ .PURPOSE Generate the column label descriptor .RETURNS Address of descriptor's name -----------*/ int col; /* IN: Column number */ { static char buf[sizeof(TBL_Dlabel)+3] = TBL_Dlabel; int i, n; n = col; i = sizeof(buf); buf[--i] = '\0'; buf[--i] = '0' + n%10; n /= 10; buf[--i] = '0' + n%10; n /= 10; buf[--i] = '0' + n; return(buf); } /*==========================================================================*/ char *TBL_Cfmt(form, ttype) /*++++++++++++++++++++ .PURPOSE Convert format from F77 into C .RETURNS Translated format / "" if error. The returned string contains: %...A for C-edit H for convert to hours (/15.) Z for zero-fill + for sing edition Sx.y for Sexagesimal (e.g. S12.4:), last byte tells the sep. char. Dx.y for Date edition ---------------------*/ char *form; /* IN: F77 Format */ int ttype; /* IN: Table-specific data type */ { static char chReturnArray[16] = "%"; int j; int idot; int dtype; int dec; /* what's that?*/ char *pchReturn; /* pointer to char, will be returned */ char add_sign; char zero_fill; dtype = TBL_ElementType(ttype); pchReturn = &chReturnArray[2]; /* why are chReturnArray[0] and [1] not used??? */ *pchReturn = '%'; /* pchReturn[0] = chReturnArray[2] = '%' */ idot = 0; /*step through form and search the '.', if existent*/ for (j=1; (j < sizeof(chReturnArray)-6) && isgraph(form[j]); j++) { if (form[j] == '.') idot = j+1; /* why +1? why not only j? */ pchReturn[j] = form[j]; /* fill pchReturn - why not chReturnArray? */ } add_sign = islower(*form); zero_fill = 0; /*j equals now the length of form e.g. for Tww.dd six, for Iww three*/ switch (form[0]) /* letter in form[0] gives format */ { case 'A': /* characters */ pchReturn[j] = 's'; break; case 'F': case 'f': if (dtype & 020) pchReturn[j] = 'f'; else { /* */ if (idot != 0) j = idot-1; pchReturn[j] = (dtype & 010 ? 'd' : 'u'); } break; /* case 'E': case 'G': case 'D': case 'e':*/ case 'D': case 'e': case 'E': if (idot != 0) /* only true if '.' found */ { /* this is important! 1/99 */ dec = atoi(form+idot); /**/ if (dec > 0) dec--; sprintf(pchReturn+idot, "%de", dec); } else /* if no '.' found, use format e */ /* problems may occur here: */ /* for negative values, exponent missing*/ /* therefore check for . */ /* when E,D,e column are created */ pchReturn[j] = 'e'; break; case 'G': /* G didn't work before 10/98*/ pchReturn[j] = 'G'; break; case 'I': case 'i': /* integer */ if (dtype & 020) pchReturn[j++] = '.', pchReturn[j++] = '0', pchReturn[j] = 'f'; else pchReturn[j] = (dtype & 010 ? 'd' : 'u'); break; case 'R': case 'r': /* Right ascension, e.g. 12 34 56*/ j++; *--pchReturn = 'H'; /* NO BREAK */ /* Fall through */ case 'S': case 's': chReturnArray[2] = 'S'; /* Sexagesimal */ pchReturn[j] = ' '; /* Separator between mn / sec */ break; case 'T': chReturnArray[2] = 'T'; /* Sexagesimal */ pchReturn[j] = ' '; /* Numeric... */ break; case 't': chReturnArray[2] = 'T'; /* Sexagesimal */ pchReturn[j] = 'A'; /* Numeric... */ add_sign = 0; break; case 'Z': case 'z': /* Zero filled */ pchReturn[j] = (dtype & 020 ? 'f' : (dtype & 010 ? 'd': 'u')); zero_fill = 1; break; case 'O': case 'o': /* Octal (format O didn't work before PNOct98)*/ pchReturn[j] = 'o'; break; case 'X': case 'x': /* Hexa */ add_sign = 0; /* NO BREAK */ /* Fall through */ default: pchReturn[j] = form[0]; /* when will default be used at all? */ break; } pchReturn[++j] = '\0'; if (zero_fill != 0) pchReturn[++j] = 'Z'; /* why something written in pchReturn behind \0???*/ if (add_sign != 0) pchReturn[++j] = '+'; /* why something written in pchReturn behind \0???*/ pchReturn[++j] = '\0'; /* why that again??? */ return(pchReturn); } int TBL_FMTCHK(form, ttype, oform) /*+++++++++ .PURPOSE Check F77 format vs datatype .RETURNS Status. .REMARKS Error is logged if something wrong. ----------*/ char *form /* IN: format F77 */; int ttype /* IN: Table coded type */; char *oform /* OUT: output format and length */; { int status, len, i, dec; char *table; /* Default Length according to datatype */ static char d_i1[] = "F5.0\0f5.0\0I4\0i4\0O3\0o3\0X2\0x2\0Z4\0z4\0"; static char d_i2[] = "F7.0\0f7.0\0I6\0i6\0O6\0o6\0X4\0x4\0Z6\0z6\0"; static char d_a2[] = "F6.0\0f6.0\0I5\0i5\0O6\0o6\0X4\0x4\0Z6\0z6\0"; static char d_i4[] = "F12.0\0f12.0\0I11\0i11\0O11\0o11\0X8\0x8\0Z11\0z11\0\ t20.6\0T19.6\0"; static char d_a4[] = "F11.0\0f11.0\0I10\0i10\0O11\0o11\0X8\0x8\0Z10\0z10\0"; static char d_r4[] = "E12.6\0e12.6\0F12.6\0f12.6\0G12.6\0I12\0i12\0\ R10.5\0r11.5\0S9.4\0s9.4\0Z12.6\0z12.6\0"; static char d_r8[] = "E12.6\0e12.6\0F12.6\0f12.6\0G12.6\0D12.6\0I12\0i12\0\ R12.7\0r13.7\0S12.6\0s12.6\0t20.6\0T19.6\0Z12.6\0z12.6\0"; status = ERR_NORMAL; dec = 0; for (i=0; form[i]; i++){ oform[i] = form[i]; if (oform[i] == '.') dec = i; } strcpy(oform,form); len = atoi(oform+1); if (dec) dec = atoi(oform+1+dec); /* Check type, no default allowed */ switch (TBL_ElementType(ttype)) { case TBL_D_A1: /* String... */ if (form[0] != 'A' && form[0] != 'a' ) status = ERR_TBLFMT; if (len <= 0) sprintf(oform+1, "%d", TBL_Items(ttype)); break; case TBL_D_I1: table = d_i1; goto check_table; case TBL_D_I2: table = d_i2; goto check_table; case TBL_D_I4: table = d_i4; goto check_table; case TBL_D_A2: table = d_a2; goto check_table; case TBL_D_A4: table = d_a4; goto check_table; case TBL_D_R4: table = d_r4; goto check_table; case TBL_D_R8: table = d_r8; goto check_table; check_table: while (*table) { if (*table == *oform) break; table += 1 + strlen(table); } if (*table) { if (len == 0) strcpy (oform, table); } else status = ERR_TBLFMT; } if (len && (len < (dec+1))) status = ERR_TBLFMT; for (i = strlen(oform); i < 6; i++) oform[i] = ' '; #if 0 /* Add length */ len = atoi(oform+1); sprintf(&oform[6],"%3d", len); #else oform[6] = oform[7] = oform[8] = '='; #endif if (status) TBL_errf(status, "datatype '%s' incompatible with format '%s'", atype(ttype), form); return (status); } int TBL_UNICHK(unit, ounit) /*+++++++++ .PURPOSE Check Units (just remove quotes of existing) .RETURNS Status ----------*/ char *unit /* IN: Unit */; char *ounit /* OUT: output unit */; { int status, i, j; status = ERR_NORMAL; /* remove double quotes*/ /* MP , dec 1989 */ j = (*unit == '"' ? 1 : 0); for (i=0; (i 0) ) { if (ounit[--i] != '"') i++; } /* Fill with blanks */ while (i < TBL_UNILEN) ounit[i++] = ' '; ounit[i] = '\0'; return (status); } /*==========================================================================*/ int TBL_LABCHK(label, outlab) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Check label: must start with alphabetic / _ . Truncted to LABLEN. The starting : is removed. .RETURNS status ------------------------------------------------------------------*/ char *label /* IN: input label */; char *outlab /* OUT: output label (exactly LABLEN) */; { char *p, c; int status, i, j; status = ERR_NORMAL; p = label; if (*p == ':') p++; for (i=j=0; (j < TBL_LABLEN) && isgraph(p[i]); i++) { c = p[i]; if (isalpha(c) || (c == '_')) ; /* OK */ else if (isdigit(c)) { if (i == 0) status = ERR_TBLABL, outlab[j++] = '_'; } else c = '_', status = ERR_TBLABL; outlab[j++] = c; } while (j < TBL_LABLEN) outlab[j++] = ' '; outlab[j] = '\0'; if (status) TBL_errf(-1, "column name :%s converted to :%s", p, outlab); return (ERR_NORMAL); } int TBL_TYPCHK(dtype, alen, icode) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Check external data type and generates TABLE code. Implements TBL_TYPCHK .RETURNS Status. ------------------------------------------------------------------*/ int dtype /* IN: MIDAS data type */; int alen /* IN: number of items */; int *icode /* OUT: Table-specific data type*/; { int status; status = ((alen > 0) && (alen <= TBL_D_MASK) ? ERR_NORMAL : ERR_TBLFMT); if (status) return (TBL_errf(status, "bad size (%d) for table column", alen)); switch (dtype) { /* branch on data type */ case D_I1_FORMAT: *icode = TBL_D_I1 << TBL_D_BITS; break; case D_I2_FORMAT: *icode = TBL_D_I2 << TBL_D_BITS; break; case D_I4_FORMAT: *icode = TBL_D_I4 << TBL_D_BITS; break; case D_R4_FORMAT: *icode = TBL_D_R4 << TBL_D_BITS; break; case D_R8_FORMAT: *icode = TBL_D_R8 << TBL_D_BITS; break; case D_C_FORMAT: case D_X_FORMAT: case D_L1_FORMAT: *icode = TBL_D_A1 << TBL_D_BITS; break; case D_UI2_FORMAT: case D_L2_FORMAT: *icode = TBL_D_A2 << TBL_D_BITS; break; case D_L4_FORMAT: case D_P_FORMAT: *icode = TBL_D_A4 << TBL_D_BITS; break; default : status = ERR_TBLFMT; TBL_errf(status, "bad numeric datatype (%d)", dtype); *icode = 0; break; } *icode |= alen; return (status); }