/* @(#)osc.c 17.1.1.1 (ES0-DMD) 01/25/02 17:35:07 */ /*=========================================================================== 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 ===========================================================================*/ /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .TYPE Module .NAME osc .LANGUAGE C .AUTHOR IPG-ESO Garching .CATEGORY Host operating system interfaces. Character functions. .ENVIRONMENT UNIX (BSD / SYSV) .COMMENTS Provide character manipulation host services. The routines return all length or indices. Routines are optimized for long strings. Note: MSDOS and VAX are apparently identical... .VERSION 1.0 880128 Definition. F. Ochsenbein .VERSION 1.0 910911 Adding some memory routines. CG. ------------------------------------------------------------*/ #include /* ANSI-C prototyping */ #include /* Need to know the OS */ #include #include #include /* * memcmp(); memcpy(); memchar(); memset(); * * This routines are defined in the XOPEN (System V Specifications). * * They are System_V originated functions that have been added to * the 4.3 BSD libraries. (Portable C and Unix System Programming) * They are also described in the ANSI X3J11 Draft Porposed Standard for * C. * * Convex V9.0 misses memcmp() and memchar(). * Alliant/Concentrix V1.0 misses all these routines and the file */ #ifdef NO_MEMCMP int memcmp(s1, s2, n) register char *s1, *s2; register int n; { int diff; if (s1 != s2) while (--n >= 0) if (diff = *s1++ - *s2++) return (diff); return (0); } #endif /* NO_MEMCMP */ #ifdef NO_MEMCHR char *memchr(sp, c, n) register char *sp, c; register int n; { while (--n >= 0) if (*sp++ == c) return (--sp); return (0); } #else /* char *memchr(); */ #endif /* NO_MEMCHR */ #ifdef NO_MEMCPY char *memcpy(s1, s2, n) register char *s1, *s2; register int n; { register char *os1 = s1; while (--n >= 0) *s1++ = *s2++; return (os1); } #endif /* NO_MEMCPY */ #ifdef NO_MEMSET char *memset(sp, c, n) register char *sp, c; register int n; { register char *sp0 = sp; while (--n >= 0) *sp++ = c; return (sp0); } #else /* char *memset(); */ #endif /* NO_MEMSET */ #ifdef NO_VSPRINTF vsprintf(buf, fmt, argv) char *buf, *fmt, **argv; { sprintf(buf, fmt, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9]); } #endif /* NO_VSPRINTF e.g: CONCENTRIX */ #define FINISH goto FIN #define RETURN(x) FIN: return(x) #define ___ 0x00 #define _U_ _UPPER_ /* UPPER-case letter A...Z */ #define _L_ _LOWER_ /* lower-case letter a...z */ #define _D_ _DIGIT_ /* digit 0...9 */ #define _S_ _SPACE_ /* space */ #define _P_ _PUNCT_ /* punctuation */ #define _C_ _CNTRL_ /* control character */ #define _X_ _XDIGIT_ /* hexa digit */ #define _B_ _BLANK_ /* blank */ /* Definition of TABS Alignments */ /*========================================================================== * Attributes of ASCII characters *==========================================================================*/ /* Attributes of ASCII characters */ unsigned char main_ascii[256] = /* ASCII attributes */ { /* UPP|low|dig|sp |pun|ctr|hex|bl * | | | | | | | */ ___|___|___|___|___|_C_|___|___, /* NUL */ ___|___|___|___|___|_C_|___|___, /* SOH */ ___|___|___|___|___|_C_|___|___, /* STX */ ___|___|___|___|___|_C_|___|___, /* ETX */ ___|___|___|___|___|_C_|___|___, /* EOT */ ___|___|___|___|___|_C_|___|___, /* ENQ */ ___|___|___|___|___|_C_|___|___, /* ACK */ ___|___|___|___|___|_C_|___|___, /* BEL */ ___|___|___|___|___|_C_|___|___, /* BS */ ___|___|___|_S_|___|_C_|___|___, /* HTab */ ___|___|___|_S_|___|_C_|___|___, /* LF */ ___|___|___|_S_|___|_C_|___|___, /* VTab */ ___|___|___|_S_|___|_C_|___|___, /* FF */ ___|___|___|_S_|___|_C_|___|___, /* CR */ ___|___|___|___|___|_C_|___|___, /* SO */ ___|___|___|___|___|_C_|___|___, /* SI */ ___|___|___|___|___|_C_|___|___, /* DLE */ ___|___|___|___|___|_C_|___|___, /* DC1 */ ___|___|___|___|___|_C_|___|___, /* DC2 */ ___|___|___|___|___|_C_|___|___, /* DC3 */ ___|___|___|___|___|_C_|___|___, /* DC4 */ ___|___|___|___|___|_C_|___|___, /* NAK */ ___|___|___|___|___|_C_|___|___, /* SYN */ ___|___|___|___|___|_C_|___|___, /* ETB */ ___|___|___|___|___|_C_|___|___, /* CAN */ ___|___|___|___|___|_C_|___|___, /* EM */ ___|___|___|___|___|_C_|___|___, /* SUB */ ___|___|___|___|___|_C_|___|___, /* ESC */ ___|___|___|___|___|_C_|___|___, /* FS */ ___|___|___|___|___|_C_|___|___, /* GS */ ___|___|___|___|___|_C_|___|___, /* RS */ ___|___|___|___|___|_C_|___|___, /* US */ ___|___|___|_S_|___|___|___|_B_, /* sp */ ___|___|___|___|_P_|___|___|___, /* ! */ ___|___|___|___|_P_|___|___|___, /* " */ ___|___|___|___|_P_|___|___|___, /* # */ ___|___|___|___|_P_|___|___|___, /* $ */ ___|___|___|___|_P_|___|___|___, /* % */ ___|___|___|___|_P_|___|___|___, /* & */ ___|___|___|___|_P_|___|___|___, /* ' */ ___|___|___|___|_P_|___|___|___, /* ( */ ___|___|___|___|_P_|___|___|___, /* ) */ ___|___|___|___|_P_|___|___|___, /* * */ ___|___|___|___|_P_|___|___|___, /* + */ ___|___|___|___|_P_|___|___|___, /* , */ ___|___|___|___|_P_|___|___|___, /* - */ ___|___|___|___|_P_|___|___|___, /* . */ ___|___|___|___|_P_|___|___|___, /* / */ ___|___|_D_|___|___|___|_X_|___, /* 0 */ ___|___|_D_|___|___|___|_X_|___, /* 1 */ ___|___|_D_|___|___|___|_X_|___, /* 2 */ ___|___|_D_|___|___|___|_X_|___, /* 3 */ ___|___|_D_|___|___|___|_X_|___, /* 4 */ ___|___|_D_|___|___|___|_X_|___, /* 5 */ ___|___|_D_|___|___|___|_X_|___, /* 6 */ ___|___|_D_|___|___|___|_X_|___, /* 7 */ ___|___|_D_|___|___|___|_X_|___, /* 8 */ ___|___|_D_|___|___|___|_X_|___, /* 9 */ ___|___|___|___|_P_|___|___|___, /* : */ ___|___|___|___|_P_|___|___|___, /* ; */ ___|___|___|___|_P_|___|___|___, /* < */ ___|___|___|___|_P_|___|___|___, /* = */ ___|___|___|___|_P_|___|___|___, /* > */ ___|___|___|___|_P_|___|___|___, /* ? */ ___|___|___|___|_P_|___|___|___, /* @ */ _U_|___|___|___|___|___|_X_|___, /* A */ _U_|___|___|___|___|___|_X_|___, /* B */ _U_|___|___|___|___|___|_X_|___, /* C */ _U_|___|___|___|___|___|_X_|___, /* D */ _U_|___|___|___|___|___|_X_|___, /* E */ _U_|___|___|___|___|___|_X_|___, /* F */ _U_|___|___|___|___|___|___|___, /* G */ _U_|___|___|___|___|___|___|___, /* H */ _U_|___|___|___|___|___|___|___, /* I */ _U_|___|___|___|___|___|___|___, /* J */ _U_|___|___|___|___|___|___|___, /* K */ _U_|___|___|___|___|___|___|___, /* L */ _U_|___|___|___|___|___|___|___, /* M */ _U_|___|___|___|___|___|___|___, /* N */ _U_|___|___|___|___|___|___|___, /* O */ _U_|___|___|___|___|___|___|___, /* P */ _U_|___|___|___|___|___|___|___, /* Q */ _U_|___|___|___|___|___|___|___, /* R */ _U_|___|___|___|___|___|___|___, /* S */ _U_|___|___|___|___|___|___|___, /* T */ _U_|___|___|___|___|___|___|___, /* U */ _U_|___|___|___|___|___|___|___, /* V */ _U_|___|___|___|___|___|___|___, /* W */ _U_|___|___|___|___|___|___|___, /* X */ _U_|___|___|___|___|___|___|___, /* Y */ _U_|___|___|___|___|___|___|___, /* Z */ ___|___|___|___|_P_|___|___|___, /* [ */ ___|___|___|___|_P_|___|___|___, /* \ */ ___|___|___|___|_P_|___|___|___, /* ] */ ___|___|___|___|_P_|___|___|___, /* ^ */ ___|___|___|___|_P_|___|___|___, /* _ */ ___|___|___|___|_P_|___|___|___, /* ` */ ___|_L_|___|___|___|___|_X_|___, /* a */ ___|_L_|___|___|___|___|_X_|___, /* b */ ___|_L_|___|___|___|___|_X_|___, /* c */ ___|_L_|___|___|___|___|_X_|___, /* d */ ___|_L_|___|___|___|___|_X_|___, /* e */ ___|_L_|___|___|___|___|_X_|___, /* f */ ___|_L_|___|___|___|___|___|___, /* g */ ___|_L_|___|___|___|___|___|___, /* h */ ___|_L_|___|___|___|___|___|___, /* i */ ___|_L_|___|___|___|___|___|___, /* j */ ___|_L_|___|___|___|___|___|___, /* k */ ___|_L_|___|___|___|___|___|___, /* l */ ___|_L_|___|___|___|___|___|___, /* m */ ___|_L_|___|___|___|___|___|___, /* n */ ___|_L_|___|___|___|___|___|___, /* o */ ___|_L_|___|___|___|___|___|___, /* p */ ___|_L_|___|___|___|___|___|___, /* q */ ___|_L_|___|___|___|___|___|___, /* r */ ___|_L_|___|___|___|___|___|___, /* s */ ___|_L_|___|___|___|___|___|___, /* t */ ___|_L_|___|___|___|___|___|___, /* u */ ___|_L_|___|___|___|___|___|___, /* v */ ___|_L_|___|___|___|___|___|___, /* w */ ___|_L_|___|___|___|___|___|___, /* x */ ___|_L_|___|___|___|___|___|___, /* y */ ___|_L_|___|___|___|___|___|___, /* z */ ___|___|___|___|_P_|___|___|___, /* { */ ___|___|___|___|_P_|___|___|___, /* | */ ___|___|___|___|_P_|___|___|___, /* } */ ___|___|___|___|_P_|___|___|___, /* ~ */ ___|___|___|___|___|_C_|___|___, /* DEL */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x8. */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x9. */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xA. */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xB. */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xC. */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xD. */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xE. */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* 0xF. */ }; /*========================================================================== * Copy memory to memory *==========================================================================*/ int oscopy(dest, source, len) /*++++++++++++++++++++++++++++++ .PURPOSE Copies second array of bytes into first one, taking care of possible overlay. .RETURNS Length (3rd argument) .REMARKS VMS version uses LIB$MOVC3 ----------------------------------------------*/ char *dest; /* OUT: pointer to destination string */ char *source; /* IN: pointer to source string */ int len; /* IN: length of source (and destination) strings */ { register char *p, *q, *q_end; if (len < 1) FINISH; if (dest == source) FINISH; /* same location */ q_end = dest + len; if ((dest < source) || (dest >= (source+len))) /* forwards */ memcpy(dest, source, len); else /* backwards */ { for (q = q_end, p = source + len; p > source;) *(--q) = *(--p); } RETURN(len); } /*==========================================================================*/ #ifdef __STDC__ int oscopuc(char * dest , char * source , int len , char escape) #else int oscopuc(dest, source, len, escape) /*++++++++++++++++++++++++++++++ .PURPOSE Copies second array of bytes into first one, stopping when escape is found or the source string i exhausted. The destination string INCLUDES on return the escape character. .RETURNS Number of copied characters, EXCLUDING the escape char if it was copied. .REMARKS No test about possible overlapping strings (result is unpredictable if strings overlap). VMS version uses LIB$MOVTUC and is limited to 65535 bytes. ----------------------------------------------*/ char *dest; /* OUT: pointer to destination string */ char *source; /* IN: pointer to source string */ int len; /* IN: length of source (and destination) strings */ char escape; /* IN: stopping char */ #endif { int l = len; while (--l >= 0) { if ((*dest++ = *source++) == escape) break; } return (l ? (len - l) - 1: len); } /*==========================================================================*/ #ifdef __STDC__ int oscfill(char * dest , int len , char fill) #else int oscfill(dest, len, fill) /*++++++++++++++++++++++++++++++ .PURPOSE Initialize a block of memory with fill character. .RETURNS The length (2nd argument) .REMARKS VMS version uses LIB$MOVC5 ----------------------------------------------*/ char *dest; /* MOD: buffer to set to zero */ int len; /* IN: length of buffer */ char fill; /* IN: The fill character */ #endif { (void)memset(dest, fill, len); return(len); } /*==========================================================================*/ #ifdef __STDC__ int oscloc(char * str , int len , char fill) #else int oscloc(str, len, fill) /*++++++++++++++++++++++++++++++ .PURPOSE Retrieve position of a specified character .RETURNS The index from 0 to (len-1) if found, len if not found. .REMARKS VMS version uses LIB$LOCC ----------------------------------------------*/ char *str; /* IN: string to scan */ int len; /* IN: length of string */ char fill; /* IN: The character to look for */ #endif { char *p; p = memchr(str, fill, len); return (p ? (p-str) : len); } /*==========================================================================*/ #ifdef __STDC__ oscbloc(char * str , int len , char fill) #else int oscbloc(str, len, fill) /*++++++++++++++++++++++++++++++ .PURPOSE Retrieve position of a specified character, in BACKWARDS direction .RETURNS The index from 0 to (len-1) if found, -1 if not found. .REMARKS ----------------------------------------------*/ char *str; /* IN: string to scan */ int len; /* IN: length of string */ char fill; /* IN: The character to look for */ #endif { register char *p; for (p = str+len; p > str; ) if (*(--p) == fill) FINISH; --p; RETURN(p-str); } /*==========================================================================*/ #ifdef __STDC__ int oscskip(char * str , int len , char fill) #else int oscskip(str, len, fill) /*++++++++++++++++++++++++++++++ .PURPOSE Retrieve position of first character that differs from fill. .RETURNS The index from 0 to (len-1) if found, len if all characters are identical to fill. .REMARKS VMS version uses LIB$SKPC ----------------------------------------------*/ char *str; /* IN: string to scan */ int len; /* IN: length of string */ char fill; /* IN: The character to look for */ #endif { register char *p, *p_end; for (p = str, p_end = str+len; p < p_end; p++) if (*p != fill) break; return(p-str); } /*==========================================================================*/ #ifdef __STDC__ int oscbskip(char * str , int len , char fill) #else int oscbskip(str, len, fill) /*++++++++++++++++++++++++++++++ .PURPOSE Retrieve position of first character different from fill, starting from the END of the string. .RETURNS The index from 0 to (len-1) if found, -1 if all characters are identical to fill. .REMARKS ----------------------------------------------*/ char *str; /* IN: string to scan */ int len; /* IN: length of string */ char fill; /* IN: The character to look for */ #endif { register char *p; for (p = str+len; p > str; ) if (*(--p) != fill) FINISH; --p; RETURN(p-str); } /*==========================================================================*/ #ifdef __STDC__ int oscspan(unsigned char * str , int len , unsigned char mask , unsigned char * table) #else int oscspan(str, len, mask, table) /*++++++++++++++++++++++++++++++ .PURPOSE Span char, i.e. locate first non-flagged char. A non-flagged char `c' is such that (table[c]&mask) is zero. .RETURNS The index from 0 to (len-1) if found, len if all characters are flagged. .REMARKS VMS version uses LIB$SPANC ----------------------------------------------*/ unsigned char *str; /* IN: string to scan */ int len; /* IN: length of string */ unsigned char mask; /* IN: AND operation to perform on table */ unsigned char *table; /* IN: The table (256 bytes) */ #endif { register unsigned char *p, *p_end; for (p = str, p_end = str+len; p < p_end; p++) if (!(table[*p]&mask)) break; return(p-str); } /*==========================================================================*/ #ifdef __STDC__ int oscbspan(unsigned char * str , int len , unsigned char mask , unsigned char * table) #else int oscbspan(str, len, mask, table) /*++++++++++++++++++++++++++++++ .PURPOSE Span char, i.e. locate first non-flagged char, starting from the END of the string. A non-flagged char `c' is such that (table[c]&mask) is zero. .RETURNS The index from 0 to (len-1) if found, -1 if all characters are flagged. .REMARKS ----------------------------------------------*/ unsigned char *str; /* IN: string to scan */ int len; /* IN: length of string */ unsigned char mask; /* IN: AND operation to perform on table */ unsigned char *table; /* IN: The table (256 bytes) */ #endif { register unsigned char *p; for (p = str+len; p > str; ) if (!(table[*(--p)]&mask)) FINISH; --p; RETURN(p-str); } /*==========================================================================*/ #ifdef __STDC__ int oscscan(unsigned char * str , int len , unsigned char mask , unsigned char * table) #else int oscscan(str, len, mask, table) /*++++++++++++++++++++++++++++++ .PURPOSE Scan char, i.e. locate first flagged char. A flagged char `c' is such that (table[c]&mask) differs from zero. .RETURNS The index from 0 to (len-1) if found, len if all characters are non-flagged. .REMARKS VMS version uses LIB$SCANC ----------------------------------------------*/ unsigned char *str; /* IN: string to scan */ int len; /* IN: length of string */ unsigned char mask; /* IN: AND operation to perform on table */ unsigned char *table; /* IN: The table (256 bytes) */ #endif { register unsigned char *p, *p_end; for (p = str, p_end = str+len; p < p_end; p++) if (table[*p]&mask) break; return(p-str); } /*==========================================================================*/ #ifdef __STDC__ int oscbscan(unsigned char * str , int len , unsigned char mask , unsigned char * table) #else int oscbscan(str, len, mask, table) /*++++++++++++++++++++++++++++++ .PURPOSE Span char, i.e. locate first flagged char, starting from the END of the string. A flagged char `c' is such that (table[c]&mask) differs from zero. .RETURNS The index from 0 to (len-1) if found, -1 if all characters are non-flagged. .REMARKS ----------------------------------------------*/ unsigned char *str; /* IN: string to scan */ int len; /* IN: length of string */ unsigned char mask; /* IN: AND operation to perform on table */ unsigned char *table; /* IN: The table (256 bytes) */ #endif { register unsigned char *p; for (p = str+len; p > str; ) if (table[*(--p)]&mask) FINISH; --p; RETURN(p-str); } /*==========================================================================*/ int oscomp(str1, str2, len) /*++++++++++++++++++++++++++++++ .PURPOSE Compare two strings of equal length. .RETURNS Sign of (str1-str2), i.e. 0 for identical strings, negative number if str1str2. .REMARKS VMS version uses STR$COMPARE ----------------------------------------------*/ char *str1; /* IN: string to compare */ char *str2; /* IN: second string */ int len; /* IN: length of strings */ { return (memcmp((char *)str1, (char *)str2, len)); } /*==========================================================================*/ int osccomp(str1, str2, len) /*++++++++++++++++++++++++++++++ .PURPOSE Compare two strings of equal length, case insensitive. .RETURNS Sign of (str1-str2), i.e. 0 for identical strings, negative number if str1str2. .REMARKS VMS version uses STR$CASE_BLIND_COMPARE ----------------------------------------------*/ char *str1; /* IN: string to compare */ char *str2; /* IN: second string */ int len; /* IN: length of strings */ { register char *p, *p_end; register int index; index = 0; for (p = str1, p_end = str1+len; p < p_end; p++, str2++) if (index = (toupper(*p) - toupper(*str2))) break; return(index); } /*==========================================================================*/ int oscindex(str1, len1, str2, len2) /*++++++++++++++++++++++++++++++ .PURPOSE Find the starting position in str1 of str2. .RETURNS The index of str2 in str1, or len if str2 not found. .REMARKS VMS version uses LIB$MATCHC ----------------------------------------------*/ char *str1; /* IN: string to compare */ int len1; /* IN: length of str1 */ char *str2; /* IN: second string */ int len2; /* IN: length of str2 */ { register char *p, *p_end; if (len2 == 0) FINISH; for (p = str1, p_end = p + len1; (p + len2) < p_end; p++) { if ((p = p + oscloc((char *)p, (p_end-p)-len2+1, *(char *)str2)) >= p_end) break; if (oscomp(p, str2, len2) == 0) FINISH; } p = p_end; RETURN(p-str1); } /*==========================================================================*/ int osctr(dest, source, len, table) /*++++++++++++++++++++++++++++++ .PURPOSE Translate a string according to a table. .RETURNS Length (3rd argument) .REMARKS VMS version uses LIB$MOVTC. Strings may overlap. ----------------------------------------------*/ unsigned char *dest; /* OUT: destination string */ unsigned char *source; /* IN: source string */ int len; /* IN: length of source (and destination) strings */ unsigned char *table; /* IN: Translation table (256 bytes) */ { register unsigned char *p, *q_end, *q; q_end = dest + len; if ((dest < source) || (dest >= (source+len))) /* forwards */ { for (p = source, q = dest; q < q_end; ) *(q++) = table[*(p++)]; } else /* backwards */ { for (q = q_end, p = source + len; p > source;) *(--q) = table[*(--p)]; } return(len); }