Wednesday, April 28, 2010

[Batch File] Rediscovering CMD.EXE batch scripts

Insanity must be setting in; I’ve been trying to solve RosettaCode tasks with Windows CMD.EXE batch scripts. For example, their A+B task:

A+B - in programming contests, classic problem, which is given so contestants can gain familiarity with online judging system being used.

A+B is one of few problems on contests, which traditionally lacks fabula.

Problem statement Given 2 integer numbers, A and B. One needs to find their sum.

Input data
Two integer numbers are written in the input stream, separated by space.
(-1000 \le A,B \le +1000)
Output data
The required output is one integer: the sum of A and B.
Example:

Input Output

2 2 4

3 2 5

These are what I posted as solutions:

Prompts version

::aplusb.cmd
@echo off
setlocal
set /p a="A: "
set /p b="B: "
set /a c=a+b
echo %c%
endlocal

All on the commandline version

::aplusb.cmd
@echo off
setlocal
set a=%1
set b=%2
set /a c=a+b
echo %c%
endlocal

Formula on the command line version

::aplusb.cmd
@echo off
setlocal
set /a c=%~1
echo %c%
endlocal

Example of 'Formula on the command line version'

>aplusb 123+456
579
>aplusb "1+999"
1000

Parse the input stream version (thanks to Tom Lavedas on alt.msdos.batch.nt)

::aplusb.cmd
@echo off
setlocal
set /p a="Input stream: "
call :add %a%
echo %res%
endlocal
goto :eof

:add
set /a res=res+%1
shift
if "%1" neq "" goto :add

Example of 'parse the input stream version'

>aplusb
Input stream: 1234 5678
6912
>aplusb
Input stream: 123 234 345 456 567 678 789 890
4082

Batch files are a bit arcane, it’s true, but the extensions added post Windows 2000 make it a lot more entertaining.

Wednesday, February 10, 2010

[VBScript] Small contributions to RosettaCode

I recently discovered RosettaCode. The initial blurb from the site is as follows:

Rosetta Code is a programming chrestomathy site. The idea is to present solutions to the same task in as many different languages as possible, to demonstrate how languages are similar and different, and to aid a person with a grounding in one approach to a problem in learning another. Rosetta Code currently has 370 tasks, and covers 195 languages, though we do not (and cannot) have solutions to every task in every language.

A variety of tasks are listed, and visitors to this site are invited to solve the tasks in the language of their choice. The tasks cover everything from the mundane Empty Program to the classic Towers of Hanoi, the practical User Input, the mathematically-inclined Lucas-Lehmer test, and the involved yet entertaining RCRPG.

I have made some small contributions to its collection of VBScript programs, as below:

99 Bottles of Beer Array concatenation Assertions Delete a file Execute a Markov algorithm Fibonacci sequence Flatten a list Function definition Generic swap Palindrome detection Pangram checker Program termination Sorting algorithms/Gnome sort Tokenize a string

Feel free to edit what I’ve done and add your own in whatever language takes your fancy.

© Copyright Bruce M. Axtens, 2010.

Saturday, December 12, 2009

[Protium] PLEAC 1.0

<@ OMT>-----------------------------</@>

<@ LETVARLIT>string|\n</@>
<@ OMT>two characters, \ and n</@>
<@ LETVARLIT>string|Jon 'Maddog' Orwant</@>
<@ OMT>literal single quotes</@>
<@ OMT>-----------------------------</@>

<@ LETVARLIT>string|
</@>
<@ OMT>a "newline" character</@>
<@ LETVARKEY>string|__Newline</@>
<@ OMT>a "newline" character</@>
<@ LETVARLIT>string|Jon "Maddog" Orwant</@>
<@ OMT>literal double quotes</@>
<@ LETVAREXPLIT>string|Jon &pipe;Maddog&pipe; Orwant</@>
<@ LETVAREXPLIT>string|Jon <&prot;>Maddog</&prot;> Orwant</@>
<@ OMT>Because | and <@ and </@ are significant there are ways to quote them</@>
<@ LETVARLIT>Bruce Goose|布魯斯鵝</@>
<@ OMT>a variable name containing spaces.
A variable containing Unicode.
Programming code in Unicode.</@>
<@ OMT>-----------------------------</@>

<@ OMT>Multi-line strings.
There is no equivalent to perl's "here" documents in Protium</@>

<@ LETVARLIT>a|
This is a multiline string
that spans 3 lines (it contains 3 newline characters).
</@>

<@ LETVARLIT>string|This is a multiline string
that spans 2 lines (it contains 1 newline character).</@>

