Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
00001 /* 00002 00003 Copyright (C) 2000, 2001, Silicon Graphics, Inc. All Rights Reserved. 00004 00005 This program is free software; you can redistribute it and/or modify it 00006 under the terms of version 2.1 of the GNU Lesser General Public License 00007 as published by the Free Software Foundation. 00008 00009 This program is distributed in the hope that it would be useful, but 00010 WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00012 00013 Further, this software is distributed without any warranty that it is 00014 free of the rightful claim of any third person regarding infringement 00015 or the like. Any license provided herein, whether implied or 00016 otherwise, applies only to this software file. Patent licenses, if 00017 any, provided herein do not apply to combinations of this program with 00018 other software, or any other product whatsoever. 00019 00020 You should have received a copy of the GNU Lesser General Public 00021 License along with this program; if not, write the Free Software 00022 Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, 00023 USA. 00024 00025 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00026 Mountain View, CA 94043, or: 00027 00028 http://www.sgi.com 00029 00030 For further information regarding this notice, see: 00031 00032 http://oss.sgi.com/projects/GenInfo/NoticeExplan 00033 00034 */ 00035 00036 00037 00038 #pragma ident "@(#) libf/fio/fstring.c 92.3 08/27/99 17:38:17" 00039 00040 #include <alloca.h> 00041 #include <string.h> 00042 00043 /* 00044 * Fortran character string handling routines for compiler-generated 00045 * code. 00046 */ 00047 00048 #define BLANK ((int) ' ') 00049 #define NUMBLNKS 128 00050 00051 static char *blanks = 00052 " " /* 32 */ 00053 " " /* 64 */ 00054 " " /* 96 */ 00055 " " /* 128 */ 00056 ; 00057 00058 /* 00059 * b_pad Pad Fortran string with blanks. 00060 * 00061 * Algorithm: use memset() and assume it's reasonably optimized. 00062 */ 00063 00064 void 00065 b_pad( char *str, 00066 int len ) 00067 { 00068 memset (str, BLANK, len); 00069 00070 return; 00071 } 00072 00073 /* 00074 * s_cat Concatenate Fortran strings. 00075 * 00076 * Concatenate an arbitrary number of strings. If the length of 00077 * the concatenated strings is shorter than the destination, then 00078 * pad with blanks; if longer, then truncate. Fortran semantics 00079 * require full expression evaluation before assignment so an 00080 * intermediate buffer is used in case the same (sub)string appears 00081 * on both sides of the assignment and would otherwise be overwritten 00082 * before concatenation. 00083 * 00084 * Strings may overlap and zero-length strings are allowed (per the 00085 * Fortran 90 standard). 00086 * 00087 * Algorithm: use memcpy() and assume it's reasonably optimized. 00088 * Build final result in intermediate buffer and use memcpy() 00089 * again to move it to the final destination. If the result 00090 * is shorter than destination then use memset() to blank 00091 * fill remainder. 00092 * 00093 * Other optimizations to be considered: 00094 * 1) An intermediate buffer is only necessary in a small 00095 * number of cases. Some sort of check could possibly 00096 * conditionally eliminate it, but may not be worth the 00097 * the trouble. 00098 * 2) Inline memcpy/memset 00099 * 3) And of course, have the compiler generate the concatenation 00100 * inline. 00101 */ 00102 00103 void 00104 s_cat( char *dest, /* Destination of concatenation */ 00105 char *src[], /* String(s) to be concatenated */ 00106 int slen[], /* ... and their length(s) */ 00107 int *num, /* Number of strings */ 00108 int dlen ) /* Length of destination */ 00109 { 00110 register int cnt; 00111 register int i; 00112 register int len; 00113 char *buf; 00114 00115 buf = alloca(dlen); 00116 cnt = *num; 00117 len = 0; 00118 00119 for (i = 0; i < cnt; i++) { 00120 register int tcnt; 00121 00122 tcnt = ((dlen - len) <= slen[i]) ? (dlen - len) : slen[i]; 00123 00124 if (tcnt < 0) /* If destination is full, stop */ 00125 break; 00126 00127 (void) memcpy (&buf[len], src[i], tcnt); 00128 00129 len = len + tcnt; 00130 } 00131 00132 (void) memcpy(dest, buf, len); 00133 00134 memset (&dest[len], BLANK, dlen - len); 00135 00136 return; 00137 } 00138 00139 /* 00140 * s_copy Copy Fortran string. 00141 * 00142 * Copy string2 to string1. If string2 is shorter than string1, then 00143 * pad with blanks. If string2 is longer than string1, then truncate. 00144 * 00145 * Strings may overlap and zero-length strings are allowed (per Fortran 00146 * 90). 00147 * 00148 * Algorithm: use memmove() and assume it's reasonably optimized. If 00149 * source is shorter than destination, then use memset() to 00150 * blank fill remainder. 00151 * 00152 * Other optimizations to be considered: 00153 * 1) Inline memmove/memset 00154 * 2) Special-case short strings, duplicate strings (s1 == s2), 00155 * and zero-length strings. 00156 * 3) And of course, have the compiler generate the move inline. 00157 */ 00158 00159 void 00160 s_copy( char *s1, 00161 char *s2, 00162 int l1, 00163 int l2 ) 00164 { 00165 register int len; 00166 00167 len = l1 - l2; 00168 00169 if (len <= 0) /* If length of destination <= length of source */ 00170 (void) memmove(s1, s2, l1); /* Copy as much as will fit */ 00171 else { 00172 (void) memmove(s1, s2, l2); /* Copy source */ 00173 memset (s1 + l2, BLANK, len); /* Pad remainder with blanks */ 00174 } 00175 00176 return; 00177 } 00178 00179 /* 00180 * s_cmp Compare Fortran strings. 00181 * 00182 * Returns: 0 if strings are equal 00183 * <0 if string 1 is less than string 2 00184 * >0 if string 1 is greater than string 2 00185 * 00186 * If the lengths of the strings are unequal, comparison occurs as 00187 * if the shorter string were padded with blanks. 00188 * 00189 * Zero-length strings are allowed (per Fortran 90). 00190 * 00191 * Algorithm: use memcmp() and assume it's reasonably optimized. If 00192 * substrings are equal, compare remnant with preset string of 00193 * blanks. 00194 * 00195 * Other optimizations to be considered: 00196 * 1) Inline memmove 00197 * 2) Special-case short strings, duplicate strings (s1 == s2), 00198 * and zero-length strings. 00199 * 3) And of course, have the compiler generate the comparisons 00200 * inline. 00201 */ 00202 00203 int 00204 s_cmp( char *s1, 00205 char *s2, 00206 int l1, 00207 int l2 ) 00208 { 00209 register int chnk; 00210 register int len; 00211 register int ret; 00212 00213 len = (l1 < l2) ? l1 : l2; 00214 00215 /* Compare the common substring with memcmp */ 00216 00217 ret = memcmp(s1, s2, len); 00218 00219 if ((ret != 0) || (l1 == l2)) 00220 goto scmp_exit; 00221 00222 if (l1 < l2) { /* s1 is shorter than s2 */ 00223 s1 = blanks; 00224 s2 = s2 + len; 00225 len = l2 - l1; /* Length of remnant */ 00226 } else { /* s2 is shorter than s1 */ 00227 s1 = s1 + len; 00228 s2 = blanks; 00229 len = l1 - l2; /* Length of remnant */ 00230 } 00231 00232 chnk = NUMBLNKS; 00233 00234 do { 00235 00236 if (len < chnk) 00237 chnk = len; 00238 00239 len = len - chnk; 00240 00241 ret = memcmp(s1, s2, chnk); 00242 00243 if (l1 < l2) /* s1 is shorter than s2 */ 00244 s2 = s2 + chnk; 00245 else 00246 s1 = s1 + chnk; 00247 00248 } while (ret == 0 && len > 0); 00249 00250 scmp_exit: 00251 return (ret); 00252 }