This article was brought to you by the guys from VDF-GUIdance.
For more DataFlex targeted articles see http://www.vdf-guidance.com


Datetime compiler problems with long strings

by Wil van Antwerpen

Summary

This article discusses the problem your compiler has with long strings in expressions and general datetime functions. (VDF15.1 and earlier)
No Files Available
Date Created: 12/03/2010
Date Updated: 12/01/2016
Author: Wil van Antwerpen
Company: Antwise Solutions


DateTime problem with long strings


March 12, 2010

Please note that this problem was specific for Visual DataFlex 15.1 and earlier.
This appears to have been fixed in Visual DataFlex16.0

What's the problem?


Ok, so you might wonder... how can you have a problem with datetime arithmetic and strings?
What is the link between these two?

Well if you have a string literal in an expression that is over 296 characters long in your application then the compiler chokes on the code:
DateTime dtVar
Move (CurrentDateTime()) To dtVar


and also on:
DateTime dtVar
Move (NullDateTime()) To dtVar


I'm not the first person that bumped into this, see also this forum thread: Another compiler oddity..
It is a very weird limitation as the string length itself doesn't make much sense, 297 characters are a problem!

All you need to do to get the error, is include the following method in your application:
Procedure Testme
  String sMessage
  DateTime dtVar
    
  Move ("very long string bla bla bla bla kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkddddddddddddddddddddddddddddddddddddddddkkksssss") to sMessage
  Move (CurrentDateTime()) to dtVar
End_Procedure

With that code in place, the compiler no longer recognizes global datetime functions like CurrentDateTime and NullDateTime.
Remove 1 character from the long string and there's no problem.
It's the 296 character string limit compiler problem;-)

It is important to note that it is not a variable length runtime problem, you can make your strings much bigger as that as long as you break them up in shorter literals.

How to fix it?


Well the fix is pretty simple, just make sure that your application doesn't have any string literals longer as 255 characters.
Exceeding that limit might give weird side effects.
It is not common for most programs to have string literals of that size and if you break them up in smaller chunks then there is no problem.

So for the example above that would be:
Procedure Testme
  String sMessage
  DateTime dtVar
    
  Move ("very long string bla bla bla bla kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk") to sMessage
  Move (sMessage+"ddddddddddddddddddddddddddddddddddddddddkkksssss") to sMessage
  Move (CurrentDateTime()) to dtVar
End_Procedure



Wait... a simple solution, but what if your application contains more as 100 lines of code?
How are you going to find those long strings then?

I wrote a quick and dirty application for this, give it the .prn filename of the application you want to check, the length of the string you want to find.
Run it and it will show you which lines to amend so you can get rid of this annoying compiler error.

This problem still exists in VDF15.1

The program


String gsFileName gsOK
Move "Order.prn" to gsFileName

Function LongString String sLine String sQuoteID Integer iOpenPos Integer iMaxLen Returns Integer
  Integer iLength
  Integer iClosePos
  String  sRemove
  
  Move 0 to iLength

  Move (Left(sLine,iOpenPos)) to sRemove 
  Move (Replace(sRemove,sLine,"")) to sLine
  Move (Pos(sQuoteID,sLine)) to iClosePos
  If (iClosePos>iMaxLen) Move iClosePos to iLength
  Function_Return iLength
End_Function // LongString

Procedure FindLongStrings String sPrnFile Integer iMaxLen
  String  sLine
  Integer iLine
  Integer iCommentPos
  Integer iDQuotPos
  Integer iSQuotPos
  Integer iPos
  Integer iLength
  Boolean bInspectCloser
  
  Move 0 to iLine
  Direct_Input channel 3 sPrnFile
  While not (SeqEof)
    Readln channel 3 sLine
    Move False to bInspectCloser
    Move 0 to iPos
    Move 0 to iLength
    Increment iLine
    
    Move (Pos('"',sLine)) to iDQuotPos
    Move (Pos("'",sLine)) to iSQuotPos
    Move (Pos('//',sLine)) to iCommentPos
    If (iDQuotPos<>0) Begin
      If (iCommentPos<>0 and iCommentPos>iDQuotPos) Move True to bInspectCloser
      If (iCommentPos=0) Move True to bInspectCloser
    End
    If (iSQuotPos<>0) Begin
      If (iCommentPos<>0 and iCommentPos>iSQuotPos) Move True to bInspectCloser
      If (iCommentPos=0) Move True to bInspectCloser
    End
    If (bInspectCloser) Begin
      If (iSQuotPos=0) Begin
        Get LongString sLine '"' iDQuotPos iMaxLen to iLength
        Move iDQuotPos to iPos
      End
      If (iDQuotPos=0) Begin
        Get LongString sLine "'" iSQuotPos iMaxLen to iLength
        Move iSQuotPos to iPos
      End
      If (iSQuotPos>0 and iDQuotPos>0) Begin
        If (iSQuotPos<iDQuotPos) Begin
          Get LongString sLine "'" iSQuotPos iMaxLen to iLength
          Move iSQuotPos to iPos
        End  
        Else Begin 
          Get LongString sLine '"' iDQuotPos iMaxLen to iLength
          Move iDQuotPos to iPos
        End
      End
      
      If (iLength>0) Begin
        Showln ("Line :"*Trim(iLine)* "String length :"*trim(iLength) )
        Showln ("="*sLine)
      End
    End
  Loop    
  Close_Input channel 3
End_Procedure

Send Info_Box "Click to START" "Click OK To start searching for the loooong string"

Send FindLongStrings gsFilename 250

Winput "Done searching.  Click OK To Quit" gsOK

With special thanks to Peter H. van Wijk for telling me to use the .prn file to scan and Sonny Falk for improving the text on the article