1#!/bin/sh -
2#
3# See the file LICENSE for redistribution information.
4#
5# Copyright (c) 1996-2009 Oracle.  All rights reserved.
6#
7# $Id$
8#
9
10# This awk script generates all the log, print, and read routines for the DB
11# logging. It also generates a template for the recovery functions (these
12# functions must still be edited, but are highly stylized and the initial
13# template gets you a fair way along the path).
14#
15# For a given file prefix.src, we generate a file prefix_auto.c, and a file
16# prefix_auto.h that contains:
17#
18#	external declarations for the file's functions
19# 	defines for the physical record types
20#	    (logical types are defined in each subsystem manually)
21#	structures to contain the data unmarshalled from the log.
22#
23# This awk script requires that four variables be set when it is called:
24#
25#	source_file	-- the C source file being created
26#	header_file	-- the C #include file being created
27#	template_file	-- the template file being created
28#
29# And stdin must be the input file that defines the recovery setup.
30#
31# Within each file prefix.src, we use a number of public keywords (documented
32# in the reference guide) as well as the following ones which are private to
33# DB:
34# 	DBPRIVATE	Indicates that a file will be built as part of DB,
35#			rather than compiled independently, and so can use
36#			DB-private interfaces (such as DB_LOG_NOCOPY).
37#	DB		A DB handle.  Logs the dbreg fileid for that handle,
38#			and makes the *_log interface take a DB * instead of a
39#			DB_ENV *.
40#	PGDBT		Just like DBT, only we know it stores a page or page
41#			header, so we can byte-swap it (once we write the
42#			byte-swapping code, which doesn't exist yet).
43#	LOCKS		Just like DBT, but uses a print function for locks.
44
45BEGIN {
46	if (source_file == "" ||
47	    header_file == "" || template_file == "") {
48	    print "Usage: gen_rec.awk requires three variables to be set:"
49	    print "\theader_file\t-- the recover #include file being created"
50	    print "\tprint_file\t-- the print source file being created"
51	    print "\tsource_file\t-- the recover source file being created"
52	    print "\ttemplate_file\t-- the template file being created"
53	    exit
54	}
55	FS="[\t ][\t ]*"
56	CFILE=source_file
57	HFILE=header_file
58	PFILE=print_file
59	TFILE=template_file
60
61	# These are the variables we use to create code that calls into
62	# db routines and/or uses an environment.
63	dbprivate = 0
64	env_type = "DB_ENV"
65	env_var = "dbenv"
66	log_call = "dbenv->log_put"
67
68}
69/^[ 	]*DBPRIVATE/ {
70	dbprivate = 1
71	env_type = "ENV"
72	env_var = "env"
73	log_call = "__log_put"
74}
75/^[ 	]*PREFIX/ {
76	prefix = $2
77	num_funcs = 0;
78
79	# Start .c files.
80	printf("/* Do not edit: automatically built by gen_rec.awk. */\n\n")\
81	    > CFILE
82	printf("#include \"db_config.h\"\n") >> CFILE
83	if (!dbprivate) {
84		printf("#include <errno.h>\n") >> CFILE
85		printf("#include <stdlib.h>\n") >> CFILE
86		printf("#include <string.h>\n") >> CFILE
87		printf("#include \"db.h\"\n") >> CFILE
88		printf("#include \"db_int.h\"\n") >> CFILE
89		printf("#include \"dbinc/db_swap.h\"\n") >> CFILE
90	}
91
92	printf("/* Do not edit: automatically built by gen_rec.awk. */\n\n")\
93	    > PFILE
94	printf("#include \"db_config.h\"\n\n") >> PFILE
95	if (!dbprivate) {
96		printf("#include <ctype.h>\n") >> PFILE
97		printf("#include <stdio.h>\n") >> PFILE
98		printf("#include <stdlib.h>\n") >> PFILE
99		printf("#include \"db.h\"\n") >> PFILE
100	}
101
102	if (prefix == "__ham")
103		printf("#ifdef HAVE_HASH\n") >> PFILE
104	if (prefix == "__qam")
105		printf("#ifdef HAVE_QUEUE\n") >> PFILE
106
107	# Start .h file, make the entire file conditional.
108	printf("/* Do not edit: automatically built by gen_rec.awk. */\n\n")\
109	    > HFILE
110	printf("#ifndef\t%s_AUTO_H\n#define\t%s_AUTO_H\n", prefix, prefix)\
111	    >> HFILE
112
113	# Write recovery template file headers
114	if (dbprivate) {
115		# This assumes we're doing DB recovery.
116		printf("#include \"db_config.h\"\n\n") > TFILE
117		printf("#include \"db_int.h\"\n") >> TFILE
118		printf("#include \"dbinc/db_page.h\"\n") >> TFILE
119		printf("#include \"dbinc/%s.h\"\n", prefix) >> TFILE
120		printf("#include \"dbinc/log.h\"\n\n") >> TFILE
121	} else {
122		printf("#include \"db.h\"\n\n") > TFILE
123	}
124}
125/^[ 	]*INCLUDE/ {
126	for (i = 2; i < NF; i++)
127		printf("%s ", $i) >> CFILE
128	printf("%s\n", $i) >> CFILE
129	for (i = 2; i < NF; i++)
130		printf("%s ", $i) >> PFILE
131	printf("%s\n", $i) >> PFILE
132}
133/^[ 	]*(BEGIN|BEGIN_COMPAT)/ {
134	if (in_begin) {
135		print "Invalid format: missing END statement"
136		exit
137	}
138	in_begin = 1;
139	is_duplicate = 0;
140	is_dbt = 0;
141	has_dbp = 0;
142	is_uint = 0;
143	hdrdbt = "NULL";
144	ddbt = "NULL";
145	#
146	# BEGIN_COMPAT does not need logging function or rec table entry.
147	#
148	need_log_function = ($1 == "BEGIN");
149	is_compat = ($1 == "BEGIN_COMPAT");
150	nvars = 0;
151
152	thisfunc = $2;
153	dup_thisfunc = $2;
154	version = $3;
155
156	rectype = $4;
157
158	make_name(thisfunc, thisfunc, version);
159}
160/^[	 ]*(DB|ARG|DBT|LOCKS|PGDBT|PGDDBT|POINTER|TIME)/ {
161	vars[nvars] = $2;
162	types[nvars] = $3;
163	modes[nvars] = $1;
164	formats[nvars] = $NF;
165	for (i = 4; i < NF; i++)
166		types[nvars] = sprintf("%s %s", types[nvars], $i);
167
168	if ($1 == "DB") {
169		has_dbp = 1;
170	}
171
172	if ($1 == "DB" || $1 == "ARG" || $1 == "TIME") {
173		sizes[nvars] = sprintf("sizeof(u_int32_t)");
174		if ($3 != "u_int32_t")
175			is_uint = 1;
176	} else if ($1 == "POINTER")
177		sizes[nvars] = sprintf("sizeof(*%s)", $2);
178	else { # DBT, PGDBT, PGDDBT
179		sizes[nvars] =\
180		    sprintf("sizeof(u_int32_t) + (%s == NULL ? 0 : %s->size)",\
181		    $2, $2);
182		is_dbt = 1;
183		if ($1 == "PGDBT")
184			hdrdbt = vars[nvars];
185		else if ($1 == "PGDDBT")
186			ddbt = vars[nvars];
187	}
188	nvars++;
189}
190/^[	 ]*DUPLICATE/ {
191	is_duplicate = 1;
192	dup_rectype = $4;
193	old_logfunc = logfunc;
194	old_funcname = funcname;
195	make_name($2, funcname, $3);
196	internal_name = sprintf("%s_%s_int", prefix, thisfunc);
197	dup_logfunc = logfunc;
198	dup_funcname = funcname;
199	dup_thisfunc = $2;
200	logfunc = old_logfunc;
201	funcname = old_funcname;
202}
203/^[	 ]*END/ {
204	if (!in_begin) {
205		print "Invalid format: missing BEGIN statement"
206		exit;
207	}
208
209	# Declare the record type.
210	printf("#define\tDB_%s\t%d\n", funcname, rectype) >> HFILE
211	if (is_duplicate)
212		printf("#define\tDB_%s\t%d\n",\
213		    dup_funcname, dup_rectype) >> HFILE
214
215	# Structure declaration.
216	printf("typedef struct _%s_args {\n", funcname) >> HFILE
217
218	# Here are the required fields for every structure
219	printf("\tu_int32_t type;\n\tDB_TXN *txnp;\n") >> HFILE
220	printf("\tDB_LSN prev_lsn;\n") >>HFILE
221
222	# Here are the specified fields.
223	for (i = 0; i < nvars; i++) {
224		t = types[i];
225		if (modes[i] == "POINTER") {
226			ndx = index(t, "*");
227			t = substr(types[i], 1, ndx - 2);
228		}
229		printf("\t%s\t%s;\n", t, vars[i]) >> HFILE
230	}
231	printf("} %s_args;\n\n", funcname) >> HFILE
232
233	# Output the read, log, and print functions (note that we must
234	# generate the required read function first, because we use its
235	# prototype in the print function).
236
237	read_function();
238
239	if (need_log_function) {
240		log_function();
241	}
242	print_function();
243
244	# Recovery template
245	if (dbprivate)
246		f = "template/rec_ctemp"
247	else
248		f = "template/rec_utemp"
249
250	cmd = sprintf(\
251    "sed -e s/PREF/%s/ -e s/FUNC/%s/ -e s/DUP/%s/ < template/rec_%s >> %s",
252	    prefix, thisfunc, dup_thisfunc,
253	    dbprivate ? "ctemp" : "utemp", TFILE)
254	system(cmd);
255
256	# Done writing stuff, reset and continue.
257	in_begin = 0;
258}
259
260END {
261	# End the conditional for the HFILE
262	printf("#endif\n") >> HFILE
263
264	# Print initialization routine; function prototype
265	p[1] = sprintf("int %s_init_print %s%s%s", prefix,
266	    "__P((", env_type, " *, DB_DISTAB *));");
267	p[2] = "";
268	proto_format(p, PFILE);
269
270	# Create the routine to call __db_add_recovery(print_fn, id)
271	printf("int\n%s_init_print(%s, dtabp)\n",\
272	    prefix, env_var) >> PFILE
273	printf("\t%s *%s;\n", env_type, env_var) >> PFILE
274	printf("\tDB_DISTAB *dtabp;\n{\n") >> PFILE
275	# If application-specific, the user will need a prototype for
276	# __db_add_recovery, since they won't have DB's.
277	if (!dbprivate) {
278		printf(\
279		    "\tint __db_add_recovery __P((%s *, DB_DISTAB *,\n",\
280		    env_type) >> PFILE
281		printf(\
282	"\t    int (*)(%s *, DBT *, DB_LSN *, db_recops), u_int32_t));\n",\
283		    env_type) >> PFILE
284	}
285
286	printf("\tint ret;\n\n") >> PFILE
287	for (i = 0; i < num_funcs; i++) {
288		if (functable[i] == 1)
289			continue;
290		printf("\tif ((ret = __db_add_recovery%s(%s, ",\
291		    dbprivate ? "_int" : "", env_var) >> PFILE
292		printf("dtabp,\n") >> PFILE
293		printf("\t    %s_print, DB_%s)) != 0)\n",\
294		    dupfuncs[i], funcs[i]) >> PFILE
295		printf("\t\treturn (ret);\n") >> PFILE
296	}
297	printf("\treturn (0);\n}\n") >> PFILE
298	if (prefix == "__ham")
299		printf("#endif /* HAVE_HASH */\n") >> PFILE
300	if (prefix == "__qam")
301		printf("#endif /* HAVE_QUEUE */\n") >> PFILE
302
303	# We only want to generate *_init_recover functions if this is a
304	# DB-private, rather than application-specific, set of recovery
305	# functions.  Application-specific recovery functions should be
306	# dispatched using the DB_ENV->set_app_dispatch callback rather than
307	# a DB dispatch table ("dtab").
308	if (!dbprivate)
309		exit
310	# Everything below here is dbprivate, so it uses ENV instead of DB_ENV
311	# Recover initialization routine
312	p[1] = sprintf("int %s_init_recover %s", prefix,\
313	    "__P((ENV *, DB_DISTAB *));");
314	p[2] = "";
315	proto_format(p, CFILE);
316
317	# Create the routine to call db_add_recovery(func, id)
318	printf("int\n%s_init_recover(env, dtabp)\n", prefix) >> CFILE
319	printf("\tENV *env;\n") >> CFILE
320	printf("\tDB_DISTAB *dtabp;\n{\n") >> CFILE
321	printf("\tint ret;\n\n") >> CFILE
322	for (i = 0; i < num_funcs; i++) {
323		if (functable[i] == 1)
324			continue;
325		printf("\tif ((ret = __db_add_recovery_int(env, ") >> CFILE
326		printf("dtabp,\n") >> CFILE
327		printf("\t    %s_recover, DB_%s)) != 0)\n",\
328		    funcs[i], funcs[i]) >> CFILE
329		printf("\t\treturn (ret);\n") >> CFILE
330	}
331	printf("\treturn (0);\n}\n") >> CFILE
332}
333
334function log_function()
335{
336	log_prototype(logfunc, 0);
337	if (is_duplicate) {
338		log_prototype(dup_logfunc, 0);
339		log_prototype(internal_name, 1);
340	}
341
342	# Function declaration
343	log_funcdecl(logfunc, 0);
344	if (is_duplicate) {
345		log_callint(funcname);
346		log_funcdecl(dup_logfunc, 0);
347		log_callint(dup_funcname);
348		log_funcdecl(internal_name, 1);
349	}
350
351	# Function body and local decls
352	printf("{\n") >> CFILE
353	printf("\tDBT logrec;\n") >> CFILE
354	printf("\tDB_LSN *lsnp, null_lsn, *rlsnp;\n") >> CFILE
355	if (dbprivate) {
356		printf("\tDB_TXNLOGREC *lr;\n") >> CFILE
357		if (has_dbp)
358			printf("\t%s *%s;\n",
359			    env_type, env_var) >> CFILE
360	} else {
361		printf("\tENV *env;\n") >> CFILE
362	}
363	printf("\tu_int32_t ") >> CFILE
364	if (is_dbt)
365		printf("zero, ") >> CFILE
366	if (is_uint)
367		printf("uinttmp, ") >> CFILE
368	printf("rectype, txn_num;\n") >> CFILE
369	printf("\tu_int npad;\n") >> CFILE
370	printf("\tu_int8_t *bp;\n") >> CFILE
371	printf("\tint ") >> CFILE
372	if (dbprivate) {
373		printf("is_durable, ") >> CFILE
374	}
375	printf("ret;\n\n") >> CFILE
376
377	# Initialization
378	if (dbprivate)
379		printf("\tCOMPQUIET(lr, NULL);\n\n") >> CFILE
380
381	if (has_dbp)
382		printf("\t%s = dbp->%s;\n", env_var, env_var) >> CFILE
383	if (!dbprivate)
384		printf("\tenv = dbenv->env;\n") >> CFILE
385	printf("\trlsnp = ret_lsnp;\n") >> CFILE
386	if (is_duplicate)
387		printf("\trectype = type;\n") >> CFILE
388	else
389		printf("\trectype = DB_%s;\n", funcname) >> CFILE
390	printf("\tnpad = 0;\n") >> CFILE
391	printf("\tret = 0;\n\n") >> CFILE
392
393	if (dbprivate) {
394		printf("\tif (LF_ISSET(DB_LOG_NOT_DURABLE)") >> CFILE
395		if (has_dbp) {
396			printf(" ||\n\t    ") >> CFILE
397			printf("F_ISSET(dbp, DB_AM_NOT_DURABLE)) {\n") >> CFILE
398		} else {
399			printf(") {\n") >> CFILE
400		}
401		printf("\t\tif (txnp == NULL)\n") >> CFILE
402		printf("\t\t\treturn (0);\n") >> CFILE
403		printf("\t\tis_durable = 0;\n") >> CFILE
404		printf("\t} else\n") >> CFILE
405		printf("\t\tis_durable = 1;\n\n") >> CFILE
406	}
407	printf("\tif (txnp == NULL) {\n") >> CFILE
408	printf("\t\ttxn_num = 0;\n") >> CFILE
409	printf("\t\tlsnp = &null_lsn;\n") >> CFILE
410	printf("\t\tnull_lsn.file = null_lsn.offset = 0;\n") >> CFILE
411	printf("\t} else {\n") >> CFILE
412	if (dbprivate && logfunc != "__db_debug") {
413		printf(\
414    "\t\tif (TAILQ_FIRST(&txnp->kids) != NULL &&\n") >> CFILE
415		printf("\t\t    (ret = __txn_activekids(") >> CFILE
416		printf("env, rectype, txnp)) != 0)\n") >> CFILE
417		printf("\t\t\treturn (ret);\n") >> CFILE
418	}
419	printf("\t\t/*\n\t\t * We need to assign begin_lsn while ") >> CFILE
420	printf("holding region mutex.\n") >> CFILE
421	printf("\t\t * That assignment is done inside the ") >> CFILE
422	printf("DbEnv->log_put call,\n\t\t * ") >> CFILE
423	printf("so pass in the appropriate memory location to be ") >> CFILE
424	printf("filled\n\t\t * in by the log_put code.\n\t\t */\n")  >> CFILE
425	printf("\t\tDB_SET_TXN_LSNP(txnp, &rlsnp, &lsnp);\n") >> CFILE
426	printf("\t\ttxn_num = txnp->txnid;\n") >> CFILE
427	printf("\t}\n\n") >> CFILE
428
429	# If we're logging a DB handle, make sure we have a log
430	# file ID for it.
431	db_handle_id_function(modes, nvars);
432
433	# Malloc
434	printf("\tlogrec.size = ") >> CFILE
435	printf("sizeof(rectype) + ") >> CFILE
436	printf("sizeof(txn_num) + sizeof(DB_LSN)") >> CFILE
437	for (i = 0; i < nvars; i++)
438		printf("\n\t    + %s", sizes[i]) >> CFILE
439	printf(";\n") >> CFILE
440	if (dbprivate) {
441		printf("\tif (CRYPTO_ON(env)) {\n") >> CFILE
442		printf(\
443	"\t\tnpad = env->crypto_handle->adj_size(logrec.size);\n") >> CFILE
444		printf("\t\tlogrec.size += npad;\n\t}\n\n") >> CFILE
445
446		printf("\tif (is_durable || txnp == NULL) {\n") >> CFILE
447		printf("\t\tif ((ret =\n\t\t    __os_malloc(env, ") >> CFILE
448		printf("logrec.size, &logrec.data)) != 0)\n") >> CFILE
449		printf("\t\t\treturn (ret);\n") >> CFILE
450		printf("\t} else {\n") >> CFILE
451		write_malloc("\t\t",
452		    "lr", "logrec.size + sizeof(DB_TXNLOGREC)", CFILE)
453		printf("#ifdef DIAGNOSTIC\n") >> CFILE
454		printf("\t\tif ((ret =\n\t\t    __os_malloc(env, ") >> CFILE
455		printf("logrec.size, &logrec.data)) != 0) {\n") >> CFILE
456		printf("\t\t\t__os_free(env, lr);\n") >> CFILE
457		printf("\t\t\treturn (ret);\n") >> CFILE
458		printf("\t\t}\n") >> CFILE
459		printf("#else\n") >> CFILE
460		printf("\t\tlogrec.data = lr->data;\n") >> CFILE
461		printf("#endif\n") >> CFILE
462		printf("\t}\n") >> CFILE
463	} else {
464		write_malloc("\t", "logrec.data", "logrec.size", CFILE)
465		printf("\tbp = logrec.data;\n\n") >> CFILE
466	}
467	printf("\tif (npad > 0)\n") >> CFILE
468	printf("\t\tmemset((u_int8_t *)logrec.data + logrec.size ") >> CFILE
469	printf("- npad, 0, npad);\n\n") >> CFILE
470	printf("\tbp = logrec.data;\n\n") >> CFILE
471
472	# Copy args into buffer
473	printf("\tLOGCOPY_32(env, bp, &rectype);\n") >> CFILE
474	printf("\tbp += sizeof(rectype);\n\n") >> CFILE
475	printf("\tLOGCOPY_32(env, bp, &txn_num);\n") >> CFILE
476	printf("\tbp += sizeof(txn_num);\n\n") >> CFILE
477	printf("\tLOGCOPY_FROMLSN(env, bp, lsnp);\n") >> CFILE
478	printf("\tbp += sizeof(DB_LSN);\n\n") >> CFILE
479
480	for (i = 0; i < nvars; i++) {
481		if (modes[i] == "ARG" || modes[i] == "TIME") {
482			if (types[i] == "u_int32_t") {
483				printf("\tLOGCOPY_32(env, bp, &%s);\n",
484				    vars[i]) >> CFILE
485				printf("\tbp += sizeof(%s);\n\n",
486				    vars[i]) >> CFILE
487			} else {
488				printf("\tuinttmp = (u_int32_t)%s;\n",
489				    vars[i]) >> CFILE
490				printf("\tLOGCOPY_32(env,") >> CFILE
491				printf("bp, &uinttmp);\n") >> CFILE
492				printf("\tbp += sizeof(uinttmp);\n\n") >> CFILE
493			}
494		} else if (modes[i] == "DBT" || modes[i] == "LOCKS" ||\
495		    modes[i] == "PGDBT" || modes[i] == "PGDDBT") {
496			printf("\tif (%s == NULL) {\n", vars[i]) >> CFILE
497			printf("\t\tzero = 0;\n") >> CFILE
498			printf("\t\tLOGCOPY_32(env, bp, &zero);\n") >> CFILE
499			printf("\t\tbp += sizeof(u_int32_t);\n") >> CFILE
500			printf("\t} else {\n") >> CFILE
501			printf("\t\tLOGCOPY_32(env, bp, &%s->size);\n",
502			    vars[i]) >> CFILE
503			printf("\t\tbp += sizeof(%s->size);\n", vars[i])\
504			    >> CFILE
505			printf("\t\tmemcpy(bp, %s->data, %s->size);\n",\
506			    vars[i], vars[i]) >> CFILE
507			if (modes[i] == "PGDBT" && !is_compat) {
508				printf("\t\tif (LOG_SWAPPED(env))\n") >> CFILE
509				printf(\
510			"\t\t\tif ((ret = __db_pageswap(dbp,\n") >> CFILE
511				printf(\
512	       "\t\t\t    (PAGE *)bp, (size_t)%s->size, (DBT *)%s, 0)) != 0)\n",
513				    vars[i], ddbt) >> CFILE
514				printf("\t\t\t\treturn (ret);\n") >> CFILE
515			} else if (modes[i] == "PGDDBT") {
516				printf("\t\tif (LOG_SWAPPED(env) && ") >> CFILE
517				printf("F_ISSET(%s, DB_DBT_APPMALLOC))\n",
518				    ddbt) >> CFILE
519				printf("\t\t\t__os_free(env, %s->data);\n",
520				    ddbt) >> CFILE
521			}
522			printf("\t\tbp += %s->size;\n", vars[i]) >> CFILE
523			printf("\t}\n\n") >> CFILE
524		} else if (modes[i] == "DB") {
525			printf(\
526			    "\tuinttmp = (u_int32_t)dbp->log_filename->id;\n")\
527			    >> CFILE
528			printf("\tLOGCOPY_32(env, bp, &uinttmp);\n") >> CFILE
529			printf("\tbp += sizeof(uinttmp);\n\n") >> CFILE
530		} else { # POINTER
531			printf("\tif (%s != NULL)", vars[i]) >> CFILE
532			if (has_dbp && types[i] == "DB_LSN *") {
533				printf(" {\n\t\tif (txnp != NULL) {\n")\
534				    >> CFILE
535				printf(\
536	"\t\t\tLOG *lp = env->lg_handle->reginfo.primary;\n") >> CFILE
537				printf(\
538	"\t\t\tif (LOG_COMPARE(%s, &lp->lsn) >= 0 && (ret =\n", vars[i])\
539				    >> CFILE
540				printf(\
541	"\t\t\t    __log_check_page_lsn(env, dbp, %s)) != 0)\n", vars[i])\
542				    >> CFILE
543				printf("\t\t\t\treturn (ret);\n") >> CFILE
544				printf("\t\t}") >> CFILE
545			}
546			printf("\n\t\tLOGCOPY_FROMLSN(env, bp, %s);\n",
547			    vars[i]) >> CFILE
548			if (has_dbp && types[i] == "DB_LSN *")
549				printf("\t} else\n") >> CFILE
550			else
551				printf("\telse\n") >> CFILE
552			printf("\t\tmemset(bp, 0, %s);\n", sizes[i]) >> CFILE
553			printf("\tbp += %s;\n\n", sizes[i]) >> CFILE
554		}
555	}
556
557	# Error checking.  User code won't have DB_ASSERT available, but
558	# this is a pretty unlikely assertion anyway, so we just leave it out
559	# rather than requiring assert.h.
560	if (dbprivate) {
561		printf("\tDB_ASSERT(env,\n") >> CFILE
562		printf("\t    (u_int32_t)(bp - (u_int8_t *)") >> CFILE
563		printf("logrec.data) <= logrec.size);\n\n") >> CFILE
564		# Save the log record off in the txn's linked list,
565		# or do log call.
566		# We didn't call the crypto alignment function when
567		# we created this log record (because we don't have
568		# the right header files to find the function), so
569		# we have to copy the log record to make sure the
570		# alignment is correct.
571		printf("\tif (is_durable || txnp == NULL) {\n") >> CFILE
572		# Output the log record and update the return LSN.
573		printf("\t\tif ((ret = __log_put(env, rlsnp,") >> CFILE
574		printf("(DBT *)&logrec,\n") >> CFILE
575		printf("\t\t    flags | DB_LOG_NOCOPY)) == 0") >> CFILE
576		printf(" && txnp != NULL) {\n") >> CFILE
577		printf("\t\t\t*lsnp = *rlsnp;\n") >> CFILE
578
579		printf("\t\t\tif (rlsnp != ret_lsnp)\n") >> CFILE
580		printf("\t\t\t\t *ret_lsnp = *rlsnp;\n") >> CFILE
581		printf("\t\t}\n\t} else {\n") >> CFILE
582		printf("\t\tret = 0;\n") >> CFILE
583		printf("#ifdef DIAGNOSTIC\n") >> CFILE
584
585		# Add the debug bit if we are logging a ND record.
586		printf("\t\t/*\n") >> CFILE
587		printf("\t\t * Set the debug bit if we are") >> CFILE
588		printf(" going to log non-durable\n") >> CFILE
589		printf("\t\t * transactions so they will be ignored") >> CFILE
590		printf(" by recovery.\n") >> CFILE
591		printf("\t\t */\n") >> CFILE
592		printf("\t\tmemcpy(lr->data, logrec.data, ") >> CFILE
593		printf("logrec.size);\n") >> CFILE
594		printf("\t\trectype |= DB_debug_FLAG;\n") >> CFILE
595		printf("\t\tLOGCOPY_32(") >> CFILE
596		printf("env, logrec.data, &rectype);\n\n") >> CFILE
597		# Output the log record.
598		printf("\t\tif (!IS_REP_CLIENT(env))\n") >> CFILE
599		printf("\t\t\tret = __log_put(env,\n") >> CFILE
600		printf("\t\t\t    rlsnp, (DBT *)&logrec, ") >> CFILE
601		printf("flags | DB_LOG_NOCOPY);\n") >> CFILE
602		printf("#endif\n") >> CFILE
603		# Add a ND record to the txn list.
604		printf("\t\tSTAILQ_INSERT_HEAD(&txnp") >> CFILE
605		printf("->logs, lr, links);\n") >> CFILE
606		printf("\t\tF_SET((TXN_DETAIL *)") >> CFILE
607		printf("txnp->td, TXN_DTL_INMEMORY);\n") >> CFILE
608		# Update the return LSN.
609		printf("\t\tLSN_NOT_LOGGED(*ret_lsnp);\n") >> CFILE
610		printf("\t}\n\n") >> CFILE
611	} else {
612		printf("\tif ((ret = dbenv->log_put(dbenv, rlsnp,") >> CFILE
613		printf(" (DBT *)&logrec,\n") >> CFILE
614		printf("\t    flags | DB_LOG_NOCOPY)) == 0") >> CFILE
615		printf(" && txnp != NULL) {\n") >> CFILE
616
617               	# Update the transactions last_lsn.
618		printf("\t\t*lsnp = *rlsnp;\n") >> CFILE
619		printf("\t\tif (rlsnp != ret_lsnp)\n") >> CFILE
620		printf("\t\t\t *ret_lsnp = *rlsnp;\n") >> CFILE
621		printf("\t}\n") >> CFILE
622	}
623
624	# If out of disk space log writes may fail.  If we are debugging
625	# that print out which records did not make it to disk.
626	printf("#ifdef LOG_DIAGNOSTIC\n") >> CFILE
627	printf("\tif (ret != 0)\n") >> CFILE
628	printf("\t\t(void)%s_print(%s,\n", funcname, env_var) >> CFILE
629	printf("\t\t    (DBT *)&logrec, ret_lsnp, ") >> CFILE
630	printf("DB_TXN_PRINT%s);\n#endif\n\n",\
631	    dbprivate ? ", NULL" : "") >> CFILE
632	# Free and return
633	if (dbprivate) {
634		printf("#ifdef DIAGNOSTIC\n") >> CFILE
635		write_free("\t", "logrec.data", CFILE)
636		printf("#else\n") >> CFILE
637		printf("\tif (is_durable || txnp == NULL)\n") >> CFILE
638		write_free("\t\t", "logrec.data", CFILE)
639		printf("#endif\n") >> CFILE
640	} else {
641		write_free("\t", "logrec.data", CFILE)
642	}
643
644	printf("\treturn (ret);\n}\n\n") >> CFILE
645}
646
647function log_prototype(fname, with_type)
648{
649	# Write the log function; function prototype
650	pi = 1;
651	p[pi++] = sprintf("int %s_log", fname);
652	p[pi++] = " ";
653	if (has_dbp) {
654		p[pi++] = "__P((DB *";
655	} else {
656		p[pi++] = sprintf("__P((%s *", env_type);
657	}
658	p[pi++] = ", DB_TXN *, DB_LSN *, u_int32_t";
659	for (i = 0; i < nvars; i++) {
660		if (modes[i] == "DB")
661			continue;
662		p[pi++] = ", ";
663		p[pi++] = sprintf("%s%s%s", (modes[i] == "DBT" ||
664		    modes[i] == "LOCKS" || modes[i] == "PGDBT" ||
665		    modes[i] == "PGDDBT") ? "const " : "", types[i],
666		    (modes[i] == "DBT" || modes[i] == "LOCKS" ||
667		    modes[i] == "PGDBT" || modes[i] == "PGDDBT") ? " *" : "");
668	}
669
670	# If this is a logging call with type, add the type here.
671	if (with_type)
672		p[pi++] = ", u_int32_t";
673
674	p[pi++] = "";
675	p[pi++] = "));";
676	p[pi++] = "";
677	proto_format(p, CFILE);
678}
679
680# If we're logging a DB handle, make sure we have a log
681# file ID for it.
682function db_handle_id_function(modes, n)
683{
684	for (i = 0; i < n; i++)
685		if (modes[i] == "DB") {
686			# We actually log the DB handle's fileid; from
687			# that ID we're able to acquire an open handle
688			# at recovery time.
689			printf(\
690		    "\tDB_ASSERT(env, dbp->log_filename != NULL);\n")\
691			    >> CFILE
692			printf("\tif (dbp->log_filename->id == ")\
693			    >> CFILE
694			printf("DB_LOGFILEID_INVALID &&\n\t    ")\
695			    >> CFILE
696			printf("(ret = __dbreg_lazy_id(dbp)) != 0)\n")\
697			    >> CFILE
698			printf("\t\treturn (ret);\n\n") >> CFILE
699			break;
700		}
701}
702
703function print_function()
704{
705	# Write the print function; function prototype
706	p[1] = sprintf("int %s_print", funcname);
707	p[2] = " ";
708	if (dbprivate)
709		p[3] = "__P((ENV *, DBT *, DB_LSN *, db_recops, void *));";
710	else
711		p[3] = "__P((DB_ENV *, DBT *, DB_LSN *, db_recops));";
712	p[4] = "";
713	proto_format(p, PFILE);
714
715	# Function declaration
716	printf("int\n%s_print(%s, ", funcname, env_var) >> PFILE
717	printf("dbtp, lsnp, notused2") >> PFILE
718	if (dbprivate)
719		printf(", notused3") >> PFILE
720	printf(")\n") >> PFILE
721	printf("\t%s *%s;\n", env_type, env_var) >> PFILE
722	printf("\tDBT *dbtp;\n") >> PFILE
723	printf("\tDB_LSN *lsnp;\n") >> PFILE
724	printf("\tdb_recops notused2;\n") >> PFILE
725	if (dbprivate)
726		printf("\tvoid *notused3;\n") >> PFILE
727	printf("{\n") >> PFILE
728
729	# Locals
730	printf("\t%s_args *argp;\n", funcname) >> PFILE
731	if (!dbprivate)
732		printf("\t%s\n", read_proto) >> PFILE
733	for (i = 0; i < nvars; i ++)
734		if (modes[i] == "TIME") {
735			printf("\tstruct tm *lt;\n") >> PFILE
736			printf("\ttime_t timeval;\n") >> PFILE
737			printf("\tchar time_buf[CTIME_BUFLEN];\n") >> PFILE
738			break;
739		}
740	for (i = 0; i < nvars; i ++)
741		if (modes[i] == "DBT" ||
742		    modes[i] == "PGDBT" || modes[i] == "PGDDBT") {
743			printf("\tu_int32_t i;\n") >> PFILE
744			printf("\tint ch;\n") >> PFILE
745			break;
746		}
747	printf("\tint ret;\n\n") >> PFILE
748
749	# Get rid of complaints about unused parameters.
750	printf("\tnotused2 = DB_TXN_PRINT;\n") >> PFILE
751	if (dbprivate)
752		printf("\tnotused3 = NULL;\n") >> PFILE
753	printf("\n") >> PFILE
754
755	# Call read routine to initialize structure
756	if (has_dbp) {
757		printf("\tif ((ret =\n") >> PFILE
758		printf(\
759		    "\t    %s_read(%s, NULL, NULL, dbtp->data, &argp)) != 0)\n",
760		    funcname, env_var) >> PFILE
761	} else {
762		printf("\tif ((ret = %s_read(%s, dbtp->data, &argp)) != 0)\n",
763		    funcname, env_var) >> PFILE
764	}
765	printf("\t\treturn (ret);\n") >> PFILE
766
767	# Print values in every record
768	printf("\t(void)printf(\n    \"[%%lu][%%lu]%s%%s: ", funcname) >> PFILE
769	printf("rec: %%lu txnp %%lx prevlsn [%%lu][%%lu]\\n\",\n") >> PFILE
770	printf("\t    (u_long)lsnp->file, (u_long)lsnp->offset,\n") >> PFILE
771	printf("\t    (argp->type & DB_debug_FLAG) ? \"_debug\" : \"\",\n")\
772	     >> PFILE
773	printf("\t    (u_long)argp->type,\n") >> PFILE
774	printf("\t    (u_long)argp->txnp->txnid,\n") >> PFILE
775	printf("\t    (u_long)argp->prev_lsn.file, ") >> PFILE
776	printf("(u_long)argp->prev_lsn.offset);\n") >> PFILE
777
778	# Now print fields of argp
779	for (i = 0; i < nvars; i ++) {
780		if (modes[i] == "TIME") {
781			printf("\ttimeval = (time_t)argp->%s;\n",
782			    vars[i]) >> PFILE
783			printf("\tlt = localtime(&timeval);\n") >> PFILE
784			printf("\t(void)printf(\n\t    \"\\t%s: ",
785			    vars[i]) >> PFILE
786		} else
787			printf("\t(void)printf(\"\\t%s: ", vars[i]) >> PFILE
788
789		if (modes[i] == "DBT" ||
790		    modes[i] == "PGDBT" || modes[i] == "PGDDBT") {
791			printf("\");\n") >> PFILE
792			printf("\tfor (i = 0; i < ") >> PFILE
793			printf("argp->%s.size; i++) {\n", vars[i]) >> PFILE
794			printf("\t\tch = ((u_int8_t *)argp->%s.data)[i];\n",\
795			    vars[i]) >> PFILE
796			printf("\t\tprintf(isprint(ch) || ch == 0x0a") >> PFILE
797			printf(" ? \"%%c\" : \"%%#x \", ch);\n") >> PFILE
798			printf("\t}\n\t(void)printf(\"\\n\");\n") >> PFILE
799		} else if (types[i] == "DB_LSN *") {
800			printf("[%%%s][%%%s]\\n\",\n",\
801			    formats[i], formats[i]) >> PFILE
802			printf("\t    (u_long)argp->%s.file,",\
803			    vars[i]) >> PFILE
804			printf(" (u_long)argp->%s.offset);\n",\
805			    vars[i]) >> PFILE
806		} else if (modes[i] == "TIME") {
807			# Time values are displayed in two ways: the standard
808			# string returned by ctime, and in the input format
809			# expected by db_recover -t.
810			printf(\
811	    "%%%s (%%.24s, 20%%02lu%%02lu%%02lu%%02lu%%02lu.%%02lu)\\n\",\n",\
812			    formats[i]) >> PFILE
813			printf("\t    (long)argp->%s, ", vars[i]) >> PFILE
814			printf("__os_ctime(&timeval, time_buf),",\
815			    vars[i]) >> PFILE
816			printf("\n\t    (u_long)lt->tm_year - 100, ") >> PFILE
817			printf("(u_long)lt->tm_mon+1,") >> PFILE
818			printf("\n\t    (u_long)lt->tm_mday, ") >> PFILE
819			printf("(u_long)lt->tm_hour,") >> PFILE
820			printf("\n\t    (u_long)lt->tm_min, ") >> PFILE
821			printf("(u_long)lt->tm_sec);\n") >> PFILE
822		} else if (modes[i] == "LOCKS") {
823			printf("\\n\");\n") >> PFILE
824			printf("\t__lock_list_print(env, &argp->locks);\n")\
825				>> PFILE
826		} else {
827			if (formats[i] == "lx")
828				printf("0x") >> PFILE
829			printf("%%%s\\n\", ", formats[i]) >> PFILE
830			if (formats[i] == "lx" || formats[i] == "lu")
831				printf("(u_long)") >> PFILE
832			if (formats[i] == "ld")
833				printf("(long)") >> PFILE
834			printf("argp->%s);\n", vars[i]) >> PFILE
835		}
836	}
837	printf("\t(void)printf(\"\\n\");\n") >> PFILE
838	write_free("\t", "argp", PFILE);
839	printf("\treturn (0);\n") >> PFILE
840	printf("}\n\n") >> PFILE
841}
842
843function read_function()
844{
845	# Write the read function; function prototype
846	if (has_dbp) {
847		p[1] = sprintf("int %s_read __P((%s *, DB **, void *, void *,",
848		    funcname, env_type);
849	} else {
850		p[1] = sprintf("int %s_read __P((%s *, void *,",
851		    funcname, env_type);
852	}
853	p[2] = " ";
854	p[3] = sprintf("%s_args **));", funcname);
855	p[4] = "";
856	read_proto = sprintf("%s %s", p[1], p[3]);
857	proto_format(p, CFILE);
858
859	# Function declaration
860	if (has_dbp) {
861		printf("int\n%s_read(%s, dbpp, td, recbuf, argpp)\n",
862		    funcname, env_var) >> CFILE
863	} else {
864		printf("int\n%s_read(%s, recbuf, argpp)\n",
865		    funcname, env_var) >> CFILE
866	}
867
868	# Now print the parameters
869	printf("\t%s *%s;\n", env_type, env_var) >> CFILE
870	if (has_dbp) {
871		printf("\tDB **dbpp;\n") >> CFILE
872		printf("\tvoid *td;\n") >> CFILE
873	}
874	printf("\tvoid *recbuf;\n") >> CFILE
875	printf("\t%s_args **argpp;\n", funcname) >> CFILE
876
877	# Function body and local decls
878	printf("{\n\t%s_args *argp;\n", funcname) >> CFILE
879	if (is_uint)
880		printf("\tu_int32_t uinttmp;\n") >> CFILE
881	printf("\tu_int8_t *bp;\n") >> CFILE
882
883	if (dbprivate) {
884		# We only use ret in the private malloc case.
885		printf("\tint ret;\n\n") >> CFILE
886	} else {
887		printf("\tENV *env;\n\n") >> CFILE
888		printf("\tenv = dbenv->env;\n\n") >> CFILE
889	}
890
891	malloc_size = sprintf("sizeof(%s_args) + sizeof(DB_TXN)", funcname)
892	write_malloc("\t", "argp", malloc_size, CFILE)
893
894	# Set up the pointers to the DB_TXN *.
895	printf("\tbp = recbuf;\n") >> CFILE
896
897	printf("\targp->txnp = (DB_TXN *)&argp[1];\n") >> CFILE
898	printf("\tmemset(argp->txnp, 0, sizeof(DB_TXN));\n\n")\
899	    >> CFILE
900	if (has_dbp)
901		printf("\targp->txnp->td = td;\n") >> CFILE
902
903	# First get the record type, prev_lsn, and txnp fields.
904	printf("\tLOGCOPY_32(env, &argp->type, bp);\n") >> CFILE
905	printf("\tbp += sizeof(argp->type);\n\n") >> CFILE
906	printf("\tLOGCOPY_32(env, &argp->txnp->txnid, bp);\n") >> CFILE
907	printf("\tbp += sizeof(argp->txnp->txnid);\n\n") >> CFILE
908	printf("\tLOGCOPY_TOLSN(env, &argp->prev_lsn, bp);\n") >> CFILE
909	printf("\tbp += sizeof(DB_LSN);\n\n") >> CFILE
910
911	# Now get rest of data.
912	for (i = 0; i < nvars; i ++) {
913		if (modes[i] == "DBT" || modes[i] == "LOCKS" ||
914		    modes[i] == "PGDBT" || modes[i] == "PGDDBT") {
915			printf("\tmemset(&argp->%s, 0, sizeof(argp->%s));\n",\
916			    vars[i], vars[i]) >> CFILE
917			printf("\tLOGCOPY_32(env,") >> CFILE
918			printf("&argp->%s.size, bp);\n", vars[i]) >> CFILE
919			printf("\tbp += sizeof(u_int32_t);\n") >> CFILE
920			printf("\targp->%s.data = bp;\n", vars[i]) >> CFILE
921			printf("\tbp += argp->%s.size;\n", vars[i]) >> CFILE
922			if (modes[i] == "PGDBT" && ddbt == "NULL" &&
923			    !is_compat) {
924				printf("\tif (LOG_SWAPPED(env) && ") >> CFILE
925				printf("dbpp != NULL && ") >> CFILE
926				printf("*dbpp != NULL) {\n") >> CFILE
927				printf("\t\tint t_ret;\n") >> CFILE
928				printf(\
929	"\t\tif ((t_ret = __db_pageswap(*dbpp, (PAGE *)argp->%s.data,\n",
930				    vars[i]) >> CFILE
931				printf(\
932		      "\t\t    (size_t)argp->%s.size, NULL, 1)) != 0)\n",
933				    vars[i]) >> CFILE
934				printf("\t\t\treturn (t_ret);\n") >> CFILE
935				printf("\t}\n") >> CFILE
936			} else if (modes[i] == "PGDDBT" && !is_compat) {
937				printf("\tif (LOG_SWAPPED(env) && ") >> CFILE
938				printf("dbpp != NULL && ") >> CFILE
939				printf("*dbpp != NULL) {\n") >> CFILE
940				printf("\t\tint t_ret;\n") >> CFILE
941				printf(\
942	"\t\tif ((t_ret = __db_pageswap(*dbpp,\n") >> CFILE
943				printf(\
944		      "\t\t    (PAGE *)argp->%s.data, (size_t)argp->%s.size,\n",
945				     hdrdbt, hdrdbt) >> CFILE
946				printf("\t\t    &argp->%s, 1)) != 0)\n",
947				    vars[i]) >> CFILE
948				printf("\t\t\treturn (t_ret);\n") >> CFILE
949				printf("\t}\n") >> CFILE
950			}
951		} else if (modes[i] == "ARG" || modes[i] == "TIME" ||
952		    modes[i] == "DB") {
953			if (types[i] == "u_int32_t") {
954				printf("\tLOGCOPY_32(env, &argp->%s, bp);\n",
955				    vars[i]) >> CFILE
956				printf("\tbp += sizeof(argp->%s);\n", vars[i])\
957				    >> CFILE
958			} else {
959				printf("\tLOGCOPY_32(env, &uinttmp, bp);\n")\
960				    >> CFILE
961				printf("\targp->%s = (%s)uinttmp;\n", vars[i],\
962				    types[i]) >> CFILE
963				printf("\tbp += sizeof(uinttmp);\n") >> CFILE
964			}
965
966			if (modes[i] == "DB") {
967				# We can now get the DB handle.
968				printf("\tif (dbpp != NULL) {\n") >> CFILE
969				printf("\t\t*dbpp = NULL;\n") >> CFILE
970				printf(\
971			"\t\tret = __dbreg_id_to_db(\n\t\t    ") >> CFILE
972				printf("env, argp->txnp, dbpp, argp->%s, 1);\n",
973				    vars[i]) >> CFILE
974				printf("\t}\n") >> CFILE
975			}
976		} else if (types[i] == "DB_LSN *") {
977			printf("\tLOGCOPY_TOLSN(env, &argp->%s, bp);\n",
978			    vars[i]) >> CFILE
979			printf("\tbp += sizeof(DB_LSN);\n", vars[i]) >> CFILE
980		} else { # POINTER
981			printf("\tDB_ASSERT(env, sizeof(argp->%s) == 4);",
982			    vars[i]) >> CFILE
983			printf("\tLOGCOPY_32(env, &argp->%s, bp);",
984			    vars[i]) >> CFILE
985			printf("\tbp += sizeof(argp->%s);\n", vars[i]) >> CFILE
986		}
987		printf("\n") >> CFILE
988	}
989
990	printf("\t*argpp = argp;\n") >> CFILE
991	if (dbprivate)
992		printf("\treturn (ret);\n}\n\n") >> CFILE
993	else
994		printf("\treturn (0);\n}\n\n") >> CFILE
995}
996
997# proto_format --
998#	Pretty-print a function prototype.
999function proto_format(p, fp)
1000{
1001	printf("/*\n") >> fp;
1002
1003	s = "";
1004	for (i = 1; i in p; ++i)
1005		s = s p[i];
1006
1007	t = " * PUBLIC: "
1008	if (length(s) + length(t) < 80)
1009		printf("%s%s", t, s) >> fp;
1010	else {
1011		split(s, p, "__P");
1012		len = length(t) + length(p[1]);
1013		printf("%s%s", t, p[1]) >> fp
1014
1015		n = split(p[2], comma, ",");
1016		comma[1] = "__P" comma[1];
1017		for (i = 1; i <= n; i++) {
1018			if (len + length(comma[i]) > 70) {
1019				printf("\n * PUBLIC:    ") >> fp;
1020				len = 0;
1021			}
1022			printf("%s%s", comma[i], i == n ? "" : ",") >> fp;
1023			len += length(comma[i]) + 2;
1024		}
1025	}
1026	printf("\n */\n") >> fp;
1027	delete p;
1028}
1029
1030function write_malloc(tab, ptr, size, file)
1031{
1032	if (dbprivate) {
1033		print(tab "if ((ret = __os_malloc(env,") >> file
1034		print(tab "    " size ", &" ptr ")) != 0)") >> file
1035		print(tab "\treturn (ret);") >> file;
1036	} else {
1037		print(tab "if ((" ptr " = malloc(" size ")) == NULL)") >> file
1038		print(tab "\treturn (ENOMEM);") >> file
1039	}
1040}
1041
1042function write_free(tab, ptr, file)
1043{
1044	if (dbprivate) {
1045		print(tab "__os_free(env, " ptr ");") >> file
1046	} else {
1047		print(tab "free(" ptr ");") >> file
1048	}
1049}
1050
1051function make_name(unique_name, dup_name, p_version)
1052{
1053	logfunc = sprintf("%s_%s", prefix, unique_name);
1054	logname[num_funcs] = logfunc;
1055	if (is_compat) {
1056		funcname = sprintf("%s_%s_%s", prefix, unique_name, p_version);
1057	} else {
1058		funcname = logfunc;
1059	}
1060
1061	if (is_duplicate)
1062		dupfuncs[num_funcs] = dup_name;
1063	else
1064		dupfuncs[num_funcs] = funcname;
1065
1066	funcs[num_funcs] = funcname;
1067	functable[num_funcs] = is_compat;
1068	++num_funcs;
1069}
1070
1071function log_funcdecl(name, withtype)
1072{
1073	# Function declaration
1074	if (has_dbp) {
1075		printf("int\n%s_log(dbp, txnp, ret_lsnp, flags",\
1076		    name) >> CFILE
1077	} else {
1078		printf("int\n%s_log(%s, txnp, ret_lsnp, flags",\
1079		    name, env_var) >> CFILE
1080	}
1081	for (i = 0; i < nvars; i++) {
1082		if (modes[i] == "DB") {
1083			# We pass in fileids on the dbp, so if this is one,
1084			# skip it.
1085			continue;
1086		}
1087		printf(",") >> CFILE
1088		if ((i % 6) == 0)
1089			printf("\n    ") >> CFILE
1090		else
1091			printf(" ") >> CFILE
1092		printf("%s", vars[i]) >> CFILE
1093	}
1094
1095	if (withtype)
1096		printf(", type") >> CFILE
1097
1098	printf(")\n") >> CFILE
1099
1100	# Now print the parameters
1101	if (has_dbp) {
1102		printf("\tDB *dbp;\n") >> CFILE
1103	} else {
1104		printf("\t%s *%s;\n", env_type, env_var) >> CFILE
1105	}
1106	printf("\tDB_TXN *txnp;\n\tDB_LSN *ret_lsnp;\n") >> CFILE
1107	printf("\tu_int32_t flags;\n") >> CFILE
1108	for (i = 0; i < nvars; i++) {
1109		# We just skip for modes == DB.
1110		if (modes[i] == "DBT" || modes[i] == "LOCKS" ||
1111		    modes[i] == "PGDBT" || modes[i] == "PGDDBT")
1112			printf("\tconst %s *%s;\n", types[i], vars[i]) >> CFILE
1113		else if (modes[i] != "DB")
1114			printf("\t%s %s;\n", types[i], vars[i]) >> CFILE
1115	}
1116	if (withtype)
1117		printf("\tu_int32_t type;\n") >> CFILE
1118}
1119
1120function log_callint(fname)
1121{
1122	if (has_dbp) {
1123		printf("\n{\n\treturn (%s_log(dbp, txnp, ret_lsnp, flags",\
1124		    internal_name) >> CFILE
1125	} else {
1126		printf("\n{\n\treturn (%s_log(%s, txnp, ret_lsnp, flags",\
1127		    internal_name, env_var) >> CFILE
1128	}
1129
1130	for (i = 0; i < nvars; i++) {
1131		if (modes[i] == "DB") {
1132			# We pass in fileids on the dbp, so if this is one,
1133			# skip it.
1134			continue;
1135		}
1136		printf(",") >> CFILE
1137		if ((i % 6) == 0)
1138			printf("\n    ") >> CFILE
1139		else
1140			printf(" ") >> CFILE
1141		printf("%s", vars[i]) >> CFILE
1142	}
1143
1144	printf(", DB_%s", fname) >> CFILE
1145	printf("));\n}\n") >> CFILE
1146}
1147