Keep a trace log

One big thing I learned from the C# port was the concept of logging: write output to a file; have a common function write_log(“something”) that creates a plaintext file nearby. This can be read, mailed, filtered and archived. A lot of times – gdb notwithstanding – I have to reproduce bugs. Having a trace log helps me narrow the problem to the last set of lines.

proc write_stamped_log {msg} {
  set log_path [file join [file dirname [info script] err.log]]
  set fh [open $log_path a]; # append
  puts $fh $msg
  close $fh

Stone mind

There are duplicable moments when I want to especially concentrate on writing a sentence, and I slow down enough to focus on each letter: neatly, the pen scribs out the words near-clean and fine. I remind myself to breathe, just in case.

The result isn’t completely straight lines, but something’s going on up there. The feeling is pseudo-detachment, as if I am observing my arm go through its motion – and that only on the periphery, since I’m staring at the letter being made.

I’m certain people have experienced this. Before I heard of ASMR, people had it. Two words: Bob Ross. And trance? Yeah, frission. But those feelings are more of a “brain buzz.” This sensation during slow writing is more of a “mind void.”

Schedule onidle tasks from Tcl

Most of my errors with an ONIDLE scheduled task were from incomplete paths. I needed to supply the absolute path to the executable because the task would run in the system context, not any local directory.

set exe_path [file normalize [file join [file dirname \
  [info script] run-task.exe]]]

exec schtasks /tn task001 /tr $exe_path /sc onidle /I 1

exit 0

Tcl, above any other language, has made me focus on paths. That first line in its various combinations will likely be in every one of my future scripts.

You can test ONIDLE scheduled tasks immediately with

schtasks /run /tn task001

The diagram at the URL below really expanded my mind about timelines:

Graphical attentions

I broke and slapped the Excel chart at the top of my reports. Two weeks had passed and no one had commented on the pretty pictures. They had to scroll down to see it; I imagined their faces lighting up as stacked columns aligned themselves under a trend line. Then I would get requests, become semi-famous, &c. Were it only so.

JPG makes blurry pictures. Excel can export to PNG. The numbers and lines are much sharper. Don’t forget the title, and label your horizontal and vertical axis. All that high school stuff, except this time I had to rationalize my yearning for acknowledgement.

A part of me dreads that part, the requests. It’s because the problem will be a slight permutation, and novel attempts must be refactored for maximal time savings. All of these tools shall rarely see the light of day; my years have gone to cloaked artifacts.

Honestly, I don’t think they look at them too closely. A part of me is relieved, while the other part wonders whether browsing Facebook would have been the lesser sin.

Traversing contexts

For the GNU debugger (gdb), I divided a paper in two and wrote in the first column “abstract” and in the second “concrete.” In the one I would put parameterized text beside commands; in the other, specific invocations of personal programs.

abstract                       concrete
--------                       --------
gdb <program>                  gdb ./a.exe
breakpoint <function-name>     breakpoint hello
n <-> s

You must compile with -g switch in gcc. This helps gdb orient itself. The message pertaining to missing line numbers is related.

Switching between abstract and concrete really helped. First, I did a lot of repetitious typing, which helped me remember. Second, gdb forced me to slow down and consider each line. I hope this technique lets me avoid sprinkling output statements in my code.

Tree traversal with static data

I would like to get into the meat of algorithm books, but malloc() and structs loom. If you initialize an array to represent a tree, you can fake the rest.

tree:               table:
         1          node  child1 child2
       /   \        1     2      3
      2     3       2     4      5
     / \   /        3     6
    4  5  6         4

For investigating techniques, this seems doable. The (gist) demonstrates pre-order, in-order, and post-order traversal of this tree. My assumption is stacks and queues can be expressed even more easily with two position markers, an insert_at variable and a fetch_from variable.

If the world state is sufficiently large to represent all possible state transforms, there’s little reason to write a dynamic allocation scheme for a data structure. At least for initial learning purposes.

Using sed to destroy a file

This happened:

$ sed 's/one/two/g' file.c > file.c

Opening the file shows an empty file. So, make sure not to do this!

I was lucky because sed prints its output to the command-line with the p flag, and I could copy-paste the original contents.

I do not usually do this for any commands; for some reason, I thought the file would be completely read into memory and the output would cleanly populate the old file.

An implementation of putchar()


putch() uses putchar() to print a fixed-length line from STDIN. Characters continue past MAXCARD elements if the line does not end before MAXLINE (MAXCARD + 1).

This is a C port of the RATFOR putchar() function in “Software Tools.” I did not want to continue to the next chapter until I had written the foundation for all these other tools.

There’s a lot of design decisions that can come from so terse a language and its implementation. With C, there’s less of a black box between you and figuring out some foundational problem.

An implementation of getchar()


Should I have named it something else? Technically, it uses getchar(). Anyway, the function uses a character buffer of size MAXLINE, which is MAXCARD + 1, and MAXCARD is the last index. A position variable getch_lastch tracks the current index of a character to store or to retrieve.

The getlin() function line discipline is almost like the getline() function in K&R: cap newlines and end at variable lengths. However, the RATFOR version parameterizes its getchar(), so it does two things: return an EOF signal and assign the next fetched character to the variable c.

ssh into local VirtualBox VM

It’s a compromise for now, but with Cygwin we can ssh into the VirtualBox VM instance running OpenBSD. Set the network adapter in VirtualBox to “Host-only Adapter” using “VirtualBox Host-Only Ethernet Adapter” and start the virtual machine. The VM will receive an IP address after several DHCPREQUESTs.

You can try ssh in Cygwin to log in. The first time, there will be an ECDSA key fingerprint check. You can compare* this to the key in the VM instance with

ssh-keygen -l -f /etc/ssh/

You can view your connection attempts on the virtual machine by looking at /var/log/authlog.

The compromise is learning bash before sh for writing backup or CSV commit scripts between the VM and Cygwin, so I will have to avoid bash habits leaking into sh.