/* @(#)tcd.c 17.1.1.1 (ES0-DMD) 01/25/02 17:36:44 */ /*=========================================================================== 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 ===========================================================================*/ /* @(#)tcd.c 8.1.1.2 (ESO-IPG) 11/15/94 16:55:36 */ /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .TYPE Module .NAME tcd.c .LANGUAGE C .AUTHOR IPG-ESO Garching .CATEGORY table interface (Design version 2.0) .VERSION 1.0 25-Mar-1987 Implementation J.D. Ponz .VERSION 1.1 25-Aug-1987 Include TCSPUT .VERSION 1.2 20-Oct-1987 Calling sequence .VERSION 1.3 23-Nov-1987 New SC calling sequence .VERSION 1.4 11-Apr-1988 New SC calling sequence .VERSION 1.5 11-Jan-1989 Include transposed file format .VERSION 1.6 11-Jun-1989 New routines TCSCNT, TCDGET .VERSION 1.7 14-Oct-1989 ibase = 1 in TCFSET ( not yet implemented) .VERSION 1.8 02-Jan-1990 TCLSER modified (null terminator) .VERSION 3.0 01-Jul-1990 New Version with Arrays / Elementary IO New entry points TCBGET / TCOSET / TCOGET .VERSION 3.1 28-Oct-1990 Added TCFED (Edition bin -> char) and TCFDV (Conversion char->bin) .VERSION 3.2 07-Dec-1990 Added TCVERS (Version) .VERSION 3.3 18-Dec-1990 Selected rows are stored in TBLCONTR descriptor. Added TCSSET routine to write the descriptor. .VERSION 3.4 15-Mar-1991: Corrected TCSINF (FO) .VERSION 3.5 29-Apr-1991: Corrected TCSINI, must work with very large tables .COMMENTS \begin{TeX} This module contains the routines to handle standard table descriptors: \begin{itemize} \item General table information giving the current number of rows and columns, the number of the sorted column (0 by default), the column acting as refence to access rows by value (0 by default) and the physical dimension of the table. The routine TCIGET gives this information. \item Table data types. The structure of one column may be retrieved with TCBGET. \item Format to define the editing format. The following operations are implemented: Get (TCFGET), put (TCFPUT). \item Reference column. Defines the column used as reference for accessing the table elements by value. Possible operations are define reference column (TCKPUT) and get reference column (TCKGET). \item Label. Defines the name associated to the column. The label is used as a variable name associated to the column in programs and procedures. Possible operations are get label (TCLGET), put label (TCLPUT) and search column with a given label (TCLSER). The label is initialized by TCCINI. Case sensitivity for label names may be turned on via {\em TCOSET ("label\_case", 1)} or off via {\em TCOSET ("label\_case", 0)}. \item Various {\em options} may be retrieved (TCOGET) or setup (TCOSET). TCOERR writes an error. \item Unit. Defines the units associated to a column. Possible operations are get unit (TCUGET) and put unit (TCUPUT). Units are initialized by TCCINI. \item Selection flag. Defines the current subset selected in the table. The functions included are: get selection (TCSGET), put selection on/off (TCSPUT), count selected items (TCSCNT) and initialize selection (TCSINI). \end{itemize} Main arguments used by the routines are: \begin{description} \item[column] sequential column number. It is an integer number provided by the system when a new column is created or defined by the user. \item[dtype] column data type. The system file midas\_def.h in MID\_INCLUDE provides the symbols D\_xx\_FORMAT where 'xx' is 'I4' for integers, 'R4' for float, 'R8' for double precision and 'C' for characters \item[form] column display format. It is a character string defining a FORTRAN compatible format. \item[label] column label. Character string (up to 16 characters) defined by the user when the column is created. Valid characters are letters, digits and the underscore '\_'. In the current version labels are NOT case independent. \item[row] sequential row number. It is an integer number defining the row number or the symbols FIRST, LAST, NEXT and PREVIOUS defined in the system file 'midas\_def.h' in the directory 'MID\_INCLUDE'. The terms row and record are equivalent in this context. \item[tid] table identifier. It is an integer number provided by the system when the table is created or opened. \item[unit] column unit. It is a character string (up to 16 characters) to define the units of the column. \end{description} \end{TeX} ------------------------------------------------------------*/ #include /* General MIDAS Symbols */ #include /* Table System parameters */ #include /* Symbols used for Tables */ #include /* Classical macros */ #include /* Character classification */ static int one = 1; static int zero = 0; static int dunit; /* Not yet used */ static int dnull = 0; static unsigned char bit_mask[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}; /* Mnemonics for some operations */ #define OnError_Continue { int flags[3]; \ SCECNT("GET", flags, flags+1, flags+2);\ SCECNT("PUT", &one, &zero , &zero); #define OnError_Reset \ SCECNT("PUT", flags, flags+1, flags+2);\ } /*========================================================================== * Local Routines *==========================================================================*/ #ifdef __STDC__ int GetLabel(TABLE *tp, int col, int pos, int len, char *buf) #else int GetLabel(tp, col, pos, len, buf) /*++++++++ .PURPOSE Interface to SCDRDC (Read Descriptor) for Label .RETURNS Status .REMARKS Trailing blanks are removed. Error is logged when found. -----------*/ TABLE *tp; /* IN: Table pointer */ int col; /* IN: Column number */ int pos; /* IN: Position (from 1) to get */ int len; /* IN: How many bytes to get */ char *buf; /* OUT: Result */ #endif { int got, status; OnError_Continue; if (status = SCDRDC(tp->imno, TBL_Dlab(col),1, pos, len, &got, buf, &dunit, &dnull)){ buf[0] = EOS; /* Failed... */ TBL_errf(status, "can't get info for column #%d, table: %s", col, tp->phname); } else { /* Remove trailing spaces, and terminate string */ while (got > 0 && buf[--got] == ' ') buf[got] = '\0'; } OnError_Reset; return(ERR_NORMAL); } #ifdef __STDC__ int PutLabel(TABLE *tp, int col, char *buf, int pos, int len) #else int PutLabel(tp, col, buf, pos, len) /*++++++++ .PURPOSE Interface to SCDWRC (Write Descriptor) for Label .RETURNS Status .REMARKS Error is logged when found. -----------*/ TABLE *tp; /* IN: Table pointer */ int col; /* IN: Column number */ char *buf; /* IN: What to write */ int pos; /* IN: Position (from 1) to write*/ int len; /* IN: How many bytes to get */ #endif { int status; if (status = SCDWRC(tp->imno, TBL_Dlab(col),1, buf, pos,len, &dunit)) TBL_errf(status, "can't write info for column #%d, table: %s", col, tp->phname); else tp->tflags |= TBL__MODIFIED; return(status); } /*========================================================================== * Public Routines *==========================================================================*/ int TCBGET(tid, column, dtype, items, bytes) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Reads Binary storage characteristics of Column. The routine returns the data type (one of the D_xx_FORMAT), the number of items (arrays), and the number of bytes required for the binary storage. .REMARKS Arrays only allowed for characters. .RETURNS status -------------------------------------------------------------*/ int tid; /* IN : table ident */ int column; /* IN : column number */ int *dtype; /* OUT: data type */ int *items; /* OUT: array size */ int *bytes; /* OUT: storage required*/ { TABLE *tp; int *ptr; int status; char ws[3]; /* check argument */ tp = TBL_ptr(tid); if (status = CheckTable(tp)) return(TBL_errs(tid, status,0)); if (status = CheckColumn(tp, column)) return(TBL_errs(tid, status, column)); if (column == 0) { /* Special Selection */ *dtype = D_I4_FORMAT; *bytes = sizeof(int); return (status); } /* assign type according to code */ ptr = tp->dtypes + column - 1; *items = TBL_Items(*ptr); switch (TBL_ElementType(*ptr)) { case TBL_D_I1: *dtype = D_I1_FORMAT; *bytes = 1; break; case TBL_D_I2: *dtype = D_I2_FORMAT; *bytes = sizeof(short); break; case TBL_D_I4: *dtype = D_I4_FORMAT; *bytes = sizeof(int); break; case TBL_D_R8: *dtype = D_R8_FORMAT; *bytes = sizeof(double); break; case TBL_D_R4: *dtype = D_R4_FORMAT; *bytes = sizeof(float); break; case TBL_D_A1: *dtype = D_C_FORMAT; *bytes = *items; GetLabel(tp,column,39,3,ws); *items = atoi(ws); if (*items == 0) *items = 1; break; case TBL_D_A2: *dtype = D_UI2_FORMAT; *bytes = sizeof(short); break; case TBL_D_A4: *dtype = D_L4_FORMAT; *bytes = sizeof(int); break; } if (*dtype != D_C_FORMAT) *bytes *= *items; return(status); } int TCDGET(tid, store) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Reads table storage format .RETURNS status -------------------------------------------------------------*/ int tid; /* IN : table id */ int *store; /* OUT: table storage format, as F_RECORD or F_TRANS */ { TABLE *tp; int status; /* check argument */ tp = TBL_ptr(tid); if (status = CheckTable(tp)) return(TBL_errs(tid, status,0)); *store = tp->swise; return(status); } int TCFGET(tid, column, form, len, dtype) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Reads column format. The routine returns the column format, the length of the column field when edited (bytes), and the data type. .RETURNS status -------------------------------------------------------------*/ int tid; /* IN : table ident */ int column; /* IN : column number */ char *form; /* OUT: column format */ int *len; /* OUT: field length */ int *dtype; /* OUT: data type */ { TABLE *tp; char *f; int j, col, tdtype, items; int status; char ws[10],ws1[4]; *len = 0; /* check argument */ tp = TBL_ptr(tid); if (status = CheckTable(tp)) return(TBL_errs(tid, status,0)); if (status = CheckColumn(tp, column)) return(TBL_errs(tid, status, column)); if (column == 0) { /* Special Selection */ strcpy(form,"I8 "); *len = 8; *dtype = D_I4_FORMAT; return (status); } col = column - 1; /* Is already loaded ? */ f = tp->format + (1+TBL_FORLEN)*col; if (*f == '\0') { /* read descriptor */ if (status = GetLabel(tp, column, 33, 9, ws)) return(status); for (j=0; jabytes[col] = atoi(&f[j]); } /* Copy format string to user's */ strcpy (form, f); tdtype = tp->dtypes[col]; items = TBL_Items(tdtype); if ((tdtype & (~TBL_D_MASK)) == 0) { GetLabel(tp,column,39,3,ws1); ws1[3] = 0; items = atoi(ws1); if (items == 0) items = 1; } /* assign type according to code */ switch (TBL_ElementType(tdtype)) { case TBL_D_A1: *dtype = D_C_FORMAT; break; case TBL_D_I1: *dtype = D_I1_FORMAT; break; case TBL_D_A2: *dtype = D_UI2_FORMAT; break; case TBL_D_I2: *dtype = D_I2_FORMAT; break; case TBL_D_A4: *dtype = D_L4_FORMAT; break; case TBL_D_I4: *dtype = D_I4_FORMAT; break; case TBL_D_R8: *dtype = D_R8_FORMAT; break; case TBL_D_R4: *dtype = D_R4_FORMAT; break; } /* Column Width */ *len = items * tp->abytes[col] + items - 1; return(status); } int TCFPUT(tid, column, form) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Writes column format. Defines or changes the format of the column. The format is defined in FORTRAN compatible form. .RETURNS status -------------------------------------------------------------*/ int tid; /* IN : table id */ int column; /* IN : column number */ char *form; /* IN : column format */ { TABLE *tp; char ws[10], *f; int status, i, j; /* check argument */ tp = TBL_ptr(tid); for (i=0; i< 10; i++) ws[i] = '\0'; if (status = CheckTable(tp)) return(TBL_errs(tid, status,0)); if (status = CheckTrueColumn(tp, column)) return(TBL_errs(tid, status, column)); /* check intrinsic type */ j = column-1; if (status = TBL_FMTCHK (form, tp->dtypes[j], ws)) return(status); /* Add Format */ f = tp->format + (1+TBL_FORLEN)*j; for (i=0; iabytes[j] = atoi(&f[i]); /* write descriptor */ if_not(tp->tflags & TBL__READONLY) status = PutLabel(tp, column, ws, 33,6); return (status); } int TCIGET(tid, column, row, nsort, allcol, allrow) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Reads table size information. .RETURNS status -------------------------------------------------------------*/ int tid; /* IN : table id */ int *column; /* OUT: number of column*/ int *row; /* OUT: number of rows */ int *nsort; /* OUT: sorted column */ int *allcol; /* OUT: number of allocated words per record */ int *allrow; /* OUT: number of allocated rows */ { TABLE *tp; int status; /* check argument */ tp = TBL_ptr(tid); if (status = CheckTable(tp)) return(TBL_errs(tid, status,0)); *column = tp->cols; *row = tp->rows; *nsort = tp->scol; *allcol = tp->acols; *allrow = tp->arows; return(status); } int TCIPUT(tid, column, row) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Writes number of table columns and rows. This routine has to be used in connection with mapping facility. .RETURNS status .REMARKS Should this really be allowed ???? -------------------------------------------------------------*/ int tid; /* IN : table id */ int column; /* IN: number of columns */ int row; /* IN: number of rows */ { TABLE *tp; int status; /* check argument */ tp = TBL_ptr(tid); if (status = CheckTable(tp)) return(TBL_errs(tid, status,0)); if (column <= 0) column = tp->cols; if (row < 0) row = tp->rows; if (row > tp->arows) return(TBL_errs(tid, ERR_TBLROW, row)); if (column > tp->cols) return(TBL_errs(tid, ERR_TBLCOL, row)); /* assign arguments */ tp->cols = column; tp->rows = row; return(status); } int TCKGET(tid, column) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Gets the sequential number of the reference column. .RETURNS status -------------------------------------------------------------*/ int tid; /* IN : table id */ int *column; /* OUT: number of column*/ { TABLE *tp; int status; /* check argument */ tp = TBL_ptr(tid); if (status = CheckTable(tp)) return(TBL_errs(tid, status,0)); *column = tp->kcol; return(status); } int TCKPUT(tid, column) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Defines the column to be used as reference to access rows by value. .RETURNS status -------------------------------------------------------------*/ int tid; /* IN : table id */ int column; /* IN : column number */ { TABLE *tp; int status; /* check argument */ tp = TBL_ptr(tid); if (status = CheckTable(tp)) return(TBL_errs(tid, status,0)); if (status = CheckColumn(tp, column)) return(TBL_errs(tid, status, column)); tp->kcol = column; tp->tflags |= TBL__MODIFIED; /* MP 080291 */ return(status); } int TCLGET(tid, column, label) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Reads column label. .RETURNS status -------------------------------------------------------------*/ int tid; /* IN : table id */ int column; /* IN : column number */ char *label; /* OUT: label name */ { TABLE *tp; int status; char *lab; /* check argument */ tp = TBL_ptr(tid); if (status = CheckTable(tp)) return(TBL_errs(tid, status,0)); if (status = CheckColumn(tp, column)) return(TBL_errs(tid, status, column)); if (column == 0) { strcpy(label,"Sequence "); return (status); } lab = tp->label + (1+TBL_LABLEN)*(column-1); /* read descriptor */ if (*lab == '\0') status = GetLabel(tp, column, 1,TBL_LABLEN, lab); if (status) return(status); strcpy (label, lab); return (status); } int TCLPUT(tid, column, label) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Writes column label. .RETURNS status -------------------------------------------------------------*/ int tid; /* IN : table id */ int column; /* IN : column number */ char *label; /* IN : label name */ { TABLE *tp; char ws[1+TBL_LABLEN]; int status; /* check argument */ tp = TBL_ptr(tid); if (status = CheckTable(tp)) return(TBL_errs(tid, status,0)); if (status = CheckTrueColumn(tp, column)) return(TBL_errs(tid, status, column)); /* converts label */ if (status = TBL_LABCHK(label,ws)) return(status); ws[TBL_LABLEN] = '\0'; /* write descriptor */ if (status = PutLabel(tp, column, ws, 1,TBL_LABLEN)) return(status); /* force reading TCLGET */ tp->label[(1+TBL_LABLEN)*(column-1)] = '\0'; return(status); } int TCLSER(tid, label, column) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Searchs the sequential number of the column having the given label, case insensitive. Column is set to -1 when name is not found. .RETURNS status. -------------------------------------------------------------*/ int tid; /* IN : table id */ char *label; /* IN : label name */ int *column; /* OUT: column number */ { TABLE *tp; char labcol[TBL_LABLEN+1], alabel[TBL_LABLEN+1]; int i, j, status; /* check argument */ tp = TBL_ptr(tid); if (status = CheckTable(tp)) return(TBL_errs(tid, status,0)); /* sequential label search*/ /* VERSION 1.8 ****************** modified to add null terminator after the first non-blank character in the label JDP - VILSPA 02-Jan-1990 */ for (j=0; (jcols; i++) { if (status = TCLGET (tid, i, alabel)) return(status); if (TBL_sdiff(labcol,alabel) == 0) { *column = i; break; } } return(status); } /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ typedef int (*FUNCTION)(); struct option { char *name; FUNCTION op_set; }; int TBL_eset(); /* Function that set error display */ int TBL_labcase(); static struct option options[] = { { "label_case", TBL_labcase}, { "display_errors", TBL_eset}, }; static FUNCTION what_to_do(name) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Convert the option string to a function .RETURNS The function to call / NULL if error .REMARKS Valid parameters are in the static options. -------------------------------------------------------------*/ char *name; /* IN: Name to check */ { struct option *op; int i; for (i = ITEMS(options), op = options; --i >= 0; op++) { if (TBL_sdiff (name, op->name) == 0) break; } return (i >= 0 ? op->op_set : (FUNCTION)0); } int TCOERR (tid, row, col, status, text) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Write an error .RETURNS Status .REMARKS -------------------------------------------------------------*/ int tid; /* IN : table id */ int row; /* IN: row number */ int col; /* IN: column number */ int status; /* IN: Status */ char *text; /* IN: Text to add */ { TABLE *tp; char fmt[30], *p; TBL_eclear(); tp = TBL_ptr(tid); return(status); } int TCOGET(op_name, value) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Gets various options; .RETURNS Status .REMARKS Valid parameters are: "label_case" sensitivity to case of labels "display_error" to display the errors -------------------------------------------------------------*/ char *op_name; /* IN : Name of option */ int *value; /* OUT: Option's value */ { int got, status; FUNCTION f; if (f = what_to_do(op_name)) { status = ERR_NORMAL; got = (*f)(0); (*f)(got); /* Reset the old value */ *value = got; } else status = ERR_TBLKEY; return(status); } int TCOSET(op_name, value) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Set various options. .RETURNS status .REMARKS See TCOGET for possible names of op_name. -------------------------------------------------------------*/ char *op_name; /* IN : Name of option */ int value; /* IN : Option's value */ { int status; FUNCTION f; if (f = what_to_do(op_name)) { status = ERR_NORMAL; (*f)(value); } else status = ERR_TBLKEY, TBL_errf(status, "Unknown option %s", op_name); return(status); } int TCSGET(tid, row, value) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Reads row selection flag. .METHOD Check if ALL selection flag in on. Otherwise, read selection flag. .RETURNS status -------------------------------------------------------------*/ int tid; /* IN : table id */ int row; /* IN : row number */ int *value; /* OUT: selection flag (TRUE if selected) */ { TABLE *tp; int status; int *x, ic; char line[1+TBL_Dselect_SIZE]; /* check argument */ tp = TBL_ptr(tid); if (status = CheckTable(tp)) return(TBL_errs(tid, status,0)); if (status = CheckRow(tp, row)) return(TBL_errs(tid, status, row)); /* Is it a view ? */ /* if (tp->swise & F_B_VIEW) { */ if (tp->vsize != 0) { ic = (tp->vsel[row>>3] & bit_mask[row&7]); *value = (ic != 0); return (status); } if (tp->select != '\0') /* TSELTABL not read */ if (status = TCSINF (tid, line)) return(status); ic = TBL_offset (tp, row, 0L); if (tp->select == '\1') /* Means ALL selected */ *value = (row <= tp->rows); else if (x = (int *)TBL_RD(tp, ic, sizeof(int))) *value = *x; else status = TBL_RDst(); return (status); } int TCSPUT(tid, row, value) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Writes row selection flag: Writes the value (TRUE/FALSE) to indicate selection/not-selection of the row in the table. .RETURNS status -------------------------------------------------------------*/ int tid; /* IN : table id */ int row; /* IN : row number */ int *value; /* IN: selection flag */ { TABLE *tp; int status; int *x, ic; unsigned char *vx; /* Table for selected rows modifications */ static incr[4] = { 0, 1, -1, 0}; /* check argument */ tp = TBL_ptr(tid); if (status = CheckTable(tp)) return(TBL_errs(tid, status,0)); if (status = CheckRow(tp, row)) return(TBL_errs(tid, status, row)); /* Is it a view ? */ /* if (tp->swise & F_B_VIEW) { */ if (tp->vsize != 0) { ic = bit_mask[row&7]; vx = &tp->vsel[row>>3]; if (*value) *vx |= ic; else *vx &= ~ic; return (status); } /* "ALL" selection may become false... */ if ((!*value) && (tp->select == '\1')) tp->select = '\0', tp->selected = -1; ic = TBL_offset (tp, row, 0L); if_not(x = (int *)TBL_RDF(tp, ic, sizeof(int), 1)) return(TBL_RDst()); if (tp->selected >= 0) { /* The count is modified. */ ic = (*value ? 1 : 0); ic |= (*x ? 2 : 0); tp->selected += incr[ic]; } *x = *value; return (status); } int TCSCNT(tid,count) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Count selected entries. .METHOD Sequential scan of the selection flags. .RETURNS status -------------------------------------------------------------*/ int tid; /* IN : table id */ int *count; /* out: number of selected entries */ { TABLE *tp; int status; int *pntr, i, iav, nw, ic ; char line[1+TBL_Dselect_SIZE]; /* check argument */ tp = TBL_ptr(tid); if (status = CheckTable(tp)) return(TBL_errs(tid, status,0)); /* read TSELTABL descriptor */ if (tp->vsize != 0) { *count = 0; for (i=1; irows; i++) { ic = (tp->vsel[i>>3] & bit_mask[i&7]); if (ic != 0) *count += 1; } return(status); } if (!tp->select){ status = SCDRDC(tp->imno, TBL_Dselect, 1, 1, TBL_Dselect_SIZE, &iav, line, &dunit, &dnull); if (status) return(TBL_errf(status, "can't access on table: %s", tp->phname)); tp->select = line[0]; if (tp->select == '-') tp->select ='\1'; } if (tp->selected >= 0) *count = tp->selected; else { /* Unknown. Must count it... */ *count = 0; nw = (tp->swise == F_TRANS ? 1 : tp->acols + 1); if_not (pntr = (int *)TBL_RD(tp, 0L, nw*sizeof(int)*tp->arows)) return(TBL_RDst()); for (i=0; i < tp->rows; i++, pntr += nw) if(*pntr) *count += 1; } /* Update the number of selected rows */ if (tp->selected != *count) tp->selected = *count, tp->tflags |= TBL__MODIFIED; return (status); } int TCSINI(tid) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Initializes selection flag. .RETURNS status -------------------------------------------------------------*/ int tid; /* IN : table id */ { TABLE *tp; int status; int i, nw, maxrows, mapped_rows; int *pntr; char line[1+TBL_Dselect_SIZE]; /* check argument */ tp = TBL_ptr(tid); if (status = CheckTable(tp)) return(TBL_errs(tid, status,0)); /* define selection line */ line[0] = '-'; for (i=1; i < TBL_Dselect_SIZE; i++) line[i] = ' '; line[i] = '\0'; /* force Null terminated string */ /* write descriptor */ status = SCDWRC(tp->imno, TBL_Dselect, 1, line, 1, TBL_Dselect_SIZE, &dunit); if (status) return(TBL_errf(status, "can't access on table: %s", tp->phname)); /* Initialize Selection flag */ nw = (tp->swise == F_TRANS ? 1 : tp->acols + 1); maxrows = TBL_EIO_LIMIT / sizeof(int) / nw; maxrows = MAX (maxrows, 1); for (i=0; i < tp->arows; i += maxrows) { mapped_rows = tp->arows - i; mapped_rows = MIN (mapped_rows, maxrows); if_not (pntr = (int *)TBL_RDF (tp, TBL_offset(tp, i+1, 0L), nw*sizeof(int)*mapped_rows, 1)) return(TBL_RDst()); while (--mapped_rows >= 0) { *pntr = 1; pntr += nw; } } tp->select = '\1'; /* All Rows Selected */ if (tp->selected != tp->rows) tp->selected = tp->rows, tp->tflags |= TBL__MODIFIED; return (status); } int TCSINF(tid, line) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Get selection information. .RETURNS status -------------------------------------------------------------*/ int tid; /* IN : table id */ char *line; /* OUT: selection info */ { TABLE *tp; int status, is, tidview; /* check argument */ tp = TBL_ptr(tid); if (status = CheckTable(tp)) return(TBL_errs(tid, status,0)); /* define selection line */ OnError_Continue; if (tp->usname) { status = SCFOPN(tp->usname,D_R4_FORMAT,F_O_MODE,F_TBL_TYPE, &tidview); status = SCDRDC(tidview, TBL_Dselect, 1, 1, TBL_Dselect_SIZE, &is, line, &dunit, &dnull); status = SCFCLO(tidview); } else status = SCDRDC(tp->imno, TBL_Dselect, 1, 1, TBL_Dselect_SIZE, &is, line, &dunit, &dnull); OnError_Reset; if (status != ERR_NORMAL) line[0] = '-', line[1] = '\0'; status = ERR_NORMAL; tp->select = line[0]; /* This byte is changed to \1 if ALL */ /* Remove Trailing Blanks */ for (is=0; isgraph(line[is]); is++) ; line[is] = '\0'; if ((line[0] == '-') && (line[1] == '\0')) tp->select = '\1', tp->selected = tp->rows; return (status); } int TCSSET(tid, line) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Set selection information. Note that the number of selected rows is not modified, unless line is blank which asks for an ALL selection. .RETURNS status -------------------------------------------------------------*/ int tid; /* IN : table id */ char *line; /* IN : selection info */ { TABLE *tp; int status, len; char local_line[TBL_Dselect_SIZE]; /* Padd line with blanks */ len = strlen(line); if (len > TBL_Dselect_SIZE) len = TBL_Dselect_SIZE; oscopy(local_line, line, len); while (len < TBL_Dselect_SIZE) local_line[len++] = ' '; /* Check the ALL selection */ if ((local_line[0] == ' ') || ((local_line[0] == '-') && (local_line[1] == ' '))) return(TCSINI(tid)); /* check argument */ tp = TBL_ptr(tid); if (status = CheckTable(tp)) return(TBL_errs(tid, status,0)); status = SCDWRC(tp->imno, TBL_Dselect, 1, local_line,1,len, &dunit); return (status); } int TCUGET(tid, column, unit) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Reads column unit. .RETURNS status -------------------------------------------------------------*/ int tid; /* IN : table id */ int column; /* IN : column number */ char *unit; /* OUT: unit name */ { TABLE *tp; int status; /* check argument */ tp = TBL_ptr(tid); if (status = CheckTable(tp)) return(TBL_errs(tid, status,0)); if (status = CheckColumn(tp, column)) return(TBL_errs(tid, status, column)); /* read descriptor; note that * GetLabel takes care of * non-existant units */ status = GetLabel(tp, column, 17, TBL_LABLEN, unit); return(status); } int TCUPUT(tid, column, unit) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Writes column units. .RETURNS status -------------------------------------------------------------*/ int tid; /* IN : table id */ int column; /* IN : column number */ char *unit; /* IN : unit name */ { TABLE *tp; char ws[TBL_UNILEN+1]; int status; /* check argument */ tp = TBL_ptr(tid); if (status = CheckTable(tp)) return(TBL_errs(tid, status,0)); if (status = CheckColumn(tp, column)) return(TBL_errs(tid, status, column)); if (status = TBL_UNICHK(unit,ws)) return(status); /* write descriptor */ if (status = PutLabel(tp, column, ws, 17,TBL_UNILEN)) return(status); return (status); } int TCVERS(tid) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Reads table Version .RETURNS ERR_NORMAL if Correct Version / -n for Obsolete Versions -------------------------------------------------------------*/ int tid; /* IN : table id */ { TABLE *tp; int status; tp = TBL_ptr(tid); if (status = CheckTable(tp)) return(TBL_errs(tid, status,0)); return (tp->version - TBL_VERSION); /* Gives the difference. 0 of OK */ } int TCAPUT(tid,column,items) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE changes the structure of a character column into an array .RETURNS ERR_NORMAL if Correct Version / -n for Obsolete Versions -------------------------------------------------------------*/ int tid; /* IN : table id */ int column; /* IN : column number */ int items; /* IN : column items */ { TABLE *tp; int dtype,nrow,ic,nbytes,null; char ws[4],*x; int status,i; tp = TBL_ptr(tid); if (status = CheckTable(tp)) return(TBL_errs(tid, status,0)); if (status = CheckColumn(tp, column)) return(TBL_errs(tid, status, column)); dtype = tp->dtypes[column]; if (dtype & (~TBL_D_MASK)) { status = ERR_TBLCOL; TBL_errf(status,"Can't change the structure of column #%d",column); return(status); } nrow = tp->rows; nbytes = tp->bytes[column-1]; for (i=1; i<=nrow; i++) { ic = TBL_offset(tp,i,column); x = TBL_RD(tp,ic,nbytes); if (!(null = TBL_isNULL(dtype,(int *)x))) { status = ERR_TBLCOL; TBL_errf(status,"Can't change the structure of column #%d",column); return(status); } } sprintf(ws,"%3d",items); status = PutLabel(tp,column,ws,39,3); }