' PARSSTR%(2.0)  Parse Charact String into Sub Str Array   01/19/1996-05/12/2010
' ------------------------------------------------------------------------------
' Copyright (C) 1996-2010 by Vladimir Veytsel                      www.davar.net

' Type -------------------------------------------------------------------------

'    Function [actionable]

' Description ------------------------------------------------------------------

'    PARSSTR% function parses its first character string parameter into array
'    of substrings specified by its second parameter, using its third parameter
'    as a delimiter of substrings, and returns the actual number of resultant
'    substrings parsed into the array.

' Declaration ------------------------------------------------------------------

'    DECLARE FUNCTION PARSSTR%(Strng$,SubStr$(),Delim$)

' Parameters -------------------------------------------------------------------

'    Strng$   - Character string to be parsed
'    SubStr$  - Array of substrings for parsed values
'    Delim$   - Delimiter to be used for parsing

' Action -----------------------------------------------------------------------

'    Input string is parsed into specified array of substrings.

' Value ------------------------------------------------------------------------

'  - Actual number of parsed substrings in substring array.

'  - IF input string is EMPTY;
'       THEN returned number of parsed substrings is 0.

'  - IF delimiter is not found in input string,
'       THEN first array element contains entire input string.

'  - IF max number of substring array elements is LESS than number of substrings,
'       THEN returned number of parsed substrings is NEGATIVE
'       (last array element contains in this case entire tail of input string).

'  - IF max number of substring array elements is GREATER than number of substrings,
'       THEN REMAINING array elements contain EMPTY strings.

' Notes ------------------------------------------------------------------------

'  - IF Delim$ parameter is EMPTY,
'       THEN input string to be parsed is checked for presence of ",":
'            IF "," is found in input string
'               THEN "," is taken as substring delimiter;
'               ELSE " " is taken as substring delimiter.

'  - IF Delim$ parameter string is longer than 1,
'       THEN FIRST symbol is taken as delimiter (all other are ignored).

'  - IF Delim$ parameter value is "*" (self-defined),
'       THEN FIRST symbol of string to be parsed is taken as delimiter.

'  - IF Delim$ parameter value is "?" (conditional),
'       THEN parsing delimiter selection logic depends on a value 
'            of the FIRST symbol of string to be parsed.
'            IF first symbol is either DIGIT or CHARACTER,
'               THEN rules for EMPTY        Delim$ parameter are applied;
'               ELSE rules for SELF-DEFINED Delim$ parameter are applied.

'  - IF " " is NOT specified, but is taken by default as substring delimiter,
'       THEN all successive SPACEs in each space group of string to be parsed
'            are compressed to a single space.
'    This enables parameter alignment in batch files, when this is convenient.

'  - IF " " IS explicitly specified to be used as a delimiter,
'       THEN no compression of successive SPACEs is performed.

'    This puts explicit " " delimiter on the same footing with any other symbol,
'    which turns out to be important for PARSSTR usage in CONVSCR, enabling to
'    pass in its second parameter virtually anything (See CONVSCR for details).

' Examples (for DIM SubStr(3) Array) -------------------------------------------

'    PARSSTR%(""             ,SubStr$(),"." )= 0   SubStr$()="","",""
'    PARSSTR%("A,BC,DEF"     ,SubStr$(),""  )= 3   SubStr$()="A","BC","DEF"
'    PARSSTR%("A BC DEF"     ,SubStr$(),""  )= 3   SubStr$()="A","BC","DEF"
'    PARSSTR%("A  BC   DEF"  ,SubStr$(),""  )= 3   SubStr$()="A","BC","DEF"
'    PARSSTR%("A"            ,SubStr$(),"." )= 1   SubStr$()="A","",""
'    PARSSTR%("A."           ,SubStr$(),"." )= 2   SubStr$()="A","",""
'    PARSSTR%("A.BC"         ,SubStr$(),"." )= 2   SubStr$()="A","BC",""
'    PARSSTR%("A.BC.DEF"     ,SubStr$(),"." )= 3   SubStr$()="A","BC","DEF"
'    PARSSTR%("A.BC.DEF."    ,SubStr$(),".:")=-3   SubStr$()="A","BC","DEF."
'    PARSSTR%(".A.BC.DEF"    ,SubStr$(),"*" )= 3   SubStr$()="A","BC","DEF"
'    PARSSTR%(" A BC DEF   " ,SubStr$()," " )=-3   SubStr$()="A","BC","DEF   "
'    PARSSTR%("1,23,456"     ,SubStr$(),"?" )= 3   SubStr$()="1","23","456"
'    PARSSTR%("A BC DEF"     ,SubStr$(),"?" )= 3   SubStr$()="A","BC","DEF"
'    PARSSTR%("a  bc   def"  ,SubStr$(),"?" )= 3   SubStr$()="a","bc","def"
'    PARSSTR%(".A.BC.DEF"    ,SubStr$(),"?" )= 3   SubStr$()="A","BC","DEF"
'    PARSSTR%("A.BC.DEF.GHIJ",SubStr$(),"." )=-3   SubStr$()="A","BC","DEF.GHIJ"
'    PARSSTR%("A.BC.DEF.GHIJ",SubStr$(),":" )= 1   SubStr$()="A.BC.DEF.GHIJ","",""

