Monday, December 24, 2018

The author of tbas, Antonio Maschio, loves DATA and READ statements, and after putting together a Chinese Zodiac submission for RosettaCode, I can see why. And then there's TAB() which is also very helpful.
DATA "甲","乙","丙","丁","戊","己","庚","辛","壬","癸"
 DECLARE celestial$(10)
 MAT READ celestial$
 DATA "子","丑","寅","卯","辰","巳","午","未","申","酉","戌","亥"
 DECLARE terrestrial$(12)
 MAT READ terrestrial$
 DATA "Rat","Ox","Tiger","Rabbit","Dragon","Snake","Horse","Goat","Monkey","Rooster","Dog","Pig"
 DECLARE animals$(12)
 MAT READ animals$
        DATA "Wood","Fire","Earth","Metal","Water"
 DECLARE elements$(5)
 MAT READ elements$
 DATA "yang","yin"
 DECLARE aspects$(2)
 MAT READ aspects$
 DATA "jiă","yĭ","bĭng","dīng","wù","jĭ","gēng","xīn","rén","gŭi"
 DATA "zĭ","chŏu","yín","măo","chén","sì","wŭ","wèi","shēn","yŏu","xū","hài"
 DECLARE celestialpinyin$(UBOUND(celestial$(),1))
 DECLARE terrestrialpinyin$(UBOUND(terrestrial$(),1))
 MAT READ celestialpinyin$
 MAT READ terrestrialpinyin$
 DATA 1935,1938,1931,1961,1963,1991,1993,1996,2001
 DECLARE years(9)
 MAT READ years
 DECLARE _base = 4  
 DECLARE _year 
 DECLARE cycleyear 
 DECLARE stemnumber 
 DECLARE stemhan$    
 DECLARE stempinyin$ 
 DECLARE elementnumber 
 DECLARE element$       
 DECLARE branchnumber 
 DECLARE branchhan$    
 DECLARE branchpinyin$ 
 DECLARE animal$       
 DECLARE aspectnumber 
 DECLARE aspect$       
 DECLARE index 
 DECLARE top = UBOUND(years(),1)
 FOR i = 1 TO top
  _year = years(i)
  cycleyear = _year - _base
  stemnumber = MOD(cycleyear, 10) 
  stemhan$    = celestial$(stemnumber + 1)
  stempinyin$ = celestialpinyin$(stemnumber + 1)
  elementnumber = div(stemnumber, 2) + 1
  element$       = elements$(elementnumber)
  branchnumber = MOD(cycleyear, 12)  
  branchhan$    = terrestrial$(branchnumber + 1)
  branchpinyin$ = terrestrialpinyin$(branchnumber + 1)
  animal$       = animals$(branchnumber + 1)
  aspectnumber = MOD(cycleyear, 2)
  aspect$       = aspects$(aspectnumber + 1)
  index = MOD(cycleyear, 60) + 1  
  PRINT _year; 
  PRINT TAB(5);stemhan$+branchhan$;
  PRINT TAB(12);stempinyin$;"-";branchpinyin$;
  PRINT TAB(25);element$;" ";animal$;" ("+aspect$+")";
  PRINT TAB(50);"year";index;"of the cycle"  
Running the program gives
$ tbas chinZod.bas
 1935 乙亥 yĭ-hài     Wood Pig (yin)           year 12 of the cycle
 1938 戊寅 wù-yín     Earth Tiger (yang)       year 15 of the cycle
 1931 辛未 xīn-wèi    Metal Goat (yin)         year 8 of the cycle
 1961 辛丑 xīn-chŏu   Metal Ox (yin)           year 38 of the cycle
 1963 癸卯 gŭi-măo    Water Rabbit (yin)       year 40 of the cycle
 1991 辛未 xīn-wèi    Metal Goat (yin)         year 8 of the cycle
 1993 癸酉 gŭi-yŏu    Water Rooster (yin)      year 10 of the cycle
 1996 丙子 bĭng-zĭ    Fire Rat (yang)          year 13 of the cycle
 2001 辛巳 xīn-sì     Metal Snake (yin)        year 18 of the cycle
© Copyright Bruce M. Axtens, 2018

Thursday, March 15, 2018

[PHP] Include a data structure once

Today's job at work was to get some data into GravityForms, a forms tool for WordPress.

So one page has a postcode entry, and the next page has some hidden postcode-specific fields that are used to calculate values later in the form-set, in this case freight costs on goods delivered by
TNT (no relation to the song by AC/DC).

The documentation for GravityForms suggests putting code into functions.php in the active theme. I'm a little wary of doing that given that changes there can work or not work in a rather catastrophic way.