<@ OMT>-----------------------------</@>

[Protium] PLEAC in Protium

PLEAC, for those unfamiliar with it, is the Programming Language Examples Alike Cookbook. This is a brilliant site which takes examples of Perl, given in Perl Cookbook by Christiansen and Torkington, and invites contributors to demonstrate how other languages implement the same functionality. Many languages are in the process of being compared and contrasted in this way, including Python, Ruby, Tcl and Haskell. All manner of functionality is covered, from Strings, Numbers, Dates and Times through to Internet Services, CGI Programming and Web Automation.

For the next few postings I am going to do a PLEAC for Protium. You won't find Protium on PLEAC's pages because PLEAC is limited to open-source languages. Protium is proprietary and closed-source (at present.)

The challenge with converting from Perl to Protium is similar to that faced by linguists translating from one human language to another: do you translate the sense of the utterance, or do you just translate word for word. For example, the Tok Pisin word rabisman literally means "rubbish man". However, it is almost never used that way. Instead it often carries the sense of "fool" or "good-for-nothing." So when converting the Perl to Protium, I've tried to give the sense of the Perl, rather than follow it line for line or word for word.

There will be the odd non-PLEAC posting, but I will try to work my way through the entire PLEAC, all 300K's worth.

Wednesday, October 14, 2009

[Jabaco] JaCOB and WScript.Network

I wonder about myself sometimes. Am I sane? For instance, I’ve taken recently to learning and developing with Jabaco. This would seem from one angle, good, and from another, daft. 

Jabaco is a simple programming language with a Visual Basic like syntax. Jabaco enables you to create powerful software for all Java supported operating systems.

So there you have it: a VB6-alike (more or less) syntax targeting the JVM. In my experience, people bagging VB syntax are in the majority. People bagging Java aren’t infrequent either. And I know Java about as well as I know Babylonia Cuneiform.

That said, it’s been a bit of fun figuring things out in Jabaco, and discovering just how effectively one can hook into the Java subsystem.

The code below demonstrates The JACOB Project: A JAva-COM Bridge talking to WScript.Network. Comments are a bit sparse, but VB folk should be able to figure it out quick enough.

Public Sub main(ByJava args() As String)
   Dim myArgs() As String
   myArgs = args
   Dim oShell As ActiveXComponent
'ActiveXComponent is exported by JACOB and referenced in the IDE
'(yes, there’s an IDE, and it’s pretty good too) Set oShell = New ActiveXComponent("WScript.Network") Dim a As String Dim b As String Dim c As String Dim dShell As Dispatch
'Dispatch also part of JACOB. Nice that it uses the standard jargon Set dShell = oShell.getObject() a = Dispatch.call(dShell,"UserDomain") b = Dispatch.call(dShell,"ComputerName") c = Dispatch.call(dShell,"UserName") MsgBox (a & ", " & b & ", " & c) comthread.Release() End Sub

The IDE makes possible ‘compiling’ to an EXE. The code above compiles to about 400K. Of course, the presence of a JRE is implied. And it runs, nicely.

I think I’ll be spending more time with Jabaco. It’s got a lot of promise, especially for the VB-deranged like me.

© Copyright Bruce M. Axtens, 2009.

Thursday, July 02, 2009

[VB6] Using VBScript's Escape and UnEscape

Something again from an answer I gave on StackOverflow. This one demonstrates how to use MSScriptControl.ScriptControl to make VBScript's Escape and Unescape functions available to the VB6 programmer.

The best thing would be add MSSCRIPT.OCX to the project, but for the sake of demonstration, I'll use CreateObject instead.


Using the code is easy.


It's that simple. And the technique can be used to get at other VBScript functionality. In fact, .Language can have values other than "VBScript", making it possible to interface to any language with a Windows Scripting Host presence.

© Copyright Bruce M. Axtens, 2009

Tuesday, May 19, 2009

[VB6] MAXDOUBLE, MINDOUBLE, +INFINITY, -INFINITY and NaN

VB6 doesn't seem to be able to specify that a Double contains MAXDOUBLE, MINDOUBLE, +INFINITY, -INFINITY or NaN. (I could be wrong on that as there may be some undocumented feature hiding in there somewhere.)

Anyway, I came up with a way of storing these values into Doubles so that they could be used in a Complex Numbers library I've been writing.

Essentially, I create an 8 byte array, load it up with the relevant values, and then, using API calls and the VarPtr function, store the contents of the array into the storage used by the Double.

Here's the code. First the declarations.


Then the routine that does the work.


Finally, a slice out of the Complex Numbers project demonstrating the use of some of these declarations.


Enjoy!


