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 launchable recyclable bundle
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' | 'launchable' | 'recyclable' | 'bundle'
| 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)