Issue 66 * February 26 2009

Targeting Older Platforms
How I used the power of the Revolution community and revOnline to build a solution to check compatibility of my stack solutions

by Kay C Lan

I was recently inspired by some posts to the Revolution discussion group to start investigating legacy compatibility. For those that don't know, Revolution changed its file format about three years ago, with Revolution 2.7. So to open a file in Revolution 2.6 or earlier, you need to have saved it in legacy format.

One reason to use the legacy format is for solutions that must run on Mac OS 9, which uses the engine from Revolution 2.6.1, and does not support all those new features we've become so accustomed to.

You save in this format by choosing "Legacy Revolution Stack" from the "Save as type:" menu in the Save As dialog. But this is just the beginning. What about the dozens of new features introduced over the last three years that Revolution 2.6 will not recognize, leading to script errors or others execution problems in your stack. How can you tell if your solution is going to work in 2.6?

Why not throw together a stack that checks legacy compatibility? It should be easy enough, since Revolution handles text parsing with ease and eats chunk comparisons for breakfast. It would seem the hardest part would be coming up with a name. Eventually I picked a name, LegaCX, and was finally able to direct my attention to the coding. You can download the result from Revolution Online, User: lankc. There's even a legacy version, which may seem odd, but all will be explained.

Luckily, I didn't realize how difficult the task would be at the beginning, or I might not have gotten started! It takes more than being able to scan scripts for "new" keywords. But with the help of the Revolution community I was able to complete my journey, and I'll explain some of the key learning I acquired in the process.

To begin, I scanned the Revolution Online User Spaces for something similar, and clearly something that ran through every line of every script was what I was after. The late great Eric Chatonet's 'Smart Script Search' (User name: So Smart Software) was just the ticket.

Below is one of Eric's functions, which I've pruned for clarity so it probably won't work if you cut and paste it into your own stack, but it clearly shows the critical core concept: a series of nested repeat loops to extract every script within a stack.

function SearchForWords pWithList,pWithoutList
   local tStack,tSubStacks
   -----
   put the hilitedText of fld "StacksList" into tStack
   put the substacks of stack tStack into tSubStacks
   if tSubStacks <> empty then put cr & tSubStacks after tStack
   -----
   put empty into tFoundList
   repeat with i = 1 to the number of lines of tStack
      repeat with j = 1 to the number of cds of stack line i of \
         tStack
         repeat with k = 1 to the number of controls of cd j of \
            stack line i of tStack
            repeat for each item pWithWord in pWithList
               put the script of control k of cd j of stack \
               line i of tStack into tCurScript
               repeat for each line tLine in tCurScript
                  if pWithWord is among the words of tLine then
                     --do what you need to here
                  end if
               end repeat
            end repeat
         end repeat
      end repeat
   end repeat
   return tFoundList
end SearchForWords 

The other nice thing I had not considered at first was the need to get 'the substacks', so that every corner of a solution is examined.

Revolution makes it very easy to step through every line of every script. What I now needed was to know every command, function, property... etc so that I could do some comparing. It would have been a lot of work to compile my own list, and there's a risk it could be inaccurate or quickly become out of date. I realized, though, that I didn't have to worry about this part of the task. The Revolution dictionary already provides a list of all the keywords I'd have to consider, along with information about their compatibility with various releases of Revolution. What I needed was some information about how to access the information in the Dictionary. From discussions on the use-list, I remembered Revolution user Björnke von Gierke had created an alternative user interface to the Dictionary,"BvG Docu," which again can be found at Revolution Online, User name: BvG.

From Björnke's work I discovered that since Revolution 2.7 the columnar data you see at the top of the Dictionary is saved in a tab-delimited file called dict.index, located in a folder called Documentation at the same level as the Revolution application itself. So as 'the defaultFolder' is initially set to point at the Revolution application, a simple:

put URL "file:Documentation/dict.index" into tDictFile 

has all the data Revolution gives you, ready for you to do whatever you see fit. In my case I did a couple of things. If you don't know, if you open the Dictionary and ctrl+click on any column heading you'll get a popup menu allowing you to include/exclude various columns, such as Synonyms and Platforms. For any Legacy Check to be accurate it must cover the situation where a user has used a synonym rather than the Keyword, so when I created the abridged version of the Dictionary, any entry that had a synonym I created a similar entry for each synonym, so for the dict.index single entry for 'create folder' I added three additional entries 'create directory', 'new folder' and 'new directory'.

The other thing to appreciate is that since Rev 3.0 Platform compatibility is listed as text, whereas prior to this it appeared as a cute little icon, the same ones that appear next to Platform Support when you look at the detail of any entry. If LegaCX imports a 2.7 - 2.9 dict.index it will automatically replace those icon references with the appropriate text. This may seem minor, but prior to 3.0, trying to sort the Dictionary entries by Platform yielded unexpected results, now as text, the entries can be sorted and yield an unexpected bonus.

So that's it in a nutshell, LegaCX pulls in every script, pulls in every Dictionary entry, and then compares the two. So lets see it in action. Below you'll see that I've selected the stack 'Untitled 4' for checking:

Check

As mentioned, there is a bonus from sorting the Dictionary by Platform, and that is at the bottom of the list are about 45 entries that do not have any Platform listed. At first I thought this was a mistake, but on reading a couple of entries it was clear that typically they are useless, they are there for HyperCard or SuperCard compatibility, are deprecated, reserved for possible future use or are simply no longer supported!

As in the image above, if you select 'Rev' from the Rev Version Option Button, LegaCX will quickly report if you've used any of these outdated Keywords. As this check is restricted to 45 entries it is a very quick check.

