Created 0.2.4 branch for release preparations
This commit is contained in:
1503
libburn/branches/ZeroFourTwo/libcevap/cgen.c
Normal file
1503
libburn/branches/ZeroFourTwo/libcevap/cgen.c
Normal file
File diff suppressed because it is too large
Load Diff
35
libburn/branches/ZeroFourTwo/libcevap/cgen.h
Normal file
35
libburn/branches/ZeroFourTwo/libcevap/cgen.h
Normal file
@ -0,0 +1,35 @@
|
||||
|
||||
#ifndef Cgen_includeD
|
||||
#define Cgen_includeD Yes
|
||||
|
||||
|
||||
|
||||
struct CgeN {
|
||||
|
||||
char *classname;
|
||||
char *structname;
|
||||
char *functname;
|
||||
|
||||
int is_managed_list;
|
||||
int is_bossless_list;
|
||||
int gen_for_stic; /* 0=no smem,srgex,sfile , 1=all three, 2=smem only */
|
||||
int make_ansi;
|
||||
int make_lowercase;
|
||||
char global_include_file[4096];
|
||||
FILE *global_include_fp;
|
||||
|
||||
struct CtyP *elements;
|
||||
struct CtyP *last_element;
|
||||
|
||||
int may_overwrite;
|
||||
FILE *fp;
|
||||
char filename[4096];
|
||||
FILE *ptt_fp;
|
||||
char ptt_filename[4096];
|
||||
|
||||
char msg[8192];
|
||||
};
|
||||
|
||||
|
||||
#endif /* Cgen_includeD */
|
||||
|
222
libburn/branches/ZeroFourTwo/libcevap/cgen.txt
Normal file
222
libburn/branches/ZeroFourTwo/libcevap/cgen.txt
Normal file
@ -0,0 +1,222 @@
|
||||
|
||||
|
||||
Description of the helper program stic*/bin/cgen
|
||||
|
||||
cgen is copyright 2001 to 2007, Thomas Schmitt <stic-source@gmx.net>
|
||||
and provided under BSD license.
|
||||
|
||||
Compilation:
|
||||
cc -g -o cgen cgen.c ctyp.c smem.c
|
||||
|
||||
|
||||
cgen produces a class stub in C programming language. The data structure of
|
||||
the class is described by some lines which get read from stdin. The stub will
|
||||
consist of four files which emerge in the current working directory:
|
||||
<classname>.h public header file of the class
|
||||
<classname>.c automatically generated C code of the class
|
||||
plus a copy of <classname>.c.methods
|
||||
<classname>_private.h private header file of the class
|
||||
<classname>.c.methods safe storage for manually created functions.
|
||||
From here they get copied into the generated stub.
|
||||
If such a file is missing, a dummy gets created.
|
||||
It will define a struct <ClassnamE> for representing the class data aspects,
|
||||
construtor <Classname>_new(), destructor <Classname>_destroy(),
|
||||
getter <Classname>_<element>_get() for each structure element.
|
||||
Some more functions get added for particular class and element roles.
|
||||
|
||||
cgen normally refuses to overwrite existing files because it supposes that
|
||||
those contain code added by the human programmer.
|
||||
Human programmer enhancements may be explanatory comments, class specific
|
||||
methods, initial element values and other special precautions within the
|
||||
generated functions.
|
||||
As long as the modelling phase is going on, one may store such human code
|
||||
in <classname>.c.methods and may use command line option -overwrite for
|
||||
modelling development cycles.
|
||||
|
||||
At some point of model matureness one may decide to give up cgen and the
|
||||
.c.method files and to go on only with _private.h , .h and .c files.
|
||||
|
||||
|
||||
Command line options
|
||||
|
||||
-no_stic prevents usage of stic_dir/s_tools/*.[ch]
|
||||
|
||||
-ansi generates ANSI C function heads and makes file <classname>.h hold
|
||||
only public definitions: an opaque declaration of the class struct
|
||||
and a list of function prototypes. The definiton of the class
|
||||
struct is then in <classname>_private.h .
|
||||
-global_include filename
|
||||
sets the name of a file which will contain globally necessary
|
||||
declarations. Currently it lists the existence of all class
|
||||
structs.
|
||||
-lowercase generate struct <classname> rather than struct <ClassnamE> and
|
||||
function names <classname>_func() rather than <Classname>_func() .
|
||||
-overwrite allows to overwrite files <classname>_private.h, <classname>.h
|
||||
and <classname>.c, but not <classname>.c.methods.
|
||||
|
||||
|
||||
Input line format:
|
||||
|
||||
There are two states of input: class level and element level.
|
||||
Exampes are shown below with class roles and element roles.
|
||||
|
||||
Input starts at class level. A class level line may be one of
|
||||
|
||||
- Comment. A line which begins with '#' is ignored on class level.
|
||||
|
||||
- Empty. A line with no characters is a comment with empty text (i.e. ignored).
|
||||
|
||||
- Class. Options which begin with '-' and finally a word in lowercase letters
|
||||
which defines the <classname>. The classname leads to a struct ClassnamE
|
||||
and some class methods implemented as C functions <Classnname>_<func>().
|
||||
|
||||
- End of input. Line "@@@" or EOF at stdin end the program run.
|
||||
|
||||
After a class line, input switches to element level where a line may be:
|
||||
|
||||
- Comment. A line which after some white space begins with '#' is considered
|
||||
a comment. The preceeding white space is ignored and the text after '#' is
|
||||
eventuellay trimmed by a single blank at both ends. This text will be part
|
||||
of the class struct definition within file <classname_private>.h as a single
|
||||
C comment line /* ... */. The sequence of elements and comments is preserved.
|
||||
An empty comment text leads to an empty line in <classname_private>.h.
|
||||
|
||||
- Empty. A line with no characters is a comment with empty text.
|
||||
|
||||
- Element. Options which begin with '-', eventual C keywords "unsigned" or
|
||||
"volatile", type or "struct <NamE>", element name. This leads to a struct
|
||||
element which is taken into respect in some class methods. Depending on the
|
||||
options in this line, some element methods <Classnname>_<func>_<element>()
|
||||
may get generated.
|
||||
|
||||
- End of class. A single '@' marks the end of the element list and brings
|
||||
input back to class level. I.e. next is expected another class name or
|
||||
"@@@" or EOF at stdin.
|
||||
|
||||
Input semantics:
|
||||
|
||||
A class can have one of two roles:
|
||||
|
||||
- Standalone class.
|
||||
Input example:
|
||||
my_class
|
||||
|
||||
- Listable class, which has pointers to peer instances: .prev and .next
|
||||
Such classes get a list destructor <Classname>_destroy_all() which destroys
|
||||
all members of a list (which is given by any of the list members).
|
||||
Such a class should have a pointer *boss as first element in which case
|
||||
the constructor will look like
|
||||
<Classname>_new(struct <ClassnamE> **o,struct <Some_clasS> *boss,int flag);
|
||||
There is a function <Classname>_link() which inserts an instance into a list
|
||||
and a function <Classname>_count() which tells the number of list members.
|
||||
For pseudo random access there is function <Classname>_by_idx().
|
||||
Input example:
|
||||
-l my_class
|
||||
|
||||
|
||||
A modifier is defined for classes:
|
||||
|
||||
- Bossless. Disables a special boss-subordinate relationship which is created
|
||||
if the first element of a class is a struct pointer with the name "boss".
|
||||
Like
|
||||
-l <classname>
|
||||
-v struct Some_clasS *boss
|
||||
Normally such a parameter *boss becomes part of the constructor method
|
||||
<Classname>_new(struct <ClassnamE> **o, struct Some_clasS *boss, int flag);
|
||||
This relationship is typical for a listable class and a single class which
|
||||
is designed to host instances of that listable class. Therefore one gets a
|
||||
warning if a listable class does not begin with a struct pointer *boss.
|
||||
But if -b is given, then CgeN ill not include a parameter *boss into the
|
||||
constructor. It will rather look normal:
|
||||
<Classname>_new(struct <ClassnamE> **o, int flag);
|
||||
It will not warn if the first element of a listable class is not struct
|
||||
pointer *boss.
|
||||
|
||||
|
||||
Elements have one of the following roles:
|
||||
|
||||
- Value. It provides only storage for a C data type (which may be a C pointer
|
||||
despite the role name "value"), a getter method <Classname>_<element>_get(),
|
||||
and a setter method <Classname>_<element>_set().
|
||||
Input examples:
|
||||
-v int i
|
||||
-v int a[100]
|
||||
-v char *cpt
|
||||
-v struct xyz x
|
||||
-v struct xyz *xpt
|
||||
|
||||
- Managed. This has to be a pointer to a struct <XyZ> or to char. It will not
|
||||
get attached to an object by the stub's code but its destructor
|
||||
<Xyz>_destroy() will be called by <Classname>_destruct(). In case of (char *)
|
||||
it is supposed that a non-NULL value has been allocated by malloc().
|
||||
Managed (char *) types get a setter function <Classname>_<element>_set()
|
||||
which allocates memory and copies the textstring from its parameter.
|
||||
Input examples:
|
||||
-m struct XyZ *xyzpt
|
||||
-m char *textstring
|
||||
|
||||
- Chainlink. A pair of prev-next-style pointers to the own class struct.
|
||||
Function <Classname>_destruct() will unlink the affected instance and
|
||||
put together its link partners.
|
||||
Input example (there must always be two consequtive -c lines):
|
||||
-c struct My_clasS *up
|
||||
-c struct My_clasS *down
|
||||
|
||||
- List. A pair of pointers to the struct <XyZ> of a listable class. The first
|
||||
one <ls> holds the start of the list, the second one <eol> holds the end.
|
||||
The getter function has an additional argument idx:
|
||||
<Classname>_get_<ls>(struct <ClassnamE> *o, int idx, struct <XyZ> **pt,
|
||||
int flag)
|
||||
idx == 0 is the start of the list, idx=1 the next element, ...
|
||||
idx == -1 retrieves the last element of the list.
|
||||
For insertion of list items there is provided method <Classname>_new_<ls>().
|
||||
The inserted item is reachable via the getter function with idx == -1
|
||||
<Classname>_destroy() instance calls <Xyz>_destroy_all(). Note that the end
|
||||
pointer is always generated as private element (-p).
|
||||
Input example (there must always be a -l and a -v line):
|
||||
-l struct XyZ *list_start
|
||||
-v struct XyZ *list_end
|
||||
|
||||
The availability of getter method <Classname>_get_<element>(), and setter
|
||||
method <Classname>_set_<element>_set() can be controled by two modifiers:
|
||||
|
||||
- Readonly. Only a getter method.
|
||||
Input example
|
||||
-r -v int broadcasted_status
|
||||
|
||||
- Private. Neither getter nor setter method.
|
||||
Input example
|
||||
-p -v int private_value
|
||||
|
||||
- Bossless listable. This marks elements which are listable objects but do not
|
||||
expect a boss pointer in their constructor. See above: Listable class and
|
||||
the bossless modifier for classes.
|
||||
Input example
|
||||
-b -l struct XyZ *list
|
||||
-v struct XyZ *last_in_list
|
||||
|
||||
- Initialization free. The class constructor will not initialize this element.
|
||||
This modifier has to be used if neither NULL nor 0 are suitable
|
||||
initialization values.
|
||||
|
||||
Example run:
|
||||
|
||||
rm class_x.c class_x.h class_y.c class_y.h
|
||||
bin/cgen <<+
|
||||
-l class_x
|
||||
-r -v struct Boss_clasS *boss
|
||||
-v int x
|
||||
-r -v struct stat stbuf
|
||||
-m struct Class_Y *y
|
||||
-m char *text
|
||||
-c struct Class_X *master
|
||||
-c struct Class_X *slave
|
||||
-b -l struct Class_X *provider
|
||||
-p -v struct Class_X *last_provider
|
||||
@
|
||||
-b -l class_y
|
||||
-r -v char providername[80]
|
||||
@
|
||||
+
|
||||
|
||||
|
364
libburn/branches/ZeroFourTwo/libcevap/ctyp.c
Normal file
364
libburn/branches/ZeroFourTwo/libcevap/ctyp.c
Normal file
@ -0,0 +1,364 @@
|
||||
|
||||
/*
|
||||
cc -g -o ctyp.c
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "smem.h"
|
||||
extern char *Sfile_fgets();
|
||||
extern int Sregex_string();
|
||||
extern int Sregex_trimline();
|
||||
|
||||
#include "ctyp.h"
|
||||
|
||||
|
||||
/* -------------------------- CtyP ----------------------- */
|
||||
|
||||
|
||||
int Ctyp_new(objpt,link,flag)
|
||||
struct CtyP **objpt;
|
||||
struct CtyP *link;
|
||||
int flag;
|
||||
{
|
||||
struct CtyP *o;
|
||||
int ret;
|
||||
|
||||
*objpt= o= TSOB_FELD(struct CtyP,1);
|
||||
if(o==NULL)
|
||||
return(-1);
|
||||
|
||||
o->is_comment= 0;
|
||||
o->is_pointer= 0;
|
||||
o->is_struct= 0;
|
||||
o->is_unsigned= 0;
|
||||
o->is_volatile= 0;
|
||||
o->array_size= 0;
|
||||
o->management= 0;
|
||||
o->with_getter= 1;
|
||||
o->with_setter= 1;
|
||||
o->bossless_list= 0;
|
||||
o->no_initializer= 0;
|
||||
o->dtype= NULL;
|
||||
o->name= NULL;
|
||||
o->prev= NULL;
|
||||
o->next= NULL;
|
||||
|
||||
if(link!=NULL)
|
||||
link->next= o;
|
||||
o->prev= link;
|
||||
|
||||
return(1);
|
||||
failed:;
|
||||
Ctyp_destroy(objpt,0);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
|
||||
int Ctyp_destroy(objpt,flag)
|
||||
struct CtyP **objpt;
|
||||
int flag;
|
||||
{
|
||||
struct CtyP *o;
|
||||
|
||||
o= *objpt;
|
||||
if(o==NULL)
|
||||
return(0);
|
||||
|
||||
if(o->prev!=NULL)
|
||||
o->prev->next= o->next;
|
||||
if(o->next!=NULL)
|
||||
o->next->prev= o->prev;
|
||||
Sregex_string(&(o->dtype),NULL,0);
|
||||
Sregex_string(&(o->name),NULL,0);
|
||||
|
||||
free((char *) o);
|
||||
*objpt= NULL;
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
int Ctyp_get_pointer_level(ct,flag)
|
||||
struct CtyP *ct;
|
||||
int flag;
|
||||
{
|
||||
return(ct->is_pointer);
|
||||
}
|
||||
|
||||
|
||||
int Ctyp_is_struct(ct,flag)
|
||||
struct CtyP *ct;
|
||||
int flag;
|
||||
{
|
||||
return(ct->is_struct);
|
||||
}
|
||||
|
||||
|
||||
int Ctyp_get_array_size(ct,flag)
|
||||
struct CtyP *ct;
|
||||
int flag;
|
||||
{
|
||||
return(ct->array_size);
|
||||
}
|
||||
|
||||
|
||||
int Ctyp_get_management(ct,flag)
|
||||
struct CtyP *ct;
|
||||
int flag;
|
||||
{
|
||||
return(ct->management);
|
||||
}
|
||||
|
||||
|
||||
int Ctyp_get_with_getter(ct,flag)
|
||||
struct CtyP *ct;
|
||||
int flag;
|
||||
{
|
||||
return(ct->with_getter);
|
||||
}
|
||||
|
||||
|
||||
int Ctyp_get_with_setter(ct,flag)
|
||||
struct CtyP *ct;
|
||||
int flag;
|
||||
{
|
||||
return(ct->with_setter);
|
||||
}
|
||||
|
||||
|
||||
int Ctyp_get_dtype(ct,text,flag)
|
||||
struct CtyP *ct;
|
||||
char **text; /* must point to NULL of freeable memory */
|
||||
int flag;
|
||||
/*
|
||||
bit0=eventually prepend "struct "
|
||||
*/
|
||||
{
|
||||
if((flag&1) && ct->is_struct) {
|
||||
if(Sregex_string(text,"struct ",0)<=0)
|
||||
return(-1);
|
||||
} else {
|
||||
if(Sregex_string(text,"",0)<=0)
|
||||
return(-1);
|
||||
}
|
||||
if(Sregex_string(text,ct->dtype,1)<=0)
|
||||
return(-1);
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
int Ctyp_get_name(ct,text,flag)
|
||||
struct CtyP *ct;
|
||||
char **text; /* must point to NULL of freeable memory */
|
||||
int flag;
|
||||
{
|
||||
if(Sregex_string(text,ct->name,0)<=0)
|
||||
return(-1);
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
int Ctyp_get_type_mod(ct,is_spointer,is_struct,array_size,flag)
|
||||
struct CtyP *ct;
|
||||
int *is_spointer,*is_struct,*array_size;
|
||||
int flag;
|
||||
{
|
||||
*is_spointer= ct->is_pointer;
|
||||
*is_struct= ct->is_struct;
|
||||
*array_size= ct->array_size;
|
||||
}
|
||||
|
||||
int Ctyp_new_from_line(ct,link,line,msg,flag)
|
||||
struct CtyP **ct;
|
||||
struct CtyP *link;
|
||||
char *line;
|
||||
char *msg;
|
||||
int flag;
|
||||
/*
|
||||
bit0= make struct ClassnamE to struct classname
|
||||
*/
|
||||
{
|
||||
struct CtyP *o;
|
||||
char *cpt,*bpt;
|
||||
int ret,l;
|
||||
char orig_line[4096];
|
||||
|
||||
ret= Ctyp_new(ct,*ct,0);
|
||||
if(ret<=0) {
|
||||
sprintf(msg,"Failed to create CtyP object (due to lack of memory ?)");
|
||||
goto ex;
|
||||
}
|
||||
o= *ct;
|
||||
|
||||
strcpy(orig_line,line);
|
||||
cpt= line;
|
||||
while(*cpt!=0 && isspace(*cpt)) cpt++;
|
||||
if(cpt[0]=='#') {
|
||||
cpt++;
|
||||
if(cpt[1]==' ')
|
||||
cpt++;
|
||||
l= strlen(cpt);
|
||||
if(cpt[0]==' ')
|
||||
cpt++;
|
||||
if(l>1)
|
||||
if(cpt[l-1]==' ')
|
||||
cpt[l-1]= 0;
|
||||
if(Sregex_string(&(o->name),cpt,0)<=0)
|
||||
{ret= -1; goto ex;}
|
||||
o->is_comment= 1;
|
||||
{ret= 1; goto ex;}
|
||||
} else if(cpt[0]==0) {
|
||||
if(Sregex_string(&(o->name),cpt,0)<=0)
|
||||
{ret= -1; goto ex;}
|
||||
o->is_comment= 1;
|
||||
{ret= 1; goto ex;}
|
||||
} else if(cpt[0]=='/' && cpt[1]=='*') {
|
||||
sprintf(msg,
|
||||
"C-style multi line comments (/* ... */) not supported yet. Use #.");
|
||||
goto ex;
|
||||
|
||||
/* >>> */
|
||||
|
||||
}
|
||||
cpt= line;
|
||||
while(cpt[0]=='-') {
|
||||
/* look for management specifiers:
|
||||
-v* just a value
|
||||
-m* allocated memory which needs to be freed
|
||||
-c* mutual link (like prev+next)
|
||||
-l* list of -m chained by mutual links prev and next
|
||||
|
||||
-r* read-only : no setter function
|
||||
-p* private : neither setter nor getter function
|
||||
-b* bossless_list : Class_new(o,flag), not Class_new(o,boss,flag)
|
||||
-i* no_initializer : do not initialize element in <Class>_new()
|
||||
#... line is a comment
|
||||
*/
|
||||
if(cpt[1]=='v' || cpt[1]=='V') {
|
||||
o->management= 0;
|
||||
} else if(cpt[1]=='m' || cpt[1]=='M') {
|
||||
o->management= 1;
|
||||
} else if(cpt[1]=='c' || cpt[1]=='C') {
|
||||
o->management= 2;
|
||||
if(o->prev!=NULL)
|
||||
if(o->prev->management==2)
|
||||
o->management= 3;
|
||||
} else if(cpt[1]=='l' || cpt[1]=='L') {
|
||||
o->management= 4;
|
||||
} else if(cpt[1]=='r' || cpt[1]=='R') {
|
||||
o->with_setter= 0;
|
||||
} else if(cpt[1]=='p' || cpt[1]=='P') {
|
||||
o->with_setter= 0;
|
||||
o->with_getter= 0;
|
||||
} else if(cpt[1]=='b' || cpt[1]=='B') {
|
||||
o->bossless_list= 1;
|
||||
} else if(cpt[1]=='i' || cpt[1]=='I') {
|
||||
o->no_initializer= 1;
|
||||
}
|
||||
while(*cpt!=0 && !isspace(*cpt)) cpt++;
|
||||
while(*cpt!=0 && isspace(*cpt)) cpt++;
|
||||
if(*cpt==0)
|
||||
goto no_name;
|
||||
}
|
||||
|
||||
if(strncmp(cpt,"struct ",7)==0) {
|
||||
o->is_struct= 1;
|
||||
cpt+= 7;
|
||||
} else if(strncmp(cpt,"unsigned ",9)==0) {
|
||||
o->is_unsigned= 1;
|
||||
cpt+= 9;
|
||||
} else if(strncmp(cpt,"volatile ",9)==0) {
|
||||
o->is_volatile= 1;
|
||||
cpt+= 9;
|
||||
if(strncmp(cpt,"unsigned ",9)==0) {
|
||||
o->is_unsigned= 1;
|
||||
cpt+= 9;
|
||||
}
|
||||
}
|
||||
if(*cpt==0)
|
||||
goto no_name;
|
||||
while(*cpt!=0 && isspace(*cpt)) cpt++;
|
||||
bpt= cpt;
|
||||
while(*bpt!=0 && !isspace(*bpt)) bpt++;
|
||||
if(*bpt==0)
|
||||
goto no_name;
|
||||
if(*bpt==0) {
|
||||
no_name:;
|
||||
sprintf(msg,"No name found after type description : %s",orig_line);
|
||||
ret= 0; goto ex;
|
||||
}
|
||||
*bpt= 0;
|
||||
if(Sregex_string(&(o->dtype),cpt,0)<=0)
|
||||
{ret= -1; goto ex;}
|
||||
if((flag&1) && o->is_struct && strlen(o->dtype)>=3)
|
||||
if(isupper(o->dtype[0]) && islower(o->dtype[1]) &&
|
||||
isupper(o->dtype[strlen(o->dtype)-1])) {
|
||||
o->dtype[0]= tolower(o->dtype[0]);
|
||||
o->dtype[strlen(o->dtype)-1]= tolower(o->dtype[strlen(o->dtype)-1]);
|
||||
}
|
||||
cpt= bpt+1;
|
||||
while(*cpt!=0 && isspace(*cpt)) cpt++;
|
||||
if(*cpt==0)
|
||||
goto no_name;
|
||||
for(;*cpt=='*';cpt++)
|
||||
o->is_pointer++;
|
||||
if(*cpt==0)
|
||||
goto no_name;
|
||||
bpt= strchr(cpt,'[');
|
||||
if(bpt!=NULL) {
|
||||
if(strchr(bpt,']')!=NULL)
|
||||
*strchr(bpt,']')= 0;
|
||||
sscanf(bpt+1,"%lu",&(o->array_size));
|
||||
*bpt= 0;
|
||||
}
|
||||
if(Sregex_string(&(o->name),cpt,0)<=0)
|
||||
{ret= -1; goto ex;}
|
||||
if(o->management==1) {
|
||||
if((!(o->is_pointer>=1 && o->is_pointer<=2)) ||
|
||||
((!o->is_struct) && strcmp(o->dtype,"char")!=0 &&
|
||||
(strcmp(o->dtype,"unsigned char")!=0))) {
|
||||
sprintf(msg,"-m can only be applied to pointers of struct or char : %s",
|
||||
orig_line);
|
||||
ret= 0; goto ex;
|
||||
}
|
||||
}
|
||||
ret= 1;
|
||||
ex:;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
int Ctyp_read_fp(ct,fp,msg,flag)
|
||||
struct CtyP **ct;
|
||||
FILE *fp;
|
||||
char msg[]; /* at least [4096+256] */
|
||||
int flag;
|
||||
/*
|
||||
bit0= make struct ClassnamE to struct classname
|
||||
*/
|
||||
{
|
||||
int ret;
|
||||
char line[4096];
|
||||
struct CtyP *o;
|
||||
|
||||
line[0]= 0;
|
||||
printf(
|
||||
"[-value|-managed|-chain|-list] class element ? (e.g.: -l struct XyZ)\n");
|
||||
if(Sfile_fgets(line,sizeof(line)-1,fp)==NULL)
|
||||
{ret= 2; goto ex;}
|
||||
printf("%s\n",line);
|
||||
Sregex_trimline(line,0);
|
||||
if(strcmp(line,"@")==0)
|
||||
{ret= 2; goto ex;}
|
||||
ret= Ctyp_new_from_line(ct,*ct,line,msg,flag&1);
|
||||
if(ret<=0)
|
||||
goto ex;
|
||||
ret= 1;
|
||||
ex:;
|
||||
return(ret);
|
||||
}
|
||||
|
41
libburn/branches/ZeroFourTwo/libcevap/ctyp.h
Normal file
41
libburn/branches/ZeroFourTwo/libcevap/ctyp.h
Normal file
@ -0,0 +1,41 @@
|
||||
|
||||
#ifndef Ctyp_includeD
|
||||
#define Ctyp_includeD
|
||||
|
||||
|
||||
|
||||
struct CtyP {
|
||||
|
||||
/* if 1 : .name contains comment text, all other elements are invalid */
|
||||
int is_comment;
|
||||
|
||||
int is_pointer; /* number of asterisks */
|
||||
int is_struct;
|
||||
int is_unsigned;
|
||||
int is_volatile;
|
||||
unsigned long array_size;
|
||||
|
||||
int management; /*
|
||||
-v 0= just a value
|
||||
-m 1= allocated memory which needs to be freed
|
||||
-c 2= mutual link with the next element
|
||||
-c 3= mutual link with the prev element
|
||||
-l 4= list of -m , chained by -c pair named 'prev','next'
|
||||
supposed to be followed by a -v of the same type
|
||||
which will mark the end of the list
|
||||
*/
|
||||
int with_getter;
|
||||
int with_setter;
|
||||
int bossless_list;
|
||||
int no_initializer;
|
||||
|
||||
char *dtype;
|
||||
char *name;
|
||||
|
||||
struct CtyP *prev;
|
||||
struct CtyP *next;
|
||||
};
|
||||
|
||||
|
||||
#endif /* Ctyp_includeD */
|
||||
|
30
libburn/branches/ZeroFourTwo/libcevap/extract_cgen_input.sh
Executable file
30
libburn/branches/ZeroFourTwo/libcevap/extract_cgen_input.sh
Executable file
@ -0,0 +1,30 @@
|
||||
#!/bin/sh
|
||||
|
||||
copy_mode=0
|
||||
|
||||
while true
|
||||
do
|
||||
read line
|
||||
if test "$copy_mode" = "0"
|
||||
then
|
||||
if echo " $line" | grep '^ Cgen=' >/dev/null 2>&1
|
||||
then
|
||||
copy_mode=1
|
||||
if echo " $line" | grep '^ Cgen=..' >/dev/null 2>&1
|
||||
then
|
||||
echo " $line" | sed -e 's/^ Cgen=//'
|
||||
fi
|
||||
elif echo " $line" | grep '^ =end Model=' >/dev/null 2>&1
|
||||
then
|
||||
break
|
||||
fi
|
||||
else
|
||||
if test " $line" = " @"
|
||||
then
|
||||
copy_mode=0
|
||||
echo "@"
|
||||
else
|
||||
echo " $line" | sed -e 's/^ //'
|
||||
fi
|
||||
fi
|
||||
done
|
16
libburn/branches/ZeroFourTwo/libcevap/libcevap_gen.sh
Executable file
16
libburn/branches/ZeroFourTwo/libcevap/libcevap_gen.sh
Executable file
@ -0,0 +1,16 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_dir=.
|
||||
model_file=./libdax_model.txt
|
||||
xtr_dir=.
|
||||
cgen_dir=.
|
||||
# cgen_dir=~/projekte/cdrskin_dir/libburn-develop/libcevap
|
||||
|
||||
cd "$test_dir" || exit 1
|
||||
test -e smem.h || exit 1
|
||||
|
||||
cat "$model_file" | \
|
||||
"$xtr_dir"/extract_cgen_input.sh | \
|
||||
"$cgen_dir"/cgen -smem_local -ansi -global_include cevap_global.h \
|
||||
-overwrite "$@"
|
||||
|
BIN
libburn/branches/ZeroFourTwo/libcevap/libdax_equip.gif
Normal file
BIN
libburn/branches/ZeroFourTwo/libcevap/libdax_equip.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
BIN
libburn/branches/ZeroFourTwo/libcevap/libdax_job.gif
Normal file
BIN
libburn/branches/ZeroFourTwo/libcevap/libdax_job.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
944
libburn/branches/ZeroFourTwo/libcevap/libdax_model.txt
Normal file
944
libburn/branches/ZeroFourTwo/libcevap/libdax_model.txt
Normal file
@ -0,0 +1,944 @@
|
||||
|
||||
#
|
||||
# libdax is the early working name for the successor software of libburn,
|
||||
# a library for writing information onto optical media, i.e. CD and DVD.
|
||||
# The current working name is libcevap, refering to various kinds of roasts in
|
||||
# Europe and Asia which share the property to be structured in smaller pieces.
|
||||
#
|
||||
# The reason for the replacement is the unclear copyright situation as well
|
||||
# as libburn's sketchy original state and the subsequential evolutionary
|
||||
# damages done by us in libburn code.
|
||||
# This does not mean libburn is shaky. Its current state just reflects the
|
||||
# virtual conflict of at least two programmer personalities and their goals.
|
||||
#
|
||||
|
||||
#
|
||||
# Please: Nobody shall take the development of libcevap as a reason for not
|
||||
# programming an application which uses libburn.
|
||||
# libburn works now. libcevap is planned to work in future.
|
||||
#
|
||||
# libcevap will replace libburn in a controlled, application friendly way.
|
||||
# The first application of libcevap will be a libburn API wrapper which will
|
||||
# allow to perform all API calls of libburn which are proveable to work in
|
||||
# the current implementation. (Some CD stuff is not understood by us yet.
|
||||
# We will have to learn.)
|
||||
#
|
||||
# The libburn API will be frozen when libcevap has closed up to its current
|
||||
# capabilities. Nevertheless it may take profit from some of the future
|
||||
# progress in libcevap (e.g. new media types).
|
||||
# We hope that finally libcevap will have capabilities superior to libburn.
|
||||
# This will then be a reason to port applications to the libcevap API.
|
||||
#
|
||||
# Application programmers are advised to encapsulate their libburn API calls
|
||||
# in an own abstraction layer. The semantic concepts of burning will be
|
||||
# compatible between libburn and libcevap. I.e you will have a library object
|
||||
# to be started up, drives to be found and grabbed, media and their states
|
||||
# to be identified, sessions, tracks, burn options to be set, blanking,
|
||||
# formatting, and so on.
|
||||
# Data types, function calls, and quirks will be incompatible between both
|
||||
# APIs, though.
|
||||
#
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
# Originally this was a backup of text input clicketitoggled into ArgoUML
|
||||
# Meanwhile it becomes an intermediate storage for attributes and
|
||||
# class interconnections in the notation of my C stub generator CgeN
|
||||
# (see also end of this text)
|
||||
|
||||
# next : work on completeness : cevapformat
|
||||
|
||||
# Open questions:
|
||||
# - how to connect to GESTURES ? Globally ?
|
||||
|
||||
|
||||
Model=libdax
|
||||
|
||||
ClassDiagram=Overview
|
||||
|
||||
Class=API
|
||||
Author=Thomas Schmitt <scdbackup@gmx.net>
|
||||
Version=1.0
|
||||
Since=11.03.2007
|
||||
Documentation=\
|
||||
The API is the only layer visible to the applications. It exposes MMC concepts
|
||||
which it reflects and augments by its own architectural concepts.
|
||||
Subordinates=EQUIP,JOB,AUX
|
||||
Cgen=\
|
||||
cevapi
|
||||
-r -m struct CevapequiP *equip
|
||||
-r -m struct CevapjoB *job
|
||||
-r -m struct CevapauX *aux
|
||||
-r -m struct CevapgestureS *gestures
|
||||
@
|
||||
=end Class
|
||||
|
||||
Class=EQUIP
|
||||
Author=Thomas Schmitt <scdbackup@gmx.net>
|
||||
Version=1.0
|
||||
Since=11.03.2007
|
||||
Documentation=\
|
||||
EQUIP represents the physical and logical equipment in reach of libdax.
|
||||
This includes the system, drives, media, and their current states.
|
||||
PeerToPeer=GESTURES
|
||||
Boss=API
|
||||
Cgen=\
|
||||
cevapequip
|
||||
-r -v struct CevapI *boss
|
||||
-r -m struct CevapsysteM *sys
|
||||
-v struct CevapgestureS *gestures
|
||||
@
|
||||
=end Class
|
||||
|
||||
Class=JOB
|
||||
Author=Thomas Schmitt <scdbackup@gmx.net>
|
||||
Version=1.0
|
||||
Since=11.03.2007
|
||||
Documentation=\
|
||||
JOB models the tasks to be performed via libdax.
|
||||
This includes disc, session, track, source, fifo, dewav, burn options.
|
||||
PeerToPeer=GESTURES
|
||||
Boss=API
|
||||
Cgen=\
|
||||
cevapjob
|
||||
-r -v struct CevapI *boss
|
||||
-r -m struct CevaptodO *todo
|
||||
-v struct CevapgestureS *gestures
|
||||
|
||||
# >>>
|
||||
|
||||
@
|
||||
=end Class
|
||||
|
||||
Class=AUX
|
||||
Author=Thomas Schmitt <scdbackup@gmx.net>
|
||||
Version=1.0
|
||||
Since=11.03.2007
|
||||
Documentation=\
|
||||
AUX bundles any models which are neither EQUIP nor JOB.
|
||||
This includes abort handler and message system.
|
||||
PeerToPeer=GESTURES
|
||||
Boss=API
|
||||
Cgen=\
|
||||
cevapaux
|
||||
-r -v struct CevapI *boss
|
||||
-v struct CevapgestureS *gestures
|
||||
|
||||
# >>>
|
||||
|
||||
@
|
||||
=end Class
|
||||
|
||||
Class=GESTURES
|
||||
Author=Thomas Schmitt <scdbackup@gmx.net>
|
||||
Version=1.0
|
||||
Since=11.03.2007
|
||||
Documentation=\
|
||||
GESTURES ist the procedural repertoire which interconnects EQUIP, JOB, and AUX
|
||||
and also provides to them the services from the SCSI oriented layers.
|
||||
PeerToPeer=EQUIP,JOB,AUX
|
||||
Subordinates=SCSI_CMD
|
||||
Cgen=\
|
||||
cevapgestures
|
||||
-r -v struct CevapI *boss
|
||||
-v struct CevapequiP *equip
|
||||
-v struct CevapjoB *job
|
||||
-v struct CevapauX *aux
|
||||
-r -m struct CevapscmD *scsi_cmd
|
||||
|
||||
# >>>
|
||||
|
||||
@
|
||||
=end Class
|
||||
|
||||
Class=SCSI_CMD
|
||||
Author=Thomas Schmitt <scdbackup@gmx.net>
|
||||
Version=1.0
|
||||
Since=11.03.2007
|
||||
Documentation=\
|
||||
SCSI_CMD represents the semantic part of SCSI (i.e. mainly MMC) specs.
|
||||
This layer models each SCSI command that is used by libdax. It knows about
|
||||
its parameters and constraints with particular equipment and jobs.
|
||||
Boss=GESTURES
|
||||
Subordinates=Classes with SCSI_EXEC Interface
|
||||
Cgen=\
|
||||
cevapscmd
|
||||
-r -v struct CevapgestureS *boss
|
||||
-r -m struct CevapsexeC *scsi_exec
|
||||
|
||||
# >>>
|
||||
|
||||
@
|
||||
=end Class
|
||||
|
||||
Interface=SCSI_EXEC
|
||||
Author=Thomas Schmitt <scdbackup@gmx.net>
|
||||
Version=1.0
|
||||
Since=16.03.2007
|
||||
Documentation=\
|
||||
SCSI_EXEC hides the difference between the implementation principle of
|
||||
SCSI format+transport and the principle of SCSI service.
|
||||
Boss=SCSI_CMD
|
||||
Implementations=SCSI_FORMAT,SCSI_SERVICE
|
||||
Cgen=\
|
||||
cevapsexec
|
||||
-r -v struct CevapscmD *boss
|
||||
-p -v struct CevapsforM *scsi_format
|
||||
-p -v struct CevapsservicE *scsi_service
|
||||
-v int silent_on_scsi_error
|
||||
|
||||
# >>>
|
||||
|
||||
@
|
||||
=end Interface
|
||||
|
||||
|
||||
Class=OSDriveAspect
|
||||
Author=Thomas Schmitt <scdbackup@gmx.net>
|
||||
Version=1.0
|
||||
Since=18.08.2007
|
||||
Documentation=\
|
||||
OSDriveAspect encapsulates operating system specific properties of an
|
||||
individual drive. It shall be handed out by SCSI_EXEC via the GESTURES layer
|
||||
to EquipDrive where it forms the link between cevap drive model and operating
|
||||
system driver.
|
||||
This class description models the implementation specific to Linux.
|
||||
Cgen=\
|
||||
cevaposdrv
|
||||
-r -v int fd
|
||||
|
||||
# >>> ??? implement the sibling stuff which never worked properly ?
|
||||
|
||||
@
|
||||
=end Class
|
||||
|
||||
|
||||
Class=SCSI_FORMAT
|
||||
Author=Thomas Schmitt <scdbackup@gmx.net>
|
||||
Version=1.0
|
||||
Since=11.03.2007
|
||||
Documentation=\
|
||||
SCSI_FORMAT translates parameters of SCSI commands into CDBs, takes care for
|
||||
transport and decodes the reply into parameters.
|
||||
Boss=SCSI_CMD via SCSI_EXEC
|
||||
Subordinates=SCSI_TRANSPORT
|
||||
Cgen=\
|
||||
cevapsform
|
||||
-r -v struct CevapsexeC *boss
|
||||
-p -v struct CevapstransP *scsi_transport
|
||||
|
||||
# former struct command
|
||||
-v unsigned char opcode[16]
|
||||
-v int oplen
|
||||
-v int dir
|
||||
-v int dxfer_len
|
||||
-v unsigned char sense[128]
|
||||
-v int error
|
||||
-v int retry
|
||||
-v struct CevapbuffeR *page
|
||||
|
||||
# >>>
|
||||
|
||||
@
|
||||
=end Class
|
||||
|
||||
Class=SCSI_TRANSPORT
|
||||
Author=Thomas Schmitt <scdbackup@gmx.net>
|
||||
Version=1.0
|
||||
Since=11.03.2007
|
||||
Documentation=\
|
||||
SCSI_TRANSPORT takes a formatted CDB from SCSI_FORMAT and makes the operating
|
||||
system perform a SCSI transaction. It then returns the reply data in raw form.
|
||||
Boss=SCSI_FORMAT
|
||||
Os_specific=yes
|
||||
Cgen=\
|
||||
cevapstransp
|
||||
-r -v struct CevapsforM *boss
|
||||
|
||||
# >>>
|
||||
@
|
||||
=end Class
|
||||
|
||||
Class=SCSI_SERVICE
|
||||
Author=Thomas Schmitt <scdbackup@gmx.net>
|
||||
Version=1.0
|
||||
Since=11.03.2007
|
||||
Documentation=\
|
||||
SCSI_SERVICE provides the combined services of SCSI_FORMAT and SCSI_TRANSPORT
|
||||
via a set of parametrized functions which abstract SCSI command transactions.
|
||||
Boss=SCSI_CMD via SCSI_EXEC
|
||||
Os_specific=yes
|
||||
Cgen=\
|
||||
cevapsservice
|
||||
-r -v struct CevapsexeC *boss
|
||||
|
||||
# >>>
|
||||
@
|
||||
=end Class
|
||||
|
||||
=end ClassDiagram=Overview
|
||||
|
||||
|
||||
|
||||
ClassDiagram=Equip_overview
|
||||
|
||||
Class=EquipSystem
|
||||
Author=Thomas Schmitt <scdbackup@gmx.net>
|
||||
Version=1.0
|
||||
Since=16.03.2007
|
||||
Documentation=\
|
||||
EquipSystem is the inner root class of EQUIP. It describes the system on
|
||||
which libdax is working. This includes the operating system, the system
|
||||
adapter classes, the drives.
|
||||
Boss=EQUIP
|
||||
Subordinates=EquipDrive*N
|
||||
Cgen=\
|
||||
cevapsystem
|
||||
-r -v struct CevapequiP *boss
|
||||
-r -m char *infotext
|
||||
-r -l struct CevapdrivE *drive
|
||||
-p -v struct CevapdrivE *eol_drive
|
||||
|
||||
# >>> be boss of SCSI_CMD ? (Rather than GESTURES)
|
||||
|
||||
# >>>
|
||||
@
|
||||
=end Class
|
||||
|
||||
|
||||
Class=EquipDrive
|
||||
Author=Thomas Schmitt <scdbackup@gmx.net>
|
||||
Version=1.0
|
||||
Since=16.03.2007
|
||||
Documentation=\
|
||||
EquipDrive represents a drive, including its capabilities, its processing
|
||||
status, the media loaded.
|
||||
Subordinates=EquipMedia
|
||||
Boss=EquipSystem
|
||||
Cgen=\
|
||||
-l cevapdrive
|
||||
-r -v struct CevapsysteM *boss
|
||||
|
||||
# Drive number
|
||||
-r -v int global_index
|
||||
|
||||
# Persistent system drive address
|
||||
-r -m char *devname
|
||||
|
||||
# Traditional SCSI address parameters (-1 if not applicable)
|
||||
-r -v int bus_no
|
||||
-r -v int host
|
||||
-r -v int id
|
||||
-r -v int channel
|
||||
-r -v int lun
|
||||
|
||||
# (former struct burn_scsi_inquiry_data idata)
|
||||
# From 12h INQUIRY , spc3r23.pdf , 6.4.2 , Table 81
|
||||
-r -v char vendor[9]
|
||||
-r -v char product[17]
|
||||
-r -v char revision[5]
|
||||
# 1= above elements contain valid information
|
||||
-r -v int idata_valid
|
||||
|
||||
# mc5r03c.pdf 5.3.2 Physical Interface Standard
|
||||
# 1=SCSI, 2=ATAPI, 3,4,6=FireWire, 7=SATA, 8=USB
|
||||
-r -v int phys_if_std
|
||||
# MMC-5 5.3.2 table 91 , e.g. "SCSI Family"
|
||||
-r -m char *phys_if_name
|
||||
|
||||
# System despendent aspect of the drive (e.g. int fd;)
|
||||
-r -v struct CevaposdrV *system_dep_drive_info
|
||||
|
||||
# Result of the CD write mode x block type tests:
|
||||
# Index is for write mode : 0=packet , 1=TAO , 2=SAO , 3=raw
|
||||
# Bits are for block type
|
||||
# Numbering as in mc5r03c.pdf 7.5.4.13 Data Block Type, Table 668 :
|
||||
# 0=RAW0 (2352, Raw data)
|
||||
# 1=RAW16 (2368, Raw data with P and Q Sub-channel
|
||||
# 2=RAW96P (2448, Raw data with P-W Sub-channel appended)
|
||||
# 3=RAW96R (2448, Raw data with raw P-W Sub-channel appended)
|
||||
# 8=MODE1 (2048, ISO/IEC 10149)
|
||||
# 9=MODE2R (2336, Mode 2 formless)
|
||||
# 10=MODE2F1 (2048, CD-ROM XA, form 1)
|
||||
# 11=MODE2F1X (2056, CD-ROM XA, form 1 plus 8 byte subheader)
|
||||
# 12=MODE2F2 (2324, CD-ROM XA, form 2)
|
||||
# 13=MODE2MIX (2332, CD-ROM XA, form 1, form 2, or mixed form)
|
||||
-r -v int block_types[4]
|
||||
|
||||
# (former struct scsi_mode_data)
|
||||
# Information about the drive's capabilities, obtained via 5Ah MODE SENSE
|
||||
# from mode page 2Ah , mmc3r10g.pdf , 6.3.11 , Table 361
|
||||
# (which is deprecated in MMC-5 E.11)
|
||||
-p -v int mdata_buffer_size
|
||||
-p -v int mdata_dvdram_read
|
||||
-p -v int mdata_dvdram_write
|
||||
-p -v int mdata_dvdr_read
|
||||
-p -v int mdata_dvdr_write
|
||||
-p -v int mdata_dvdrom_read
|
||||
-p -v int mdata_cdrw_read
|
||||
-p -v int mdata_cdrw_write
|
||||
-p -v int mdata_cdr_read
|
||||
-p -v int mdata_cdr_write
|
||||
-p -v int mdata_max_read_speed
|
||||
-p -v int mdata_max_write_speed
|
||||
-p -v int madata_min_write_speed
|
||||
-p -v int mdata_cur_read_speed
|
||||
-p -v int mdata_cur_write_speed
|
||||
-p -v int mdata_simulate
|
||||
-p -v int mdata_c2_pointers
|
||||
-r -v int mdata_underrun_proof
|
||||
|
||||
# Results from ACh GET PERFORMANCE, Type 03h
|
||||
# (Speed values go into *_*_speed)
|
||||
# (speed_descriptors became cevapperf which is under cevapmedia)
|
||||
-p -v int min_end_lba
|
||||
-p -v int max_end_lba
|
||||
|
||||
# from mode page 01h , mmc5r03c.pdf , 7.3.2.1 , Table 657
|
||||
-p -v int mdata_retry_page_length
|
||||
-p -v int mdata_retry_page_valid
|
||||
|
||||
# from mode page 05h , mmc5r03c.pdf , 7.5.4.1 , Table 664
|
||||
-p -v int mdata_write_page_length
|
||||
-p -v int mdata_write_page_valid
|
||||
|
||||
# 1= above elements contain valid information
|
||||
-p -v int mdata_valid
|
||||
|
||||
# The mutex shall be used to coordinate access to the drive in situations
|
||||
# where multi-threaded race conditions could disturb operations.
|
||||
# E.g. lock, read busy state, interpret, set busy state, unlock
|
||||
# A mere reader of the busy state does not have to lock because
|
||||
# reading of the state itself is atomar.
|
||||
-i -v pthread_mutex_t access_lock
|
||||
|
||||
# Flags from feature 002Fh feature descriptor mmc5r03c.pdf 5.3.25 :
|
||||
# bit1= DVD-RW supported
|
||||
# bit2= Test Write available
|
||||
# bit3= DVD-R DL supported
|
||||
# bit6= Buffer Under-run Free recording available (page 05h BUFE)
|
||||
# Value -1 indicates that no 002Fh was current in the features list.
|
||||
-r -v int current_feat2fh_byte4
|
||||
|
||||
# 0= drive is grabbed, 1= drive is not grabbed
|
||||
-v volatile int released
|
||||
|
||||
# File descriptor of an eventual emulated drive
|
||||
-v int stdio_fd
|
||||
|
||||
# >>> ???
|
||||
# (do we need a drive owned buffer to carry data from call to call or what ?)
|
||||
-v struct CevapbuffeR *buffer
|
||||
|
||||
# List of profiles as reported by the drive
|
||||
-r -l struct CevapprofilE *profile
|
||||
-p -v struct CevapprofilE *eol_profile
|
||||
|
||||
# Media currently loaded in the drive
|
||||
-r -m struct CevapmediA *media
|
||||
|
||||
|
||||
# >>> transport.h : toc_temp (what is this ? It belongs to BURN_WRITE_RAW)
|
||||
# >>>
|
||||
|
||||
@
|
||||
=end Class
|
||||
|
||||
|
||||
Class=EquipMedia
|
||||
Author=Thomas Schmitt <scdbackup@gmx.net>
|
||||
Version=1.0
|
||||
Since=16.03.2007
|
||||
Documentation=\
|
||||
EquipMedia represents an optical disc, including its type, its writeability,
|
||||
its formatting, its available formats and performances.
|
||||
Subordinates=\
|
||||
EquipProfile*N,EquipFormat*N,EquipPerformance*N,EquipStatus,EquipMulticaps
|
||||
Boss=EquipDrive
|
||||
Cgen=\
|
||||
cevapmedia
|
||||
-r -v struct CevapdrivE *boss
|
||||
|
||||
# Volatile and/or public properties of the media
|
||||
-r -m struct CevapstatuS *status
|
||||
|
||||
# MMC-to-MMC feature info from 46h for DVD-RW.
|
||||
# Quite internal. Regard as opaque :)
|
||||
# 1 = incremental recording available, 0 = not available
|
||||
-r -v int current_has_feat21h
|
||||
|
||||
# Link Size item number 0 from feature 0021h descriptor
|
||||
-r -v int current_feat21h_link_size
|
||||
|
||||
# Wether a DVD-RW media holds an incomplete session
|
||||
# (which could need closing after write)
|
||||
-v int needs_close_session
|
||||
|
||||
# From 51h READ DISC INFORMATION
|
||||
# 0=needs format start, 1=needs format restart
|
||||
-r -v int bg_format_status
|
||||
|
||||
# From 23h READ FORMAT CAPACITY mmc5r03c.pdf 6.24
|
||||
# 1=unformatted, 2=formatted, 3=unclear
|
||||
-r -v int format_descr_type
|
||||
# meaning depends on format_descr_type
|
||||
-r -v off_t format_curr_max_size
|
||||
# dito
|
||||
-r -v unsigned int format_curr_blsas
|
||||
-r -v int best_format_type
|
||||
-r -v off_t best_format_size
|
||||
-r -l struct CevapformaT *format_descriptor
|
||||
-p -v struct CevapformaT *eol_format_descriptor
|
||||
|
||||
# The specific capabilities and restrictions of the media
|
||||
-r -m struct CevapmcapS *multicaps
|
||||
|
||||
# Results from ACh GET PERFORMANCE, Type 03h
|
||||
# (Speed values go into drive.mdata_*_*_speed)
|
||||
-r -l struct CevapperF *speed_descriptor
|
||||
-p -v struct CevapperF *eol_speed_descriptor
|
||||
|
||||
# >>>
|
||||
|
||||
@
|
||||
=end Class
|
||||
|
||||
|
||||
Class=EquipProfile
|
||||
Author=Thomas Schmitt <scdbackup@gmx.net>
|
||||
Version=1.0
|
||||
Since=16.03.2007
|
||||
Documentation=\
|
||||
EquipProfile maps a MMC profile into libdax (See mmc5r03c.pdf chapter 5).
|
||||
A profile describes a set of features and may be either current, possible,
|
||||
disabled, or unavailable.
|
||||
Subordinates=EquipFeature*N
|
||||
Boss=EquipMedia
|
||||
Cgen=\
|
||||
-l cevapprofile
|
||||
-r -v struct CevapdrivE *boss
|
||||
-r -v int is_current
|
||||
-r -v int profile_code
|
||||
-r -v char *profile_text
|
||||
-r -v int is_cd_profile
|
||||
-r -v int is_supported_profile
|
||||
-r -l struct CevapfeaturE *feature
|
||||
-p -v struct CevapfeaturE *eol_feature
|
||||
@
|
||||
=end Class
|
||||
|
||||
Class=EquipFeature
|
||||
Author=Thomas Schmitt <scdbackup@gmx.net>
|
||||
Version=1.0
|
||||
Since=16.03.2007
|
||||
Documentation=\
|
||||
EquipFeature maps a MMC feature into libdax (See mmc5r03c.pdf chapter 5).
|
||||
A feature describes a set of SCSI commands and (implicitely) of use cases.
|
||||
Boss=EquipProfile
|
||||
Cgen=\
|
||||
-l cevapfeature
|
||||
-r -v struct CevapprofilE *boss
|
||||
|
||||
# >>>
|
||||
|
||||
@
|
||||
=end Class
|
||||
|
||||
Class=EquipFormat
|
||||
Author=Thomas Schmitt <scdbackup@gmx.net>
|
||||
Version=1.0
|
||||
Since=
|
||||
Documentation=\
|
||||
EquipFormat represents a single Formattable Capacity Descriptor
|
||||
as of mmc5r03c.pdf 6.24.3.3 .
|
||||
Boss=EquipMedia
|
||||
Cgen=\
|
||||
-l cevapformat
|
||||
-r -v struct CevapmediA *boss
|
||||
|
||||
# format type: e.g 0x00 is "Full", 0x15 is "Quick"
|
||||
-r -v int type
|
||||
|
||||
# the size in bytes derived from Number of Blocks
|
||||
-r -v off_t size
|
||||
|
||||
# the Type Dependent Parameter (usually the write alignment size)
|
||||
-r -v unsigned int tdp
|
||||
|
||||
# >>>
|
||||
|
||||
@
|
||||
=end Class
|
||||
|
||||
Class=EquipPerformance
|
||||
Author=Thomas Schmitt <scdbackup@gmx.net>
|
||||
Version=1.0
|
||||
Since=
|
||||
Documentation=\
|
||||
>>> EquipPerformance
|
||||
Boss=EquipMedia
|
||||
Cgen=\
|
||||
-l cevapperf
|
||||
-r -v struct CevapmediA *boss
|
||||
|
||||
# >>>
|
||||
|
||||
@
|
||||
=end Class
|
||||
|
||||
Class=EquipStatus
|
||||
Author=Thomas Schmitt <scdbackup@gmx.net>
|
||||
Version=1.0
|
||||
Since=17.3.2007
|
||||
Documentation=\
|
||||
EquipStatus represents the status of media and drive. This includes
|
||||
blank/appendable/closed, progress indicator.
|
||||
Boss=EquipMedia
|
||||
Cgen=\
|
||||
cevapstatus
|
||||
-r -v struct CevapmediA *boss
|
||||
-v int status
|
||||
-m char *status_text
|
||||
-v volatile int busy
|
||||
|
||||
# From various sources : free space on media (in bytes)
|
||||
# With CD this might change after particular write
|
||||
# parameters have been set and nwa has been inquired.
|
||||
-v off_t media_capacity_remaining
|
||||
|
||||
# Current write address during write jobs. (Next address to be written)
|
||||
# <<< does this belong to JOB ?
|
||||
-r -v int nwa
|
||||
|
||||
# if > 0 : first lba on media that is too high for write
|
||||
-v int media_lba_limit
|
||||
|
||||
-v struct CevapprogresS *progress
|
||||
|
||||
# >>>
|
||||
|
||||
@
|
||||
=end Class
|
||||
|
||||
Class=EquipMulticaps
|
||||
Author=Thomas Schmitt <scdbackup@gmx.net>
|
||||
Version=1.0
|
||||
Since=14.8.2007
|
||||
Documentation=\
|
||||
EquipMulticaps represents media dependent properties and media states which
|
||||
are either volatile or especially interesting to several other modules. This
|
||||
includes eventually existing sessions, closure status, profile dependent
|
||||
capabilities.
|
||||
Boss=EquipMedia
|
||||
Cgen=\
|
||||
cevapmcaps
|
||||
|
||||
# The current profile out of the drive profile list
|
||||
-v struct CevapprofilE *current_profile
|
||||
|
||||
# Wether the media is erasable (or overwriteable)
|
||||
-v int erasable
|
||||
|
||||
# A description of the existing media content structure
|
||||
-r -m struct CevapdisC *disc
|
||||
|
||||
# Start and end addresses out of ATIP.
|
||||
# From 43h READ TOC/PMA/ATIP , mmc5r03c.pdf , 6.26
|
||||
-r -v int start_lba
|
||||
-r -v int end_lba
|
||||
|
||||
# From 51h READ DISC INFORMATION Number of Sessions (-1)
|
||||
-v int complete_sessions
|
||||
|
||||
# From 51h READ DISC INFORMATION Last Track Number in Last Session
|
||||
-v int last_track_no
|
||||
|
||||
# >>> libburn.h:struct burn_multi_caps
|
||||
|
||||
@
|
||||
=end Class
|
||||
|
||||
Class=EquipTocItem
|
||||
Author=Thomas Schmitt <scdbackup@gmx.net>
|
||||
Version=1.0
|
||||
Since=14.8.2007
|
||||
Boss=
|
||||
Cgen=\
|
||||
-l cevaptocitem
|
||||
-r -v struct CevapdisC *boss
|
||||
-v int session
|
||||
-v int valid
|
||||
-v int control
|
||||
|
||||
# obscure info from CD TOC : possibly length of track
|
||||
-v unsigned char point
|
||||
-v unsigned char min
|
||||
-v unsigned char sec
|
||||
-v unsigned char frame
|
||||
|
||||
-v int pmin
|
||||
-v int psec
|
||||
-v int pframe
|
||||
|
||||
-v int start_lba
|
||||
-v int track_blocks
|
||||
@
|
||||
=end Class
|
||||
|
||||
|
||||
|
||||
=end ClassDiagram=Equip_overview
|
||||
|
||||
|
||||
ClassDiagram=Job_overview
|
||||
|
||||
Class=JobTodo
|
||||
Author=Thomas Schmitt <scdbackup@gmx.net>
|
||||
Version=1.0
|
||||
Since=18.3.2007
|
||||
Documentation=\
|
||||
JobTodo records what is to be done during a job. This includes peripheral
|
||||
actions like tray load/eject and central actions like blank, format, burn.
|
||||
Subordinates=JobDisc,JobOptions
|
||||
Cgen=\
|
||||
cevaptodo
|
||||
-v volatile int cancel
|
||||
|
||||
# >>>
|
||||
|
||||
@
|
||||
=end Class
|
||||
|
||||
Class=JobDisc
|
||||
Author=Thomas Schmitt <scdbackup@gmx.net>
|
||||
Version=1.0
|
||||
Since=18.3.2007
|
||||
Documentation=\
|
||||
JobDisc models a disc structure. Either one which already exists or
|
||||
one which is to be created in a job run.
|
||||
Subordinates=JobSession*N
|
||||
Boss=JobTodo
|
||||
Cgen=\
|
||||
cevapdisc
|
||||
-l struct CevapsessioN *session
|
||||
-p -v struct CevapsessioN *eol_session
|
||||
-l struct CevaptociteM *toc_entry
|
||||
-p -v struct CevaptociteM *eol_toc_entry
|
||||
|
||||
# >>> take over services of struct burn_disc
|
||||
|
||||
@
|
||||
=end Class
|
||||
|
||||
Class=JobSession
|
||||
Author=Thomas Schmitt <scdbackup@gmx.net>
|
||||
Version=1.0
|
||||
Since=18.3.2007
|
||||
Documentation=\
|
||||
JobSession represents a recording session. A session usually bundles
|
||||
several tracks. Traditionally the last session of a disc is recognized
|
||||
by operating systems as the thing to be mounted.
|
||||
Subordinates=JobTrack*N,JobFifo
|
||||
Boss=JobDisc
|
||||
Cgen=\
|
||||
-l cevapsession
|
||||
-r -v struct CevapdisC *boss
|
||||
|
||||
# >>>
|
||||
|
||||
-l struct CevaptracK *track
|
||||
-p -v struct CevaptracK *eol_track
|
||||
|
||||
# >>>
|
||||
|
||||
@
|
||||
=end Class
|
||||
|
||||
Class=JobTrack
|
||||
Author=Thomas Schmitt <scdbackup@gmx.net>
|
||||
Version=1.0
|
||||
Since=18.3.2007
|
||||
Documentation=\
|
||||
JobTrack represents a track to be recorded. A track mainly is associated with
|
||||
a data source but in many cases it also becomes a recognizable entity on the
|
||||
target media.
|
||||
Subordinates=JobBlock*N,JobTrackFilter,JobSource
|
||||
Boss=JobSession
|
||||
Cgen=\
|
||||
-l cevaptrack
|
||||
-r -v struct CevapsessioN *boss
|
||||
|
||||
# >>>
|
||||
|
||||
@
|
||||
=end Class
|
||||
|
||||
Class=JobBlock
|
||||
Author=Thomas Schmitt <scdbackup@gmx.net>
|
||||
Version=1.0
|
||||
Since=18.3.2007
|
||||
Documentation=\
|
||||
JobBlock represents a single output data transaction unit. On CD this is
|
||||
the same as an addressable media block resp. sector. On DVD this might be
|
||||
an addressable block od 2k or a packet of e.g. 32k.
|
||||
Boss=JobTrack
|
||||
Cgen=\
|
||||
cevapblock
|
||||
-v int alba
|
||||
-v int rlba
|
||||
|
||||
# >>>
|
||||
|
||||
@
|
||||
=end Class
|
||||
|
||||
Class=JobSource
|
||||
Author=Thomas Schmitt <scdbackup@gmx.net>
|
||||
Version=1.0
|
||||
Since=8.4.2007
|
||||
Documentation=\
|
||||
JobSource represents a data source for a track. Typically this is a disk
|
||||
file or a stream file descriptor like stdin.
|
||||
Subordinates=JobSourceBlock*N
|
||||
Boss=JobTrack
|
||||
=end Class
|
||||
|
||||
Class=JobSourceBlock
|
||||
Author=Thomas Schmitt <scdbackup@gmx.net>
|
||||
Version=1.0
|
||||
Since=8.4.2007
|
||||
Documentation=\
|
||||
JobSourceBlock represents a single input data transaction unit.
|
||||
Boss=JobSource
|
||||
=end Class
|
||||
|
||||
Class=JobFifo
|
||||
Author=Thomas Schmitt <scdbackup@gmx.net>
|
||||
Version=1.0
|
||||
Since=8.4.2007
|
||||
Documentation=\
|
||||
JobFifo reads data via JobTrackFilter and buffers them until JobBlock can
|
||||
accept them.
|
||||
Boss=JobSession
|
||||
=end Class
|
||||
|
||||
Class=JobTrackFilter
|
||||
Author=Thomas Schmitt <scdbackup@gmx.net>
|
||||
Version=1.0
|
||||
Since=8.4.2007
|
||||
Documentation=\
|
||||
JobTrackFilter reads data from JobSourceBlock, processes them and presents
|
||||
them to JobFifo or JobBlock. This includes stripping of .wav headers.
|
||||
Boss=JobTrack
|
||||
=end Class
|
||||
|
||||
Class=JobOptions
|
||||
Author=Thomas Schmitt <scdbackup@gmx.net>
|
||||
Version=1.0
|
||||
Since=18.3.2007
|
||||
Documentation=\
|
||||
JobOptions bundles the adjustable parameters of a job. This includes dummy
|
||||
mode, speed, appendability, blank mode, format selection, write mode,
|
||||
underrun protection, random access addressing.
|
||||
Boss=JobTodo
|
||||
Cgen=\
|
||||
cevapjobopts
|
||||
|
||||
# >>>
|
||||
|
||||
# Keeping an eye on the drive buffer
|
||||
-v int wait_for_buffer_free
|
||||
-v unsigned int wfb_min_usec
|
||||
-v unsigned int wfb_max_usec
|
||||
-v unsigned int wfb_timeout_sec
|
||||
-v unsigned int wfb_min_percent
|
||||
-v unsigned int wfb_max_percent
|
||||
|
||||
# >>> -m struct params params (used by disabled read cd funtionality)
|
||||
|
||||
@
|
||||
=end Class
|
||||
|
||||
Class=JobBuffer
|
||||
Author=Thomas Schmitt <scdbackup@gmx.net>
|
||||
Version=1.0
|
||||
Since=13.8.2007
|
||||
Documentation=\
|
||||
JobBuffer is an intermediate storage for the content of several JobBlock
|
||||
or JobSourceBlock.
|
||||
Cgen=\
|
||||
cevapbuffer
|
||||
-r -m unsigned char *data
|
||||
-v int sectors
|
||||
-v int bytes
|
||||
@
|
||||
=end Class
|
||||
|
||||
Class=JobProgress
|
||||
Author=Thomas Schmitt <scdbackup@gmx.net>
|
||||
Version=1.0
|
||||
Since=13.8.2007
|
||||
Documentation=\
|
||||
JobProgress reflects the state and parts of the history of a job
|
||||
Cgen=\
|
||||
cevapprogress
|
||||
|
||||
# Keeping an eye on the drive buffer
|
||||
-v int nominal_write_speed
|
||||
-v off_t pessimistic_buffer_free
|
||||
-v int pbf_altered
|
||||
-v unsigned int pessimistic_writes
|
||||
-v unsigned int waited_writes
|
||||
-v unsigned int waited_tries
|
||||
-v unsigned int waited_usec
|
||||
|
||||
# >>> the info provided by struct burn_progress
|
||||
|
||||
# >>>
|
||||
@
|
||||
=end Class
|
||||
|
||||
Class=
|
||||
Author=Thomas Schmitt <scdbackup@gmx.net>
|
||||
Version=1.0
|
||||
Since=
|
||||
Documentation=\
|
||||
=end Class
|
||||
|
||||
=end ClassDiagram=Equip_overview
|
||||
|
||||
|
||||
ClassDiagram=Gestures_overview
|
||||
|
||||
# >>>
|
||||
|
||||
=end ClassDiagram=Gestures_overview
|
||||
|
||||
|
||||
|
||||
=end Model=libdax
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Notes:
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Compile cgen:
|
||||
( cd libcevap && cc -g -o cgen cgen.c ctyp.c smem.c )
|
||||
|
||||
Generate C stubs:
|
||||
( cd libcevap && ./libcevap_gen.sh )
|
||||
Option -lowercase would generate all lowercase struct and function names
|
||||
|
||||
Compile test:
|
||||
( cd libcevap && ( rm a.out ; cc -g main.c cevap*.c smem.c ) )
|
||||
Option -DCevap_lowercasE would tell main.c that -lowercase was used above.
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
For a description of CgeN see libcevap/cgen.txt
|
||||
|
||||
The generated code uses smem.[ch] out of one of my BSD licensed projects.
|
||||
For a description see end of libcevap/smem.h .
|
||||
|
||||
------------------------------------------------------------------------
|
BIN
libburn/branches/ZeroFourTwo/libcevap/libdax_overview.gif
Normal file
BIN
libburn/branches/ZeroFourTwo/libcevap/libdax_overview.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
39
libburn/branches/ZeroFourTwo/libcevap/main.c
Normal file
39
libburn/branches/ZeroFourTwo/libcevap/main.c
Normal file
@ -0,0 +1,39 @@
|
||||
|
||||
/*
|
||||
cc -g -DCevap_lowercasE -c main.c
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "cevapi.h"
|
||||
|
||||
#include "smem.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
#ifdef Cevap_lowercasE
|
||||
struct cevapi *cevap= NULL;
|
||||
#else
|
||||
struct CevapI *cevap= NULL;
|
||||
#endif
|
||||
int ret;
|
||||
|
||||
/* full memory supervision */
|
||||
Smem_set_record_items(1);
|
||||
|
||||
/* one short trip for testing */
|
||||
#ifdef Cevap_lowercasE
|
||||
ret= cevapi_new(&cevap,0);
|
||||
if(ret>0)
|
||||
cevapi_destroy(&cevap,0);
|
||||
#else /* Cevap_lowercasE */
|
||||
ret= Cevapi_new(&cevap,0);
|
||||
if(ret>0)
|
||||
Cevapi_destroy(&cevap,0);
|
||||
#endif /* ! Cevap_lowercasE */
|
||||
|
||||
/* report any leaked memory */
|
||||
Smem_stderr(1|2);
|
||||
|
||||
exit(ret<=0);
|
||||
}
|
445
libburn/branches/ZeroFourTwo/libcevap/smem.c
Normal file
445
libburn/branches/ZeroFourTwo/libcevap/smem.c
Normal file
@ -0,0 +1,445 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
#define Smem_included_by_smem_C
|
||||
#include "smem.h"
|
||||
|
||||
|
||||
|
||||
/* ------------------------------ SmemiteM ----------------------------- */
|
||||
|
||||
|
||||
int Smemitem_new(item,data,size,next,hash_start,flag)
|
||||
struct SmemiteM **item;
|
||||
char *data;
|
||||
size_t size;
|
||||
struct SmemiteM *next;
|
||||
struct SmemiteM **hash_start;
|
||||
int flag;
|
||||
{
|
||||
struct SmemiteM *t;
|
||||
|
||||
*item= t= (struct SmemiteM *) malloc(sizeof(struct SmemiteM));
|
||||
if(t==NULL)
|
||||
return(-1);
|
||||
t->data= data;
|
||||
t->size= size;
|
||||
t->prev= NULL;
|
||||
t->next= next;
|
||||
|
||||
#ifdef Smem_with_hasH
|
||||
t->hash_next= NULL;
|
||||
t->hash_prev= NULL;
|
||||
#endif /* Smem_with_hasH */
|
||||
|
||||
if(next!=NULL) {
|
||||
if(next->prev!=NULL) {
|
||||
t->prev= next->prev;
|
||||
next->prev->next= t;
|
||||
}
|
||||
next->prev= t;
|
||||
}
|
||||
|
||||
#ifdef Smem_with_hasH
|
||||
if(hash_start!=NULL) {
|
||||
t->hash_next= *hash_start;
|
||||
if(t->hash_next!=NULL) {
|
||||
t->hash_next->hash_prev= t;
|
||||
}
|
||||
*hash_start= t;
|
||||
}
|
||||
#endif /* Smem_with_hasH */
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
int Smemitem_destroy(in_item,hash_start,flag)
|
||||
struct SmemiteM **in_item;
|
||||
struct SmemiteM **hash_start;
|
||||
int flag;
|
||||
{
|
||||
struct SmemiteM *item;
|
||||
|
||||
item= *in_item;
|
||||
if(item==NULL)
|
||||
return(0);
|
||||
if(item==Smem_start_iteM)
|
||||
Smem_start_iteM= item->next;
|
||||
if(item->prev!=NULL)
|
||||
item->prev->next= item->next;
|
||||
if(item->next!=NULL)
|
||||
item->next->prev= item->prev;
|
||||
|
||||
#ifdef Smem_with_hasH
|
||||
if(hash_start!=NULL) {
|
||||
if(item==*hash_start)
|
||||
*hash_start= item->hash_next;
|
||||
if(item->hash_prev!=NULL)
|
||||
item->hash_prev->hash_next= item->hash_next;
|
||||
if(item->hash_next!=NULL)
|
||||
item->hash_next->hash_prev= item->hash_prev;
|
||||
}
|
||||
#endif /* Smem_with_hasH */
|
||||
|
||||
free((char *) item);
|
||||
*in_item= NULL;
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
int Smemitem_report(item,line,flag)
|
||||
struct SmemiteM *item;
|
||||
char line[1024];
|
||||
int flag;
|
||||
{
|
||||
char *cpt;
|
||||
int i,upto;
|
||||
|
||||
sprintf(line,"%4lu bytes at %8.8lx ",(unsigned long) item->size,
|
||||
(unsigned long) item->data);
|
||||
cpt= line+strlen(line);
|
||||
if(item->size<=256)
|
||||
upto= item->size;
|
||||
else
|
||||
upto= 256;
|
||||
if(item->data!=NULL) {
|
||||
strcpy(cpt,"= \"");
|
||||
cpt+= 3;
|
||||
for(i=0;i<upto;i++){
|
||||
if(item->data[i]<32 || item->data[i]>=127 || item->data[i]=='\\') {
|
||||
sprintf(cpt,"\\%2.2X",(unsigned char) item->data[i]);
|
||||
cpt+= 3;
|
||||
} else {
|
||||
*(cpt++)= item->data[i];
|
||||
}
|
||||
}
|
||||
if(i<item->size) {
|
||||
sprintf(cpt,"\" [truncated]");
|
||||
} else {
|
||||
*(cpt++)= '"';
|
||||
*cpt= 0;
|
||||
}
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
int Smemitem_stderr(item,flag)
|
||||
struct SmemiteM *item;
|
||||
int flag;
|
||||
{
|
||||
char line[1024];
|
||||
Smemitem_report(item,line,0);
|
||||
fprintf(stderr,"%s\n",line);
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* -------------------------------- Smem ------------------------------ */
|
||||
|
||||
|
||||
int Smem_protest(line,flag)
|
||||
char *line;
|
||||
int flag;
|
||||
{
|
||||
fprintf(stderr,"%s\n",line);
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
int Smem_hashindex(ptr,flag)
|
||||
char *ptr;
|
||||
int flag;
|
||||
{
|
||||
unsigned long idx;
|
||||
|
||||
idx= (unsigned long) ptr;
|
||||
return((idx>>Smem_hashshifT)%(Smem_hashsizE));
|
||||
}
|
||||
|
||||
|
||||
/* find a certain memory item */
|
||||
struct SmemiteM *Smem_find_item(ptr,flag)
|
||||
char *ptr;
|
||||
int flag;
|
||||
{
|
||||
int misscount= 0,idx;
|
||||
struct SmemiteM *current;
|
||||
|
||||
#ifdef Smem_with_hasH
|
||||
|
||||
idx= Smem_hashindex(ptr,0);
|
||||
for(current= Smem_hasH[idx];current!=NULL;current= current->hash_next) {
|
||||
if(current->data==ptr)
|
||||
return(current);
|
||||
misscount++;
|
||||
}
|
||||
|
||||
#else /* Smem_with_hasH */
|
||||
|
||||
for(current= Smem_start_iteM;current!=NULL;current= current->next) {
|
||||
if(current->data==ptr)
|
||||
return(current);
|
||||
misscount++;
|
||||
}
|
||||
|
||||
#endif /* ! Smem_with_hasH */
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
|
||||
int Smem_search_and_delete(ptr,flag)
|
||||
char *ptr;
|
||||
int flag;
|
||||
/*
|
||||
bit0= revoke registration : decrement counters
|
||||
*/
|
||||
{
|
||||
int idx;
|
||||
struct SmemiteM *current;
|
||||
|
||||
current= Smem_find_item(ptr,0);
|
||||
if(current==NULL)
|
||||
return(0);
|
||||
Smem_record_counT--;
|
||||
Smem_record_byteS-= current->size;
|
||||
idx= Smem_hashindex(ptr,0);
|
||||
Smemitem_destroy(¤t,&(Smem_hasH[idx]),0);
|
||||
Smem_hash_counteR[idx]-= 1.0;
|
||||
if(flag&1) {
|
||||
Smem_malloc_counT--;
|
||||
Smem_pending_counT--;
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
char *Smem_malloc(size)
|
||||
size_t size;
|
||||
{
|
||||
int idx;
|
||||
char *cpt;
|
||||
|
||||
if(size==0) {
|
||||
Smem_protest("########### smem.c : malloc(0) caught",0);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* if(size==1032)
|
||||
cpt= NULL; / * set breakpoint here to find requests of certain size */
|
||||
|
||||
cpt= (char *) malloc(size);
|
||||
if(cpt==NULL) {
|
||||
char text[161];
|
||||
sprintf(text,"########### smem.c : malloc( %lu ) returned NULL",
|
||||
(unsigned long) size);
|
||||
Smem_protest(text,0);
|
||||
return(NULL);
|
||||
}
|
||||
/* if(cpt==0x080a1e20)
|
||||
cpt= NULL; / * set breakpoint here to find origin of certain address */
|
||||
|
||||
Smem_malloc_counT++;
|
||||
Smem_pending_counT++;
|
||||
if(Smem_record_itemS) {
|
||||
idx= Smem_hashindex(cpt,0);
|
||||
Smem_hash_counteR[idx]+= 1.0;
|
||||
if(Smemitem_new(&Smem_start_iteM,cpt,size,Smem_start_iteM,
|
||||
&(Smem_hasH[idx]),0)<=0) {
|
||||
Smem_protest(
|
||||
"########### smem.c : malloc( sizeof(SmemiteM) ) returned NULL",0);
|
||||
return(NULL);
|
||||
}
|
||||
Smem_record_counT++;
|
||||
Smem_record_byteS+= size;
|
||||
}
|
||||
return(cpt);
|
||||
}
|
||||
|
||||
|
||||
int Smem_free(ptr)
|
||||
char *ptr;
|
||||
{
|
||||
if(ptr==NULL) {
|
||||
Smem_protest("########### smem.c : free() of NULL pointer caught",0);
|
||||
return(0);
|
||||
}
|
||||
if(Smem_record_itemS) {
|
||||
if(Smem_search_and_delete(ptr,0)<=0) {
|
||||
Smem_protest("########### smem.c : free() of unrecorded pointer caught",0);
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
Smem_free_counT++;
|
||||
Smem_pending_counT--;
|
||||
free(ptr);
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
int Smem_report(line,flag)
|
||||
char line[1024];
|
||||
int flag;
|
||||
{
|
||||
sprintf(line,"malloc= %.f , free= %.f , pending= %.f",
|
||||
Smem_malloc_counT,Smem_free_counT,Smem_pending_counT);
|
||||
if(Smem_record_itemS) {
|
||||
sprintf(line+strlen(line)," , bytes=%.f , records= %.f",
|
||||
Smem_record_byteS,Smem_record_counT);
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
int Smem_stderr(flag)
|
||||
int flag;
|
||||
/*
|
||||
bit0= report 50 youngest pending items too
|
||||
bit1= do not report if nothing is pending
|
||||
*/
|
||||
{
|
||||
struct SmemiteM *current;
|
||||
char line[1024];
|
||||
int i= 0;
|
||||
|
||||
if(flag&2)
|
||||
if(Smem_pending_counT==0.0
|
||||
&& Smem_record_counT==0.0
|
||||
&& Smem_record_byteS==0.0)
|
||||
return(2);
|
||||
Smem_report(line,0);
|
||||
fprintf(stderr,"%s\n",line);
|
||||
if(flag&1) {
|
||||
for(current= Smem_start_iteM;current!=NULL;current= current->next) {
|
||||
Smemitem_stderr(current,0);
|
||||
if(++i>=50)
|
||||
break;
|
||||
}
|
||||
if(current!=NULL)
|
||||
if(current->next!=NULL)
|
||||
fprintf(stderr,"[list truncated]\n");
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
int Smem_set_record_items(value)
|
||||
int value;
|
||||
{
|
||||
int i;
|
||||
|
||||
if(!Smem_hash_initializeD) {
|
||||
for(i=0;i<Smem_hashsizE;i++) {
|
||||
Smem_hasH[i]= NULL;
|
||||
Smem_hash_counteR[i]= 0.0;
|
||||
}
|
||||
Smem_hash_initializeD= 1;
|
||||
}
|
||||
Smem_record_itemS= value;
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
int Smem_is_recorded(ptr,flag)
|
||||
char *ptr;
|
||||
int flag;
|
||||
/*
|
||||
bit0= complain if return(0)
|
||||
*/
|
||||
{
|
||||
if(Smem_record_itemS==0)
|
||||
return(2);
|
||||
if(Smem_find_item(ptr,0)!=NULL)
|
||||
return(1);
|
||||
if(flag&1)
|
||||
Smem_protest("########### smem.c : free() of unrecorded pointer caught",0);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/* A simple C string cloner */
|
||||
int Smem_clone_string(ptr,text)
|
||||
char **ptr;
|
||||
char *text;
|
||||
{
|
||||
*ptr= Smem_malloC(strlen(text)+1);
|
||||
if(*ptr==NULL)
|
||||
return(-1);
|
||||
strcpy(*ptr,text);
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
/* ----------------- for usage via debugger commands --------------------- */
|
||||
|
||||
|
||||
/* find a certain memory item */
|
||||
struct SmemiteM *Smem_find_data(ptr)
|
||||
char *ptr;
|
||||
{
|
||||
return(Smem_find_item(ptr,0));
|
||||
}
|
||||
|
||||
|
||||
/* browsing the list */
|
||||
struct SmemiteM *Smem_fetch_item(step,flag)
|
||||
int step;
|
||||
int flag;
|
||||
/*
|
||||
bit0= reset cursor (and therefore address absolutely)
|
||||
*/
|
||||
{
|
||||
static struct SmemiteM *current= NULL;
|
||||
|
||||
if((flag&1)||current==NULL)
|
||||
current= Smem_start_iteM;
|
||||
if(step>0) {
|
||||
for(;current!=NULL;current= current->next) {
|
||||
if(step==0)
|
||||
return(current);
|
||||
step--;
|
||||
}
|
||||
} else if(step<0) {
|
||||
for(;current!=NULL;current= current->prev) {
|
||||
if(step==0)
|
||||
return(current);
|
||||
step++;
|
||||
}
|
||||
} else {
|
||||
return(current);
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
|
||||
int Smem_print_hash_counter() {
|
||||
int i;
|
||||
|
||||
for(i=0;i<Smem_hashsizE;i++)
|
||||
printf("%4d : %10.f\n",i,Smem_hash_counteR[i]);
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
/* delete all recorded memory items */
|
||||
int Smem_delete_all_items()
|
||||
{
|
||||
int ret;
|
||||
|
||||
while(Smem_start_iteM!=NULL) {
|
||||
ret= Smem_free(Smem_start_iteM->data);
|
||||
if(ret<=0)
|
||||
return(0);
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
165
libburn/branches/ZeroFourTwo/libcevap/smem.h
Normal file
165
libburn/branches/ZeroFourTwo/libcevap/smem.h
Normal file
@ -0,0 +1,165 @@
|
||||
|
||||
#ifndef Smem_includeD
|
||||
#define Smem_includeD
|
||||
|
||||
|
||||
/* compile time adjustable parameters : */
|
||||
|
||||
/* if not defined, flat malloc() and free() is used */
|
||||
#define Smem_own_functionS
|
||||
#ifdef Smem_no_own_functionS
|
||||
#undef Smem_own_functionS
|
||||
#endif /* Smem_no_own_functionS */
|
||||
|
||||
/* if not defined, the record items will be smaller by 8 byte
|
||||
but deletion of items may be much slower */
|
||||
#define Smem_with_hasH
|
||||
|
||||
|
||||
|
||||
struct SmemiteM {
|
||||
|
||||
char *data;
|
||||
size_t size;
|
||||
|
||||
struct SmemiteM *prev,*next;
|
||||
|
||||
struct SmemiteM *hash_prev,*hash_next;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef Smem_own_functionS
|
||||
|
||||
char *Smem_malloc();
|
||||
int Smem_free();
|
||||
|
||||
#define TSOB_FELD(typ,anz) (typ *) Smem_malloc((anz)*sizeof(typ));
|
||||
#define Smem_malloC Smem_malloc
|
||||
#define Smem_freE Smem_free
|
||||
|
||||
#else /* Smem_own_functionS */
|
||||
|
||||
#define TSOB_FELD(typ,anz) (typ *) malloc((anz)*sizeof(typ));
|
||||
#define Smem_malloC malloc
|
||||
#define Smem_freE free
|
||||
|
||||
#endif /* ! Smem_own_functionS */
|
||||
|
||||
int Smem_set_record_items();
|
||||
int Smem_stderr();
|
||||
int Smem_clone_string();
|
||||
|
||||
|
||||
#define Smem_hashsizE 251
|
||||
#define Smem_hashshifT 8
|
||||
|
||||
#ifdef Smem_included_by_smem_C
|
||||
|
||||
double Smem_malloc_counT= 0.0;
|
||||
double Smem_free_counT= 0.0;
|
||||
double Smem_pending_counT= 0.0;
|
||||
struct SmemiteM *Smem_start_iteM= NULL;
|
||||
struct SmemiteM *Smem_hasH[Smem_hashsizE];
|
||||
double Smem_hash_counteR[Smem_hashsizE];
|
||||
|
||||
/* these both init values are essential, since setting Smem_record_itemS=1
|
||||
by use of Smem_set_record_items() initializes the hash array
|
||||
(i do not really trust the compiler producers to have read K&R) */
|
||||
int Smem_hash_initializeD= 0;
|
||||
int Smem_record_itemS= 0;
|
||||
|
||||
double Smem_record_counT= 0.0;
|
||||
double Smem_record_byteS= 0.0;
|
||||
|
||||
#else /* Smem_included_by_smem_C */
|
||||
|
||||
extern double Smem_malloc_counT;
|
||||
extern double Smem_free_counT;
|
||||
extern double Smem_pending_counT;
|
||||
extern struct SmemiteM *Smem_start_iteM;
|
||||
extern struct SmemiteM *Smem_hasH[Smem_hashsizE];
|
||||
extern double Smem_hash_counteR[Smem_hashsizE];
|
||||
extern int Smem_hash_initializeD;
|
||||
extern int Smem_record_itemS;
|
||||
extern double Smem_record_counT;
|
||||
extern double Smem_record_byteS;
|
||||
|
||||
#endif /* ! Smem_included_by_smem_C */
|
||||
|
||||
|
||||
|
||||
#endif /* ! Smem_includeD */
|
||||
|
||||
|
||||
/*
|
||||
|
||||
smem
|
||||
|
||||
Functions to replace malloc() and free() in order to get more control
|
||||
over memory leaks or spurious errors caused by faulty usage of malloc()
|
||||
and free().
|
||||
|
||||
|
||||
Sourcecode provisions:
|
||||
|
||||
Use only the following macros for memory management:
|
||||
TSOB_FELD(type,count) creates an array of items of given type
|
||||
Smem_malloC() analogue of malloc()
|
||||
Smem_freE() analogue of free()
|
||||
One may #define malloc Smem_malloC resp. #define free Smem_freE
|
||||
but better would be to review (and often to streamline) the sourcecode
|
||||
in respect to those two functions.
|
||||
|
||||
|
||||
Speed versus control:
|
||||
|
||||
In production versions, where maximum speed is required, one may undefine
|
||||
the macro Smem_own_functionS in smem.h .
|
||||
This causes the above macros to directly invoke malloc() and free() without
|
||||
any speed reduction (and without any additional use).
|
||||
Undefinitio can be done globaly by modifying smem.h or locally by defining
|
||||
Smem_no_own_functionS before including smem.h .
|
||||
|
||||
If Smem_own_functionS remains defined, then the functions
|
||||
Smem_malloc()
|
||||
Smem_free()
|
||||
are used rather than malloc() and free().
|
||||
They count the number of calls to maintain a rough overview of memory usage.
|
||||
Smem_malloc() additionally checks for 0 size and Smem_free() checks for
|
||||
NULL pointers, which they both report to stderr. Eventually one should set
|
||||
a breakpoint in function Smem_protest() to learn about the origin of such
|
||||
messages.
|
||||
A status line may be obtained by Smem_report() or printed by Smem_stderr().
|
||||
|
||||
As long as the variable Smem_record_itemS is set to 0, there is not very much
|
||||
overhead compared with malloc() and free().
|
||||
If the variable is set to 1 by Smem_set_record_items() then all malloc()
|
||||
results are kept in a list where they will be deleted by their corresponding
|
||||
Smem_free() calls. If a pointer is to be freed, which is not recorded in the
|
||||
list then an error message will be printed to stderr. The memory will not
|
||||
be freed !
|
||||
This mode not only may be very slow, it also consumes at least 16 byte per
|
||||
piece of data which was obtained by malloc as long as it has not been freed.
|
||||
Due to the current nature of the list, large numbers of memory items are freed
|
||||
much faster in the reverse order of their creation. If there is a list of
|
||||
100000 strings to delete, it is very rewarding to free the youngest ones first.
|
||||
A shortcut via hashing is available but consumes 24 bytes rather than 16.
|
||||
(see above Smem_with_hasH )
|
||||
|
||||
The function Smem_is_recorded() can be used to check wether a pointer is
|
||||
valid according to the list. It returns :
|
||||
0 = is not in list , 1 = is in list , 2 = recording is off
|
||||
|
||||
If one decides to start recording malloc() results in the midst of a program
|
||||
run, one has to be aware of false protests of Smem_free() if a memory piece
|
||||
has been allocated before recording started. This will also cause those pieces
|
||||
to be memory leaks because Smem_free() refuses to delete them. (Freeing memory
|
||||
that was not obtained by malloc or was already freed previously can result in
|
||||
deferred SIGSEGV or similar trouble, depending on OS and library.)
|
||||
Also in that case one should stop recording before ending the program, to
|
||||
avoid a lot of false complaints about longliving memory objects.
|
||||
|
||||
*/
|
Reference in New Issue
Block a user