github.com/goccy/go-jit@v0.0.0-20200514131505-ff78d45cf6af/internal/ccall/jit-util.c (about)

     1  /*
     2   * jit-memory.c - Memory copy/set/compare routines.
     3   *
     4   * Copyright (C) 2004  Southern Storm Software, Pty Ltd.
     5   *
     6   * This file is part of the libjit library.
     7   *
     8   * The libjit library is free software: you can redistribute it and/or
     9   * modify it under the terms of the GNU Lesser General Public License
    10   * as published by the Free Software Foundation, either version 2.1 of
    11   * the License, or (at your option) any later version.
    12   *
    13   * The libjit library is distributed in the hope that it will be useful,
    14   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    15   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    16   * Lesser General Public License for more details.
    17   *
    18   * You should have received a copy of the GNU Lesser General Public
    19   * License along with the libjit library.  If not, see
    20   * <http://www.gnu.org/licenses/>.
    21   */
    22  
    23  #include <jit/jit-util.h>
    24  #include "jit-config.h"
    25  
    26  #include <stdio.h>
    27  #ifdef HAVE_STDLIB_H
    28  # include <stdlib.h>
    29  #endif
    30  #if defined(HAVE_STRING_H)
    31  # include <string.h>
    32  #elif defined(HAVE_STRINGS_H)
    33  # include <strings.h>
    34  #endif
    35  #if defined(HAVE_MEMORY_H)
    36  # include <memory.h>
    37  #endif
    38  #if defined(HAVE_STDARG_H)
    39  # include <stdarg.h>
    40  #elif defined(HAVE_VARARGS_H)
    41  # include <varargs.h>
    42  #endif
    43  
    44  /*
    45   * Undefine the macros in "jit-internal.h" so that we
    46   * can define the real function forms.
    47   */
    48  #undef jit_memset
    49  #undef jit_memcpy
    50  #undef jit_memmove
    51  #undef jit_memcmp
    52  #undef jit_memchr
    53  
    54  /*@
    55   * @section Memory allocation
    56   *
    57   * The @code{libjit} library provides an interface to the traditional
    58   * system @code{malloc} routines.  All heap allocation in @code{libjit}
    59   * goes through these functions.  If you need to perform some other kind
    60   * of memory allocation, you can replace these functions with your
    61   * own versions.
    62  @*/
    63  
    64  /*@
    65   * @deftypefun {void *} jit_malloc (unsigned int @var{size})
    66   * Allocate @var{size} bytes of memory from the heap.
    67   * @end deftypefun
    68   *
    69   * @deftypefun {type *} jit_new (@var{type})
    70   * Allocate @code{sizeof(@var{type})} bytes of memory from the heap and
    71   * cast the return pointer to @code{@var{type} *}.  This is a macro that
    72   * wraps up the underlying @code{jit_malloc} function and is less
    73   * error-prone when allocating structures.
    74   * @end deftypefun
    75  @*/
    76  void *jit_malloc(unsigned int size)
    77  {
    78  	return malloc(size);
    79  }
    80  
    81  /*@
    82   * @deftypefun {void *} jit_calloc (unsigned int @var{num}, unsigned int @var{size})
    83   * Allocate @code{@var{num} * @var{size}} bytes of memory from the heap and clear
    84   * them to zero.
    85   * @end deftypefun
    86   *
    87   * @deftypefun {type *} jit_cnew (@var{type})
    88   * Allocate @code{sizeof(@var{type})} bytes of memory from the heap and
    89   * cast the return pointer to @code{@var{type} *}.  The memory is cleared
    90   * to zero.
    91   * @end deftypefun
    92  @*/
    93  void *jit_calloc(unsigned int num, unsigned int size)
    94  {
    95  	return calloc(num, size);
    96  }
    97  
    98  /*@
    99   * @deftypefun {void *} jit_realloc (void *@var{ptr}, unsigned int @var{size})
   100   * Re-allocate the memory at @var{ptr} to be @var{size} bytes in size.
   101   * The memory block at @var{ptr} must have been allocated by a previous
   102   * call to @code{jit_malloc}, @code{jit_calloc}, or @code{jit_realloc}.
   103   * @end deftypefun
   104  @*/
   105  void *jit_realloc(void *ptr, unsigned int size)
   106  {
   107  	return realloc(ptr, size);
   108  }
   109  
   110  /*@
   111   * @deftypefun void jit_free (void *@var{ptr})
   112   * Free the memory at @var{ptr}.  It is safe to pass a NULL pointer.
   113   * @end deftypefun
   114  @*/
   115  void jit_free(void *ptr)
   116  {
   117  	if(ptr)
   118  	{
   119  		free(ptr);
   120  	}
   121  }
   122  
   123  /*@
   124   * @section Memory set, copy, compare, etc
   125   * @cindex Memory operations
   126   *
   127   * The following functions are provided to set, copy, compare, and search
   128   * memory blocks.
   129  @*/
   130  
   131  /*@
   132   * @deftypefun {void *} jit_memset (void *@var{dest}, int @var{ch}, unsigned int @var{len})
   133   * Set the @var{len} bytes at @var{dest} to the value @var{ch}.
   134   * Returns @var{dest}.
   135   * @end deftypefun
   136  @*/
   137  void *jit_memset(void *dest, int ch, unsigned int len)
   138  {
   139  #ifdef HAVE_MEMSET
   140  	return memset(dest, ch, len);
   141  #else
   142  	unsigned char *d = (unsigned char *)dest;
   143  	while(len > 0)
   144  	{
   145  		*d++ = (unsigned char)ch;
   146  		--len;
   147  	}
   148  	return dest;
   149  #endif
   150  }
   151  
   152  /*@
   153   * @deftypefun {void *} jit_memcpy (void *@var{dest}, const void *@var{src}, unsigned int @var{len})
   154   * Copy the @var{len} bytes at @var{src} to @var{dest}.  Returns
   155   * @var{dest}.  The behavior is undefined if the blocks overlap
   156   * (use @var{jit_memmove} instead for that case).
   157   * @end deftypefun
   158  @*/
   159  void *jit_memcpy(void *dest, const void *src, unsigned int len)
   160  {
   161  #if defined(HAVE_MEMCPY)
   162  	return memcpy(dest, src, len);
   163  #elif defined(HAVE_BCOPY)
   164  	bcopy(src, dest, len);
   165  	return dest;
   166  #else
   167  	unsigned char *d = (unsigned char *)dest;
   168  	const unsigned char *s = (const unsigned char *)src;
   169  	while(len > 0)
   170  	{
   171  		*d++ = *s++;
   172  		--len;
   173  	}
   174  	return dest;
   175  #endif
   176  }
   177  
   178  /*@
   179   * @deftypefun {void *} jit_memmove (void *@var{dest}, const void *@var{src}, unsigned int @var{len})
   180   * Copy the @var{len} bytes at @var{src} to @var{dest} and handle
   181   * overlapping blocks correctly.  Returns @var{dest}.
   182   * @end deftypefun
   183  @*/
   184  void *jit_memmove(void *dest, const void *src, unsigned int len)
   185  {
   186  #ifdef HAVE_MEMMOVE
   187  	return memmove(dest, src, len);
   188  #else
   189  	unsigned char *d = (unsigned char *)dest;
   190  	const unsigned char *s = (const unsigned char *)src;
   191  	if(((const unsigned char *)d) < s)
   192  	{
   193  		while(len > 0)
   194  		{
   195  			*d++ = *s++;
   196  			--len;
   197  		}
   198  	}
   199  	else
   200  	{
   201  		d += len;
   202  		s += len;
   203  		while(len > 0)
   204  		{
   205  			*(--d) = *(--s);
   206  			--len;
   207  		}
   208  	}
   209  	return dest;
   210  #endif
   211  }
   212  
   213  /*@
   214   * @deftypefun int jit_memcmp (const void *@var{s1}, const void *@var{s2}, unsigned int @var{len})
   215   * Compare @var{len} bytes at @var{s1} and @var{s2}, returning a negative,
   216   * zero, or positive result depending upon their relationship.  It is
   217   * system-specific as to whether this function uses signed or unsigned
   218   * byte comparisons.
   219   * @end deftypefun
   220  @*/
   221  int jit_memcmp(const void *s1, const void *s2, unsigned int len)
   222  {
   223  #if defined(HAVE_MEMCMP)
   224  	return memcmp(s1, s2, len);
   225  #elif defined(HAVE_BCMP)
   226  	return bcmp(s1, s2, len);
   227  #else
   228  	const unsigned char *str1 = (const unsigned char *)s1;
   229  	const unsigned char *str2 = (const unsigned char *)s2;
   230  	while(len > 0)
   231  	{
   232  		if(*str1 < *str2)
   233  			return -1;
   234  		else if(*str1 > *str2)
   235  			return 1;
   236  		++str1;
   237  		++str2;
   238  		--len;
   239  	}
   240  	return 0;
   241  #endif
   242  }
   243  
   244  /*@
   245   * @deftypefun {void *} jit_memchr (void *@var{str}, int @var{ch}, unsigned int @var{len})
   246   * Search the @var{len} bytes at @var{str} for the first instance of
   247   * the value @var{ch}.  Returns the location of @var{ch} if it was found,
   248   * or NULL if it was not found.
   249   * @end deftypefun
   250  @*/
   251  void *jit_memchr(const void *str, int ch, unsigned int len)
   252  {
   253  #ifdef HAVE_MEMCHR
   254  	return memchr(str, ch, len);
   255  #else
   256  	const unsigned char *s = (const unsigned char *)str;
   257  	while(len > 0)
   258  	{
   259  		if(*s == (unsigned char)ch)
   260  		{
   261  			return (void *)s;
   262  		}
   263  		++s;
   264  		--len;
   265  	}
   266  	return (void *)0;
   267  #endif
   268  }
   269  
   270  /*@
   271   * @section String operations
   272   * @cindex String operations
   273   *
   274   * The following functions are provided to manipulate NULL-terminated
   275   * strings.  It is highly recommended that you use these functions in
   276   * preference to system functions, because the corresponding system
   277   * functions are extremely non-portable.
   278  @*/
   279  
   280  /*@
   281   * @deftypefun {unsigned int} jit_strlen (const char *@var{str})
   282   * Returns the length of @var{str}.
   283   * @end deftypefun
   284  @*/
   285  unsigned int jit_strlen(const char *str)
   286  {
   287  #ifdef HAVE_STRLEN
   288  	return (unsigned int)(strlen(str));
   289  #else
   290  	unsigned int len = 0;
   291  	while(*str++ != '\0')
   292  	{
   293  		++len;
   294  	}
   295  	return len;
   296  #endif
   297  }
   298  
   299  /*@
   300   * @deftypefun {char *} jit_strcpy (char *@var{dest}, const char *@var{src})
   301   * Copy the string at @var{src} to @var{dest}.  Returns @var{dest}.
   302   * @end deftypefun
   303  @*/
   304  char *jit_strcpy(char *dest, const char *src)
   305  {
   306  #ifdef HAVE_STRCPY
   307  	return strcpy(dest, src);
   308  #else
   309  	char ch;
   310  	char *d = dest;
   311  	while((ch = *src++) != '\0')
   312  	{
   313  		*d++ = ch;
   314  	}
   315  	*d = '\0';
   316  	return dest;
   317  #endif
   318  }
   319  
   320  /*@
   321   * @deftypefun {char *} jit_strcat (char *@var{dest}, const char *@var{src})
   322   * Copy the string at @var{src} to the end of the string at @var{dest}.
   323   * Returns @var{dest}.
   324   * @end deftypefun
   325  @*/
   326  char *jit_strcat(char *dest, const char *src)
   327  {
   328  #ifdef HAVE_STRCAT
   329  	return strcat(dest, src);
   330  #else
   331  	char ch;
   332  	char *d = dest + jit_strlen(dest);
   333  	while((ch = *src++) != '\0')
   334  	{
   335  		*d++ = ch;
   336  	}
   337  	*d = '\0';
   338  	return dest;
   339  #endif
   340  }
   341  
   342  /*@
   343   * @deftypefun {char *} jit_strncpy (char *@var{dest}, const char *@var{src}, unsigned int @var{len})
   344   * Copy at most @var{len} characters from the string at @var{src} to
   345   * @var{dest}.  Returns @var{dest}.
   346   * @end deftypefun
   347  @*/
   348  char *jit_strncpy(char *dest, const char *src, unsigned int len)
   349  {
   350  #ifdef HAVE_STRNCPY
   351  	return strncpy(dest, src, len);
   352  #else
   353  	char ch;
   354  	char *d = dest;
   355  	while(len > 0 && (ch = *src++) != '\0')
   356  	{
   357  		*d++ = ch;
   358  		--len;
   359  	}
   360  	while(len > 0)
   361  	{
   362  		*d++ = '\0';
   363  		--len;
   364  	}
   365  	return dest;
   366  #endif
   367  }
   368  
   369  /*@
   370   * @deftypefun {char *} jit_strdup (const char *@var{str})
   371   * Allocate a block of memory using @code{jit_malloc} and copy
   372   * @var{str} into it.  Returns NULL if @var{str} is NULL or there
   373   * is insufficient memory to perform the @code{jit_malloc} operation.
   374   * @end deftypefun
   375  @*/
   376  char *jit_strdup(const char *str)
   377  {
   378  	char *new_str;
   379  	if(!str)
   380  	{
   381  		return 0;
   382  	}
   383  	new_str = jit_malloc(strlen(str) + 1);
   384  	if(!new_str)
   385  	{
   386  		return 0;
   387  	}
   388  	strcpy(new_str, str);
   389  	return new_str;
   390  }
   391  
   392  /*@
   393   * @deftypefun {char *} jit_strndup (const char *@var{str}, unsigned int @var{len})
   394   * Allocate a block of memory using @code{jit_malloc} and copy at most
   395   * @var{len} characters of @var{str} into it.  The copied string is then
   396   * NULL-terminated.  Returns NULL if @var{str} is NULL or there
   397   * is insufficient memory to perform the @code{jit_malloc} operation.
   398   * @end deftypefun
   399  @*/
   400  char *jit_strndup(const char *str, unsigned int len)
   401  {
   402  	char *new_str;
   403  	if(!str)
   404  	{
   405  		return 0;
   406  	}
   407  	new_str = jit_malloc(len + 1);
   408  	if(!new_str)
   409  	{
   410  		return 0;
   411  	}
   412  	jit_memcpy(new_str, str, len);
   413  	new_str[len] = '\0';
   414  	return new_str;
   415  }
   416  
   417  /*@
   418   * @deftypefun int jit_strcmp (const char *@var{str1}, const char *@var{str2})
   419   * Compare the two strings @var{str1} and @var{str2}, returning
   420   * a negative, zero, or positive value depending upon their relationship.
   421   * @end deftypefun
   422  @*/
   423  int jit_strcmp(const char *str1, const char *str2)
   424  {
   425  #ifdef HAVE_STRCMP
   426  	return strcmp(str1, str2);
   427  #else
   428  	int ch1, ch2;
   429  	for(;;)
   430  	{
   431  		ch1 = *str1++;
   432  		ch2 = *str2++;
   433  		if(ch1 != ch2 || !ch1 || !ch2)
   434  		{
   435  			break;
   436  		}
   437  	}
   438  	return (ch1 - ch2);
   439  #endif
   440  }
   441  
   442  /*@
   443   * @deftypefun int jit_strncmp (const char *@var{str1}, const char *@var{str2}, unsigned int @var{len})
   444   * Compare the two strings @var{str1} and @var{str2}, returning
   445   * a negative, zero, or positive value depending upon their relationship.
   446   * At most @var{len} characters are compared.
   447   * @end deftypefun
   448  @*/
   449  int jit_strncmp(const char *str1, const char *str2, unsigned int len)
   450  {
   451  #ifdef HAVE_STRNCMP
   452  	return strncmp(str1, str2, len);
   453  #else
   454  	int ch1, ch2;
   455  	while(len > 0)
   456  	{
   457  		ch1 = *str1++;
   458  		ch2 = *str2++;
   459  		if(ch1 != ch2 || !ch1 || !ch2)
   460  		{
   461  			return (ch1 - ch2);
   462  		}
   463  		--len;
   464  	}
   465  	return 0;
   466  #endif
   467  }
   468  
   469  /*@
   470   * @deftypefun int jit_stricmp (const char *@var{str1}, const char *@var{str2})
   471   * Compare the two strings @var{str1} and @var{str2}, returning
   472   * a negative, zero, or positive value depending upon their relationship.
   473   * Instances of the English letters A to Z are converted into their
   474   * lower case counterparts before comparison.
   475   *
   476   * Note: this function is guaranteed to use English case comparison rules,
   477   * no matter what the current locale is set to, making it suitable for
   478   * comparing token tags and simple programming language identifiers.
   479   *
   480   * Locale-sensitive string comparison is complicated and usually specific
   481   * to the front end language or its supporting runtime library.  We
   482   * deliberately chose not to handle this in @code{libjit}.
   483   * @end deftypefun
   484  @*/
   485  int jit_stricmp(const char *str1, const char *str2)
   486  {
   487  	int ch1, ch2;
   488  	for(;;)
   489  	{
   490  		ch1 = *str1++;
   491  		ch2 = *str2++;
   492  		if(ch1 >= 'A' && ch1 <= 'Z')
   493  		{
   494  			ch1 = ch1 - 'A' + 'a';
   495  		}
   496  		if(ch2 >= 'A' && ch2 <= 'Z')
   497  		{
   498  			ch2 = ch2 - 'A' + 'a';
   499  		}
   500  		if(ch1 != ch2 || !ch1 || !ch2)
   501  		{
   502  			break;
   503  		}
   504  	}
   505  	return (ch1 - ch2);
   506  }
   507  
   508  /*@
   509   * @deftypefun int jit_strnicmp (const char *@var{str1}, const char *@var{str2}, unsigned int @var{len})
   510   * Compare the two strings @var{str1} and @var{str2}, returning
   511   * a negative, zero, or positive value depending upon their relationship.
   512   * At most @var{len} characters are compared.  Instances of the English
   513   * letters A to Z are converted into their lower case counterparts
   514   * before comparison.
   515   * @end deftypefun
   516  @*/
   517  int jit_strnicmp(const char *str1, const char *str2, unsigned int len)
   518  {
   519  	int ch1, ch2;
   520  	while(len > 0)
   521  	{
   522  		ch1 = *str1++;
   523  		ch2 = *str2++;
   524  		if(ch1 >= 'A' && ch1 <= 'Z')
   525  		{
   526  			ch1 = ch1 - 'A' + 'a';
   527  		}
   528  		if(ch2 >= 'A' && ch2 <= 'Z')
   529  		{
   530  			ch2 = ch2 - 'A' + 'a';
   531  		}
   532  		if(ch1 != ch2 || !ch1 || !ch2)
   533  		{
   534  			return (ch1 - ch2);
   535  		}
   536  		--len;
   537  	}
   538  	return 0;
   539  }
   540  
   541  /*@
   542   * @deftypefun {char *} jit_strchr (const char *@var{str}, int @var{ch})
   543   * Search @var{str} for the first occurrence of @var{ch}.  Returns
   544   * the address where @var{ch} was found, or NULL if not found.
   545   * @end deftypefun
   546  @*/
   547  char *jit_strchr(const char *str, int ch)
   548  {
   549  #ifdef HAVE_STRCHR
   550  	return strchr(str, ch);
   551  #else
   552  	char *s = (char *)str;
   553  	for(;;)
   554  	{
   555  		if(*s == (char)ch)
   556  		{
   557  			return s;
   558  		}
   559  		else if(*s == '\0')
   560  		{
   561  			break;
   562  		}
   563  		++s;
   564  	}
   565  	return 0;
   566  #endif
   567  }
   568  
   569  /*@
   570   * @deftypefun {char *} jit_strrchr (const char *@var{str}, int @var{ch})
   571   * Search @var{str} for the first occurrence of @var{ch}, starting
   572   * at the end of the string.  Returns the address where @var{ch}
   573   * was found, or NULL if not found.
   574   * @end deftypefun
   575  @*/
   576  char *jit_strrchr(const char *str, int ch)
   577  {
   578  #ifdef HAVE_STRRCHR
   579  	return strrchr(str, ch);
   580  #else
   581  	unsigned int len = jit_strlen(str);
   582  	char *s = (char *)(str + len);
   583  	while(len > 0)
   584  	{
   585  		--s;
   586  		if(*s == (char)ch)
   587  		{
   588  			return s;
   589  		}
   590  		--len;
   591  	}
   592  	return 0;
   593  #endif
   594  }
   595  
   596  int jit_sprintf(char *str, const char *format, ...)
   597  {
   598  	va_list va;
   599  	int result;
   600  #ifdef HAVE_STDARG_H
   601  	va_start(va, format);
   602  #else
   603  	va_start(va);
   604  #endif
   605  #ifdef VSPRINTF
   606  	result = vsprintf(str, format, va);
   607  #else
   608  	*str = '\0';
   609  	result = 0;
   610  #endif
   611  	va_end(va);
   612  	return result;
   613  }
   614  
   615  int jit_snprintf(char *str, unsigned int len, const char *format, ...)
   616  {
   617  	va_list va;
   618  	int result;
   619  #ifdef HAVE_STDARG_H
   620  	va_start(va, format);
   621  #else
   622  	va_start(va);
   623  #endif
   624  #if defined(HAVE_VSNPRINTF)
   625  	result = vsnprintf(str, len, format, va);
   626  #elif defined(HAVE__VSNPRINTF)
   627  	result = _vsnprintf(str, len, format, va);
   628  #else
   629  	*str = '\0';
   630  	result = 0;
   631  #endif
   632  	va_end(va);
   633  	return result;
   634  }