© Copyright Bruce M. Axtens, 2009

Thursday, May 14, 2009

[VB6]Searching an ActiveX/COM object for a method

This article was first posted by me on StackOverflow in response to my own question, "How do I search an ActiveX/COM object for a method?". This article is an edited version of the original.

"After Googling around not quite finding what I wanted, I remembered the
Edanmo site which got me thinking about TLBINF32.DLL, downloading Microsoft's TLBINF32.CHM and reading up on GetMembersWithSubStringEx.

Below is the implementation of it (done in VB6 with a reference to TLBINF32.DLL), some demo VBScript and output, and the wrapping of that functionality in some VBA.


VBScript demo. The above code was included in my StdLib DLL in the Registry coclass.


Output from the demo (script was run in SciTE).


Finally, the VBA code. A cell has a symbol in it and this routine finds it or returns an error string. (reg. in this case refers to the Registry coclass in the StdLib.DLL)


Hmm ... no error checking. Should fix that.

© Copyright Bruce M. Axtens, 2009

Sunday, April 12, 2009

[newLISP] restart-router

The boss said I'd find Lisp addictive, and he was right.

The following is a
newLISP implementation of a project attempted in VB6. The VB6 one failed to work consistently. The newLISP one hasn't failed yet.

The situation is that our ADSL connection goes down at random times, necessitating a walk down the hall to the comms room, wherein one turns off the power to the router so that it resets. I found out during the week that if I telnet into the router, give the appropriate password and the enter 'restart', that'll restart the router. Will it reduce the need to walk to the comms room? I really don't know as, all of a sudden, the router is working fine.

Here's the code:
I really like the fourth parameter on the net-receive call; not only do I receive but I can look for something in what is received. I suppose testing for not receiving it would be good, but I'll leave that for another time.

Once the restart command is sent, there's no need to attempt a net-receive. Just close the connection. Note also the easy way of referring to and using a function in a DLL.

Using the link.lsp script (which comes in the standard newLISP install) I've been able to turn this code into a standalone EXE, and once I've established that it really does do the job, I'll install it on a couple of other machines in the office.

I suppose we actually need the exercise, but maybe we don't need the aggravation.

By the way, my last newLISP posting has generated an interesting conversation on
comp.lang.misc (also mirrored on comp.lang.lisp).

© Copyright Bruce M. Axtens, 2009

Thursday, April 09, 2009

[newLISP] reverse-find

I've always thought learning Lisp would be a good thing to do. The purists may argue that newLISP is not the best place to start. Oh well, too bad.

Below is my first (ever) lambda expression, a port of the VBScript RevInstr() function.


I must say I'm impressed with newLISP. Note that the minus (-) function above can receive more than one argument. A lot of the functions are like that.

Using the reverse-find is very like the (find) function, as below



One thing that differentiates my lambda expression from the in-built find, is in the manner in which an error is flagged.



I'm not sure at this point why the difference and what to do about it. In my use of (find) I check for a result equal to nil, but with (reverse-find) I have to check to see if the result is a string. For example,



Doubtless, someone in the
newLISP Fan Club will set me straight soon.

© Copyright Bruce M. Axtens, 2009

Friday, November 28, 2008

[Shameless Plug] Resistance Is Useless (an iPhone / iPod Touch app)

A good friend of mine has recently developed an iPhone / iPod Touch app for decoding the colour bands of 4, 5 and 6 band resistors. Check it out!



© Copyright Bruce M. Axtens, 2008

Monday, November 03, 2008

[Networks] How to calculate a netmask

To say that I've been busy of late is somewhat of an understatement. Mind you, I've had time to create a presence over on StackOverflow, and to start "playing" MouseHunt on FaceBook.

I was responding to something over on StackOverflow: "
What’s the best way to convert from network bitcount to netmask?" and added my two-bob to the mix with the following bit of VBScript.
A few examples runs are as follows:
It's been ages since I did the Cisco coursework (never did sit the exam) so I'm not sure if it's totally correct.

The binary2hexadecimal and binary2decimal functions were interesting to write as I was trying to find simpler, more lateral ways of doing things.
© Copyright Bruce M. Axtens, 2008

Monday, July 28, 2008

[Delphi] Updating SysTray

I'd been lurking at ITtoolbox for a while and saw this request for help with updating the system tray.

I've had similar problems myself. For instance, if you use boost or some similar process-control tool to kill the Skype.exe and SkypePM.exe programs, the processes disappear from memory but the system tray still shows the Skype icon until you move the mouse over the icon. Then the tray refreshes, the Skype icon disappears and the remaining icons rearrange.

