Thursday, December 18, 2008

Compiling SCL from SCL (ish)

I don't know about you, but in the past I've developed QUEST solutions where it would have been nice to be able to use SCL code to identify a set of other SCL files to compile.  However, there is no straightforward way to do this as using the SCL_COMPILE BCL command from an SCL script will generate an error and not compile the SCL file.

There is a workaround, however, and that is to use BCL to execute an SCL subroutine which returns the path of an SCL file to the bcl_msg BCL variable.  You can then use the SCL_COMPILE command passing bcl_msg as an argument to compile an SCL file selected using SCL code.

The downside is that if the routine doesn't return a file path the BCL code still tries to compile the blank string file path, and shows an error in the message window.  Unfortunately (as far as I can tell) you can't use conditional statements in a BCL script, so there's not much we can do about this.  I'd say if you need to be able to compile SCL from SCL, it's worth the small inconvenience of seeing the error message when you don't specify a file.

I've used this technique to compile SCL files listed in a configuration file (not the QUEST kind) that could only be parsed using SCL (rather than straight BCL), so that users can specify different SCL logics in building a QUEST model from an eVSM file.

This may not be of any use to anyone reading this, so I've provided an example which hopefully will make using QUEST just a little bit easier to use.  I don't know about you, but I often debug my SCL code by writing a little, then compiling it in QUEST, until it's all done and working.  However, if you're working on multiple SCL files it can be a pain to go to the Run->Simulate->Compile button and pick files in various folders.

So what I've done is created a BCL macro that calls an SCL routine that keeps track of (up to) the last 49 or so SCL files that I've compiled (in the current session) and gives me the option of selecting another file to compile.  So I've basically duplicated the Run->Simulate->Compile functionality, and added a list of the most recently compiled files for you to chose from.

You can get the BCL script here and the corresponding SCL file here.  Keep in mind that you need to modify the BCL script to compile the SCL file wherever it is saved on your computer.

Tuesday, November 11, 2008

Select an Element

QUEST SCL provides a function for selecting items (including elements) from the QUEST world, aptly named Select.   Basically, you tell the function what you want to pick (elements, cad_parts, etc...), the selection mode (mouse pick, pick from a list, or key in the name), and you pass in a string variable that will be set by the routine to the selected item's name (You also have to specify a text prompt, and whether or not you want the selected item to be highlighted).

I usually don't need to use all the available options in the Select function, so I've put together a routine I use often that I can drop into an SCL macro or call with an Extern reference, so here it is:

   routine select_an_element( prompt : String ) : Element
   Var
   elem_name : String
   picked_elem : Element
   Begin
      while( select( prompt , ELEMENT , PICK_MODE , TRUE , elem_name ) ) do
         picked_elem = get_element( elem_name )
      endwhile
      return picked_elem
   End

Like I said, this is just an easy to implement routine you can drop into your code without worrying too much about it, which is how I like to program...

Tuesday, October 21, 2008

Set part class dimensions

As far as the QUEST online documentation shows, there is no BCL command for setting a part class' dimensions.

I thought it would be possible to do this by exporting a part class to a text file, modifying the text file with the new dimensions, and then re-importing the text file to overwrite our part class with the new dimensions.

Here is the resulting SCL macro.

You can use it from within SCL by calling set_pclass_dimensions with a handle to the part class, then the 3 arguments to set the part class dimensions to.

You can call it from a BCL script using the following commands, setting the full path to the set_pclass_dimensions.scl file, substituting Part1 with the name of the part class you want, and setting the dimensions to the sizes you want:

SCL_COMPILE 'set_pclass_dimensions.scl' 0
SCL_EXEC set_pclass_dimensions_by_name WITH ARGUMENTS 'Part1' , 100 , 200 , 300

SCL Subroutine Indexer

If you're anything like me, you've written a large variety of SCL logics and have tons of procedures and routines buried in files which are in turn buried in different QUEST LOGICS and SCLMACROS libraries.  Sometimes I need a logic that I know I've already written, but can't remember where it is.  I use Google Desktop to find files, but it is unable to search within the text of a plain text file unless it has an extension it recognizes (i.e. not .scl).

Rather than write a plugin for Google Desktop to enable SCL search, I went the quicker, dirtier, and easier path (for me, anyway) and wrote a couple macros in Excel to index a set of SCL files (extracting all procedure and routine declarations) into an Excel worksheet.  A while back I wrote an interface for Excel's AutoFilter that makes setting filters on large datasets a little easier than without.

