Never been to TextSnippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world (or not, you can keep them private!)

About this user

Guido Sohne

« Newer Snippets
Older Snippets »
7 total  XML / RSS feed 


Implementation of CRC-CCITT (CRC-16 variant) in Objective Caml. Uses a bit vector implementation but is not table driven.

 open Bitv
 open List
 open Printf

 (* convenience functions *)
 let bits initf = Bitv.init 16 initf 
 let zeros = Bitv.create 16 false
 let ones = Bitv.create 16 true
 let from_str s = function n -> (String.get s n) == '1'

 (* CC-ITT CRC polynomials: big endian and little endian *)
 let poly8048 =   from_str "1000010000001000" 
 let poly1021 =   from_str "0001000000100001" 

 (* bit twiddling functions. I hate that OCaml doesn't have a bit vector type *)
 (* and unsigned ints are 30 bits, and signed ints are 31 bits if that isn't wierd enough *)
 (* and no, there is no 16 bit type that can be used as an integer. Sigh. *)
 let bit n bits = Bitv.get bits n
 let shl n bitv = Bitv.shiftl bitv n
 let bxor bitv1 bitv2 = Bitv.bw_xor bitv1 bitv2
 let byte_bits c = Bitv.sub (Bitv.of_int_us(int_of_char c)) 0 8
 let pad n bits = Bitv.append bits (Bitv.create n false)

 (* calculate the CRC for a given byte value. can use this to create a table *)
 (* lookup version that should be faster, should you find yourself in a big hurry *)
 let chksum poly remainder byte = 
   let rem = bxor (shl 8 (pad 8 byte)) remainder in
   let sum remnant = 
     let shifted = shl 1 remnant in 
     if bit 15 remnant then bxor shifted poly else shifted
   in let rec bits at max remnant byte =
     if at < max then bits (at + 1) max (sum remnant) byte else remnant
   in bits 0 8 rem byte

 (* fold the list, collecting and applying the checksum to each byte *)
 let crc init bytes =
   List.fold_left (chksum (bits poly8048)) init bytes

 (* test to see if we get the proper output corresponding to a correct implementation *)
 (* should be 0x29B1, ocaml ints have 30 bits, accounting for strange pad value used *)
 let result = 
   let bits = byte_bits ['1';'2';'3';'4';'5';'6';'7';'8';'9';] in
   printf "0x%X\n" (Bitv.to_int_us(pad 14 (crc ones bits)))

Convert numbers to words

Ugly code. But it works. If you have something better, then post it.

This code is probably (definitely :-) buggy, so if you want to get real work done, just use the Linguistics gem instead.

class Number
  def self.to_words(number)
  def self.commify(number)
  def initialize
    @unit = %w[zero one two three four five six seven eight nine]
    @teen = %w[ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen]
    @tens = %w[zero ten twenty thirty fourty fifty sixty seventy eighty ninety]
    @qtys = %w[hundred thousand million billion trillion quadrillion quintillion]
    @zero = ["zero"]
    @hundred = "hundred"
    @sepr = "and"
  def to_s(number)
    out = quantify(number).flatten
    for x in 0 .. out.length - 1
      out[x] = nil if out[x] == @sepr && out[x+1] == @sepr
    out = @zero if out.length == 1 && out[0] == @sepr
    out.pop while out.last == @sepr
    out.shift while out.first == @sepr    
    out.join(' ').gsub(/ ,/,',')
  def padded_groups(v)
    out = []
    padded = (s=v.to_s;x=s.length;s).rjust(x+(3-(x%3))).gsub(//,'0')
  def wordify(v)
    out = []
    zero = '0'[0]
    h, t, u = v[0] - zero, v[1] - zero, v[2] - zero
    if h != 0
      out << @unit[h]
      out << @hundred
    out << @sepr if h != 0 && (t != 0 || u != 0)
    out << @sepr if h == 0 && t == 0 && u != 0
    if t == 1
      out << @teen[u]
      out << @tens[t] if t != 0
      out << @unit[u] if u != 0
    return out
  def quantify(v)
    v = padded_groups(v).reverse
    pos = v.length - 1
    out = []
    while pos >= 0
      word = wordify(v[pos])
      if word[0] != nil
        out << word
        out << @qtys[pos] if pos != 0                
        out << @sepr
      pos -= 1
    return out


# for number in [
#     0, 
#     1, 
#     3, 
#     11, 
#     100,
#     1000, 
#     1001, 
#     1100, 
#     1101, 
#     1_000_001, 
#     8_000_000_000, 
#     8_000_000_001, 
#     4_567_890_923, 
#     6_804_567_890_903, 
#     5_006_804_567_890_903
#   ]
#   print "#{Number.commify(number)}: #{Number.to_words(number)}\n"
# end

Convenient and fast text input using a numeric keypad

Recently, I had to program a device that had only a numeric keypad for some light data entry. The manufacturer had a relatively cumbersome method for entering text and I had to come up with an alternative means to more conveniently enter text using the numeric keypad.

The application did not require mixed case characters, so I decided to limit data entry to uppercase characters to reduce the number of keystrokes required. Unlike typical mobile phone input, there is no timeout for the next character to be entered. Adding this is not hard at all, and would probably only require about three to five extra lines of code ...

void succ(int* ip, char* cp, char* ch)
    int il = strlen(ch);
    char *np;
    if(*(cp + *ip) == '\0') {
        *(cp + *ip) = *ch;
    np = strchr(ch, *(cp + *ip));
    if(np == NULL) {
        *(cp + *ip) = *ch;
    } else if(np == ch + il - 1) {
        *(cp + *ip) = *ch;
    } else {
        *(cp + *ip) = *(np + 1);

int textual_input(int line, char *destination, int maxlen)
    int nKey, i = 0;
    char text[128];

    memset(text, 0, sizeof(text));

        nKey = Sys_Key_WaitKey();
        switch (nKey)
            case KEY_DEL: text[i] = '\0'; i > 0 ? i-- : i = 0; break;
            case KEY_0: i++; text[i] = ' '; break;
            case KEY_1: i++; break;
            case KEY_2: succ(&i, text, "ABC"); break;
            case KEY_3: succ(&i, text, "DEF"); break;
            case KEY_4: succ(&i, text, "GHI"); break;
            case KEY_5: succ(&i, text, "JKL"); break;
            case KEY_6: succ(&i, text, "MNO"); break;
            case KEY_7: succ(&i, text, "PQRS"); break;
            case KEY_8: succ(&i, text, "TUV"); break;
            case KEY_9: succ(&i, text, "WXYZ"); break;
            case KEY_ENTER: goto done; break;
            case KEY_CANCEL: goto cancel; break;
        Syd_DisplayLine(line, text, 0, ALIGN_LEFT );
    strncpy(destination, text, maxlen);
    return 0;
    memset(destination, 0, maxlen);
    return -1;

I hope someone finds this code useful. It's not a huge piece of code, not hard to understand and is also small enough to maintain. As always, I love to hear of better ways to do things so any suggestions are welcome!

Building a uClinux toolchain on Mac OS X (10.4.4)

[Article originally posted at]


You'll need Bernardo Innocenti's sources available from

It's probably wise to choose the most recent version of his sources, and hope for the best. Stick to the exact version of each source required (e.g. gcc 3.4.0 != gcc 3.4.3). I tried 3.4.3 but it crashed inside xgcc due to my incompetence at patching the sources.


Your experience may differ from mine. What I do know is that building this takes quite some time and you won't enjoy doing it again and again to fix problems (unless that's your sort of fun!)

Before building, install DarwinPorts and
        sudo port install coreutils
        sudo port install gsed
        sudo ln -s /opt/local/bin/gcp /opt/local/bin/cp
        sudo ln -s /opt/local/bin/gnused /opt/local/bin/sed
        export PATH=/opt/local/bin:$PATH 
        sudo gcc_select 3.3

Start the build process by editing the script as per your needs. I used Apple gcc 3.3 with the following settings in ...

After setting up the script and downloading the necessary additional files and patches, you can do
        cd where-ever-your-buildroot-is
        sh build-uclinux-tools build

and each time you encounter an error (and hopefully fix what's causing it) you can do
        sh build-uclinux-tools continue


You're going to run into various errors during the build. These steps document how I managed to get past them. There are probably mistakes in them, or at least better ways to do them. Suggestions and improvements are most welcome. It should be easy to make this into a patch. Maybe I'll do that the next time around, but it took so long to build that I wouldn't hold my breath for it.

1) Building elf2flt-20040326

You'll get an error saying "elf.h not found" (it's not present on Darwin systems)
        cp uClibc-0.9.26/include/elf.h elf2flt-20040326

Edit elf2flt-20040326/elf.h and uncomment the #include line. During linking, you'll get an error saying crt0.a not found. Edit, and change
                LDFLAGS = @LDFLAGS@ -static

                LDFLAGS = @LDFLAGS@ 

And that should take care of it for you. Continue building via
        sh build-uclinux-tools continue    

2) Building m68k-bdm-1.3.0

This will fail because BDM hardware access hasn't been written for Darwin yet. The ioperm system call is missing, and there's no native driver, so edit and in the stageA function, replace the following lines

        --with-libiberty=${BASEDIR}/${TARGET}-binutils/libiberty/libiberty.a \

with the lines below

     --with-libiberty=${BASEDIR}/${TARGET}-binutils/libiberty/libiberty.a \
        --disable-ioperm --disable-driver \

i.e. add --disable-ioperm and --disable-driver to the configure stanza.

3) Building m68k-bdm-1.3.0

This will fail again since its trying to build a static executable. Apparently, that's a no-no on Darwin. Edit and in the utils directory and remove the -static lurking as below:-
        bdmctrl_LDFLAGS = -static

should be changed to
        bdmctrl_LDFLAGS =

You should be still able to connect to a remote server that's running BDM. Since I'm running on a Powerbook, which doesn't even have a parallel port, it's not a big deal to not build the hardware interface bits of BDM. Your mileage may vary. You should be able to continue your build now.

4) Building gdb-6.1

