(7)proto.h:dbm例程的所有函数原型声明。包括内部接口和gdbm的用户接口。ndbm和dbm的兼容性实现也要用到这里的各个函数。这些函数的功能在具体的源代码解剖时会有详细说明。注意一些老式的非标准的C编译器中函数声明不能带参数列表,而标准的C编译器中函数声明必须带参数列表。为了兼容性,这里把函数的参数列表arg(包括函数名后面的括号)抽离出来定义成宏__P(arg),当编译器是标准编译器时(用标准C编译器内部定义的__STDC__宏来指定),__P(arg)被展开成arg,从而带参数列表。当编译器是非标准编译器时,__P(arg)被展开成(),从而不带参数列表。

/* proto.h - dbm例程的原型(所有函数原型) */
#ifndef __P
#ifdef __STDC__
#define __P(args) args
#else
#define __P(args) ()
#endif
#endif
/* 来自于bucket.c */
void _gdbm_new_bucket    __P((gdbm_file_info *, hash_bucket *, int));
void _gdbm_get_bucket    __P((gdbm_file_info *, int));
void _gdbm_split_bucket  __P((gdbm_file_info *, int));
void _gdbm_write_bucket  __P((gdbm_file_info *, cache_elem *));
/* 来自于falloc.c */
off_t _gdbm_alloc       __P((gdbm_file_info *, int));
void _gdbm_free         __P((gdbm_file_info *, off_t, int));
int  _gdbm_put_av_elem  __P((avail_elem, avail_elem [], int *, int));
/* 来自于findkey.c */
char *_gdbm_read_entry  __P((gdbm_file_info *, int));
int _gdbm_findkey       __P((gdbm_file_info *, datum, char **, int *));
/* 来自于hash.c */
int _gdbm_hash __P((datum));
/* 来自于update.c */
void _gdbm_end_update   __P((gdbm_file_info *));
void _gdbm_fatal         __P((gdbm_file_info *, char *));
/* 来自于gdbmopen.c */
int _gdbm_init_cache    __P((gdbm_file_info *, int));
/* 用户可以调用的例程(函数).... */
void  gdbm_close      __P((gdbm_file_info *));
int   gdbm_delete     __P((gdbm_file_info *, datum));
datum gdbm_fetch      __P((gdbm_file_info *, datum));
gdbm_file_info *gdbm_open __P((char *, int, int, int, void (*) (void)));
int   gdbm_reorganize     __P((gdbm_file_info *));
datum gdbm_firstkey       __P((gdbm_file_info *));
datum gdbm_nextkey        __P((gdbm_file_info *, datum));
int   gdbm_store          __P((gdbm_file_info *, datum, datum, int));
int   gdbm_exists     __P((gdbm_file_info *, datum));
void  gdbm_sync       __P((gdbm_file_info *));
int   gdbm_setopt     __P((gdbm_file_info *, int, int *, int));
int   gdbm_fdesc      __P((gdbm_file_info *));

(8)ndbm.h:ndbm用户要包含的头文件。包含dbm_store操作的参数标识、datum结构、DBM结构、ndbm的所有用户接口声明,其中dbm_error和dbm_clearerr是用宏来定义的。

/* ndbm.h  -  ndbm用户要包含的头文件  */
/* 用dbm_store作简单地插入或覆盖操作时的参数 */
#define  DBM_INSERT  0
#define  DBM_REPLACE 1
/* 数据和关键字的结构,本定义具有兼容性 */
typedef struct {char *dptr;int   dsize;} datum;
/* 文件信息头 */
typedef struct {int dummy[10];} DBM;
/* ndbm的所有用户接口声明,有些是用宏来定义 */
extern DBM  *dbm_open ();
extern void  dbm_close ();
extern datum     dbm_fetch ();
extern int   dbm_store ();
extern int   dbm_delete ();
extern int   dbm_delete ();
extern datum     dbm_firstkey ();
extern datum     dbm_nextkey ();
#define      dbm_error(dbf)  (0)
#define      dbm_clearerr(dbf)
extern int   dbm_dirfno ();
extern int   dbm_pagfno ();
extern int   dbm_rdonly ();

