1#!/bin/sh -
2#
3# See the file LICENSE for redistribution information.
4#
5# Copyright (c) 1996,2008 Oracle.  All rights reserved.
6#
7# $Id: gen_rec.awk,v 12.43 2008/04/19 15:30:36 mjc Exp $
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			printf("\t\tif (txnp == NULL)\n") >> CFILE
401			printf("\t\t\treturn (0);\n") >> CFILE
402		}
403		printf("\t\tif (txnp == NULL)\n") >> CFILE
404		printf("\t\t\treturn (0);\n") >> CFILE
405		printf("\t\tis_durable = 0;\n") >> CFILE
406		printf("\t} else\n") >> CFILE
407		printf("\t\tis_durable = 1;\n\n") >> CFILE
408	}
409	printf("\tif (txnp == NULL) {\n") >> CFILE
410	printf("\t\ttxn_num = 0;\n") >> CFILE
411	printf("\t\tlsnp = &null_lsn;\n") >> CFILE
412	printf("\t\tnull_lsn.file = null_lsn.offset = 0;\n") >> CFILE
413	printf("\t} else {\n") >> CFILE
414	if (dbprivate && logfunc != "__db_debug") {
415		printf(\
416    "\t\tif (TAILQ_FIRST(&txnp->kids) != NULL &&\n") >> CFILE
417		printf("\t\t    (ret = __txn_activekids(") >> CFILE
418		printf("env, rectype, txnp)) != 0)\n") >> CFILE
419		printf("\t\t\treturn (ret);\n") >> CFILE
420	}
421	printf("\t\t/*\n\t\t * We need to assign begin_lsn while ") >> CFILE
422	printf("holding region mutex.\n") >> CFILE
423	printf("\t\t * That assignment is done inside the ") >> CFILE
424	printf("DbEnv->log_put call,\n\t\t * ") >> CFILE
425	printf("so pass in the appropriate memory location to be ") >> CFILE
426	printf("filled\n\t\t * in by the log_put code.\n\t\t */\n")  >> CFILE
427	printf("\t\tDB_SET_TXN_LSNP(txnp, &rlsnp, &lsnp);\n") >> CFILE
428	printf("\t\ttxn_num = txnp->txnid;\n") >> CFILE
429	printf("\t}\n\n") >> CFILE
430
431	# If we're logging a DB handle, make sure we have a log
432	# file ID for it.
433	db_handle_id_function(modes, nvars);
434
435	# Malloc
436	printf("\tlogrec.size = ") >> CFILE
437	printf("sizeof(rectype) + ") >> CFILE
438	printf("sizeof(txn_num) + sizeof(DB_LSN)") >> CFILE
439	for (i = 0; i < nvars; i++)
440		printf("\n\t    + %s", sizes[i]) >> CFILE
441	printf(";\n") >> CFILE
442	if (dbprivate) {
443		printf("\tif (CRYPTO_ON(env)) {\n") >> CFILE
444		printf(\
445	"\t\tnpad = env->crypto_handle->adj_size(logrec.size);\n") >> CFILE
446		printf("\t\tlogrec.size += npad;\n\t}\n\n") >> CFILE
447
448		printf("\tif (is_durable || txnp == NULL) {\n") >> CFILE
449		printf("\t\tif ((ret =\n\t\t    __os_malloc(env, ") >> CFILE
450		printf("logrec.size, &logrec.data)) != 0)\n") >> CFILE
451		printf("\t\t\treturn (ret);\n") >> CFILE
452		printf("\t} else {\n") >> CFILE
453		write_malloc("\t\t",
454		    "lr", "logrec.size + sizeof(DB_TXNLOGREC)", CFILE)
455		printf("#ifdef DIAGNOSTIC\n") >> CFILE
456		printf("\t\tif ((ret =\n\t\t    __os_malloc(env, ") >> CFILE
457		printf("logrec.size, &logrec.data)) != 0) {\n") >> CFILE
458		printf("\t\t\t__os_free(env, lr);\n") >> CFILE
459		printf("\t\t\treturn (ret);\n") >> CFILE
460		printf("\t\t}\n") >> CFILE
461		printf("#else\n") >> CFILE
462		printf("\t\tlogrec.data = lr->data;\n") >> CFILE
463		printf("#endif\n") >> CFILE
464		printf("\t}\n") >> CFILE
465	} else {
466		write_malloc("\t", "logrec.data", "logrec.size", CFILE)
467		printf("\tbp = logrec.data;\n\n") >> CFILE
468	}
469	printf("\tif (npad > 0)\n") >> CFILE
470	printf("\t\tmemset((u_int8_t *)logrec.data + logrec.size ") >> CFILE
471	printf("- npad, 0, npad);\n\n") >> CFILE
472	printf("\tbp = logrec.data;\n\n") >> CFILE
473
474	# Copy args into buffer
475	printf("\tLOGCOPY_32(env, bp, &rectype);\n") >> CFILE
476	printf("\tbp += sizeof(rectype);\n\n") >> CFILE
477	printf("\tLOGCOPY_32(env, bp, &txn_num);\n") >> CFILE
478	printf("\tbp += sizeof(txn_num);\n\n") >> CFILE
479	printf("\tLOGCOPY_FROMLSN(env, bp, lsnp);\n") >> CFILE
480	printf("\tbp += sizeof(DB_LSN);\n\n") >> CFILE
481
482	for (i = 0; i < nvars; i++) {
483		if (modes[i] == "ARG" || modes[i] == "TIME") {
484			if (types[i] == "u_int32_t") {
485				printf("\tLOGCOPY_32(env, bp, &%s);\n",
486				    vars[i]) >> CFILE
487				printf("\tbp += sizeof(%s);\n\n",
488				    vars[i]) >> CFILE
489			} else {
490				printf("\tuinttmp = (u_int32_t)%s;\n",
491				    vars[i]) >> CFILE
492				printf("\tLOGCOPY_32(env,") >> CFILE
493				printf("bp, &uinttmp);\n") >> CFILE
494				printf("\tbp += sizeof(uinttmp);\n\n") >> CFILE
495			}
496		} else if (modes[i] == "DBT" || modes[i] == "LOCKS" ||\
497		    modes[i] == "PGDBT" || modes[i] == "PGDDBT") {
498			printf("\tif (%s == NULL) {\n", vars[i]) >> CFILE
499			printf("\t\tzero = 0;\n") >> CFILE
500			printf("\t\tLOGCOPY_32(env, bp, &zero);\n") >> CFILE
501			printf("\t\tbp += sizeof(u_int32_t);\n") >> CFILE
502			printf("\t} else {\n") >> CFILE
503			printf("\t\tLOGCOPY_32(env, bp, &%s->size);\n",
504			    vars[i]) >> CFILE
505			printf("\t\tbp += sizeof(%s->size);\n", vars[i])\
506			    >> CFILE
507			printf("\t\tmemcpy(bp, %s->data, %s->size);\n",\
508			    vars[i], vars[i]) >> CFILE
509			if (modes[i] == "PGDBT" && !is_compat) {
510				printf("\t\tif (LOG_SWAPPED(env))\n") >> CFILE
511				printf(\
512			"\t\t\tif ((ret = __db_pageswap(dbp,\n") >> CFILE
513				printf(\
514	       "\t\t\t    (PAGE *)bp, (size_t)%s->size, (DBT *)%s, 0)) != 0)\n",
515				    vars[i], ddbt) >> CFILE
516				printf("\t\t\t\treturn (ret);\n") >> CFILE
517			} else if (modes[i] == "PGDDBT") {
518				printf("\t\tif (LOG_SWAPPED(env) && ") >> CFILE
519				printf("F_ISSET(%s, DB_DBT_APPMALLOC))\n",
520				    ddbt) >> CFILE
521				printf("\t\t\t__os_free(env, %s->data);\n",
522				    ddbt) >> CFILE
523			}
524			printf("\t\tbp += %s->size;\n", vars[i]) >> CFILE
525			printf("\t}\n\n") >> CFILE
526		} else if (modes[i] == "DB") {
527			printf(\
528			    "\tuinttmp = (u_int32_t)dbp->log_filename->id;\n")\
529			    >> CFILE
530			printf("\tLOGCOPY_32(env, bp, &uinttmp);\n") >> CFILE
531			printf("\tbp += sizeof(uinttmp);\n\n") >> CFILE
532		} else { # POINTER
533			printf("\tif (%s != NULL)", vars[i]) >> CFILE
534			if (has_dbp && types[i] == "DB_LSN *") {
535				printf(" {\n\t\tif (txnp != NULL) {\n")\
536				    >> CFILE
537				printf(\
538	"\t\t\tLOG *lp = env->lg_handle->reginfo.primary;\n") >> CFILE
539				printf(\
540	"\t\t\tif (LOG_COMPARE(%s, &lp->lsn) >= 0 && (ret =\n", vars[i])\
541				    >> CFILE
542				printf(\
543	"\t\t\t    __log_check_page_lsn(env, dbp, %s) != 0))\n", vars[i])\
544				    >> CFILE
545				printf("\t\t\t\treturn (ret);\n") >> CFILE
546				printf("\t\t}") >> CFILE
547			}
548			printf("\n\t\tLOGCOPY_FROMLSN(env, bp, %s);\n",
549			    vars[i]) >> CFILE
550			if (has_dbp && types[i] == "DB_LSN *")
551				printf("\t} else\n") >> CFILE
552			else
553				printf("\telse\n") >> CFILE
554			printf("\t\tmemset(bp, 0, %s);\n", sizes[i]) >> CFILE
555			printf("\tbp += %s;\n\n", sizes[i]) >> CFILE
556		}
557	}
558
559	# Error checking.  User code won't have DB_ASSERT available, but
560	# this is a pretty unlikely assertion anyway, so we just leave it out
561	# rather than requiring assert.h.
562	if (dbprivate) {
563		printf("\tDB_ASSERT(env,\n") >> CFILE
564		printf("\t    (u_int32_t)(bp - (u_int8_t *)") >> CFILE
565		printf("logrec.data) <= logrec.size);\n\n") >> CFILE
566		# Save the log record off in the txn's linked list,
567		# or do log call.
568		# We didn't call the crypto alignment function when
569		# we created this log record (because we don't have
570		# the right header files to find the function), so
571		# we have to copy the log record to make sure the
572		# alignment is correct.
573		printf("\tif (is_durable || txnp == NULL) {\n") >> CFILE
574		# Output the log record and update the return LSN.
575		printf("\t\tif ((ret = __log_put(env, rlsnp,") >> CFILE
576		printf("(DBT *)&logrec,\n") >> CFILE
577		printf("\t\t    flags | DB_LOG_NOCOPY)) == 0") >> CFILE
578		printf(" && txnp != NULL) {\n") >> CFILE
579		printf("\t\t\t*lsnp = *rlsnp;\n") >> CFILE
580
581		printf("\t\t\tif (rlsnp != ret_lsnp)\n") >> CFILE
582		printf("\t\t\t\t *ret_lsnp = *rlsnp;\n") >> CFILE
583		printf("\t\t}\n\t} else {\n") >> CFILE
584		printf("\t\tret = 0;\n") >> CFILE
585		printf("#ifdef DIAGNOSTIC\n") >> CFILE
586
587		# Add the debug bit if we are logging a ND record.
588		printf("\t\t/*\n") >> CFILE
589		printf("\t\t * Set the debug bit if we are") >> CFILE
590		printf(" going to log non-durable\n") >> CFILE
591		printf("\t\t * transactions so they will be ignored") >> CFILE
592		printf(" by recovery.\n") >> CFILE
593		printf("\t\t */\n") >> CFILE
594		printf("\t\tmemcpy(lr->data, logrec.data, ") >> CFILE
595		printf("logrec.size);\n") >> CFILE
596		printf("\t\trectype |= DB_debug_FLAG;\n") >> CFILE
597		printf("\t\tLOGCOPY_32(") >> CFILE
598		printf("env, logrec.data, &rectype);\n\n") >> CFILE
599		# Output the log record.
600		printf("\t\tif (!IS_REP_CLIENT(env))\n") >> CFILE
601		printf("\t\t\tret = __log_put(env,\n") >> CFILE
602		printf("\t\t\t    rlsnp, (DBT *)&logrec, ") >> CFILE
603		printf("flags | DB_LOG_NOCOPY);\n") >> CFILE
604		printf("#endif\n") >> CFILE
605		# Add a ND record to the txn list.
606		printf("\t\tSTAILQ_INSERT_HEAD(&txnp") >> CFILE
607		printf("->logs, lr, links);\n") >> CFILE
608		printf("\t\tF_SET((TXN_DETAIL *)") >> CFILE
609		printf("txnp->td, TXN_DTL_INMEMORY);\n") >> CFILE
610		# Update the return LSN.
611		printf("\t\tLSN_NOT_LOGGED(*ret_lsnp);\n") >> CFILE
612		printf("\t}\n\n") >> CFILE
613	} else {
614		printf("\tif ((ret = dbenv->log_put(dbenv, rlsnp,") >> CFILE
615		printf(" (DBT *)&logrec,\n") >> CFILE
616		printf("\t    flags | DB_LOG_NOCOPY)) == 0") >> CFILE
617		printf(" && txnp != NULL) {\n") >> CFILE
618
619               	# Update the transactions last_lsn.
620		printf("\t\t*lsnp = *rlsnp;\n") >> CFILE
621		printf("\t\tif (rlsnp != ret_lsnp)\n") >> CFILE
622		printf("\t\t\t *ret_lsnp = *rlsnp;\n") >> CFILE
623		printf("\t}\n") >> CFILE
624	}
625
626	# If out of disk space log writes may fail.  If we are debugging
627	# that print out which records did not make it to disk.
628	printf("#ifdef LOG_DIAGNOSTIC\n") >> CFILE
629	printf("\tif (ret != 0)\n") >> CFILE
630	printf("\t\t(void)%s_print(%s,\n", funcname, env_var) >> CFILE
631	printf("\t\t    (DBT *)&logrec, ret_lsnp, ") >> CFILE
632	printf("DB_TXN_PRINT%s);\n#endif\n\n",\
633	    dbprivate ? ", NULL" : "") >> CFILE
634	# Free and return
635	if (dbprivate) {
636		printf("#ifdef DIAGNOSTIC\n") >> CFILE
637		write_free("\t", "logrec.data", CFILE)
638		printf("#else\n") >> CFILE
639		printf("\tif (is_durable || txnp == NULL)\n") >> CFILE
640		write_free("\t\t", "logrec.data", CFILE)
641		printf("#endif\n") >> CFILE
642	} else {
643		write_free("\t", "logrec.data", CFILE)
644	}
645
646	printf("\treturn (ret);\n}\n\n") >> CFILE
647}
648
649function log_prototype(fname, with_type)
650{
651	# Write the log function; function prototype
652	pi = 1;
653	p[pi++] = sprintf("int %s_log", fname);
654	p[pi++] = " ";
655	if (has_dbp) {
656		p[pi++] = "__P((DB *";
657	} else {
658		p[pi++] = sprintf("__P((%s *", env_type);
659	}
660	p[pi++] = ", DB_TXN *, DB_LSN *, u_int32_t";
661	for (i = 0; i < nvars; i++) {
662		if (modes[i] == "DB")
663			continue;
664		p[pi++] = ", ";
665		p[pi++] = sprintf("%s%s%s", (modes[i] == "DBT" ||
666		    modes[i] == "LOCKS" || modes[i] == "PGDBT" ||
667		    modes[i] == "PGDDBT") ? "const " : "", types[i],
668		    (modes[i] == "DBT" || modes[i] == "LOCKS" ||
669		    modes[i] == "PGDBT" || modes[i] == "PGDDBT") ? " *" : "");
670	}
671
672	# If this is a logging call with type, add the type here.
673	if (with_type)
674		p[pi++] = ", u_int32_t";
675
676	p[pi++] = "";
677	p[pi++] = "));";
678	p[pi++] = "";
679	proto_format(p, CFILE);
680}
681
682# If we're logging a DB handle, make sure we have a log
683# file ID for it.
684function db_handle_id_function(modes, n)
685{
686	for (i = 0; i < n; i++)
687		if (modes[i] == "DB") {
688			# We actually log the DB handle's fileid; from
689			# that ID we're able to acquire an open handle
690			# at recovery time.
691			printf(\
692		    "\tDB_ASSERT(env, dbp->log_filename != NULL);\n")\
693			    >> CFILE
694			printf("\tif (dbp->log_filename->id == ")\
695			    >> CFILE
696			printf("DB_LOGFILEID_INVALID &&\n\t    ")\
697			    >> CFILE
698			printf("(ret = __dbreg_lazy_id(dbp)) != 0)\n")\
699			    >> CFILE
700			printf("\t\treturn (ret);\n\n") >> CFILE
701			break;
702		}
703}
704
705function print_function()
706{
707	# Write the print function; function prototype
708	p[1] = sprintf("int %s_print", funcname);
709	p[2] = " ";
710	if (dbprivate)
711		p[3] = "__P((ENV *, DBT *, DB_LSN *, db_recops, void *));";
712	else
713		p[3] = "__P((DB_ENV *, DBT *, DB_LSN *, db_recops));";
714	p[4] = "";
715	proto_format(p, PFILE);
716
717	# Function declaration
718	printf("int\n%s_print(%s, ", funcname, env_var) >> PFILE
719	printf("dbtp, lsnp, notused2") >> PFILE
720	if (dbprivate)
721		printf(", notused3") >> PFILE
722	printf(")\n") >> PFILE
723	printf("\t%s *%s;\n", env_type, env_var) >> PFILE
724	printf("\tDBT *dbtp;\n") >> PFILE
725	printf("\tDB_LSN *lsnp;\n") >> PFILE
726	printf("\tdb_recops notused2;\n") >> PFILE
727	if (dbprivate)
728		printf("\tvoid *notused3;\n") >> PFILE
729	printf("{\n") >> PFILE
730
731	# Locals
732	printf("\t%s_args *argp;\n", funcname) >> PFILE
733	if (!dbprivate)
734		printf("\t%s\n", read_proto) >> PFILE
735	for (i = 0; i < nvars; i ++)
736		if (modes[i] == "TIME") {
737			printf("\tstruct tm *lt;\n") >> PFILE
738			printf("\ttime_t timeval;\n") >> PFILE
739			printf("\tchar time_buf[CTIME_BUFLEN];\n") >> PFILE
740			break;
741		}
742	for (i = 0; i < nvars; i ++)
743		if (modes[i] == "DBT" ||
744		    modes[i] == "PGDBT" || modes[i] == "PGDDBT") {
745			printf("\tu_int32_t i;\n") >> PFILE
746			printf("\tint ch;\n") >> PFILE
747			break;
748		}
749	printf("\tint ret;\n\n") >> PFILE
750
751	# Get rid of complaints about unused parameters.
752	printf("\tnotused2 = DB_TXN_PRINT;\n") >> PFILE
753	if (dbprivate)
754		printf("\tnotused3 = NULL;\n") >> PFILE
755	printf("\n") >> PFILE
756
757	# Call read routine to initialize structure
758	if (has_dbp) {
759		printf("\tif ((ret =\n") >> PFILE
760		printf(\
761		    "\t    %s_read(%s, NULL, NULL, dbtp->data, &argp)) != 0)\n",
762		    funcname, env_var) >> PFILE
763	} else {
764		printf("\tif ((ret = %s_read(%s, dbtp->data, &argp)) != 0)\n",
765		    funcname, env_var) >> PFILE
766	}
767	printf("\t\treturn (ret);\n") >> PFILE
768
769	# Print values in every record
770	printf("\t(void)printf(\n    \"[%%lu][%%lu]%s%%s: ", funcname) >> PFILE
771	printf("rec: %%lu txnp %%lx prevlsn [%%lu][%%lu]\\n\",\n") >> PFILE
772	printf("\t    (u_long)lsnp->file, (u_long)lsnp->offset,\n") >> PFILE
773	printf("\t    (argp->type & DB_debug_FLAG) ? \"_debug\" : \"\",\n")\
774	     >> PFILE
775	printf("\t    (u_long)argp->type,\n") >> PFILE
776	printf("\t    (u_long)argp->txnp->txnid,\n") >> PFILE
777	printf("\t    (u_long)argp->prev_lsn.file, ") >> PFILE
778	printf("(u_long)argp->prev_lsn.offset);\n") >> PFILE
779
780	# Now print fields of argp
781	for (i = 0; i < nvars; i ++) {
782		if (modes[i] == "TIME") {
783			printf("\ttimeval = (time_t)argp->%s;\n",
784			    vars[i]) >> PFILE
785			printf("\tlt = localtime(&timeval);\n") >> PFILE
786			printf("\t(void)printf(\n\t    \"\\t%s: ",
787			    vars[i]) >> PFILE
788		} else
789			printf("\t(void)printf(\"\\t%s: ", vars[i]) >> PFILE
790
791		if (modes[i] == "DBT" ||
792		    modes[i] == "PGDBT" || modes[i] == "PGDDBT") {
793			printf("\");\n") >> PFILE
794			printf("\tfor (i = 0; i < ") >> PFILE
795			printf("argp->%s.size; i++) {\n", vars[i]) >> PFILE
796			printf("\t\tch = ((u_int8_t *)argp->%s.data)[i];\n",\
797			    vars[i]) >> PFILE
798			printf("\t\tprintf(isprint(ch) || ch == 0x0a") >> PFILE
799			printf(" ? \"%%c\" : \"%%#x \", ch);\n") >> PFILE
800			printf("\t}\n\t(void)printf(\"\\n\");\n") >> PFILE
801		} else if (types[i] == "DB_LSN *") {
802			printf("[%%%s][%%%s]\\n\",\n",\
803			    formats[i], formats[i]) >> PFILE
804			printf("\t    (u_long)argp->%s.file,",\
805			    vars[i]) >> PFILE
806			printf(" (u_long)argp->%s.offset);\n",\
807			    vars[i]) >> PFILE
808		} else if (modes[i] == "TIME") {
809			# Time values are displayed in two ways: the standard
810			# string returned by ctime, and in the input format
811			# expected by db_recover -t.
812			printf(\
813	    "%%%s (%%.24s, 20%%02lu%%02lu%%02lu%%02lu%%02lu.%%02lu)\\n\",\n",\
814			    formats[i]) >> PFILE
815			printf("\t    (long)argp->%s, ", vars[i]) >> PFILE
816			printf("__os_ctime(&timeval, time_buf),",\
817			    vars[i]) >> PFILE
818			printf("\n\t    (u_long)lt->tm_year - 100, ") >> PFILE
819			printf("(u_long)lt->tm_mon+1,") >> PFILE
820			printf("\n\t    (u_long)lt->tm_mday, ") >> PFILE
821			printf("(u_long)lt->tm_hour,") >> PFILE
822			printf("\n\t    (u_long)lt->tm_min, ") >> PFILE
823			printf("(u_long)lt->tm_sec);\n") >> PFILE
824		} else if (modes[i] == "LOCKS") {
825			printf("\\n\");\n") >> PFILE
826			printf("\t__lock_list_print(env, &argp->locks);\n")\
827				>> PFILE
828		} else {
829			if (formats[i] == "lx")
830				printf("0x") >> PFILE
831			printf("%%%s\\n\", ", formats[i]) >> PFILE
832			if (formats[i] == "lx" || formats[i] == "lu")
833				printf("(u_long)") >> PFILE
834			if (formats[i] == "ld")
835				printf("(long)") >> PFILE
836			printf("argp->%s);\n", vars[i]) >> PFILE
837		}
838	}
839	printf("\t(void)printf(\"\\n\");\n") >> PFILE
840	write_free("\t", "argp", PFILE);
841	printf("\treturn (0);\n") >> PFILE
842	printf("}\n\n") >> PFILE
843}
844
845function read_function()
846{
847	# Write the read function; function prototype
848	if (has_dbp) {
849		p[1] = sprintf("int %s_read __P((%s *, DB **, void *, void *,",
850		    funcname, env_type);
851	} else {
852		p[1] = sprintf("int %s_read __P((%s *, void *,",
853		    funcname, env_type);
854	}
855	p[2] = " ";
856	p[3] = sprintf("%s_args **));", funcname);
857	p[4] = "";
858	read_proto = sprintf("%s %s", p[1], p[3]);
859	proto_format(p, CFILE);
860
861	# Function declaration
862	if (has_dbp) {
863		printf("int\n%s_read(%s, dbpp, td, recbuf, argpp)\n",
864		    funcname, env_var) >> CFILE
865	} else {
866		printf("int\n%s_read(%s, recbuf, argpp)\n",
867		    funcname, env_var) >> CFILE
868	}
869
870	# Now print the parameters
871	printf("\t%s *%s;\n", env_type, env_var) >> CFILE
872	if (has_dbp) {
873		printf("\tDB **dbpp;\n") >> CFILE
874		printf("\tvoid *td;\n") >> CFILE
875	}
876	printf("\tvoid *recbuf;\n") >> CFILE
877	printf("\t%s_args **argpp;\n", funcname) >> CFILE
878
879	# Function body and local decls
880	printf("{\n\t%s_args *argp;\n", funcname) >> CFILE
881	if (is_uint)
882		printf("\tu_int32_t uinttmp;\n") >> CFILE
883	printf("\tu_int8_t *bp;\n") >> CFILE
884
885	if (dbprivate) {
886		# We only use ret in the private malloc case.
887		printf("\tint ret;\n\n") >> CFILE
888	} else {
889		printf("\tENV *env;\n\n") >> CFILE
890		printf("\tenv = dbenv->env;\n\n") >> CFILE
891	}
892
893	malloc_size = sprintf("sizeof(%s_args) + sizeof(DB_TXN)", funcname)
894	write_malloc("\t", "argp", malloc_size, CFILE)
895
896	# Set up the pointers to the DB_TXN *.
897	printf("\tbp = recbuf;\n") >> CFILE
898
899	printf("\targp->txnp = (DB_TXN *)&argp[1];\n") >> CFILE
900	printf("\tmemset(argp->txnp, 0, sizeof(DB_TXN));\n\n")\
901	    >> CFILE
902	if (has_dbp)
903		printf("\targp->txnp->td = td;\n") >> CFILE
904
905	# First get the record type, prev_lsn, and txnp fields.
906	printf("\tLOGCOPY_32(env, &argp->type, bp);\n") >> CFILE
907	printf("\tbp += sizeof(argp->type);\n\n") >> CFILE
908	printf("\tLOGCOPY_32(env, &argp->txnp->txnid, bp);\n") >> CFILE
909	printf("\tbp += sizeof(argp->txnp->txnid);\n\n") >> CFILE
910	printf("\tLOGCOPY_TOLSN(env, &argp->prev_lsn, bp);\n") >> CFILE
911	printf("\tbp += sizeof(DB_LSN);\n\n") >> CFILE
912
913	# Now get rest of data.
914	for (i = 0; i < nvars; i ++) {
915		if (modes[i] == "DBT" || modes[i] == "LOCKS" ||
916		    modes[i] == "PGDBT" || modes[i] == "PGDDBT") {
917			printf("\tmemset(&argp->%s, 0, sizeof(argp->%s));\n",\
918			    vars[i], vars[i]) >> CFILE
919			printf("\tLOGCOPY_32(env,") >> CFILE
920			printf("&argp->%s.size, bp);\n", vars[i]) >> CFILE
921			printf("\tbp += sizeof(u_int32_t);\n") >> CFILE
922			printf("\targp->%s.data = bp;\n", vars[i]) >> CFILE
923			printf("\tbp += argp->%s.size;\n", vars[i]) >> CFILE
924			if (modes[i] == "PGDBT" && ddbt == "NULL" &&
925			    !is_compat) {
926				printf("\tif (LOG_SWAPPED(env) && ") >> CFILE
927				printf("dbpp != NULL && ") >> CFILE
928				printf("*dbpp != NULL) {\n") >> CFILE
929				printf("\t\tint t_ret;\n") >> CFILE
930				printf(\
931	"\t\tif ((t_ret = __db_pageswap(*dbpp, (PAGE *)argp->%s.data,\n",
932				    vars[i]) >> CFILE
933				printf(\
934		      "\t\t    (size_t)argp->%s.size, NULL, 1)) != 0)\n",
935				    vars[i]) >> CFILE
936				printf("\t\t\treturn (t_ret);\n") >> CFILE
937				printf("\t}\n") >> CFILE
938			} else if (modes[i] == "PGDDBT" && !is_compat) {
939				printf("\tif (LOG_SWAPPED(env) && ") >> CFILE
940				printf("dbpp != NULL && ") >> CFILE
941				printf("*dbpp != NULL) {\n") >> CFILE
942				printf("\t\tint t_ret;\n") >> CFILE
943				printf(\
944	"\t\tif ((t_ret = __db_pageswap(*dbpp,\n") >> CFILE
945				printf(\
946		      "\t\t    (PAGE *)argp->%s.data, (size_t)argp->%s.size,\n",
947				     hdrdbt, hdrdbt) >> CFILE
948				printf("\t\t    &argp->%s, 1)) != 0)\n",
949				    vars[i]) >> CFILE
950				printf("\t\t\treturn (t_ret);\n") >> CFILE
951				printf("\t}\n") >> CFILE
952			}
953		} else if (modes[i] == "ARG" || modes[i] == "TIME" ||
954		    modes[i] == "DB") {
955			if (types[i] == "u_int32_t") {
956				printf("\tLOGCOPY_32(env, &argp->%s, bp);\n",
957				    vars[i]) >> CFILE
958				printf("\tbp += sizeof(argp->%s);\n", vars[i])\
959				    >> CFILE
960			} else {
961				printf("\tLOGCOPY_32(env, &uinttmp, bp);\n")\
962				    >> CFILE
963				printf("\targp->%s = (%s)uinttmp;\n", vars[i],\
964				    types[i]) >> CFILE
965				printf("\tbp += sizeof(uinttmp);\n") >> CFILE
966			}
967
968			if (modes[i] == "DB") {
969				# We can now get the DB handle.
970				printf("\tif (dbpp != NULL) {\n") >> CFILE
971				printf("\t\t*dbpp = NULL;\n") >> CFILE
972				printf(\
973			"\t\tret = __dbreg_id_to_db(\n\t\t    ") >> CFILE
974				printf("env, argp->txnp, dbpp, argp->%s, 1);\n",
975				    vars[i]) >> CFILE
976				printf("\t}\n") >> CFILE
977			}
978		} else if (types[i] == "DB_LSN *") {
979			printf("\tLOGCOPY_TOLSN(env, &argp->%s, bp);\n",
980			    vars[i]) >> CFILE
981			printf("\tbp += sizeof(DB_LSN);\n", vars[i]) >> CFILE
982		} else { # POINTER
983			printf("\tDB_ASSERT(env, sizeof(argp->%s) == 4);",
984			    vars[i]) >> CFILE
985			printf("\tLOGCOPY_32(env, &argp->%s, bp);",
986			    vars[i]) >> CFILE
987			printf("\tbp += sizeof(argp->%s);\n", vars[i]) >> CFILE
988		}
989		printf("\n") >> CFILE
990	}
991
992	printf("\t*argpp = argp;\n") >> CFILE
993	if (dbprivate)
994		printf("\treturn (ret);\n}\n\n") >> CFILE
995	else
996		printf("\treturn (0);\n}\n\n") >> CFILE
997}
998
999# proto_format --
1000#	Pretty-print a function prototype.
1001function proto_format(p, fp)
1002{
1003	printf("/*\n") >> fp;
1004
1005	s = "";
1006	for (i = 1; i in p; ++i)
1007		s = s p[i];
1008
1009	t = " * PUBLIC: "
1010	if (length(s) + length(t) < 80)
1011		printf("%s%s", t, s) >> fp;
1012	else {
1013		split(s, p, "__P");
1014		len = length(t) + length(p[1]);
1015		printf("%s%s", t, p[1]) >> fp
1016
1017		n = split(p[2], comma, ",");
1018		comma[1] = "__P" comma[1];
1019		for (i = 1; i <= n; i++) {
1020			if (len + length(comma[i]) > 70) {
1021				printf("\n * PUBLIC:    ") >> fp;
1022				len = 0;
1023			}
1024			printf("%s%s", comma[i], i == n ? "" : ",") >> fp;
1025			len += length(comma[i]) + 2;
1026		}
1027	}
1028	printf("\n */\n") >> fp;
1029	delete p;
1030}
1031
1032function write_malloc(tab, ptr, size, file)
1033{
1034	if (dbprivate) {
1035		print(tab "if ((ret = __os_malloc(env,") >> file
1036		print(tab "    " size ", &" ptr ")) != 0)") >> file
1037		print(tab "\treturn (ret);") >> file;
1038	} else {
1039		print(tab "if ((" ptr " = malloc(" size ")) == NULL)") >> file
1040		print(tab "\treturn (ENOMEM);") >> file
1041	}
1042}
1043
1044function write_free(tab, ptr, file)
1045{
1046	if (dbprivate) {
1047		print(tab "__os_free(env, " ptr ");") >> file
1048	} else {
1049		print(tab "free(" ptr ");") >> file
1050	}
1051}
1052
1053function make_name(unique_name, dup_name, p_version)
1054{
1055	logfunc = sprintf("%s_%s", prefix, unique_name);
1056	logname[num_funcs] = logfunc;
1057	if (is_compat) {
1058		funcname = sprintf("%s_%s_%s", prefix, unique_name, p_version);
1059	} else {
1060		funcname = logfunc;
1061	}
1062
1063	if (is_duplicate)
1064		dupfuncs[num_funcs] = dup_name;
1065	else
1066		dupfuncs[num_funcs] = funcname;
1067
1068	funcs[num_funcs] = funcname;
1069	functable[num_funcs] = is_compat;
1070	++num_funcs;
1071}
1072
1073function log_funcdecl(name, withtype)
1074{
1075	# Function declaration
1076	if (has_dbp) {
1077		printf("int\n%s_log(dbp, txnp, ret_lsnp, flags",\
1078		    name) >> CFILE
1079	} else {
1080		printf("int\n%s_log(%s, txnp, ret_lsnp, flags",\
1081		    name, env_var) >> CFILE
1082	}
1083	for (i = 0; i < nvars; i++) {
1084		if (modes[i] == "DB") {
1085			# We pass in fileids on the dbp, so if this is one,
1086			# skip it.
1087			continue;
1088		}
1089		printf(",") >> CFILE
1090		if ((i % 6) == 0)
1091			printf("\n    ") >> CFILE
1092		else
1093			printf(" ") >> CFILE
1094		printf("%s", vars[i]) >> CFILE
1095	}
1096
1097	if (withtype)
1098		printf(", type") >> CFILE
1099
1100	printf(")\n") >> CFILE
1101
1102	# Now print the parameters
1103	if (has_dbp) {
1104		printf("\tDB *dbp;\n") >> CFILE
1105	} else {
1106		printf("\t%s *%s;\n", env_type, env_var) >> CFILE
1107	}
1108	printf("\tDB_TXN *txnp;\n\tDB_LSN *ret_lsnp;\n") >> CFILE
1109	printf("\tu_int32_t flags;\n") >> CFILE
1110	for (i = 0; i < nvars; i++) {
1111		# We just skip for modes == DB.
1112		if (modes[i] == "DBT" || modes[i] == "LOCKS" ||
1113		    modes[i] == "PGDBT" || modes[i] == "PGDDBT")
1114			printf("\tconst %s *%s;\n", types[i], vars[i]) >> CFILE
1115		else if (modes[i] != "DB")
1116			printf("\t%s %s;\n", types[i], vars[i]) >> CFILE
1117	}
1118	if (withtype)
1119		printf("\tu_int32_t type;\n") >> CFILE
1120}
1121
1122function log_callint(fname)
1123{
1124	if (has_dbp) {
1125		printf("\n{\n\treturn (%s_log(dbp, txnp, ret_lsnp, flags",\
1126		    internal_name) >> CFILE
1127	} else {
1128		printf("\n{\n\treturn (%s_log(%s, txnp, ret_lsnp, flags",\
1129		    internal_name, env_var) >> CFILE
1130	}
1131
1132	for (i = 0; i < nvars; i++) {
1133		if (modes[i] == "DB") {
1134			# We pass in fileids on the dbp, so if this is one,
1135			# skip it.
1136			continue;
1137		}
1138		printf(",") >> CFILE
1139		if ((i % 6) == 0)
1140			printf("\n    ") >> CFILE
1141		else
1142			printf(" ") >> CFILE
1143		printf("%s", vars[i]) >> CFILE
1144	}
1145
1146	printf(", DB_%s", fname) >> CFILE
1147	printf("));\n}\n") >> CFILE
1148}
1149