You will receive an error due to an incorrect gdb.texinfo file. Edit gdb-6.1/gdb/doc/gdb.texinfo and around line 6961 (or whatever makeinfo complained about) and change
@strong{Note:} a trace experiment and data collection may stop automatically if any tracepoint's passcount is reached
(@pxref{Tracepoint Passcounts}), or if the trace buffer becomes full.

to become
Note: a trace experiment and data collection may stop automatically if any tracepoint's passcount is reached
(@pxref{Tracepoint Passcounts}), or if the trace buffer becomes full.

After this, you should have a successful build. All the tools will be installed on your system by Bernardo's excellent build script.

Format an integer with commas to make it more readable

More information or better ways of doing this welcome ...

def commify(number)
    c = { :value => "", :length => 0 }
    r = number.to_s.reverse.split("").inject(c) do |t, e|  
      iv, il = t[:value], t[:length]
      iv += ',' if il % 3 == 0 && il != 0    
      { :value => iv + e, :length => il + 1 }

Alex Young suggested

def commify(v)

and there's always

number_with_delimiter(number, delimiter)

from NumberHelper in the Rails API ... which is implemented as follows:-

def number_with_delimiter(number, delimiter=",")
  number.to_s.gsub(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{delimiter}")

They don't always work too well when the number has a decimal point in it (and more than two or so digits after the decimal point), so there's room for an improved version ...

JV suggested the following snippet from which appears to be able to handle commas and decimal places as well.

def commify(n)
    n.to_s =~ /([^\.]*)(\..*)?/
    int, dec = $1.reverse, $2 ? $2 : ""
    while int.gsub!(/(,|\.|^)(\d{3})(\d)/, '\1\2,\3')
    int.reverse + dec

Rake task to load fixtures in a specific order

The default task for loading fixtures, rake load_fixtures, appears to load the fixture data in alphabetical order. If you have foreign key or other constraints, it may be impossible to load the fixtures into the database.

The rake task below searches for a file called test/ordered_fixtures.rb and loads that file. The file contains code that sets an environment variable specifying the load order for fixtures.

  %w( entities interaction_sources interaction_devices payments 
      interactions accounts employments enrollments payables 
      receivables tenures wards ).join(' ')

The lib/tasks/fixtures.rake (rake load_fixtures_ordered) task first loads all fixtures specified via ordered_fixtures, and then loads all other fixtures not specified as being ordered so it should work for you even if you do not create an ordered_fixtures file.

require File.expand_path(File.dirname(__FILE__) + "/../../config/environment")
require File.expand_path(File.dirname(__FILE__) + "/../../test/ordered_fixtures")


desc "Load fixtures into #{ENV['RAILS_ENV']} database"
task :load_fixtures_ordered => :environment do
  require 'active_record/fixtures'  
  ordered_fixtures =
  ENV["FIXTURE_ORDER"].split.each { |fx| ordered_fixtures[fx] = nil }
  other_fixtures = Dir.glob(File.join(RAILS_ROOT, 'test', 'fixtures', '*.{yml,csv}')).collect { |file| File.basename(file, '.*') }.reject {|fx| ordered_fixtures.key? fx }
  (ordered_fixtures.keys + other_fixtures).each do |fixture|
    Fixtures.create_fixtures('test/fixtures',  fixture)
  end unless :environment == 'production' 
  # You really don't want to load your *fixtures* 
  # into your production database, do you?  

The code may not be the best but it Works For Me.

svnserve launchd item for OS X 10.4

It's not that straightforward getting svnserve to work under launchd. I can't take the credit for this but I thought it would be useful to have it here on TextSnippets.

1) Install subversion if you don't have it already. Here's how with DarwinPorts.

sudo port install subversion

Or just download it from ...

2) Create your Subversion repository (for my own use, I used /Users/xyz/Repositories) e.g.

svnadmin create /Users/xyz/Repositories

3) Place the following XML into a file named org.tigris.subversion.svnserve.plist in the /Library/LaunchDaemons directory.

<?xml version="1.0" encoding="UTF-8"?>
DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "">
<plist version="1.0">
        SVN Version Control System</string>

You'll need to change xyz to your user name ...

4) Test it out by doing a

sudo launchctl load /Library/LaunchDaemons/org.tigris.subversion.svnserve.plist

sudo launchctl start org.tigris.subversion.svnserve

svn co svn://
« Newer Snippets
Older Snippets »
7 total  XML / RSS feed