(9)dbm.h:dbm用户要包含的头文件。包含datum结构、dbm的所有用户接口声明。

/* dbm.h  - dbm用户要包含的头文件  */
/* 数据和关键字的结构,本定义具有兼容性 */
typedef struct {char *dptr;int   dsize;} datum;
/* dbm的所有用户接口声明 */
extern int  dbminit ();
extern datum    fetch ();
extern int  store ();
extern int  delete ();
extern int  delete ();
extern datum    firstkey ();
extern datum    nextkey ();
extern int  dbmclose ();

(10)gdbm.proto和gdbm.proto2:编译时会合并成gdbm.h头文件,这是gdbm用户要包含的头文件。其中gdbm.proto2只包含了一个用户接口声明,其余都在gdbm.proto中(记录错误码的全局变量在gdbmerrno.h中,编译时会复制到gdbm.h中)。包含了各个操作的参数标识、datum结构、GDBM_FILE结构、gdbm的所有用户接口声明。注意其中的预编译格式
#ifdef __cplusplus
  extern "C" {
#endif

//一段代码,或者一系列函数原型声明

#ifdef __cplusplus
}
#endif
   这里__cplusplus是C++编译器中的内部定义的宏,C编译器中没有这个宏。这个格式的含义是:如果这是一段C++的代码(即用C++编译器来编译),那么加入extern "C"{...}处理其中的代码。即用C语言的方式来处理其中的代码。这主要是因为C++和C对产生的函数名字的处理是不一样的。C语言中没有重载函数的概念,所以C编译器编译的程序里,所有函数只有函数名对应的入口。而由于 C++语言有重载函数的概念,如果只有函数名对应入口,则会出现混淆。所以C++编译器编译的程序,应该是用函数名加参数类型列表来对应到入口,有时还包括返回类型等(从其生成的汇编代码中可以看出来,用gcc试试就可以知道了)。当我们在C++中要使用一个用C语言编写的库时,编译时是使用C++的方式来处理你的代码中用到的C函数,但是实际上链接的库文件却是用C的方式来处理函数的,这样经常会出现链接过不去的错误,因为链接器找不到函数。上面的extern "C"就是告诉C++编译器,这是一个用C写成的库文件,请用C的方式来链接它们。总之,当我们用C语言开发项目时,若希望用户在老式的非标准的C编译器,或者在C++中也能使用它们时,特别注意在导出的头文件中要使用__P宏、_cplusplus宏、extern"C"等。