One thing to note is I haven't set it up to read any subroutine declarations that span multiple lines (using the line continuation character "\") so at the moment it won't pick up the full declaration.

Updated:  10/21/08 - Modified the auto-filter helper to run faster in populating the result list box for large data sets

To use this indexer, simply copy the SCL_Indexer.xls file to your computer, and open it in Excel.  I signed the VBA project with a digital certificate created on my own computer, so you should be able to import the certificate, but to be honest I'm not sure how that will work, and you may be stuck hitting "enable macros" every time you open the file.  If nothing else, you can try saving the file to a trusted location.

When you open the file (with macros enabled) the indexer will create a toolbar called "AutoFilterHelper".  This toolbar contains the buttons for running the indexer and searching the index (In Excel 2007 a section will be added to the Addins ribbon with the buttons).

To use the indexer just click on the binocular button.  This will open a form that allows you to select a directory or file, and to index it.  You may select to index any subdirectories from a directory.  Hit cancel while it's indexing if you want it to stop.

Once the index is built you will see that the worksheet is populated with all procedure and routines indexed, with the return type (Null means it's a procedure) and arguments listed.  The file name for each subroutine is listed as well.

To use the auto filter helper, click on the magnifying glass, and select the column header you want to search.  It may take some time to populate the result box, but you will see a list of all subroutine names in the bottom right box.  To search the list, start typing in the text box and the results in the result box will reflect what you've typed in the search box.

Select an item in the result box and click "Apply Filter" and that filter will be applied in the index worksheet.  For more information on auto filter: http://www.contextures.com/xlautofilter01.html

Monday, October 6, 2008

SCL Code "Profiler"

I've written a fairly large SCL macro, which you'll be able to get soon here.

In order to keep tabs on how much of this 8000+ line macro is real code, I decided to write an SCL logic "profiler", which really just goes through and counts the number of comment lines, blank lines, and everything else, and reports it out for you.  So really in my (currently) 8195 lines of code there's really 5978 lines of code, 1061 blank lines, and 1156 lines commented out.

The line counter code can be downloaded here.

Wednesday, October 1, 2008

String Replace

This routine gives you similar functionality to the replace function in VBA. Basically, the routine just reads through a string argument and replaces any instance of to_replace with replace_with.
As far as I can tell there is no built-in function in SCL for doing this...

routine replace_string( full_string : String ; to_replace : String ; replace_with : String ) : String
Var
   result : String
   start_idx : Integer
   rep_idx : Integer
Begin
   start_idx = 11
   result = full_string
   while( index( result , to_replace , start_idx ) > 0 ) do
      rep_idx = index( result , to_replace , start_idx )
      result = leftstr( result , index( result , to_replace , start_idx ) - 1 ) + replace_with + rightstr( result , len( result ) - index( result , to_replace , start_idx ) - len( to_replace ) + 1 )
      start_idx = rep_idx + len( replace_with )
   endwhile
   return result
End

Friday, September 19, 2008

Batch Control Language (BCL)

QUST has two macro/scripting languages, SCL and BCL. BCL is short for Batch Control Language, and it is basically there to let you automate almost everything you can do through the QUEST User Interface. This automation can be done through straight-up BCL scripts, which are plain-text files containing a series of BCL formatted commands. An example of such a command is:

CREATE SOURCE CLASS 'Source1'

which will create a new source class named Source1. This will also create one element in the Source1 class. You can locate this element using the follwing command:

LOCATE ELEMENT 'Source1_1' AT 100 , 100 , 0

This kind of scripting can be tedious and error-prone. The good thing is, almost all BCL commands are supported for use through SCL programming. This means you can write an SCL script to read a list of element names and locations, and execute BCL calls to create and locate those elements.

To use BCL within an SCL script, you use the BCL( command_text : String ) : Integer function. All you do is provide a string argument that contains your BCL command, and SCL will have QUEST execute it. The BCL function returns an integer containing the error code, so you can know whether or not the command executed properly. A list of error code numbers and their corresponding descriptions can be found in the bclerr.inc file in your QUESTlib\Include folder.

It's also possible to have QUEST execute a BCL script as soon as the QUEST.exe program starts. Details for setting up QUEST to run this way from Excel can be found here.

So, assuming you've set up QUEST to run a BCL script generated in Excel, you may now be wondering how to generate BCL scripts in Excel. I have set up a number of Excel VBA User Defined Functions (UDFs) that can be used to generate a subset of all the BCL commands. I'm currently working on building a version of this that I can release for everyone to use, but until then why not start building your own BCL UDFs?