473,606 Members | 3,100 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

GDBM prototype magic.

Hi Guys,

I was going through gdbm-1.8.3 source (http://ftp.gnu.org/gnu/gdbm/
gdbm-1.8.3.tar.gz) and found this strange thing : all the exposed
functions of gdbm work with GDBM_FILE pointer (which is returned by
gdbm_open), but in the implementation of gdbm functions (e.g.
gdbm_open in gdbmopen.c)work with a structure called gdbm_file_info.

Now GDBM_FILE is defined like this in gdbm.h an exposed header :

typedef struct { int dummy[10];} *GDBM_FILE;

but gdbm_file_info is a structure which is a lot bigger than this.

For e.g. in gdbm.h gdbm_open is defined as :

extern int gdbm_store __P((GDBM_FILE, datum, datum, int)); /* __P(x)
is x if it is standard C or C++ else _P(x) is () */

but in its definition it is like this :

int
gdbm_store (dbf, key, content, flags)
gdbm_file_info *dbf;
datum key;
datum content;
int flags;

I have these questions : (I searched previous archives of c.l.c, but
only found mention of typedef struct {int dummy[10];} *GDBM_FILE; in a
post called "What makes C _not_ a subset of C++, where it said that
this particular declaration is illegal in C++)

1. How does this sort of code compiles in standard C ? ( What function
prototype matching rule of C applies here ?) When I checked in the
generated Makefile there wasn't any special flags that were passed to
gcc.

2. Why was this done ? My first guess is because the author did not
want to expose the gdbm_file_info structure in gdbm.h so that he can
change it between different releases preserving compatibility (?) Also
to keep the external interface clean.

3. Is this safe ? Will it work in all the compilers and machines i.e.
is it portable ?

Any help is appreciated.
Jun 27 '08 #1
4 1894
vshenoy wrote:
Hi Guys,

I was going through gdbm-1.8.3 source (http://ftp.gnu.org/gnu/gdbm/
gdbm-1.8.3.tar.gz) and found this strange thing : all the exposed
functions of gdbm work with GDBM_FILE pointer (which is returned by
gdbm_open), but in the implementation of gdbm functions (e.g.
gdbm_open in gdbmopen.c)work with a structure called gdbm_file_info.

Now GDBM_FILE is defined like this in gdbm.h an exposed header :

typedef struct { int dummy[10];} *GDBM_FILE;

but gdbm_file_info is a structure which is a lot bigger than this.

For e.g. in gdbm.h gdbm_open is defined as :

extern int gdbm_store __P((GDBM_FILE, datum, datum, int)); /* __P(x)
is x if it is standard C or C++ else _P(x) is () */

but in its definition it is like this :

int
gdbm_store (dbf, key, content, flags)
gdbm_file_info *dbf;
datum key;
datum content;
int flags;

I have these questions : (I searched previous archives of c.l.c, but
only found mention of typedef struct {int dummy[10];} *GDBM_FILE; in a
post called "What makes C _not_ a subset of C++, where it said that
this particular declaration is illegal in C++)

1. How does this sort of code compiles in standard C ? ( What function
prototype matching rule of C applies here ?) When I checked in the
generated Makefile there wasn't any special flags that were passed to
gcc.
The function definition and its declaration are not match, this behavior
should be undefined.

This can work because the linker will not check the prototype.
>
2. Why was this done ? My first guess is because the author did not
want to expose the gdbm_file_info structure in gdbm.h so that he can
change it between different releases preserving compatibility (?) Also
to keep the external interface clean.
Check the source code or ask the author directly. ;)
3. Is this safe ? Will it work in all the compilers and machines i.e.
is it portable ?
No, it's not a good hack.

--
Hi, I'm a .signature virus, please copy/paste me to help me spread
all over the world.
Jun 27 '08 #2
On Mon, 21 Apr 2008 00:35:50 -0700 (PDT), vshenoy
<vi************ *@gmail.comwrot e:
>Hi Guys,

I was going through gdbm-1.8.3 source (http://ftp.gnu.org/gnu/gdbm/
gdbm-1.8.3.tar.gz) and found this strange thing : all the exposed
functions of gdbm work with GDBM_FILE pointer (which is returned by
gdbm_open), but in the implementation of gdbm functions (e.g.
gdbm_open in gdbmopen.c)work with a structure called gdbm_file_info.

Now GDBM_FILE is defined like this in gdbm.h an exposed header :

typedef struct { int dummy[10];} *GDBM_FILE;

but gdbm_file_info is a structure which is a lot bigger than this.
Nowhere in the discussion below is there any indication of what a
gdbm_file_info looks like. Where do you get the idea it is bigger
than 10 int?
>
For e.g. in gdbm.h gdbm_open is defined as :