/* gdbm.proto  -  gdbm用户要包含的头文件,会被编译到gdbm.h中去  */
/* 多重包含时的保护符 */
#ifndef _GDBM_H_
#define _GDBM_H_
/* gdbm_open操作的参数标识 */
#define  GDBM_READER  0     /* 只读 */
#define  GDBM_WRITER  1     /* 可读可写,但不能创建 */
#define  GDBM_WRCREAT 2     /* 如果没有发现,则创建db(可写) */
#define  GDBM_NEWDB   3     /* 总是创建新的db(可写) */
#define  GDBM_FAST    0x10  /* 快速写入!=> 没有fsyncs时。已经过时了 */
#define  GDBM_SYNC    0x20  /* 对磁盘的同步操作(sync),即将所有未写的系统缓冲区写到磁盘中 */
#define  GDBM_NOLOCK  0x40  /* 不对文件做锁定操作 */
/* gdbm_store的参数,这个函数用来插入数据或覆盖已有的数据(当给定的关键字在数据库中已经存在时) */
#define  GDBM_INSERT  0     /* 不覆盖数据库中的数据 */
#define  GDBM_REPLACE 1     /* 用新值覆盖已有的值 */
/* gdbm_setopt的参数,这个函数用来指定要执行的操作类型 */
#define  GDBM_CACHESIZE 1       /* 设置缓存大小 */
#define  GDBM_FASTMODE  2       /* 打开或关闭快速模式,已经过时 */
#define  GDBM_SYNCMODE  3   /* 打开或关闭同步操作(sync) */
#define  GDBM_CENTFREE  4   /* 保持文件头中的所有空闲数据块 */
#define  GDBM_COALESCEBLKS 5    /* 试着合并空闲数据块 */
/* 数据和关键字的结构,本定义具有兼容性 */
typedef struct {char *dptr;int   dsize;} datum;
/* 文件信息头 */
typedef struct {int dummy[10];} *GDBM_FILE;
/* 确定C(++)编译器是否需要完整的函数原型声明  */
#ifndef __P
#if defined(__STDC__) || defined(__cplusplus) || defined(c_plusplus)
#define __P(x) x
#else
#define __P(x) ()
#endif
#endif
/* 外部变量,存放gdbm的版本信息 */
extern char *gdbm_version;  /* GDBM的C++支持 */
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
/* 下面是所有的例程集 */
extern GDBM_FILE gdbm_open __P((char *, int, int, int, void (*)()));
extern void gdbm_close __P((GDBM_FILE));
extern int gdbm_store __P((GDBM_FILE, datum, datum, int));
extern datum gdbm_fetch __P((GDBM_FILE, datum));
extern int gdbm_delete __P((GDBM_FILE, datum));
extern datum gdbm_firstkey __P((GDBM_FILE));
extern datum gdbm_nextkey __P((GDBM_FILE, datum));
extern int gdbm_reorganize __P((GDBM_FILE));
extern void gdbm_sync __P((GDBM_FILE));
extern int gdbm_exists __P((GDBM_FILE, datum));
extern int gdbm_setopt __P((GDBM_FILE, int, int *, int));
extern int gdbm_fdesc __P((GDBM_FILE));
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif
/* gdbm.proto2 - 额外的函数原型声明,会被编译到gdbm.h中去 */
/* GDBM的C++支持 */
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
extern char *gdbm_strerror __P((gdbm_error));
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif
#endif

(11)getopt.h:包含了getopt、getopt_long、getopt_long_only函数,以及一个内部使用的函数_getopt_internal。getopt用来解析命令行的选项,在POSIX对它有详细的规范。它处理短选项,即“-c value“的格式,c是单个字符的短选项名,value是这个选项关联的值,多个短选项可以合并在一块(从而可有多个字符,但每个字符都是一个选项)。循环调用getopt就可以依次得到每个选项。getopt返回agrv数组中的下一个选项字符,遇到未知选项时,getopt返回问号(?),并把它保存到optopt中;遇到需要关联值的选项但未提供关联值时,getopt返回冒号(:)。外部变量optarg保存当前处理的选项的关联值(如果有的话);optind保存第一个非选项的索引;遇到未知选项时opterr会变成非零值,getopt就会向stderr打印一条错误信息;未知选项保存在optopt中。对GNU版本的getopt,在扫描命令行时,每处理完一个选项,就会重写argv数组,把所有非选项都集中在一起,到最后处理完所有选项后,argv数组只会保存各个非选项的字符串,从argv[optind]开始可以访问这些非选项的字符串。
   getopt_long和getopt_long_only是GNU对getopt的扩展,它支持处理长选项,即“--string=value”,string是长选项名(是一个字符串),value是其关联的值。
   getopt系列函数现在已经成为了C函数库的一部分,在Linux等现代的类UNIX系统中都有提供。getopt在<unistd.h>中 。作为扩展的getopt_long、getopt_long_only等在<getopt.h>中,且使用时必须包含有#define _GNU_SOURCE,还需要用到struct option结构。这里提供getopt.h及其源代码实现getopt.c只是为了向后兼容(因为以前的UNIX系统可能并没有提供这些设施)。因此这里并不准备对它们进行解剖。

转载于:https://my.oschina.net/abcijkxyz/blog/723150