Nevertheless, I ended up coding against the gform_field_input hook
add_filter('gform_field_input', 'update_hidden', 10, 5);
function update_hidden($input, $field, $value, $lead_id, $form_id)
So then the was the issue of how to include the postcode-to-charges array (PCA) (stored in an external php file) once rather than each time gform_field_input fired, which is once per control. With the PCA being just shy of a megabyte in length, I wasn't particularly interested in having it load repeatedly.

The PCA looks like this
return array(
 '0221' => array(
  'BasicChrg' => 9.982, 
  'KgChrg' => 0.5405, 
  'MinChrg' => 15.3755, 
  'RemotAreaChrg' => 0, 
  'ResidChrg' => 5, 
  '0to15Chrg' => 0, 
  '15to199Chrg' => 10, 
  '200to299Chrg' => 30, 
  '300to399Chrg' => 40, 
  '400to499Chrg' => 150, 
  '500to599Chrg' => 250, 
  '600plusChrg' => 300, 
  'FuelSurchrg' => 0.07)
StackOverflow did offer a suggestion on how to deal with this but I had no joy with it. So I went with using include_once. That, however, also had problems. According to the documentation, include_once returns a boolean true when it gets called the second time for the same file. So one must use a temporary variable to hold the result rather than committing it immediately to your PCA variable.

So the code I have ended up with is (some omitted for brevity's sake):
function update_hidden($input, $field, $value, $lead_id, $form_id)
 global $TNTFreightPrices, $PostCode;

 $path = $_SERVER['DOCUMENT_ROOT'] . '/wp-content/uploads/tntfreightprices/TNTFreightPrices.php';
 $tmp = include_once $path;
 if (gettype($tmp) == "array") {
  $TNTFreightPrices = $tmp;
  $PostCode = rgpost('input_52');

 if ($form_id == 8) {
  $BasicChrg = $TNTFreightPrices[$PostCode]['BasicChrg'];

  $fid = $field['id'];
  if ($fid == 53) {
   $input = "<input id='input_8_53' class='gform_hidden' name='input_53' aria-invalid='false' value='$BasicChrg' type='hidden'>";
It remains to be seen whether I stay with $TNTFreightPrices and $PostCode in global space as that's a carryover from other experiments.

It was part fun and part hairloss but at least we're closer to a solution. Probably there are better ways. WooCommerce?

© Copyright Bruce M. Axtens., 2018

Monday, February 12, 2018

[dotnet] core, standard and framework

Riiiiiight, now I get it ... maybe.

Check the original posting on StackOverflow for the full description.

© Copyright Bruce M. Axtens, 2018

Friday, February 09, 2018

[JavaScript] String.prototype

Back in 2011, I started learning JavaScript. I'm still learning but haven't moved beyond ES3, largely because that's the dialect I'm using for most of my server-side scripting. In other words, Microsoft JScript (gasp, shock, horrors, gevalt etc.)

Most of the rest of what I do at the moment is using C#. A while back I went looking for a way to extend my C# programs with scripting and found
ClearScript. I've been using it to great effect for the last 3 years in the vast majority of my work projects. I've even written a JScript-on-steroids which exposes large chunks of C# to JScript and permits the writing of some very powerful scripts.

In the next few postings I'll be discussing some of the interesting things I've discovered. For a lot of folk, it'll be old hat ... so old that mice are living in it. But, who knows, maybe someone will find a use for some of it, or be able to adapt it to newer dialects.


String.prototype.toProperCase = function () {
  return this.replace(/\w\S*/g, function (txt) {
    return String(txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase());
I found this on StackOverflow. It attempts to proper-case (title-case) every word in a string. I don't use it often but it was an interesting find.

String.prototype.after = function (a, including) {
  including = including || false;
  a = this.indexOf(a);
  return -1 === a ? String(this) : String(this.substr(a + (including ? 0 : 1)));
A staple, this gives whatever is after a substring in a string. The substring can be included or excluded for the result.

String.prototype.before = function (a, including) {
  including = including || false;
  a = this.indexOf(a);
  return -1 === a ? String(this) : String(this.substr(0, a + (including ? 1 : 0)));
Another staple, this gives whatever is before a substring in a string. Again, the substring can be included or excluded for the result.

String.prototype.stripChars = function (chars, cnt) {
  var i,
  cnt = cnt || 0;
  var answer = this;
  for (i = 0; i < chars.length; i++) {
    var chr = chars.charAt(i);
    if (cnt === 0) {
      var pat = new RegExp(chr, "g");
      answer = answer.replace(pat, "");
    } else {
      for (j = 0; j < cnt; j++) {
        answer = answer.replace(chr, "");
  return String(answer);
I don't use this often, but it has been useful. It removes each element of chars from the string. If cnt is undefined or zero, all are removed. If cnt is 1 or more, then that many are removed.

String.prototype.between = function (begin, end, including) {
  including = including || false;
  var left = this.indexOf(begin);
  if (left < 0) {
    return String('');
  left += begin.length;
  var right = typeof end === 'undefined' ? this.length : this.indexOf(end, left);
  if (right < 0) {
    return String('');
  return including ? String(begin + this.substring(left, right) + end) : String(this.substring(left, right));
There are various ways of pulling SGML and other markups apart. This one, in various languages, has been in the toolkit for years. This variant permits excluding or including the delimiters. Apart from that, it isn't smart -- "drooling singing".between("droo","ing") gives l

String.prototype.endswith = function (str) {
  return this.indexOf(str) !== -1 && this.indexOf(str) === this.length - str.length;
Returns true if the strings ends with contents of str otherwise false. Has helped with detecting filetypes in filenames.

String.prototype.toSqlString = function () {
  return String("'" + String(this).replace(/'/g, "''") + "'");
This puts a single quote at the start and end of the string and doubles any embedded single quotes. I use this in combination with .questionMarkIs() to format SQL statements.

String.prototype.toArrayOfLines = function () {
  return this.split(/\r\n|\r|\n/g);
Splitting a text file to lines is something I do a lot of. This is the functional variant of code I have in almost every script written over the last 7 years.


String.prototype.questionMarkIs = function (val) {
  return String(this.replace("?", val));
For a while I was doing all kinds of weird things to build SQL queries. Lately I've taken to simply putting question marks in and then replacing them with the value (with or without .toSqlString()).

That should do for now. Enjoy!

© Copyright Bruce M. Axtens, 2018

Thursday, February 08, 2018

[configuration files] dhall

Okay, I know next to nothing about this at the moment but it does look interesting.
dhall is a programmable configuration language that is not Turing-complete. You can think of Dhall as: JSON + functions + types + imports
I can think of some places where this approach to config would be helpful and less dangerous that what I am currently doing.

© Copyright Bruce M. Axtens, 2018

Wednesday, February 07, 2018

[tbas] tbas basic interpreter

In my ample (NOT!) spare time, I'm helping out with a programming language project called tbas. I saw it advertised on comp.lang.basic.misc in September 2017 (yep, usenet is still going strong.)

The author is one Antonio Maschio from Italy.

You can get source, documentation and a CygWin binary from the main site. There are some examples on RosettaCode.

To give you an idea of the flavour of the language, the following is a simple CAESAR cipher implementation.

    LET MSG$ = ""
    LET OFFS = 0
    LINE INPUT "Message"; MSG$
    INPUT "Offset"; OFFS
        TARG(I) = TARG(I) + OFFS

An example of running the above

    >tbas CAESAR.BAS
    Message ? My dog's got fleas
    Offset ? 1

© Copyright Bruce M. Axtens, 2018

Thursday, July 20, 2017

[FreeDOS] The FAST and SOFA compilers

Two recent additions to the FreeDOS stable of development languages are FAST (Fast PC Compiler) and SOFA (Super Optimised Fast Assembler), inventions of one Peter Campbell of New Zealand. Peter developed FAST and SOFA in the mid 1980s and they were used as the main development languages for the Fastbase accounting system. In 2000, Peter rewrote the entire system in Tcl. All use and development of FAST and SOFA stopped at that point.

SOFA is an 8088 (and semi-80386) assembler. The syntax has some similarities to two other shareware assemblers,
A86 and CHASM. SOFA can assemble its own source-code. Its features include quick assembly time (thousands of lines per second), conditional compilation and include files.

FAST was written in SOFA. The language syntax was influenced by Basic, Pascal, C and Assembler. The binaries produced are small and fast

Peter Campbell died in tragic circumstances at Easter 2007, leaving the Fastbase business to his brother, Russell Bell.

The adding of FAST and SOFA to FreeDOS took a little too long: I had heard of the language during the 1990s and had rediscovered it in the
Vetusware abandonware collection. From there I found out about FastBase and made contact with Russell. This was 2009 and it was at that time that I suggested to Russell that SOFA/FAST could be re-released as Open Source software, thus preserving in some way Peter's legacy. Russell promptly gave permission and provided me with the sources. Embarassingly, it has taken me eight years to finalise the process.

SOFA and FAST will appear eventually on
HOPL (The Online Historical Encyclopaedia of Programming Languages). In the meantime, postings regarding the languages can be found on HOPL's Facebook front-end at SOFA and FAST respectively.

[1] Already some FreeDOS utilities have been rewritten in FAST.

© Copyright Bruce M. Axtens, 2017