extern int gdbm_store __P((GDBM_FILE, datum, datum, int)); /* __P(x)
is x if it is standard C or C++ else _P(x) is () */
Why show us gdbm_store when your question is about gdbm_open?

This is not a definition. It is a declaration (also known as a
prototype). It serves two purposes: 1) to let the compiler check on
(and possibly convert) the arguments you pass, and 2) to let the
compiler generate code to use the return value.
>
but in its definition it is like this :

int
gdbm_store (dbf, key, content, flags)
gdbm_file_info *dbf;
datum key;
datum content;
int flags;
Technically, this definition is inconsistent with the prototype. If
gdbm.h is not included in this source module, the compiler will not
know about the inconsistency. The linker never cares about arguments.
At the code level, there is no problem if gdbm_file_info is also a
structure because all pointers to structure have the same size and
representation.

This is a very old style function definition (pre-C89). While it is
still legal, it is a strong hint that you are looking at code that
predates the standard.
>
I have these questions : (I searched previous archives of c.l.c, but
only found mention of typedef struct {int dummy[10];} *GDBM_FILE; in a
post called "What makes C _not_ a subset of C++, where it said that
this particular declaration is illegal in C++)
It's off-topic but I wonder why unless one of the tokens is a reserved
word.
>
1. How does this sort of code compiles in standard C ? ( What function
prototype matching rule of C applies here ?) When I checked in the
generated Makefile there wasn't any special flags that were passed to
gcc.
Is gdbm.h included in the source module that contains gdbm_store? If
not, there is no prototype to match.
>
2. Why was this done ? My first guess is because the author did not
want to expose the gdbm_file_info structure in gdbm.h so that he can
change it between different releases preserving compatibility (?) Also
to keep the external interface clean.
Not uncommon but remember how old this is.
>
3. Is this safe ? Will it work in all the compilers and machines i.e.
is it portable ?
You would not normally be compiling gdbm_store. It would be in a
library that would be used by the linker to resolve your references to
it. As explained above, while their is an inconsistency it is not the
type to manifest as an error in your generated code.

I would expect it to work only on those systems for which gdbm-1.8.3
is designed. Does gnu work on Windows also or is it limited to Unix?
Does gdbm_open eventually call fopen or does it use system specific
tricks to open the file? If the latter, I would be surprised if it
worked at all on my IBM mainframe.
Remove del for email
Jun 27 '08 #3
Hi Barry,
Nowhere in the discussion below is there any indication of what a
gdbm_file_info looks like. Where do you get the idea it is bigger
than 10 int?
This is the definition of gdbm_file_info (comments removed) :

typedef struct {
char *name;
int read_write;
int fast_write;
int central_free;
int coalesce_blocks ;
int file_locking;
void (*fatal_err) ();
int desc;
gdbm_file_heade r *header;
off_t *dir;
cache_elem *bucket_cache;
int cache_size;
int last_read;
hash_bucket *bucket;
int bucket_dir;
cache_elem *cache_entry;
char header_changed;
char directory_chang ed;
char bucket_changed;
char second_changed;
} gdbm_file_info;

with some of the compound structures themselves being more than 10
bytes. It is defined in gdbmdefs.h. Also in the same header file
included is header called "proto.h" which is somewhat similar to the
exposed gdbm.h except that it uses gdbm_file_info instead of GDBM_FILE
*
>
For e.g. in gdbm.h gdbm_open is defined as :
extern int gdbm_store __P((GDBM_FILE, datum, datum, int)); /* __P(x)
is x if it is standard C or C++ else _P(x) is () */

This is not a definition. It is a declaration (also known as a
prototype). It serves two purposes: 1) to let the compiler check on
(and possibly convert) the arguments you pass, and 2) to let the
compiler generate code to use the return value.
I am sorry. It should have been "declared as" instead of "defined as".
Why show us gdbm_store when your question is about gdbm_open?
Sorry again for context switching so fast. Basically what I wanted to
say is all the exposed functions (like gdbm_store) work with GDBM_FILE
*, which is returned by gdbm_open, where as internally (in the source
code) all functions receive gdbm_file_info as arguments returned by
gdbm_open in place of GDBM_FILE *
but in its definition it is like this :
int
gdbm_store (dbf, key, content, flags)
gdbm_file_info *dbf;
datum key;
datum content;
int flags;

