static char rcsver[] = "$Id: output.c,v 1.1.1.1 1999/10/15 19:30:35 gorelick Exp $"; /** ** $Source: /tes/cvs/vanilla/output.c,v $ ** ** $Log: output.c,v $ ** Revision 1.1.1.1 1999/10/15 19:30:35 gorelick ** Version 3.0 ** ** 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" #include "output.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); PRINT_SCALED_INT(data, field); } static void print_scaled_uint(PTR raw, OSTRUCT *oinfo) { FIELD *field = oinfo->field; DATA data = ConvertData(raw, field); PRINT_SCALED_UINT(data, field); } static void print_scaled_real(PTR raw, OSTRUCT *oinfo) { FIELD *field = oinfo->field; DATA data = ConvertData(raw, field); PRINT_SCALED_REAL(data, field); } static void print_int(PTR raw, OSTRUCT *oinfo) { FIELD *field = oinfo->field; DATA data = ConvertData(raw, field); PRINT_INT(data); } static void print_uint(PTR raw, OSTRUCT *oinfo) { FIELD *field = oinfo->field; DATA data = ConvertData(raw, field); PRINT_UINT(data); } static void print_real(PTR raw, OSTRUCT *oinfo) { FIELD *field = oinfo->field; DATA data = ConvertData(raw, field); PRINT_REAL(data); } static void print_string(PTR raw, OSTRUCT *oinfo) { FIELD *field = oinfo->field; DATA data = ConvertData(raw, field); PRINT_STRING(data, field); } 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); PRINT_INT(data); } static void var_print_uint(PTR raw, VARDATA *vardata) { DATA data = ConvertVarData(raw, vardata); PRINT_UINT(data); } static void var_print_real(PTR raw, VARDATA *vardata) { DATA data = ConvertVarData(raw, vardata); PRINT_REAL(data); } static void var_print_string(PTR raw, VARDATA *vardata) { DATA data = ConvertVarData(raw, vardata); PRINT_STRING(data, vardata); } 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; } 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 MSB_BIT_FIELD: p = (FuncPtr) print_int; break; 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; } /** ** Field is 1 of 4 types: ** fake, ** simple array ** atomic ** vardata **/ void setup_output_parameters(OSTRUCT ** oinfo, int n, int defeat_scale) { int i; FuncPtr p; OSTRUCT *o; FIELD *f; for (i = 0; i < n; i++) { o = oinfo[i]; f = o->field; if (f->fakefield) { /* ** A fake field, skip it's dependents next time around */ i += f->fakefield->nfields; } if (f->dimension > 0) { /* ** A simple array field ** Cache the array output range, and print funcions */ if (o->range.end <= 0) { o->cooked.range.end = f->dimension; } else { o->cooked.range.end = MIN(o->range.end, f->dimension); } o->cooked.range.start = MAX(o->range.start, 1); o->cooked.is_atomic = 0; o->cooked.print_func = (FuncPtr) print_array; /* Select the function to do output of individual elements */ p = select_atom_output_func(f->iformat, !defeat_scale && f->scale); if (p == NULL) { fprintf(stderr, "Fatal! Format unsupported.\n"); abort(); } o->cooked.print_func2 = p; } else if (f->vardata == NULL) { /* ** An atomic field (dimension == 0 && !var) */ o->cooked.is_atomic = 1; /* Select the function to do the field output */ p = select_atom_output_func(f->iformat, !defeat_scale && f->scale); if (p == NULL) { fprintf(stderr, "Fatal! Format unsupported.\n"); abort(); } o->cooked.print_func = p; /* ** Set output extension function to NULL, since we are ** doing an atomic-field output. */ o->cooked.print_func2 = NULL; } else { /* ** Variable data field ** Select the output routine to use */ switch (f->vardata->type) { case Q15: o->cooked.print_func = (FuncPtr) print_q15_var_data; break; case VAX_VAR: o->cooked.print_func = (FuncPtr) print_vax_var_data; o->cooked.print_func2 = select_var_atom_output_func(f->vardata->iformat, 0); break; default: fprintf(stderr, "Fatal! Variable data type unsupported.\n"); abort(); break; } if ((o->range.start == 0) && (o->range.end == 0)) { /* Atomic field output as a hex file pointer */ o->cooked.is_atomic = 1; } else { /* ** Array field output upto either the specified limit or ** uptil the end of available data (specified by a negative ** number as the end value) */ o->cooked.is_atomic = 0; o->cooked.range.start = MAX(o->range.start, 1); if (o->range.end == 0) { /* Shouldn't happen though */ o->cooked.range.end = -1; } else { o->cooked.range.end = o->range.end; } } } } } void output_rec(OSTRUCT **o, int n) { int i; PTR raw; for (i = 0; i < n; i++) { if (o[i]->field->fakefield) { /* ** If this is a fakefield, compute its value, and output it. ** skip it's trailing dependent fields */ (*o[i]->field->fakefield->fptr)(o+i); i += o[i]->field->fakefield->nfields; } else { raw = o[i]->slice->start_rec + o[i]->field->start; (*(PrintFunc) o[i]->cooked.print_func) (raw, o[i]); } printf("%c", (i < n - 1 ? O_DELIM : '\n')); } }