static char rcsver[] = "$Id: output.c,v 2.2 1999/07/12 23:14:08 gorelick Exp $"; /** ** $Source: /tes/src/vanilla/RCS/output.c,v $ ** ** $Log: output.c,v $ ** Revision 2.2 1999/07/12 23:14:08 gorelick ** *** empty log message *** ** ** Revision 2.1 1999/02/10 04:00:50 gorelick ** *** empty log message *** ** ** Revision 2.0 1998/12/22 22:47:04 gorelick ** release version ** ** Revision 2.0 1998/12/18 01:26:03 gorelick ** release version ** ** Revision 1.3 1998/11/12 22:58:55 gorelick ** first release version ** **/ #include #include #include #include "header.h" #include "proto.h" extern DATA ConvertVarData(PTR raw, VARDATA *vdata); PTR GiveMeVarPtr(PTR raw, TABLE *table, int offset); /* extern int ConvertVaxVarByteCount(PTR raw, VARDATA *vdata / * ??? * /); */ static short VARTEST[] = {12,10,11,12,13,14,15,12}; /* #define GiveMeVarPtr(raw, table, offset) ((void *)VARTEST) */ typedef void (*PrintFunc)(void *, OSTRUCT *); typedef void (*VarPrintFunc)(void *, VARDATA *); /** INTERNAL INTERFACES **/ /* ** print_X() prints a value of type X by taking a pointer to the ** raw value of the field and an OSTRUCT. ** ** print_scaled_X() prints the scaled value of type X by applying ** the specified scale and offset values. ** ** An OSTRUCT is being passed instead of a FIELD structure to keep ** the parameters of all the major print functions the same. This ** allows us to cache a print function pointer and call it for each ** output operation of that field. */ static void print_int(PTR raw, OSTRUCT *oinfo); static void print_uint(PTR raw, OSTRUCT *oinfo); static void print_real(PTR raw, OSTRUCT *oinfo); static void print_string(PTR raw, OSTRUCT *oinfo); static void print_scaled_int(PTR raw, OSTRUCT *oinfo); static void print_scaled_uint(PTR raw, OSTRUCT *oinfo); static void print_scaled_real(PTR raw, OSTRUCT *oinfo); /* ** print_array() prints the array of elements stored starting at ** the memory location stored in raw. */ static void print_array(PTR raw, OSTRUCT *oinfo); /* ** print_X_var_data() prints either the pointer to the variable ** data or the variable data items itself. Variable data record ** type "X" can be either VAX or Q15. The raw pointer points ** towards the file-pointer of the variable data within the variable ** part of the table. */ static void print_vax_var_data(PTR raw, OSTRUCT *oinfo); static void print_q15_var_data(PTR raw, OSTRUCT *oinfo); /* ** var_print_X() set of functions is the counterpart of the ** print_X() functions above, except that these work on VARDATA ** structures and pointers to a value of type X. These have been ** created to speedup the process by avoiding unnecessary conditions. */ static void var_print_int(PTR raw, VARDATA *vardata); static void var_print_uint(PTR raw, VARDATA *vardata); static void var_print_real(PTR raw, VARDATA *vardata); static void var_print_string(PTR raw, VARDATA *vardata); /* ** select_atom_output_func() selects a function for the output of ** the specified data type. It checks to see if a scaled or an ** unscaled function should be used. */ static FuncPtr select_atom_output_func(IFORMAT format, int is_scaled); /* ** select_var_atom_output_func() is the counterpart of ** select_atom_output_func() except that it works on atoms that can ** appear within the variable data */ static FuncPtr select_var_atom_output_func(IFORMAT format, int is_scaled); /** IMPLEMENTATION **/ static void print_scaled_int(PTR raw, OSTRUCT *oinfo) { FIELD *field = oinfo->field; DATA data = ConvertData(raw, field); printf("%.11g", ((double)data.i) * field->scale + field->offset); } static void print_scaled_uint(PTR raw, OSTRUCT *oinfo) { FIELD *field = oinfo->field; DATA data = ConvertData(raw, field); printf("%.11g", ((double)data.ui) * field->scale + field->offset); } static void print_scaled_real(PTR raw, OSTRUCT *oinfo) { FIELD *field = oinfo->field; DATA data = ConvertData(raw, field); printf("%.11g", data.r * field->scale + field->offset); } static void print_int(PTR raw, OSTRUCT *oinfo) { FIELD *field = oinfo->field; DATA data = ConvertData(raw, field); printf("%i", data.i); } static void print_uint(PTR raw, OSTRUCT *oinfo) { FIELD *field = oinfo->field; DATA data = ConvertData(raw, field); printf("%u", data.ui); } static void print_real(PTR raw, OSTRUCT *oinfo) { FIELD *field = oinfo->field; DATA data = ConvertData(raw, field); printf("%.11g", data.r); } static void print_string(PTR raw, OSTRUCT *oinfo) { FIELD *field = oinfo->field; DATA data = ConvertData(raw, field); printf("%*.*s", field->size, field->size, data.str); } static void print_array(PTR raw, OSTRUCT *oinfo) { int i; FIELD *field = oinfo->field; PrintFunc p = (PrintFunc)oinfo->cooked.print_func2; for (i = oinfo->cooked.range.start; i <= oinfo->cooked.range.end; i++){ (*p)(raw+(i-1)*field->size, oinfo); if (i < oinfo->cooked.range.end){ printf("%c", O_DELIM); } } } static void var_print_int(PTR raw, VARDATA *vardata) { DATA data = ConvertVarData(raw, vardata); printf("%i", data.i); } static void var_print_uint(PTR raw, VARDATA *vardata) { DATA data = ConvertVarData(raw, vardata); printf("%u", data.ui); } static void var_print_real(PTR raw, VARDATA *vardata) { DATA data = ConvertVarData(raw, vardata); printf("%.11g", data.r); } static void var_print_string(PTR raw, VARDATA *vardata) { DATA data = ConvertVarData(raw, vardata); printf("%*.*s", vardata->size, vardata->size, data.str); } static void print_q15_var_data(PTR raw, OSTRUCT *oinfo) { FIELD *field = oinfo->field; DATA data = ConvertData(raw, field); int m, n; double scale; int i; /* Assumption: VarPtr is always a signed-integer */ if(oinfo->cooked.is_atomic){ printf("%#x", data.i); } else { if (data.i < 0){ /* No variable data */ raw = NULL; n = 0; scale = 0; } else { /* Have some variable data */ raw = GiveMeVarPtr(raw, oinfo->table, data.i); assert(raw != NULL); /* Fatal memory reference error */ /* Assumption: byte size only contains the size of data bytes excluding the header and trailer byte size */ /* Read (signed int) byte size of variable data items from the head 2-bytes */ n = ConvertVaxVarByteCount(raw, field->vardata) / field->vardata->size; raw += 2; /* Skip the byte size */ assert(n > 0); /* Exponent must be there, otherwise, Q15 is incomplete */ /* Assumption: Q15 exponent is always a signed integer */ /* Read the Q15 (signed int) exponent (value) from the head 2-bytes */ scale = pow(2, (double)ConvertVarData(raw, oinfo->field->vardata).i-15); raw += 2; /* Skip the exponent */ /* Subtract 1 to exclude the quotient from the count of elements */ n--; } m = oinfo->cooked.range.end; /* m < 0: Output all the elements there are. If there are none, output atleast one "n/a" and hence if (n == 0){ n = 1; } m = 0: (Already handled somewhere up) Output the pointer values */ if (m < 0){ m = n; if (n == 0){ n = 1; } } else if (m > n){ int t = m; m = n; n = t; } /* Make sure m <= n */ else if (m < n){ n = m; } /* Number of avaialable data items to output */ for (i = oinfo->cooked.range.start; i <= m; i++){ printf("%.11g", (double)ConvertVarData(raw+(i-1)*field->vardata->size, field->vardata).i * scale); if (i < n){ printf("%c",O_DELIM); } } for (; i <= n; i++){ /* Number of n/a's to output */ printf("N/A"); if (i < n){ printf("%c",O_DELIM); } } } } static void print_vax_var_data(PTR raw, OSTRUCT *oinfo) { FIELD *field = oinfo->field; DATA data = ConvertData(raw, field); int m, n; double scale; VarPrintFunc p; int i; /* Assumption: VarPtr is always a signed-integer */ if(oinfo->cooked.is_atomic){ printf("%#x", data.i); } else { if (data.i < 0){ /* No variable data */ raw = NULL; n = 0; } else { /* Have some variable data */ raw = GiveMeVarPtr(raw, oinfo->table, data.i); assert(raw != NULL); /* Fatal memory reference error */ /* Assumption: byte size only contains the size of data bytes excluding the header and trailer byte size */ /* Read (signed int) byte size of variable data items from the head 2-bytes */ n = ConvertVaxVarByteCount(raw, field->vardata) / field->vardata->size; raw += 2; /* Skip the byte size */ } m = oinfo->cooked.range.end; /* m < 0: Output all the elements there are. If there are none, output atleast one "n/a" and hence if (n == 0){ n = 1; } m = 0: (Already handled somewhere up) Output the pointer values */ if (m < 0){ m = n; if (n == 0){ n = 1; } } else if (m > n){ int t = m; m = n; n = t; } /* Make sure m <= n */ else if (m < n){ n = m; } /* switch(field->vardata->iformat){ case INT: p = var_print_int; break; case UINT: p = var_print_uint; break; case REAL: p = var_print_real; break; case STRING: p = var_print_string; break; default: fprintf(stderr, "Vax Variable Data: Unknown format! Aborting.\n"); abort(); break; } */ p = (VarPrintFunc)oinfo->cooked.print_func2; /* Output available data items */ for (i = oinfo->cooked.range.start; i <= m; i++){ (*p)(raw+(i-1)*field->vardata->size, field->vardata); if (i < n){ printf("%c",O_DELIM); } } /* Output rest of elements as N/As */ for (; i <= n; i++){ printf("N/A"); if (i < n){ printf("%c",O_DELIM); } } } } static FuncPtr select_atom_output_func(IFORMAT format, int is_scaled) { FuncPtr p; switch(format){ case INT: if (is_scaled){ p = (FuncPtr)print_scaled_int; } else { p = (FuncPtr)print_int; } break; case UINT: if (is_scaled){ p = (FuncPtr)print_scaled_uint; } else { p = (FuncPtr)print_uint; } break; case REAL: if (is_scaled){ p = (FuncPtr)print_scaled_real; } else { p = (FuncPtr)print_real; } break; case STRING: p = (FuncPtr)print_string; break; default: p = NULL; break; } return p; } static FuncPtr select_var_atom_output_func(IFORMAT format, int is_scaled) { FuncPtr p; if (is_scaled){ fprintf(stderr, "Fatal! Variable data type not suppored.\n"); abort(); } switch(format){ case INT: p = (FuncPtr)var_print_int; break; case UINT: p = (FuncPtr)var_print_uint; break; case REAL: p = (FuncPtr)var_print_real; break; case STRING: p = (FuncPtr)var_print_string; break; default: p = (FuncPtr)NULL; break; } return p; } void setup_output_parameters(OSTRUCT **oinfo, int n, int defeat_scale) { int i; FuncPtr p; for (i = 0; i < n; i++){ if (oinfo[i]->field->dimension > 0){ /* An array field */ /* Cache the array output range, and print funcions */ if (oinfo[i]->range.end <= 0){ oinfo[i]->cooked.range.end = oinfo[i]->field->dimension; } else { oinfo[i]->cooked.range.end = MIN(oinfo[i]->range.end, oinfo[i]->field->dimension); } oinfo[i]->cooked.range.start = MAX(oinfo[i]->range.start, 1); oinfo[i]->cooked.is_atomic = 0; oinfo[i]->cooked.print_func = (FuncPtr)print_array; /* Select the function to do output of individual elements */ p = select_atom_output_func(oinfo[i]->field->iformat, !defeat_scale && oinfo[i]->field->scale); oinfo[i]->cooked.print_func2 = p; if (p == NULL){ fprintf(stderr, "Fatal! Format unsupported.\n"); abort(); } } else { if (oinfo[i]->field->vardata == NULL){ /* Atomic field */ oinfo[i]->cooked.is_atomic = 1; /* Select the function to do the field output */ p = select_atom_output_func(oinfo[i]->field->iformat, !defeat_scale && oinfo[i]->field->scale); oinfo[i]->cooked.print_func = p; /* Set output extension function to NULL, since we are doing an atomic-field output. */ oinfo[i]->cooked.print_func2 = NULL; if (p == NULL){ fprintf(stderr, "Fatal! Format unsupported.\n"); abort(); } } else { /* Variable data field */ /* Select the output routine to use */ switch(oinfo[i]->field->vardata->type){ case Q15: oinfo[i]->cooked.print_func = (FuncPtr)print_q15_var_data; break; case VAX_VAR: oinfo[i]->cooked.print_func = (FuncPtr)print_vax_var_data; oinfo[i]->cooked.print_func2 = select_var_atom_output_func(oinfo[i]->field->vardata->iformat,0); break; default: fprintf(stderr, "Fatal! Variable data type unsupported.\n"); abort(); break; } if ((oinfo[i]->range.start == 0) && (oinfo[i]->range.end == 0)){ /* Atomic field output as a hex file pointer */ oinfo[i]->cooked.is_atomic = 1; } else { /* Array field output upto either the specified limit or uptil the end of available data (specified by a -ve number as the end value) */ oinfo[i]->cooked.is_atomic = 0; oinfo[i]->cooked.range.start = MAX(oinfo[i]->range.start, 1); if (oinfo[i]->range.end == 0){ /* Shouldn't happen though */ oinfo[i]->cooked.range.end = -1; } else { oinfo[i]->cooked.range.end = oinfo[i]->range.end; } } } } } } void output_rec(OSTRUCT *ofieldsx[], int n) { int i; PTR raw; for (i = 0; i < n; i++){ raw = ofieldsx[i]->slice->start_rec + ofieldsx[i]->field->start; (*(PrintFunc)ofieldsx[i]->cooked.print_func)(raw, ofieldsx[i]); if (i < n-1){ printf("%c", O_DELIM); } } printf("\n"); }