Thursday, 12 September 2013

Can all for-loops be transformed to while-loops?

I previously wrote on using for as a brace-less scope using a trick by Jens Gustedt but I wanted to be able to propagate any break clause that might be used within that scope so that it would take effect in an enclosing loop or case statement.

I found a method that worked for gcc but which made use of it's compound statements.

#include 

main() {
  int a;
  for (a=1; a<=2; a++) {
    printf("Main context a=%d\n", a);

    for (int o = 0; o >=0; ({ if (o == 1) { printf("Detected break\n"); break; } }) )
      for (int i=0; !o && (o=1), i==0; o=-1, i=-1 ) { printf("Inner context\n"); break; }
  }
}

produces:
Main context a=1
Inner context
Detected break

which shows that the break statement in the inner-context was propagated to take effect in the top level loop, by means of the break statement in the compound statement of the second loop.

Thats nice, and it is the intended effect, but a for-loop of this form

for ( expression-1 ; expression-2 ; expression-3 ) statement;

is meant to be equivalent to this while loop:

expression-1 ;
while ( expression-2) {
  statement
  expression-3 ;
}

In my case, expression-3 consisted of ({ if (o == 1) { printf("Detected break\n"); break; } }) and the break clause took affect in the containing scope - no doubt because it was not part of the statement of it's associated for-loop.

But it would transform into this while-loop:

expression-1 ;
while ( expression-2) {
  statement
  printf("Detected break\n"); break ;
}

Can there be any doubt that in this while-loop, the break statement would terminate the loop itself and not any containing scope? I don't think so.

Therefore gcc compound statements in for loops open the door to high-class trickery which cannot be achieved the normal way.

using sed to split a stream into 2 streams

An expensive file listing operation needs to invoke an action on the listed files.

xargs is normally the candidate for that, but what when there are multiple file types with varied actions?

Normally I would pipe into a bash scriptlet like this

... | while read "$file" ; do if [ $(expr "$file" :  "$pattern" ) = "0" ] ; then ... ; else ...

but it lacks the bulk appeal of xargs which can reduce the number of command invocations by thousands of times for a large file list.

So here I make use of sed, and bash's >( ... ) construct to open a subshell and substitute a magic filename that refers a file descriptor that writes to the input of the subshell. (The substituted filename is typically something like /dev/fd/63). The newline can be entered on a terminal session with ^V ^J. It is also essential that there are no spaces between the ' and >( and also between the ) and ', otherwise the sed script will be presented to sed as multiple arguments instead of one argument.

... | sed -e '/\.ko$/{w'>( xargs strip --strip-debug )'
;d}' | xargs strip

This allows kernel objects to be stripped of debug only but other objects to be stripped entirely.

An alternative would be to use tee and a separate grep

... | tee >( grep '\.ko$' | xargs strip --strip-debug ) | grep -v '\.ko$' | xargs strip

Thursday, 1 August 2013

Installing ESXi Server with PXE and a serial console

I wanted to install ESXi Server 5.1 on a machine on the other side of the word. I have remote power control, and serial console and access to it's DHCP server and another server on that network, so I thought I could manage it.

I read many half-baked, typo-ridden and downright misleading sets of instructions so I thought I'd write some half-baked, typo-ridden and downright misleading instructions which worked for me.

Generally follow the instructions on the vSphere 5 Doumentation Center with a dash of this but here is what I did:

Unpack the iso into a tftp subdirectory (vmw for me), and so my pxelinux config file is here - and note that I am using the mboot.c32 from the vmware iso but the menu.c32 from my pxelinux installation, otherwise mboot tries to fetch a file called -c.

DEFAULT menu.c32
MENU TITLE ESXi-5.x.x-XXXXXX-full Boot Menu
NOHALT 1
PROMPT 0
TIMEOUT 80
LABEL install
  KERNEL /vmw/mboot.c32
  APPEND -c /vmw/boot.cfg gdbPort=none logPort=none tty2Port=com1
  ipappend 2
  MENU LABEL ESXi-5.x.x-XXXXXX-full ^Installer

LABEL hddboot
 LOCALBOOT 0x80
 MENU LABEL ^Boot from local disk

edit boot.cfg (unpacked from the iso), note that the leading / from all the filenames has been removed, a prefix has been added and some nonsense about comports added to kernelopt