On
Experts Exchange I found a bit of Delphi code which moves the mouse over the systray (using system messages rather than moving the mouse pointer itself.) This convinces Windows to update the systray. Because not everyone has an Experts Exchange membership, I've turned the code into a COM DLL, which you can download. Source is included (Artistic2 license.) A copy of the original Experts Exchange code can be found here.

Once you've registered the DLL (regsvr32 UpdateSysTray.DLL) you can use it in anything that supports ActiveX/COM objects. For example, in VBScript:


© Copyright Bruce M. Axtens, 2008

Tuesday, June 10, 2008

[VBScript] StandardLibrary.zip

For those interested, who haven't been able to download it recently, here's the latest iteration of StandardLibrary.vbs. Now it's called stdlib.vbs and can be obtained from my boost account at the Perth Linux Users Group.

There have been a few changes, mostly additional functions and the odd tweak in favour of better functionality.

Significant in the additions are a few functions for sending emails: Blat, BlatAttachment, ErrorEmail, ErrorEmailApp, RedemptionSend and ThunderbirdSend. If I remember correctly, ErrorEmail has been around for a while, but is included here for completeness sake.













A while back Derek Parnell wrote a replacement for
Euphoria's print function which would show the structure of arrays. ShowStructure and a support routine AsString make this available to the VBScript programmer. By the way, in case you haven't heard, Euphoria is now open-source!



The output, then, from code such as this:
would be
which maybe leads on toward data serialisation ...

There've been some additions to the file handling space, with the addition of routines to read and write unicode files (ReadFileU, WriteFileU, ReadFirstLineU and its ANSI equivalent, ReadFirstLine.)

Logging has been worked on. It's something I'm unlikely to be totally happy with, but there's now a SetLog and a ClearLog as well as the standard Log (and, given the possibility of confusion with the logarithm system, maybe I should change it to Trace (oh man, how many scripts that would break!))

