This is predef6.c in view mode; [Download] [Up]
/* * Copyright (C) 1985-1992 New York University * * This file is part of the Ada/Ed-C system. See the Ada/Ed README file for * warranty (none) and distribution info and also the GNU General Public * License for more details. */ /* +---------------------------------------------------+ | | | I N T E R P P R E D E F S | | Part 6: Editing Procedures | | (C Version) | | | | Adapted From Low Level SETL version written by | | | | Monte Zweben | | Philippe Kruchten | | Jean-Pierre Rosen | | | | Original High Level SETL version written by | | | | Clint Goss | | Tracey M. Siesser | | Bernard D. Banner | | Stephen C. Bryant | | Gerry Fisher | | | | C version written by | | | | Robert B. K. Dewar | | | +---------------------------------------------------+ */ /* This module contains routines for the implementation of some of * the predefined Ada packages and routines, namely SEQUENTIAL_IO, * DIRECT_IO, TEXT_IO, and CALENDAR. Part 6 contains the routines * for generating string images of internal objects. */ #include "ipredef.h" static double image_real_digits (double, int, char *); static void image_real (double, int, int, int); /* IMAGE_REAL_DIGITS */ /* Procedure to output number of digits specified by multiplying dval, which * is non-negative and less than 1.0, successively by 10. Output digits are * placed in string s. The value returned is the reduced value of dval. For * example, if dval is 0.314689 on entry, and n is 3, then the characters 314 * are output, and the returned value is 0.689 */ static double image_real_digits (double dval, int n, char *s) /*;image_real_digits*/ { int i; while (n--) { dval *= 10.0; i = (int)dval; *s++ = '0' + i; dval = dval - (double)i; } return dval; } /* IMAGE_REAL */ /* This routine is shared for fixed and float values. It returns a string image * of the double value dval, using fore, aft, exp as described in 14.3.8. The * resulting string image is stored in work_string. Note: if fore is zero, then * the string has the minimum required number of characters before the point. * If an out of range value is encountered, the exception in data_exception * is raised. If a bad character is encountered, DATA_ERROR is raised. */ static void image_real (double dval, int fore, int aft, int exp) /*;image_real*/ { int exponent; char sign; char *s, *t; int total_digits; int exp_digits; double round; /* Set pointer s to generate output characters in work string */ s = work_string; /* Make sure fore, aft, exp have acceptable values. 14.3.7 does not * justify limiting fore, aft and exp to 512, but it seems reasonable! */ if (fore <= 0) fore = 1; else if (fore > 512) fore = 512; if (aft < 0) aft = 0; else if (aft > 512) aft = 512; if (exp < 0) exp = 0; else if (exp > 512) exp = 512; /* Deal with 0.0 specially */ if (dval == 0.0) { while (fore-- > 1) *s++ = ' '; *s++ = '0'; *s++ = '.'; while (aft--) *s++ = '0'; if (exp) { *s++ = 'E'; *s++ = '+'; exp--; exp = MAX(exp,1); while (exp--) *s++ = '0'; } *s = 0; return; } /* If non-zero capture sign */ if (dval < 0.0) { sign = '-'; dval = -dval; fore--; } else sign = '+'; /* Reduce number to range 0.1 <= dval < 1.0, except that we do not * scale up if there is no exponent field, since we are happy with * leading zeroes in this case */ exponent = 0; if (exp != 0) { while (dval < 0.1) { exponent--; dval *= 10.0; } } while (dval >= 1.0) { exponent++; dval /= 10.0; } /* A special case, if there is no exponent field, we want at least one * digit in front of the point, which means that the exponent value * should be at least one to get the proper value for this digit. */ if (exp == 0 && exponent == 0) { exponent++; dval /= 10.0; } /* To round up, we must add a 5 in the place one past the last one to * be displayed. For the case of no exponent field there are exponent * digits before the point, otherwise there is only one digit. Note * that it is possible for rounding to push us back over 1.0 */ if (exp == 0) total_digits = aft + exponent; else total_digits = aft + 1; round = 0.5; while (total_digits--) round /= 10.0; dval += round; if (dval >= 1.0) { dval /= 10.0; exponent++; } /* Convert number for case of no exponent field present */ if (exp == 0) { while (fore > exponent) { fore--; *s++ = ' '; } if (sign == '-') *s++ = sign; dval = image_real_digits(dval,exponent,s); s += exponent; *s++ = '.'; image_real_digits(dval,aft,s); s += aft; } /* Convert number for case of exponent present */ else { while (fore > 1) { fore--; *s++ = ' '; } if (sign == '-') *s++ = sign; dval = image_real_digits(dval,1,s); s++; *s++ = '.'; image_real_digits(dval,aft,s); s += aft; /* Convert the exponent, first output E and sign */ exponent--; /* since one digit before point */ *s++ = 'E'; if (exponent < 0) { exponent = -exponent; *s++ = '-'; } else *s++ = '+'; exp--; /* to account for sign */ if (exp == 0) exp=1; /* but leave at least one digit */ /* Output digits of exponent */ t = s + 64; /* cannot be more than 64 non-zero dec digits! */ exp_digits = 0; while (exponent) { exp_digits++; *--t = '0' + (exponent % 10); exponent /= 10; } while (exp-- > exp_digits) *s++ = '0'; while (exp_digits--) *s++ = *t++; } /* Conversion is complete */ *s = 0; } /* IMAGE_INTEGER */ /* Returns a string image of item using the given base in work_string. If * an out of range value is encountered, the exception in data_exception * is raised. If a bad character is encountered, DATA_ERROR is raised. */ void image_integer(int item, int base) /*;image_integer*/ { char *p, *q; int digit; /* Convert base if not 10 */ p = work_string; if (base != 10) { if (base > 10) { *p++ = '1'; *p++ = '0' + base - 10; } else *p++ = base + '0'; *p++ = '#'; } /* Deal with sign. Note: we work with the negative of the absolute * value of the number so that we do not have to make special checks * for the largest negative number in the twos complement case. */ if (item < 0) *p++ = '-'; else item = -item; /* Convert value to digit string in specified base */ if (item == 0) { *p++ = '0'; } else { q = work_string + 15; *q = 0; while(item) { digit = -(item % base); item /= base; *--q = (digit > 9) ? digit - 10 + 'A' : digit + '0'; } while(*p++ = *q++); p--; } /* Add final # if based, and we are done */ if (base != 10) *p++ = '#'; *p = 0; } /* IMAGE_FIXED */ /* Returns a string image of the fixed point value item_val, where item_type * is a pointer to the type template, and fore, aft and exp control the * format according to the rules in 14.3.8. The result is in work_string. * Note: if fore is zero, then the result string has the minimum required * number of characters before the point. If an out of range value is * encountered, the exception in data_exception is raised. If a bad character * is encountered, DATA_ERROR is raised. */ void image_fixed (long item_val, int *item_type, int fore, int aft, int exp) /*;image_fixed*/ { int exp2, exp5; double dval; exp2 = FX_RANGE(item_type)->small_exp_2; exp5 = FX_RANGE(item_type)->small_exp_5; dval = (double)item_val; while (exp2 > 0) { exp2--; dval *= 2.0; } while (exp2 < 0) { exp2++; dval /= 2.0; } while (exp5 > 0) { exp5--; dval *= 5.0; } while (exp5 < 0) { exp5++; dval /= 5.0; } image_real (dval,fore,aft,exp); } /* IMAGE_FLOAT */ /* Returns a string image of the float value item_val, where fore, aft and * exp control the format according to the rules in 143.8. The result is in * work_string. Note: if fore is zero, then the result string has the minimum * required number of characters before the point. If an out of range value is * encountered, the exception in data_exception is raised. If a bad character * is encountered, DATA_ERROR is raised. */ void image_float (float num, int fore, int aft, int exp) /*;image_float*/ { image_real ((double)(num),fore,aft,exp); } /* IMAGE_ENUM */ /* Procedure to return the value of the given enumeration type value as a * string in work_string. The type_ptr parameter points to the type or * subtype template to be used for the operation. */ void image_enum(int enum_val, int *type_ptr) /*;image_enum*/ { int *ptr; char *c; int lit_len; if (TYPE(type_ptr) == TT_E_RANGE) /* an actual subtype */ type_ptr = ADDR(E_RANGE(type_ptr) -> ebase, E_RANGE(type_ptr) -> eoff); enum_val -= E_RANGE(type_ptr) -> elow; ptr = type_ptr + WORDS_E_RANGE;/* names are just past template */ lit_len = *ptr++; c = work_string; if (lit_len == -1) { /* special case for character */ *c++ = QUOTE; *c++ = enum_val; *c++ = QUOTE; } else { while(enum_val--) { ptr += lit_len; lit_len = *ptr++; } while(lit_len--) *c++ = *ptr++; } *c = 0; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.