| 1 | #include <string>
 | 
| 2 | #include <stdio.h>
 | 
| 3 | #include <stdlib.h>
 | 
| 4 | 
 | 
| 5 | #include "id_kind.h"
 | 
| 6 | #include "osh.asdl.h"
 | 
| 7 | 
 | 
| 8 | // Returns the root ref, or -1 for invalid
 | 
| 9 | int GetRootRef(uint8_t* image) {
 | 
| 10 |   if (image[0] != 'O') return -1;
 | 
| 11 |   if (image[1] != 'H') return -1;
 | 
| 12 |   if (image[2] != 'P') return -1;
 | 
| 13 |   if (image[3] != 1) return -1;  // version 1
 | 
| 14 |   if (image[4] != 4) return -1;  // alignment 4
 | 
| 15 | 
 | 
| 16 |   return image[5] + (image[6] << 8) + (image[7] << 16);
 | 
| 17 | }
 | 
| 18 | 
 | 
| 19 | void PrintToken(const uint32_t* base, const token_t& e, int indent) {
 | 
| 20 |   for (int i = 0; i < indent; ++i) {
 | 
| 21 |     putchar('\t');
 | 
| 22 |   }
 | 
| 23 |   printf("Token %hhu %s\n", e.id(), e.val(base));
 | 
| 24 | }
 | 
| 25 | 
 | 
| 26 | void PrintWordPart(const uint32_t* base, const word_part_t& e, int indent) {
 | 
| 27 |   for (int i = 0; i < indent; ++i) {
 | 
| 28 |     putchar('\t');
 | 
| 29 |   }
 | 
| 30 |   printf("t%hhu ", e.tag());
 | 
| 31 |   switch (e.tag()) {
 | 
| 32 |   case word_part_e::LiteralPart: {
 | 
| 33 |     auto& e2 = static_cast<const LiteralPart&>(e);
 | 
| 34 |     printf("LiteralPart\n");
 | 
| 35 |     PrintToken(base, e2.token(base), indent+1);
 | 
| 36 |     break;
 | 
| 37 |   }
 | 
| 38 |   default:
 | 
| 39 |     printf("OTHER word_part\n");
 | 
| 40 |     break;
 | 
| 41 |   }
 | 
| 42 | }
 | 
| 43 | 
 | 
| 44 | void PrintWord(const uint32_t* base, const word_t& e, int indent) {
 | 
| 45 |   for (int i = 0; i < indent; ++i) {
 | 
| 46 |     putchar('\t');
 | 
| 47 |   }
 | 
| 48 |   printf("t%hhu ", e.tag());
 | 
| 49 |   switch (e.tag()) {
 | 
| 50 |   case word_e::CompoundWord: {
 | 
| 51 |     auto& e2 = static_cast<const CompoundWord&>(e);
 | 
| 52 |     printf("CompoundWord %d\n", e2.parts_size(base));
 | 
| 53 |     for (int i = 0; i < e2.parts_size(base); ++i) {
 | 
| 54 |       PrintWordPart(base, e2.parts(base, i), indent+1);
 | 
| 55 |     }
 | 
| 56 |     break;
 | 
| 57 |   }
 | 
| 58 |   default:
 | 
| 59 |     printf("OTHER word\n");
 | 
| 60 |     break;
 | 
| 61 |   }
 | 
| 62 | }
 | 
| 63 | 
 | 
