pdbc - palm database source file format
A pdbc source file is a textual representation or a Palm DataBase (PDB) or Palm Resource (PRC) file.
A PDB file has some attributes (e.g. a filename, creator and type id, ...) and zero or more data records.
A PRC file has the same attributes as a PDB file but contains resources instead of records.
The difference between a PDB and a PRC file is that in a PRC file the 'resource' flag is set.
A PDB or PRC file can have 2 special data chunks
--- the appinfo
and the sortinfo
blocks.
Each data record has some record attributes and the user data (in case of resources it has obviously resource attributes).
A pdbc source file is an ascii text file.
Keywords are lowercase, value literals are case insensitive.
The //
marks the beginning of a comment until end of line.
The /*
marks the beginning of a comment until */
.
/* */
comments cannot be nested.
The main item of a pdbc file is the file
specification.
file // file attributes begin // optional appinfo block // optional sortinfo block // zero or more record blocks end;
File attributes are of the form name = value;
.
The optional appinfo and sortinfo blocks look like this:
appinfo begin // data end;
sortinfo begin // data end;
The record blocks contain the actual user data of the PDB. Each record can contain a maximum of 64 KB.
record // record attributes begin // data end;
Record attributes are of the form name = value;
.
The resource blocks contain the actual user data of the PRC. Each resource can contain a maximum of 64 KB.
resource // resource attributes begin // data end;
Resource attributes are also of the form name = value;
.
The actual data is a stream of values. Value literals can be of various types (integer, float, double, string, char).
Integer values are interpreted in a base (default=hex) and a size (default=byte). Base and size can be changed by modifiers (bin, oct, dec, hex, base, byte, word, long, size).
String and char values can be padded to a specified length (default=0, meaning no padding). The padding can be changed by modifiers (padstring, padchar).
Double and float values are recognized by the presence of a decimal point (e.g. 0.12345 or 3.1415d or 2.71828f). The way double/float values without a trailing d/f specifier are treated can be changed by modifiers (double, float).
All modifiers have effect only inside a begin
/end
block.
Outside the begin
/end
block the old values are valid again.
Nesting begin
/end
blocks is allowed.
begin // default is: hex,byte,padstring(0),padchar(0) 11 22 // written as: 11 12 begin long 33 44 // written as: 00000033 00000044 begin dec word 55 66 // written as: 0037 0042 end // back to: hex,long,padstring(0),padchar(0) 77 88 // written as: 00000077 00000088 end // back to: hex,byte,padstring(0),padchar(0) 99 AA // written as: 99 AA end
Note: This implies that every record block starts anew with the default settings. It is (currently) not possible to change the default settings.
Note: begin
/end
blocks where introduced to make
include files safe.
It is good practice to write every data include with its
own begin
/end
and specify the settings for your include
file inside the block.
begin hex byte padstring(0) padchar(0) // my data end
You can specify a base in a suffix of the integer value. This changes only the interpretation of this value, not the current settings
begin hex byte 01 02 // hex bytes written as: 01 02 10110001_b // bin byte written as: B1 777_o // oct byte written as: FF 123_d // dec byte written as: 7B 03 04 // hex bytes written as: 03 04 end
Inside a data stream you can include a binary file as-is.
begin includebin "my_image.gif" end
This allows the inclusion of already binary data without needing to decompile the data first.
Note: This allows to include text directly as data.
begin hex byte includebin "my_text.txt" 00 // terminating byte end
No padding is done in the includebin
.
Specified as double quoted string (padded to 32 bytes).
Can be defined has a simple + | expression.
Hex short values or one of the following keywords are allowed:
resource
readonly
dirty
backup
newer
reset
nobeam
stream
hidden
If the resource
flag is set the created output will not be a PDB file but a PRC file instead.
The record
blocks are in this case resource
blocks with different attributes.
See the 'resource' section below.
Hex long value.
The date is either now
or a date time specification.
The keyword today
may be used as date specification.
DATEVALUE : year '/' month '/' day . TIMEVALUE : hour ':' min ':' sec .
Hex long value.
Can be given as a single quoted character of 4 bytes or as one hex long value or as a '{}' encapsulated list of 4 values .
Can be given as a single quoted character of 4 bytes or as one hex long value or as a '{}' encapsulated list of 4 values .
Hex long value.
Can be given as a single quoted character of 3 bytes or as one hex 3-byte value or as a '{}' encapsulated list of 3 values .
Can be defined has a simple + | expression.
Hex byte values or one of the following keywords are allowed:
secret
busy
dirty
delete
category(
decvalue)
)
If the resource
flag is set in the file attrib
then the created output
will not be a PDB file but a PRC file instead.
The record
blocks are in this case resource
blocks with different attributes.
Can be given as a single quoted character of 4 bytes or as one hex long value or as a '{}' encapsulated list of 4 values .
Is given as a decimal value.
_b
, _d
, _o
or _h
you can force the
integer to be in the specified base.
INTEGER : HEXDIGIT {HEXDIGIT} [basesuffix] . basesuffix : '_b' | '_o' | '_d' | '_h' | '_x' .
Default base/size is: hex/byte.
You can change the current base/size with the appropriate modifiers described below.
FLOAT : DIGIT { DIGIT } '.' DIGIT 'e' DIGIT { DIGIT } 'f' .
FLOAT : DIGIT { DIGIT } '.' DIGIT 'e' DIGIT { DIGIT } 'd'.
You can change this behaviour with the modifiers double
and float
described below.
STRING : '"' { ASCIICHAR } '"' .
Backslash ('\') can be used to escape special characters (\\, \a, \b, \f, \n, \r, \t, \v, \ddd) as described in printf(5).
Depending on the current string padding NULL bytes may be appended.
Default string padding is: 0 (=no padding)
You can change the string padding with the
padstring(decvalue)
modifier described below.
CHAR : "'" { ASCIICHAR } "'" .
Other than in many other languages the character literal can be longer than 1 byte (actually as long as you want - where some languages allow only up to 4 byte characters). The only difference between a double quoted ``string'' and a single quoted 'character' is that the 'character' does not terminate with a NULL byte.
Depending on the current character padding NULL bytes may be appended.
Default character padding is: 0 (no padding)
You can change the character padding with the
padchar(decvalue)
modifier described below.
Only 1, 2 and 4 are valid values.
If the string literal is smaller than decvalue, then NULL bytes are written to the right of the string until decvalue bytes are written.
If the string literal is bigger than decvalue, then no padding happens but a warning is given (see -W option).
If the current string padding is 0 (zero), then no padding happens and no warning is given (default).
The padding includes the zero byte at the end of the ``string''.
If the character literal is smaller than decvalue, then NULL bytes are written to the right of the string until decvalue bytes are written.
If the character literal is bigger than decvalue, then no padding happens but a warning is given (see -W option).
If the current character padding is 0 (zero), then no padding happens and no warning is given (default).
Operators are similar to C/C++ and are here listed in order of increasing precedence: ? : conditional expr (expr ? true_expr : false_expr) | bitwise or ^ bitwise xor & bitwise and == != equal/unequal < <= > >= /less/less or equal/greater/greater or equal/ << >> shift left/right + - addition/subtraction * / % multiplication/division/module ! ~ - + logical not/binary not/unary minus/unary plus () nested expression
file : 'file' { file_attr } file_body ';' . file_body : 'begin' { chunk } 'end' . chunk : appinfo | sortinfo | record | resource. appinfo : 'appinfo' block ';' . sortinfo : 'sortinfo' block ';' . record : 'record' { record_attr } block ';' . resource : 'resource' { resource_attr } block ';' . block : 'begin' { expr_value | modifier | block | value } 'end' . file_attr : 'filename' '=' STRING ';' | 'attrib' '=' file_attr_value ';' | 'version' '=' HEXVALUE ';' | 'creation_date' '=' datetime ';' | 'modification_date' '=' datetime ';' | 'backup_date' '=' datetime ';' | 'modification' '=' HEXVALUE ';' | 'typeid' '=' file_id ';' | 'creatorid' '=' file_id ';' | 'uniqueid_seed' '=' HEXVALUE ';' . file_attr_value : file_attr_flag { ( '+' | '|' ) file_attr_flag } . file_attr_flag : 'resource' | 'readonly' | 'dirty' | 'backup' | 'newer' | 'reset' | 'nobeam' | 'stream' | 'hidden' | HEXVALUE . datetime : 'now' | 'today' [ TIMEVALUE ] | DATEVALUE [ TIMEVALUE ] | HEXVALUE . file_id : CHAR | HEXVALUE | '{' HEXVALUE HEXVALUE HEXVALUE HEXVALUE '}' . record_attr : 'attrib' '=' rec_attr_value ';' | 'recordid' '=' rec_id ';' . rec_attr_value : rec_attr_flag { ( '+' | '|' ) rec_attr_flag } . rec_attr_flag : 'secret' | 'busy' | 'dirty' | 'delete' | 'category' '(' DECVALUE ')' | HEXVALUE . rec_id : CHAR | HEXVALUE | '{' HEXVALUE HEXVALUE HEXVALUE '}' . resource_attr : 'typeid' '=' type_id ';' | 'id' '=' DECVALUE ';' . type_id : CHAR | HEXVALUE | '{' HEXVALUE HEXVALUE HEXVALUE HEXVALUE '}' . expr_value : '(' expr ')' . expr : condex . condex : orex | orex '?' condex ':' condex . orex : xorex | orex '|' xorex . xorex : andex | xorex '^' andex . andex : eqex | andex '&' eqex . eqex : relex | eqex '==' relex | eqex '!=' relex . relex : shiftex | relex '<' shiftex | relex '<=' shiftex | relex '>' shiftex | relex '>=' shiftex . shiftex : arith | shiftex '<<' arith | shiftex '>>' arith . arith : term | arith '+' term | arith '-' term . term : factor | term '*' factor | term '/' factor | term '%' factor . factor : prim | '!' factor | '~' factor | '-' prim | '+' prim . prim : value | nested . nested : '(' expr ')' . value : BINVALUE | OCTVALUE | DECVALUE | HEXVALUE | REAL | FLOAT | DOUBLE | STRING | CHAR . modifier : base | size | pad | double_float . base : 'hex' | 'dec' | 'oct' | 'bin' | 'base' '(' DECVALUE ')' . size : 'byte' | 'word' | 'long' | 'size' '(' DECVALUE ')' . pad : 'padstring' '(' DECVALUE ')' | 'padchar' '(' DECVALUE ')' . double_float : 'double' | 'float' .The EBNF syntax also exists as a HTML version.
file filename = "mydatabase"; creatorid = 'ABCD'; typeid = 'PQRS'; attrib = readonly | nobeam; creation_date = today 01:00:00; begin
appinfo begin end;
sortinfo begin end;
record begin 01 02 03 04 // written as: 01 02 03 04 end;
record begin bin 10100001 00001111 // written as: A1 0F dec word 1234 5678 0 // written as: 04 D2 16 2E 00 00 oct long 111 2 // written as: 00 00 00 49 00 00 00 02 end;
record begin "ABC" // written as: 41 42 43 00 'A' 'B' 'C' 'D' // written as: 41 42 43 44 'ABCD' // written as: 41 42 43 44 end;
record begin padstring(6) padchar(4) "ABC" // written as: 41 42 43 00 00 00 'AB' // written as: 41 42 00 00 end;
record begin hex byte 01 02 FE FF begin // begin new scope dec word 1234 5678 end // restore old scope 03 04 FC FD // again in hex byte mode end;
include "more_records.pdbh"
record begin includebin "image.gif" end;
record begin includebin "some_text.txt" 00 end;
end;
file filename = "mydatabase"; creatorid = 'ABCD'; typeid = 'PQRS'; attrib = resource | readonly | nobeam; begin
resource typeid = 'menu'; id = 1001; begin includebin "some_precompiled_data.menu" end;
end;
Eric Obermuhlner (eric@obermuhlner.com)