#include #include #include #include /* abs() */ #include /* alternative location for abs() */ #include "dbext.h" /* CHAR, etc., *_VALUE_CODE, STRUCT_DEF_HDR_TYPE */ #include "prtarray.h" /* print_array_*() */ #include "prtstruc.h" #include "find_def.h" /* find_def() */ /***************************************************************************** * * * COMMON OCEANOGRAPHIC DATA ACCESS SYSTEM (CODAS) * * * * WRITTEN BY: RAMON CABRERA, ERIC FIRING, and JULIE RANADA * * JOINT INSTITUTE FOR MARINE AND ATMOSPHERIC RESEARCH * * 1000 POPE ROAD MSB 404 * * HONOLULU, HI 96822 * * * * VERSION: 3.00 * * * * DATE: APRIL 1989 * * * *****************************************************************************/ /* FILE: prtstruc.c Structure printing functions and supporting routines. */ /*----------------------------------------------------------------------------- The following external variable declarations are used by the printing routines below in order to keep track of the cursor position in the case of printing to stdout. The variable screen_lines is initialized to zero each time a call to clear_screen is made, and is incremented by the print functions each time a line is printed to the screen. The variable max_screen_lines is used as a cutoff point to pause screen output until the user presses the enter key, so screen output does not scroll off. It is set to a default value appropriate for 24/25-line monitors. It may be reset using the function set_max_screen_lines below. The two external variables are declared in prtarray.c. */ extern int screen_lines; extern int max_screen_lines; /*----------------------------------------------------------------------------- FUNCTION: find_ncol Given a sample value and the print format string, it returns how many columns of such values can be printed on one screen line. PARAMETERS: format = the print format string sample_value = the value that will be printed in the given format RETURNS: the number of columns of such values that can be printed on an 80-character screen line */ int find_ncol(char *format, char *sample_value, SHORT value_type) { char buff[255]; switch(value_type) { case CHAR_VALUE_CODE: case BYTE_VALUE_CODE: case UBYTE_VALUE_CODE: sprintf(buff, format, *sample_value); break; case SHORT_VALUE_CODE: case USHORT_VALUE_CODE: sprintf(buff, format, *((SHORT *) sample_value)); break; case LONG_VALUE_CODE: case ULONG_VALUE_CODE: sprintf(buff, format, *((LONG *) sample_value)); break; case FLOAT_VALUE_CODE: case COMPLEX_VALUE_CODE: sprintf(buff, format, *((FLOAT *) sample_value)); break; case DOUBLE_VALUE_CODE: sprintf(buff, format, *((DOUBLE *) sample_value)); break; case TEXT_VALUE_CODE: sprintf(buff, format, sample_value); break; } return(80 / max_val(1, (int)strlen(buff))); } /*----------------------------------------------------------------------------- FUNCTION: print_structure It prints a single instance of a structure as an array of ubytes if the structure definition is not provided, or member by member if the structure definition is provided. In the latter case, the user-provided format or print function is used if provided, or the defaults otherwise. ARGUMENTS: fp = pointer to file to print to data = pointer to structure bytes name = pointer to structure name nbytes = no. of bytes in the structure str_def = pointer to head of linked list of structure definitions RETURNS: no. of bytes printed */ unsigned int print_structure(FILE *fp, char *data, char *name, unsigned int nbytes, STRUCT_DEF_HDR_TYPE *str_def) { STRUCT_DEF_ENTRY_TYPE *str_def_ptr; FORMAT_SPEC *format_ptr; char *data_ptr; unsigned int i, j, nelem; if ((str_def == NULL) || ((str_def_ptr = (STRUCT_DEF_ENTRY_TYPE *) find_def(name, str_def)) == NULL)) /* NO STRUCTURE DEFINITION */ { fprintf(fp, " %20s : STRUCTURE (%u BYTES)\n\n", name, nbytes); if (nbytes > 0) return(print_array_1u(fp, (UBYTE *) data, nbytes, 6, "%12u")); else return(BADUINT); } data_ptr = data; nelem = str_def_ptr->hdr.nelem; for (i = 0; i < nelem; i++) { str_def_ptr += 1; if (str_def_ptr->elem.count != 0) { format_ptr = *(FORMAT_SPEC **) (str_def_ptr->elem.format_ptr); if (format_ptr) { if (format_ptr->print_function == NULL) data_ptr += print_select(fp, data_ptr, &(str_def_ptr->elem), str_def_ptr->elem.count, format_ptr->fmt_string, str_def); else { fputs(format_ptr->fmt_string, fp); for (j = 0; j < str_def_ptr->elem.count; j++) data_ptr += (*(format_ptr->print_function))(fp, data_ptr); } } else /* use default print function (print_select) & format */ { if (i == 0) { fprintf(fp, " %20s : STRUCTURE\n\n", name); } data_ptr += print_select(fp, data_ptr, &(str_def_ptr->elem), str_def_ptr->elem.count, NULL, str_def); fprintf(fp, "\n"); } } } return(data_ptr - data); } /*----------------------------------------------------------------------------- FUNCTION: print_array_struct It prints an array of structures, where each structure-element of the array is printed using the print_structure routine above. ARGUMENTS: fp = pointer to file to print to data = pointer to array of structures name = pointer to structure name n = no. of bytes in the array, if negative no. of elements in the array, if positive str_def = pointer to head of linked list of structure definitions RETURNS: no. of bytes printed */ unsigned int print_array_struct(FILE *fp, char *data, char *name, int n, STRUCT_DEF_HDR_TYPE *str_def) { unsigned int i, byte_count = 0, struct_size = 0; if (n > 0) /* n is no. of elements in array of structures */ for (i = 0; i < n; i++) byte_count += print_structure(fp, data+byte_count, name, 0, str_def); else /* n must be negative of no. of bytes in array of structures */ while ((int) (abs(n) - byte_count) > struct_size) { struct_size = print_structure(fp, data+byte_count, name, abs(n), str_def); byte_count += struct_size; } return(byte_count); } /*----------------------------------------------------------------------------- FUNCTION: print_select This function prints data to a file using either given or default formats. The data can be of any type from VALUE_CODE--single element, array, or structure. PARAMETERS: fp = pointer to FILE to print to data = pointer to data to be printed nuv = pointer to structure with ff. members: 1) name = variable name for data 2) units = variable units ("none" or "" or NULL if not applicable) 3) value_type = VALUE_CODE (0 to 11) The structure may therefore correspond to a DATA_LIST_ENTRY_TYPE or a STRUCT_DEF_ELEM_TYPE. n = no. of elements in data format = pointer to array of format structures for printing (NULL if using default formats) str_def = pointer to structure definitions in memory (NULL if non-structure or no structure definitions) */ unsigned int print_select(FILE *fp, char *data, STRUCT_DEF_ELEM_TYPE *nuv, unsigned int n, char *format, STRUCT_DEF_HDR_TYPE *str_def) { int ncol, no_format; unsigned int byte_count = 0; static struct { char format[15]; int ncol; } VALUE_FORMAT[] = { {"%12d" , 6}, {"%12u" , 6}, {"%c" , 80}, {"%12hd" , 6}, {"%12hu" , 6}, {"%12ld" , 6}, {"%12lu" , 6}, {"%12.6g" , 6}, {"%12.6lg" , 6}, {"%11.6g+i%11.6g", 3}, {"%s" , 1} }; if (nuv->value_type == STRUCT_VALUE_CODE) return(print_array_struct(fp, data, nuv->name, n, str_def)); else { no_format = (!format) || (!strcmp(format, "")); if (no_format) { fprintf(fp, " %20s : ", nuv->name); if (n > 1) { if ( (*(nuv->units)) && (stricmp(nuv->units, "none")) ) fprintf(fp, "in %s ", nuv->units); else fprintf(fp, "no units "); if ((nuv->value_type == CHAR_VALUE_CODE) || (nuv->value_type == TEXT_VALUE_CODE)) fprintf(fp, "(%u CHARACTERS)\n\n", n); else fprintf(fp, "(%u VALUES)\n\n", n); } format = VALUE_FORMAT[nuv->value_type].format; ncol = VALUE_FORMAT[nuv->value_type].ncol; } ncol = find_ncol(format, data, nuv->value_type); switch (nuv->value_type) { case BYTE_VALUE_CODE: byte_count = print_array_1s(fp, data, n, ncol, format); break; case UBYTE_VALUE_CODE: byte_count = print_array_1u(fp, (UBYTE *) data, n, ncol, format); break; case CHAR_VALUE_CODE: byte_count = print_array_1u(fp, (UBYTE *) data, n, ncol, format); break; case SHORT_VALUE_CODE: byte_count = print_array_2s(fp, (SHORT *) data, n, ncol, format); break; case USHORT_VALUE_CODE: byte_count = print_array_2u(fp, (USHORT *) data, n, ncol, format); break; case LONG_VALUE_CODE: byte_count = print_array_4(fp, (LONG *) data, n, ncol, format); break; case ULONG_VALUE_CODE: byte_count = print_array_4(fp, (LONG *) data, n, ncol, format); break; case FLOAT_VALUE_CODE: byte_count = print_array_float(fp, (FLOAT *) data, n, ncol, format); break; case DOUBLE_VALUE_CODE: byte_count = print_array_double(fp, (DOUBLE *) data, n, ncol, format); break; case COMPLEX_VALUE_CODE: byte_count = 2 * print_array_float(fp, (FLOAT *) data, n, ncol, format); break; case TEXT_VALUE_CODE: *(data + n - 1) = '\0'; /* make sure string is null-terminated */ fprintf(fp, format, data); byte_count = n; } if ( (n == 1) && (nuv->units != NULL) && (no_format) ) { if ( (*(nuv->units)) ) /* && (stricmp(nuv->units, "none")) ) */ fprintf(fp, " %s ", nuv->units); else fprintf(fp, " none "); } } return(byte_count); }