PDB conversion for Expense

This code converts the built-in Expense database into Lua format. The implementation is totally undocumented, I'm afraid.

<*>=
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#include "pushchar.h"
#include "pdblua.h"
#include "pdbio.h"
#include "pdbrep.h"
#include "pdbconv.h"

#include "pi-expense.h"

<functions>

<functions>= (<-U) [D->]
char * ExpenseCurrencyNames[] = {
  "Australia", "Austria", "Belgium", "Brazil", "Canada", "Denmark", "Finland",
  "France", "Germany", "Hong Kong", "Iceland", "Ireland", "Italy", "Japan", 
  "Luxembourg", "Mexico", "Netherlands", "New Zealand", "Norway", "Spain",
  "Sweden", "Switzerland", "United Kingdom", "United States", "None", (char *)0
};

static char *weekdayNames[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
Defines ExpenseCurrencyNames, weekdayNames (links are to index).

P11. An application info structure is intended to be stored in the database's app info block and to contain data relevant to the database.

<functions>+= (<-U) [<-D->]
static struct ExpenseAppInfo readexpinfo(Text*);
static void dumpexpinfo(FILE *out, struct pdb *db, Text txt) {
  struct ExpenseAppInfo tai = readexpinfo(&txt);
  int i;

  fprintf(out,   "\n    {");
  fprintf(out,   "\n      categories = ");
  unpack_categories(out, (struct PDBCategoryAppInfo *)&tai.category, 1);
  fprintf(out,  ",\n      sortOrder = %d, sortOrderName = \"%s\",", 
                          tai.sortOrder, ExpenseSortNames[tai.sortOrder]);
  fprintf(out,   "\n      customCurrencies = ");
  /*#define QUOTE(_) ((_) ? "\"" : ""), ((_) ? _ : "nil"), ((_) ? "\"" : "")*/
  for (i = 0; i < sizeof(tai.currencies)/sizeof(tai.currencies[0]); i++)
    fprintf(out, "\n        %s { name = %s, symbol = %s, rate = %s }",
           i == 0 ? "{" : ",", QUOTE(tai.currencies[i].name),
           QUOTE(tai.currencies[i].symbol), QUOTE(tai.currencies[i].rate));
  fprintf(out,   "\n        }");
  fprintf(out,   "\n    }");
}
Defines dumpexpinfo (links are to index).

<functions>+= (<-U) [<-D->]
static struct ExpenseAppInfo readexpinfo(Text *t) {
  struct ExpenseAppInfo tai;
  int rc;
  rc = unpack_ExpenseAppInfo (&tai, t->p, t->len);
  assert(rc == t->len);
  return tai;
}
Defines readexpinfo (links are to index).

<export i to Lua, offset by 1>=
(lua_pushnumber((double)(i+1)), lua_setglobal("i"));

<functions>+= (<-U) [<-D->]
static struct Expense expread(Text *t, int recnum) {
  struct Expense rec;
  int len;
  len = unpack_Expense(&rec, t->p, t->len);
  if (len < chars_remaining(t))
    fprintf(stderr, "Warning: %d unused bytes in record %d\n",
            chars_remaining(t) - len, recnum);
  t->p += len;
  return rec;
}
Defines expread (links are to index).

<functions>+= (<-U) [<-D->]

<functions>+= (<-U) [<-D->]
static void dumpexpr(FILE *out, struct pdb *db, int i);
static struct Expense expread(Text *t, int recnum);

#define BIT(x) ((x) ? "1" : "nil")
static void dumpexpr(FILE *out, struct pdb *db, int recnum) {
  Record *r = db->records + recnum;
  struct Expense t;
  struct ExpenseAppInfo tai;

  unpack_Expense(&t, r->data.p, r->data.len);
  unpack_ExpenseAppInfo(&tai, db->info.appInfo.p, db->info.appInfo.len);

  fprintf(out, "{");
  fprintf(out, "\n        category = \"%s\",", 
         tai.category.name[db->records[recnum].category]);
  fprintf(out, "\n        typeNum = %d, paymentNum = %d, currencyNum = %d,",
         t.type, t.payment, t.currency);
  fprintf(out, "\n        type = \"%s\", payment = \"%s\", currency = \"%s\",",
         ExpenseTypeNames[t.type], ExpensePaymentNames[t.payment],
         ExpenseCurrencyNames[t.currency]);
  fprintf(out, "\n        amount = %s, vendor = %s, city = %s,",
         QUOTE(t.amount), QUOTE(t.vendor), QUOTE(t.city));
  fprintf(out, "\n        attendees = %s, note = %s, ",
         QUOTE(t.attendees), QUOTE(t.note));
  fprintf(out, "\n        date = { month = %d, day = %d, year = %d, weekday = \"%s\",",
         t.date.tm_mon+1, t.date.tm_mday, 1900+t.date.tm_year, 
         weekdayNames[t.date.tm_wday]);
  fprintf(out, "\n                 hour = %d, min = %d, sec = %d }",
         t.date.tm_hour, t.date.tm_min, t.date.tm_sec);
  fprintf(out, "\n      }");
}
Defines BIT, dumpexpr (links are to index).

<functions>+= (<-U) [<-D]
static char *trailers[] = {
  0
};

struct PDBConv expense = {
  "Expense database",
  "DATA", "exps",
  { 0, dumpexpinfo, 0 },
  { 0, generic_unpackInfo, generic_packInfo },
  { 0, dumpexpr, 0 }, 
  trailers
};
Defines expense, trailers (links are to index).