Friday, January 16, 2009

How Filehamster Saved My Life

I don't know about you, but in the course of developing SCL macros and logics I sometimes tend to make bad choices, and undoing those changes can be pretty painful, especially if I went and modified something on a large scale (i.e. adding a call stack on 328 subroutines in an SCL file and finding out that my implementation gets extremely slow as the stack grows).

Thankfully, for the past couple years I've used a tool called FileHamster from MOGWare, which is a free and extremely easy to use backup program that basically sits and watches any files you want it to, and when you change it it snags a copy and stores it for you.  You can add comments to a revision as it's copied or later on (like "Last backup before adding call stack") so you can easily identify the point where you made a change you need to reverse, and restore your file to that version.

Filehamster just takes a copy of what's changed and saves it out for you to a backup directory. But there's very little overhead in setting up a file watch, and with SCL files we're dealing with text files in the size range of 1-300K, so it would take a while to use up an appreciable amount of hard disk space.  If you're that concerned there's a plugin for sale that'll compress each revision for you.

There's actually a set of plugins for sale on their site for extending FileHamster into something more like a full-on source control package, but I'm going to hold out until they come up with a plugin that can hear that voice in the back of my head asking "does he really think this is going to work?"

Tuesday, January 13, 2009

SCL Call Stack

If you saw my last post on compiling SCL files from SCL, you may have seen that there are some array utility routines I've written that allow you to insert and remove array elements through a simple call providing the array and the number of elements in it.

After creating these routines, I thought they'd be perfect for implementing a call stack in SCL.  Having a call stack available in SCL would mean we can more easily track down the source of bugs in our scl subroutines, especially if they're more generic utilities that may be called from any number of different routines.

So the way I'll be using this is in a very large (8,000+ line) SCL utility where many routines are simply wrappers around BCL commands that make it so I don't have to write out BCL statements again and again.  Basically any time a subroutine starts or ends I just write the stack out to a text file; and if the macro crashes, I just check the latest stack text file and see what subroutines were in the stack, so I can track the problem down.


I'd suggest you save the call_stack.scl file into QUESTlib/UserDef/Logics so it's always compiled and ready to go when you need it...

Basically there are three procedures in the call_stack.scl file you need to worry about: start_procedure, end_procedure, and print_stack.  Just call start_procedure and end_procedure with the name of your subroutine as an argument, and the stack will reflect all subroutines you've got running.

However, like I said earlier, I have 8000 lines of SCL code with over 300 subroutines.  So how am I supposed to put in a call to start_procedure and end_procedure for all those subroutines?

The answer is using SCL, what else?  So I went and wrote an SCL macro that lets me select an SCL file, and it then goes through and identifies each subroutine in the file, and adds a call to start_procedure at the beginning and end_procedure at the end of each subroutine, with the name of the sub as the argument.  The file gets saved out as the original filename with "_cs" appended on, so you can go and copy it over if you want, or just run that for debugging purposes.

Monday, January 5, 2009

Model Scaling

I recently built a QUEST model on a CAD layout and it turned out the layout wasn't properly scaled.  This is easy enough to fix, just a matter of either modifying the CAD part in the QUEST drawing world, or just scaling it in the dimensions section of the layout accessory.

But what about the elements?  I had to scale the layout to about 120% of its original size and didn't feel like moving all the machines and buffers and everything to their new locations on the layout.

So what would I do other than write an SCL macro that lets me move all elements in a model relative to some new scale.  Here's the code.

Basically what it does is populates a spot structure, multiplies the location coordinates by the scale input by the user, and locates the element on the spot's new coordinates.

The best part about writing this macro was that it took about 5 minutes, just by copying in SCL subroutines I've previously written and was able to find using my SCL Subroutine Indexer.

Update: When using this macro I found it might be better to be able to scale the model differently along various axes.  So I went and modified the macro to scale each axis to different values as input by the user using a var_pop_up.