<?xml version="1.0" encoding="utf-8"?>
<!-- generator="Kukkaisvoima version 9" -->
<rss version="2.0"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
>
<channel>
<atom:link href="http://www.nickcoleman.org/blog/index.cgi/feed" rel="self" />
<title>Nick Coleman</title>
<link>http://www.nickcoleman.org/blog/index.cgi</link>
<description>Nick Coleman blog</description>
<pubDate>Fri, 17 Feb 2012 08:02:00 -0700</pubDate>
<lastBuildDate>Fri, 17 Feb 2012 08:02:00 -0700</lastBuildDate>
<generator>http://23.fi/kukkaisvoima/</generator>
<language>en</language>
<item>
<title>How To Set Up A Light-Weight On-line Thesaurus For Vim
</title>
<link>http://www.nickcoleman.org/blog/index.cgi?post=vim-thesaurus%21201202170802%21general%2Cblogging%2Cinternet%2Cprogramming%2Csoftware%2Cunix</link>
<comments>http://www.nickcoleman.org/blog/index.cgi?post=vim-thesaurus%21201202170802%21general%2Cblogging%2Cinternet%2Cprogramming%2Csoftware%2Cunix#comments</comments>
<pubDate>Fri, 17 Feb 2012 08:02:00 -0700</pubDate>
<dc:creator>Nick</dc:creator>
<category>general</category>
<category>blogging</category>
<category>internet</category>
<category>programming</category>
<category>software</category>
<category>unix</category>
<guid isPermaLink="true">http://www.nickcoleman.org/blog/index.cgi?post=vim-thesaurus%21201202170802%21general%2Cblogging%2Cinternet%2Cprogramming%2Csoftware%2Cunix/</guid>
<description><![CDATA[ 
 [...]]]></description>