Next you can check against a particular Revolution version number, so in the image below it's 2.6 selected from the Rev Version Option Button.

Check

And so here we see why I failed to build a true legacy checker.

Running through a stack's scripts cannot check for any property that has manually been set! For a while I toyed with the idea of calling all properties and seeing what their value was, based on the false assumption that properties that aren't used are empty. But alas, no, create a new stack, place a bog-standard rectangle graphic on it then in the message box type "put the mitreLimit of graphic Rectangle" and it will return 10. How would I possibly know what all the default values are, so unless someone knows how to extract this information, this is the first major limitation of LegaCX.

Notwithstanding, what is presented is valid and is a relatively quick check. Thanks to sorting the Dictionary by Version the check starts with 3.0 Keywords and as soon as it gets to the first 2.6 entry (in the above case) skips to the next entry. In my synonym enhanced version there are 144 entries higher than 2.6, there are 1886 total entries so the speed is about 8% of that of a full Dictionary search.

This all changes once you specify a particular OS. In this case every single entry must be checked. As shown in the image below, although 'beepPitch' is a Rev 1.0 property, if you want an OSX app you'll have to confirm your code accounts for 'beepPitch'. As expected, as every Dictionary Keyword must be examined, this check takes about 10 times longer. Note, this check includes outdated Keywords, as they have no Platform, so it's the most informative check to run.

no OS

And so here we see why I failed to build a true legacy checker.

Running through a stack's scripts cannot check for any property that has manually been set! For a while I toyed with the idea of calling all properties and seeing what their value was, based on the false assumption that properties that aren't used are empty. But alas, no, create a new stack, place a bog standard rectangle graphic on it then in the message box type "put the mitreLimit of graphic Rectangle" and it will return 10. How would I possibly know what all the default values are, so unless someone knows how to extract this information, this is the first major limitation of LegaCX.

Notwithstanding, what is presented is valid and is a relatively quick check. Thanks to sorting the Dictionary by Version the check starts with 3.0 Keywords and as soon as it gets to the first 2.6 entry (in the above case) skips to the next entry. In my synonym enhanced version there are 144 entries higher than 2.6, there are 1886 total entries so the speed is about 8% of that of a full Dictionary search.

This all changes once you specify a particular OS. In this case every single entry must be checked. As shown in the image below, although 'beepPitch' is a Rev 1.0 property, if you want an OSX app you'll have to confirm your code accounts for 'beepPitch'. As expected, as every Dictionary Keyword must be examined, this check takes about 10 times longer. Note, this check includes outdated Keywords, as they have no Platform, so it's the most informative check to run.

Check OS

So the final image below is a check against all OSs. As a check against multiple platform is still a one-liner, the time to execute is almost identical to a check against a single platform.

What the below image does reveal is the other major limitation of LegaCX.

Full Check

The data Revolution gives you is great, if the data is correct. Given the vast amount of information in the dictionary, it's not surprising to find some errors and omissions, or conditions that don't fit into a neat category.

For example, The 'do' command is not listed in the Dictionary as being Mac OS compatible. Neither is the 'paste' command. Paste is also one of the commands changed in Revolution 2.9, so does that affect usage in Revolution 2.6 and earlier? The dictionary doesn't have a keyword entry for the common synonym "btn" (for "button"), and also currently is missing an entry for the new keyword "byte."

Other problems will occur with Keywords that have multiple meanings, such as 'return', which is both a control structure and a constant. Now fortunately 'return' in both senses is compatible way back to Rev 1.0 and on all Platforms, so there is no need to determine usage; not so with 'set'. 'set' is both a keyword and a command, but as a keyword it is only valid on Windows and Unix. Fortunately when used this way the syntax is 'to set', so when LegaCX's abridged dictionary is created, 'set, keyword', is changed to 'to set,keyword'.

Unfortunately I don't have the time to manually go through the Dictionary and manually check for missing or duplicate Keywords, but in the case of duplicates where differences in Platform/Version exists, if you happen to stumble across one, if I can incorporate a way to differentiate between the two, let me know and I'll include it.

Because LegaCX does more than just check for legacy compatibility, I've uploaded to Revolution Online a legacy format file, preloaded with the Rev 3.0 Dictionary Keywords; the two files are LegaCX30 and LegaCX26. Of interest, if you open LegaCX26 it looks different to LegaCX30 because the two fields have a blendLevel manually set to 5. This is a 3.0 feature, which is completely ignored when saved in legacy format. So Revolution allows you to save in legacy format, but in the case of some properties, these will 'appear' not to be working.

So there you have it, those of you with long xTalk history and stacks born on the wrong side of the track, with derelict Keywords, LegaCX can help you clean up the neighborhood. On track but have Platform concerns, LegaCX might be useful in pinpointing the need for OS-specific code. As a legacy checker though, it's only mildly useable and easily fallible. On the bright side, Revolution Documentation is coming ahead in leaps and bounds, so when Rev 4.0 comes out, anything new in dict.index will automatically be picked up by LegaCX.

It's my hope that the LegaCX stack and this article helps anyone who is migrating stacks back and forth between the various implementations of xTalk, whether it be HyperCard, SuperCard, or older versions of Revolution. Please feel free to use whatever code is within LegaCX to adapt to your own needs. Any suggestions on improvements welcome.

Additional thanks go to Jacqueline Landman Gay and Mark Swindell for their extensive help on the discussion group in inspiring this project.

 

About the Author

Kay C Lan is a long time Mac user who was smitten by HyperCard when it first came out. An addicted tinkerer, be it mechanical, electrical or programmatic, his hobbies are Rev, model trains and cycling.

 

Main Menu

What's New

Merchandise