diff options
Diffstat (limited to 'gcc/m2/mc-boot/GDynamicStrings.c')
-rw-r--r-- | gcc/m2/mc-boot/GDynamicStrings.c | 2686 |
1 files changed, 2686 insertions, 0 deletions
diff --git a/gcc/m2/mc-boot/GDynamicStrings.c b/gcc/m2/mc-boot/GDynamicStrings.c new file mode 100644 index 0000000..23ed7fb --- /dev/null +++ b/gcc/m2/mc-boot/GDynamicStrings.c @@ -0,0 +1,2686 @@ +/* do not edit automatically generated by mc from DynamicStrings. */ +/* DynamicStrings.mod provides a dynamic string type and procedures. + +Copyright (C) 2001-2021 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" +# 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 + +# include "GStorage.h" +#if defined(__cplusplus) +# undef NULL +# define NULL 0 +#endif +#define _DynamicStrings_H +#define _DynamicStrings_C + +# include "Glibc.h" +# include "GStrLib.h" +# include "GStorage.h" +# include "GAssertion.h" +# include "GSYSTEM.h" +# include "GASCII.h" +# include "GM2RTS.h" + +# define MaxBuf 127 +# define PoisonOn FALSE +# define DebugOn FALSE +# define CheckOn FALSE +# define TraceOn FALSE +typedef struct DynamicStrings_Contents_r DynamicStrings_Contents; + +typedef struct DynamicStrings_DebugInfo_r DynamicStrings_DebugInfo; + +typedef struct DynamicStrings_stringRecord_r DynamicStrings_stringRecord; + +typedef struct DynamicStrings_descriptor_r DynamicStrings_descriptor; + +typedef DynamicStrings_descriptor *DynamicStrings_Descriptor; + +typedef struct DynamicStrings_frameRec_r DynamicStrings_frameRec; + +typedef DynamicStrings_frameRec *DynamicStrings_frame; + +typedef struct DynamicStrings__T3_a DynamicStrings__T3; + +typedef enum {DynamicStrings_inuse, DynamicStrings_marked, DynamicStrings_onlist, DynamicStrings_poisoned} DynamicStrings_desState; + +typedef DynamicStrings_stringRecord *DynamicStrings_String; + +struct DynamicStrings_DebugInfo_r { + DynamicStrings_String next; + void *file; + unsigned int line; + void *proc; + }; + +struct DynamicStrings_descriptor_r { + unsigned int charStarUsed; + void *charStar; + unsigned int charStarSize; + unsigned int charStarValid; + DynamicStrings_desState state; + DynamicStrings_String garbage; + }; + +struct DynamicStrings_frameRec_r { + DynamicStrings_String alloc; + DynamicStrings_String dealloc; + DynamicStrings_frame next; + }; + +struct DynamicStrings__T3_a { char array[(MaxBuf-1)+1]; }; +struct DynamicStrings_Contents_r { + DynamicStrings__T3 buf; + unsigned int len; + DynamicStrings_String next; + }; + +struct DynamicStrings_stringRecord_r { + DynamicStrings_Contents contents; + DynamicStrings_Descriptor head; + DynamicStrings_DebugInfo debug; + }; + +static unsigned int Initialized; +static DynamicStrings_frame frameHead; +static DynamicStrings_String captured; + +/* + InitString - creates and returns a String type object. + Initial contents are, a. +*/ + +extern "C" DynamicStrings_String DynamicStrings_InitString (const char *a_, unsigned int _a_high); + +/* + KillString - frees String, s, and its contents. + NIL is returned. +*/ + +extern "C" DynamicStrings_String DynamicStrings_KillString (DynamicStrings_String s); + +/* + Fin - finishes with a string, it calls KillString with, s. + The purpose of the procedure is to provide a short cut + to calling KillString and then testing the return result. +*/ + +extern "C" void DynamicStrings_Fin (DynamicStrings_String s); + +/* + InitStringCharStar - initializes and returns a String to contain the C string. +*/ + +extern "C" DynamicStrings_String DynamicStrings_InitStringCharStar (void * a); + +/* + InitStringChar - initializes and returns a String to contain the single character, ch. +*/ + +extern "C" DynamicStrings_String DynamicStrings_InitStringChar (char ch); + +/* + Mark - marks String, s, ready for garbage collection. +*/ + +extern "C" DynamicStrings_String DynamicStrings_Mark (DynamicStrings_String s); + +/* + Length - returns the length of the String, s. +*/ + +extern "C" unsigned int DynamicStrings_Length (DynamicStrings_String s); + +/* + ConCat - returns String, a, after the contents of, b, have been appended. +*/ + +extern "C" DynamicStrings_String DynamicStrings_ConCat (DynamicStrings_String a, DynamicStrings_String b); + +/* + ConCatChar - returns String, a, after character, ch, has been appended. +*/ + +extern "C" DynamicStrings_String DynamicStrings_ConCatChar (DynamicStrings_String a, char ch); + +/* + Assign - assigns the contents of, b, into, a. + String, a, is returned. +*/ + +extern "C" DynamicStrings_String DynamicStrings_Assign (DynamicStrings_String a, DynamicStrings_String b); + +/* + Dup - duplicate a String, s, returning the copy of s. +*/ + +extern "C" DynamicStrings_String DynamicStrings_Dup (DynamicStrings_String s); + +/* + Add - returns a new String which contains the contents of a and b. +*/ + +extern "C" DynamicStrings_String DynamicStrings_Add (DynamicStrings_String a, DynamicStrings_String b); + +/* + Equal - returns TRUE if String, a, and, b, are equal. +*/ + +extern "C" unsigned int DynamicStrings_Equal (DynamicStrings_String a, DynamicStrings_String b); + +/* + EqualCharStar - returns TRUE if contents of String, s, is the same as the + string, a. +*/ + +extern "C" unsigned int DynamicStrings_EqualCharStar (DynamicStrings_String s, void * a); + +/* + EqualArray - returns TRUE if contents of String, s, is the same as the + string, a. +*/ + +extern "C" unsigned int DynamicStrings_EqualArray (DynamicStrings_String s, const char *a_, unsigned int _a_high); + +/* + Mult - returns a new string which is n concatenations of String, s. +*/ + +extern "C" DynamicStrings_String DynamicStrings_Mult (DynamicStrings_String s, unsigned int n); + +/* + Slice - returns a new string which contains the elements + low..high-1 + + strings start at element 0 + Slice(s, 0, 2) will return elements 0, 1 but not 2 + Slice(s, 1, 3) will return elements 1, 2 but not 3 + Slice(s, 2, 0) will return elements 2..max + Slice(s, 3, -1) will return elements 3..max-1 + Slice(s, 4, -2) will return elements 4..max-2 +*/ + +extern "C" DynamicStrings_String DynamicStrings_Slice (DynamicStrings_String s, int low, int high); + +/* + Index - returns the indice of the first occurance of, ch, in + String, s. -1 is returned if, ch, does not exist. + The search starts at position, o. +*/ + +extern "C" int DynamicStrings_Index (DynamicStrings_String s, char ch, unsigned int o); + +/* + RIndex - returns the indice of the last occurance of, ch, + in String, s. The search starts at position, o. + -1 is returned if, ch, is not found. +*/ + +extern "C" int DynamicStrings_RIndex (DynamicStrings_String s, char ch, unsigned int o); + +/* + RemoveComment - assuming that, comment, is a comment delimiter + which indicates anything to its right is a comment + then strip off the comment and also any white space + on the remaining right hand side. + It leaves any white space on the left hand side alone. +*/ + +extern "C" DynamicStrings_String DynamicStrings_RemoveComment (DynamicStrings_String s, char comment); + +/* + RemoveWhitePrefix - removes any leading white space from String, s. + A new string is returned. +*/ + +extern "C" DynamicStrings_String DynamicStrings_RemoveWhitePrefix (DynamicStrings_String s); + +/* + RemoveWhitePostfix - removes any leading white space from String, s. + A new string is returned. +*/ + +extern "C" DynamicStrings_String DynamicStrings_RemoveWhitePostfix (DynamicStrings_String s); + +/* + ToUpper - returns string, s, after it has had its lower case characters + replaced by upper case characters. + The string, s, is not duplicated. +*/ + +extern "C" DynamicStrings_String DynamicStrings_ToUpper (DynamicStrings_String s); + +/* + ToLower - returns string, s, after it has had its upper case characters + replaced by lower case characters. + The string, s, is not duplicated. +*/ + +extern "C" DynamicStrings_String DynamicStrings_ToLower (DynamicStrings_String s); + +/* + CopyOut - copies string, s, to a. +*/ + +extern "C" void DynamicStrings_CopyOut (char *a, unsigned int _a_high, DynamicStrings_String s); + +/* + char - returns the character, ch, at position, i, in String, s. +*/ + +extern "C" char DynamicStrings_char (DynamicStrings_String s, int i); + +/* + string - returns the C style char * of String, s. +*/ + +extern "C" void * DynamicStrings_string (DynamicStrings_String s); + +/* + InitStringDB - the debug version of InitString. +*/ + +extern "C" DynamicStrings_String DynamicStrings_InitStringDB (const char *a_, unsigned int _a_high, const char *file_, unsigned int _file_high, unsigned int line); + +/* + InitStringCharStarDB - the debug version of InitStringCharStar. +*/ + +extern "C" DynamicStrings_String DynamicStrings_InitStringCharStarDB (void * a, const char *file_, unsigned int _file_high, unsigned int line); + +/* + InitStringCharDB - the debug version of InitStringChar. +*/ + +extern "C" DynamicStrings_String DynamicStrings_InitStringCharDB (char ch, const char *file_, unsigned int _file_high, unsigned int line); + +/* + MultDB - the debug version of MultDB. +*/ + +extern "C" DynamicStrings_String DynamicStrings_MultDB (DynamicStrings_String s, unsigned int n, const char *file_, unsigned int _file_high, unsigned int line); + +/* + DupDB - the debug version of Dup. +*/ + +extern "C" DynamicStrings_String DynamicStrings_DupDB (DynamicStrings_String s, const char *file_, unsigned int _file_high, unsigned int line); + +/* + SliceDB - debug version of Slice. +*/ + +extern "C" DynamicStrings_String DynamicStrings_SliceDB (DynamicStrings_String s, int low, int high, const char *file_, unsigned int _file_high, unsigned int line); + +/* + PushAllocation - pushes the current allocation/deallocation lists. +*/ + +extern "C" void DynamicStrings_PushAllocation (void); + +/* + PopAllocation - test to see that all strings are deallocated since + the last push. Then it pops to the previous + allocation/deallocation lists. + + If halt is true then the application terminates + with an exit code of 1. +*/ + +extern "C" void DynamicStrings_PopAllocation (unsigned int halt); + +/* + PopAllocationExemption - test to see that all strings are deallocated, except + string, e, since the last push. + Then it pops to the previous allocation/deallocation + lists. + + If halt is true then the application terminates + with an exit code of 1. +*/ + +extern "C" DynamicStrings_String DynamicStrings_PopAllocationExemption (unsigned int halt, DynamicStrings_String e); + +/* + writeStringDesc write out debugging information about string, s. */ + +static void writeStringDesc (DynamicStrings_String s); + +/* + writeNspace - +*/ + +static void writeNspace (unsigned int n); + +/* + DumpStringInfo - +*/ + +static void DumpStringInfo (DynamicStrings_String s, unsigned int i); + +/* + DumpStringInfo - +*/ + +static void stop (void); + +/* + doDSdbEnter - +*/ + +static void doDSdbEnter (void); + +/* + doDSdbExit - +*/ + +static void doDSdbExit (DynamicStrings_String s); + +/* + DSdbEnter - +*/ + +static void DSdbEnter (void); + +/* + DSdbExit - +*/ + +static void DSdbExit (DynamicStrings_String s); +static unsigned int Capture (DynamicStrings_String s); + +/* + Min - +*/ + +static unsigned int Min (unsigned int a, unsigned int b); + +/* + Max - +*/ + +static unsigned int Max (unsigned int a, unsigned int b); + +/* + writeString - writes a string to stdout. +*/ + +static void writeString (const char *a_, unsigned int _a_high); + +/* + writeCstring - writes a C string to stdout. +*/ + +static void writeCstring (void * a); + +/* + writeCard - +*/ + +static void writeCard (unsigned int c); + +/* + writeLongcard - +*/ + +static void writeLongcard (long unsigned int l); + +/* + writeAddress - +*/ + +static void writeAddress (void * a); + +/* + writeLn - writes a newline. +*/ + +static void writeLn (void); + +/* + AssignDebug - assigns, file, and, line, information to string, s. +*/ + +static DynamicStrings_String AssignDebug (DynamicStrings_String s, const char *file_, unsigned int _file_high, unsigned int line, const char *proc_, unsigned int _proc_high); + +/* + IsOn - returns TRUE if, s, is on one of the debug lists. +*/ + +static unsigned int IsOn (DynamicStrings_String list, DynamicStrings_String s); + +/* + AddTo - adds string, s, to, list. +*/ + +static void AddTo (DynamicStrings_String *list, DynamicStrings_String s); + +/* + SubFrom - removes string, s, from, list. +*/ + +static void SubFrom (DynamicStrings_String *list, DynamicStrings_String s); + +/* + AddAllocated - adds string, s, to the head of the allocated list. +*/ + +static void AddAllocated (DynamicStrings_String s); + +/* + AddDeallocated - adds string, s, to the head of the deallocated list. +*/ + +static void AddDeallocated (DynamicStrings_String s); + +/* + IsOnAllocated - returns TRUE if the string, s, has ever been allocated. +*/ + +static unsigned int IsOnAllocated (DynamicStrings_String s); + +/* + IsOnDeallocated - returns TRUE if the string, s, has ever been deallocated. +*/ + +static unsigned int IsOnDeallocated (DynamicStrings_String s); + +/* + SubAllocated - removes string, s, from the list of allocated strings. +*/ + +static void SubAllocated (DynamicStrings_String s); + +/* + SubDeallocated - removes string, s, from the list of deallocated strings. +*/ + +static void SubDeallocated (DynamicStrings_String s); + +/* + SubDebugInfo - removes string, s, from the list of allocated strings. +*/ + +static void SubDebugInfo (DynamicStrings_String s); + +/* + AddDebugInfo - adds string, s, to the list of allocated strings. +*/ + +static void AddDebugInfo (DynamicStrings_String s); + +/* + ConcatContents - add the contents of string, a, where, h, is the + total length of, a. The offset is in, o. +*/ + +static void ConcatContents (DynamicStrings_Contents *c, const char *a_, unsigned int _a_high, unsigned int h, unsigned int o); + +/* + DeallocateCharStar - deallocates any charStar. +*/ + +static void DeallocateCharStar (DynamicStrings_String s); + +/* + CheckPoisoned - checks for a poisoned string, s. +*/ + +static DynamicStrings_String CheckPoisoned (DynamicStrings_String s); + +/* + MarkInvalid - marks the char * version of String, s, as invalid. +*/ + +static void MarkInvalid (DynamicStrings_String s); + +/* + ConcatContentsAddress - concatenate the string, a, where, h, is the + total length of, a. +*/ + +static void ConcatContentsAddress (DynamicStrings_Contents *c, void * a, unsigned int h); + +/* + AddToGarbage - adds String, b, onto the garbage list of, a. Providing + the state of b is marked. The state is then altered to + onlist. String, a, is returned. +*/ + +static DynamicStrings_String AddToGarbage (DynamicStrings_String a, DynamicStrings_String b); + +/* + IsOnGarbage - returns TRUE if, s, is on string, e, garbage list. +*/ + +static unsigned int IsOnGarbage (DynamicStrings_String e, DynamicStrings_String s); + +/* + IsWhite - returns TRUE if, ch, is a space or a tab. +*/ + +static unsigned int IsWhite (char ch); + +/* + DumpState - +*/ + +static void DumpState (DynamicStrings_String s); + +/* + DumpStringSynopsis - +*/ + +static void DumpStringSynopsis (DynamicStrings_String s); + +/* + DumpString - displays the contents of string, s. +*/ + +static void DumpString (DynamicStrings_String s); + +/* + Init - initialize the module. +*/ + +static void Init (void); + + +/* + writeStringDesc write out debugging information about string, s. */ + +static void writeStringDesc (DynamicStrings_String s) +{ + writeCstring (s->debug.file); + writeString ((const char *) ":", 1); + writeCard (s->debug.line); + writeString ((const char *) ":", 1); + writeCstring (s->debug.proc); + writeString ((const char *) " ", 1); + writeAddress (reinterpret_cast<void *> (s)); + writeString ((const char *) " ", 1); + switch (s->head->state) + { + case DynamicStrings_inuse: + writeString ((const char *) "still in use (", 14); + writeCard (s->contents.len); + writeString ((const char *) ") characters", 12); + break; + + case DynamicStrings_marked: + writeString ((const char *) "marked", 6); + break; + + case DynamicStrings_onlist: + writeString ((const char *) "on a (lost) garbage list", 24); + break; + + case DynamicStrings_poisoned: + writeString ((const char *) "poisoned", 8); + break; + + + default: + writeString ((const char *) "unknown state", 13); + break; + } +} + + +/* + writeNspace - +*/ + +static void writeNspace (unsigned int n) +{ + while (n > 0) + { + writeString ((const char *) " ", 1); + n -= 1; + } +} + + +/* + DumpStringInfo - +*/ + +static void DumpStringInfo (DynamicStrings_String s, unsigned int i) +{ + DynamicStrings_String t; + + if (s != NULL) + { + writeNspace (i); + writeStringDesc (s); + writeLn (); + if (s->head->garbage != NULL) + { + writeNspace (i); + writeString ((const char *) "garbage list:", 13); + writeLn (); + do { + s = s->head->garbage; + DumpStringInfo (s, i+1); + writeLn (); + } while (! (s == NULL)); + } + } +} + + +/* + DumpStringInfo - +*/ + +static void stop (void) +{ +} + + +/* + doDSdbEnter - +*/ + +static void doDSdbEnter (void) +{ + if (CheckOn) + { + DynamicStrings_PushAllocation (); + } +} + + +/* + doDSdbExit - +*/ + +static void doDSdbExit (DynamicStrings_String s) +{ + if (CheckOn) + { + s = DynamicStrings_PopAllocationExemption (TRUE, s); + } +} + + +/* + DSdbEnter - +*/ + +static void DSdbEnter (void) +{ +} + + +/* + DSdbExit - +*/ + +static void DSdbExit (DynamicStrings_String s) +{ +} + +static unsigned int Capture (DynamicStrings_String s) +{ + /* + * #undef GM2_DEBUG_DYNAMICSTINGS + * #if defined(GM2_DEBUG_DYNAMICSTINGS) + * # define DSdbEnter doDSdbEnter + * # define DSdbExit doDSdbExit + * # define CheckOn TRUE + * # define TraceOn TRUE + * #endif + */ + captured = s; + return 1; + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + Min - +*/ + +static unsigned int Min (unsigned int a, unsigned int b) +{ + if (a < b) + { + return a; + } + else + { + return b; + } + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + Max - +*/ + +static unsigned int Max (unsigned int a, unsigned int b) +{ + if (a > b) + { + return a; + } + else + { + return b; + } + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + writeString - writes a string to stdout. +*/ + +static void writeString (const char *a_, unsigned int _a_high) +{ + int i; + char a[_a_high+1]; + + /* make a local copy of each unbounded array. */ + memcpy (a, a_, _a_high+1); + + i = static_cast<int> (libc_write (1, &a, static_cast<size_t> (StrLib_StrLen ((const char *) a, _a_high)))); +} + + +/* + writeCstring - writes a C string to stdout. +*/ + +static void writeCstring (void * a) +{ + int i; + + if (a == NULL) + { + writeString ((const char *) "(null)", 6); + } + else + { + i = static_cast<int> (libc_write (1, a, libc_strlen (a))); + } +} + + +/* + writeCard - +*/ + +static void writeCard (unsigned int c) +{ + char ch; + int i; + + if (c > 9) + { + writeCard (c / 10); + writeCard (c % 10); + } + else + { + ch = ((char) ( ((unsigned int) ('0'))+c)); + i = static_cast<int> (libc_write (1, &ch, static_cast<size_t> (1))); + } +} + + +/* + writeLongcard - +*/ + +static void writeLongcard (long unsigned int l) +{ + char ch; + int i; + + if (l > 16) + { + writeLongcard (l / 16); + writeLongcard (l % 16); + } + else if (l < 10) + { + /* avoid dangling else. */ + ch = ((char) ( ((unsigned int) ('0'))+((unsigned int ) (l)))); + i = static_cast<int> (libc_write (1, &ch, static_cast<size_t> (1))); + } + else if (l < 16) + { + /* avoid dangling else. */ + ch = ((char) (( ((unsigned int) ('a'))+((unsigned int ) (l)))-10)); + i = static_cast<int> (libc_write (1, &ch, static_cast<size_t> (1))); + } +} + + +/* + writeAddress - +*/ + +static void writeAddress (void * a) +{ + writeLongcard ((long unsigned int ) (a)); +} + + +/* + writeLn - writes a newline. +*/ + +static void writeLn (void) +{ + char ch; + int i; + + ch = ASCII_lf; + i = static_cast<int> (libc_write (1, &ch, static_cast<size_t> (1))); +} + + +/* + AssignDebug - assigns, file, and, line, information to string, s. +*/ + +static DynamicStrings_String AssignDebug (DynamicStrings_String s, const char *file_, unsigned int _file_high, unsigned int line, const char *proc_, unsigned int _proc_high) +{ + void * f; + void * p; + char file[_file_high+1]; + char proc[_proc_high+1]; + + /* make a local copy of each unbounded array. */ + memcpy (file, file_, _file_high+1); + memcpy (proc, proc_, _proc_high+1); + + f = &file; + p = &proc; + Storage_ALLOCATE (&s->debug.file, (StrLib_StrLen ((const char *) file, _file_high))+1); + if ((libc_strncpy (s->debug.file, f, (StrLib_StrLen ((const char *) file, _file_high))+1)) == NULL) + {} /* empty. */ + s->debug.line = line; + Storage_ALLOCATE (&s->debug.proc, (StrLib_StrLen ((const char *) proc, _proc_high))+1); + if ((libc_strncpy (s->debug.proc, p, (StrLib_StrLen ((const char *) proc, _proc_high))+1)) == NULL) + {} /* empty. */ + return s; + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + IsOn - returns TRUE if, s, is on one of the debug lists. +*/ + +static unsigned int IsOn (DynamicStrings_String list, DynamicStrings_String s) +{ + while ((list != s) && (list != NULL)) + { + list = list->debug.next; + } + return list == s; + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + AddTo - adds string, s, to, list. +*/ + +static void AddTo (DynamicStrings_String *list, DynamicStrings_String s) +{ + if ((*list) == NULL) + { + (*list) = s; + s->debug.next = NULL; + } + else + { + s->debug.next = (*list); + (*list) = s; + } +} + + +/* + SubFrom - removes string, s, from, list. +*/ + +static void SubFrom (DynamicStrings_String *list, DynamicStrings_String s) +{ + DynamicStrings_String p; + + if ((*list) == s) + { + (*list) = s->debug.next; + } + else + { + p = (*list); + while ((p->debug.next != NULL) && (p->debug.next != s)) + { + p = p->debug.next; + } + if (p->debug.next == s) + { + p->debug.next = s->debug.next; + } + else + { + /* not found, quit */ + return ; + } + } + s->debug.next = NULL; +} + + +/* + AddAllocated - adds string, s, to the head of the allocated list. +*/ + +static void AddAllocated (DynamicStrings_String s) +{ + Init (); + AddTo (&frameHead->alloc, s); +} + + +/* + AddDeallocated - adds string, s, to the head of the deallocated list. +*/ + +static void AddDeallocated (DynamicStrings_String s) +{ + Init (); + AddTo (&frameHead->dealloc, s); +} + + +/* + IsOnAllocated - returns TRUE if the string, s, has ever been allocated. +*/ + +static unsigned int IsOnAllocated (DynamicStrings_String s) +{ + DynamicStrings_frame f; + + Init (); + f = frameHead; + do { + if (IsOn (f->alloc, s)) + { + return TRUE; + } + else + { + f = f->next; + } + } while (! (f == NULL)); + return FALSE; + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + IsOnDeallocated - returns TRUE if the string, s, has ever been deallocated. +*/ + +static unsigned int IsOnDeallocated (DynamicStrings_String s) +{ + DynamicStrings_frame f; + + Init (); + f = frameHead; + do { + if (IsOn (f->dealloc, s)) + { + return TRUE; + } + else + { + f = f->next; + } + } while (! (f == NULL)); + return FALSE; + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + SubAllocated - removes string, s, from the list of allocated strings. +*/ + +static void SubAllocated (DynamicStrings_String s) +{ + DynamicStrings_frame f; + + Init (); + f = frameHead; + do { + if (IsOn (f->alloc, s)) + { + SubFrom (&f->alloc, s); + return ; + } + else + { + f = f->next; + } + } while (! (f == NULL)); +} + + +/* + SubDeallocated - removes string, s, from the list of deallocated strings. +*/ + +static void SubDeallocated (DynamicStrings_String s) +{ + DynamicStrings_frame f; + + Init (); + f = frameHead; + do { + if (IsOn (f->dealloc, s)) + { + SubFrom (&f->dealloc, s); + return ; + } + else + { + f = f->next; + } + } while (! (f == NULL)); +} + + +/* + SubDebugInfo - removes string, s, from the list of allocated strings. +*/ + +static void SubDebugInfo (DynamicStrings_String s) +{ + if (IsOnDeallocated (s)) + { + Assertion_Assert (! DebugOn); + /* string has already been deallocated */ + return ; + } + if (IsOnAllocated (s)) + { + SubAllocated (s); + AddDeallocated (s); + } + else + { + /* string has not been allocated */ + Assertion_Assert (! DebugOn); + } +} + + +/* + AddDebugInfo - adds string, s, to the list of allocated strings. +*/ + +static void AddDebugInfo (DynamicStrings_String s) +{ + s->debug.next = NULL; + s->debug.file = NULL; + s->debug.line = 0; + s->debug.proc = NULL; + if (CheckOn) + { + AddAllocated (s); + } +} + + +/* + ConcatContents - add the contents of string, a, where, h, is the + total length of, a. The offset is in, o. +*/ + +static void ConcatContents (DynamicStrings_Contents *c, const char *a_, unsigned int _a_high, unsigned int h, unsigned int o) +{ + unsigned int i; + char a[_a_high+1]; + + /* make a local copy of each unbounded array. */ + memcpy (a, a_, _a_high+1); + + i = (*c).len; + while ((o < h) && (i < MaxBuf)) + { + (*c).buf.array[i] = a[o]; + o += 1; + i += 1; + } + if (o < h) + { + (*c).len = MaxBuf; + Storage_ALLOCATE ((void **) &(*c).next, sizeof (DynamicStrings_stringRecord)); + (*c).next->head = NULL; + (*c).next->contents.len = 0; + (*c).next->contents.next = NULL; + ConcatContents (&(*c).next->contents, (const char *) a, _a_high, h, o); + AddDebugInfo ((*c).next); + (*c).next = AssignDebug ((*c).next, (const char *) "../../gcc-git-devel-modula2/gcc/m2/gm2-libs/DynamicStrings.mod", 62, 722, (const char *) "ConcatContents", 14); + } + else + { + (*c).len = i; + } +} + + +/* + DeallocateCharStar - deallocates any charStar. +*/ + +static void DeallocateCharStar (DynamicStrings_String s) +{ + if ((s != NULL) && (s->head != NULL)) + { + if (s->head->charStarUsed && (s->head->charStar != NULL)) + { + Storage_DEALLOCATE (&s->head->charStar, s->head->charStarSize); + } + s->head->charStarUsed = FALSE; + s->head->charStar = NULL; + s->head->charStarSize = 0; + s->head->charStarValid = FALSE; + } +} + + +/* + CheckPoisoned - checks for a poisoned string, s. +*/ + +static DynamicStrings_String CheckPoisoned (DynamicStrings_String s) +{ + if (((PoisonOn && (s != NULL)) && (s->head != NULL)) && (s->head->state == DynamicStrings_poisoned)) + { + M2RTS_HALT (-1); + __builtin_unreachable (); + } + return s; + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + MarkInvalid - marks the char * version of String, s, as invalid. +*/ + +static void MarkInvalid (DynamicStrings_String s) +{ + if (PoisonOn) + { + s = CheckPoisoned (s); + } + if (s->head != NULL) + { + s->head->charStarValid = FALSE; + } +} + + +/* + ConcatContentsAddress - concatenate the string, a, where, h, is the + total length of, a. +*/ + +static void ConcatContentsAddress (DynamicStrings_Contents *c, void * a, unsigned int h) +{ + typedef char *ConcatContentsAddress__T1; + + ConcatContentsAddress__T1 p; + unsigned int i; + unsigned int j; + + j = 0; + i = (*c).len; + p = static_cast<ConcatContentsAddress__T1> (a); + while ((j < h) && (i < MaxBuf)) + { + (*c).buf.array[i] = (*p); + i += 1; + j += 1; + p += 1; + } + if (j < h) + { + /* avoid dangling else. */ + (*c).len = MaxBuf; + Storage_ALLOCATE ((void **) &(*c).next, sizeof (DynamicStrings_stringRecord)); + (*c).next->head = NULL; + (*c).next->contents.len = 0; + (*c).next->contents.next = NULL; + ConcatContentsAddress (&(*c).next->contents, reinterpret_cast<void *> (p), h-j); + AddDebugInfo ((*c).next); + if (TraceOn) + { + (*c).next = AssignDebug ((*c).next, (const char *) "../../gcc-git-devel-modula2/gcc/m2/gm2-libs/DynamicStrings.mod", 62, 917, (const char *) "ConcatContentsAddress", 21); + } + } + else + { + (*c).len = i; + (*c).next = NULL; + } +} + + +/* + AddToGarbage - adds String, b, onto the garbage list of, a. Providing + the state of b is marked. The state is then altered to + onlist. String, a, is returned. +*/ + +static DynamicStrings_String AddToGarbage (DynamicStrings_String a, DynamicStrings_String b) +{ + DynamicStrings_String c; + + if (PoisonOn) + { + a = CheckPoisoned (a); + b = CheckPoisoned (b); + } + /* + IF (a#NIL) AND (a#b) AND (a^.head^.state=marked) + THEN + writeString('warning trying to add to a marked string') ; writeLn + END ; + */ + if (((((a != b) && (a != NULL)) && (b != NULL)) && (b->head->state == DynamicStrings_marked)) && (a->head->state == DynamicStrings_inuse)) + { + c = a; + while (c->head->garbage != NULL) + { + c = c->head->garbage; + } + c->head->garbage = b; + b->head->state = DynamicStrings_onlist; + if (CheckOn) + { + SubDebugInfo (b); + } + } + return a; + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + IsOnGarbage - returns TRUE if, s, is on string, e, garbage list. +*/ + +static unsigned int IsOnGarbage (DynamicStrings_String e, DynamicStrings_String s) +{ + if ((e != NULL) && (s != NULL)) + { + while (e->head->garbage != NULL) + { + if (e->head->garbage == s) + { + return TRUE; + } + else + { + e = e->head->garbage; + } + } + } + return FALSE; + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + IsWhite - returns TRUE if, ch, is a space or a tab. +*/ + +static unsigned int IsWhite (char ch) +{ + return (ch == ' ') || (ch == ASCII_tab); + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + DumpState - +*/ + +static void DumpState (DynamicStrings_String s) +{ + switch (s->head->state) + { + case DynamicStrings_inuse: + writeString ((const char *) "still in use (", 14); + writeCard (s->contents.len); + writeString ((const char *) ") characters", 12); + break; + + case DynamicStrings_marked: + writeString ((const char *) "marked", 6); + break; + + case DynamicStrings_onlist: + writeString ((const char *) "on a garbage list", 17); + break; + + case DynamicStrings_poisoned: + writeString ((const char *) "poisoned", 8); + break; + + + default: + writeString ((const char *) "unknown state", 13); + break; + } +} + + +/* + DumpStringSynopsis - +*/ + +static void DumpStringSynopsis (DynamicStrings_String s) +{ + writeCstring (s->debug.file); + writeString ((const char *) ":", 1); + writeCard (s->debug.line); + writeString ((const char *) ":", 1); + writeCstring (s->debug.proc); + writeString ((const char *) " string ", 8); + writeAddress (reinterpret_cast<void *> (s)); + writeString ((const char *) " ", 1); + DumpState (s); + if (IsOnAllocated (s)) + { + writeString ((const char *) " globally allocated", 19); + } + else if (IsOnDeallocated (s)) + { + /* avoid dangling else. */ + writeString ((const char *) " globally deallocated", 21); + } + else + { + /* avoid dangling else. */ + writeString ((const char *) " globally unknown", 17); + } + writeLn (); +} + + +/* + DumpString - displays the contents of string, s. +*/ + +static void DumpString (DynamicStrings_String s) +{ + DynamicStrings_String t; + + if (s != NULL) + { + DumpStringSynopsis (s); + if ((s->head != NULL) && (s->head->garbage != NULL)) + { + writeString ((const char *) "display chained strings on the garbage list", 43); + writeLn (); + t = s->head->garbage; + while (t != NULL) + { + DumpStringSynopsis (t); + t = t->head->garbage; + } + } + } +} + + +/* + Init - initialize the module. +*/ + +static void Init (void) +{ + if (! Initialized) + { + Initialized = TRUE; + frameHead = NULL; + DynamicStrings_PushAllocation (); + } +} + + +/* + InitString - creates and returns a String type object. + Initial contents are, a. +*/ + +extern "C" DynamicStrings_String DynamicStrings_InitString (const char *a_, unsigned int _a_high) +{ + DynamicStrings_String s; + char a[_a_high+1]; + + /* make a local copy of each unbounded array. */ + memcpy (a, a_, _a_high+1); + + Storage_ALLOCATE ((void **) &s, sizeof (DynamicStrings_stringRecord)); + s->contents.len = 0; + s->contents.next = NULL; + ConcatContents (&s->contents, (const char *) a, _a_high, StrLib_StrLen ((const char *) a, _a_high), 0); + Storage_ALLOCATE ((void **) &s->head, sizeof (DynamicStrings_descriptor)); + s->head->charStarUsed = FALSE; + s->head->charStar = NULL; + s->head->charStarSize = 0; + s->head->charStarValid = FALSE; + s->head->garbage = NULL; + s->head->state = DynamicStrings_inuse; + AddDebugInfo (s); + if (TraceOn) + { + s = AssignDebug (s, (const char *) "../../gcc-git-devel-modula2/gcc/m2/gm2-libs/DynamicStrings.mod", 62, 758, (const char *) "InitString", 10); + } + return s; + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + KillString - frees String, s, and its contents. + NIL is returned. +*/ + +extern "C" DynamicStrings_String DynamicStrings_KillString (DynamicStrings_String s) +{ + DynamicStrings_String t; + + if (PoisonOn) + { + s = CheckPoisoned (s); + } + if (s != NULL) + { + if (CheckOn) + { + /* avoid gcc warning by using compound statement even if not strictly necessary. */ + if (IsOnAllocated (s)) + { + SubAllocated (s); + } + else if (IsOnDeallocated (s)) + { + /* avoid dangling else. */ + SubDeallocated (s); + } + } + if (s->head != NULL) + { + s->head->state = DynamicStrings_poisoned; + s->head->garbage = DynamicStrings_KillString (s->head->garbage); + if (! PoisonOn) + { + DeallocateCharStar (s); + } + if (! PoisonOn) + { + Storage_DEALLOCATE ((void **) &s->head, sizeof (DynamicStrings_descriptor)); + s->head = NULL; + } + } + t = DynamicStrings_KillString (s->contents.next); + if (! PoisonOn) + { + Storage_DEALLOCATE ((void **) &s, sizeof (DynamicStrings_stringRecord)); + } + } + return NULL; + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + Fin - finishes with a string, it calls KillString with, s. + The purpose of the procedure is to provide a short cut + to calling KillString and then testing the return result. +*/ + +extern "C" void DynamicStrings_Fin (DynamicStrings_String s) +{ + if ((DynamicStrings_KillString (s)) != NULL) + { + M2RTS_HALT (-1); + __builtin_unreachable (); + } +} + + +/* + InitStringCharStar - initializes and returns a String to contain the C string. +*/ + +extern "C" DynamicStrings_String DynamicStrings_InitStringCharStar (void * a) +{ + DynamicStrings_String s; + + Storage_ALLOCATE ((void **) &s, sizeof (DynamicStrings_stringRecord)); + s->contents.len = 0; + s->contents.next = NULL; + if (a != NULL) + { + ConcatContentsAddress (&s->contents, a, static_cast<unsigned int> (libc_strlen (a))); + } + Storage_ALLOCATE ((void **) &s->head, sizeof (DynamicStrings_descriptor)); + s->head->charStarUsed = FALSE; + s->head->charStar = NULL; + s->head->charStarSize = 0; + s->head->charStarValid = FALSE; + s->head->garbage = NULL; + s->head->state = DynamicStrings_inuse; + AddDebugInfo (s); + if (TraceOn) + { + s = AssignDebug (s, (const char *) "../../gcc-git-devel-modula2/gcc/m2/gm2-libs/DynamicStrings.mod", 62, 957, (const char *) "InitStringCharStar", 18); + } + return s; + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + InitStringChar - initializes and returns a String to contain the single character, ch. +*/ + +extern "C" DynamicStrings_String DynamicStrings_InitStringChar (char ch) +{ + typedef struct InitStringChar__T4_a InitStringChar__T4; + + struct InitStringChar__T4_a { char array[1+1]; }; + InitStringChar__T4 a; + DynamicStrings_String s; + + a.array[0] = ch; + a.array[1] = ASCII_nul; + s = DynamicStrings_InitString ((const char *) &a.array[0], 1); + if (TraceOn) + { + s = AssignDebug (s, (const char *) "../../gcc-git-devel-modula2/gcc/m2/gm2-libs/DynamicStrings.mod", 62, 977, (const char *) "InitStringChar", 14); + } + return s; + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + Mark - marks String, s, ready for garbage collection. +*/ + +extern "C" DynamicStrings_String DynamicStrings_Mark (DynamicStrings_String s) +{ + if (PoisonOn) + { + s = CheckPoisoned (s); + } + if ((s != NULL) && (s->head->state == DynamicStrings_inuse)) + { + s->head->state = DynamicStrings_marked; + } + return s; + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + Length - returns the length of the String, s. +*/ + +extern "C" unsigned int DynamicStrings_Length (DynamicStrings_String s) +{ + if (s == NULL) + { + return 0; + } + else + { + return s->contents.len+(DynamicStrings_Length (s->contents.next)); + } + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + ConCat - returns String, a, after the contents of, b, have been appended. +*/ + +extern "C" DynamicStrings_String DynamicStrings_ConCat (DynamicStrings_String a, DynamicStrings_String b) +{ + DynamicStrings_String t; + + if (PoisonOn) + { + a = CheckPoisoned (a); + b = CheckPoisoned (b); + } + if (a == b) + { + return DynamicStrings_ConCat (a, DynamicStrings_Mark (DynamicStrings_Dup (b))); + } + else if (a != NULL) + { + /* avoid dangling else. */ + a = AddToGarbage (a, b); + MarkInvalid (a); + t = a; + while (b != NULL) + { + while ((t->contents.len == MaxBuf) && (t->contents.next != NULL)) + { + t = t->contents.next; + } + ConcatContents (&t->contents, (const char *) &b->contents.buf.array[0], (MaxBuf-1), b->contents.len, 0); + b = b->contents.next; + } + } + if ((a == NULL) && (b != NULL)) + { + M2RTS_HALT (-1); + __builtin_unreachable (); + } + return a; + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + ConCatChar - returns String, a, after character, ch, has been appended. +*/ + +extern "C" DynamicStrings_String DynamicStrings_ConCatChar (DynamicStrings_String a, char ch) +{ + typedef struct ConCatChar__T5_a ConCatChar__T5; + + struct ConCatChar__T5_a { char array[1+1]; }; + ConCatChar__T5 b; + DynamicStrings_String t; + + if (PoisonOn) + { + a = CheckPoisoned (a); + } + b.array[0] = ch; + b.array[1] = ASCII_nul; + t = a; + MarkInvalid (a); + while ((t->contents.len == MaxBuf) && (t->contents.next != NULL)) + { + t = t->contents.next; + } + ConcatContents (&t->contents, (const char *) &b.array[0], 1, 1, 0); + return a; + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + Assign - assigns the contents of, b, into, a. + String, a, is returned. +*/ + +extern "C" DynamicStrings_String DynamicStrings_Assign (DynamicStrings_String a, DynamicStrings_String b) +{ + if (PoisonOn) + { + a = CheckPoisoned (a); + b = CheckPoisoned (b); + } + if ((a != NULL) && (b != NULL)) + { + a->contents.next = DynamicStrings_KillString (a->contents.next); + a->contents.len = 0; + } + return DynamicStrings_ConCat (a, b); + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + Dup - duplicate a String, s, returning the copy of s. +*/ + +extern "C" DynamicStrings_String DynamicStrings_Dup (DynamicStrings_String s) +{ + if (PoisonOn) + { + s = CheckPoisoned (s); + } + s = DynamicStrings_Assign (DynamicStrings_InitString ((const char *) "", 0), s); + if (TraceOn) + { + s = AssignDebug (s, (const char *) "../../gcc-git-devel-modula2/gcc/m2/gm2-libs/DynamicStrings.mod", 62, 1173, (const char *) "Dup", 3); + } + return s; + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + Add - returns a new String which contains the contents of a and b. +*/ + +extern "C" DynamicStrings_String DynamicStrings_Add (DynamicStrings_String a, DynamicStrings_String b) +{ + if (PoisonOn) + { + a = CheckPoisoned (a); + b = CheckPoisoned (b); + } + a = DynamicStrings_ConCat (DynamicStrings_ConCat (DynamicStrings_InitString ((const char *) "", 0), a), b); + if (TraceOn) + { + a = AssignDebug (a, (const char *) "../../gcc-git-devel-modula2/gcc/m2/gm2-libs/DynamicStrings.mod", 62, 1193, (const char *) "Add", 3); + } + return a; + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + Equal - returns TRUE if String, a, and, b, are equal. +*/ + +extern "C" unsigned int DynamicStrings_Equal (DynamicStrings_String a, DynamicStrings_String b) +{ + unsigned int i; + + if (PoisonOn) + { + a = CheckPoisoned (a); + b = CheckPoisoned (b); + } + if ((DynamicStrings_Length (a)) == (DynamicStrings_Length (b))) + { + while ((a != NULL) && (b != NULL)) + { + i = 0; + Assertion_Assert (a->contents.len == b->contents.len); + while (i < a->contents.len) + { + if (a->contents.buf.array[i] != a->contents.buf.array[i]) + { + M2RTS_HALT (-1); + __builtin_unreachable (); + } + if (b->contents.buf.array[i] != b->contents.buf.array[i]) + { + M2RTS_HALT (-1); + __builtin_unreachable (); + } + if (a->contents.buf.array[i] != b->contents.buf.array[i]) + { + return FALSE; + } + i += 1; + } + a = a->contents.next; + b = b->contents.next; + } + return TRUE; + } + else + { + return FALSE; + } + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + EqualCharStar - returns TRUE if contents of String, s, is the same as the + string, a. +*/ + +extern "C" unsigned int DynamicStrings_EqualCharStar (DynamicStrings_String s, void * a) +{ + DynamicStrings_String t; + + if (PoisonOn) + { + s = CheckPoisoned (s); + } + t = DynamicStrings_InitStringCharStar (a); + if (TraceOn) + { + t = AssignDebug (t, (const char *) "../../gcc-git-devel-modula2/gcc/m2/gm2-libs/DynamicStrings.mod", 62, 1258, (const char *) "EqualCharStar", 13); + } + t = AddToGarbage (t, s); + if (DynamicStrings_Equal (t, s)) + { + t = DynamicStrings_KillString (t); + return TRUE; + } + else + { + t = DynamicStrings_KillString (t); + return FALSE; + } + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + EqualArray - returns TRUE if contents of String, s, is the same as the + string, a. +*/ + +extern "C" unsigned int DynamicStrings_EqualArray (DynamicStrings_String s, const char *a_, unsigned int _a_high) +{ + DynamicStrings_String t; + char a[_a_high+1]; + + /* make a local copy of each unbounded array. */ + memcpy (a, a_, _a_high+1); + + if (PoisonOn) + { + s = CheckPoisoned (s); + } + t = DynamicStrings_InitString ((const char *) a, _a_high); + if (TraceOn) + { + t = AssignDebug (t, (const char *) "../../gcc-git-devel-modula2/gcc/m2/gm2-libs/DynamicStrings.mod", 62, 1288, (const char *) "EqualArray", 10); + } + t = AddToGarbage (t, s); + if (DynamicStrings_Equal (t, s)) + { + t = DynamicStrings_KillString (t); + return TRUE; + } + else + { + t = DynamicStrings_KillString (t); + return FALSE; + } + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + Mult - returns a new string which is n concatenations of String, s. +*/ + +extern "C" DynamicStrings_String DynamicStrings_Mult (DynamicStrings_String s, unsigned int n) +{ + if (PoisonOn) + { + s = CheckPoisoned (s); + } + if (n <= 0) + { + s = AddToGarbage (DynamicStrings_InitString ((const char *) "", 0), s); + } + else + { + s = DynamicStrings_ConCat (DynamicStrings_Mult (s, n-1), s); + } + if (TraceOn) + { + s = AssignDebug (s, (const char *) "../../gcc-git-devel-modula2/gcc/m2/gm2-libs/DynamicStrings.mod", 62, 1320, (const char *) "Mult", 4); + } + return s; + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + Slice - returns a new string which contains the elements + low..high-1 + + strings start at element 0 + Slice(s, 0, 2) will return elements 0, 1 but not 2 + Slice(s, 1, 3) will return elements 1, 2 but not 3 + Slice(s, 2, 0) will return elements 2..max + Slice(s, 3, -1) will return elements 3..max-1 + Slice(s, 4, -2) will return elements 4..max-2 +*/ + +extern "C" DynamicStrings_String DynamicStrings_Slice (DynamicStrings_String s, int low, int high) +{ + DynamicStrings_String d; + DynamicStrings_String t; + int start; + int end; + int o; + + if (PoisonOn) + { + s = CheckPoisoned (s); + } + if (low < 0) + { + low = ((int ) (DynamicStrings_Length (s)))+low; + } + if (high <= 0) + { + high = ((int ) (DynamicStrings_Length (s)))+high; + } + else + { + /* make sure high is <= Length (s) */ + high = Min (DynamicStrings_Length (s), static_cast<unsigned int> (high)); + } + d = DynamicStrings_InitString ((const char *) "", 0); + d = AddToGarbage (d, s); + o = 0; + t = d; + while (s != NULL) + { + if (low < (o+((int ) (s->contents.len)))) + { + if (o > high) + { + s = NULL; + } + else + { + /* found sliceable unit */ + if (low < o) + { + start = 0; + } + else + { + start = low-o; + } + end = Max (Min (MaxBuf, static_cast<unsigned int> (high-o)), 0); + while (t->contents.len == MaxBuf) + { + if (t->contents.next == NULL) + { + Storage_ALLOCATE ((void **) &t->contents.next, sizeof (DynamicStrings_stringRecord)); + t->contents.next->head = NULL; + t->contents.next->contents.len = 0; + AddDebugInfo (t->contents.next); + if (TraceOn) + { + t->contents.next = AssignDebug (t->contents.next, (const char *) "../../gcc-git-devel-modula2/gcc/m2/gm2-libs/DynamicStrings.mod", 62, 1388, (const char *) "Slice", 5); + } + } + t = t->contents.next; + } + ConcatContentsAddress (&t->contents, &s->contents.buf.array[start], static_cast<unsigned int> (end-start)); + o += s->contents.len; + s = s->contents.next; + } + } + else + { + o += s->contents.len; + s = s->contents.next; + } + } + if (TraceOn) + { + d = AssignDebug (d, (const char *) "../../gcc-git-devel-modula2/gcc/m2/gm2-libs/DynamicStrings.mod", 62, 1405, (const char *) "Slice", 5); + } + return d; + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + Index - returns the indice of the first occurance of, ch, in + String, s. -1 is returned if, ch, does not exist. + The search starts at position, o. +*/ + +extern "C" int DynamicStrings_Index (DynamicStrings_String s, char ch, unsigned int o) +{ + unsigned int i; + unsigned int k; + + if (PoisonOn) + { + s = CheckPoisoned (s); + } + k = 0; + while (s != NULL) + { + if ((k+s->contents.len) < o) + { + k += s->contents.len; + } + else + { + i = o-k; + while (i < s->contents.len) + { + if (s->contents.buf.array[i] == ch) + { + return k+i; + } + i += 1; + } + k += i; + o = k; + } + s = s->contents.next; + } + return -1; + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + RIndex - returns the indice of the last occurance of, ch, + in String, s. The search starts at position, o. + -1 is returned if, ch, is not found. +*/ + +extern "C" int DynamicStrings_RIndex (DynamicStrings_String s, char ch, unsigned int o) +{ + unsigned int i; + unsigned int k; + int j; + + if (PoisonOn) + { + s = CheckPoisoned (s); + } + j = -1; + k = 0; + while (s != NULL) + { + if ((k+s->contents.len) < o) + { + k += s->contents.len; + } + else + { + if (o < k) + { + i = 0; + } + else + { + i = o-k; + } + while (i < s->contents.len) + { + if (s->contents.buf.array[i] == ch) + { + j = k; + } + k += 1; + i += 1; + } + } + s = s->contents.next; + } + return j; + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + RemoveComment - assuming that, comment, is a comment delimiter + which indicates anything to its right is a comment + then strip off the comment and also any white space + on the remaining right hand side. + It leaves any white space on the left hand side alone. +*/ + +extern "C" DynamicStrings_String DynamicStrings_RemoveComment (DynamicStrings_String s, char comment) +{ + int i; + + i = DynamicStrings_Index (s, comment, 0); + if (i == 0) + { + s = DynamicStrings_InitString ((const char *) "", 0); + } + else if (i > 0) + { + /* avoid dangling else. */ + s = DynamicStrings_RemoveWhitePostfix (DynamicStrings_Slice (DynamicStrings_Mark (s), 0, i)); + } + if (TraceOn) + { + s = AssignDebug (s, (const char *) "../../gcc-git-devel-modula2/gcc/m2/gm2-libs/DynamicStrings.mod", 62, 1517, (const char *) "RemoveComment", 13); + } + return s; + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + RemoveWhitePrefix - removes any leading white space from String, s. + A new string is returned. +*/ + +extern "C" DynamicStrings_String DynamicStrings_RemoveWhitePrefix (DynamicStrings_String s) +{ + unsigned int i; + + i = 0; + while (IsWhite (DynamicStrings_char (s, static_cast<int> (i)))) + { + i += 1; + } + s = DynamicStrings_Slice (s, (int ) (i), 0); + if (TraceOn) + { + s = AssignDebug (s, (const char *) "../../gcc-git-devel-modula2/gcc/m2/gm2-libs/DynamicStrings.mod", 62, 1629, (const char *) "RemoveWhitePrefix", 17); + } + return s; + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + RemoveWhitePostfix - removes any leading white space from String, s. + A new string is returned. +*/ + +extern "C" DynamicStrings_String DynamicStrings_RemoveWhitePostfix (DynamicStrings_String s) +{ + int i; + + i = ((int ) (DynamicStrings_Length (s)))-1; + while ((i >= 0) && (IsWhite (DynamicStrings_char (s, i)))) + { + i -= 1; + } + s = DynamicStrings_Slice (s, 0, i+1); + if (TraceOn) + { + s = AssignDebug (s, (const char *) "../../gcc-git-devel-modula2/gcc/m2/gm2-libs/DynamicStrings.mod", 62, 1651, (const char *) "RemoveWhitePostfix", 18); + } + return s; + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + ToUpper - returns string, s, after it has had its lower case characters + replaced by upper case characters. + The string, s, is not duplicated. +*/ + +extern "C" DynamicStrings_String DynamicStrings_ToUpper (DynamicStrings_String s) +{ + char ch; + unsigned int i; + DynamicStrings_String t; + + if (s != NULL) + { + MarkInvalid (s); + t = s; + while (t != NULL) + { + i = 0; + while (i < t->contents.len) + { + ch = t->contents.buf.array[i]; + if ((ch >= 'a') && (ch <= 'z')) + { + t->contents.buf.array[i] = ((char) (( ((unsigned int) (ch))- ((unsigned int) ('a')))+ ((unsigned int) ('A')))); + } + i += 1; + } + t = t->contents.next; + } + } + return s; + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + ToLower - returns string, s, after it has had its upper case characters + replaced by lower case characters. + The string, s, is not duplicated. +*/ + +extern "C" DynamicStrings_String DynamicStrings_ToLower (DynamicStrings_String s) +{ + char ch; + unsigned int i; + DynamicStrings_String t; + + if (s != NULL) + { + MarkInvalid (s); + t = s; + while (t != NULL) + { + i = 0; + while (i < t->contents.len) + { + ch = t->contents.buf.array[i]; + if ((ch >= 'A') && (ch <= 'Z')) + { + t->contents.buf.array[i] = ((char) (( ((unsigned int) (ch))- ((unsigned int) ('A')))+ ((unsigned int) ('a')))); + } + i += 1; + } + t = t->contents.next; + } + } + return s; + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + CopyOut - copies string, s, to a. +*/ + +extern "C" void DynamicStrings_CopyOut (char *a, unsigned int _a_high, DynamicStrings_String s) +{ + unsigned int i; + unsigned int l; + + l = Min (_a_high+1, DynamicStrings_Length (s)); + i = 0; + while (i < l) + { + a[i] = DynamicStrings_char (s, static_cast<int> (i)); + i += 1; + } + if (i <= _a_high) + { + a[i] = ASCII_nul; + } +} + + +/* + char - returns the character, ch, at position, i, in String, s. +*/ + +extern "C" char DynamicStrings_char (DynamicStrings_String s, int i) +{ + unsigned int c; + + if (PoisonOn) + { + s = CheckPoisoned (s); + } + if (i < 0) + { + c = (unsigned int ) (((int ) (DynamicStrings_Length (s)))+i); + } + else + { + c = i; + } + while ((s != NULL) && (c >= s->contents.len)) + { + c -= s->contents.len; + s = s->contents.next; + } + if ((s == NULL) || (c >= s->contents.len)) + { + return ASCII_nul; + } + else + { + return s->contents.buf.array[c]; + } + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + string - returns the C style char * of String, s. +*/ + +extern "C" void * DynamicStrings_string (DynamicStrings_String s) +{ + typedef char *string__T2; + + DynamicStrings_String a; + unsigned int l; + unsigned int i; + string__T2 p; + + if (PoisonOn) + { + s = CheckPoisoned (s); + } + if (s == NULL) + { + return NULL; + } + else + { + if (! s->head->charStarValid) + { + l = DynamicStrings_Length (s); + if (! (s->head->charStarUsed && (s->head->charStarSize > l))) + { + DeallocateCharStar (s); + Storage_ALLOCATE (&s->head->charStar, l+1); + s->head->charStarSize = l+1; + s->head->charStarUsed = TRUE; + } + p = static_cast<string__T2> (s->head->charStar); + a = s; + while (a != NULL) + { + i = 0; + while (i < a->contents.len) + { + (*p) = a->contents.buf.array[i]; + i += 1; + p += 1; + } + a = a->contents.next; + } + (*p) = ASCII_nul; + s->head->charStarValid = TRUE; + } + return s->head->charStar; + } + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + InitStringDB - the debug version of InitString. +*/ + +extern "C" DynamicStrings_String DynamicStrings_InitStringDB (const char *a_, unsigned int _a_high, const char *file_, unsigned int _file_high, unsigned int line) +{ + char a[_a_high+1]; + char file[_file_high+1]; + + /* make a local copy of each unbounded array. */ + memcpy (a, a_, _a_high+1); + memcpy (file, file_, _file_high+1); + + return AssignDebug (DynamicStrings_InitString ((const char *) a, _a_high), (const char *) file, _file_high, line, (const char *) "InitString", 10); + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + InitStringCharStarDB - the debug version of InitStringCharStar. +*/ + +extern "C" DynamicStrings_String DynamicStrings_InitStringCharStarDB (void * a, const char *file_, unsigned int _file_high, unsigned int line) +{ + char file[_file_high+1]; + + /* make a local copy of each unbounded array. */ + memcpy (file, file_, _file_high+1); + + return AssignDebug (DynamicStrings_InitStringCharStar (a), (const char *) file, _file_high, line, (const char *) "InitStringCharStar", 18); + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + InitStringCharDB - the debug version of InitStringChar. +*/ + +extern "C" DynamicStrings_String DynamicStrings_InitStringCharDB (char ch, const char *file_, unsigned int _file_high, unsigned int line) +{ + char file[_file_high+1]; + + /* make a local copy of each unbounded array. */ + memcpy (file, file_, _file_high+1); + + return AssignDebug (DynamicStrings_InitStringChar (ch), (const char *) file, _file_high, line, (const char *) "InitStringChar", 14); + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + MultDB - the debug version of MultDB. +*/ + +extern "C" DynamicStrings_String DynamicStrings_MultDB (DynamicStrings_String s, unsigned int n, const char *file_, unsigned int _file_high, unsigned int line) +{ + char file[_file_high+1]; + + /* make a local copy of each unbounded array. */ + memcpy (file, file_, _file_high+1); + + return AssignDebug (DynamicStrings_Mult (s, n), (const char *) file, _file_high, line, (const char *) "Mult", 4); + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + DupDB - the debug version of Dup. +*/ + +extern "C" DynamicStrings_String DynamicStrings_DupDB (DynamicStrings_String s, const char *file_, unsigned int _file_high, unsigned int line) +{ + char file[_file_high+1]; + + /* make a local copy of each unbounded array. */ + memcpy (file, file_, _file_high+1); + + return AssignDebug (DynamicStrings_Dup (s), (const char *) file, _file_high, line, (const char *) "Dup", 3); + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + SliceDB - debug version of Slice. +*/ + +extern "C" DynamicStrings_String DynamicStrings_SliceDB (DynamicStrings_String s, int low, int high, const char *file_, unsigned int _file_high, unsigned int line) +{ + char file[_file_high+1]; + + /* make a local copy of each unbounded array. */ + memcpy (file, file_, _file_high+1); + + DSdbEnter (); + s = AssignDebug (DynamicStrings_Slice (s, low, high), (const char *) file, _file_high, line, (const char *) "Slice", 5); + DSdbExit (s); + return s; + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + + +/* + PushAllocation - pushes the current allocation/deallocation lists. +*/ + +extern "C" void DynamicStrings_PushAllocation (void) +{ + DynamicStrings_frame f; + + if (CheckOn) + { + Init (); + Storage_ALLOCATE ((void **) &f, sizeof (DynamicStrings_frameRec)); + f->next = frameHead; + f->alloc = NULL; + f->dealloc = NULL; + frameHead = f; + } +} + + +/* + PopAllocation - test to see that all strings are deallocated since + the last push. Then it pops to the previous + allocation/deallocation lists. + + If halt is true then the application terminates + with an exit code of 1. +*/ + +extern "C" void DynamicStrings_PopAllocation (unsigned int halt) +{ + if (CheckOn) + { + if ((DynamicStrings_PopAllocationExemption (halt, NULL)) == NULL) + {} /* empty. */ + } +} + + +/* + PopAllocationExemption - test to see that all strings are deallocated, except + string, e, since the last push. + Then it pops to the previous allocation/deallocation + lists. + + If halt is true then the application terminates + with an exit code of 1. +*/ + +extern "C" DynamicStrings_String DynamicStrings_PopAllocationExemption (unsigned int halt, DynamicStrings_String e) +{ + DynamicStrings_String s; + DynamicStrings_frame f; + unsigned int b; + + Init (); + if (CheckOn) + { + /* avoid gcc warning by using compound statement even if not strictly necessary. */ + if (frameHead == NULL) + { + stop (); + /* writeString ("mismatched number of PopAllocation's compared to PushAllocation's") */ + M2RTS_Halt ((const char *) "../../gcc-git-devel-modula2/gcc/m2/gm2-libs/DynamicStrings.mod", 62, 176, (const char *) "PopAllocationExemption", 22, (const char *) "mismatched number of PopAllocation's compared to PushAllocation's", 65); + } + else + { + if (frameHead->alloc != NULL) + { + b = FALSE; + s = frameHead->alloc; + while (s != NULL) + { + if (! (((e == s) || (IsOnGarbage (e, s))) || (IsOnGarbage (s, e)))) + { + if (! b) + { + writeString ((const char *) "the following strings have been lost", 36); + writeLn (); + b = TRUE; + } + DumpStringInfo (s, 0); + } + s = s->debug.next; + } + if (b && halt) + { + libc_exit (1); + } + } + frameHead = frameHead->next; + } + } + return e; + /* static analysis guarentees a RETURN statement will be used before here. */ + __builtin_unreachable (); +} + +extern "C" void _M2_DynamicStrings_init (__attribute__((unused)) int argc,__attribute__((unused)) char *argv[],__attribute__((unused)) char *envp[]) +{ + Initialized = FALSE; + Init (); +} + +extern "C" void _M2_DynamicStrings_finish (__attribute__((unused)) int argc,__attribute__((unused)) char *argv[],__attribute__((unused)) char *envp[]) +{ +} |