| /* do not edit automatically generated by mc from StrLib. */ |
| /* StrLib.mod provides string manipulation procedures. |
| |
| Copyright (C) 2001-2025 Free Software Foundation, Inc. |
| Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>. |
| |
| This file is part of GNU Modula-2. |
| |
| GNU Modula-2 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 3, or (at your option) |
| any later version. |
| |
| GNU Modula-2 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. |
| |
| Under Section 7 of GPL version 3, you are granted additional |
| permissions described in the GCC Runtime Library Exception, version |
| 3.1, as published by the Free Software Foundation. |
| |
| You should have received a copy of the GNU General Public License and |
| a copy of the GCC Runtime Library Exception along with this program; |
| see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
| <http://www.gnu.org/licenses/>. */ |
| |
| #include "config.h" |
| #include "system.h" |
| #include <stdbool.h> |
| # if !defined (PROC_D) |
| # define PROC_D |
| typedef void (*PROC_t) (void); |
| typedef struct { PROC_t proc; } PROC; |
| # endif |
| |
| # if !defined (TRUE) |
| # define TRUE (1==1) |
| # endif |
| |
| # if !defined (FALSE) |
| # define FALSE (1==0) |
| # endif |
| |
| #define _StrLib_C |
| |
| #include "GStrLib.h" |
| # include "GASCII.h" |
| |
| |
| /* |
| StrConCat - combines a and b into c. |
| */ |
| |
| extern "C" void StrLib_StrConCat (const char *a_, unsigned int _a_high, const char *b_, unsigned int _b_high, char *c, unsigned int _c_high); |
| |
| /* |
| StrLess - returns TRUE if string, a, alphabetically occurs before |
| string, b. |
| */ |
| |
| extern "C" bool StrLib_StrLess (const char *a_, unsigned int _a_high, const char *b_, unsigned int _b_high); |
| extern "C" bool StrLib_StrEqual (const char *a_, unsigned int _a_high, const char *b_, unsigned int _b_high); |
| extern "C" unsigned int StrLib_StrLen (const char *a_, unsigned int _a_high); |
| |
| /* |
| StrCopy - copy string src into string dest providing dest is large enough. |
| If dest is smaller than a then src then the string is truncated when |
| dest is full. Add a nul character if there is room in dest. |
| */ |
| |
| extern "C" void StrLib_StrCopy (const char *src_, unsigned int _src_high, char *dest, unsigned int _dest_high); |
| |
| /* |
| IsSubString - returns true if b is a subcomponent of a. |
| */ |
| |
| extern "C" bool StrLib_IsSubString (const char *a_, unsigned int _a_high, const char *b_, unsigned int _b_high); |
| |
| /* |
| StrRemoveWhitePrefix - copies string, into string, b, excluding any white |
| space infront of a. |
| */ |
| |
| extern "C" void StrLib_StrRemoveWhitePrefix (const char *a_, unsigned int _a_high, char *b, unsigned int _b_high); |
| |
| /* |
| IsWhite - returns TRUE if, ch, is a space or a tab. |
| */ |
| |
| static bool IsWhite (char ch); |
| |
| |
| /* |
| IsWhite - returns TRUE if, ch, is a space or a tab. |
| */ |
| |
| static bool IsWhite (char ch) |
| { |
| return (ch == ' ') || (ch == ASCII_tab); |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| StrConCat - combines a and b into c. |
| */ |
| |
| extern "C" void StrLib_StrConCat (const char *a_, unsigned int _a_high, const char *b_, unsigned int _b_high, char *c, unsigned int _c_high) |
| { |
| unsigned int Highb; |
| unsigned int Highc; |
| unsigned int i; |
| unsigned int j; |
| char a[_a_high+1]; |
| char b[_b_high+1]; |
| |
| /* make a local copy of each unbounded array. */ |
| memcpy (a, a_, _a_high+1); |
| memcpy (b, b_, _b_high+1); |
| |
| Highb = StrLib_StrLen ((const char *) b, _b_high); |
| Highc = _c_high; |
| StrLib_StrCopy ((const char *) a, _a_high, (char *) c, _c_high); |
| i = StrLib_StrLen ((const char *) c, _c_high); |
| j = 0; |
| while ((j < Highb) && (i <= Highc)) |
| { |
| const_cast<char *>(c)[i] = b[j]; |
| i += 1; |
| j += 1; |
| } |
| if (i <= Highc) |
| { |
| const_cast<char *>(c)[i] = ASCII_nul; |
| } |
| } |
| |
| |
| /* |
| StrLess - returns TRUE if string, a, alphabetically occurs before |
| string, b. |
| */ |
| |
| extern "C" bool StrLib_StrLess (const char *a_, unsigned int _a_high, const char *b_, unsigned int _b_high) |
| { |
| unsigned int Higha; |
| unsigned int Highb; |
| unsigned int i; |
| char a[_a_high+1]; |
| char b[_b_high+1]; |
| |
| /* make a local copy of each unbounded array. */ |
| memcpy (a, a_, _a_high+1); |
| memcpy (b, b_, _b_high+1); |
| |
| Higha = StrLib_StrLen ((const char *) a, _a_high); |
| Highb = StrLib_StrLen ((const char *) b, _b_high); |
| i = 0; |
| while ((i < Higha) && (i < Highb)) |
| { |
| if (a[i] < b[i]) |
| { |
| return true; |
| } |
| else if (a[i] > b[i]) |
| { |
| /* avoid dangling else. */ |
| return false; |
| } |
| /* must be equal, move on to next character */ |
| i += 1; |
| } |
| return Higha < Highb; /* substrings are equal so we go on length */ |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| extern "C" bool StrLib_StrEqual (const char *a_, unsigned int _a_high, const char *b_, unsigned int _b_high) |
| { |
| unsigned int i; |
| unsigned int higha; |
| unsigned int highb; |
| char a[_a_high+1]; |
| char b[_b_high+1]; |
| |
| /* make a local copy of each unbounded array. */ |
| memcpy (a, a_, _a_high+1); |
| memcpy (b, b_, _b_high+1); |
| |
| higha = _a_high; |
| highb = _b_high; |
| i = 0; |
| while ((((i <= higha) && (i <= highb)) && (a[i] != ASCII_nul)) && (b[i] != ASCII_nul)) |
| { |
| if (a[i] != b[i]) |
| { |
| return false; |
| } |
| i += 1; |
| } |
| return ! (((i <= higha) && (a[i] != ASCII_nul)) || ((i <= highb) && (b[i] != ASCII_nul))); |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| extern "C" unsigned int StrLib_StrLen (const char *a_, unsigned int _a_high) |
| { |
| unsigned int High; |
| unsigned int Len; |
| char a[_a_high+1]; |
| |
| /* make a local copy of each unbounded array. */ |
| memcpy (a, a_, _a_high+1); |
| |
| Len = 0; |
| High = _a_high; |
| while ((Len <= High) && (a[Len] != ASCII_nul)) |
| { |
| Len += 1; |
| } |
| return Len; |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| StrCopy - copy string src into string dest providing dest is large enough. |
| If dest is smaller than a then src then the string is truncated when |
| dest is full. Add a nul character if there is room in dest. |
| */ |
| |
| extern "C" void StrLib_StrCopy (const char *src_, unsigned int _src_high, char *dest, unsigned int _dest_high) |
| { |
| unsigned int HighSrc; |
| unsigned int HighDest; |
| unsigned int n; |
| char src[_src_high+1]; |
| |
| /* make a local copy of each unbounded array. */ |
| memcpy (src, src_, _src_high+1); |
| |
| n = 0; |
| HighSrc = StrLib_StrLen ((const char *) src, _src_high); |
| HighDest = _dest_high; |
| while ((n < HighSrc) && (n <= HighDest)) |
| { |
| const_cast<char *>(dest)[n] = src[n]; |
| n += 1; |
| } |
| if (n <= HighDest) |
| { |
| const_cast<char *>(dest)[n] = ASCII_nul; |
| } |
| } |
| |
| |
| /* |
| IsSubString - returns true if b is a subcomponent of a. |
| */ |
| |
| extern "C" bool StrLib_IsSubString (const char *a_, unsigned int _a_high, const char *b_, unsigned int _b_high) |
| { |
| unsigned int i; |
| unsigned int j; |
| unsigned int LengthA; |
| unsigned int LengthB; |
| char a[_a_high+1]; |
| char b[_b_high+1]; |
| |
| /* make a local copy of each unbounded array. */ |
| memcpy (a, a_, _a_high+1); |
| memcpy (b, b_, _b_high+1); |
| |
| LengthA = StrLib_StrLen ((const char *) a, _a_high); |
| LengthB = StrLib_StrLen ((const char *) b, _b_high); |
| i = 0; |
| if (LengthA > LengthB) |
| { |
| while (i <= (LengthA-LengthB)) |
| { |
| j = 0; |
| while ((j < LengthB) && (a[i+j] == b[j])) |
| { |
| j += 1; |
| } |
| if (j == LengthB) |
| { |
| return true; |
| } |
| else |
| { |
| i += 1; |
| } |
| } |
| } |
| return false; |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| StrRemoveWhitePrefix - copies string, into string, b, excluding any white |
| space infront of a. |
| */ |
| |
| extern "C" void StrLib_StrRemoveWhitePrefix (const char *a_, unsigned int _a_high, char *b, unsigned int _b_high) |
| { |
| unsigned int i; |
| unsigned int j; |
| unsigned int higha; |
| unsigned int highb; |
| char a[_a_high+1]; |
| |
| /* make a local copy of each unbounded array. */ |
| memcpy (a, a_, _a_high+1); |
| |
| i = 0; |
| j = 0; |
| higha = StrLib_StrLen ((const char *) a, _a_high); |
| highb = _b_high; |
| while ((i < higha) && (IsWhite (a[i]))) |
| { |
| i += 1; |
| } |
| while ((i < higha) && (j <= highb)) |
| { |
| const_cast<char *>(b)[j] = a[i]; |
| i += 1; |
| j += 1; |
| } |
| if (j <= highb) |
| { |
| const_cast<char *>(b)[j] = ASCII_nul; |
| } |
| } |
| |
| extern "C" void _M2_StrLib_init (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[], __attribute__((unused)) char *envp[]) |
| { |
| } |
| |
| extern "C" void _M2_StrLib_fini (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[], __attribute__((unused)) char *envp[]) |
| { |
| } |