home *** CD-ROM | disk | FTP | other *** search
/ Dan Appleman's Visual Bas…s Guide to the Win32 API / Dan.Applmans.Visual.Basic.5.0.Programmers.Guide.To.The.Win32.API.1997.Ziff-Davis.Press.CD / VB5PG32.mdf / desaware / apitools / apimod1.bas < prev    next >
Encoding:
BASIC Source File  |  1996-02-06  |  25.8 KB  |  784 lines

  1. Attribute VB_Name = "APIMOD1"
  2. ' Copyright (c) 1996 by Desaware
  3. ' Part of the Desaware API Toolkit
  4. ' All Rights Reserved
  5.  
  6. Option Explicit
  7.  
  8. Global Separators$  ' Separators between tokens
  9. Global Const ReturnType$ = "%&!#@$"
  10. Global ReturnTypeName$(7)   ' Individual names
  11.  
  12. ' State for parsing
  13. ' 0 = Normal
  14. ' 1 = In quote
  15. Dim ParseState%
  16.  
  17. ' Location of special characters in string
  18. Const idComment% = 4    '  ' character
  19. Const idSpace% = 1      ' Space character
  20. Const IdTab% = 7        ' Tab character
  21. Const idQuote% = 8      '  " character
  22. Const idLineCont% = 5   ' _ - Line continuation char
  23.  
  24. ' State machine information
  25. Dim MajorState%      ' Major state as follows:
  26.                         ' 0 - Clear
  27.                         ' 1 - In Comment
  28.                         ' 2 - In Declare
  29.                         ' 3 - In Type
  30.                         ' 4 - In Global
  31. Dim MinorState%     ' Used by individual state machines as follows
  32.  
  33. ' Current category description (via '')
  34. Global Category$
  35.  
  36. ' Object identification information
  37. Type paramType
  38.     ParamName As String ' Name of parameter
  39.     paramType As String
  40.     IsArray As Integer
  41.     IsByVal As Integer
  42. End Type
  43.  
  44. Global objType%    ' 0 = Clear
  45.                 ' 1 = Sub
  46.                 ' 2 = Function
  47.                 ' 3 = Type
  48.                 ' 4 = Constant
  49.  
  50. Global objName$     ' Name of the object
  51. Global objLib$      ' Library or value for globals
  52. Global objAlias$    ' Alias
  53. Global objReturn%   ' Return type (VB char) - See ReturnTypes$
  54.                     ' 0 - Variant (default)
  55.                     ' 1 - Integer, 2 - Long, 3 - Single, 4 - Double
  56.                     ' 5 - Currency, 6 - String, 7 - Object
  57.  
  58. Global pDesc() As paramType   ' Array of parameter names or type field names
  59.  
  60. '
  61. ' Initialize the constants
  62. '
  63. Sub am1Initialize()
  64.     ' Characters that separate the tokens
  65.     Separators$ = " ()'_," & Chr$(9) & Chr$(34) & "%#$!@&="
  66.     ' We append the tab and " character as well
  67.  
  68.     ReturnTypeName(0) = "Variant"
  69.     ReturnTypeName(1) = "Integer"
  70.     ReturnTypeName(2) = "Long"
  71.     ReturnTypeName(3) = "Single"
  72.     ReturnTypeName(4) = "Double"
  73.     ReturnTypeName(5) = "Currency"
  74.     ReturnTypeName(6) = "String"
  75.     ReturnTypeName(7) = "Object"
  76. End Sub
  77.  
  78. '
  79. '   This is the main input line for the state machine
  80. '   InputString$ is the string read from the file.
  81. '   Returns 0 on success.
  82. '   Returns 1 On object ready.
  83. '   Returns 2 on syntax error.
  84. '
  85. Function am1ParseLine%(ByVal InputString$)
  86.     Dim s$
  87.     Dim res%    ' Set by state machines to return value (above)
  88.     Dim TokenRes%
  89.     
  90.     InputString$ = Trim(InputString$)   ' Trim whitespace
  91.  
  92.     Do  ' We'll loop through every token in the string
  93.         s$ = GetToken1(InputString$, TokenRes%)
  94.     ' Debug.Print s$, MajorState% & "." & MinorState%
  95.         ' How the string is handled depends on the state
  96.         Select Case MajorState%
  97.             Case 0  ' Clear state
  98.                     res% = ProcessClearState(s$, TokenRes%)
  99.             Case 1  ' Processing Comment
  100.                     res% = ProcessCommentState(s$, TokenRes%)
  101.             Case 2  ' Processing Declaration
  102.                     res% = ProcessDeclareState(s$, TokenRes%)
  103.             Case 3  ' Processing User Type
  104.                     res% = ProcessTypeState(s$, TokenRes%)
  105.             Case 4  ' Processing Global
  106.                     res% = ProcessGlobalState(s$, TokenRes%)
  107.         End Select
  108.     Loop While Len(s$) > 0
  109.  
  110.     am1ParseLine% = res%
  111.  
  112. End Function
  113.  
  114. '
  115. ' Returns the position of the next separator.
  116. ' Valid separator is any separator unless ParseState% is 1, in which
  117. ' case only a quote is valid.
  118. ' TokenId% is the location of the token in the separator string
  119. '
  120. Function FindSeparator%(InputString$, TokenId%)
  121.     Dim InputLength%
  122.     Dim c%
  123.     
  124.     If ParseState% = 1 Then ' Find next quote only
  125.         c% = InStr(InputString$, Chr$(34))
  126.         If c% > 0 Then
  127.             TokenId% = InStr(Separators$, Chr$(34))
  128.         End If
  129.         FindSeparator = c%
  130.         Exit Function
  131.     End If
  132.  
  133.     InputLength% = Len(InputString$)
  134.     For c% = 1 To InputLength%
  135.         TokenId% = InStr(Separators$, Mid$(InputString$, c%, 1))
  136.         Select Case TokenId%
  137.             Case 0  ' Ignore - it's not a separator
  138.  
  139.             Case idLineCont
  140.                 ' A line continuation character is valid only
  141.                 ' if it is the first character in the string
  142.                 If c% = 1 Then
  143.                     FindSeparator = c%
  144.                     Exit Function
  145.                 End If
  146.             Case Else
  147.                 ' This character is a separator
  148.                 FindSeparator = c%
  149.                 Exit Function
  150.         End Select
  151.         
  152.     Next c%
  153.  
  154.     FindSeparator = 0
  155.     TokenId% = 0
  156.  
  157. End Function
  158.  
  159. '
  160. ' Retrieves the left token from the input string, modifies
  161. ' the input string to remove the token. Ignores white space
  162. ' result% = 0 - on success, 1 - Missing close quote
  163. '
  164. Function GetToken1$(instring$, result%)
  165.     Dim maxlen%
  166.     Dim Separatorloc%, Quote2%
  167.     Dim TokenId%
  168.     Dim Quote2Loc%
  169.     result% = 0
  170.     maxlen% = Len(instring$)
  171.     If maxlen% = 0 Then ' Empty string
  172.         GetToken1$ = instring$
  173.         result% = 0
  174.     End If
  175.  
  176.     Separatorloc% = FindSeparator(instring$, TokenId%)
  177.     Select Case Separatorloc%
  178.         Case 0  ' Just retrieve through the rest of the line
  179.                 GetToken1 = instring$
  180.                 instring$ = ""
  181.  
  182.         Case 1  ' First char is a separator
  183.                 ' Special cases are comment and quote
  184.                 Select Case TokenId%
  185.                     Case idQuote%   ' Return quoted string as a single token
  186.                         ParseState% = 1
  187.                         Quote2% = FindSeparator(Mid$(instring$, 2), TokenId%) + 1
  188.                         ParseState% = 0
  189.                         If Quote2% <= 1 Then
  190.                             result% = 1
  191.                             Exit Function
  192.                         Else
  193.                             GetToken1$ = Left$(instring$, Quote2%)
  194.                             If maxlen% > Quote2% Then instring$ = Mid$(instring$, Quote2% + 1) Else instring$ = ""
  195.                             Exit Function
  196.                         End If
  197.                     Case idComment% ' Return comment as a single token
  198.                         GetToken1$ = instring$
  199.                         ' If there's a line continuation at the end, parse it separately
  200.                         TrimWhiteSpace instring$, 2 ' Trim trailing spaces
  201.                         If instring$ = "" Then Exit Function
  202.                         If InStr(Separators$, Right$(instring$, 1)) = idLineCont Then
  203.                             ' Check if it's a line continuation
  204.                             maxlen% = Len(instring$)
  205.                             TokenId% = InStr(Separators$, Mid$(instring$, maxlen% - 1, 1))
  206.                             If TokenId% = idSpace Or TokenId% = IdTab Then
  207.                                 GetToken1$ = Left(instring$, maxlen% - 1)
  208.                                 instring$ = Right$(instring$, 1)
  209.                                 Exit Function
  210.                             End If
  211.                         End If
  212.                         instring$ = ""
  213.                     Case idSpace%, IdTab%   ' It's whitespace
  214.                         TrimWhiteSpace instring$, 1
  215.                         If Len(instring$) > 0 Then
  216.                             ' Recursive call on rest of string
  217.                             GetToken1 = GetToken1(instring$, TokenId%)
  218.                         Else
  219.                             GetToken1$ = ""
  220.                             instring$ = ""
  221.                         End If
  222.                     Case Else
  223.                         ' All other separators are tokens
  224.                         GetToken1$ = Left$(instring$, 1)
  225.                         If maxlen% > 1 Then
  226.                             instring$ = Mid$(instring$, 2)
  227.                         Else
  228.                             instring$ = ""
  229.                         End If
  230.  
  231.                 End Select
  232.  
  233.         
  234.         Case Else   ' First char is not a separator
  235.                 ' Return the string up to the separator
  236.                 GetToken1$ = Left$(instring$, Separatorloc% - 1)
  237.                 instring$ = Mid$(instring$, Separatorloc%)
  238.     End Select
  239.         
  240.  
  241.  
  242.  
  243. End Function
  244.  
  245. '
  246. '   Checks the string against the return type name array
  247. '   to find out which return type it is.
  248. '   Returns -1 on error
  249. '
  250. Function GetTypeValue%(s As String)
  251.     Dim x%
  252.     Dim us$
  253.     us$ = UCase$(s)
  254.     For x = 0 To UBound(ReturnTypeName)
  255.         If us$ = UCase$(ReturnTypeName(x)) Then
  256.             GetTypeValue% = x
  257.             Exit Function
  258.         End If
  259.     Next x
  260.  
  261.  
  262. End Function
  263.  
  264. '
  265. '   MajorState% is zero - processes the clear
  266. '   MinorState% =   0 - Normal entry
  267. '                   1 - Line term pending
  268. Function ProcessClearState%(s As String, TokenRes%)
  269.     Select Case UCase$(s)
  270.         Case "DECLARE"
  271.                 MajorState% = 2
  272.                 MinorState% = 0
  273.         Case "PUBLIC"
  274.                 MajorState% = 4
  275.                 MinorState% = 0
  276.         Case "TYPE"
  277.                 MajorState% = 3
  278.                 MinorState% = 0
  279.         Case "GLOBAL"
  280.                 MajorState% = 4
  281.                 MinorState% = 0
  282.         Case "_"
  283.                 MinorState% = 1
  284.         Case Else
  285.             If s = "REM" Or Left$(s, 1) = "'" Then ' It's a comment
  286.                 MajorState% = 1
  287.                 MinorState% = 0
  288.                 If Len(s) > 1 Then
  289.                     If Mid$(s, 2, 1) = "'" Then
  290.                         ' Double '' sets current category
  291.                         If Len(s) > 2 Then
  292.                             Category$ = Mid$(s, 3)
  293.                             TrimWhiteSpace Category$, 3
  294.                         End If
  295.                     End If
  296.                 End If
  297.             Else
  298.                 MinorState% = 0
  299.                 ' Anything else is simply ignored
  300.             End If
  301.     End Select
  302.     ' Clear state never terminates an object
  303.     ProcessClearState% = 0
  304. End Function
  305.  
  306. '
  307. ' Comment state
  308. ' MinorState% = 0 - In comment, throw out everything
  309. '               1 - Line continuation received, watch for newline
  310. ' Exit on receipt of new line.
  311. ' If anything else arrives, throw it out
  312. '
  313. Function ProcessCommentState%(s As String, TokenRes%)
  314.     Select Case s
  315.         Case "_"
  316.             MinorState% = 1
  317.         Case ""
  318.             ' If newline arrived, if last item was line continuation
  319.             ' stay in comment state for next line
  320.             ' Otherwise, switch back to clear state
  321.             Select Case MinorState%
  322.                 Case 0
  323.                     MajorState% = 0
  324.                 Case Else
  325.                     MinorState% = 0
  326.             End Select
  327.         Case Else
  328.             MinorState% = 0
  329.     End Select
  330.             
  331.     ' Just ignore anything else
  332.     ProcessCommentState = 0
  333. End Function
  334.  
  335. '
  336. ' Declare state
  337. ' MinorState% = 0 - Entry point
  338. '               1 - Processing comment
  339. '
  340. ' Exit on receipt of new line.
  341. ' If anything else arrives, throw it out
  342. '
  343. '   MinorState  0 - Declare received
  344. '               1 - Comment
  345. '               2 - Syntax error found - throw away rest
  346. '               3 - Sub,Function received, waiting on name
  347. '               4 - Name received, waiting on lib
  348. '               5 - Lib received, waiting on lib name
  349. '               6 - Libname recorded, waiting on ( or Alias
  350. '               7 - Alias received waiting on Aliasname
  351. '               8 - Aliasname received, waiting on (
  352. '               9 - Start of parameter
  353. '               10 -    ) received, can get EOL, comment or As
  354. '               11 - Type word received
  355. '               12 - Like 9, except ByVal received
  356. '               13 - Just processed param name
  357. '               14 - Appending array info to var name
  358. '               15 - AS received, waiting for type
  359. '               16 - Full parameter received, look for , or )
  360. '
  361. '
  362. Function ProcessDeclareState%(s As String, TokenRes%)
  363.     
  364.     Static lineterm%    ' Separate state machine for line timer character
  365.     Static CompletionState% ' Set to 1 on legal statement
  366.     Static CurParamNum%
  367.     
  368.     If CompletionState% = 0 Then CompletionState% = 2   ' Default to error state
  369.  
  370.     ' The following conditions apply regardless of minor state
  371.     Select Case s
  372.         Case "_"
  373.             lineterm% = True
  374.             ProcessDeclareState% = 0
  375.             Exit Function
  376.         Case ""
  377.             If Not lineterm% Then
  378.                 MajorState% = 0
  379.                 MinorState% = 0
  380.                 ProcessDeclareState% = CompletionState%
  381.                 Exit Function
  382.             End If
  383.             lineterm% = False
  384.         Case Else
  385.             lineterm% = False
  386.             If Left$(s, 1) = "'" Or UCase$(s) = "REM" Then
  387.                 ' Enter internal comment state
  388.                 ProcessDeclareState% = 0
  389.                 MinorState% = 1
  390.                 Exit Function
  391.             End If
  392.     End Select
  393.  
  394.  
  395.     Select Case MinorState%
  396.         Case 0
  397.                 objName$ = ""
  398.                 objLib$ = ""
  399.                 objAlias$ = ""
  400.                 objReturn% = 0
  401.                 Select Case UCase$(s)
  402.                     Case "SUB"
  403.                         objType = 1
  404.                         ReDim pDesc(0)
  405.                         MinorState% = 3
  406.                     Case "FUNCTION"
  407.                         objType = 2
  408.                         ReDim pDesc(0)
  409.                         MinorState% = 3
  410.                     Case Else
  411.                         objType = 0
  412.                         MinorState% = 2
  413.                 End Select
  414.                 CompletionState% = 2    ' Set error status
  415.         Case 1, 2 ' Internal comment mode or syntax error
  416.                 ' Just ignore everything - top level will
  417.                 ' handle it
  418.         Case 3
  419.                 If Len(s) = 1 And InStr(Separators, s) Then
  420.                     ' Not a legal name
  421.                     MinorState% = 2
  422.                 Else
  423.                     objName$ = s
  424.                     objReturn% = 0 ' Default variant
  425.                     MinorState% = 4
  426.                 End If
  427.         Case 4  ' We might also get type char at this point
  428.                 If Len(s) = 1 And objReturn% = 0 And InStr(ReturnType$, s) > 0 Then
  429.                     ' It's a type character
  430.                     objReturn% = InStr(ReturnType$, s)
  431.                     ' Stay in current minor state for lib
  432.                     ' Multiple type chars are not detected as error
  433.                 Else
  434.                     If UCase$(s) = "LIB" Then MinorState% = 5 Else MinorState% = 2
  435.                 End If
  436.         Case 5
  437.                 If Left$(s, 1) <> Chr$(34) Or Len(s) < 3 Or TokenRes% = 1 Then
  438.                     MinorState% = 2
  439.                 Else
  440.                     MinorState% = 6
  441.                     objLib$ = Mid$(s, 2, Len(s) - 2)
  442.                 End If
  443.         Case 6
  444.                 Select Case UCase$(s)
  445.                     Case "("
  446.                         MinorState% = 9
  447.                     Case "ALIAS"
  448.                         MinorState% = 7
  449.                     Case Else
  450.                         MinorState% = 2
  451.                 End Select
  452.         Case 7
  453.                 If Left$(s, 1) <> Chr$(34) Or Len(s) < 3 Or TokenRes% = 1 Then
  454.                     MinorState% = 2
  455.                 Else
  456.                     MinorState% = 8
  457.                     objAlias$ = Mid$(s, 2, Len(s) - 2)
  458.                 End If
  459.         Case 8
  460.                 If s = "(" Then MinorState% = 9 Else MinorState% = 2
  461.         Case 9, 12 ' ( received (or , on prev param), processing param
  462.             Select Case UCase$(s)
  463.                 Case ")"    ' Possible legal state
  464.                     CompletionState = 1
  465.                     MinorState = 10
  466.                 Case "BYVAL"
  467.                     If MinorState% = 12 Then
  468.                         MinorState% = 2
  469.                     Else
  470.                         MinorState% = 12
  471.                     End If
  472.                 Case Else
  473.                     If Len(s) = 1 And InStr(Separators, s) Then
  474.                         MinorState% = 2
  475.                     Else
  476.                         ' Record the name
  477.                         CurParamNum = UBound(pDesc) + 1
  478.                         ReDim Preserve pDesc(CurParamNum)
  479.                         pDesc(CurParamNum).ParamName = s
  480.                         If MinorState% = 12 Then pDesc(CurParamNum).IsByVal = True
  481.                         MinorState% = 13
  482.                     End If
  483.                     
  484.             End Select
  485.         Case 10 ' Only "AS" acceptable
  486.             If UCase$(s) = "AS" And objReturn% = 0 Then MinorState% = 11 Else MinorState% = 2
  487.             CompletionState% = 2    ' Must finish
  488.         Case 11
  489.             objReturn% = GetTypeValue(s)
  490.             If objReturn% >= 0 Then CompletionState% = 1
  491.         Case 13
  492.             Select Case UCase$(s)
  493.                 Case "("
  494.                     MinorState% = 14
  495.                     pDesc(CurParamNum).IsArray = True
  496.                 Case "AS"
  497.                     MinorState% = 15
  498.                 Case ","
  499.                     MinorState% = 9 ' Get ready for next
  500.                 Case Else
  501.                     ' It might be a type character
  502.                     If Len(s) = 1 And InStr(ReturnType$, s) > 0 Then
  503.                         pDesc(CurParamNum).paramType = ReturnTypeName(InStr(ReturnType$, s))
  504.                         ' pDesc(CurParamNum).ParamType = InStr(ReturnType$, s)
  505.                         MinorState% = 16
  506.                     Else
  507.                         MinorState% = 2
  508.                     End If
  509.  
  510.             End Select
  511.         Case 14
  512.             If s = ")" Then
  513.                 MinorState% = 13
  514.             End If
  515.         Case 15
  516.             pDesc(CurParamNum).paramType = s
  517.             MinorState% = 16
  518.             'objReturn% = GetTypeValue(s)
  519.             'If objReturn% >= 0 Then
  520.             '    pDesc(CurParamNum).ParamType = objReturn%
  521.             '    MinorState% = 16
  522.             'Else
  523.             '    MinorState% = 2
  524.             'End If
  525.         Case 16
  526.             Select Case s
  527.                 Case ","
  528.                     MinorState% = 9
  529.                 Case ")"
  530.                     CompletionState% = 1
  531.                     MinorState% = 10
  532.                 Case Else
  533.                     MinorState% = 2
  534.             End Select
  535.  
  536.     End Select
  537.  
  538.     
  539.     
  540.  
  541.  
  542. End Function
  543.  
  544. '
  545. ' Declare state
  546. ' MinorState% = 0 - Entry point
  547. '               1 - Processing comment
  548. '
  549. ' Exit on receipt of new line.
  550. ' If anything else arrives, throw it out
  551. '
  552. '   MinorState  0 - Global or Public received
  553. '               1 - Comment
  554. '               2 - Syntax error found - throw away rest
  555. '               3 - Const received, waiting on name
  556. '               4 - Name received, waiting on =
  557. '               5 - = received, waiting on Value
  558. '
  559. '
  560. Function ProcessGlobalState%(ByVal s$, TokenRes As Integer)
  561.     
  562.     Static lineterm%    ' Separate state machine for line timer character
  563.     Static CompletionState% ' Set to 1 on legal statement
  564.     
  565.     If CompletionState% = 0 Then CompletionState% = 2   ' Default to error state
  566.  
  567.     ' The following conditions apply regardless of minor state
  568.     Select Case s
  569.         Case "_"
  570.             lineterm% = True
  571.             ProcessGlobalState% = 0
  572.             Exit Function
  573.         Case ""
  574.             If Not lineterm% Then
  575.                 MajorState% = 0
  576.                 MinorState% = 0
  577.                 ProcessGlobalState% = CompletionState%
  578.                 Exit Function
  579.             End If
  580.             lineterm% = False
  581.         Case Else
  582.             lineterm% = False
  583.             If Left$(s, 1) = "'" Or UCase$(s) = "REM" Then
  584.                 ' Enter internal comment state
  585.                 ProcessGlobalState% = 0
  586.                 MinorState% = 1
  587.                 Exit Function
  588.             End If
  589.     End Select
  590.  
  591.  
  592.     Select Case MinorState%
  593.         Case 0
  594.                 objName$ = ""
  595.                 objLib$ = ""
  596.                 Select Case UCase$(s)
  597.                     Case "CONST"
  598.                         objType = 4
  599.                         MinorState% = 3
  600.                     Case Else
  601.                         objType = 0
  602.                         MinorState% = 2
  603.                 End Select
  604.                 CompletionState% = 2    ' Set error status
  605.         Case 1, 2 ' Internal comment mode or syntax error
  606.                 ' Just ignore everything - top level will
  607.                 ' handle it
  608.         Case 3
  609.                 If Len(s) = 1 And InStr(Separators, s) Then
  610.                     ' Not a legal name
  611.                     MinorState% = 2
  612.                 Else
  613.                     objName$ = s
  614.                     MinorState% = 4
  615.                 End If
  616.         Case 4  ' We might also get type char at this point
  617.                 If s = "=" Then
  618.                     MinorState% = 5
  619.                     objLib$ = ""
  620.                     Exit Function
  621.                 End If
  622.                 
  623.                 If Len(s) = 1 And InStr(ReturnType$, s) > 0 Then
  624.                     ' It's a type character
  625.                         objReturn% = InStr(ReturnType$, s)
  626.                 Else
  627.                     MinorState% = 2
  628.                 End If
  629.         Case 5
  630.                 objLib$ = objLib$ & s   ' Keep adding to value
  631.                 CompletionState% = 1
  632.     End Select
  633. End Function
  634.  
  635. '
  636. ' Type state
  637. ' MinorState% = 0 - Entry point
  638. '               1 - Processing comment
  639. '
  640. ' Exit on receipt of new line.
  641. ' If anything else arrives, throw it out
  642. '
  643. '   MinorState  0 - Type received waiting on name or comment
  644. '               1 - Comment
  645. '               2 - Syntax error found - throw away rest
  646. '               3 - Ready for first Field name
  647. '               4 - Comment during Field
  648. '               5 - Field name recorded
  649. '               6 - End received, waiting on type
  650. '               7 - Comment after completion
  651. '
  652. '
  653. '
  654. '
  655. Function ProcessTypeState%(ByVal s$, TokenRes%)
  656.     
  657.     Static CompletionState% ' Set to 1 on legal statement
  658.     Static lineterm%    ' Separate state machine for line timer character
  659.     Static CurrentParamNum%
  660.     
  661.     If CompletionState% = 0 Then CompletionState% = 2   ' Default to error state
  662.  
  663.     Select Case s
  664.         Case "_"
  665.             lineterm% = True
  666.             ProcessTypeState% = 0
  667.             Exit Function
  668.         Case ""
  669.             If lineterm% Then
  670.                 ' No change to state for Types
  671.                 lineterm% = False
  672.                 Exit Function
  673.             End If
  674.             lineterm% = False
  675.         Case Else
  676.             lineterm% = False
  677.     End Select
  678.  
  679.  
  680.     Select Case MinorState%
  681.         Case 0
  682.                 If (Len(s) = 1 And InStr(Separators$, s) > 0) Or s = "" Then
  683.                     MinorState% = 2
  684.                     Exit Function
  685.                 End If
  686.                 objType = 3
  687.                 objName$ = s
  688.                 ReDim pDesc(0)  ' Clear array
  689.                 MinorState% = 3
  690.             
  691.         Case 1  ' It's a comment
  692.                 ' True EOL means time for next variable
  693.                 If s = "" Then MinorState% = 3
  694.                 
  695.         Case 2
  696.                 If s = "" Then
  697.                     MajorState = 0
  698.                     ProcessTypeState% = CompletionState%
  699.                 End If
  700.  
  701.         Case 3
  702.                 If s = "" Then Exit Function 'Ignore extra lines
  703.                 If UCase$(s) = "END" Then
  704.                     MinorState% = 6
  705.                     Exit Function
  706.                 End If
  707.                     
  708.                 If Left$(s, 1) = "'" Or UCase$(s) = "REM" Then
  709.                     MinorState% = 4
  710.                     Exit Function
  711.                 End If
  712.                 If (Len(s) = 1 And InStr(Separators$, s) > 0) Then
  713.                     MinorState% = 2
  714.                     Exit Function
  715.                 End If
  716.                 CurrentParamNum = UBound(pDesc) + 1
  717.                 ReDim Preserve pDesc(CurrentParamNum)
  718.                 pDesc(CurrentParamNum).ParamName$ = s
  719.                 MinorState% = 5
  720.         
  721.         Case 4
  722.                 If s = "" Then MinorState% = 3
  723.         
  724.         Case 5
  725.                 If Left$(s, 1) = "'" Or UCase$(s) = "REM" Then
  726.                     MinorState% = 4
  727.                     Exit Function
  728.                 End If
  729.                 If s = "" Then  ' Line end
  730.                     MinorState% = 3
  731.                     Exit Function
  732.                 End If
  733.                 pDesc(CurrentParamNum).ParamName$ = pDesc(CurrentParamNum).ParamName$ & " " & s
  734.                 
  735.         Case 6
  736.                 Select Case UCase$(s)
  737.                     Case "TYPE"
  738.                         MinorState% = 7
  739.                         CompletionState% = 1
  740.                     Case Else
  741.                         MinorState% = 2
  742.                 End Select
  743.                     
  744.         Case 7
  745.             If s = "" Then
  746.                 MajorState% = 0
  747.                 MinorState% = 0
  748.                 ProcessTypeState% = CompletionState%
  749.             End If
  750.  
  751.     End Select
  752.  
  753. End Function
  754.  
  755. '
  756. ' Trims whitespace from string per mode
  757. '   mode 1 = left, 2 = right, 3 = both
  758. '
  759. Sub TrimWhiteSpace(s$, ByVal mode%)
  760.     Dim ch%
  761.     If s$ = "" Then Exit Sub
  762.     If mode% And 1 Then
  763.         Do
  764.             ch% = Asc(s$)
  765.             If ch% = 32 Then s$ = LTrim$(s$)
  766.             If ch% = 9 Then
  767.                 If Len(s$) > 1 Then s$ = Mid$(s$, 2) Else s$ = ""
  768.             End If
  769.         Loop While s$ <> "" And (ch% = 32 Or ch% = 9)
  770.     End If
  771.     If mode% And 2 Then
  772.         Do
  773.             ch% = Asc(Right$(s$, 1))
  774.             If ch% = 32 Then s$ = RTrim$(s$)
  775.             If ch% = 9 Then
  776.                 If Len(s$) > 1 Then s$ = Mid$(s$, 1, Len(s$) - 1) Else s$ = ""
  777.             End If
  778.         Loop While s$ <> "" And (ch% = 32 Or ch% = 9)
  779.     End If
  780.         
  781.  
  782. End Sub
  783.  
  784.