bootstate=0
title=Loading ESXi installer
prefix=vmw
kernel=tboot.b00
kernelopt=runweasel com1_Port=0x3f8 tty2Port=com1 gdbPort=none logPort=none 
modules=b.b00 --- useropts.gz --- k.b00 --- chardevs.b00 --- a.b00 --- user.b00 --- s.v00 --- ata_pata.v00 --- ata_pata.v01 --- ata_pata.v02 --- ata_pata.v03 --- ata_pata.v04 --- ata_pata.v05 --- ata_pata.v06 --- ata_pata.v07 --- block_cc.v00 --- ehci_ehc.v00 --- weaselin.t00 --- esx_dvfi.v00 --- xlibs.v00 --- ima_qla4.v00 --- ipmi_ipm.v00 --- ipmi_ipm.v01 --- ipmi_ipm.v02 --- misc_cni.v00 --- misc_dri.v00 --- net_be2n.v00 --- net_bnx2.v00 --- net_bnx2.v01 --- net_cnic.v00 --- net_e100.v00 --- net_e100.v01 --- net_enic.v00 --- net_forc.v00 --- net_igb.v00 --- net_ixgb.v00 --- net_nx_n.v00 --- net_r816.v00 --- net_r816.v01 --- net_s2io.v00 --- net_sky2.v00 --- net_tg3.v00 --- net_vmxn.v00 --- ohci_usb.v00 --- sata_ahc.v00 --- sata_ata.v00 --- sata_sat.v00 --- sata_sat.v01 --- sata_sat.v02 --- sata_sat.v03 --- sata_sat.v04 --- scsi_aac.v00 --- scsi_adp.v00 --- scsi_aic.v00 --- scsi_bnx.v00 --- scsi_fni.v00 --- scsi_hps.v00 --- scsi_ips.v00 --- scsi_lpf.v00 --- scsi_meg.v00 --- scsi_meg.v01 --- scsi_meg.v02 --- scsi_mpt.v00 --- scsi_mpt.v01 --- scsi_mpt.v02 --- scsi_qla.v00 --- scsi_qla.v01 --- scsi_rst.v00 --- uhci_usb.v00 --- tools.t00 --- xorg.v00 --- imgdb.tgz --- imgpayld.tgz
build=
updated=0

It only remained to de-program F11 as a magic key for gnome-terminal as that key was needed to accept the license.

Thursday, 13 June 2013

Bocelli - The Lords Prayer

This is another great song, good for headaches too.


My Song in the Night - More headache cures

More headache cures.

This is done a few times by different folks, but I like this the best because it shows all the players, after the race is done, together while the song is sung
remembering


https://www.youtube.com/watch?v=vKKDAQEk8HA

Monday, 10 June 2013

The nearby stars

Here is my answer to W.H. Auden's poem on stars; this time it is less a satire and more a re-expression of what the poem did to me.

The nearby stars

I care not for stars,
and they care not for me:
We see each-other distantly

But stars are also far apart
And well accustomed to their view
But you are near, and I love you.

The original is:

“Looking up at the stars, I know quite well
That, for all they care, I can go to hell,
But on earth indifference is the least
We have to dread from man or beast.

How should we like it were stars to burn
With a passion for us we could not return?
If equal affection cannot be,
Let the more loving one be me.

Admirer as I think I am
Of stars that do not give a damn,
I cannot, now I see them, say
I missed one terribly all day.

Were all stars to disappear or die,
I should learn to look at an empty sky
And feel its total dark sublime,
Though this might take me a little time.”


― W.H. Auden

Tuesday, 21 May 2013

gnuplot rolling average

Plot rolling average in gnuplot

After reading this example which provided a fixed 5-sample rolling average a put together this which will provide a variable size rolling average and which can be re-used for multiple traces.

The sprintf whose pattern is conditional on (int($0)==0) will reset avg_data when a new plot is started. I suppose this depends on the plot starting at the first row - perhaps a better technique could be found.

min(a,b) = a >= b ? b : a
samples(n) = min(int($0), n)
avg_data = ""

sum_n(data, n) = ( n <= 0 ? 0 : word(data, words(data) - n) + sum_n(data, n - 1))


avg(x, n) = ( avg_data = sprintf("%s %f", (int($0)==0)?"":avg_data, x), sum_n(avg_data, samples(n))/samples(n))

Then, a plot can be made like this which would plot a rolling average of the previous 5 values:

plot [0:*] "file.dat" using 0:(avg(column(3), 5))