Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
fstring.c
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines