/* @(#)osc.c 17.1.1.1 (ES0-DMD) 01/25/02 17:35:24 */ /*=========================================================================== 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 *** VAX/VMS Version *** .COMMENTS Provide character manipulation host services. The routines return all length or indices. Routines are optimized for long strings. .VERSION 1.0 28-Jan-1988 Definition. F. Ochsenbein .VERSION 1.1 05-Sep-1989: Changed some `unclever' macros... ------------------------------------------------------------*/ #include #include MID_EXTERN int oserror; MID_EXTERN int vmserror; #include /* System */ #include /* System */ #include /* System */ typedef struct dsc$descriptor descript; # define CMAX 0xffff /* Maximal length */ # define L dsc$w_length # define S dsc$a_pointer # define InitDescript(text) \ {sizeof(text)-1, DSC$K_DTYPE_T, DSC$K_CLASS_S,text} # define void_string \ {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL_PTR(char)} # define SET_STRING(dsc,str,l) dsc.S = (char *)str, dsc.L = l \ /* Set address & length of a string */ #define FINISH goto FIN #define RETURN(x) FIN: return(x) #define ___ 0x00 #define _U_ 0x01 /* UPPER-case letter A...Z */ #define _L_ 0x02 /* lower-case letter a...z */ #define _D_ 0x04 /* digit 0...9 */ #define _S_ 0x08 /* space */ #define _P_ 0x10 /* punctuation */ #define _C_ 0x20 /* control character */ #define _X_ 0x40 /* hexa digit */ #define _B_ 0x80 /* blank */ /*========================================================================== * Attributes of ASCII characters *==========================================================================*/ /* Attributes of ASCII characters */ MID_GLOBAL 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 Uses LIB$MOVC3. No length limit. ----------------------------------------------*/ char *dest; /* OUT: pointer to destination string */ char *source; /* IN: pointer to source string */ int len; /* IN: length of source (and destination) strings */ { static unsigned short int length; register char *p, *q, *qe; if (len < 1) FINISH; if (dest == source) FINISH; /* same location */ qe = dest + len; if ((dest < source) || (dest >= (source+len))) /* forwards */ { for (p = source, q = dest; q < qe; ) { length = MIN(qe-q, CMAX); LIB$MOVC3(&length, p, q); p += length, q += length; } } else /* backwards */ { for (q = qe, p = source + len; p > source;) { length = MIN(q-dest, CMAX); p -= length, q -= length; LIB$MOVC3(&length, p, q); } } RETURN(len); } /*==========================================================================*/ 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 */ { static char escape_char; register int luc; MID_RSTATIC char tuc[256] = {0,1,2,3,4,5,6,7,8,9, 10,11,12,13,14,15,16,17,18,19, 20,21,22,23,24,25,26,27,28,29, 30,31,32,33,34,35,36,37,38,39, 40,41,42,43,44,45,46,47,48,49, 50,51,52,53,54,55,56,57,58,59, 60,61,62,63,64,65,66,67,68,69, 70,71,72,73,74,75,76,77,78,79, 80,81,82,83,84,85,86,87,88,89, 90,91,92,93,94,95,96,97,98,99, 100,101,102,103,104,105,106,107,108,109, 110,111,112,113,114,115,116,117,118,119, 120,121,122,123,124,125,126,127,128,129, 130,131,132,133,134,135,136,137,138,139, 140,141,142,143,144,145,146,147,148,149, 150,151,152,153,154,155,156,157,158,159, 160,161,162,163,164,165,166,167,168,169, 170,171,172,173,174,175,176,177,178,179, 180,181,182,183,184,185,186,187,188,189, 190,191,192,193,194,195,196,197,198,199, 200,201,202,203,204,205,206,207,208,209, 210,211,212,213,214,215,216,217,218,219, 220,221,222,223,224,225,226,227,228,229, 230,231,232,233,234,235,236,237,238,239, 240,241,242,243,244,245,246,247,248,249, 250,251,252,253,254,255} ; static descript sdv_table = {256, DSC$K_DTYPE_T, DSC$K_CLASS_S, tuc}; static descript sdv_esc = { 1, DSC$K_DTYPE_T, DSC$K_CLASS_S, &escape_char}; static descript sdv_in = void_string; static descript sdv_out = void_string; escape_char = escape; sdv_in.S = source; sdv_in.L = MIN(len, CMAX); sdv_out.S = dest ; sdv_out.L = sdv_in.L; luc = LIB$MOVTUC(&sdv_in, &sdv_esc, &sdv_table, &sdv_out); if ((luc > 0) && (luc <= len)) *(dest + --luc) = escape_char; else luc = len; return(luc); } /*==========================================================================*/ 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 */ { static unsigned short int length ; static unsigned short int zero = 0 ; register char *p, *pe; static char fill_char ; if (len < 1) FINISH; fill_char = fill; for (p = dest, pe = dest + len; p < pe; p += length) { length = MIN(pe-p, CMAX); LIB$MOVC5(&zero, 0, &fill_char, &length, p); /* Source is null */ } RETURN(len); } /*==========================================================================*/ 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 */ { register char *p; register char *pe; register int index; static char fill_char; static descript sdv_c = { 1, DSC$K_DTYPE_T, DSC$K_CLASS_S, &fill_char}; static descript sdv_str = void_string; sdv_c.L = 1, fill_char = fill; for (p = str, pe = str+len; p < pe; p += sdv_str.L) { sdv_str.L = MIN(pe-p, CMAX); sdv_str.S = p; index = LIB$LOCC(&sdv_c,&sdv_str); if (index) return(--index); } p = pe; RETURN(p-str); } /*==========================================================================*/ 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 */ { register char *p; for (p = str+len; p > str; ) if (*(--p) == fill) FINISH; --p; RETURN(p-str); } /*==========================================================================*/ 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 */ { register char *p, *pe; register int index; static char fill_char; static descript sdv_c = { 1, DSC$K_DTYPE_T, DSC$K_CLASS_S, &fill_char}; static descript sdv_str = void_string; sdv_c.L = 1, fill_char = fill; for (p = str, pe = str+len; p < pe; p += sdv_str.L) { sdv_str.L = MIN(pe-p, CMAX); sdv_str.S = p; index = LIB$SKPC(&sdv_c,&sdv_str); if (index) return(--index); } p = pe; RETURN(p-str); } /*==========================================================================*/ 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 */ { register char *p; for (p = str+len; p > str; ) if (*(--p) != fill) FINISH; --p; RETURN(p-str); } /*==========================================================================*/ 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) */ { register unsigned char *p, *pe; register int index; static unsigned char local_mask; static descript sdv_str = void_string; local_mask = mask; for (p = str, pe = str+len; p < pe; p += sdv_str.L) { sdv_str.L = MIN(pe-p, CMAX); sdv_str.S = (char *)p; index = LIB$SPANC(&sdv_str,table,&local_mask); if (index) return(--index); } p = pe; RETURN(p-str); } /*==========================================================================*/ 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) */ { register unsigned char *p; for (p = str+len; p > str; ) if (!(table[*(--p)]&mask)) FINISH; --p; RETURN(p-str); } /*==========================================================================*/ 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) */ { register unsigned char *p, *pe; register int index; static unsigned char local_mask; static descript sdv_str = void_string; local_mask = mask; for (p = str, pe = str+len; p < pe; p += sdv_str.L) { sdv_str.L = MIN(pe-p, CMAX); sdv_str.S = (char *)p; index = LIB$SCANC(&sdv_str,table,&local_mask); if (index) return(--index); } p = pe; RETURN(p-str); } /*==========================================================================*/ 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) */ { 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 ----------------------------------------------*/ unsigned char *str1; /* IN: string to compare */ unsigned char *str2; /* IN: second string */ int len; /* IN: length of strings */ { register unsigned char *p, *pe; register int index; static descript sdv1 = void_string; static descript sdv2 = void_string; index = 0; for (p = str1, pe = str1+len; p < pe; p += sdv1.L, str2 += sdv2.L) { sdv1.S = (char *)p; sdv1.L = MIN(pe-p, CMAX); sdv2.S = (char *)str2; sdv2.L = sdv1.L; if (index = STR$COMPARE(&sdv1,&sdv2)) break; } RETURN(index); } /*==========================================================================*/ 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 ----------------------------------------------*/ unsigned char *str1; /* IN: string to compare */ unsigned char *str2; /* IN: second string */ int len; /* IN: length of strings */ { register unsigned char *p, *pe; register int index; static descript sdv1 = void_string; static descript sdv2 = void_string; index = 0; for (p = str1, pe = str1+len; p < pe; p += sdv1.L, str2 += sdv2.L) { sdv1.S = (char *)p; sdv1.L = MIN(pe-p, CMAX); sdv2.S = (char *)str2; sdv2.L = sdv1.L; if (index = STR$CASE_BLIND_COMPARE(&sdv1,&sdv2)) 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 ----------------------------------------------*/ unsigned char *str1; /* IN: string to compare */ int len1; /* IN: length of str1 */ unsigned char *str2; /* IN: second string */ int len2; /* IN: length of str2 */ { register unsigned char *p, *pe; register int index; static descript sdv1 = void_string; static descript sdv2 = void_string; SET_STRING(sdv2, str2, len2); for (p = str1, pe = str1+len1; p < pe; p += sdv1.L) { sdv1.S = (char *)p; sdv1.L = MIN(pe-p, CMAX); index = LIB$MATCHC(&sdv2,&sdv1); if (index) return(--index); } p = pe; RETURN(p-str1); } /*==========================================================================*/ int osctr(dest, source, len, table) /*++++++++++++++++++++++++++++++ .PURPOSE Translate a string according to a table, i.e. replace each character `c' by table[`c']. .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, *qe, *q; static char fill_char; static descript sdv_fill = { 1, DSC$K_DTYPE_T, DSC$K_CLASS_S, &fill_char}; static descript sdv_in = void_string; static descript sdv_out = void_string; static descript sdv_table = void_string; SET_STRING(sdv_table, table, 256); qe = dest + len; if ((dest < source) || (dest >= (source+len))) /* forwards */ { for (p = source, q = dest; q < qe; ) { sdv_out.S = (char *)q; sdv_out.L = MIN(qe-q, CMAX); sdv_in.S = (char *)p; sdv_in.L = sdv_out.L; LIB$MOVTC(&sdv_in, &sdv_fill, &sdv_table, &sdv_out); p += sdv_in.L, q += sdv_in.L; } } else /* backwards */ { for (q = qe, p = source + len; p > source;) *(--q) = table[*(--p)]; } RETURN(len); }