1# 2# See the file LICENSE for redistribution information. 3# 4# Copyright (c) 1996,2008 Oracle. All rights reserved. 5# 6# $Id: gen_msg.awk,v 12.4 2008/01/11 21:51:46 sue Exp $ 7# 8 9BEGIN { 10 if (source_file == "" || header_file == "") { 11 print "Usage: gen_msg.awk requires these variables to be set:"; 12 print "\theader_file\t-- the message #include file being created"; 13 print "\tsource_file\t-- the message source file being created"; 14 exit; 15 } 16 CFILE=source_file; 17 HFILE=header_file; 18 maxmsg = 0; 19} 20/^[ ]*PREFIX/ { 21 prefix = $2; 22 23 # Start .c files. 24 printf("/* Do not edit: automatically built by gen_msg.awk. */\n\n") \ 25 > CFILE 26 printf("#include \"db_config.h\"\n\n") >> CFILE 27 28 # Start .h file, make the entire file conditional. 29 printf("/* Do not edit: automatically built by gen_msg.awk. */\n\n") \ 30 > HFILE 31 printf("#ifndef\t%s_AUTO_H\n#define\t%s_AUTO_H\n\n", prefix, prefix) \ 32 >> HFILE; 33 printf("/*\n") >> HFILE; 34 printf(" * Message sizes are simply the sum of field sizes (not\n") \ 35 >> HFILE; 36 printf(" * counting variable size parts, when DBTs are present),\n") \ 37 >> HFILE; 38 printf(" * and may be different from struct sizes due to padding.\n") \ 39 >> HFILE; 40 printf(" */\n") >> HFILE; 41} 42/^[ ]*INCLUDE/ { 43 for (i = 2; i < NF; i++) 44 printf("%s ", $i) >> CFILE; 45 printf("%s\n", $i) >> CFILE; 46} 47/^[ ]*BEGIN_MSG/ { 48 if (in_begin) { 49 print "Invalid format: missing END statement"; 50 exit; 51 } 52 in_begin = 1; 53 nvars = 0; 54 thismsg = $2; 55 for (i = 2; i<= NF; i++) { 56 if ($i == "alloc") 57 alloc = 1; 58 else if ($i == "check_length") 59 check_length = 1; 60 else if ($i == "version") 61 version = 1; 62 } 63 64 base_name = sprintf("%s_%s", prefix, thismsg); 65 typedef_name = sprintf("%s_args", base_name); 66 msg_size_name = toupper(sprintf("%s_SIZE", base_name)); 67 max_name = toupper(sprintf("%s_MAXMSG_SIZE", prefix)); 68} 69/^[ ]*ARG/ { 70 vars[nvars] = $2; 71 types[nvars] = $3; 72 if (types[nvars] == "DBT") 73 has_dbt = 1; 74 nvars++; 75} 76/^[ ]*END/ { 77 if (!in_begin) { 78 print "Invalid format: missing BEGIN statement"; 79 exit; 80 } 81 if (nvars == 0) { 82 printf("%s needs at least one field\n", thismsg); 83 exit; 84 } 85 86 sum = 0; 87 for (i = 0; i < nvars; i++) 88 sum += type_length(types[i]); 89 printf("#define\t%s\t%d\n", msg_size_name, sum) >> HFILE; 90 if (sum > maxmsg) 91 maxmsg = sum; 92 93 printf("typedef struct _%s {\n", typedef_name) >> HFILE; 94 for (i = 0; i < nvars; i++) { 95 if (types[i] == "DB_LSN" || types[i] == "DBT") 96 printf("\t%s\t\t%s;\n", types[i], vars[i]) >> HFILE; 97 else 98 printf("\t%s\t%s;\n", types[i], vars[i]) >> HFILE; 99 } 100 printf("} %s;\n\n", typedef_name) >> HFILE; 101 102 emit_marshal(); 103 emit_unmarshal(); 104 105 # Reinitialize variables for next time. 106 in_begin = 0; 107 alloc = 0; 108 check_length = 0; 109 version = 0; 110 has_dbt = 0; 111} 112END { 113 # End the conditional for the HFILE 114 printf("#define\t%s\t%d\n", max_name, maxmsg) >> HFILE; 115 printf("#endif\n") >> HFILE; 116} 117 118# Length of fixed part of message. Does not count variable-length data portion 119# of DBT. 120# 121function type_length(type) 122{ 123 if (type == "DB_LSN") 124 return (8); 125 if (type == "DBT" || type == "u_int32_t" || type == "db_pgno_t") 126 return (4); 127 if (type == "u_int16_t") 128 return (2); 129 printf("unknown field type: %s", type); 130 exit(1); 131} 132 133function emit_marshal() 134{ 135 pi = 1; 136 if (check_length) 137 p[pi++] = "int "; 138 else 139 p[pi++] = "void "; 140 function_name = sprintf("%s_marshal", base_name); 141 p[pi++] = function_name; 142 p[pi++] = " __P((ENV *, "; 143 if (version) 144 p[pi++] = "u_int32_t, "; 145 p[pi++] = sprintf("%s *, u_int8_t *", typedef_name); 146 if (check_length) 147 p[pi++] = ", size_t, size_t *"; 148 p[pi++] = "));"; 149 proto_format(p, CFILE); 150 151 if (check_length) 152 printf("int\n") >> CFILE; 153 else 154 printf("void\n") >> CFILE; 155 printf("%s(env", function_name) >> CFILE; 156 if (version) 157 printf(", version") >> CFILE; 158 printf(", argp, bp") >> CFILE; 159 if (check_length) 160 printf(", max, lenp") >> CFILE; 161 printf(")\n") >> CFILE; 162 163 printf("\tENV *env;\n") >> CFILE; 164 if (version) 165 printf("\tu_int32_t version;\n") >> CFILE; 166 printf("\t%s *argp;\n", typedef_name) >> CFILE; 167 printf("\tu_int8_t *bp;\n") >> CFILE; 168 if (check_length) 169 printf("\tsize_t *lenp, max;\n") >> CFILE; 170 printf("{\n") >> CFILE; 171 172 if (version) 173 printf("\tint copy_only;\n") >> CFILE; 174 if (check_length) { 175 printf("\tu_int8_t *start;\n\n") >> CFILE; 176 printf("\tif (max < %s", msg_size_name) >> CFILE; 177 for (i = 0; i < nvars; i++) 178 if (types[i] == "DBT") 179 printf("\n\t + (size_t)argp->%s.size", \ 180 vars[i]) >> CFILE; 181 # add in dbt sizes 182 printf(")\n") >> CFILE; 183 printf("\t\treturn (ENOMEM);\n") >> CFILE; 184 printf("\tstart = bp;\n\n") >> CFILE; 185 } 186 187 if (version) { 188 printf("\tcopy_only = 0;\n") >> CFILE; 189 printf("\tif (version < DB_REPVERSION_47)\n") >> CFILE; 190 printf("\t\tcopy_only = 1;\n") >> CFILE; 191 } 192 for (i = 0; i < nvars; i++) { 193 if (types[i] == "u_int32_t" || types[i] == "db_pgno_t") { 194 if (version) { 195 printf("\tif (copy_only) {\n") >> CFILE; 196 printf(\ 197 "\t\tmemcpy(bp, &argp->%s, sizeof(u_int32_t));\n", vars[i]) >> CFILE; 198 printf(\ 199 "\t\tbp += sizeof(u_int32_t);\n") >> CFILE; 200 printf("\t} else\n\t") >> CFILE; 201 } 202 printf("\tDB_HTONL_COPYOUT(env, bp, argp->%s);\n", \ 203 vars[i]) >> CFILE; 204 } else if (types[i] == "u_int16_t") { 205 if (version) { 206 printf("\tif (copy_only) {\n") >> CFILE; 207 printf(\ 208 "\t\tmemcpy(bp, &argp->%s, sizeof(u_int16_t));\n", vars[i]) >> CFILE; 209 printf(\ 210 "\t\tbp += sizeof(u_int16_t);\n") >> CFILE; 211 printf("\t} else\n\t") >> CFILE; 212 } 213 printf("\tDB_HTONS_COPYOUT(env, bp, argp->%s);\n", \ 214 vars[i]) >> CFILE; 215 } else if (types[i] == "DB_LSN") { 216 if (version) { 217 printf("\tif (copy_only) {\n") >> CFILE; 218 printf(\ 219 "\t\tmemcpy(bp, &argp->%s.file, sizeof(u_int32_t));\n", vars[i]) >> CFILE; 220 printf(\ 221 "\t\tbp += sizeof(u_int32_t);\n") >> CFILE; 222 printf(\ 223 "\t\tmemcpy(bp, &argp->%s.offset, sizeof(u_int32_t));\n", vars[i]) >> CFILE; 224 printf(\ 225 "\t\tbp += sizeof(u_int32_t);\n") >> CFILE; 226 printf("\t} else {\n\t") >> CFILE; 227 } 228 printf("\tDB_HTONL_COPYOUT(env, bp, argp->%s.file);\n",\ 229 vars[i]) >> CFILE; 230 if (version) 231 printf("\t") >> CFILE; 232 printf( \ 233 "\tDB_HTONL_COPYOUT(env, bp, argp->%s.offset);\n", \ 234 vars[i]) >> CFILE; 235 if (version) 236 printf("\t}\n") >> CFILE; 237 } else if (types[i] == "DBT") { 238 if (version) { 239 printf("\tif (copy_only) {\n") >> CFILE; 240 printf(\ 241 "\t\tmemcpy(bp, &argp->%s.size, sizeof(u_int32_t));\n", vars[i]) >> CFILE; 242 printf(\ 243 "\t\tbp += sizeof(u_int32_t);\n") >> CFILE; 244 printf("\t} else\n\t") >> CFILE; 245 } 246 printf("\tDB_HTONL_COPYOUT(env, bp, argp->%s.size);\n",\ 247 vars[i]) >> CFILE; 248 printf("\tif (argp->%s.size > 0) {\n", vars[i]) \ 249 >> CFILE; 250 printf( \ 251 "\t\tmemcpy(bp, argp->%s.data, argp->%s.size);\n", \ 252 vars[i], vars[i]) >> CFILE; 253 printf("\t\tbp += argp->%s.size;\n", vars[i]) >> CFILE; 254 printf("\t}\n") >> CFILE; 255 } else { 256 printf("unknown field type: %s", types[i]); 257 exit(1); 258 } 259 } 260 261 if (check_length) { 262 printf("\n\t*lenp = (size_t)(bp - start);\n") >> CFILE; 263 printf("\treturn (0);\n") >> CFILE; 264 } 265 printf("}\n\n") >> CFILE; 266} 267 268function emit_unmarshal() 269{ 270 pi = 1; 271 p[pi++] = "int "; 272 function_name = sprintf("%s_unmarshal", base_name); 273 p[pi++] = function_name; 274 p[pi++] = " __P((ENV *, "; 275 if (version) 276 p[pi++] = sprintf("u_int32_t, "); 277 if (alloc) 278 p[pi++] = sprintf("%s **, u_int8_t *, ", typedef_name); 279 else 280 p[pi++] = sprintf("%s *, u_int8_t *, ", typedef_name); 281 p[pi++] = sprintf("size_t, u_int8_t **));"); 282 proto_format(p, CFILE); 283 284 printf("int\n") >> CFILE; 285 if (alloc) 286 arg_name = "argpp"; 287 else 288 arg_name = "argp"; 289 printf("%s(env, ", function_name) >> CFILE; 290 if (version) 291 printf("version, ") >> CFILE; 292 printf("%s, bp, ", arg_name) >> CFILE; 293 printf("max, nextp)\n") >> CFILE; 294 printf("\tENV *env;\n") >> CFILE; 295 if (version) 296 printf("\tu_int32_t version;\n") >> CFILE; 297 if (alloc) 298 printf("\t%s **argpp;\n", typedef_name) >> CFILE; 299 else 300 printf("\t%s *argp;\n", typedef_name) >> CFILE; 301 printf("\tu_int8_t *bp;\n") >> CFILE; 302 printf("\tsize_t max;\n") >> CFILE; 303 printf("\tu_int8_t **nextp;\n") >> CFILE; 304 printf("{\n") >> CFILE; 305 has_locals = 0; 306 if (has_dbt) { 307 printf("\tsize_t needed;\n") >> CFILE; 308 has_locals = 1; 309 } 310 if (alloc) { 311 printf("\t%s *argp;\n", typedef_name) >> CFILE; 312 printf("\tint ret;\n") >> CFILE; 313 has_locals = 1; 314 } 315 if (version) { 316 printf("\tint copy_only;\n") >> CFILE; 317 has_locals = 1; 318 } 319 if (has_locals) 320 printf("\n") >> CFILE; 321 322 # Check that input byte buffer is long enough. 323 # 324 if (has_dbt) { 325 printf("\tneeded = %s;\n", msg_size_name) >> CFILE; 326 printf("\tif (max < needed)\n") >> CFILE; 327 } else 328 printf("\tif (max < %s)\n", msg_size_name) >> CFILE; 329 printf("\t\tgoto too_few;\n") >> CFILE; 330 331 if (alloc) { 332 printf( \ 333 "\tif ((ret = __os_malloc(env, sizeof(*argp), &argp)) != 0)\n") \ 334 >> CFILE; 335 printf("\t\treturn (ret);\n\n") >> CFILE; 336 } 337 if (version) { 338 printf("\tcopy_only = 0;\n") >> CFILE; 339 printf("\tif (version < DB_REPVERSION_47)\n") >> CFILE; 340 printf("\t\tcopy_only = 1;\n") >> CFILE; 341 } 342 343 for (i = 0; i < nvars; i++) { 344 if (types[i] == "u_int32_t" || types[i] == "db_pgno_t") { 345 if (version) { 346 printf("\tif (copy_only) {\n") >> CFILE; 347 printf(\ 348 "\t\tmemcpy(&argp->%s, bp, sizeof(u_int32_t));\n", vars[i]) >> CFILE; 349 printf(\ 350 "\t\tbp += sizeof(u_int32_t);\n") >> CFILE; 351 printf("\t} else\n\t") >> CFILE; 352 } 353 printf("\tDB_NTOHL_COPYIN(env, argp->%s, bp);\n", \ 354 vars[i]) >> CFILE; 355 } else if (types[i] == "u_int16_t") { 356 if (version) { 357 printf("\tif (copy_only) {\n") >> CFILE; 358 printf(\ 359 "\t\tmemcpy(&argp->%s, bp, sizeof(u_int16_t));\n", vars[i]) >> CFILE; 360 printf(\ 361 "\t\tbp += sizeof(u_int16_t);\n") >> CFILE; 362 printf("\t} else\n\t") >> CFILE; 363 } 364 printf("\tDB_NTOHS_COPYIN(env, argp->%s, bp);\n", \ 365 vars[i]) >> CFILE; 366 } else if (types[i] == "DB_LSN") { 367 if (version) { 368 printf("\tif (copy_only) {\n") >> CFILE; 369 printf(\ 370 "\t\tmemcpy(&argp->%s.file, bp, sizeof(u_int32_t));\n", vars[i]) >> CFILE; 371 printf(\ 372 "\t\tbp += sizeof(u_int32_t);\n") >> CFILE; 373 printf(\ 374 "\t\tmemcpy(&argp->%s.offset, bp, sizeof(u_int32_t));\n", vars[i]) >> CFILE; 375 printf(\ 376 "\t\tbp += sizeof(u_int32_t);\n") >> CFILE; 377 printf("\t} else {\n\t") >> CFILE; 378 } 379 printf("\tDB_NTOHL_COPYIN(env, argp->%s.file, bp);\n", \ 380 vars[i]) >> CFILE; 381 if (version) 382 printf("\t") >> CFILE; 383 printf( \ 384 "\tDB_NTOHL_COPYIN(env, argp->%s.offset, bp);\n", \ 385 vars[i]) >> CFILE; 386 if (version) 387 printf("\t}\n") >> CFILE; 388 } else if (types[i] == "DBT") { 389 if (version) { 390 printf("\tif (copy_only) {\n") >> CFILE; 391 printf(\ 392 "\t\tmemcpy(&argp->%s.size, bp, sizeof(u_int32_t));\n", vars[i]) >> CFILE; 393 printf(\ 394 "\t\tbp += sizeof(u_int32_t);\n") >> CFILE; 395 printf("\t} else\n\t") >> CFILE; 396 } 397 printf("\tDB_NTOHL_COPYIN(env, argp->%s.size, bp);\n", \ 398 vars[i]) >> CFILE; 399 printf("\targp->%s.data = bp;\n", vars[i]) >> CFILE; 400 printf("\tneeded += (size_t)argp->%s.size;\n", \ 401 vars[i]) >> CFILE; 402 printf("\tif (max < needed)\n") >> CFILE; 403 printf("\t\tgoto too_few;\n") >> CFILE; 404 printf("\tbp += argp->%s.size;\n", vars[i]) >> CFILE; 405 } else { 406 printf("unknown field type: %s", types[i]); 407 exit(1); 408 } 409 } 410 411 printf("\n\tif (nextp != NULL)\n") >> CFILE; 412 printf("\t\t*nextp = bp;\n") >> CFILE; 413 if (alloc) { 414 printf("\t*argpp = argp;\n") >> CFILE; 415 } 416 printf("\treturn (0);\n\n") >> CFILE; 417 418 printf("too_few:\n") >> CFILE; 419 printf("\t__db_errx(env,\n") >> CFILE; 420 printf("\t \"Not enough input bytes to fill a %s message\");\n", \ 421 base_name) >> CFILE; 422 printf("\treturn (EINVAL);\n") >> CFILE; 423 printf("}\n\n") >> CFILE; 424} 425 426# proto_format -- 427# Pretty-print a function prototype. 428function proto_format(p, fp) 429{ 430 printf("/*\n") >> fp; 431 432 s = ""; 433 for (i = 1; i in p; ++i) 434 s = s p[i]; 435 436 t = " * PUBLIC: " 437 if (length(s) + length(t) < 80) 438 printf("%s%s", t, s) >> fp; 439 else { 440 split(s, p, "__P"); 441 len = length(t) + length(p[1]); 442 printf("%s%s", t, p[1]) >> fp 443 444 n = split(p[2], comma, ","); 445 comma[1] = "__P" comma[1]; 446 for (i = 1; i <= n; i++) { 447 if (len + length(comma[i]) > 70) { 448 printf("\n * PUBLIC: ") >> fp; 449 len = 0; 450 } 451 printf("%s%s", comma[i], i == n ? "" : ",") >> fp; 452 len += length(comma[i]) + 2; 453 } 454 } 455 printf("\n */\n") >> fp; 456 delete p; 457} 458