Anti-nuisance lawsuit warning: The purpose of these notes is to remind me, Zoegond, of stuff or to help me work stuff out. They may contain mistakes.

Quick

  • ($a, $b....) = unpack("A2A7...", $packed)
  • push( array, list )

Saturday, November 26, 2011

Stop Clamwin in system tray

Get rid of the system tray icon that appears when you install a new version of Clamwin by opening HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run in regedit, and deleting the key with clamtray.exe in it.

Or use the excellent Clamwin Portable.

AC3 to WAV

To convert an AC3 file to WAV I used BeSweet's AC3 to WAV option. (The BeSweet GUI is the simplest way to do this if you aren't used to the program - though the file selection controls are a bit retro).

Extracting audio from VOB/IFO combinations

The method that worked for me was to use PGCDemux, pointing it to the IFO file and ticking 'Demux all audio streams' (and no other boxes). This produced an AC3 file which Media Player Classic was able to play.

Monday, November 7, 2011

Perl regexp grouping

A group which has ? after it to make it optional will 'use up' a grouping variable whether or not it gets matched. So

/(a)?(b)/

will place "b" in $2 whether matched against "ab" or "b".

Monday, October 31, 2011

Perl mkdir, make_path and mkpath

mkdir can only create directories in directories that already exist. So if you say

mkdir("c:\\season1\\unearthly\\ep1\\caps");

it will only work if directory c:\season1\unearthly\ep1 already exists.

File::Path::make_path() will create a directory and any necessary ancestor directories (must use mkpath() instead on Perl 5.10 and possibly other versions earlier than 5.14).

NB it's File::Path:: not File::Path-> - the latter will give you a misleading error "mkdir File::.: Invalid argument; The filename, directory name, or volume label syntax is incorrect" .

Wednesday, October 26, 2011

Perl and large integers

Trying to get a straight answer to the question 'What is the largest integer Perl can handle on Win32?' and failing, I decided to ask Perl, eventually ending up with the questions

perl -e "print 2**49+1"
perl -e "print -2**49-1"


and getting precise answers.

So on my 32-bit Windows the answer is "more than 2^49 and less than 2^50".

readdir