Technically, this definition is inconsistent with the prototype. If
gdbm.h is not included in this source module, the compiler will not
know about the inconsistency. The linker never cares about arguments.
That is a good point. The source code doesn't include gdbm.h anywhere.
In fact gdbm.h is generated as a part of build process from files
called gdbm.proto and gdbm.proto2.
At the code level, there is no problem if gdbm_file_info is also a
structure because all pointers to structure have the same size and
representation.
Exactly. My question is that is this a portable behavior ? Can we rely
on compiler silently converting back and forth between gdbm_file_info
* and GDBM_FILE * ?
>
Is gdbm.h included in the source module that contains gdbm_store? If
not, there is no prototype to match.
Like I said above, no.
>
2. Why was this done ? My first guess is because the author did not
want to expose the gdbm_file_info structure in gdbm.h so that he can
change it between different releases preserving compatibility (?) Also
to keep the external interface clean.

Not uncommon but remember how old this is.
Actually this is the latest gdbm version.
You would not normally be compiling gdbm_store. It would be in a
library that would be used by the linker to resolve your references to
it. As explained above, while their is an inconsistency it is not the
type to manifest as an error in your generated code.
I was surprised seeing this kind of code in one of the most widely
used database libraries.
I would expect it to work only on those systems for which gdbm-1.8.3
is designed. Does gnu work on Windows also or is it limited to Unix?
It works on windows according to this page :

http://gnuwin32.sourceforge.net/packages/gdbm.htm
Does gdbm_open eventually call fopen or does it use system specific
tricks to open the file? If the latter, I would be surprised if it
worked at all on my IBM mainframe.
It uses open(2) for opening the file.
Jun 27 '08 #4
On Mon, 21 Apr 2008 08:23:19 -0700 (PDT), vshenoy
<vi************ *@gmail.comwrot e:
>Hi Barry,
>Nowhere in the discussion below is there any indication of what a
gdbm_file_in fo looks like. Where do you get the idea it is bigger
than 10 int?

This is the definition of gdbm_file_info (comments removed) :

typedef struct {
char *name;
int read_write;
int fast_write;
int central_free;
int coalesce_blocks ;
int file_locking;
void (*fatal_err) ();
int desc;
gdbm_file_heade r *header;
off_t *dir;
cache_elem *bucket_cache;
int cache_size;
int last_read;
hash_bucket *bucket;
int bucket_dir;
cache_elem *cache_entry;
char header_changed;
char directory_chang ed;
char bucket_changed;
char second_changed;
} gdbm_file_info;

with some of the compound structures themselves being more than 10
bytes. It is defined in gdbmdefs.h. Also in the same header file
included is header called "proto.h" which is somewhat similar to the
exposed gdbm.h except that it uses gdbm_file_info instead of GDBM_FILE
*
>>
>For e.g. in gdbm.h gdbm_open is defined as :
>extern int gdbm_store __P((GDBM_FILE, datum, datum, int)); /* __P(x)
is x if it is standard C or C++ else _P(x) is () */

This is not a definition. It is a declaration (also known as a
prototype). It serves two purposes: 1) to let the compiler check on
(and possibly convert) the arguments you pass, and 2) to let the
compiler generate code to use the return value.

I am sorry. It should have been "declared as" instead of "defined as".
>Why show us gdbm_store when your question is about gdbm_open?

Sorry again for context switching so fast. Basically what I wanted to
say is all the exposed functions (like gdbm_store) work with GDBM_FILE
*, which is returned by gdbm_open, where as internally (in the source
code) all functions receive gdbm_file_info as arguments returned by
gdbm_open in place of GDBM_FILE *
>but in its definition it is like this :
>int
gdbm_store (dbf, key, content, flags)
gdbm_file_info *dbf;
datum key;
datum content;
int flags;

Technically, this definition is inconsistent with the prototype. If
gdbm.h is not included in this source module, the compiler will not
know about the inconsistency. The linker never cares about arguments.

That is a good point. The source code doesn't include gdbm.h anywhere.
In fact gdbm.h is generated as a part of build process from files
called gdbm.proto and gdbm.proto2.
>At the code level, there is no problem if gdbm_file_info is also a
structure because all pointers to structure have the same size and
representation .

