1# 2# See the file LICENSE for redistribution information. 3# 4# Copyright (c) 1996, 2013 Oracle and/or its affiliates. All rights reserved. 5# 6# $Id$ 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_AUTOMSG_H\n#define\t%s_AUTOMSG_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 if (type == "u_int8_t") 130 return (1); 131 printf("unknown field type: %s", type); 132 exit(1); 133} 134 135function emit_marshal() 136{ 137 pi = 1; 138 if (check_length) 139 p[pi++] = "int "; 140 else 141 p[pi++] = "void "; 142 function_name = sprintf("%s_marshal", base_name); 143 p[pi++] = function_name; 144 p[pi++] = " __P((ENV *, "; 145 if (version) 146 p[pi++] = "u_int32_t, "; 147 p[pi++] = sprintf("%s *, u_int8_t *", typedef_name); 148 if (check_length) 149 p[pi++] = ", size_t, size_t *"; 150 p[pi++] = "));"; 151 proto_format(p, CFILE); 152 153 if (check_length) 154 printf("int\n") >> CFILE; 155 else 156 printf("void\n") >> CFILE; 157 printf("%s(env", function_name) >> CFILE; 158 if (version) 159 printf(", version") >> CFILE; 160 printf(", argp, bp") >> CFILE; 161 if (check_length) 162 printf(", max, lenp") >> CFILE; 163 printf(")\n") >> CFILE; 164 165 printf("\tENV *env;\n") >> CFILE; 166 if (version) 167 printf("\tu_int32_t version;\n") >> CFILE; 168 printf("\t%s *argp;\n", typedef_name) >> CFILE; 169 printf("\tu_int8_t *bp;\n") >> CFILE; 170 if (check_length) 171 printf("\tsize_t *lenp, max;\n") >> CFILE; 172 printf("{\n") >> CFILE; 173 174 if (version) 175 printf("\tint copy_only;\n") >> CFILE; 176 if (check_length) { 177 printf("\tu_int8_t *start;\n\n") >> CFILE; 178 printf("\tif (max < %s", msg_size_name) >> CFILE; 179 for (i = 0; i < nvars; i++) 180 if (types[i] == "DBT") 181 printf("\n\t + (size_t)argp->%s.size", \ 182 vars[i]) >> CFILE; 183 # add in dbt sizes 184 printf(")\n") >> CFILE; 185 printf("\t\treturn (ENOMEM);\n") >> CFILE; 186 printf("\tstart = bp;\n\n") >> CFILE; 187 } 188 189 if (version) { 190 printf("\tcopy_only = 0;\n") >> CFILE; 191 printf("\tif (version < DB_REPVERSION_47)\n") >> CFILE; 192 printf("\t\tcopy_only = 1;\n") >> CFILE; 193 } 194 for (i = 0; i < nvars; i++) { 195 if (types[i] == "u_int32_t" || types[i] == "db_pgno_t") { 196 if (version) { 197 printf("\tif (copy_only) {\n") >> CFILE; 198 printf(\ 199 "\t\tmemcpy(bp, &argp->%s, sizeof(u_int32_t));\n", vars[i]) >> CFILE; 200 printf(\ 201 "\t\tbp += sizeof(u_int32_t);\n") >> CFILE; 202 printf("\t} else\n\t") >> CFILE; 203 } 204 printf("\tDB_HTONL_COPYOUT(env, bp, argp->%s);\n", \ 205 vars[i]) >> CFILE; 206 } else if (types[i] == "u_int16_t") { 207 if (version) { 208 printf("\tif (copy_only) {\n") >> CFILE; 209 printf(\ 210 "\t\tmemcpy(bp, &argp->%s, sizeof(u_int16_t));\n", vars[i]) >> CFILE; 211 printf(\ 212 "\t\tbp += sizeof(u_int16_t);\n") >> CFILE; 213 printf("\t} else\n\t") >> CFILE; 214 } 215 printf("\tDB_HTONS_COPYOUT(env, bp, argp->%s);\n", \ 216 vars[i]) >> CFILE; 217 } else if (types[i] == "u_int8_t") { 218 printf(\ 219 "\t*bp++ = argp->%s;\n", vars[i]) >> CFILE; 220 } else if (types[i] == "DB_LSN") { 221 if (version) { 222 printf("\tif (copy_only) {\n") >> CFILE; 223 printf(\ 224 "\t\tmemcpy(bp, &argp->%s.file, sizeof(u_int32_t));\n", vars[i]) >> CFILE; 225 printf(\ 226 "\t\tbp += sizeof(u_int32_t);\n") >> CFILE; 227 printf(\ 228 "\t\tmemcpy(bp, &argp->%s.offset, sizeof(u_int32_t));\n", vars[i]) >> CFILE; 229 printf(\ 230 "\t\tbp += sizeof(u_int32_t);\n") >> CFILE; 231 printf("\t} else {\n\t") >> CFILE; 232 } 233 printf("\tDB_HTONL_COPYOUT(env, bp, argp->%s.file);\n",\ 234 vars[i]) >> CFILE; 235 if (version) 236 printf("\t") >> CFILE; 237 printf( \ 238 "\tDB_HTONL_COPYOUT(env, bp, argp->%s.offset);\n", \ 239 vars[i]) >> CFILE; 240 if (version) 241 printf("\t}\n") >> CFILE; 242 } else if (types[i] == "DBT") { 243 if (version) { 244 printf("\tif (copy_only) {\n") >> CFILE; 245 printf(\ 246 "\t\tmemcpy(bp, &argp->%s.size, sizeof(u_int32_t));\n", vars[i]) >> CFILE; 247 printf(\ 248 "\t\tbp += sizeof(u_int32_t);\n") >> CFILE; 249 printf("\t} else\n\t") >> CFILE; 250 } 251 printf("\tDB_HTONL_COPYOUT(env, bp, argp->%s.size);\n",\ 252 vars[i]) >> CFILE; 253 printf("\tif (argp->%s.size > 0) {\n", vars[i]) \ 254 >> CFILE; 255 printf( \ 256 "\t\tmemcpy(bp, argp->%s.data, argp->%s.size);\n", \ 257 vars[i], vars[i]) >> CFILE; 258 printf("\t\tbp += argp->%s.size;\n", vars[i]) >> CFILE; 259 printf("\t}\n") >> CFILE; 260 } else { 261 printf("unknown field type: %s", types[i]); 262 exit(1); 263 } 264 } 265 266 if (check_length) { 267 printf("\n\t*lenp = (size_t)(bp - start);\n") >> CFILE; 268 printf("\treturn (0);\n") >> CFILE; 269 } 270 printf("}\n\n") >> CFILE; 271} 272 273function emit_unmarshal() 274{ 275 pi = 1; 276 p[pi++] = "int "; 277 function_name = sprintf("%s_unmarshal", base_name); 278 p[pi++] = function_name; 279 p[pi++] = " __P((ENV *, "; 280 if (version) 281 p[pi++] = sprintf("u_int32_t, "); 282 if (alloc) 283 p[pi++] = sprintf("%s **, u_int8_t *, ", typedef_name); 284 else 285 p[pi++] = sprintf("%s *, u_int8_t *, ", typedef_name); 286 p[pi++] = sprintf("size_t, u_int8_t **));"); 287 proto_format(p, CFILE); 288 289 printf("int\n") >> CFILE; 290 if (alloc) 291 arg_name = "argpp"; 292 else 293 arg_name = "argp"; 294 printf("%s(env, ", function_name) >> CFILE; 295 if (version) 296 printf("version, ") >> CFILE; 297 printf("%s, bp, ", arg_name) >> CFILE; 298 printf("max, nextp)\n") >> CFILE; 299 printf("\tENV *env;\n") >> CFILE; 300 if (version) 301 printf("\tu_int32_t version;\n") >> CFILE; 302 if (alloc) 303 printf("\t%s **argpp;\n", typedef_name) >> CFILE; 304 else 305 printf("\t%s *argp;\n", typedef_name) >> CFILE; 306 printf("\tu_int8_t *bp;\n") >> CFILE; 307 printf("\tsize_t max;\n") >> CFILE; 308 printf("\tu_int8_t **nextp;\n") >> CFILE; 309 printf("{\n") >> CFILE; 310 has_locals = 0; 311 if (has_dbt) { 312 printf("\tsize_t needed;\n") >> CFILE; 313 has_locals = 1; 314 } 315 if (alloc) { 316 printf("\t%s *argp;\n", typedef_name) >> CFILE; 317 printf("\tint ret;\n") >> CFILE; 318 has_locals = 1; 319 } 320 if (version) { 321 printf("\tint copy_only;\n") >> CFILE; 322 has_locals = 1; 323 } 324 if (has_locals) 325 printf("\n") >> CFILE; 326 327 # Check that input byte buffer is long enough. 328 # 329 if (has_dbt) { 330 printf("\tneeded = %s;\n", msg_size_name) >> CFILE; 331 printf("\tif (max < needed)\n") >> CFILE; 332 } else 333 printf("\tif (max < %s)\n", msg_size_name) >> CFILE; 334 printf("\t\tgoto too_few;\n") >> CFILE; 335 336 if (alloc) { 337 printf( \ 338 "\tif ((ret = __os_malloc(env, sizeof(*argp), &argp)) != 0)\n") \ 339 >> CFILE; 340 printf("\t\treturn (ret);\n\n") >> CFILE; 341 } 342 if (version) { 343 printf("\tcopy_only = 0;\n") >> CFILE; 344 printf("\tif (version < DB_REPVERSION_47)\n") >> CFILE; 345 printf("\t\tcopy_only = 1;\n") >> CFILE; 346 } 347 348 for (i = 0; i < nvars; i++) { 349 if (types[i] == "u_int32_t" || types[i] == "db_pgno_t") { 350 if (version) { 351 printf("\tif (copy_only) {\n") >> CFILE; 352 printf(\ 353 "\t\tmemcpy(&argp->%s, bp, sizeof(u_int32_t));\n", vars[i]) >> CFILE; 354 printf(\ 355 "\t\tbp += sizeof(u_int32_t);\n") >> CFILE; 356 printf("\t} else\n\t") >> CFILE; 357 } 358 printf("\tDB_NTOHL_COPYIN(env, argp->%s, bp);\n", \ 359 vars[i]) >> CFILE; 360 } else if (types[i] == "u_int16_t") { 361 if (version) { 362 printf("\tif (copy_only) {\n") >> CFILE; 363 printf(\ 364 "\t\tmemcpy(&argp->%s, bp, sizeof(u_int16_t));\n", vars[i]) >> CFILE; 365 printf(\ 366 "\t\tbp += sizeof(u_int16_t);\n") >> CFILE; 367 printf("\t} else\n\t") >> CFILE; 368 } 369 printf("\tDB_NTOHS_COPYIN(env, argp->%s, bp);\n", \ 370 vars[i]) >> CFILE; 371 } else if (types[i] == "u_int8_t") { 372 printf(\ 373 "\targp->%s = *bp++;\n", vars[i]) >> CFILE; 374 } else if (types[i] == "DB_LSN") { 375 if (version) { 376 printf("\tif (copy_only) {\n") >> CFILE; 377 printf(\ 378 "\t\tmemcpy(&argp->%s.file, bp, sizeof(u_int32_t));\n", vars[i]) >> CFILE; 379 printf(\ 380 "\t\tbp += sizeof(u_int32_t);\n") >> CFILE; 381 printf(\ 382 "\t\tmemcpy(&argp->%s.offset, bp, sizeof(u_int32_t));\n", vars[i]) >> CFILE; 383 printf(\ 384 "\t\tbp += sizeof(u_int32_t);\n") >> CFILE; 385 printf("\t} else {\n\t") >> CFILE; 386 } 387 printf("\tDB_NTOHL_COPYIN(env, argp->%s.file, bp);\n", \ 388 vars[i]) >> CFILE; 389 if (version) 390 printf("\t") >> CFILE; 391 printf( \ 392 "\tDB_NTOHL_COPYIN(env, argp->%s.offset, bp);\n", \ 393 vars[i]) >> CFILE; 394 if (version) 395 printf("\t}\n") >> CFILE; 396 } else if (types[i] == "DBT") { 397 if (version) { 398 printf("\tif (copy_only) {\n") >> CFILE; 399 printf(\ 400 "\t\tmemcpy(&argp->%s.size, bp, sizeof(u_int32_t));\n", vars[i]) >> CFILE; 401 printf(\ 402 "\t\tbp += sizeof(u_int32_t);\n") >> CFILE; 403 printf("\t} else\n\t") >> CFILE; 404 } 405 printf("\tDB_NTOHL_COPYIN(env, argp->%s.size, bp);\n", \ 406 vars[i]) >> CFILE; 407 printf("\tif (argp->%s.size == 0)\n", vars[i]) >> CFILE; 408 printf("\t\targp->%s.data = NULL;\n", vars[i]) >> CFILE; 409 printf("\telse\n") >> CFILE; 410 printf("\t\targp->%s.data = bp;\n", vars[i]) >> CFILE; 411 printf("\tneeded += (size_t)argp->%s.size;\n", \ 412 vars[i]) >> CFILE; 413 printf("\tif (max < needed)\n") >> CFILE; 414 printf("\t\tgoto too_few;\n") >> CFILE; 415 printf("\tbp += argp->%s.size;\n", vars[i]) >> CFILE; 416 } else { 417 printf("unknown field type: %s", types[i]); 418 exit(1); 419 } 420 } 421 422 printf("\n\tif (nextp != NULL)\n") >> CFILE; 423 printf("\t\t*nextp = bp;\n") >> CFILE; 424 if (alloc) { 425 printf("\t*argpp = argp;\n") >> CFILE; 426 } 427 printf("\treturn (0);\n\n") >> CFILE; 428 429 printf("too_few:\n") >> CFILE; 430 printf("\t__db_errx(env, DB_STR(\"3675\",\n") >> CFILE; 431 printf("\t \"Not enough input bytes to fill a %s message\"));\n", \ 432 base_name) >> CFILE; 433 printf("\treturn (EINVAL);\n") >> CFILE; 434 printf("}\n\n") >> CFILE; 435} 436 437# proto_format -- 438# Pretty-print a function prototype. 439function proto_format(p, fp) 440{ 441 printf("/*\n") >> fp; 442 443 s = ""; 444 for (i = 1; i in p; ++i) 445 s = s p[i]; 446 447 t = " * PUBLIC: " 448 if (length(s) + length(t) < 80) 449 printf("%s%s", t, s) >> fp; 450 else { 451 split(s, p, "__P"); 452 len = length(t) + length(p[1]); 453 printf("%s%s", t, p[1]) >> fp 454 455 n = split(p[2], comma, ","); 456 comma[1] = "__P" comma[1]; 457 for (i = 1; i <= n; i++) { 458 if (len + length(comma[i]) > 70) { 459 printf("\n * PUBLIC: ") >> fp; 460 len = 0; 461 } 462 printf("%s%s", comma[i], i == n ? "" : ",") >> fp; 463 len += length(comma[i]) + 2; 464 } 465 } 466 printf("\n */\n") >> fp; 467 delete p; 468} 469