<content:encoded><![CDATA[
<p>
<div class="summary">Vim has support for a built-in thesaurus. However, it consumes a
lot of memory, which you may not want for a feature you do not use much, and its
auto-complete selection has issues.  Here is how to set up an on-line thesaurus query that is light weight.</div>
<p>
<h2>Summary</h2>
<p>
This is the first post of two about a light weight way to implement a thesaurus.  It is
great for what I need, which is the occasional use of a thesaurus for writing text such
as this article.  Once it is set up, you can forget about it and just use <b>K</b>
whenever you want to look up a word.
<p>
A nice bonus or synergy is that the website also returns a definition for the word, so
it functions as a simple dictionary as well.
<p>
The second post will deal with how to use Vim's built in syntax rule sets to provide
highlighting and nice colours.
<p>
There are two or three simple steps:
<ol><li>a vim script that passes the cursor word to an external shell script.</li>
<li>a shell script that looks up the word using an online thesaurus, then parses
the output to remove unnecessary cruft.</li>
<li>an optional syntax file to provide highlighting and colours.</li></ol>
<p>
Here is what it looks like with a quick-n-dirty syntax rule set:
<div class="image">
<img src="http://www.nickcoleman.org/blog/images/thesaurus.jpg" title="Vim thesaurus"
alt="vim with thesaurus window" >
<p>Sample output for "quick"
</div>
<p>
<hr>
<p>
I use Vim for programming and it is great for that.  I use it when I need to edit files on remote
servers that I have ssh'ed in.  I also use Vim for writing text because it is a great
text editor.  I am writing this in Vim, for example. 
<p>
Often, one of the things you want when writing text is a thesaurus, which is the topic
for today.
<p>
<h2>Why on-line</h2>
Vim comes with support for a thesaurus, but I've never really liked it, for two reasons.  
<p>
You download a thesaurus (the Moby one is common), point Vim to it and you are good to
go. However, a thesaurus can consume a lot of memory.  The Moby file is 24 MB, although to
be fair Vim doesn't use anything like that.  If you are using Vim remotely, you may not
want to use <em>any</em> extra memory. For example, I have a remote VPS that has only
128 MB of total memory, so every megabyte is critical.  This is especially true if you
use the thesaurus only rarely; the trade-off is not worth it.
<p>
The bigger issue for me is that Vim does not handle a long list of alternative words very well.
It is fine with a short list where you use it just like auto-complete, but it seems to
get confused with a long list.  Unfortunately, Moby often serves up a long list, and you
frequently find you have inadvertently changed your perfectly good word to something
completely different.  You then have to Undo and try again.
<p>
In fact, I got so frustrated with the Vim/Moby combination I ended up unsetting the
thesaurus feature in Vim after just a couple of months.
<p>
The good news is that there is an alternative, and that is to use one of the many
on-line thesauruses. 
<p>
I have set things up so that a script calls a command-line browser to dump the output
from the online website, then parses it to remove extra cruft such as sidebars, headers
and footers, and white space, and puts it into a scratch buffer in Vim itself for me to
browse through and perhaps copy a word from.
<p>
<h2>Vim setup</h2>
First, set up Vim to call a script, which I will describe further down, and display the
results in a scratch buffer.  (I shamelessly pulled this straight from the ReadMan
script, which displays a Unix man page for the keyword on the cursor.) To use it, simply
press <b>K</b> with the cursor under the word that you want to see alternatives.  You
can do all the normal things in the buffer like search, jump to a line, copy a word
(<b>cw</b>), and so on. To close it, just hit the <b>q</b> key.  
<p>
Copy and paste the following into your <code>.vimrc</code> or wherever you prefer.  I
have it in a common.vim file in my ftplugin directory, where my various filetype scripts
can source it if they want.
<p>
<div class="pygmentize"><pre><span class="k">fun</span><span class="p">!</span> ReadThesaurus<span class="p">()</span><br><span class="c">   &quot; Assign current word under cursor to a script variable</span><br>   <span class="k">let</span> s:thes_word <span class="p">=</span> expand<span class="p">(</span><span class="s1">&#39;&lt;cword&gt;&#39;</span><span class="p">)</span><br><span class="c">   &quot; Open a new window, keep the alternate so this doesn&#39;t clobber it. </span><br>   <span class="k">keepalt split </span>thes_<br><span class="c">   &quot; Show cursor word in status line</span><br>   <span class="k">exe</span> &quot;<span class="k">setlocal </span><span class="nb">statusline</span><span class="p">=</span>&quot; . <span class="s1">s:thes_word</span><br><span class="c">   &quot; Set buffer options for scratch buffer</span><br>   <span class="k">setlocal</span> <span class="nb">noswapfile</span> <span class="nb">nobuflisted</span> <span class="nb">nowrap</span> <span class="nb">nospell</span> <br>     \<span class="nb">buftype</span><span class="p">=</span>nofile <span class="nb">bufhidden</span><span class="p">=</span>hide <br><span class="c">   &quot; Delete existing content</span><br>   <span class="m">1</span><span class="p">,</span>$<span class="k">d</span><br><span class="c">   &quot; Run the thesaurus script</span><br>   <span class="k">exe </span><span class="s2">&quot;:0r !/home/nickcoleman/bin/thesaurus &quot;</span> . s:thes_word <br><span class="c">   &quot; Goto first line</span><br>   <span class="m">1</span><br><span class="c">   &quot; Set file type to &#39;thesaurus&#39;</span><br>   <span class="k">set</span> <span class="k">filetype</span><span class="p">=</span><span class="nb">thesaurus</span><br><span class="c">   &quot; Map q to quit without confirm</span><br>   <span class="k">nmap </span><span class="p">&lt;</span><span class="nb">buffer</span><span class="p">&gt;</span> <span class="k">q</span> :<span class="k">q</span><span class="p">&lt;</span>CR<span class="p">&gt;</span><br><span class="k">endfun</span><br><span class="c">&quot; Map the K key to the ReadThesaurus function</span><br><span class="nb">noremap</span> <span class="p">&lt;</span><span class="nb">buffer</span><span class="p">&gt;</span> K :<span class="k">call</span> ReadThesaurus<span class="p">()&lt;</span>CR<span class="p">&gt;&lt;</span>CR<span class="p">&gt;</span><br></pre></div>
<p>
The script is fully commented for you to follow what is going on.
<p>
Notice I specified the location of the shell script that Vim is calling to be
<code>$HOME/bin/thesaurus</code>.  Change this to wherever you are going to put the
shell script.
<p>
I call the scratch buffer "thes_" so that I have a name for it which means I can
easily re-use the buffer again.  Otherwise Vim would create a new buffer every time and
go through buffer numbers like crazy.  In the unlikely event you have an actual file
called "thes_", change the script to use some other wacky name.  I could have used the
Vim function <code>tempname()</code> to generate a unique buffer name, but "thes_" is
meaningful and easy to remember if you want to unhide the buffer later.
<p>
I set the status line to show the word I am looking up.  Sometimes the website will
return a different word, a near synonym, so the status line reminds me exactly which
word I are looking up. An example is looking up the word "the" which returns the
definition and synonyms for "histrionical".  No, I don't know why.
<p>
I include a line to set the filetype to "thesaurus". Its purpose is to allow me to set
up anything special for that filetype later on.  A possible use would be to create a
syntax file to do special highlighting or colouring.  That will be the topic for the
next post.
<p>
The mapping for K has a second <code>&lt;CR&gt;</code>.  It eats up the "Press ENTER or type
command to continue" prompt.  There are other ways to do this, but they can mess up the
display or have the side effect of applying globally instead of just this buffer.
<p>
By the way, in case it isn't obvious, the reason I split the functionality in to
two&mdash;part- Vim and part-shell scripts&mdash;instead of doing it all in Vim is
because Vim's scripting language, always an awkward beast at the best of times, would
make it too hard.  Best to use the good parts of each and combine them.
<p>
<h2>Thesaurus script</h2> Up to now, everything has been operating system agnostic.  The
script below is written for unix-like operating systems, including OS X, because it uses
some unix utilities like links and sed.  (The others it uses such as basename and
readlink aren't absolutely necessary, just good style.) I have written a <a
href="#windows">paragraph or two below </a> on how to get those tools for Windows.
<p>
Originally I wrote a quick-n-dirty one-liner, but I decided the script might be useful
outside Vim as well, so I tidied it up to be a useful script that you can call from the
command line.
<p>
This is the shell script that Vim calls.  Put it in the location you specified in the
Vim script above.  It is straightforward, apart from the <code>sed</code> call, and there
are enough comments so you can see what is happening.
<p>
<div class="pygmentize"><pre><span class="c">#!/bin/sh</span><br><br><span class="c"># This searchs an online thesaurus, cuts as much cruft out as possible,</span><br><span class="c"># and displays the definitions.</span><br><br><span class="c">#URL=&#39;http://www.merriam-webster.com/thesaurus/&#39;</span><br><span class="nv">URL</span><span class="o">=</span><span class="s1">&#39;http://thesaurus.com/browse/&#39;</span><br><br><span class="c"># Display help, and quit.</span><br><span class="k">function </span>usage <span class="o">{</span><br>    cat <span class="s">&lt;&lt; EOF_HELP</span><br><span class="s">    Usage: $(basename $0) [-r][-h] word</span><br><span class="s">    Display the parsed results of an online thesaurus search for &lt;word&gt;</span><br><br><span class="s">    -r  Raw results; no filtering.</span><br><span class="s">    -h  Display this help.</span><br><br><span class="s">EOF_HELP</span><br>    <span class="nb">exit</span> <br><span class="o">}</span><br><br><span class="c"># Check for a parameter.  Get the output from the website</span><br><span class="k">function </span>get_thes <span class="o">{</span><br>    <span class="o">[</span>  -z <span class="s2">&quot;$1&quot;</span> <span class="o">]</span> <span class="o">&amp;&amp;</span> usage<br>    <span class="k">$(</span>readlink -e <span class="k">$(</span>which links<span class="k">))</span> -dump <span class="s2">&quot;${URL}$1&quot;</span> <br><span class="o">}</span><br><br><span class="c"># Check for a -h parameter or absence of parameter.</span><br><span class="o">[</span> <span class="s2">&quot;$1&quot;</span> <span class="o">=</span> <span class="s2">&quot;-h&quot;</span> -o -z <span class="s2">&quot;$1&quot;</span> <span class="o">]</span> <span class="o">&amp;&amp;</span> usage<br><br><span class="c"># If -r just get the raw output, otherwise pass it through sed.</span><br><span class="k">if</span> <span class="o">[</span> <span class="s2">&quot;$1&quot;</span> <span class="o">=</span> <span class="s2">&quot;-r&quot;</span> <span class="o">]</span> ; <span class="k">then</span><br><span class="k">    </span><span class="nb">shift</span><br><span class="nb">    </span>get_thes <span class="nv">$1</span><br><span class="k">else</span><br>    <span class="c"># Sed is doing many things: </span><br>    <span class="c"># Print out &quot;no results found for &quot; and quit. </span><br>    <span class="c"># Print out only the lines I&#39;m interested in, which are:</span><br>    <span class="c">#   No results found for</span><br>    <span class="c">#   Main Entry:</span><br>    <span class="c">#   Definition:</span><br>    <span class="c">#   and all from Synonyms: to Antonyms:</span><br>    <span class="c"># Put a new line after Antonyms.</span><br>    get_thes <span class="nv">$1</span> | sed -n -e <span class="s1">&#39;/No results found for/ {&#39;</span> <span class="se">\</span><br>      -e <span class="s1">&#39; s|^[ \t]*\(No results .*\):|\1|p ; q} &#39;</span><span class="se">\</span><br>      -e <span class="s1">&#39;{/Main Entry:/p &#39;</span> <span class="se">\</span><br>      -e <span class="s1">&#39;/Definition:/p &#39;</span> <span class="se">\</span><br>      -e <span class="s1">&#39;/Synonyms:/,/\(Antonyms:\)\|\(^$\)/p} &#39;</span> <span class="se">\</span><br>      -e <span class="s1">&#39;/Antonyms:/ a \ &#39;</span><br><span class="k">fi</span>    <br></pre></div>
<p>
I use <b>thesaurus.com</b> because I found it has a wider coverage than
<b>merriam-webster.com</b>.  If you want to use a different website, you will need to
write your own sed script to parse it.
<p>
I separated the sed actions into discrete chunks above so you can get a clearer picture
of what sed is doing, but they appear as one line in the actual script.  That line is
below, for you to cut-n-paste.
<p>
<div class="pygmentize"><pre>    get_thes <span class="nv">$1</span> | sed -n -e <span class="s1">&#39;/No results found for/ { s|^[ \t]*\(No results .*\):|\1|p ; q} ;{/Main Entry:/p ; /Definition:/p ; /Synonyms:/,/\(Antonyms:\)\|\(^$\)/p} ; /Antonyms:/ a \  &#39;</span>
</pre></div>
<p>
You are done.  To use, move the cursor in Normal mode underneath the word of interest
and press <b>K</b>.
<p>
<h2<Bugs</h2>
<p>
I noticed once that the script loses permissions to a temporary file that Vim uses
internally.  It seems to only happen if a remote ssh session in screen is unexpectedly
terminated, and not always then.  Closing and re-opening Vim (yes, a pain) will fix it.
<p>
<a name="windows"></a>
<p>
<h2>Additional Info for Windows Users</h2>
<p>
<h4>Summary</h4>
In summary, Windows users have a little extra to do, but not much.
<ol><li>Install <code>sed</code> and <code>links</code>. It takes only a few seconds
each to download and install.  The default install is fine.</li>
<li>Create a batch file to get and parse the thesaurus data. The batch file will be an
abbreviated form of the shell script above, tailored for Windows.</li>
<li>Point vim to the location of the batch file.</li></ol>
<p>
<h4>Install Links &amp; Sed</h4>
Windows users will need to install the <code>links</code> and <code>sed</code>
commands and perhaps a shell if you don't want to use a DOS batch file (which is below).
I did a bit of a search and found a  <a
href="http://www.nickcoleman.org/axs/ax.pl?http://links.twibright.com/download/binaries/win32/">Windows
build of <code>links</code> here</a>, and a good set of  <a
href="http://www.nickcoleman.org/axs/ax.pl?http://gnuwin32.sourceforge.net/packages.html">unix
tools for Windows here</a> (direct link for sed is <a
href="http://www.nickcoleman.org/axs/ax.pl?http://gnuwin32.sourceforge.net/packages/sed.htm">
here</a>), both of which are fine.
<p>
<h4>Create DOS Batch File</h4>
You don't need the full-blown shell script above.  The simple DOS batch file below will do. It
runs links and then pipes the output to sed.  You might need to change the paths to the
folder(s) where you installed links and sed if you did not use the defaults when you
installed them.
<p>
<div class="pygmentize"><pre>@"c:\program files\links\links.exe" -dump http://thesaurus.com/browse/%1 | "c:\program files\gnuwin32\bin\sed.exe" -n -e <span class="s1">&quot;/No results found for/ { s|^[ \t]*\(No results .*\):|\1|p ; q} ;{/Main Entry:/p ; /Definition:/p ; /Synonyms:/,/\(Antonyms:\)\|\(^$\)/p} ; /Antonyms:/ a \  &quot;</span><br></pre></div>
<p>
There are a couple of differences to the unix script.  Sed needs double quotes
surrounding its commands instead of single quotes.  The paths to the executables need
double quotes because of the spaces in the path.  I put a '@' in front of everything
to prevent DOS from echoing back the entire command. Finally, I put <code>%1</code>
instead of <code>$1</code> for the DOS way to pass in the parameter.
<p>
It is probably worth opening a <code>cmd.exe</code> window and testing the batch file.  Assuming you
called the batch file "thesaurus.bat", run <code>thesaurus.bat loose</code> and you
should get a listing back after a few seconds with all the synonyms of "loose".
<p>
<h4>Point Vim</h4>
Now that you have a batch file that works, put it in a folder somewhere. The vim script
needs one small change to point to that location.  
<p>
In Windows, $HOME expands to "C:\Documents and Settings\{user}".<a href="#fn1"
id="back1"><sup>1</sup></a>  However, it doesn't
expand in a script if it is contained within quotes.  So the vim script should be
changed from 
<p>
<div class="code">
" Run the thesaurus script
   :exe ":0r !$HOME/bin/thesaurus " . s:thes_word 
</div>
<p>
to 
<p>
<div class="code">
" Run the thesaurus script
   :exe ':0r !"' . $HOME . '\thesaurus.bat" ' . s:thes_word
</div>
assuming again that your DOS batch file is called "thesaurus.bat".  This puts
$HOME outside the quotes and Vim will expand it to "C:\Documents and
Settings\{user}\thesaurus.bat"<a href="#fn1"
id="back1"><sup>1</sup></a>.  
<p>
If you put the batch file in a sub folder, add that folder name in front of
<code>'\thesaurus.bat'</code> like this: <code>'\my_folder\thesaurus.bat'</code>.
<p>
If it does not work, because you tested the batch file itself beforehand, the problem is
almost certainly in how you specified the location of your batch file in the vim script.
<p>
<hr>
<p>
<div class="footnote">
<a href="#back1" id="fn1">[1] for Windows XP.  Vista expands to "C:\Users\{user}".  Windows
7 the same as Vista? -- I don't know, I don't have it. </a> <a href="#back1">&#8593;</a>
</div>
<p>
]]></content:encoded>
<wfw:commentRss>http://www.nickcoleman.org/blog/index.cgi?post=vim-thesaurus%21201202170802%21general%2Cblogging%2Cinternet%2Cprogramming%2Csoftware%2Cunix/feed/</wfw:commentRss>
</item>
<item>
<title>Fixing Pm-Utils Userspace Governor for Linux and BSD
</title>
<link>http://www.nickcoleman.org/blog/index.cgi?post=cpu-frequency-sleep-slackware%21201202050917%21unix</link>
<comments>http://www.nickcoleman.org/blog/index.cgi?post=cpu-frequency-sleep-slackware%21201202050917%21unix#comments</comments>
<pubDate>Sun, 05 Feb 2012 09:17:00 -0700</pubDate>
<dc:creator>Nick</dc:creator>
<category>unix</category>
<guid isPermaLink="true">http://www.nickcoleman.org/blog/index.cgi?post=cpu-frequency-sleep-slackware%21201202050917%21unix/</guid>
<description><![CDATA[ 
 [...]]]></description>
<content:encoded><![CDATA[
<p>
<div class="summary">Slackware, like other Linuxes and BSDs, uses pm-utils to manage
sleep and resume, including managing the cpu frequency governors.  The standard scripts
restore the governor after the machine has woken from sleep mode, but they don't restore
the governor's frequency.  Here is how to fix it.</div>
<p>
I run Slackware on my laptop, as I've mentioned here before, and about the only issue I
have with it instead of the natively installed Vista Home is that it runs a bit hot.
From what I can tell (because Vista does not give you a lot of tools to investigate),
Vista does two things more aggressively: it slows down the CPU frequency, and it changes
the fan speed sooner.  However, the benefits of have a unix-y environment more
than make up for that so I am happy with running Slackware.
<p>
However, that does not mean I can't tweak things a bit, such as setting up a CPU
frequency governor and scaling the frequency, which I <a
href="http://www.nickcoleman.org/axs/ax.pl?http://www.nickcoleman.org/blog/index.cgi?post=cpufreqmore%21201101182308%21unix%2Cprogramming">wrote
about</a> previously.
<p>
<h2>Pm-utils</h2>
Slackware uses pm-utils, a suite of scripts from <a
href="http://www.nickcoleman.org/axs/ax.pl?http://pm-utils.freedesktop.org">freedesktop.org</a>, to manage suspend and
resume.  Among other things, pm-utils saves the governor setting on suspend and restores
it on resume (suspend means hibernate or sleep, and resume means wake up).  Here is the
function (in <code>/usr/lib/pm-utils/sleep.d/94cpufreq</code>) that saves the settings:
<p>
<div class="pygmentize"><pre>hibernate_cpufreq<span class="o">()</span>
<span class="o">{</span>
  <span class="o">(</span> <span class="nb">cd</span> /sys/devices/system/cpu/
  <span class="k">for </span>x in cpu<span class="o">[</span>0-9<span class="o">]</span>*; <span class="k">do</span>
    <span class="c"># if cpufreq is a symlink, it is handled by another cpu. Skip.</span>
    <span class="o">[</span> -L <span class="s2">&quot;$x/cpufreq&quot;</span> <span class="o">]</span> <span class="o">&amp;&amp;</span> <span class="k">continue</span>
<span class="k">    </span><span class="nv">gov</span><span class="o">=</span><span class="s2">&quot;$x/cpufreq/scaling_governor&quot;</span>
    <span class="c"># if we do not have a scaling_governor file, skip.</span>
    <span class="o">[</span> -f <span class="s2">&quot;$gov&quot;</span> <span class="o">]</span> <span class="o">||</span> <span class="k">continue</span>
    <span class="c"># if our temporary governor is not available, skip.</span>
    grep -q <span class="s2">&quot;$TEMPORARY_CPUFREQ_GOVERNOR&quot;</span> <span class="se">\</span>
      <span class="s2">&quot;$x/cpufreq/scaling_available_governors&quot;</span> <span class="o">||</span> <span class="k">continue</span>
<span class="k">    </span>savestate <span class="s2">&quot;${x}_governor&quot;</span> &lt; <span class="s2">&quot;$gov&quot;</span>
    <span class="nb">echo</span> <span class="s2">&quot;$TEMPORARY_CPUFREQ_GOVERNOR&quot;</span> &gt; <span class="s2">&quot;$gov&quot;</span>
  <span class="k">done</span> <span class="o">)</span>
<span class="o">}</span>
</pre></div>
<p>
It is pretty straightforward: for each CPU, check if the governor is a scaling type and
save its value if it is.  (<code>savestate</code> is a function in another file that saves the
current state in <code>/var/run/pm-utils/pm-suspend/storage</code>.)
<p>
Here is the corresponding function that restores the settings on wakeup:
<p>
<div class="pygmentize"><pre>thaw_cpufreq<span class="o">()</span>
<span class="o">{</span>
  <span class="o">(</span> <span class="nb">cd</span> /sys/devices/system/cpu/
  <span class="k">for </span>x in cpu<span class="o">[</span>0-9<span class="o">]</span>*/cpufreq/scaling_governor ; <span class="k">do</span>
    <span class="o">[</span> -f <span class="s2">&quot;$x&quot;</span> <span class="o">]</span> <span class="o">||</span> <span class="k">continue</span>
<span class="k">    </span>state_exists <span class="s2">&quot;${x%%/*}_governor&quot;</span> <span class="o">||</span> <span class="k">continue</span>
<span class="k">    </span>restorestate <span class="s2">&quot;${x%%/*}_governor&quot;</span> &gt; <span class="s2">&quot;$x&quot;</span>
  <span class="k">done</span> <span class="o">)</span>
<span class="o">}</span>
</pre></div>
<p>
Again, straightforward: if there is a saved value for the CPU's governor, restore it.
<p>
So far, so good.
<p>
However, astute readers and anyone who read the summary at the beginning will realise
that there is a bug for the userspace governor. First, a bit on governors. 
<p>
Of the five available governors, convervative, performance, powersave, ondemand and
userspace, userspace is the only one that does not have a default value(s) associated
with it. The other governors come with reasonably sensible defaults, and some of them
even allow you to change their values. Userspace comes with no defaults, which makes
sense because the whole point of a userspace governor is that it is up to the user to
control it. 
<p>
<h2>Bug</h2>
Back to pm-utils.  You can see from the scripts that nowhere do they save and restore
the parameters that the governors control.  That means when the machine wakes up it
restores whichever governor was in use, but not any of the governor's parameters.  For
the userspace governor, you are back to a fixed CPU frequency at maximum, which you
probably don't want because otherwise why are you using the userspace governor in the
first place.
<p>
It is kind of annoying to wonder why the fan suddenly is going at full blast.  Then you
check the CPU's frequency.  Oh, it's at max, when I thought I had set it to a middle
value.  Oh yeah, I closed the lid earlier and put the laptop into sleep mode.
<p>
<h2>Fix</h2>
It is an easy fix. Check if the governor is "userspace" and save the current frequency
setting on suspend, and restore it on resume.
<p>
All changes to the pm-utils scripts should be done in <code>/etc/pm</code> otherwise
they will be lost on any upgrade.  Copy <code>/usr/lib/pm-utils/sleep.d/94cpufreq</code>
to <code>/etc/pm/sleep.d/</code>.  Edit the file to add the lines marked with "--&gt;":
<p>
<div class="pygmentize"><pre>hibernate_cpufreq<span class="o">()</span>
<span class="o">{</span>
  <span class="o">(</span> <span class="nb">cd</span> /sys/devices/system/cpu/
  <span class="k">for </span>x in cpu<span class="o">[</span>0-9<span class="o">]</span>*; <span class="k">do</span>
    <span class="c"># if cpufreq is a symlink, it is handled by another cpu. Skip.</span>
    <span class="o">[</span> -L <span class="s2">&quot;$x/cpufreq&quot;</span> <span class="o">]</span> <span class="o">&amp;&amp;</span> <span class="k">continue</span>
<span class="k">    </span><span class="nv">gov</span><span class="o">=</span><span class="s2">&quot;$x/cpufreq/scaling_governor&quot;</span>
    <span class="c"># if we do not have a scaling_governor file, skip.</span>
    <span class="o">[</span> -f <span class="s2">&quot;$gov&quot;</span> <span class="o">]</span> <span class="o">||</span> <span class="k">continue</span>
    <span class="c"># if our temporary governor is not available, skip.</span>
    grep -q <span class="s2">&quot;$TEMPORARY_CPUFREQ_GOVERNOR&quot;</span> <span class="se">\</span>
      <span class="s2">&quot;$x/cpufreq/scaling_available_governors&quot;</span> <span class="o">||</span> <span class="k">continue</span>
<span class="k">    </span>savestate <span class="s2">&quot;${x}_governor&quot;</span> &lt; <span class="s2">&quot;$gov&quot;</span>
--&gt; <span class="c"># Save userspace governor&#39;s frequency</span>
--&gt; <span class="o">[</span> <span class="k">$(</span>cat <span class="s2">&quot;$gov&quot;</span><span class="k">)</span> <span class="o">=</span> <span class="s2">&quot;userspace&quot;</span> <span class="o">]</span> <span class="o">&amp;&amp;</span> <span class="se">\</span>
--&gt;     savestate <span class="s2">&quot;${x}_frequency&quot;</span> &lt; <span class="s2">&quot;$x/cpufreq/scaling_cur_freq&quot;</span>
    <span class="nb">echo</span> <span class="s2">&quot;$TEMPORARY_CPUFREQ_GOVERNOR&quot;</span> &gt; <span class="s2">&quot;$gov&quot;</span>
  <span class="k">done</span> <span class="o">)</span>
<span class="o">}</span>
<p>
thaw_cpufreq<span class="o">()</span>
<span class="o">{</span>
  <span class="o">(</span> <span class="nb">cd</span> /sys/devices/system/cpu/
  <span class="k">for </span>x in cpu<span class="o">[</span>0-9<span class="o">]</span>*/cpufreq/scaling_governor ; <span class="k">do</span>
    <span class="o">[</span> -f <span class="s2">&quot;$x&quot;</span> <span class="o">]</span> <span class="o">||</span> <span class="k">continue</span>
<span class="k">    </span>state_exists <span class="s2">&quot;${x%%/*}_governor&quot;</span> <span class="o">||</span> <span class="k">continue</span>
<span class="k">    </span>restorestate <span class="s2">&quot;${x%%/*}_governor&quot;</span> &gt; <span class="s2">&quot;$x&quot;</span>
--&gt; <span class="c"># If frequency has been saved, restore it.</span>
--&gt; state_exists <span class="s2">&quot;${x%%/*}_frequency&quot;</span> <span class="o">||</span> <span class="k">continue</span>
--&gt;<span class="k"> </span>restorestate <span class="s2">&quot;${x%%/*}_frequency&quot;</span> &gt; <span class="s2">&quot;${x%%_*}_setspeed&quot;</span>
  <span class="k">done</span> <span class="o">)</span>
<span class="o">}</span>
</pre></div>
<p>
<h2>More bugs</h2>
<p>
This still does not save any parameters for other governors.  It does not concern me
because I mainly use the userspace governor and the others have sensible defaults anyway.
<p>
If you want to save parameters for the other governors, the fix is fairly easy.  Check
in <code>/sys/devices/system/cpu/cpu0/cpufreq</code> (for CPU0; check the other CPUs too) for
the parameters that the governor can set. They will be the files with write access.
Modify the code to save and restore them.  
<p>
<h3>Freedesktop.org</h3>
<p>
I have a love-hate relationship with freedesktop.org.  I am grateful someone has taken
on the thankless task of attempting to make a set of standards for Linux desktops.  I
really dislike some of their design decisions, and much of the xdg-mime stuff seems
unnecessarily convoluted and obtuse. The complete lack of documentation is appalling.
Try to fix an invalid mime association that has an incorrect default application and you
seem to go round-and-round in circles.
<p>
Anyway, I was going to submit the small changes above as a bug fix.  Then I noticed that
there are minor bugs still outstanding from 2008, <strong>four</strong> years ago. 
Perhaps development has stopped completely.
<p>
I hope freedesktop.org has a future.  Possibly the schism between KDE, Unity desktop and
Gnome will resolve, otherwise those of us who use none of those desktops will be caught
up in the crossfire of conflicting and different standards, to our detriment. 
<p>
]]></content:encoded>
<wfw:commentRss>http://www.nickcoleman.org/blog/index.cgi?post=cpu-frequency-sleep-slackware%21201202050917%21unix/feed/</wfw:commentRss>
</item>
<item>
<title>Melbourne Tennis Open
</title>
<link>http://www.nickcoleman.org/blog/index.cgi?post=tennis-melbourne-open-2012%21201201301212%21sport</link>
<comments>http://www.nickcoleman.org/blog/index.cgi?post=tennis-melbourne-open-2012%21201201301212%21sport#comments</comments>
<pubDate>Mon, 30 Jan 2012 12:12:00 -0700</pubDate>
<dc:creator>Nick</dc:creator>
<category>sport</category>
<guid isPermaLink="true">http://www.nickcoleman.org/blog/index.cgi?post=tennis-melbourne-open-2012%21201201301212%21sport/</guid>
<description><![CDATA[ 
 [...]]]></description>
<content:encoded><![CDATA[
<p>
Well, the Melbourne Open has finished after a huge couple of weeks. If you read <a
href="http://www.nickcoleman.org/axs/ax.pl?http://www.nickcoleman.org/blog/index.cgi?post=tennis%21200912281738%21sport">my
previous post</a> on tennis, you know I am not usually a fan of this overpaid over-hyped
event.  But this one was pretty good.
<p>
We saw some great games.  The main thing for me, though, was that we saw some relative
new-comers get up and win their important games from the big stars.  There is a changing
of the guard underway in all areas, women's and men's.   That started last year or even
the year before, but this year was conclusive.
<p>
However, to harp on again, women's tennis is still unwatchable because of the banshee
shrieking.  It is not even improving.  If anything, it is getting worse.  They have
become more vocal and, if it is possible, louder.
<p>
Why do they do it?  Why is it impossible for them to grunt without shrieking? It is
extremely distracting. Until they stop (unlikely), or authorities regulate it
(unlikely), or viewers start protesting (maybe), I can't watch it.
<p>
Which isn't a great loss since it is as boring as batshit anyway.  Pip, pip!
<p>
[Late news] <i>The Age</i> has a poll on <a
href="http://www.nickcoleman.org/axs/ax.pl?http://www.theage.com.au/polls/sport/tennis/fault-the-shrieking-debate-20120125-1qgkx.html">"Is
it time to crack down on shrieking"</a>, and <b>91%</b> say Yes.
<p>
]]></content:encoded>
<wfw:commentRss>http://www.nickcoleman.org/blog/index.cgi?post=tennis-melbourne-open-2012%21201201301212%21sport/feed/</wfw:commentRss>
</item>
<item>
<title>Not Much Happening
</title>
<link>http://www.nickcoleman.org/blog/index.cgi?post=not-much-happening%21201201251000%21general</link>
<comments>http://www.nickcoleman.org/blog/index.cgi?post=not-much-happening%21201201251000%21general#comments</comments>
<pubDate>Wed, 25 Jan 2012 10:00:00 -0700</pubDate>
<dc:creator>Nick</dc:creator>
<category>general</category>
<guid isPermaLink="true">http://www.nickcoleman.org/blog/index.cgi?post=not-much-happening%21201201251000%21general/</guid>
<description><![CDATA[ 
 [...]]]></description>
<content:encoded><![CDATA[
<p>
A quick note to say I haven't been posting much because &nbsp; a) it is as hot as
hell, too hot to use my overheating laptop; and &nbsp; b) I've been involved in a
couple of projects that have been overheating my laptop, and I will post about them
soon.
<p>
]]></content:encoded>
<wfw:commentRss>http://www.nickcoleman.org/blog/index.cgi?post=not-much-happening%21201201251000%21general/feed/</wfw:commentRss>
</item>
<item>
<title>Tumblr Blog
</title>
<link>http://www.nickcoleman.org/blog/index.cgi?post=tumblr-blog%21201201171133%21general%2Cblogging</link>
<comments>http://www.nickcoleman.org/blog/index.cgi?post=tumblr-blog%21201201171133%21general%2Cblogging#comments</comments>
<pubDate>Tue, 17 Jan 2012 11:33:00 -0700</pubDate>
<dc:creator>Nick</dc:creator>
<category>general</category>
<category>blogging</category>
<guid isPermaLink="true">http://www.nickcoleman.org/blog/index.cgi?post=tumblr-blog%21201201171133%21general%2Cblogging/</guid>
<description><![CDATA[ 
 [...]]]></description>
<content:encoded><![CDATA[
<p>
I wanted to try out Tumblr to see how easy it was.  Turns out it is pretty easy.
Actually, I'm (surprisingly, perhaps) pleased with how seamless the whole thing was.
<p>
Even from the limited number of posts so far, the tumblr blog gets more feedback, which
always gives an incentive to write more.  I think that applies whether you are driven by
vanity or not. 
<p>
I'm not sure whether I'll keep the tumblr blog going or not, nor how I am going to split
content between the two. 
<p>
I usually blog in two distinct categories: general stuff which includes science, and
unix and programming stuff. For the time being, I guess I will just post to which blog
seems more suitable. 
<p>
You can check out the <a
href="http://www.nickcoleman.org/axs/ax.pl?http://nickcoleman.tumblr.com/">tumblr blog
here</a>.
<p>
]]></content:encoded>
<wfw:commentRss>http://www.nickcoleman.org/blog/index.cgi?post=tumblr-blog%21201201171133%21general%2Cblogging/feed/</wfw:commentRss>
</item>
<item>
<title>Fun With Crumpled Paper
</title>
<link>http://www.nickcoleman.org/blog/index.cgi?post=fun-with-crumpled-paper%21201201141113%21science</link>
<comments>http://www.nickcoleman.org/blog/index.cgi?post=fun-with-crumpled-paper%21201201141113%21science#comments</comments>
<pubDate>Sat, 14 Jan 2012 11:13:00 -0700</pubDate>
<dc:creator>Nick</dc:creator>
<category>science</category>
<guid isPermaLink="true">http://www.nickcoleman.org/blog/index.cgi?post=fun-with-crumpled-paper%21201201141113%21science/</guid>
<description><![CDATA[ 
 [...]]]></description>
<content:encoded><![CDATA[
<p>
Here is a fascinating factoid about crumpled paper.  Take a piece of paper and crumple it,
then place it over another piece of paper.  Some point of the crumpled piece is exactly
over its corresponding point of the other piece.
<p>
No way, you say.
<p>
It is true. You can prove it intuitively.  If you stand somewhere in your city and place a
map of the city on the ground, one point on the map will be exactly over its
corresponding physical point.  It has to be, since the map is nothing but the city
shrunk down.  If you are at the corner of A Street and B Street and place the map on the
ground, the map's A &amp; B corner is right over the actual corner.
<p>
Similarly, the crumpled paper is, in a sense, the paper shrunk down.  If you place the
crumpled paper over another, there must a point on the crumpled paper that is over its
corresponding point on the other piece of paper.
<p>
<div class="footnote">I first read this on <a
href="http://www.nickcoleman.org/axs/ax.pl?http://news.ycombinator.com/item?id=3440326"><i>Hacker
News</i></a> from contributors <em>ColinWright</em> and <em>noblethrasher</em>.</div>
]]></content:encoded>
<wfw:commentRss>http://www.nickcoleman.org/blog/index.cgi?post=fun-with-crumpled-paper%21201201141113%21science/feed/</wfw:commentRss>
</item>
<item>
<title>Calcc, A Programmers' Calculator
</title>
<link>http://www.nickcoleman.org/blog/index.cgi?post=calcc-programmers-calculator%21201201131521%21programming%2Cunix</link>
<comments>http://www.nickcoleman.org/blog/index.cgi?post=calcc-programmers-calculator%21201201131521%21programming%2Cunix#comments</comments>
<pubDate>Fri, 13 Jan 2012 15:21:00 -0700</pubDate>
<dc:creator>Nick</dc:creator>
<category>programming</category>
<category>unix</category>
<guid isPermaLink="true">http://www.nickcoleman.org/blog/index.cgi?post=calcc-programmers-calculator%21201201131521%21programming%2Cunix/</guid>
<description><![CDATA[ 
 [...]]]></description>
<content:encoded><![CDATA[
<p>
<div class="summary">Calcc is a useful command line calculator for programmers, with a
full range of bit and byte operators.</div>
<p>
I have been going through James Malloy's tutorial on writing your own operating system<a
href="#fn1" id="back1"><sup>1 </sup></a>, which involves some assembly and
quite a bit of bit twiddling with shifts and masks in C.
<p>
I haven't written any assembly or done any serious bit manipulation for years.  I can do
simple (i.e. 1 byte) hexadecimal addition in my head, but nothing more complex than that, so I
needed a quick calculator that showed me the results from doing things like bit shifts,
rotates, masking, and so on.
<p>
A bit of googling found one contributor to <a
href="http://www.nickcoleman.org/axs/ax.pl?http://stackoverflow.com/questions/198479/freeware-programmer-calculator">
Stackoverflow recommending</a> <b>calcc</b> by Luigi Auriemma. A quick <a
href="http://www.nickcoleman.org/axs/ax.pl?ualuigi.altervista.org/mytoolz.htm"> download
of a small zip file </a> and there it was, GPL'ed source code and pre-built binaries for
unix and MS Windows.
<p>
It is quick and simple to use and has the usual unary and binary
operators you can think of such as integer maths, logical connectives and bit manipulation. 
<p>
Input can be any of the usual bases of 2, 4, 8, 10 and 16, plus percentages, floats,
datetime and IP dotted quads.  You can mix and match within the one command.  To see a
number conversion, just enter a number and the list will display. Enter multiple numbers
in different formats and with different operators to see the result.
<p>
Most valuable for me is that the output provides everything at once: hex, unsigned and
signed decimal, octal, binary,  ascii, and so on. You don't have to specify the output
like 'print/x' (gdb's way of specifying hex output); it is all there in one list. Very
useful.
<p>
<div class="image">
<img src="http://www.nickcoleman.org/blog/images/calcc_before-screenshot.jpg">
<p>64 bit original version<p>Example input shows addition of decimal + binary + octal + hex</div>
<p>
You can build either a 32 bit or a 64 bit binary by using a compile option.  I prefer
the 32 bit one because I find 8 byte words hard to parse.  It's probably what I am used
to; those of you with 64 bit machines will probably want the 64 bit version.
<p>
I really like this tool. I have had it open in a spare xterm constantly while I go
through the aforementioned tutorial.  Very much recommended for programmers. 
<p>
<h4>Changes</h4>
<p>
I would like to change a couple of things.  Calcc uses <code>fgets</code> to get its
input, which means unix users won't get command-line editing nor, importantly, a command
history buffer (I hate having to retype a command with only one small change).  Also,
sometimes I want to find the hex for an ASCII char, so an ASCII table would be nice.
<p>
I modified calcc to use the GNU readline library. It comes with various command line
editing shortcuts and has a history buffer built in, with which any Bash user is familiar.
I also added an ASCII table and a 'quit' command, plus I tidied up the output to suit my
personal style.
<p>
<div class="image">
<img src="http://www.nickcoleman.org/blog/images/calcc_after-screenshot.jpg">
<p>32 bit version with my changes</div>
<p>
<h4>Output</h4>
<p>
Let's look at the output (for the 32 bit version) and see what it provides.
<table cellpadding="15" frame="box" align="center">
<tr><td>unsigned dec</td> <td>hex</td> <td>octal</td> <td>binary</td><td></td></tr>
<tr><td>signed dec</td> <td>ascii</td> <td>exponential</td> <td>base 4</td> <td>I.P.  address</td></tr>
<tr> <td>base32</td> <td>base64</td> <td>date/time</td> <td></td> </tr>
<tr><td>float</td> <td>double</td></tr>
</table>
<p>
Notice the IP address and datetime fields.  You can do arithmetic on those types too.
See the help for the full list. 
<p>
<h4>Grab the diff</h4>
<p>
You can grab the <a
href="http://www.nickcoleman.org/axs/ax.pl?http://www.nickcoleman.org/dropbox/calcc_changes.diff">diff
file here</a>. Put it in the same directory as the source code and patch it with <code>patch
&lt; calcc_changes.diff</code>
<p>
Drop me a line if you find it useful.  Thanks to Luigi for producing a useful calculator
for programmers.
<p>
<h4>Colourized diff</h4>
<p>
Here is the diff with syntax highlighting for those who want to read it first.
<p>
<div class="pygmentize"><pre><span class="gd">--- calcc.c</span>
<span class="gi">+++ calcc.c</span>
<span class="gu">@@ -18,8 +18,28 @@</span>
     http://www.gnu.org/licenses/gpl-2.0.txt
 */
 
<span class="gi">+/* NJC 01/11/12  </span>
<span class="gi">+* ====== Compilation ==========</span>
<span class="gi">+*</span>
<span class="gi">+* The printed output can be in words of either 4 bytes or 8 bytes, depending on compile-time options.</span>
<span class="gi">+* If you have a 32 bit machine, you may prefer the 4 byte output as it takes less screen space</span>
<span class="gi">+* and is easier to scan.</span>
<span class="gi">+* </span>
<span class="gi">+* Change &quot;my_calcc&quot; to whatever you want to call the binary.</span>
<span class="gi">+*</span>
<span class="gi">+* 32 bit output</span>
<span class="gi">+* gcc calcc.c -DBITS32 -O2 -lreadline -lncurses -o my_calcc</span>
<span class="gi">+*</span>
<span class="gi">+* 64 bit output</span>
<span class="gi">+* gcc calcc.c -DBITS64 -O2 -lreadline -lncurses -o my_calcc</span>
<span class="gi">+*</span>
<span class="gi">+*/</span>
<span class="gi">+</span>
 #include &lt;stdio.h&gt;
 #include &lt;stdlib.h&gt;
<span class="gi">+// NJC 01/10/12   Changed input from fgets to use the readline library</span>
<span class="gi">+#include &lt;readline/readline.h&gt;</span>
<span class="gi">+#include &lt;readline/history.h&gt;</span>
 #include &lt;string.h&gt;
 #include &lt;stdint.h&gt;
 #include &lt;ctype.h&gt;
<span class="gu">@@ -30,8 +50,6 @@</span>
 typedef uint32_t    u32;
 typedef uint64_t    u64;
 
<span class="gd">-</span>
<span class="gd">-</span>
 // #define BITS32   // uncomment to enable 32 bits
 // #define DEBUG    // uncomment to enable the step-by-step visualization
 
<span class="gu">@@ -80,13 +98,17 @@</span>
 char *showtime(NTI num);
 char *showchar(NTI num);
 char *showbase(NTI num, int size, int sign);
<span class="gi">+// NJC 01/11/12 </span>
<span class="gi">+char * rl_gets ();</span>
<span class="gi">+void print_ascii();</span>
 
 
 
 static const u8 b64_table[] = &quot;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/&quot;;
 static const u8 b32_table[] = &quot;ABCDEFGHIJKLMNOPQRSTUVWXYZ234567&quot;;
 static const u8 hex_table[] = &quot;0123456789abcdef&quot;;
<span class="gd">-</span>
<span class="gi">+// NJC 01/11/12 </span>
<span class="gi">+static char *line_read = (char *)NULL;</span>
 
 
 int main(int argc, char *argv[]) {
<span class="gu">@@ -99,7 +121,7 @@</span>
     int     op,
             len,
             slen;
<span class="gd">-    char    buff[READSZ * 9],   // should be enough</span>
<span class="gi">+	    char    buff[READSZ * 9],   // should be enough</span>
             tmp[NTSZ + 1],
             *data,
             *pl,
<span class="gu">@@ -109,12 +131,12 @@</span>
 
     setbuf(stdout, NULL);
 
<span class="gd">-    printf(&quot;\n&quot;</span>
<span class="gd">-        &quot;Calcc &quot;VER&quot; (%d bits version)\n&quot;</span>
<span class="gd">-        &quot;by Luigi Auriemma\n&quot;</span>
<span class="gd">-        &quot;e-mail: aluigi@autistici.org\n&quot;</span>
<span class="gd">-        &quot;web:    aluigi.org\n&quot;</span>
<span class="gd">-        &quot;\n&quot;, NTSZ);</span>
<span class="gi">+    // NJC 01/10/12 removed extra \n&#39;s to make vanity header appear on one line</span>
<span class="gi">+    printf( &quot;Calcc &quot;VER&quot; (%d bits version) &quot;</span>
<span class="gi">+        &quot;by Luigi Auriemma &quot;</span>
<span class="gi">+        &quot;e-mail: aluigi@autistici.org &quot;</span>
<span class="gi">+        &quot;web:    aluigi.org &quot;</span>
<span class="gi">+        &quot;\nType help or ?\n&quot;, NTSZ);</span>
 
     if(argc &gt; 1) {
         p = buff;
<span class="gu">@@ -127,7 +149,10 @@</span>
         goto do_it;
     }
 
<span class="gd">-    while(fgets(buff, READSZ, stdin)) {</span>
<span class="gi">+    // NJC 01/10/12  while(fgets(buff, READSZ, stdin)) {</span>
<span class="gi">+    while(line_read = rl_gets()) {</span>
<span class="gi">+	if (line_read)</span>
<span class="gi">+	    memccpy(buff, line_read, &#39;\0&#39;, READSZ - 1);		// copy readline&#39;s buffer to ours, stopping at first \0 (EOString for readline),  or sizeof buff.</span>
 
 do_it:
         mytolower(buff);
<span class="gu">@@ -159,6 +184,12 @@</span>
             help();
             *buff = 0;
         }
<span class="gi">+	else if (buff[0] == &#39;a&#39;) {</span>
<span class="gi">+	    print_ascii();</span>
<span class="gi">+	    *buff = 0;</span>
<span class="gi">+	}</span>
<span class="gi">+	else if (buff[0] == &#39;q&#39; || buff[0] == &#39;Q&#39;)</span>
<span class="gi">+	    goto quit;</span>
 
         for(;;) {
             data = buff;
<span class="gu">@@ -314,12 +345,13 @@</span>
             showbase(tot, 32, 0), showbase(tot, 64, 0), showtime(tot),
             totfl, totdb);
     }
<span class="gd">-</span>
<span class="gi">+quit:</span>
<span class="gi">+    putchar(&#39;\n&#39;);</span>
     return(0);
 }
 
 
<span class="gd">-</span>
<span class="gi">+// NJC 01/12/12 added a, q/Q/ctrl-D/ctrl-C</span>
 void help(void) {
     fputs(&quot;\n&quot;
         &quot;Input types:\n&quot;
<span class="gu">@@ -331,7 +363,8 @@</span>
         &quot;  y  = year                            t  = time hh:mm:ss (0 for current date)\n&quot;
         &quot;  ,. = float/double numbers (is not possible to make operations on them)\n&quot;
         &quot;     = decimal (default)\n&quot;
<span class="gd">-        &quot;\n&quot;</span>
<span class="gi">+        &quot;  a  = print ASCII table               q,Q,ctrl-D,ctrl-C = quit\n&quot;</span>
<span class="gi">+	&quot;\n&quot;</span>
         &quot;Operators and priority order:\n&quot;
         &quot;  ~  = complement                      !  = not\n&quot;
         &quot;  &lt;&lt; = shift left                      &gt;&gt; = shift right\n&quot;
<span class="gu">@@ -667,7 +700,7 @@</span>
 char *showtime(NTI num) {
     struct  tm  *tmx;
     time_t  datex;
<span class="gd">-    static  char    buff[32];</span>
<span class="gi">+    static  char    buff1[32];</span>
     static const char   *day[] =
             { &quot;Sun&quot;,&quot;Mon&quot;,&quot;Tue&quot;,&quot;Wed&quot;,&quot;Thu&quot;,&quot;Fri&quot;,&quot;Sat&quot; },
             *months[] =
<span class="gu">@@ -677,14 +710,14 @@</span>
     tmx = gmtime(&amp;datex);
     if(!tmx) return(&quot;none&quot;);
     sprintf(
<span class="gd">-        buff,</span>
<span class="gi">+        buff1,</span>
         &quot;%s %02d %s %d %02d:%02d:%02d&quot;,
         day[tmx-&gt;tm_wday],
         tmx-&gt;tm_mday,
         months[tmx-&gt;tm_mon],
         1900 + tmx-&gt;tm_year,
         tmx-&gt;tm_hour, tmx-&gt;tm_min, tmx-&gt;tm_sec);
<span class="gd">-    return(buff);</span>
<span class="gi">+    return(buff1);</span>
 }
 
 
<span class="gu">@@ -746,4 +779,80 @@</span>
     return(o + i);
 }
 
<span class="gd">-</span>
<span class="gi">+// NJC 01/11/12  from the readline library guide at gnu.org.</span>
<span class="gi">+/* Read a string, and return a pointer to it.</span>
<span class="gi">+   Returns NULL on EOF. */</span>
<span class="gi">+char *</span>
<span class="gi">+rl_gets ()</span>
<span class="gi">+{</span>
<span class="gi">+  /* If the buffer has already been allocated,</span>
<span class="gi">+     return the memory to the free pool. */</span>
<span class="gi">+  if (line_read)</span>
<span class="gi">+    {</span>
<span class="gi">+      free (line_read);</span>
<span class="gi">+      line_read = (char *)NULL;</span>
<span class="gi">+    }</span>
<span class="gi">+</span>
<span class="gi">+  /* Get a line from the user. */</span>
<span class="gi">+  line_read = readline (&quot; &gt; &quot;);</span>
<span class="gi">+</span>
<span class="gi">+  /* If the line has any text in it,</span>
<span class="gi">+     save it on the history. */</span>
<span class="gi">+  if (line_read &amp;&amp; *line_read)</span>
<span class="gi">+    add_history (line_read);</span>
<span class="gi">+</span>
<span class="gi">+  return (line_read);</span>
<span class="gi">+}</span>
<span class="gi">+</span>
<span class="gi">+// NJC 01/11/12 Print the ASCII table</span>
<span class="gi">+void</span>
<span class="gi">+print_ascii() {</span>
<span class="gi">+    u8 i, j, x;</span>
<span class="gi">+    char  a[10] = &quot;&quot; ;					// wide enough to hold ascii representation of non-keyboard chars like DEL etc.</span>
<span class="gi">+    for (i = 0 ; i &lt; 20 ; i++  ) {			// print in columns, 10 cols wide == 20 rows to hold 127 data points.</span>
<span class="gi">+	for ( j = 0 ; j &lt; 128 ; j += 20 ) {		// each new column is +20 from the one to the left.</span>
<span class="gi">+	    x = i + j;</span>
<span class="gi">+	    if ( x &gt; 127 )</span>
<span class="gi">+		break ;					// no more ASCII chars after decimal 127</span>
<span class="gi">+	    switch (x) {</span>
<span class="gi">+		case   0: strcpy(a, &quot;NUL&quot;); break;</span>
<span class="gi">+		case   1: strcpy(a, &quot;SOH&quot;); break;</span>
<span class="gi">+		case   2: strcpy(a, &quot;STX&quot;); break;</span>
<span class="gi">+		case   3: strcpy(a, &quot;ETX&quot;); break;</span>
<span class="gi">+		case   4: strcpy(a, &quot;EOT&quot;); break;</span>
<span class="gi">+		case   5: strcpy(a, &quot;ENQ&quot;); break;</span>
<span class="gi">+		case   6: strcpy(a, &quot;ACK&quot;); break;</span>
<span class="gi">+		case   7: strcpy(a, &quot;BEL \\a&quot;); break;</span>
<span class="gi">+		case   8: strcpy(a, &quot;BS \\b&quot;); break;</span>
<span class="gi">+		case   9: strcpy(a, &quot;HT \\t&quot;); break;</span>
<span class="gi">+		case  10: strcpy(a, &quot;LF \\n&quot;); break;</span>
<span class="gi">+		case  11: strcpy(a, &quot;VT \\t&quot;); break;</span>
<span class="gi">+		case  12: strcpy(a, &quot;FF \\f&quot;); break;</span>
<span class="gi">+		case  13: strcpy(a, &quot;CR \\r&quot;); break;</span>
<span class="gi">+		case  14: strcpy(a, &quot;SO&quot;); break;</span>
<span class="gi">+		case  15: strcpy(a, &quot;SI&quot;); break;</span>
<span class="gi">+		case  16: strcpy(a, &quot;DLE&quot;); break;</span>
<span class="gi">+		case  17: strcpy(a, &quot;DC1&quot;); break;</span>
<span class="gi">+		case  18: strcpy(a, &quot;DC2&quot;); break;</span>
<span class="gi">+		case  19: strcpy(a, &quot;DC3&quot;); break;</span>
<span class="gi">+		case  20: strcpy(a, &quot;DC4&quot;); break;</span>
<span class="gi">+		case  21: strcpy(a, &quot;NAK&quot;); break;</span>
<span class="gi">+		case  22: strcpy(a, &quot;SYN&quot;); break;</span>
<span class="gi">+		case  23: strcpy(a, &quot;ETB&quot;); break;</span>
<span class="gi">+		case  24: strcpy(a, &quot;CAN&quot;); break;</span>
<span class="gi">+		case  25: strcpy(a, &quot;EM&quot;); break;</span>
<span class="gi">+		case  26: strcpy(a, &quot;SUB&quot;); break;</span>
<span class="gi">+		case  27: strcpy(a, &quot;ESC&quot;); break;</span>
<span class="gi">+		case  28: strcpy(a, &quot;FS&quot;); break;</span>
<span class="gi">+		case  29: strcpy(a, &quot;GS&quot;); break;</span>
<span class="gi">+		case  30: strcpy(a, &quot; RS&quot;); break;</span>
<span class="gi">+		case  31: strcpy(a, &quot; US&quot;); break;</span>
<span class="gi">+		case  32: strcpy(a, &quot;space&quot;); break;</span>
<span class="gi">+		case 127: strcpy(a, &quot;DEL&quot;); break;</span>
<span class="gi">+		default:  a[0] = x ; a[1] = &#39;\0&#39;;</span>
<span class="gi">+	    }</span>
<span class="gi">+	    printf(&quot;%6s %3.0d %2X\t&quot;,a,x,x);</span>
<span class="gi">+	}</span>
<span class="gi">+	putchar(&#39;\n&#39;);</span>
<span class="gi">+    }</span>
<span class="gi">+}</span>
</pre></div>
<p>
<hr>
<div class="footnote">
<a href="#back1" id="fn1">[1] </a> 
<a
href="http://www.nickcoleman.org/axs/ax.pl?http://www.jamesmolloy.co.uk/tutorial_html/index.html">
Roll your own toy unix-clone operating system</a><a href="#back1">&#8593;</a>
</div>
]]></content:encoded>
<wfw:commentRss>http://www.nickcoleman.org/blog/index.cgi?post=calcc-programmers-calculator%21201201131521%21programming%2Cunix/feed/</wfw:commentRss>
</item>
<item>
<title>Simon O'Donnell Leaves The Cricket Show
</title>
<link>http://www.nickcoleman.org/blog/index.cgi?post=cricketsimon%21201112290958%21sport</link>
<comments>http://www.nickcoleman.org/blog/index.cgi?post=cricketsimon%21201112290958%21sport#comments</comments>
<pubDate>Thu, 29 Dec 2011 09:58:00 -0700</pubDate>
<dc:creator>Nick</dc:creator>
<category>sport</category>
<guid isPermaLink="true">http://www.nickcoleman.org/blog/index.cgi?post=cricketsimon%21201112290958%21sport/</guid>
<description><![CDATA[ 
 [...]]]></description>
<content:encoded><![CDATA[
<p>
If you are wondering where Simon O'Donnell is in <a
href="http://www.nickcoleman.org/axs/ax.pl?http://en.wikipedia.org/wiki/The_Cricket_Show"><i>The
Cricket Show</i></a>, it turns out he will be the host for Nine's <i>Sunday Footy
Show</i>.  O'Donnell is leaving because he has commitments outside Channel Nine and
would not be able to do both shows. 
<p>
I like O'Donnell's presentation style.  He had an easy conversational interview style
and he had the knowledge that comes from being a former Test player.  With his relaxed
nature, he was able to get past the formulaic plastic face of PR spin and get his
interviewees to really talk about themselves and their game.  His tips and answers to
young viewer questions about their technique was insightful.
<p>
All in all, it was an enjoyable way to spend the lunch break and get some of the
background and culture of cricket.
<p>
Michael Slater is taking up the reigns from O'Donnell and, from his efforts so far, is
doing a pretty good job.
<p>
]]></content:encoded>
<wfw:commentRss>http://www.nickcoleman.org/blog/index.cgi?post=cricketsimon%21201112290958%21sport/feed/</wfw:commentRss>
</item>
<item>
<title>ABC3 TV Good Listening
</title>
<link>http://www.nickcoleman.org/blog/index.cgi?post=abc3%21201112210922%21entertainment</link>
<comments>http://www.nickcoleman.org/blog/index.cgi?post=abc3%21201112210922%21entertainment#comments</comments>
<pubDate>Wed, 21 Dec 2011 09:22:00 -0700</pubDate>
<dc:creator>Nick</dc:creator>
<category>entertainment</category>
<guid isPermaLink="true">http://www.nickcoleman.org/blog/index.cgi?post=abc3%21201112210922%21entertainment/</guid>
<description><![CDATA[ 
 [...]]]></description>
<content:encoded><![CDATA[
<p>
ABC3 is the <a
href="http://www.nickcoleman.org/axs/ax.pl?http://en.wikipedia.org/wiki/ABC_Television">ABC
TV's</a> station for young viewers, mainly pre-teens.  It closes around 9pm each night.
Then they play some music and display a "We will be back tomorrow" image.
<p>
Over the last few months, I have occasionally miscued the remote and landed there.
Surprisingly, or perhaps not given the time of night, the music is not kiddies' music.
Sometimes it is really great.
<p>
Last night, for example, appeared to be Funk night, with some great tunes from the 80s
and 90s and including some bands you have never heard of like <i>The Soul Seven</i> who
were mainly a session band and who only put out two singles.  
<p>
I don't know if they are using <a
href="http://www.nickcoleman.org/axs/ax.pl?http://en.wikipedia.org/wiki/Rage_(TV_program)"><em>Rage</em></a>'s
producers to draw up their play list, but whoever did certainly knows their music.
<p>
Last night I cancelled my TV viewing, cranked up the volume and listened to some good
music courtesy of ABC3 Childrens' Channel.
<p>
]]></content:encoded>
<wfw:commentRss>http://www.nickcoleman.org/blog/index.cgi?post=abc3%21201112210922%21entertainment/feed/</wfw:commentRss>
</item>
<item>
<title>Slackware's New(ish) Cron Is Great For Laptops
</title>
<link>http://www.nickcoleman.org/blog/index.cgi?post=cronslackware%21201112181115%21unix</link>
<comments>http://www.nickcoleman.org/blog/index.cgi?post=cronslackware%21201112181115%21unix#comments</comments>
<pubDate>Sun, 18 Dec 2011 11:15:00 -0700</pubDate>
<dc:creator>Nick</dc:creator>
<category>unix</category>
<guid isPermaLink="true">http://www.nickcoleman.org/blog/index.cgi?post=cronslackware%21201112181115%21unix/</guid>
<description><![CDATA[ 
 [...]]]></description>
<content:encoded><![CDATA[
<p>
<div class="summary">Slackware's cron daemon has some new features that make it
especially good for laptops.</div>
<p>
As long as I can remember, Slackware has used Dillon's cron <strong>dcron</strong> as its cron
daemon.  Dcron is a lightweight cron with an emphasis on a solid secure codebase which,
while missing a few esoteric features found in bigger cron daemons, is great for most users.
<p>
Since 13.1 and continuing with 13.37, Slackware has had an updated version of dcron that
introduced some very handy features that make it especially suitable for laptops, or
indeed any machine that spends much of its time in sleep mode.  The features give dcron
some of the characteristics of <a href="http://www.nickcoleman.org/axs/ax.pl?http://en.wikipedia.org/wiki/Anacron"><i>anacron</i></a>. 
<p>
Somehow I managed to miss the changes until now, almost two years later.  (I must have
been in a personal sleep mode.)  Here I am going to explain the features and why they
are great for laptops, and give a couple of examples.
<p>
<h2>Sleep</h2> 
Over the years you have probably picked up several handy scripts that you run from a
cron job. Some of them might run every day, some of them every week.  For example, I
have a weather script that grabs the local weather forecast from the Bureau of
Meteorology website, parses it, and emails me a summary of today's forecast at 7:10
every morning.  What if my laptop is in sleep mode at 7:10am?  In that case, the script
does not get a chance to run because 7:10am has lapsed by the time I open my laptop.
<p>
<h2>ID and FREQ</h2>
Now dcron lets you give an ID to a cron job which acts as a reference to that job.  The
point of having a reference is that the job no longer disappears into thin air if its
activation time has passed while the machine was asleep. 
<p>
The FREQ keyword specifies how often you want cron to check if the job ID has run in
order to reschedule it if it has not.  In the case of my weather script, the crontab
entry looks like this, with the original entry first and the improved entry second (in
case it is not obvious, I deleted the first entry in the real crontab):
<div class="code">
10  7  * * *   /home/user/bin/forecast
10,40  7-11 * * *  ID=weather FREQ=4h/30m   /home/user/bin/forecast
</div>
The first entry runs the forecast script at 7:10am.  If the machine is asleep, it is
not activated.  
<p>
With the second entry and ignoring the ID and FREQ keywords for the moment, the script
runs every 10 past and 40 past the hour for the hours of 7, 8, 9, 10 and 11 o'clock.
Obviously I do not want it to run at each of those times and this is where the FREQ
keyword comes in.  The FREQ entry says to run the job only if it has been at least 4
hours since it last ran, and to check on this every 30 minutes.
<p>
Take this morning as an example.  I opened the laptop at 10:15am.  The last time this
entry ran was yesterday morning.  Upon wakeup, dcron checks this entry and notices that job ID of
<strong>weather</strong> last ran more than 4 hours ago, so it is good to go. At 10:40 (the next
available slot), the job ran.  Since then, it has not run again because before 14:40 it is less than
4 hours since it last ran, and after 14:40 it is outside its scheduled times of 7-11.
<p>
Most of my personal crontab entries now use this method.
<p>
You can see why this type of crontab entry needs an ID, because dcron needs some way of
tracking how recently a particular job ran.  Rather than use an internally-generated ID, it gives
you the ability to specify your own.  A side benefit is that the cron emails use the ID
in their subject header (which is why I use meaningful words rather than a number).
<p>
<h3>Scheduling</h3> 
A few points on scheduling.  You need to allow sufficient range in your times so that
the job can run.  Note the weather script previously had only 7am specified, now it has
a range of 7-11 to allow a wide time period for the script to run (presumably I am not
interested in getting the forecast after 11am).  And, the FREQ range needs to be long
enough so that the job will not run again until the next time period, but short enough
so that it can run again.  Confused?  An example.
<p>
If I want a job to run every day, I should not specify <code>FREQ=1d</code>. Say I had
a range of 7-11 hours, and the job ran at 11:40.  The next day I open the laptop early
and, at 7:10am, the job would not run because it had not been 24 hours since the last
run.  This is not what I want.  If I specify <code>FREQ=12h</code>, the job would run at
7:10am.
<p>
Conversely, I should not specify <code>FREQ=2h</code> because then the job would run at,
for example, 7:10am, 9:10am and 11:10am if my laptop was open early, again not what I want.
<p>
The FREQ should be long enough so that the job cannot run again within the same time
period, but short enough so that if it last ran at the <strong>latest</strong> time it can next run at
the <strong>earliest</strong> time.
<p>
<h2>Other Features</h2>
There are some other features in the new dcron too.  
<ul><li>FREQ can re-run a job if it did not exit cleanly (use exit 11 to signal this).</li>
<li>A job can depend on another job(s) such as "run job2 only if job1 (and job0 and &hellip; ) has already run".
Use the keyword AFTER.</li>
<li>You can now use the keywords of @hourly, @daily, @weekly, @monthly and @yearly, which users of
other crons have missed in dcron.</li>
</ul>
<p>
<h2>Summary</h2>
The new cron daemon introduces some features that let cron jobs that are missed while a
machine is in sleep mode run once the machine is wakened.  This provides some of the
features of anacron.  It also gives extra flexibility with jobs that can depend on other
jobs, and with new keywords.
<p>
]]></content:encoded>
<wfw:commentRss>http://www.nickcoleman.org/blog/index.cgi?post=cronslackware%21201112181115%21unix/feed/</wfw:commentRss>
</item>
</channel>
</rss>