Exactly. My question is that is this a portable behavior ? Can we rely
on compiler silently converting back and forth between gdbm_file_info
* and GDBM_FILE * ?
No. The compiler is not silently converting back and forth. In your
code, it is generating an argument of type GDBM.FILE (which is already
a pointer to struct so we don't put an asterisk after it). This is
the argument that will be passed during execution. The library
function will take this argument and treat it as a gdbm_file_info* .
The library function is allowed to do this (more correctly, will get
away with doing this) because the two pointer types are guaranteed to
have the same size and representation. Your code cannot set or
reference the members of the struct (by convention). Nor can it
create an object of this type (the struct has no tag and the typedef
defines only a pointer to struct type). Consequently, you don't
really care how big the struct really is or how badly the typedef
mismatches the actual struct contents.
>
>>
Is gdbm.h included in the source module that contains gdbm_store? If
not, there is no prototype to match.

Like I said above, no.
>>
>2. Why was this done ? My first guess is because the author did not
want to expose the gdbm_file_info structure in gdbm.h so that he can
change it between different releases preserving compatibility (?) Also
to keep the external interface clean.

Not uncommon but remember how old this is.

Actually this is the latest gdbm version.
That may be but the presence of a K&R style function definition
indicates this is old code being carried forward.
>
>You would not normally be compiling gdbm_store. It would be in a
library that would be used by the linker to resolve your references to
it. As explained above, while their is an inconsistency it is not the
type to manifest as an error in your generated code.

I was surprised seeing this kind of code in one of the most widely
used database libraries.
>I would expect it to work only on those systems for which gdbm-1.8.3
is designed. Does gnu work on Windows also or is it limited to Unix?

It works on windows according to this page :

http://gnuwin32.sourceforge.net/packages/gdbm.htm
>Does gdbm_open eventually call fopen or does it use system specific
tricks to open the file? If the latter, I would be surprised if it
worked at all on my IBM mainframe.
It uses open(2) for opening the file.
That is not a C standard function. I believe it's posix so it
probably only works on systems which have some extension method that
adds the posix function headers and libraries.
Remove del for email
Jun 27 '08 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
3338
by: Fortepianissimo | last post by:
First off I know I can install the latest python from Fink quite easily and it'll give me everything needed. But I'm trying to distribute my python app to end users who don't really care (or know) anything about Fink. The default Python on Mac OS X is 2.3 but doesn't come with gdbm. Did anyone try to get the source of gdbm and build it, and somehow built the gdbm module for Python on Mac OS X? If so could you share a few hints? It'll...
1
4096
by: Ed | last post by:
I am trying to use a Perl script which requires a Database module other than "dbm" to be the default Mod. So, what the script is checking is import anydbm if (anydbm._defaultmod.__name__ == 'dumbdbm' or anydbm._defaultmod.__name__ == 'dbm'): First of, I'm doing this on a Sparc/Solaris 8 box. So, I'm trying to get gdbm to be the default mod. I've downloaded and
3
1161
by: jyang825 | last post by:
Hi all, I was hoping I could do something like this in JavaScript: var a = {x:1, y:2}; var b = {x:2, z:3}; b.prototype = a; And then:
31
3103
by: Tony | last post by:
I just noticed that prototype.js is one of the files in the Ajax.NET distribution - I'm pretty concerned about this. Does anyone know if this is the same "prototype.js" that is not well-liked around here? If so, do you know if Ajax.NET can be used without prototype.js? -- "The most convoluted explanation that fits all of the made-up facts is the most likely to be believed by conspiracy theorists. Fitting the
1
1773
by: brokow | last post by:
I have been trying to get the gdbm module in python 2.4 to read a gdbm file from python 1.5.2 and having no luck. I get a file error when I try to open the 1.5.2-created gdbm file. Even a very simple gdbm database causes the trouble. E.g. I create a one-entry db in python 1.5.2 Python 1.5.2 (#0, Apr 13 1999, 10:51:12) on win32 Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam >>> import gdbm >>> db2 =...
0
873
by: Laszlo Nagy | last post by:
Hi All, gdbm objects have a "firstkey" and a "nextkey" method. So if I want iterate through the keys (which I often do) then I have to do this: def itergdbmkeys(gdbm_obj): key = gdbm_obj.firstkey() if key is None: raise StopIteration yield key
2
1223
by: Shriphani | last post by:
dictionary = gdbm.open('dictionary','c') dictionary = 'Openbox' dictionary.get('Ellipsize') the last line generates an attribute error. Can someone tell me what I am doing wrong? Regards, Shriphani Palakodety
0
1027
by: Douglas Applegate | last post by:
Hi- I am having a problem with shelve. The problem I think is really with gdbm. I'll write out a file using shelve/gdbm on an amd64 machine and then I'll try to read it in on a i386 machine. The result is a 'gdbm fatal: read error.' Reversing directions results in the same problem. Below are two small programs that get at the heart of the problem: #test.py############## #!/usr/bin/env python
2
1982
by: RayOsborn | last post by:
I have some old "shelve" databases created in Python 2.2 that use the old bsddb format, whereas the version of Python 2.4 installed by my web hosting service doesn't have bsddb available at all (or at least, it has, but probably not linked properly to the more recent Sleepy Cat versions of the Berkeley DB - it fails to import _bsddb). Currently, I have to put python2.2 in my shebangs to get the cgi scripts to run at all. The question is...
0
8036
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8461
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
8317
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
6796
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
5470
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
3948
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4010
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
1572
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
1313
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.