dbm数据库源代码分析(4):头文件部分(续)相关推荐

  1. dbm数据库源代码分析(3):头文件部分

    现在解剖gdbm的头文件部分的源码.    (1)autoconf.h:由configure脚本根据autoconf.h.in模板生成.autoconf.h为平台相关的的头文件.函数.库等定义常量标志 ...

  2. 结合编译过程,分析C++头文件和源文件的区别

    编译过程 简单的说其实要理解C文件与头文件(即.h)有什么不同之处,首先需要弄明白编译器的工作过程,一般说来编译器会做以下几个过程: 预处理阶段 词法与语法分析阶段 编译阶段,首先编译成纯汇编语句,再 ...

  3. linux关机机器语言,Linux 核心源代码分析 - 第十章 开机 关机 [续二] [超星]...

    版权声明:本文档录自超星阅览器"免费图书馆"中的<Linux 核心源代码分析>.原文为扫描版,本文本文档是在下(大天赐)[http://blog.sina.com.cn ...

  4. Mysql源代码分析系列

    Mysql源代码分析系列(2): 源代码结构 Mysql源代码主要包括客户端程序代码,服务器端代码,测试工具和一些库构成,下面我们对比较重要的目录做些介绍. BUILD 这个目录在本系列的上篇文章中我 ...

  5. YCM代码补全插件找不到c++头文件

    开发环境: Ubuntu22.04 LTS x86_64架构Intel CPU YCM(YouCompleteMe)是一款用于vim编辑器的强大代码补全插件. YCM提供许多强大功能: 代码补全: 语 ...

  6. C++:include:理解 C++ 中的头文件和源文件的作用

    关于头文件和源文件我们主要围绕: C++编译模式, 声明和定义区别, 符号只能被定义一次, 符号被定义在多个源文件,但是一个源文件只能定义一次 这四个方面来分析论述 1:C++ 编译模式 在一个C++ ...

  7. C++ 笔记(25)— 理解 C++ 中的头文件和源文件的作用

    1. C++ 编译模式 通常,在一个 C++ 程序中,只包含两类文件: .cpp 文件,被称作 C++ 源文件,里面放的都是 C++ 的源代码 .h 文件,被称作 C++ 头文件,里面放的也是 C++ ...

  8. C++之头文件与源文件

    (转) 一.C++编译模式     通常,在一个C++程序中,只包含两类文件--.cpp文件和.h文件.其中,.cpp文件被称作C++源文件,里面放的都是C++的源代码:而.h文件则被称作C++头文件 ...

  9. Linux的目录结构和头文件相关;哪里找- sys/types.h, sys/stat.h

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/qq_29757283/article/ ...

最新文章

  1. #舍得Share#Flash Media Server4.5迅雷高速下载地址by lwxshow
  2. Chrome中的from memory cache与from disk cache
  3. HDU 3537 Daizhenyang's Coin
  4. Python之PIL库
  5. (7) hibernate之级联cascade和关系维持inverse
  6. 【python】pycharm启动 一直index,无法运行
  7. linux python复制安装,复制一个Python全部环境到另一个环境,python另一个,导出此环境下安装的包...
  8. pythonjava app切出后无网络连接_写了一个java的Server 用python的client访问却访问不通问题。...
  9. IC卡应用系统开发-(一)卡片读写
  10. 《Android移动应用开发》 复习题(一)
  11. 各个行业的前端静态页面模板
  12. Speed Gear(变速精灵XP) V6.0 - 免费版,破解版,绿色版
  13. xp 游戏计算机没有了怎么办,我的xp系统没有自带游戏怎么办
  14. STM32 自定义串口协议
  15. 微信小程序-image标签
  16. Windows Server2012搭建邮件服务器
  17. 解决stm32下载错误 “Could not stop Cortex-M device.Please check the JTAG cable.“
  18. 安装dreamwaver
  19. 公司新加了一台友宝自动售货机引发的思考-适配器模式
  20. Python使用pngquant实现批量压缩图片

热门文章

  1. 虚拟机 Centos8 服务器密码忘了
  2. 手把手教你编写一个音乐播放器
  3. 大型网站解决方案技术
  4. iOS-Xcode Archive 不生成dsym文件的解决方法
  5. 如何给电脑安装Windows双系统
  6. APP稀有资源及19种无需编程的App创建工具
  7. 深度学习——神经网络的种类(前馈神经网络,反馈神经网络,图网络)
  8. 实验1-2 Welcome to You! (5 分)
  9. 互联网运营平台指标体系_分享 :滴滴数据仓库指标体系建设实践
  10. Modelsim SE-64 10.4建立UVM环境