/* @(#)trpic.c 17.1.1.1 (ES0-DMD) 01/25/02 17:47:39 */ /*=========================================================================== 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 ===========================================================================*/ /*+++++++++ .MODULE trpic.c .AUTHOR Francois Ochsenbein [ESO] .LANGUAGE C .CATEGORY Conversion from character to binary using a picture. .COMMENTS Definition of pictures are in edpic.c .VERSION 1.0 27-May-1988: Creation .VERSION 1.1 08-Jul-1988: Modified for separator = '.': following is left-adjusted... .VERSION 1.2 21-Oct-1988: Cosmetic Modifications. .VERSION 1.3 13-Jun-1989: Allow dashes (-) in middle of a number .VERSION 1.4 22-Mar-1990: Added stkpic (tokenisation) .VERSION 1.5 01-Aug-1990: Modified tr_pic, to allow e.g. +995959 pictures (no blanks embedded) -----------------------------------------*/ #include #include #include #include #include MID_EXTERN struct trerr_s *trerror; #define LEN 132 #define FINISH goto FIN #define GobbleSpaces(s,l) s += oscspan(s, l, _SPACE_, main_ascii) MID_STATIC long accu; MID_RSTATIC long p10[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; MID_STATIC int base = 10; MID_STATIC char sign; MID_STATIC char stk = 0; /* Indicator for stkpic */ /*===========================================================================*/ static int Number(str, len) /*++++++ .PURPOSE Just scan a string until non-valid characters are found. The number is stored in accu. .RETURNS Number of valid characters .REMARKS Not traced. --------*/ char *str; /* IN: The string to scan */ int len; /* IN: Length of the string */ { char *p, *pe; int i; accu = 0; if (len <= 0) return(0); for (p = str, pe = p + len; (p < pe) && (isxdigit(*p)); p++) { if (isdigit(*p)) i = '0'; else if (isupper(*p)) i = 'A' - 10; else i = 'a' - 10; i = *p - i; if (i >= base) break; accu = accu * base + i; } i = p - str; /* Number of Digits */ return(i); } /*===========================================================================*/ static int Sign(str, len) /*++++++ .PURPOSE Just scan the beginning of a string: skip leading blanks, and get the sign. .RETURNS Number of valid characters .REMARKS Not traced. --------*/ char *str; /* IN: The string to scan */ int len; /* IN: Length of the string */ { char *p, *pe; sign = 0; if (len <= 0) return(0); p = str, pe = p + len; GobbleSpaces(p, len); if (p < pe) { switch(*p) { case '-': sign = 1; case '+': p++; break; } GobbleSpaces(p, pe-p); /* Skip blanks */ } return(p-str); } /*===========================================================================*/ int tr_pic(str, len, pic, value) /*++++++ .PURPOSE Converts a string to a long number according to a picture (see module edpic.c) .RETURNS Length of matched characters in picture / -1 for error or no number .REMARKS returned value is e.g. 101 for 1.01 under picture 9.99 --------*/ char *str; /* IN: String to scan */ int len; /* IN: Length of str */ char *pic; /* IN: The picture */ long *value; /* OUT: result */ { char *p, *pe, *a, *astop, b, separator, sign_found; int i, nd, nda; long limit; p = str, pe = p + len; GobbleSpaces(p, len); *value = 0; sign = 0; separator = 0; sign_found = 0; trerror->errno= 0; for (a = pic, astop = a; *a; a += i, p += nd) { /* if ((p < pe) && (*p == '&')) pe = p; */ i = 0, nd = 0, limit = 0, base = 0; switch(*a) { case '+': a++; /* No digit allowed */ if (sign_found) goto case_other; i = oscskip(a, LEN, '+'); goto case_sign; case '-': /* Look for sign */ if (sign_found) goto case_other; if (*p == '-') a++; i = oscskip(a, LEN, '-'); case_sign: sign_found = 1; p += Sign(p, pe-p); b = '9'; if (a[i] == '0') goto case_0; goto case_other; #if 0 case '&': /* It's a stop */ GobbleSpaces(p, pe-p); /* Skip trailing spaces */ pe = p; FINISH; #endif case ' ': GobbleSpaces(p, pe-p); break; case '\\': i = 2; /* Escape */ if ((p < pe) && (*p != a[1])) goto BAD; nd = 1; break; case_hexa: case 'X': sign_found = 1; i += oscskip(a, LEN, 'X'); if (i < 8) limit = 1 << (4*i); base = 16; break; case_0: case '0': sign_found = 1; i += oscskip(a, LEN, '0'); b = '9'; /* Default base */ case_other: default: if ((i > 0) && (a[i] == 'X')) goto case_hexa; if (isdigit(a[i])) { sign_found = 1; b = a[i++]; while (b == a[i]) i++; } if (i > 0) /* Must get a number ... */ { base = b - '0' + 1; if ((isdigit(*a)) && (*a != '0')) Number(a, i), limit = accu + 1; else if ((base == 10) && (i < ITEMS(p10))) limit = p10[i]; break; } if (p >= pe) break; i = 1; if (isspace(*p)) /* Skip trailing spaces */ { GobbleSpaces(p, pe-p); /* if (*p == '&') pe = p; */ } else nd = 1; if (p >= pe) break; if (*a == '.') sign_found = 1; if (*p != *a) goto BAD; separator = *p; nd = 1; } if (i == 0) i = oscskip(a, LEN, *a); nda = i; /* Number of bytes taken into account in picture */ if (base) /* Must get a number... */ { nd = Number(p, MIN(nda, pe-p)); if (nd > i) /* Too many digits */ FINISH; if (limit) { if (accu >= limit) FINISH; /* Bad... */ *value = *value * limit; } if ((separator == '.') && (base == 10)) /* Decimal part left adjusted... */ accu *= p10[i-nd], nda = nd; *value += accu; } if (p < pe) astop = a+nda; } FIN: GobbleSpaces(p, pe-p); /* Skip trailing spaces */ BAD: /* We've finished... When stkpic was called, we've to return the length of the matched string --- otherwise the length of the matched pattern (picture) */ if (stk) return(p - str); /* Called from stkpic */ if (sign) *value = -(*value); if (p < pe) /* Bad number */ { trerror->errno = TRERR_UNDEF; trerror->msg = pic; trerror->str = str; trerror->len = len; trerror->offset = (p-str); tr_error(); i = -1; } else i = astop - pic; return(i); } /*===========================================================================*/ int stkpic(str, pic) /*++++++ .PURPOSE Compute the length of the tokenized string .RETURNS Length of str matched for specified picture .REMARKS --------*/ char *str; /* IN: String to scan */ char *pic; /* IN: The picture */ { int status; long value; stk = 1; /* Tells tr_pic that we just tokenize */ status = tr_pic (str, strlen(str), pic, &value); stk = 0; return(status); }