home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 2: PC
/
frozenfish_august_1995.bin
/
bbs
/
d09xx
/
d0948.lha
/
Snoopy
/
Ini
/
ini.manual
< prev
next >
Wrap
Text File
|
1993-12-20
|
16KB
|
413 lines
ini.library
Release Version 2.0
I-WANT-TO-BE-FREE-WARE
written by Gerson Kurz
Nov.21,1993
PURPOSE
The ini.library was written to give the amiga user a more consistent
configuration file format, and programmers a much easier way of
storing config or project information on disks.
Most programs have config files to store global settings and such.
These files have all different structures people in the real world
(the users) cannot examine or understand; and, worse yet, often differ
from version to version. We all know the hassle with those 'old->new'
configuration file converters...With the ini.library this changes: you
have access to a standardized ini file format known from other
operating systems such as unix, windows and so on; it allows
you to save your config stuff much easier (less code), and it
enables the user to read and even modify configuration data with
a simple text editor (or, a wide-range field for unemployed PD
programmers: using an INI editor)
As the ini.library is I-WANT-TO-BE-FREE-WARE you are ENCOURAGED to
use it - its free of charge! (go ahead, do it!) and it offers much
more comfort to your applications. PD dealers, diskmags, everyone,
I'd like you to push'n'hype the ini.library ;-).
INI files are plain line-oriented ASCII texts that can contain three
possible types of lines : COMMENTS, HEADERS and VARIABLES. COMMENTS are
lines that include additional information not used by the parser.
You can use these comment lines to give the user ideas about what
your variables mean and what reasonable changes s(he) is allowed
to make to that variables. HEADERS are identifiers for sections and
are enclosed in [] brackets. A SECTION is a group of zero to infinite (?)
number of variables and provides a simple but efficient means of
logically grouping data. VARIABLES are simple statements in the
form "<variable>=<contents>" where both <variable> and <contents>
could be virtually anything - you name it.
Each INI file must start with a sequence of 4 characters ";INI"
otherwise the ini.library will return the INIERROR_INVALID_INI_FILE.
This was included to prevent misuse of the ini.library: imagine your
program has a 'load user configuration' menu and the user tries out
some binary hack or an IFF picture (you know users, don't you?! ;-)
If you watch out for INIERROR_INVALID_INI_FILE, you can send the user
a message of complaint and ignore its wishes -> great.
Since this is a cause for many first-time problems, from version 2.1
upwards this checking can be made optional; see ini_NewConfig() for
details
COMMENTS
Comments can be placed anywhere [well, almost]. If you want
to have a full-line comment, place a ';' or a '*' in the first
column of that line. Anything after these two characters will be ignored.
If you want to place a comment at the end of a line you should use
the ';' sign ONLY. Also note that if you make a comment after a
variable you should probably enclose its contents in quotation marks;
otherwise the whitespaces between the last character of the contents
and the comment start will be part of the contents. This is
no problem if you are using integer or boolean variables; it might
be a problem for SOME string variables, but doesn't necessarily have
to - its up to your interpretation of the input data.
Examples:
;INI for MUIMon release version
* another piece of wisdom
best part of munich=ULTRAWORLD ; 100% wild techno
SECTIONS
Sections are used to group variables logically. You should try to place
all your data in groups so that your inifiles have a more consistent
look and both you and the user can find data easier. The concept of
sections can have various usages, one is to handle logic groupings
for one program, another is to handle data related to different
programs accessing the same INI file, yet another is to just make
your INI more readable. Of course,the ini.library is flexible enough
to ignore sections altogether, but you shouldn't force it! Sections
cost you nothing and make for a lot better programs.
HEADERS
Headers start a new section. Headers are strings enclosed in
[] brackets and can be any string you like. Everything following
a header is logically assigned to that header - up to the next
section header or an end-of-file.
Examples:
[drivers]
pc0=storage:dosdrivers/pc0
cd=devs:CDROM
[Disko Lovers,International]
best ULTRAWORLD DJs=MONIKA,TIN-A-303,BLEEP & TRIPPLE R,DJ HELL
; hi to SMC all ravers around the globe. See you on MAYDAY V
[hermeneutic philosophy revisited]
zizek=no meta language exists
VARIABLES
Variables are basically strings that are assigned a name. The
names is what you search for, the strings is what you get -it is as
simple as that. For instance, in "TABS=8" the string "TABS" is
the name (also called the variable), the string "8" is its value.
The interpretation of the string value is up to you. The ini.library
provides three basic types of interpretation : Strings, Integers (LONGs)
and boolean Values (BOOLs). You can of course add your own
interpretations as you like, and this is why the ini concept is so
flexible: You can virtually store ALL information you need in such
a way that it is represented as an ASCII string. If you want your
strings to be of a certain length, you can enclose them in
brackets, for example such as in
user="T\"N\"I and THE DREAM TEAM"
where you can assign the string >T"N"I AND THE DREAM TEAM< to
the variable named >user<. Note that a sequence of \" is used
as an escape character in the above example.
If you have ideas for additional datatypes of general interest
the ini.library should understand, please contact me. If possible,
I'll include them.
Examples:
--------------------------------------------------------------
;INI
[GLOBAL]
user="T'N'I and The Dream Team" ;from INTENSE Records
tabs=8
indent=YES
autofold=FALSE
preferences=
[DIRECTORYS]
home=work:assembler/
; add multiple directorys by using '+' or ','
include=include:+dh1:more_includes/
libs=dh2:code/libs/asm/+lib:+disko:love
--------------------------------------------------------------
The above example shows you some ideas of inifiles: Two groups
are part of this inifile: GLOBAL and DIRECTORYS. Each section
can (but doesn't have to) have different variables, each variable
can be any string enclosed in quotation marks or from the = sign
to the end of the line. If you want to add comments, enclose the
string in quotes, and add a comment like in the "user=" line above.
Note that the feature described as "add multiple directorys by ..."
is a description of an add-on datatype used by the application for
this INI file and NOT provided by the ini.library itself.
Now you should be able to read inifiles. More complex features such
as section protection and file location are described in the
"programmers.guide" document which should be part of this distribution.
HINTS
If you decide to use the ini.library -WHICH I STRONGLY HOPE YOU DO-
you should always check for error returns - you may never know when
they come in handy for you.
If you save your files, make use of the grouping feature; that is,
at least provide some GLOBAL section so that the user knows what
he's up for. It makes INIfiles more readable and doesn't cost
you anything.
LIMITATIONS
Yes, there are some.
* currently no whitespaces before and after the "=" are allowed.
This means that the two following lines are different for
the ini.library parser functions
ultraworld=great
ultraworld = great
There is a simple workaround for this: just do your own variable
and contents parsing (explicit datatypes, see above). Future
versions WILL include a fix on that, I PROMISE.
* the ini.library uses approximately twice as much memory as the
ini file is in size (less for larger files). This is not a
problem for most users, because inifiles seldom grow over
a size of some 10-20 kb (even on windows I haven't seen a inifile
larger than 25kb up to this day), and many applications not even
reach a 5kb limit. (You can write a LOT variables in a 5 kb file).
However, this memory is needed only while your parser is active,
(i.e. between calls to ini_New() and ini_Delete() ). Afterwards,
only the library code (5kb) is kept in memory.
PROGRAMMING
The ini.library has a very comfortable programmers interface.
In the following paragraphs I'll tell you about the general
concepts and design questions; detailed function descriptions
should be obtained by looking at the autodocs-file ini.doc or
the autoguide(tm) file ini.guide. But lets start with some
conventions:
INTERNAL CONVENTIONS
All ini.library functions scratch ONLY the return register (d0).
ALL other registers are preserved; something most assembly
programmers will be gratefull for.
Most functions (except for very few exceptions) will return an
error code in d0 you SHOULD examine. Detailed error codes are
given in the includefiles.
BASIC IDEAS
The two most important functions are (like in C++)
ini_New() - the INI object constructor
ini_Delete() - the INI object destructor
ini_New() opens an INI file ("constructs" an INI object) and ini_Delete()
closes it ("destructs" the INI object). The INI object is represented as
the INIPARSER structure defined in the includes; you have to allocate
enough memory for it (sizeof(INIPARSER)=ip_SIZEOF). The Destructor should
be called ALWAYS, even if ini_New() failes, otherwise you'll probably loose
some memory.... Examples :
;-------------------------------------------------------------
void ReadIni( void )
{
INIPARSER parser; /* local variable */
if( ini_New( "<filename>", &parser ) == INIERROR_NONE )
{
/* examine file */
}
ini_Delete( &parser );
}
;-------------------------------------------------------------
ReadIni: lea filename(pc),a0
lea parser(pc),a1
movea.l IniBase,a6
jsr _LVOini_New(a6)
cmpi.l #INIERROR_NONE,d0
bne.b .SKIPERROR
; ...
; examine file
; ...
.SKIPERROR lea parser(pc),a0
movea.l IniBase,a6
jsr _LVOini_Delete(a6)
rts
; to keep it simple: global space for the INIPARSER
parser: ds.b ip_SIZEOF
filename: dc.b "<filename>",0
;-------------------------------------------------------------
All user functions of the ini.library require the parser as an argument,
so I guess you could call them "methods" on the INI object. The three
basic examination functions are
ini_GetString(),
ini_GetInteger() and
ini_GetBool().
A detailed description is given in the autodocs; for now lets just take
a look at ini_GetInteger. It looks something like this :
INIERROR error = ini_GetInteger( INIPARSER *parser,
STRPTR head,
STRPTR var,
LONG defaultLong,
LONG *target );
The "INIPARSER *parser" is, of course, the INI object you should know
already. "head" is the section you're looking for, and "var" is the
name of the variable. Example :
;-------------------------------------------------------------
;INI-Example
[global]
tabs=8
;-------------------------------------------------------------
Here head would be "global" and var "tabs". The (signed) Integer
"defaultLong" will be used if the var cannot be found, and "target"
is the place to write back the value. As you see, "target" will be
written to always, either the correct value or the "defaultLong" value,
so you can skip the error handling if you are satisfied with default
values in case something goes wrong. This function would be called
;-------------------------------------------------------------
long tabs;
...
ini_GetInteger( &parser, "global", "tabs", 8, &tabs )
...
;-------------------------------------------------------------
...
lea parser(pc),a0
lea head_global(pc),a1
lea var_tabs(pc),a2
moveq #8,d0
lea tabs(pc),a3
movea.l IniBase,a6
jsr _LVOini_GetInteger(a6)
...
tabs: ds.l 1
head_global: dc.b "global",0
var_tabs: dc.b "tabs",0
;-------------------------------------------------------------
EXAMINING A WHOLE SECTION
You can loop thru a section line-per-line, e.g. if you don't know the
exact structure of a section. Some example : You want to make your
menus user configurable (see examples/configmenus.c). You could create
some INI file like the following :
;-------------------------------------------------------------
;INI-file for user-configurable menus
[menus]
title=Project
item="About...",about,?
item="Load",load,L
...
title=Preferences
...
(and so on)
;-------------------------------------------------------------
Of course, your program doesn't know how exactly the "menus" section
looks like, so you have to read line-per-line. You can do this very simple:
The functino ini_GetHeader() will give you a pointer to a structure
INILINEINFO (defined in the includes). This structure is the
internal representation of lines in an INI file. All INILINEINFOs
are part of an anchored standard amiga-list (see exec/nodes), so you
can loop through them. Each INILINEINFO has a field called "ili_flags"
which contains the type of entry used. Basically, what you would do
in the above example is : find all INILINEINFOs following the section
header for "menus" up to the next section header (ili_flags = HEADER)
or the end-of-file (=end-of-list). Example:
;-------------------------------------------------------------
{
INILINEINFO *info,*header;
if( ( header = ini_GetHeader( &parser, "menus" ) ) != NULL )
{
for( info = (INILINEINFO *)header->node.ln_Succ;
info->node.ln_Succ && info->ili_type != INIFLAG_HEADER;
info = (INILINEINFO *)info->node.ln_Succ )
{
/* deal with it */
}
}
}
;-------------------------------------------------------------
...
lea parser(pc),a0
lea head_menus(pc),a1
jsr _LVOini_GetHeader(a6)
tst.l d0
beq .SKIPIT
movea.l d0,a5
move.l LN_SUCC(a5),a5
.FORLOOP
tst.l LN_SUCC(a5)
beq.b .SKIPIT
cmpi.b #INIFLAG_HEADER,ili_flags(a5)
bne.b .SKIPIT
; deal with it
movea.l LN_SUCC(a5),a5
bra.b .FORLOOP
.SKIPIT
...
head_menus: dc.b "menus",0
;-------------------------------------------------------------
AUTHOR
Send your bug reports, ideas, love letters, fresh'n'phunky vinyl to
Gerson Kurz
Karl K÷glsperger Str.7 / A303
(yes, its APPARTMENT 303, not Roland TB 303 ;-)
80939 Mⁿnchen
West Germany
This tool is dedicated to the **ULTRAWORLD** (Fuck the Sperrstunde!)
** The INI.LIBRARY is I-WANT-TO-BE-FREE-WARE **
dedicated to the global house & techno scene
written by Gerson Kurz
The ini.library may be used by and FREELY distributed with any
application be it commercial or public domain. There are no
pagan users fees, Trump-esque licenses, or other forms of rabid
capitalist trickery associated with using this library and the
example files. You do not even have to acknowledge the secret
of your superb and efficient config handling you gain by using
the ini.library. The only limitation is that you may not alter
the actual executable of the ini.library, nor sell the product and
its examples as a distinct product (i.e. represent it as such).
I don't give any guarantee for the fitness of the ini.library for
any purpose : use at own risk.
SPECIAL NOTE
Is there anybody out there who likes to write manuals ?! (I HATE IT)
I would like to get in contact with you, because I'd like to have
a better manual for this library (and some other programs of mine).