' External Function ------------------------------------------------------------

     #INCLUDE ONCE "COMPRES"

' Start Function ---------------------------------------------------------------

     DEFINT A-Z  ' All defaulted variables are integer

     FUNCTION PARSSTR%(Strng$,SubStr$(),Delim$)

' Constant ---------------------------------------------------------------------

     Digits_Chars$="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"

' Copy Modifiable Parameters Into Working Variables ----------------------------

     Work_Delim$=Delim$
     Work_Strng$=Strng$

' Form Actual Delimiter for Input String Parsing -------------------------------

     Work_Delim$=LEFT$(Work_Delim$,1)
     IF (Work_Delim$="?") THEN  ' Conditional delimiting
        IF (VERIFY(LEFT$(Work_Strng$,1),Digits_Chars$)=0) THEN
           Work_Delim$=""
        ELSE
           Work_Delim$="*"
        END IF
     END IF

     IF (LEN(Work_Delim$)>0) THEN
        IF (Work_Delim$="*") THEN
           Work_Delim$=LEFT$(Work_Strng$,1)
           Work_Strng$=MID$(Work_Strng$,2)
        END IF
     ELSE
        IF (INSTR(Work_Strng$,",")>0) THEN
           Work_Delim$=","  ' String does    contain ","
        ELSE
           Work_Delim$=" "  ' String doesn't contain ","
        END IF
     END IF

     IF ((     Delim$<>" ")  AND _
         (Work_Delim$ =" ")) THEN 
        Work_Strng$=COMPRES$(Work_Strng$," ")
     END IF

' Parse String into SubString Array Using Actual Delimiter ---------------------

     SubStrings=UBOUND(SubStr$)
     IF (LEN(Work_Strng$)=0) THEN
        Act_SubStrs=0
     ELSE
        Delimiters=TALLY(Work_Strng$,Work_Delim$)+1
        IF (Delimiters=0) THEN
           SubStr$(1)=Work_Strng$ :I=2
        ELSE
           Act_SubStrs=MIN(SubStrings,Delimiters)
           Work_Strng$=Work_Strng$+Work_Delim$    ' Add post-last delimiter
           FOR I=1 TO Act_SubStrs
               J=INSTR(Work_Strng$,Work_Delim$)   ' Find next delimiter
               SubStr$(I)=LEFT$(Work_Strng$,J-1)  ' Get next substring
               Work_Strng$=MID$(Work_Strng$,J+1)  ' Trim current substring
           NEXT I
        END IF
     END IF

' Empty Remaining SubString Array Elements (if Any) ----------------------------

     FOR I=MAX(1,I) TO SubStrings
         SubStr$(I)=""
     NEXT I

' Adjustment when Array Dimensions is Less Than Number of SubStrings -----------

     IF (SubStrings<Delimiters) THEN
        SubStr$(SubStrings)=SubStr$(SubStrings)+Work_Delim$+LEFT$(Work_Strng$,LEN(Work_Strng$)-1)
        Act_SubStrs=-Act_SubStrs
     END IF

' Return Function Value to the Point of Invocation -----------------------------

     PARSSTR%=Act_SubStrs

' Finish Function --------------------------------------------------------------

     END FUNCTION