"""
############################################
extract palm memos from a .pdb database 
file, to simple text files, one per memo,
using filenames derived from part of the
first line of memo; run in .pdb file's dir;
memo files appear in ./dbname/00n-line1.txt,
example: ./MemoDB/255-hardware_notes_4.txt;
dbase fmt = hdr + rec info array + memos\0;
############################################
"""

import glob                                   # glob not in /usr
import struct, os
#flist = glob.glob('*.pdb')                   # skip others for now
flist = ['MemoDB.pdb']                        # addresses beamed over

for fname in flist:
    file = open(fname, 'rb')                  # open in binary mode
    bytes = file.read()
    print fname, len(bytes)

    # dbname in hdr
    eos = bytes.find(chr(0))                  # null term, upto 32 chars
    dbname = bytes[:min(32,eos)]
    print dbname
    if not os.path.exists(dbname):
        os.mkdir(dbname)
    else:
        os.system('rm %s/*' % dbname)         # make or clear output dir

    # number records in hdr
    frec = 77
    (nrec,) = struct.unpack('>H',bytes[frec-1:frec+1])        # short, big-endian
    print nrec

    # scan rec info array after hdr
    flst = 70
    for rec in range(1, nrec+1):
        # rec start offset
        floc = flst + (rec * 8)
        (rloc,) = struct.unpack('>I', bytes[floc:floc+4])      # int, or just << bytes

        # rec end offset
        fend = flst + ((rec+1) * 8)
        (rend,) = struct.unpack('>I', bytes[fend:fend+4])
        print rec, floc, rloc, rend

        try:                                                   # memos past info array
            memo = bytes[rloc:rend]                            # entire memo text
            if memo[-1] == '\x00': memo = memo[:-1]            # drop null at end

            # makeup file name from 1st line
            eolnpos = memo.find('\n')
            if eolnpos == -1: eolnpos = len(memo)              # -1 if no eoln
            linelen = min(40, eolnpos)                         # up to 40 chars
            line0 = memo[:linelen]
            if line0[-1] == '\r': line0 = line0[:-1]           # drop dos crg ret?
            line1 = ''
            for c in line0:                                    # strip invalid chars
                if (not c.isalnum()) and (c not in ['-']):     # allow dash, not colon
                    line1 += '_'
                else:
                    line1 += c
            print repr(line1)
 
            # output in text mode for eolns
            xname  = '%s/%03d-%s.txt' % (dbname, rec, line1)
            xtract = open(xname, 'w')
            xtract.write(memo)           
            xtract.close()

        except:
            import sys
            print sys.exc_type, sys.exc_value
            print 'BAD'

print 'Done'