ircout.om (15183B)
1 func ircout(c: *compiler) { 2 var d: *decl; 3 4 fputs(c.cout, "typedef unsigned char b;\n"); 5 fputs(c.cout, "typedef unsigned long u;\n"); 6 fputs(c.cout, "typedef long s;\n"); 7 8 // Forward declare used functions 9 d = first_decl(c); 10 loop { 11 if !d { 12 break; 13 } 14 15 if d.func_used && d.func_defined { 16 ircforward(c, d); 17 } 18 19 d = next_decl(c, d); 20 } 21 22 // Emit stdlib declarations 23 ircdeclstdlib(c); 24 25 // Define used functions 26 d = first_decl(c); 27 loop { 28 if !d { 29 break; 30 } 31 32 if d.func_used && d.func_defined { 33 ircdefine(c, d); 34 } 35 36 d = next_decl(c, d); 37 } 38 39 fflush(c.cout); 40 } 41 42 func ircdeclstdlib(c: *compiler) { 43 fputs(c.cout, "extern u syscall();\n"); 44 fputs(c.cout, "extern void exit();\n"); 45 fputs(c.cout, "extern s read();\n"); 46 fputs(c.cout, "extern s write();\n"); 47 fputs(c.cout, "extern u mmap();\n"); 48 fputs(c.cout, "extern int close();\n"); 49 fputs(c.cout, "extern int unlink();\n"); 50 fputs(c.cout, "extern int open();\n"); 51 fputs(c.cout, "extern char **environ;\n"); 52 fputs(c.cout, "int main(int argc, char**argv) {\n"); 53 fputs(c.cout, "\treturn zmain((u)argc, (u)argv, (u)environ);\n"); 54 fputs(c.cout, "}\n"); 55 } 56 57 func ircstdlib(c: *compiler, d: *decl) { 58 if strcmp(d.name, "syscall") == 0 { 59 fputs(c.cout, "/* no glue for syscall using stdlib */\n"); 60 } else if strcmp(d.name, "_start") == 0 { 61 fputs(c.cout, "/* no glue for _start using stdlib */\n"); 62 } else if strcmp(d.name, "exit") == 0 { 63 fputs(c.cout, "u zexit(u vn) {\n"); 64 fputs(c.cout, "\texit((int)vn);\n"); 65 fputs(c.cout, "}\n"); 66 } else if strcmp(d.name, "read") == 0 { 67 fputs(c.cout, "u zread(u vfd, u vbuf, u vn) {\n"); 68 fputs(c.cout, "\treturn (u)read((int)vfd, (void*)vbuf, (unsigned long)vn);\n"); 69 fputs(c.cout, "}\n"); 70 } else if strcmp(d.name, "write") == 0 { 71 fputs(c.cout, "u zwrite(u vfd, u vbuf, u vn) {\n"); 72 fputs(c.cout, "\treturn (u)write((int)vfd, (void*)vbuf, (unsigned long)vn);\n"); 73 fputs(c.cout, "}\n"); 74 } else if strcmp(d.name, "mmap") == 0 { 75 fputs(c.cout, "u zmmap(u vaddr, u vlen, u vprot, u vflags, u vfd, u voff) {\n"); 76 fputs(c.cout, "\treturn (u)mmap((void*)vaddr, (unsigned long)vlen, (int)vprot, (int)vflags, (int)vfd, (long)voff);\n"); 77 fputs(c.cout, "}\n"); 78 } else if strcmp(d.name, "close") == 0 { 79 fputs(c.cout, "u zclose(u vfd) {\n"); 80 fputs(c.cout, "\treturn (u)close((int)vfd);\n"); 81 fputs(c.cout, "}\n"); 82 } else if strcmp(d.name, "unlink") == 0 { 83 fputs(c.cout, "u zunlink(u vname) {\n"); 84 fputs(c.cout, "\treturn (u)unlink((char *)vname);\n"); 85 fputs(c.cout, "}\n"); 86 } else if strcmp(d.name, "open") == 0 { 87 fputs(c.cout, "u zopen(u vname, u vflags, u vmode) {\n"); 88 fputs(c.cout, "\treturn (u)open((char *)vname, (int)vflags, (int)vmode);\n"); 89 fputs(c.cout, "}\n"); 90 } else if strcmp(d.name, "get_machine") == 0 { 91 fputs(c.cout, "u zget_machine() {\n"); 92 fputs(c.cout, "\treturn 0;\n"); 93 fputs(c.cout, "}\n"); 94 } else { 95 die("unimplemented stdlib glue"); 96 } 97 } 98 99 func ircdecl(c: *compiler, ic: *irfunc) { 100 var i: int; 101 var iv: *irvar; 102 103 fputs(c.cout, "u z"); 104 fputs(c.cout, ic.name); 105 fputs(c.cout, "("); 106 107 i = 0; 108 loop { 109 if i == ic.arg_count { 110 break; 111 } 112 113 iv = ic.vars[i]; 114 115 fputs(c.cout, "u v"); 116 fputs(c.cout, iv.name); 117 118 i = i + 1; 119 120 if i != ic.arg_count { 121 fputs(c.cout, ", "); 122 } 123 } 124 125 fputs(c.cout, ")"); 126 } 127 128 func ircforward(c: *compiler, d: *decl) { 129 var ic: *irfunc; 130 131 ic = d.func_ir; 132 if !ic { 133 return; 134 } 135 136 fputs(c.cout, "u z"); 137 fputs(c.cout, ic.name); 138 fputs(c.cout, "();\n"); 139 } 140 141 func ircdefine(c: *compiler, d: *decl) { 142 var i: int; 143 var ic: *irfunc; 144 var iv: *irvar; 145 var top: *irblock; 146 var size: int; 147 var id: int; 148 149 if d.func_stdlib { 150 ircstdlib(c, d); 151 return; 152 } 153 154 ic = d.func_ir; 155 if !ic { 156 return; 157 } 158 159 i = 0; 160 loop { 161 if i == ic.vars_len { 162 break; 163 } 164 165 iv = ic.vars[i]; 166 167 i = i + 1; 168 } 169 170 top = ic.blocks[0]; 171 ircuse(c, ic, top); 172 173 ircdecl(c, ic); 174 fputs(c.cout, " {\n"); 175 176 i = ic.arg_count; 177 loop { 178 if i == ic.vars_len { 179 break; 180 } 181 182 iv = ic.vars[i]; 183 184 if iv.dead { 185 i = i + 1; 186 continue; 187 } 188 189 fputs(c.cout, "\t"); 190 fputs(c.cout, "u "); 191 192 if iv.name { 193 fputs(c.cout, "v"); 194 fputs(c.cout, iv.name); 195 } else { 196 fputs(c.cout, "v"); 197 fputd(c.cout, i); 198 } 199 200 if iv.t && iv.t.kind != TY_VOID { 201 size = type_sizeof(c, iv.t); 202 } else { 203 size = sizeof(i); 204 } 205 206 if size == sizeof(i) { 207 fputs(c.cout, " = 0"); 208 } else { 209 fputs(c.cout, "["); 210 fputd(c.cout, (size + sizeof(i) + 1) / sizeof(i)); 211 fputs(c.cout, "] = {0}"); 212 } 213 214 fputs(c.cout, ";\n"); 215 216 i = i + 1; 217 } 218 219 ircbody(c, ic, top); 220 irreset(top); 221 222 fputs(c.cout, "}\n"); 223 } 224 225 func ircuse(c: *compiler, ic: *irfunc, ib: *irblock) { 226 var i: int; 227 228 if !ib { 229 return; 230 } 231 232 if ib.mark { 233 ib.mark = 6; 234 return; 235 } 236 237 ib.mark = 2; 238 239 if ib.out { 240 ircuse(c, ic, ib.out); 241 } 242 243 if ib.alt && ib.ops[ib.ops_len - 1].kind == IOP_BRANCH { 244 ircuse(c, ic, ib.alt); 245 ib.alt.mark = 6; 246 } 247 } 248 249 func ircbody(c: *compiler, ic: *irfunc, ib: *irblock) { 250 if !ib || ib.mark & 1 { 251 return; 252 } 253 254 ib.mark = ib.mark | 1; 255 256 ircblock(c, ic, ib); 257 258 if ib.out { 259 ircbody(c, ic, ib.out); 260 } 261 262 if ib.alt && ib.ops[ib.ops_len - 1].kind == IOP_BRANCH { 263 ircbody(c, ic, ib.alt); 264 } 265 } 266 267 func ircblock(c: *compiler, ic: *irfunc, ib: *irblock) { 268 var i: int; 269 var op: *irop; 270 var kind: int; 271 var didlabel: int; 272 273 didlabel = (ib.mark & 4) == 0; 274 275 loop { 276 if i + 1 == ib.ops_len { 277 break; 278 } 279 280 op = ib.ops[i]; 281 282 kind = op.kind; 283 if kind == IOP_ARG || kind == IOP_RETVAL { 284 i = i + 1; 285 continue; 286 } 287 288 ircline(c, op); 289 290 if !didlabel { 291 fputs(c.cout, "b"); 292 fputd(c.cout, ib.n); 293 fputs(c.cout, ":"); 294 didlabel = 1; 295 } 296 297 fputs(c.cout, "\t"); 298 ircop(c, ic, ib, op, 20); 299 fputs(c.cout, ";\n"); 300 301 i = i + 1; 302 } 303 304 op = ib.ops[i]; 305 306 kind = op.kind; 307 if kind == IOP_CALL { 308 ircline(c, op); 309 310 if !didlabel { 311 fputs(c.cout, "b"); 312 fputd(c.cout, ib.n); 313 fputs(c.cout, ":"); 314 didlabel = 1; 315 } 316 317 irccall(c, ic, ib, op); 318 } else if kind == IOP_JUMP { 319 ircline(c, op); 320 321 if !didlabel { 322 fputs(c.cout, "b"); 323 fputd(c.cout, ib.n); 324 fputs(c.cout, ":"); 325 didlabel = 1; 326 } 327 328 if ib.out.mark & 1 { 329 fputs(c.cout, "\t"); 330 fputs(c.cout, "goto b"); 331 fputd(c.cout, ib.out.n); 332 fputs(c.cout, ";\n"); 333 } 334 } else if kind == IOP_BRANCH { 335 ircline(c, op); 336 337 if !didlabel { 338 fputs(c.cout, "b"); 339 fputd(c.cout, ib.n); 340 fputs(c.cout, ":"); 341 didlabel = 1; 342 } 343 344 fputs(c.cout, "\t"); 345 fputs(c.cout, "if ("); 346 ircop_neg(c, ic, ib, op.a, 20); 347 fputs(c.cout, ") goto b"); 348 fputd(c.cout, ib.alt.n); 349 fputs(c.cout, ";\n"); 350 351 if ib.out.mark & 1 { 352 ircline(c, op); 353 fputs(c.cout, "\t"); 354 fputs(c.cout, "goto b"); 355 fputd(c.cout, ib.out.n); 356 fputs(c.cout, ";\n"); 357 } 358 } else if kind == IOP_RETURN { 359 ircline(c, op); 360 361 if !didlabel { 362 fputs(c.cout, "b"); 363 fputd(c.cout, ib.n); 364 fputs(c.cout, ":"); 365 didlabel = 1; 366 } 367 368 fputs(c.cout, "\t"); 369 fputs(c.cout, "return "); 370 ircop(c, ic, ib, op.a, 20); 371 fputs(c.cout, ";\n"); 372 } else { 373 die("invalid op"); 374 } 375 } 376 377 func ircline(c: *compiler, op: *irop) { 378 return; // Try to minimize the output, don't output lines. 379 380 if !op.filename { 381 return; 382 } 383 384 fputs(c.cout, "#line "); 385 fputd(c.cout, op.lineno); 386 fputs(c.cout, " "); 387 ircstr(c, op.filename, strlen(op.filename)); 388 fputs(c.cout, "\n"); 389 } 390 391 func ircstr(c: *compiler, s: *byte, n: int) { 392 var i: int; 393 var ch: int; 394 395 i = 0; 396 fputs(c.cout, "\""); 397 loop { 398 if i == n { 399 break; 400 } 401 402 if i % 100 == 99 { 403 fputs(c.cout, "\"\n\t\t\""); 404 } 405 406 ch = s[i] as int; 407 408 if ch < 32 || ch > 127 || ch == '\\' || ch == '"' { 409 fputc(c.cout, '\\'); 410 fputc(c.cout, '0' + (ch >> 6) & 7); 411 fputc(c.cout, '0' + (ch >> 3) & 7); 412 fputc(c.cout, '0' + ch & 7); 413 } else { 414 fputc(c.cout, ch); 415 } 416 417 i = i + 1; 418 } 419 fputs(c.cout, "\""); 420 } 421 422 func ircop_neg(c: *compiler, ic: *irfunc, ib: *irblock, op: *irop, pri: int) { 423 var kind: int; 424 425 kind = op.kind; 426 if kind == IOP_EQ { 427 ircop(c, ic, ib, op.a, 7); 428 fputs(c.cout, " != "); 429 ircop(c, ic, ib, op.b, 7); 430 } else if kind == IOP_NE { 431 ircop(c, ic, ib, op.a, 7); 432 fputs(c.cout, " == "); 433 ircop(c, ic, ib, op.b, 7); 434 } else if kind == IOP_GT { 435 fputs(c.cout, "(s)"); 436 ircop(c, ic, ib, op.a, 2); 437 fputs(c.cout, " <= (s)"); 438 ircop(c, ic, ib, op.b, 2); 439 } else if kind == IOP_GE { 440 fputs(c.cout, "(s)"); 441 ircop(c, ic, ib, op.a, 2); 442 fputs(c.cout, " < (s)"); 443 ircop(c, ic, ib, op.b, 2); 444 } else if kind == IOP_LT { 445 fputs(c.cout, "(s)"); 446 ircop(c, ic, ib, op.a, 2); 447 fputs(c.cout, " >= (s)"); 448 ircop(c, ic, ib, op.b, 2); 449 } else if kind == IOP_LE { 450 fputs(c.cout, "(s)"); 451 ircop(c, ic, ib, op.a, 2); 452 fputs(c.cout, " > (s)"); 453 ircop(c, ic, ib, op.b, 2); 454 } else { 455 fputs(c.cout, "!"); 456 ircop(c, ic, ib, op, 2); 457 } 458 } 459 460 func ircop(c: *compiler, ic: *irfunc, ib: *irblock, op: *irop, pri: int) { 461 var kind: int; 462 var iv: *irvar; 463 var size: int; 464 var mypri: int; 465 466 // C Operator Precedence 467 // 1 call() 468 // 2 ! ~ * - & (cast) 469 // 3 * / % 470 // 4 + - 471 // 5 << >> 472 // 6 < <= > >= 473 // 7 == != 474 // 8 & 475 // 9 | 476 kind = op.kind; 477 if kind == IOP_VAR || kind == IOP_VARREF { 478 mypri = 2; 479 } else if kind == IOP_FUNC { 480 mypri = 2; 481 } else if kind == IOP_CONST { 482 mypri = 1; 483 } else if kind == IOP_STR { 484 mypri = 2; 485 } else if kind == IOP_LOAD { 486 mypri = 2; 487 } else if kind == IOP_STORE { 488 mypri = 2; 489 } else if kind == IOP_NEG { 490 mypri = 2; 491 } else if kind == IOP_NOT { 492 mypri = 2; 493 } else if kind == IOP_ADD { 494 mypri = 4; 495 } else if kind == IOP_AND { 496 mypri = 8; 497 } else if kind == IOP_OR { 498 mypri = 10; 499 } else if kind == IOP_XOR { 500 mypri = 9; 501 } else if kind == IOP_DIV { 502 mypri = 2; 503 } else if kind == IOP_MOD { 504 mypri = 2; 505 } else if kind == IOP_LSH { 506 mypri = 6; 507 } else if kind == IOP_RSH { 508 mypri = 6; 509 } else if kind == IOP_MUL { 510 mypri = 3; 511 } else if kind == IOP_SUB { 512 mypri = 4; 513 } else if kind == IOP_EQ { 514 mypri = 7; 515 } else if kind == IOP_NE { 516 mypri = 7; 517 } else if kind == IOP_GT { 518 mypri = 2; 519 } else if kind == IOP_GE { 520 mypri = 2; 521 } else if kind == IOP_LT { 522 mypri = 2; 523 } else if kind == IOP_LE { 524 mypri = 2; 525 } else { 526 die("invalid op"); 527 } 528 529 if mypri >= pri { 530 fputs(c.cout, "("); 531 } 532 533 if kind == IOP_VAR || kind == IOP_VARREF { 534 iv = ic.vars[op.n]; 535 536 if iv.t && iv.t.kind != TY_VOID { 537 size = type_sizeof(c, iv.t); 538 } else { 539 size = sizeof(size); 540 } 541 542 if size == sizeof(size) { 543 if kind == IOP_VARREF { 544 fputs(c.cout, "(u)&"); 545 } 546 } else { 547 if kind == IOP_VARREF { 548 fputs(c.cout, "(u)"); 549 } else { 550 fputs(c.cout, "*"); 551 } 552 } 553 554 if iv.name { 555 fputs(c.cout, "v"); 556 fputs(c.cout, iv.name); 557 } else { 558 fputs(c.cout, "v"); 559 fputd(c.cout, op.n); 560 } 561 } else if kind == IOP_FUNC { 562 fputs(c.cout, "(u)z"); 563 fputs(c.cout, op.s); 564 } else if kind == IOP_CONST { 565 fputd(c.cout, op.n); 566 fputs(c.cout, "UL"); 567 } else if kind == IOP_STR { 568 fputs(c.cout, "(u)"); 569 ircstr(c, op.s, op.slen); 570 } else if kind == IOP_LOAD { 571 if op.t.kind == TY_BYTE { 572 fputs(c.cout, "(u)*(b*)"); 573 ircop(c, ic, ib, op.a, 2); 574 } else { 575 fputs(c.cout, "*(u*)"); 576 ircop(c, ic, ib, op.a, 2); 577 } 578 } else if kind == IOP_STORE { 579 if op.a.kind == IOP_VAR { 580 ircop(c, ic, ib, op.a, 14); 581 fputs(c.cout, " = "); 582 ircop(c, ic, ib, op.b, 14); 583 } else if op.a.kind == IOP_LOAD { 584 if op.t.kind == TY_BYTE { 585 fputs(c.cout, "*(b*)"); 586 } else { 587 fputs(c.cout, "*(u*)"); 588 } 589 ircop(c, ic, ib, op.a.a, 2); 590 fputs(c.cout, " = "); 591 ircop(c, ic, ib, op.b, 14); 592 } else { 593 die("invalid store"); 594 } 595 } else if kind == IOP_NEG { 596 fputs(c.cout, "-"); 597 ircop(c, ic, ib, op.a, 2); 598 } else if kind == IOP_NOT { 599 fputs(c.cout, "~"); 600 ircop(c, ic, ib, op.a, 2); 601 } else if kind == IOP_ADD { 602 ircop(c, ic, ib, op.a, 4); 603 fputs(c.cout, " + "); 604 ircop(c, ic, ib, op.b, 4); 605 } else if kind == IOP_AND { 606 ircop(c, ic, ib, op.a, 8); 607 fputs(c.cout, " & "); 608 ircop(c, ic, ib, op.b, 8); 609 } else if kind == IOP_OR { 610 ircop(c, ic, ib, op.a, 10); 611 fputs(c.cout, " | "); 612 ircop(c, ic, ib, op.b, 10); 613 } else if kind == IOP_XOR { 614 ircop(c, ic, ib, op.a, 9); 615 fputs(c.cout, " ^ "); 616 ircop(c, ic, ib, op.b, 9); 617 } else if kind == IOP_DIV { 618 fputs(c.cout, "(u)((s)"); 619 ircop(c, ic, ib, op.a, 2); 620 fputs(c.cout, " / (s)"); 621 ircop(c, ic, ib, op.b, 2); 622 fputs(c.cout, ")"); 623 } else if kind == IOP_MOD { 624 fputs(c.cout, "(u)((s)"); 625 ircop(c, ic, ib, op.a, 2); 626 fputs(c.cout, " % (s)"); 627 ircop(c, ic, ib, op.b, 2); 628 fputs(c.cout, ")"); 629 } else if kind == IOP_LSH { 630 ircop(c, ic, ib, op.a, 6); 631 fputs(c.cout, " << "); 632 ircop(c, ic, ib, op.b, 6); 633 } else if kind == IOP_RSH { 634 ircop(c, ic, ib, op.a, 6); 635 fputs(c.cout, " >> "); 636 ircop(c, ic, ib, op.b, 6); 637 } else if kind == IOP_MUL { 638 ircop(c, ic, ib, op.a, 3); 639 fputs(c.cout, " * "); 640 ircop(c, ic, ib, op.b, 3); 641 } else if kind == IOP_SUB { 642 ircop(c, ic, ib, op.a, 4); 643 fputs(c.cout, " - "); 644 ircop(c, ic, ib, op.b, 4); 645 } else if kind == IOP_EQ { 646 fputs(c.cout, "(u)("); 647 ircop(c, ic, ib, op.a, 7); 648 fputs(c.cout, " == "); 649 ircop(c, ic, ib, op.b, 7); 650 fputs(c.cout, ")"); 651 } else if kind == IOP_NE { 652 fputs(c.cout, "(u)("); 653 ircop(c, ic, ib, op.a, 7); 654 fputs(c.cout, " != "); 655 ircop(c, ic, ib, op.b, 7); 656 fputs(c.cout, ")"); 657 } else if kind == IOP_GT { 658 fputs(c.cout, "(u)((s)"); 659 ircop(c, ic, ib, op.a, 6); 660 fputs(c.cout, " > (s)"); 661 ircop(c, ic, ib, op.b, 6); 662 fputs(c.cout, ")"); 663 } else if kind == IOP_GE { 664 fputs(c.cout, "(u)((s)"); 665 ircop(c, ic, ib, op.a, 6); 666 fputs(c.cout, " >= (s)"); 667 ircop(c, ic, ib, op.b, 6); 668 fputs(c.cout, ")"); 669 } else if kind == IOP_LT { 670 fputs(c.cout, "(u)((s)"); 671 ircop(c, ic, ib, op.a, 6); 672 fputs(c.cout, " < (s)"); 673 ircop(c, ic, ib, op.b, 6); 674 fputs(c.cout, ")"); 675 } else if kind == IOP_LE { 676 fputs(c.cout, "(u)((s)"); 677 ircop(c, ic, ib, op.a, 6); 678 fputs(c.cout, " <= (s)"); 679 ircop(c, ic, ib, op.b, 6); 680 fputs(c.cout, ")"); 681 } else { 682 die("invalid op"); 683 } 684 685 if mypri >= pri { 686 fputs(c.cout, ")"); 687 } 688 } 689 690 func irccall(c: *compiler, ic: *irfunc, ib: *irblock, op: *irop) { 691 fputs(c.cout, "\t"); 692 ircretval(c, ic, ib); 693 694 if op.a.kind != IOP_FUNC { 695 fputs(c.cout, "((u(*)())"); 696 ircop(c, ic, ib, op.a, 2); 697 fputs(c.cout, ")("); 698 } else { 699 fputs(c.cout, "z"); 700 fputs(c.cout, op.a.s); 701 fputs(c.cout, "("); 702 } 703 704 ircargs(c, ic, ib, op.n); 705 fputs(c.cout, ");\n"); 706 707 if ib.out.mark & 1 { 708 ircline(c, op); 709 fputs(c.cout, "\t"); 710 fputs(c.cout, "goto b"); 711 fputd(c.cout, ib.out.n); 712 fputs(c.cout, ";\n"); 713 } 714 } 715 716 func ircretval(c: *compiler, ic: *irfunc, ib: *irblock) { 717 var i: int; 718 var op: *irop; 719 var kind: int; 720 721 i = 0; 722 loop { 723 if i == ib.ops_len { 724 break; 725 } 726 727 op = ib.ops[i]; 728 if op.kind == IOP_RETVAL { 729 ircop(c, ic, ib, op.a, 14); 730 fputs(c.cout, " = "); 731 break; 732 } 733 734 i = i + 1; 735 } 736 } 737 738 func ircargs(c: *compiler, ic: *irfunc, ib: *irblock, n: int) { 739 var i: int; 740 var op: *irop; 741 var kind: int; 742 var args: **irop; 743 744 args = alloc(c.a, n * sizeof(*args)) as **irop; 745 746 i = 0; 747 loop { 748 if i == ib.ops_len { 749 break; 750 } 751 752 op = ib.ops[i]; 753 if op.kind == IOP_ARG { 754 args[op.n] = op.a; 755 } 756 757 i = i + 1; 758 } 759 760 i = 0; 761 loop { 762 if i == n { 763 break; 764 } 765 766 if args[i] { 767 ircop(c, ic, ib, args[i], 15); 768 } else { 769 fputs(c.cout, "0UL"); 770 } 771 772 i = i + 1; 773 774 if i != n { 775 fputs(c.cout, ", "); 776 } 777 } 778 779 free(c.a, args as *byte); 780 }