What else? Well, BuildTree builds a directory tree. FirstLineOf returns the first vbNewLine-delimited line from a string (useful where you've used ReadFile or ReadFileU to inhale an entire file.) LastLineOf does what FirstLineOf does but for the end of the file, and NthLineOf gets you the ... nth ... line.

I've actually forgotten what I wrote UpToAndAfter for, but it's included anyway.

IsOnLine uses the ResolveIP function with the IP address 198.182.196.48 (which points somewhere on linux.org) to see if you are still on line.

SetPriority uses the same code as used in BOOST to set process priority.

StrInArray finds a string in an array of strings, with optional case sensitivity.

StringMap scans a string for the presence of items in one array and swaps them for the equivalently indexed elements in the second array. If the second array is a string, they get swapped for that string.

Doze wraps WSCript.Sleep and HTASleep, so that it can be used in .VBS files and .HTA files.

ModalThing2 shows a modal dialog (only works in .HTA files)

And, finally, SoundMessage:


Obviously, if you see something that needs to be fixed, fix it. And tell me to fix it so that it can be fixed in the distribution and your name can be added to the list of contributors.

© Copyright Bruce M. Axtens, 2008

[Visual BASIC 6] BOOST (v3)

BOOST got another look-in recently. I had been using it exclusively to do "realtime" and "kill". This particular time I tried to do an "abovenormal" -- instead it did a "kill".

In the process of finding and fixing that bug, I replaced the Collection mechanism with the augmented Collection supplied by the "Class Builder" add-in.

The source code is essentially the same as before but with a few changes. First the SysVars and Var classes. (The comments are predominantly those supplied by the add-in.)

First, SysVars.cls:


Next, Vars.cls (it's tiny but it could hold so much more):


Now the main module. The first thing that is different here, is that nLevel is now a Long. Integer doesn't handle the ABOVENORMAL_PRIORITY value without complaint.

Next change is removing the reference to Collection, changing it to SysVars and setting up the values.

The benefit of using SysVars and that approach to the Collection object is that we now have an .Exists method, so we now have a tidier way of setting nLevel and trapping invalid settings thereof.



All the other routines are as before.

I haven't gotten around to extending this tool to do stuff to remote computers. It's not hard; killing a process on another machine means another value for sComputer in KillProcess, and, of course, the relevant privilege level.

© Copyright Bruce M. Axtens, 2008

Tuesday, March 11, 2008

[Perl] How to do it better

There are some really helpful people in the Perl community. I advertised the original posting on comp.lang.perl.misc and received some very useful responses from John W. Krahn and Michele Dondi, as below.

With respect to the rules, John wrote:



John> Why [were] you converting the '|' character and the 'e' character to 'e'?



John> The . character class matches a lot more than just letters, or did you really mean "replace any first character except newline with 'n'".



John> The . character class matches a lot more than just letters.



Then, with respect to the string eval() of each rule, John said, "Ouch! Use a dispatch table instead of string eval()."



At this point Michele Dondi chipped in with, ">my %rule = (
>  1 => sub {
>    ( my $arg = shift ) =~ tr/s//d;
>    return $arg;
>    },
>  2 => sub {
>    return join '', sort split //, shift;
>    },

Since the keys are numbers, an array may be appropriate."

So there you have it, better rules, anonymous subroutines, and hashes. Powerful stuff.

I wonder how Tcl and the other languages would have done it. Or Protium, for that matter. Any takers?

© Copyright Bruce M. Axtens, 2008

Sunday, March 02, 2008

[Perl] How not to do it?

The header for this website says, "Some useful stuff and some examples of how not to do it." This may fall into the latter category.

One of my kids had been playing a computer-based game which used a variety of word puzzles. The question he posed to me was to take a word, apply a small set of rules to it, as many times as necessary, and come up with another word. He would supply the rules and both words, and I would supply the sequence of rule applications which would effect the conversion.

(I'm no guru when it comes to Perl, so if you see something that could be expressed in a more efficient manner, please let me know.)

These are the rules:

1. Remove all 's'



2. Sort the characters of the word into alphabetic order



3. Convert all vowels to 'e'



4. Replace the first letter with 'n'



5. Drop the last letter



6. Replace letter pairs with 'ow'



My son then said that the start word was 'first' (or 'ant') and the stop word was 'now'. After some fiddling, resulting in the code below, I said, "With these rules you can't get from 'first' to 'now'. Not even from 'ant' to 'now'. But from 'gnat', yes."

So here's the code, for what it's worth. It was assumed that this would be run as a command line tool, so I load up the start word (stored in $root) and a recursion management flag (stored in $managed). Recursion management is defaulted to true. The recursion level is marked with $level and there's a hash, called %deadends, to keep track of "solutions" that shouldn't be pushed any further as they have already been proved not to get any closer to the solution.



Everything else happens in the apply function which looks at every possible combination of rules in pursuit of the target word. After getting the word to check from @_ with shift, a couple of variables are declared and a for loop initiated, stepping through the rules.



Each rule is evaluated against the passed in value in $arg, and stored in $res. $reason is cleared and each test applied to $res.



If $res is the same as $arg, $reason is "equal". If the length of $res is less than 3, $reason is set to "too short". If $managed is 1, and $res is already in the %deadends hash, $reason is set to "deadend", and if $res is equal to "now" (the goal, as it happens) then $reason is set to "found".



If $reason is not empty and not "equal" then print a newline, as many spaces as there are levels of recursion, the rule that got us here, the incoming word and the result of the rule application. If $reason is "deadend" then print an exclamation mark to show that a deadend has been reached, otherwise print a full stop.



If we've actually reached "now", indicate that with an asterisk. (We could exit the script at this point, but I left it to show all the possible paths to the stop word.)



If managing recursion, store the value of $res in the deadends hash.



Now, if $reason is, for some reason, empty, print a newline, as many spaces as there are recursion levels, the rule, and the $arg and the $res. Then increase the value of $level and recursively call apply with the contents of $res. When it returns, decrease the value of $level.



Here's the first call to apply, with a newline displayed once processing returns from the call.



Keeping track of dead-ends proved useful. Without it, the 'first' to 'now' attempt generated at 406K file (redirecting the output). With it, I got a 5K file. Similarly, 'ant' to 'now' was 1.8K without, and 457 bytes with. When it came to starting with 'gnat', a managed conversion generated an 8K file. Without management the laptop slowed to a crawl. After about five minutes I got an "Out of memory!" on stderr, so I killed the perl processing resulting in a 902 Megabyte file.

This is the result of a managed attempt with 'ant' as the start word:



Sadly, no asterisks. Next, the log of a managed run starting with 'gnat'. Success came quite quickly: start with 'gnat' and apply rules 2, 3, 4, 2, 4, 5, 6 and 2. An even shorter path appears further down: 3, 4, 2, 5, 6, and 4. The shortest appears to be 4, 2, 5, 6, 4 -- nnat, annt, ann, aow, now.



Writing this makes me wonder if I should have found some way to jump from a successful traversal back to 'gnat' rather than applying the rules to instances of 'now' in search of an extended path to 'now'. I leave that as an exercise to the reader, and if you work out how to do it, please let me know.

© Copyright Bruce M. Axtens, 2008