Add BSD license file
[platform/upstream/db4.git] / dist / gen_rec.awk
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
45 BEGIN {
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
260 END {
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
334 function 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
647 function 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.
682 function 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
703 function 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
843 function 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.
999 function 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
1030 function 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
1042 function 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
1051 function 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
1071 function 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
1120 function 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 }