| 64 | void PrintCommand(const uint32_t* base, const command_t& e, int indent) {
 | 
| 65 |   for (int i = 0; i < indent; ++i) {
 | 
| 66 |     putchar('\t');
 | 
| 67 |   }
 | 
| 68 |   printf("t%hhu ", e.tag());
 | 
| 69 | 
 | 
| 70 |   switch (e.tag()) {
 | 
| 71 |   case command_e::SimpleCommand: {
 | 
| 72 |     auto& e2 = static_cast<const SimpleCommand&>(e);
 | 
| 73 |     printf("SimpleCommand %d\n", e2.words_size(base));
 | 
| 74 |     for (int i = 0; i < e2.words_size(base); ++i) {
 | 
| 75 |       PrintWord(base, e2.words(base, i), indent+1);
 | 
| 76 |     }
 | 
| 77 |     break;
 | 
| 78 |   }
 | 
| 79 |   case command_e::Assignment: {
 | 
| 80 |     auto& e2 = static_cast<const Assignment&>(e);
 | 
| 81 |     printf("Assignment flags: ");
 | 
| 82 |     for (int i = 0; i < e2.flags_size(base); ++i) {
 | 
| 83 |       printf("%s ", e2.flags(base, i));
 | 
| 84 |     }
 | 
| 85 |     printf("\n");
 | 
| 86 |     break;
 | 
| 87 |   }
 | 
| 88 |   case command_e::AndOr: {
 | 
| 89 |     auto& e2 = static_cast<const AndOr&>(e);
 | 
| 90 |     printf("Ops: ");
 | 
| 91 |     for (int i = 0; i < e2.ops_size(base); ++i) {
 | 
| 92 |       printf("%hhu ", e2.ops(base, i));
 | 
| 93 |     }
 | 
| 94 |     printf("\n");
 | 
| 95 |     for (int i = 0; i < e2.children_size(base); ++i) {
 | 
| 96 |       PrintCommand(base, e2.children(base, i), indent+1);
 | 
| 97 |     }
 | 
| 98 |     printf("\n");
 | 
| 99 |     break;
 | 
| 100 |   }
 | 
| 101 |   case command_e::CommandList: {
 | 
| 102 |     auto& e2 = static_cast<const CommandList&>(e);
 | 
| 103 |     printf("CommandList %d\n", e2.children_size(base));
 | 
| 104 |     for (int i = 0; i < e2.children_size(base); ++i) {
 | 
| 105 |       PrintCommand(base, e2.children(base, i), indent+1);
 | 
| 106 |     }
 | 
| 107 |     break;
 | 
| 108 |   }
 | 
| 109 |   default:
 | 
| 110 |     printf("OTHER\n");
 | 
| 111 |     break;
 | 
| 112 |   }
 | 
| 113 | }
 | 
| 114 | 
 | 
| 115 | int main(int argc, char **argv) {
 | 
| 116 |   if (argc == 0) {
 | 
| 117 |     printf("Expected filename\n");
 | 
| 118 |     return 1;
 | 
| 119 |   }
 | 
| 120 |   FILE *f = fopen(argv[1], "rb");
 | 
| 121 |   if (!f) {
 | 
| 122 |     fprintf(stderr, "Error opening %s\n", argv[1]);
 | 
| 123 |     return 1;
 | 
| 124 |   }
 | 
| 125 |   fseek(f, 0, SEEK_END);
 | 
| 126 |   size_t num_bytes = ftell(f);
 | 
| 127 |   fseek(f, 0, SEEK_SET);  //same as rewind(f);
 | 
| 128 | 
 | 
| 129 |   uint8_t* image = static_cast<uint8_t*>(malloc(num_bytes + 1));
 | 
| 130 |   fread(image, num_bytes, 1, f);
 | 
| 131 |   fclose(f);
 | 
| 132 | 
 | 
| 133 |   image[num_bytes] = 0;
 | 
| 134 |   printf("Read %zu bytes\n", num_bytes);
 | 
| 135 | 
 | 
| 136 |   int root_ref = GetRootRef(image);
 | 
| 137 |   if (root_ref == -1) {
 | 
| 138 |     printf("Invalid image\n");
 | 
| 139 |     return 1;
 | 
| 140 |   }
 | 
| 141 |   // Hm we could make the root ref be a BYTE offset?
 | 
| 142 |   int alignment = 4;
 | 
| 143 |   printf("alignment: %d root: %d\n", alignment, root_ref);
 | 
| 144 | 
 | 
| 145 |   auto base = reinterpret_cast<uint32_t*>(image);
 | 
| 146 | 
 | 
| 147 |   size_t offset = alignment * root_ref;
 | 
| 148 |   auto expr = reinterpret_cast<command_t*>(image + offset);
 | 
| 149 |   PrintCommand(base, *expr, 0);
 | 
| 150 | }
 |