readdir returns bare file names without any path. Also there will be two results "." and ".." representing current and parent directories (unless the directory is the drive root, in which case on Win32 neither seems to be present, but since everyone throws both of them away it probably doesn't matter).

Monday, October 24, 2011

Combo box dropdown failure

A combo box won't drop down unless the vertical size you gave it includes enough space for (a) the edit box bit and (b) at least one row (?) of the drop-down bit.

So if you're using, say, a constant YHIGH for controls with one line of text, your combo box height should be in the region of YHIGH * number of lines to show in the drop down. Don't worry, it won't expand the edit box bit to take up all that space.

(Thanks to this post)

CreateProcess

Using CreateProcess opens two handles (one for a thread, one for a process) which are stored by Windows in the PROCESS_INFORMATION structure that you supplied with CreateProcess.

You should close both if the child process exits while your program is still running - but it also seems you can close them any time before this without causing your child process to exit. (Obviously then you can't communicate with the child). I'd want to do this if I'd started a process so that the user could interact with it.

Pointers to member functions

A pointer to a member function returning int, say, is not the same type as a pointer to a function returning int.

This buggers up any attempt to do anything simple like supplying a pointer to one of your class members where Windows expects a WNDPROC.

Don't think there is any easy way round this. This explains some more complicated ways round it.

Saturday, October 22, 2011

Perl system and synchronicity

system("calc");

runs the Calculator and waits till the user closes it.

system("cmd /c start calc");


runs the Calculator and continues with your script without waiting.

system("cmd /c start /wait calc");


has the same effect as system("calc").

Friday, October 21, 2011

AAD and AAM

You can use AAD and AAM (ASCII adjust for Division/Multiplication) to do quick decimal-binary conversions for numbers 0-99.

Suppose AX = 0506h (representing decimal digits 5 and 6 for the decimal number 56)

then AAD will set AX = 0038h (56d)

and then AAM will set AX = 0506h.

So AAD converts 2 digits in AX to binary in AL, and AAM converts binary in AL to 2 digits in AX.

(Once you've got your two digits you can easily turn them into ASCII characters by adding 30h to each byte and adjusting for the characters between '9' and 'A').

Tuesday, October 18, 2011

Endianness

I'm surprised I could have forgotten this but - if you have the following

mem: dw 0
mov ax,1
mov [mem],ax

the two bytes at /mem/ will be set to 01 00, not 00 01.

Saturday, October 15, 2011

Astronomy sky diagrams and photos often have a little key to indicate if they're erect views, inverted views or mirror views.

What used to puzzle me is that an erect view is indicated by

 N
E+

when that looks like it should mean a laterally reflected view, as E is on the 'wrong' side.

But then I realised that when you're looking up at the sky (which is the perspective that a sky photo has) you're looking OUT of the map, not INTO it. Consequently E and W are reversed.

Thursday, October 13, 2011

Giving up smoking

Preparation

(Before you start smoking...
1. Don't. If you think getting used to smoking, not being sick etc is hard, wait till you try getting used to not smoking.
2. Pick a brand that is a bit unusual and not available in all shops. Like B&H 100s.)


1. Pick a date to stop and stick to it. It should be a work day or a day on which you will have something to occupy you most of the time.
2. If you're going to use a nicotine replacement method, pick one and have at least a week's supply. Consider using two, like gum and an inhaler, in case like me you don't fancy chewing gum right after breakfast.
3. If you habitually smoke in the same places (chair, room etc) at home, choose a different, temporary place and stick to it.
4. If you usually buy cigarettes at the same shop, be prepared to stop going there. Find somewhere else to buy anything else that you get from there (lottery tickets have been my downfall).
5. Start keeping your cigarettes in a different room to where you usually smoke. The short walk before each smoke helps disrupt your habit.
6. Explain to smoking friends that you're going to stop. If they take offence, well, they aren't your friends.
7. Consider getting a prescription for Champix. It worked for me, it really took the edge off the initial cravings. And it didn't make me go mental (or more mental) as some websites suggest. Also, now that I know it works, if I do start smoking again, I can't use the excuse that stopping would be too hard, because Champix will always be there. If you follow this route, start the Champix 3 days before you stop smoking.

The day before - morning
1. Have your first cigarette of the day in a different place or at a different time. This will disrupt your expectations of getting one tomorrow morning.

The day before - before your last cigarette
1. Tomorrow you will have 4-5 minutes' spare time in the morning for each cigarette you usually smoke before going out. Set your alarm later to correspond (eg I used to have 3 fags in the morning, so I gave myself 10 minutes extra in bed).
2. Get a brush ready to clean up your smoking areas.
3. Dispose of all surplus cigarettes. I flush mine down the toilet. You don't want to find yourself going through the bins tomorrow.

The day before - after your last cigarette
1. Clean up all dropped ash from your smoking areas. If you can, move the chair or other furniture to make it difficult to sit there tomorrow.
2. Empty all ashtrays (into a non-flammable container!) Do it now. Don't leave them lying around as the smell will make you want to smoke tomorrow. Throw them out when they're empty, or put them at the back of a cupboard or the back of your car or somewhere where you won't see them for a few weeks.
3. Throw out all empty packets, cellophane etc.
4. Put any nicotine replacement supplies ready.
5. Go to bed.

The day
1. Change your starting routine - if you associate cigarettes with coffee, have orange juice instead etc.
2. Take any nicotine replacement supplies with you when you go out.
3. Don't go into your usual cigarette purchasing places.
4. Be prepared for temptation and be prepared to ignore it. Each one goes away after a few minutes. I get 20-30 spells of temptation on the first day. Remind yourself each time that, if you give in, you'll be disappointed in yourself in an hour's time; if you don't give in, you'll be pleased and proud of yourself in an hour's time.
5. Don't court temptation - don't stand around with people who smoke, don't watch them.
6. Use any nicotine replacement as directed. If it's an 'on-demand' method like gum or an inhaler, use it at regular intervals. DON'T let a need for nicotine build up, it will feel too much like you're hungry for a cigarette.
7. Completed the first day? Reward yourself with a treat. Something sweet, or a drink (unless you associate drinking with smoking). Well done!

Days 2-3
There will be fewer spells of temptation but they keep coming. Don't let up on the anti-temptation measures. Reward yourself again.

Days 4-5
These will be easier and there might be quite long periods of time where you don't think about smoking at all. Now don't start thinking 'Oh, that was easy. I can start again and then stop again.' You'll have to go through the first 3 days again if you do! If you don't, you will NEVER AGAIN have to do that. Keep up with the rewards too.

Subsequently...
If I get to day 6, I've done it. Your mileage may vary. Danger points for me are 2 weeks, a month, 2 months and 3 months. After 2 or 3 weeks you will feel less need for any nicotine replacements you've been using. Don't fret if it takes longer, ANY nicotine replacement is many times healthier than smoking. The nicotine receptors in your brain WILL eventually reset themselves and stop demanding nicotine.

(If you fail...
Each time you don't succeed increases your chance next time, because you've learnt more about the pitfalls. Set a new stopping date, ideally within a week)


After a month you can stop avoiding cigarette purchase locations if you feel confident. From here on it's just a matter of not starting agan.

Monday, October 10, 2011

Constructors, temporary objects and initialisation

With this setup (two constructors, a copy constructor and the destructor)

class A {
A() {...}
A(int i) {...}
A(const A &a) {...}
~A() {...}
};

{
A c = A(11);
}


results in one call to the int constructor and one call to the destructor, whereas

{
A d;
d = A(11);
}


results in one call to the no-argument constructor, then one call to the int constructor when the temporary object is created, then a call to the destructor when its statement is complete; finally another destructor call when d goes out of scope.

NB btw that although both these forms look like they have an assignment in them, because it's in a definition, an assignment is not actually performed (and any assignment operator is not called). This situation counts as an initialisation not an assignment.

Sunday, October 9, 2011

new and constructors

C++ is not C# - these two forms have different effects

{
A v = A(9);
A *w = new A(8);
}


The first one constructs a temporary A and assigns it to v. Constructor A(int) is called exactly once, and when v goes out of scope, ~A is called.

The second one allocates an A-sized piece of memory, constructs a temporary A, assigns it to that piece of memory, and sets w to point to it. Constructor A(int) is called exactly once, but when w goes out of scope, ~A is not called. The only destructor that would get called here is the one for type A*, and A* isn't a class so either there isn't one, or there is one that does nothing. Either way it isn't what you want.

Wednesday, October 5, 2011

Choice of language

Perl is my first choice of language for writing tools for my own use. But recently I've been using C++ more instead, because I get an executable which can be stored on the PATH and is therefore quicker to invoke than typing the path to Perl and the path to the scripts directory.

But... The last tool I needed was a program to rewrite a list of files in order so that their modification time order was the same as their name order. This took 12 hours' C++ development time - I had to write a Directory class, a string class and a Rewriter class as well as debug my memory allocation.

For comparison, I wrote the same thing in Perl and it took 2 hours. I still had to write a Rewriter class but of course the Perl version took much less time to create.

Now, assuming each invocation of the C++ version is 10 seconds faster to type, I've got to use the tool 3600 times to get back the extra development time I invested in the C++ version. Which I'm probably not going to do as I only need it for reordering image files so they come out right in gallery viewers.

Of course, the C++ version runs faster, but I don't need it to run faster. The sole gain was in the experience of writing C++, which I haven't done in earnest for about 15 years.

So the moral of the story is not just to consider development time, or execution time, but also how often you're going to use the program you're writing.

Tuesday, October 4, 2011

argv and argc

argc is the count of arguments including argv[0] (the executable name), so argv[argc] == 0.

C++ static member functions

If you're defining an out-of-class static member function, don't put static in the definition, or it won't compile. Just put it in the declaration.

class Thing {
public:
static int f(char *g);
};

int Thing::f(char *g) {
...
}

Monday, October 3, 2011

do while is not a loop

I've found that if you have a loop like this

$i = 0;
do {
print "$i ";
last if $i == 3;
++$i;
} while ($i != 10);

you will get the run-time error 'Can't "last" outside a loop block' when $i reaches 3.

Putting the 'last' in a proper if() {} block doesn't make any difference.

Apparently this occurs because do { } is just a grouping block, not a looping one, and the while here is the statement modifier while, not the control structure while. do { } is what you use if you want to put a statement modifier on a block of statements - { } alone just won't 'do'.

While that makes a sort of sense, a big red warning in Programming Perl would have helped. 'Do not use! Useful construct merely simulated!'

Additionally: what makes this really dangerous is that, if it occurs in a sub called from within a genuine while, the last will immediately jump out of the genuine loop (even if that loop's in a different scope) without any error or warning message. DO NOT USE.

C++ structs

There doesn't seem to be anything a class can do that a struct can't. The only official difference I can find is that struct members are public by default.

mingw maximum file name length

The maximum file name/path length with mingw appears to be FILENAME_MAX, not NAME_MAX.

Saturday, September 24, 2011

C++ conversion

int(n) and (int)n have exactly the same effect. But the C++-style int() syntax can only be used with types which have 'simple names' (I think this means eg int but not int *).

This explains btw why the mistaken use of

p = new int(n);

instead of

p = new int[n];

doesn't cause a warning or error: the compiler thinks you want a pointer to a new int, which int has been initialised with n.

C++ references

The & operator is no different to other operators when used on a reference: in all cases, the reference is dereferenced first. So

int i;
int &r = i;
int *p;

p = &r;

gives you a pointer to i in p. &r dereferences r, to get i, before taking its address.

C++ constructor fumblings

Object a;

causes the constructor for Object to be called.

Object *pa;

does not (as I expected), but

pa = new Object;

does, which I suppose I also expected.

If it doesn't exist then the compiler gives up. Interestingly, gcc reports the constructors it does find, and I noticed that if I define no constructors at all for Object, then there is no complaint from the compiler, but if the only one I define is an unsuitable candidate, then gcc reports trying both my constructor and Object::Object(const Object&).

This is really confusing, it suggests that if no constructors are defined, then one for no arguments is created by default; but if one is defined, then a copy constructor is created by default??

Thursday, September 22, 2011

gcc gotchas and easy mistakes

(all these notes are re gcc with mingw)

The 'cc' in 'gcc' is not a way of representing 'C++'. There is a separate invocation g++ - if you use gcc instead of g++ you'll get tons of confusing errors as soon as your program incorporates anything too C++-ish, like templates.

PRECOMPILED HEADERS

I get the impression that compiling header files in order to check their syntax leaves some kind of precompiled header behind that gcc will use in future compilations, which is not what you want if you're frequently changing a header file that you're writing.

I couldn't find any .pch or .gch files lying about that might be implementing this - because I was looking in the mingw installation directories. The .gch file is written to the directory that the corresponding source file is in.

STL string notes

::c_str() returns char * equivalent.

Saturday, September 17, 2011

Windows API tabbing

To get tabbing between controls working two steps are necessary:

1. The WS_TABSTOP window style must be or'd onto all controls that are to be tab stops.

2. The TranslateMessage/DispatchMessage bit in your GetMessage loop in WinMain should have this condition put round it:

if (!IsDialogMessage(hwnd, &msg)) ...

(hwnd being the handle you got back from CreateWindow and msg being the MSG structure you gave GetMessage a pointer to - see the minimal mingw app)

This stops 'dialogue' messages (which despite their name are useful in any window that contains controls [MSDN]) from being sent to your WindowProc callback. IsDialogMessage doesn't just check the message type; if it detects a dialogue message, it also translates and dispatches it to make the tabbing happen. And that's why the message must not be dispatched to your WindowProc.

Having done all this you should find tabbing miraculously taking place between the controls.

Friday, September 16, 2011

More mingw linking

Been trying a series of progressively bolder mini-apps, starting with the mingw minimal Windows app and working upwards.

It wasn't till I tried to use GetStockObject or SystemParametersInfo that I needed to put -mwindows into the gcc command line. Probably because those are both functions from libraries (user32 and wingdi) whereas no library is given for eg CreateWindow.

Windows API basics & gotchas

When supplying a window width and height to CreateWindow, NB that this will be the size of the whole window, not just the client rectangle (the usable bit). So to make a window with enough height to accommodate a client rect with height h, you'll need h + caption height + 2 * border height (for top and bottom borders)

Get the various heights with GetSystemMetrics, using constants SM_CYCAPTION and SM_CYBORDER respectively.

mingw minimal Windows app

Article with example minimal program for showing a window and writing text to it and handling closure. To be used as a base.

Just like 1996!

Thursday, September 15, 2011

Taming Java add-on

If you install the Java browser add-on you're liable to find jqs.exe ("Java Quick Starter") consuming system resources at startup. This is because the install adds a Windows service called "Java Quick Starter". Get rid of it with the command

sc delete "JavaQuickStarterService"

NB the lack of spaces in the argument there.

Tested a page which had a Java applet the day after doing this and it worked fine.

Thursday, July 7, 2011

UnxUtils find

Don't use single quotes round a -name spec to the UnxUtils version of find. Use double quotes or no quotes.

\utils\u\find c:\perl -name *.pl -mtime -20
\utils\u\find c:\perl -name "*.pl" -mtime -20

Not
\utils\u\find c:\perl -name '*.pl' -mtime -20


which you're probably used to from the Unix version.


Also, to specify a date range, just use two conditions (they get implicitly ANDed):

\utils\u\find c:\ -name "*.sql" -mtime -30 -mtime +26

Wednesday, June 29, 2011

STL vectors and iterators

vector::end() (like end() for containers generally) returns an iterator, not an element, and it refers to the end+1 position, not the last element position.

Tuesday, June 28, 2011

C++ since 1996

Ongoing notes about how C++ has changed since I last used it.

Namespaces


'using' for namespaces, can specify a whole namespace or just one name from it. Don't have to use using, can use explicit scope prefixes eg

std::string s;

(NB with mingw 'using std' will cause loads of errors with eg '#include vector'. The scope prefix way works fine though. May be some fix for this involving editing stl_user_config.h)

Executable size


If you do use any of the standard libraries, be prepared for a gigantic executable. 100K for declaring a 'string', 125K if you want to assign it too, 500K to print it out via iostream. In a way though this is a good thing as it's effectively offering you a higher level language - if you want a small executable you can still write C++, just not use any standard includes. stdio.h still works if you need it and the executable size is still only 20K for a minimal example.

(NB the huge executable thing is not there under Linux, the minimal executable is about 7K whichever way you do it).

(Further NB that even under Windows most of the hugeness is due to iostream. Using cstdio (ie stdio.h) instead cuts that 500K down to 130K.)


No finally


C++ has no finally in its exception handling. If you need to release a resource, make its pointer a public member of a local class (local classes are allowed, apparently) and have the class's destructor free the resource. Eg

class Allocs {
public: char *stem;
~Allocs() { delete stem; }
};
Allocs m;

Saturday, June 25, 2011

Dual boot Ubuntu and Windows 7 - how did I do it?

I've now got the dual-booting installation of Ubuntu 11.04 and Windows 7 that I wanted, but I'm buggered if I know how I managed it.

The steps I took were:

1. Made a Ubuntu live USB with unetbootin which I used to test hardware compatibility. The persistence feature on the USB didn't work, in fact it led to hangs every time I tried it, but Ubuntu itself worked fine.

2. Used Windows disc management to make two new partitions on the HD, a 40G one for Ubuntu and an 8G one for swap.

3. Made a Ubuntu installation USB with unetbootin and installed Ubuntu to the partition I'd made. I specifically didn't use the option to alter the boot setup at all because my experience with Windows XP and Linux was that doing this buggers up the Windows boot mechanism and it has to be fixed using a Windows tool.

4. Made a Super Grub Disc USB using unetbootin and tried to boot the HD Ubuntu with it. This didn't work, because as I found out later, Ubuntu uses Grub2 not 'Legacy' Grub.

5. Tried to make a Super Grub2 Disc USB with unetbootin. Although I got a boot menu off this it wouldn't work at all. As I found out later, unetbootin can't make SG2 USBs.

6. Made an SG2 USB with Windows dd. This worked perfectly, detecting Ubuntu and Windows 7. Booted into Ubuntu from it, all good.

7. Restarted the notebook intending to boot Windows and use bcdedit to put Ubuntu onto the Windows boot menu. But I got a Ubuntu-branded Grub2 menu - presumably Ubuntu had put that there when I installed it on the HD. (I'm sure I ran Windows at least once after that installation, though, and I didn't get the menu then).

8. Booted Ubuntu from this menu, worked fine. Restarted and booted Windows from this menu, worked fine. Have run both several times since with no problems.

So I'm pleased, but perplexed.

Wednesday, June 22, 2011

Windows dd for Super Grub2 Disk live usb

I wanted to create a live usb for Super Grub2 Disc, and unetbootin currently won't do that properly.

So I got hold of Windows dd and used that.

First did

dd --list

to find which device name the USB stick had (in this case \\?\Device\Harddisk1\Partition0). Then

dd --filter=removable --progress --size bs=32k if=c:\super_grub_disk_hybrid-1.98s1.iso of=\\?\Device\Harddisk1\Partition0

to write the image to the stick. It booted fine and I was able to locate and boot the Ubuntu installation I'd lost on my HD.

(I used bs=32k because the iso is very small - 1.4M - and I wanted to see some evidence that it was being written. You'd use bs=1M or larger to write a full-size CD iso.)


(Updated to say: --filter-removable is a safety precaution. It restricts writing only to discs which dd believes to be removeable. Sometimes dd --list will report a disc as removeable, but dd --filter-removable will refuse to write to it, thinking it isn't removeable. In such cases, try omitting the --filter-removable switch, but of course you should make sure you do actually have the right output target.)

Linux

Linux dd may not have any of the -- or - options - try eg
sudo dd status=progress bs=1M if=/U/com/packages/lubunto18.04.iso of=/dev/sdd
noting particularly that you specify a drive (/dev/sdd) here, not a partition (/dev/sdd1).)

I read that sync is no use afterwards, the equivalent is eg
blockdev --flushbufs /dev/sdd

Thursday, June 16, 2011

Ubuntu persistence

Persistence on live USB keeps going wrong and leading to stalled boots - boot can always be achieved by removing 'persistent' from boot params.

Can use a second live USB with Puppy Linux to read the first USB and check the casper-rw file (can't do it from live Ubuntu as casper-rw is mounted). NB that in this case we're using a path to a file, not a device name, as the first argument to mount because the filesystem we're mounting is inside a file.

mkdir /mnt/cas
mount /mnt/sdb1/casper-rw /mnt/cas -o loop

(the /mnt/sdb1 bit may be different according to where Puppy has mounted the USB)

We can now ls /mnt/cas to see the files inside casper-rw. And we can also check the filesystem:

fsck -y /mnt/sdb1/casper-rw

(after a stalled boot this will find and fix lots of errors)

Boot with 'persistent' will now work again - though persistence still won't work!

SYSLINUX

SYSLINUX is a Linux boot loader, syslinux.exe is an install program which puts SYSLINUX onto a disc, making it bootable. (Bit like sys a: on DOS). LDLINUX.SYS is also created in root.

SYSLINUX expects a kernel file called LINUX in the disc's root directory. You can change the expected name but not the location.

SYSLINUX can read a syslinux.cfg file from root, /syslinux or /boot/syslinux on the disc. It tries all those locations.

The parameters after an APPEND in the .cfg file are linux kernel parameters.

When unetbootin creates a live USB, what it actually does is install SYSLINUX on the disc, and generate an appropriate .cfg file.

AutoIt3 run command

When running single commands as described under Running Scripts, don't use the double single quotes in the example. Use double double quotes.

"c:\program files\autoit3\autoit3.exe" /autoit3executeline "msgbox(0,""test"",""Testing"")"

Live USBs

Having once created a live USB, if you then write additional files onto it other than by using the application it boots, you may be overwriting parts of the drive that the application is using for persistence. So best not to.

The particular example is creating a Ubuntu live USB and then copying extra files onto the drive from Windows.

Wednesday, June 1, 2011

caspol makes .NET work

CasPol -m -ag 1.2 -url file://xxx2/xxxshare$/xx/src/cs/* FullTrust

NB caspol.exe must not be on a mapped drive, or you'll get "ERROR: Insufficient rights to obtain policy level"

Monday, May 9, 2011

divisors

Q&D aliquot divisor finder

function divisors0(n) {
var divs = [];
var f = 1;
while (f * f <= n) {
if (f == 1 && n != 1) {
divs.push(f);
} else if (f * f == n) {
divs.push(f);
} else if (n % f == 0) {
divs.push(f);
divs.push(n / f);
}
f = f + 1;
}
divs.sort( function(a,b) { return a-b; } );
return divs;
}

Friday, May 6, 2011

C# namespaces

Don't give a class the same name as its namespace as the compiler will stupidly claim that it can't tell them apart, even when it's obvious in context.

C variable initialisation

C variables are not initialised by the compiler unless they're static.

'If they have told me, I've forgotten.'

Thursday, May 5, 2011

Autoit3 concatenation

Autoit3 concatenates strings with &.

If you use + it will perform numeric addition and your result will be a single number.

Tuesday, April 19, 2011

Exponential decay

Suppose a quantity q of substance is emitted by something over a period of time t, and the release is an exponential decay curve, like with cooling.

The proportion of q that has been emitted by an intermediate time h will be



\frac{{}1-e^{-(h/t)}} {1-e^{-1}}

( 1 - exp(-(h/t)) ) / ( 1 - exp(-1) )

The exponent -1 in the divisor is the reduction of -(1/1).

NB that we're saying nothing about whether more substance is emitted after the quantity q has been emitted. In particular the remaining amount of substance is unlikely to be 0 because the exponential decay curve never quite meets the x axis (I think).

Monday, April 11, 2011

Javascript modulo

The Javascript % operator can return a negative result, so in JS

-2 % 7 == -2

whereas in Perl

-2 % 7 == 5

Thursday, April 7, 2011

Powershell format-table

If you supply a property hash to format-table, it will show that column and no others, unless you specify the other columns

... | format-table name,value,@{ label="name_again"; expression = {$_.Name} }

I don't understand why we have a comma separated list of columns here, I haven't seen that syntax elsewhere in PSH yet.

Tuesday, April 5, 2011

Powershell foreach-object

If you do

gci | gc | measure-object -character

you get one measurement, on all the files concatenated together.

More useful is

gci | foreach-object { gc $_.name | Measure-Object -character}

which gives a count for each one.

And more useful still is

gci | foreach-object { $_.name + "," + ( gc $_.name | Measure-Object -character ).Characters }

which shows the file names too.

You have to use the parentheses or it doesn't work at all. You have to use .Characters as otherwise you just get the parent Microsoft.PowerShell.Commands.TextMeasureInfo object. I don't understand why that doesn't happen in the second example, but there you go.

Monday, April 4, 2011

ADO/ODBC dates

If you use ADO with Perl to run database queries, datetime fields will be converted into a character representation which does not necessarily use the default style for your SQL Server installation. This will cause problems if you will be using the representation to insert back into the db.

So if $daterep contains a datetime field which has been selected from the db in this way, then

"insert into table1(datetimefield) values ('$daterep')"

may result in a conversion failure. Put an explicit conversion on the select

"select convert(datetime, datetimefield, 120) daterep"

(You could instead put a conversion on the insert, but you'd have to inspect the data and see which format it was first).

Monday, March 28, 2011

SharpDevelop /r mystery

If there is a SharpDevelop way of doing this

"C:\Program Files\Mono-2.4.2.3\bin\gmcs" prog.cs /r:Interop.IWshRuntimeLibrary.dll

(where Interop.IWshRuntimeLibrary.dll is in current directory), then I haven't been able to find out what it is.
I haven't tried it with that specific example, but for more common reference cases it's simply
-reference:System.Windows.Forms
or whatever

Monday, March 14, 2011

SQL Server unique clustered

Supposedly the 'primary key' constraint has the same effect as the 'unique clustered' one. But I have found that using the latter leads to a different execution plan (and much improved execution time) from the former.

Either way, if you're going to insert a lot of records into a temp table or table var, put a unique clustered constraint/index on it by some method.

Thursday, March 10, 2011

Javascript mistakes

Javascript is not Perl! if you mean

document.activeElement.getAttribute('name')

but you put

document.activeElement.getAttribute(name)

name will silently be created and evaluate as an empty string.

Tuesday, March 1, 2011

DOM simulating a click

Simulating a click on a page element:

click = document.createEvent("UIEvents");
click.initUIEvent("click", true, true, window, 1);
worked = theElement.dispatchEvent(click);

So we create an event of type UIEvents, initialise it as a (cancellable, bubbleable) click event, and send it to /theElement/ of our choice.

This method seems clearer than simulating mouse clicks, or focussing the element and simulating a spacebar press. Btw /worked/ is often false when the event was successfully despatched, I suspect I don't quite understand dispatchEvent yet.

(This is just a recipe from reading the Moz createEvent page)

Ruby ++ and --

This is the missing post from Aleksi Niemela explaining why Ruby hasn't got ++ and -- operators:

(1) ++ and -- are NOT reserved operator in Ruby. (2) C's increment/decrement operators are in fact hidden assignment. They affect variables, not objects. You cannot accomplish assignment via method. Ruby uses +=/-= operator instead. (3) self cannot be a target of assignment. In addition, altering the value of integer 1 might cause severe confusion throughout the program.


http://web.archive.org/web/20030901065005/www.ruby-talk.org/blade/2710

Coming from Perl, you've got to watch this: ++a silently does nothing (it's interpreted as two unary plus operators, +(+a) ) and a++ is an error.

ADO and GUIDs

Take note that when using ADO GUIDs come back formatted with enclosing curly brackets. These are NOT part of the GUID and need to be stripped off.

Show Desktop

I'm fed up losing this link - this is the code that should go in the "Show Desktop.scf" file in the toolbar directory:

[Shell]
Command=2
IconFile=explorer.exe,3
[Taskbar]
Command=ToggleDesktop

Monday, February 28, 2011

Powershell basics

You can collect the output of a commandlet or whole pipeline into a variable

$a = (gci 0.txt)

and then invoke methods of $a

$a.Name

or you can omit the variable

(gci 0.txt).Name

Powershell get-content

get-content (when applied to a file) returns a collection of objects, each of which is a line from the file.

Thursday, February 24, 2011

Batch variable substring

The batch variable substring syntax only works with environment-style variables, ie ones that are substituted thus %var% .

It doesn't work with command line parameters (and I assume not for FOR placeholders either).

Wednesday, February 23, 2011

SQL Server extended properties

fn_listextendedproperty is very particular about which arguments can be left out. Or rather it isn't particular, it just returns no output if it doesn't like your invocation.

The only 'wildcard' invocation I've managed to make work is

select * from fn_listextendedproperty('MS_Description', 'schema', 'dbo', 'table', 'thetable', 'column', default )

Putting default in anywhere else - even if the defaults are the final items in the list, as specified in the documentation - leads to no results.

sqlite identity

For a sqlite field to work as an identity field it has to be precisely integer primary key (not int...) .

sqlite command shell

The sqlite command shell can't cope with a comment in between the closing semicolon of a command and the next command. Eg you must say

select * from blah;
/*
a comment
*/
;
.exit

Monday, February 14, 2011

Circuit analysis with transistors (BJT)

(Notes on http://www.ittc.ku.edu/~jstiles/312/handouts/Steps%20for%20DC%20Analysis%20of%20BJT%20Circuits.pdf)

1. Assume operating mode (Active, Saturated, Cutoff)

2. Enforce appropriate equalities:
A - Vbe = 0.7, Ic = beta * Ib
S - Vbe = 0.7, Vcb = -0.5 (so Vce = 0.2)
C - Ib = Ic = Ie = 0

Also Vce = Vcb + Vbe in all modes

3. Analyse
A - Ic = beta * Ib, Ie = Ic + Ib, Vce = Vcb + 0.7. Find one i and one of Vce, Vcb
S - Find two of Ic, Ib, Ie using the three voltages (which are all known)
C - Find two of Vbe, Vce, Vcb

4. Check inequalities
A - Vcb > 0 or Vce > 0.7; Ib > 0 (or Ic or Ie > 0)
S - Ic < beta * Ib; Ib and Ic and Ie all > 0
C - Vbe < 0, Vcb > 0

5. If any of the inequalities are not present, the assumption was wrong. Start again with a different one.

Sunday, February 13, 2011

Transistors

When trying to work out collector and emitter voltages start with the base current Ib.

The transistor will try to make Ic equal to Ib * beta. This means that if there is a collector resistor Rc then Vc will be pulled down to whatever level makes the voltage drop across Rc produce the desired current. That level cannot be less than 0 - if it is, then Vc ~ 0 and Ic/Ib < beta (saturation).

If there is no Rc then Vc will be Vcc, it seems. But this does not mean Ic = 0; the collector works like a current sink (a hypothetical thing that absorbs current without obeying Ohm's Law).

Similarly, Ve will be whatever level results in the desired current (Ib + Ic) through the emitter resistor. Bear in mind that BE works like a diode, so if it is forward biased then Vb - Ve = 0.6 V. (And this also means that it will break down if reverse biased by too great a difference)

Btw there's nothing magic about the -4.4/-5V cutoff in the Art of Electronics emitter follower example. The figure is -5V because that is Ve when Ic = 0; Ve is -5V in that situation because the emitter is between two resistors of equal value. Beyond the load resistor is 0V and beyond the emitter resistor is -10V, so Ve is halfway between in accordance with the voltage divider principle. If for example Re is only half the value of RL, then the figure is -6.67V.

Friday, February 11, 2011

Pull-up resistor

So if there is a pull-up resistor between a pin and 5V, how is that keeping the pin at 5V? Surely there is a voltage drop across the resistor?

Well apparently there is, but it is very very small because the resistor value would be chosen to be small compared to the impedance of the device the pin belongs to. It's like any voltage divider, Vpu = Vcc * (Rpu / (Rpu + Rdevice)). Where Rpu << Rdevice, Vpu ~ 0.

Friday, February 4, 2011

SQL case

The short form of case -

case field when x then y when z then w else v end

appears to do a comparison with =. This means that a clause 'when null then...' will always be false, for the usual reason that any expression (other than is) involving null returns null.

Where null is one of the switch values, you must use the long form

case when field = x then y when field is null then w else v end

Thursday, February 3, 2011

Capacitors in series

The voltage across capacitors in series is inversely proportional to their capacitance.

This is because:

- they are all partaking of the same current, so charge is evenly distributed between them.
- Q=CV so C=Q/V so capacitance = charge / voltage
- so farads can be thought of as 'coulombs per volt'
- so if two capacitors in series each hold 2C of charge, and cap A is rated 1F and cap B is rated 2F, the 2C in A keep its terminals 2V apart, but the 2C in B only keeps its terminals 1V apart.
- cap A, rated with half the capacitance of B, thus has twice the voltage across it. TICK

Thanks again to Grob for pointing this out where Cook, and Art of Electronics, didn't.

(I understand capacitance better if I think of it as 'charge sensitivity'. Higher capacitance means lower voltage between the terminals after being filled with the same amount of charge.)

AC voltage

When an AC source is stated as being a particular voltage (eg 240V) that is usually an RMS value ( 1 / sqrt(2) * peak).

So peak voltage of the '240V' AC source is 339V, and the voltage at any given time varies between 339V and -339V.

And don't forget that all voltages are a statement of potential difference between 2 points, in this case the two terminals of the source.

So if we are giving the voltage in terms of the difference between the brown 'Live' wire and the blue 'Neutral' one, at positive peak brown is at +339V with respect to blue. (brown 339V, blue 0V)

1/4 cycle later brown is at 0V with respect to blue. (brown 0V, blue 0V)

And after another 1/4 cycle brown is at -339V with respect to blue. (brown -339V, blue 0V)

The absolute potential difference between the two terminals varies between 0 and 339 volts and its root mean square value is 240V, which is where we started.

Thanks to Grob: Basic Electronics for finally explaining this one in a way I could grasp.

(Incidentally although the difference between the two terminals says nothing about the difference between either and any other point, in a domestic wiring situation you would expect a 240V RMS reading between either terminal and the earth wire).

Friday, January 21, 2011

Perl undef

undef is not a constant. If you say

$a = undef;

you are not doing what you intend.

undef works like an operator

undef $a;

and can be used with return

return undef;

and can be used in an assignment

$a = undef;

Perl push/pop

NB that if you are using a Perl array as a stack, by pushing and popping with it, the top-of-stack item has the highest index, not index 0.

Wednesday, January 19, 2011

Perl character classes

\d \s \w and their inverses can be used in Perl regexp character classes.

Metacharacters in character classes are - ] \ ^ $

Friday, January 14, 2011

Perl if

The postfix if (and unless, while, until) in Perl aren't operators but statement modifiers. So operator precedence is not a concern when they follow an expression.

Tuesday, January 11, 2011

Circuit analysis with diodes

(Non-PDF notes on http://www.ittc.ku.edu/~jstiles/312/handouts/The%20Ideal%20Diode%20Circuit%20Analysis%20Guide.pdf)

1. Guess the bias of each diode, ie assume forward or reverse bias (FB/RB)
2. 'Enforce' the assumptions by replacing
(a) FB diodes with a short circuit (0 ohm link) so that there is zero voltage drop across them
(b) RB diodes with an open circuit (break) so that there is zero current through them.
3. Determine the circuit values in the usual way, and use them to check the assumptions you made:
(a) A short circuit (FB) should have positive current flowing through it
(b) An open circuit (RB) should have negative voltage across its two ends.
NB to check for these conditions, not for the 'zero' conditions in point 2.
4. Any assumptions that aren't met should be reversed, and the process gone through again.

Then, because real diodes aren't ideal diodes and do have a voltage drop across them, adjust the analysis to take the drops into account.

Friday, January 7, 2011

Win32 Perl

It appears to be SIGHUP that Perl gets when its console window is closed, and SIGINT when Ctrl-C is pressed.

This makes sense as 'SIGHUP is a signal sent to a process when its controlling terminal is closed' and 'SIGINT is the signal sent to a process by its controlling terminal when a user wishes to interrupt the process'.

Thursday, January 6, 2011

.NET timespan

NB that Timespans have a sign (because they are the result of subtracting one DateTime from another).

.NET time and date

If you parse a string that only contains a time into a DateTime, the result is that time on the current day. Eg '11:14' parsed on Jan 6 2011 => 20119601T1114.

If you parse a string that only contains a date into a DateTime, the result is midnight (0000) on that day. Eg '01/01/2011' => 20110101T0000. You also get this if you take the Date property of any DateTime.

The difference between two DateTimes (including one returned from .Date) obtained with '-' is a TimeSpan. Similarly, if you want to add to a datetime with '+', the addend must be a TimeSpan.

C# is extremely picky about these definitions, which is a pain, but at least the system is consistent once you understand it. You aren't guessing like with SQL.

C# case

switch (expression)
{
case constant-expression:
statement
jump-statement
[default:
statement
jump-statement]
}


jump-statement is either break, or goto case-label, where default is also an acceptable label. Eg 'goto case "x"'.

Fall-through from case to case is not allowed, except when you precede a case with any number of empty cases.

Followers

Blog Archive