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 }