home *** CD-ROM | disk | FTP | other *** search
/ Large Pack of OldSkool DOS MOD Trackers / goattracker_2.68.zip / src / asm / parse.c < prev    next >
C/C++ Source or Header  |  2008-04-01  |  22KB  |  851 lines

  1. /*
  2.  * Copyright (c) 2005 Magnus Lind.
  3.  *
  4.  * This software is provided 'as-is', without any express or implied warranty.
  5.  * In no event will the authors be held liable for any damages arising from
  6.  * the use of this software.
  7.  *
  8.  * Permission is granted to anyone to use this software, alter it and re-
  9.  * distribute it freely for any non-commercial, non-profit purpose subject to
  10.  * the following restrictions:
  11.  *
  12.  *   1. The origin of this software must not be misrepresented; you must not
  13.  *   claim that you wrote the original software. If you use this software in a
  14.  *   product, an acknowledgment in the product documentation would be
  15.  *   appreciated but is not required.
  16.  *
  17.  *   2. Altered source versions must be plainly marked as such, and must not
  18.  *   be misrepresented as being the original software.
  19.  *
  20.  *   3. This notice may not be removed or altered from any distribution.
  21.  *
  22.  *   4. The names of this software and/or it's copyright holders may not be
  23.  *   used to endorse or promote products derived from this software without
  24.  *   specific prior written permission.
  25.  *
  26.  */
  27.  
  28. #include "parse.h"
  29. #include "asmtab.h"
  30. #include "log.h"
  31. #include "chnkpool.h"
  32. #include "namedbuf.h"
  33. #include "pc.h"
  34.  
  35. #include <stdlib.h>
  36.  
  37.  
  38. static struct chunkpool s_atom_pool[1];
  39. static struct chunkpool s_vec_pool[1];
  40. static struct vec s_sym_table[1];
  41. static const char *s_macro_name;
  42.  
  43. struct sym_entry
  44. {
  45.     const char *symbol;
  46.     struct expr *expr;
  47. };
  48.  
  49. static int sym_entry_cmp(const void *a, const void *b)
  50. {
  51.     struct sym_entry *sym_a;
  52.     struct sym_entry *sym_b;
  53.     int val;
  54.  
  55.     sym_a = (struct sym_entry*)a;
  56.     sym_b = (struct sym_entry*)b;
  57.  
  58.     val = strcmp(sym_a->symbol, sym_b->symbol);
  59.  
  60.     return val;
  61. }
  62.  
  63. void scanner_init(void);
  64. void scanner_free(void);
  65.  
  66. void parse_init()
  67. {
  68.     scanner_init();
  69.     chunkpool_init(s_atom_pool, sizeof(struct atom));
  70.     chunkpool_init(s_vec_pool, sizeof(struct vec));
  71.     expr_init();
  72.     vec_init(s_sym_table, sizeof(struct sym_entry));
  73.     pc_unset();
  74.     named_buffer_init();
  75. }
  76.  
  77. static void free_vec_pool(struct vec *v)
  78. {
  79.     vec_free(v, NULL);
  80. }
  81.  
  82. void parse_free()
  83. {
  84.     named_buffer_free();
  85.     chunkpool_free(s_atom_pool);
  86.     chunkpool_free2(s_vec_pool, (cb_free*)free_vec_pool);
  87.     expr_free();
  88.     vec_free(s_sym_table, NULL);
  89.     scanner_free();
  90. }
  91.  
  92. int is_valid_i8(i32 value)
  93. {
  94.     return (value >= -128 && value <= 127);
  95. }
  96.  
  97. int is_valid_u8(i32 value)
  98. {
  99.     return (value >= 0 && value <= 255);
  100. }
  101.  
  102. int is_valid_ui8(i32 value)
  103. {
  104.     return (value >= -128 && value <= 255);
  105. }
  106.  
  107. int is_valid_u16(i32 value)
  108. {
  109.     return (value >= 0 && value <= 65535);
  110. }
  111.  
  112. int is_valid_ui16(i32 value)
  113. {
  114.     return (value >= -32768 && value <= 65535);
  115. }
  116.  
  117. void dump_sym_entry(int level, struct sym_entry *se)
  118. {
  119.     LOG(level, ("sym_entry 0x%08X symbol %s, expr 0x%08X\n",
  120.                 (u32)se, se->symbol, (u32)se->expr));
  121. }
  122.  
  123. struct expr *new_is_defined(const char *symbol)
  124. {
  125.     struct expr *val;
  126.     struct sym_entry e[1];
  127.     int pos;
  128.     int expr_val = 0;
  129.  
  130.     e->symbol = symbol;
  131.     pos = vec_find(s_sym_table, sym_entry_cmp, e);
  132.     if(pos >= 0)
  133.     {
  134.         /* found */
  135.         expr_val = 1;
  136.     }
  137.     val = new_expr_number(expr_val);
  138.     return val;
  139. }
  140.  
  141. void new_symbol_expr(const char *symbol, struct expr *arg)
  142. {
  143.     struct sym_entry e[1];
  144.     struct sym_entry *se;
  145.     int pos;
  146.  
  147.     e->symbol = symbol;
  148.     pos = vec_find(s_sym_table, sym_entry_cmp, e);
  149.     if(pos > -1)
  150.     {
  151.         /* error, symbol redefinition not allowed */
  152.         LOG(LOG_ERROR, ("not allowed to redefine symbol %s\n", symbol));
  153.         exit(1);
  154.     }
  155.     if(pos == -1)
  156.     {
  157.         /* error, find failed */
  158.         LOG(LOG_ERROR, ("new_symbol_expr: vec_find() internal error\n"));
  159.         exit(1);
  160.     }
  161.     e->expr = arg;
  162.  
  163.     se = vec_insert(s_sym_table, -(pos + 2), e);
  164.     LOG(LOG_DEBUG, ("creating symdef: "));
  165.     dump_sym_entry(LOG_DEBUG, se);
  166. }
  167.  
  168. void new_symbol(const char *symbol, i32 value)
  169. {
  170.     struct expr *e;
  171.  
  172.     e = new_expr_number(value);
  173.     new_symbol_expr(symbol, e);
  174. }
  175.  
  176. const char *find_symref(const char *symbol, struct expr **expp)
  177. {
  178.     struct sym_entry e[1];
  179.     struct sym_entry *ep;
  180.     struct expr *exp;
  181.     int pos;
  182.     const char *p;
  183.  
  184.     p = NULL;
  185.     e->symbol = symbol;
  186.     pos = vec_find(s_sym_table, sym_entry_cmp, e);
  187.     if(pos < -1)
  188.     {
  189.         static char buf[1024];
  190.         /* error, symbol not found */
  191.         sprintf(buf, "symbol %s not found", symbol);
  192.         p = buf;
  193.         LOG(LOG_DEBUG, ("%s\n", p));
  194.         return p;
  195.     }
  196.     if(pos == -1)
  197.     {
  198.         /* error, find failed */
  199.         LOG(LOG_ERROR, ("find_symref: vec_find() internal error\n"));
  200.         exit(-1);
  201.     }
  202.     ep = vec_get(s_sym_table, pos);
  203.     exp = ep->expr;
  204.  
  205.     LOG(LOG_DEBUG, ("found: "));
  206.     dump_sym_entry(LOG_DEBUG, ep);
  207.  
  208.     if(expp != NULL)
  209.     {
  210.         *expp = exp;
  211.     }
  212.  
  213.     return p;
  214. }
  215.  
  216. void new_label(const char *label)
  217. {
  218.     struct sym_entry e[1];
  219.     struct sym_entry *se;
  220.     int pos;
  221.  
  222.     e->symbol = label;
  223.     pos = vec_find(s_sym_table, sym_entry_cmp, e);
  224.     if(pos > -1)
  225.     {
  226.         /* error, symbol redefinition not allowed */
  227.         LOG(LOG_ERROR, ("not allowed to redefine label %s\n", label));
  228.         exit(1);
  229.     }
  230.     if(pos == -1)
  231.     {
  232.         /* error, find failed */
  233.         LOG(LOG_ERROR, ("new_label: vec_find() internal error\n"));
  234.         exit(1);
  235.     }
  236.  
  237.     e->expr = pc_get();
  238.  
  239.     se = vec_insert(s_sym_table, -(pos + 2), e);
  240.     LOG(LOG_DEBUG, ("creating label: "));
  241.     dump_sym_entry(LOG_DEBUG, se);
  242. }
  243.  
  244. static void dump_sym_table(int level, struct vec *v)
  245. {
  246.     struct vec_iterator i[1];
  247.     struct sym_entry *se;
  248.  
  249.     vec_get_iterator(v, i);
  250.     while((se = vec_iterator_next(i)) != NULL)
  251.     {
  252.         LOG(level, ("sym_table: %s\n", se->symbol));
  253.     }
  254. }
  255.  
  256. static const char *resolve_expr2(struct expr *e, i32 *valp)
  257. {
  258.     struct expr *e2;
  259.     i32 value;
  260.     i32 value2;
  261.     const char *p;
  262.  
  263.     p = NULL;
  264.     LOG(LOG_DEBUG, ("resolve_expr: "));
  265.  
  266.     expr_dump(LOG_DEBUG, e);
  267.  
  268.     switch (e->expr_op)
  269.     {
  270.     case NUMBER:
  271.         /* we are already resolved */
  272.         value = e->type.number;
  273.         break;
  274.     case vNEG:
  275.         p = resolve_expr2(e->type.arg1, &value);
  276.         if(p != NULL) break;
  277.         value = -value;
  278.         break;
  279.     case LNOT:
  280.         p = resolve_expr2(e->type.arg1, &value);
  281.         if(p != NULL) break;
  282.         value = !value;
  283.         break;
  284.     case SYMBOL:
  285.         p = find_symref(e->type.symref, &e2);
  286.         if(p != NULL) break;
  287.         if(e2 == NULL)
  288.         {
  289.             static char buf[1024];
  290.             /* error, symbol not found */
  291.             sprintf(buf, "symbol %s has no value.", e->type.symref);
  292.             p = buf;
  293.             LOG(LOG_DEBUG, ("%s\n", p));
  294.             break;
  295.         }
  296.         p = resolve_expr2(e2, &value);
  297.         break;
  298.     default:
  299.         LOG(LOG_DEBUG, ("binary op %d\n", e->expr_op));
  300.  
  301.         p = resolve_expr2(e->type.arg1, &value);
  302.         if(p != NULL) break;
  303.  
  304.         /* short circuit the logical operators */
  305.         if(e->expr_op == LOR)
  306.         {
  307.             value = (value != 0);
  308.             if(value) break;
  309.         }
  310.         else if(e->expr_op == LAND)
  311.         {
  312.             value = (value != 0);
  313.             if(!value) break;
  314.         }
  315.  
  316.         p = resolve_expr2(e->expr_arg2, &value2);
  317.         if(p != NULL) break;
  318.  
  319.         switch(e->expr_op)
  320.         {
  321.         case MINUS:
  322.             value -= value2;
  323.             break;
  324.         case PLUS:
  325.             value += value2;
  326.             break;
  327.         case MULT:
  328.             value *= value2;
  329.             break;
  330.         case DIV:
  331.             value /= value2;
  332.             break;
  333.         case MOD:
  334.             value %= value2;
  335.             break;
  336.         case LT:
  337.             value = (value < value2);
  338.             break;
  339.         case GT:
  340.             value = (value > value2);
  341.             break;
  342.         case EQ:
  343.             value = (value == value2);
  344.             break;
  345.         case NEQ:
  346.             value = (value != value2);
  347.             break;
  348.         case LOR:
  349.             value = (value2 != 0);
  350.             break;
  351.         case LAND:
  352.             value = (value2 != 0);
  353.             break;
  354.         default:
  355.             LOG(LOG_ERROR, ("unsupported op %d\n", e->expr_op));
  356.             exit(1);
  357.         }
  358.     }
  359.     if(p == NULL)
  360.     {
  361.         if(e->expr_op != NUMBER)
  362.         {
  363.             /* shortcut future recursion */
  364.             e->expr_op = NUMBER;
  365.             e->type.number = value;
  366.         }
  367.         if(valp != NULL)
  368.         {
  369.             *valp = value;
  370.         }
  371.     }
  372.  
  373.     return p;
  374. }
  375.  
  376. static i32 resolve_expr(struct expr *e)
  377. {
  378.     i32 val;
  379.     const char *p;
  380.  
  381.     p = resolve_expr2(e, &val);
  382.     if(p != NULL)
  383.     {
  384.         LOG(LOG_ERROR, ("%s\n", p));
  385.         exit(-1);
  386.     }
  387.     return val;
  388. }
  389.  
  390. struct expr *new_expr_incword(const char *name, struct expr *skip)
  391. {
  392.     i32 word;
  393.     i32 offset;
  394.     long length;
  395.     struct membuf *in;
  396.     struct expr *expr;
  397.     unsigned char *p;
  398.  
  399.     offset = resolve_expr(skip);
  400.     in = get_named_buffer(name);
  401.     length = membuf_memlen(in);
  402.     if(offset < 0)
  403.     {
  404.         offset += length;
  405.     }
  406.     if(offset < 0 || offset > length - 2)
  407.     {
  408.         LOG(LOG_ERROR,
  409.             ("Can't read word from offset %d in file \"%s\".\n",
  410.              offset, name));
  411.         exit(-1);
  412.     }
  413.     p = membuf_get(in);
  414.     p += offset;
  415.     word = *p++;
  416.     word |= *p++ << 8;
  417.  
  418.     expr = new_expr_number(word);
  419.     return expr;
  420. }
  421.  
  422. void set_org(struct expr *arg)
  423. {
  424.     /* org assembler directive */
  425.     pc_set_expr(arg);
  426.     LOG(LOG_DEBUG, ("setting .org to ???\n"));
  427.     return;
  428. }
  429.  
  430. void push_macro_state(const char *name)
  431. {
  432.     s_macro_name = name;
  433.     push_state_macro = 1;
  434.     new_named_buffer(name);
  435. }
  436.  
  437. void macro_append(const char *text)
  438. {
  439.     struct membuf *mb;
  440.  
  441.     LOG(LOG_DEBUG, ("appending >>%s<< to macro\n", text));
  442.  
  443.     mb = get_named_buffer(s_macro_name);
  444.     membuf_append(mb, text, strlen(text));
  445. }
  446.  
  447. void push_if_state(struct expr *arg)
  448. {
  449.     int val;
  450.     LOG(LOG_DEBUG, ("resolving if expression\n"));
  451.     val = resolve_expr(arg);
  452.     LOG(LOG_DEBUG, ("if expr resolved to %d\n", val));
  453.     if(val)
  454.     {
  455.         push_state_init = 1;
  456.     }
  457.     else
  458.     {
  459.         push_state_skip = 1;
  460.     }
  461. }
  462.  
  463. struct atom *new_op(u8 op_code, u8 atom_op_type, struct expr *op_arg)
  464. {
  465.     struct atom *atom;
  466.  
  467.     atom = chunkpool_malloc(s_atom_pool);
  468.     atom->type = atom_op_type;
  469.     atom->u.op.code = op_code;
  470.     atom->u.op.arg = op_arg;
  471.  
  472.     switch(atom_op_type)
  473.     {
  474.     case ATOM_TYPE_OP_ARG_NONE:
  475.         pc_add(1);
  476.         break;
  477.     case ATOM_TYPE_OP_ARG_U8:
  478.         pc_add(2);
  479.         break;
  480.     case ATOM_TYPE_OP_ARG_U16:
  481.         pc_add(3);
  482.         break;
  483.     case ATOM_TYPE_OP_ARG_I8:
  484.         pc_add(2);
  485.         atom->u.op.arg = new_expr_op2(MINUS, atom->u.op.arg, pc_get());
  486.         break;
  487.     case ATOM_TYPE_OP_ARG_UI8:
  488.         pc_add(2);
  489.         break;
  490.     default:
  491.         LOG(LOG_ERROR, ("invalid op arg range %d\n", atom_op_type));
  492.         exit(1);
  493.     }
  494.     pc_dump(LOG_DEBUG);
  495.  
  496.     return atom;
  497. }
  498.  
  499. struct atom *new_op0(u8 op_code)
  500. {
  501.     struct atom *atom;
  502.     atom = new_op(op_code, ATOM_TYPE_OP_ARG_NONE, NULL);
  503.     return atom;
  504. }
  505.  
  506. struct atom *new_exprs(struct expr *arg)
  507. {
  508.     struct atom *atom;
  509.  
  510.     atom = chunkpool_malloc(s_atom_pool);
  511.     atom->type = ATOM_TYPE_EXPRS;
  512.     atom->u.exprs = chunkpool_malloc(s_vec_pool);
  513.     vec_init(atom->u.exprs, sizeof(struct expr*));
  514.     exprs_add(atom, arg);
  515.     return atom;
  516. }
  517.  
  518. struct atom *exprs_add(struct atom *atom, struct expr *arg)
  519. {
  520.     if(atom->type != ATOM_TYPE_EXPRS)
  521.     {
  522.         LOG(LOG_ERROR, ("can't add expr to atom of type %d\n", atom->type));
  523.         exit(1);
  524.     }
  525.     vec_push(atom->u.exprs, &arg);
  526.     return atom;
  527. }
  528.  
  529. struct atom *exprs_to_byte_exprs(struct atom *atom)
  530. {
  531.     if(atom->type != ATOM_TYPE_EXPRS)
  532.     {
  533.         LOG(LOG_ERROR, ("can't convert atom of type %d to byte exprs.\n",
  534.                         atom->type));
  535.         exit(1);
  536.     }
  537.     atom->type = ATOM_TYPE_BYTE_EXPRS;
  538.  
  539.     pc_add(vec_count(atom->u.exprs));
  540.     return atom;
  541. }
  542.  
  543. struct atom *exprs_to_word_exprs(struct atom *atom)
  544. {
  545.     if(atom->type != ATOM_TYPE_EXPRS)
  546.     {
  547.         LOG(LOG_ERROR, ("can't convert exprs of type %d to word exprs.\n",
  548.                         atom->type));
  549.         exit(1);
  550.     }
  551.     atom->type = ATOM_TYPE_WORD_EXPRS;
  552.  
  553.     pc_add(vec_count(atom->u.exprs) * 2);
  554.     return atom;
  555. }
  556.  
  557. struct atom *new_res(struct expr *len, struct expr *value)
  558. {
  559.     struct atom *atom;
  560.  
  561.     atom = chunkpool_malloc(s_atom_pool);
  562.     atom->type = ATOM_TYPE_RES;
  563.     atom->u.res.length = len;
  564.     atom->u.res.value = value;
  565.  
  566.     pc_add_expr(len);
  567.     return atom;
  568. }
  569.  
  570. struct atom *new_incbin(const char *name, struct expr *skip, struct expr *len)
  571. {
  572.     struct atom *atom;
  573.     long length;
  574.     i32 len32;
  575.     i32 skip32;
  576.     struct membuf *in;
  577.  
  578.     /* find out how long the file is */
  579.     in = get_named_buffer(name);
  580.     length = membuf_memlen(in);
  581.  
  582.     skip32 = 0;
  583.     if(skip != NULL)
  584.     {
  585.         skip32 = resolve_expr(skip);
  586.     }
  587.     if(skip32 < 0)
  588.     {
  589.         skip32 += length;
  590.     }
  591.     if(skip32 < 0 || skip32 > length)
  592.     {
  593.         LOG(LOG_ERROR,
  594.             ("Can't read from offset %d in file \"%s\".\n", skip32, name));
  595.         exit(-1);
  596.     }
  597.     length -= skip32;
  598.  
  599.     len32 = 0;
  600.     if(len != NULL)
  601.     {
  602.         len32 = resolve_expr(len);
  603.     }
  604.     if(len32 < 0)
  605.     {
  606.         len32 += length;
  607.     }
  608.     if(len32 < 0 || len32 > length)
  609.     {
  610.         LOG(LOG_ERROR,
  611.             ("Can't read %d bytes from offset %d from file \"%s\".\n",
  612.              len32, skip32, name));
  613.         exit(-1);
  614.     }
  615.  
  616.     atom = chunkpool_malloc(s_atom_pool);
  617.     atom->type = ATOM_TYPE_BUFFER;
  618.     atom->u.buffer.name = name;
  619.     atom->u.buffer.length = len32;
  620.     atom->u.buffer.skip = skip32;
  621.  
  622.     if(len != NULL)
  623.     {
  624.         pc_add(len32);
  625.     }
  626.     return atom;
  627. }
  628.  
  629.  
  630. void asm_error(const char *msg)
  631. {
  632.     LOG(LOG_ERROR, ("Error: %s\n", msg));
  633.     exit(1);
  634. }
  635.  
  636. void asm_echo(const char *msg)
  637. {
  638.     fprintf(stdout, "%s\n", msg);
  639. }
  640.  
  641. void asm_include(const char *msg)
  642. {
  643.     struct membuf *src;
  644.  
  645.     src = get_named_buffer(msg);
  646.     asm_src_buffer_push(src);
  647. }
  648.  
  649. void symbol_dump_resolved(int level, const char *symbol)
  650. {
  651.     i32 value;
  652.     struct expr *e;
  653.     const char *p;
  654.     p = find_symref(symbol, &e);
  655.     if(p == NULL)
  656.     {
  657.         if(e != NULL)
  658.         {
  659.             value = resolve_expr(e);
  660.             LOG(level, ("symbol \"%s\" resolves to %d ($%04X)\n",
  661.                         symbol, value, value));
  662.         }
  663.         else
  664.         {
  665.             LOG(level, ("symbol \"%s\" is defined but has no value\n",
  666.                         symbol));
  667.         }
  668.     }
  669.     else
  670.     {
  671.         LOG(level, ("symbol \"%s\" not found\n", symbol));
  672.     }
  673. }
  674.  
  675. void output_atoms(struct membuf *out, struct vec *atoms)
  676. {
  677.     struct vec_iterator i[1];
  678.     struct vec_iterator i2[1];
  679.     struct atom **atomp;
  680.     struct atom *atom;
  681.     struct expr **exprp;
  682.     struct expr *expr;
  683.     struct membuf *in;
  684.     const char *p;
  685.     i32 value;
  686.     i32 value2;
  687.  
  688.     dump_sym_table(LOG_DEBUG, s_sym_table);
  689.  
  690.     vec_get_iterator(atoms, i);
  691.     while((atomp = vec_iterator_next(i)) != NULL)
  692.     {
  693.         atom = *atomp;
  694.  
  695.         LOG(LOG_DEBUG, ("yadda\n"));
  696.  
  697.         switch(atom->type)
  698.         {
  699.         case ATOM_TYPE_OP_ARG_NONE:
  700.             LOG(LOG_DEBUG, ("output: $%02X\n", atom->u.op.code));
  701.             membuf_append_char(out, atom->u.op.code);
  702.             break;
  703.         case ATOM_TYPE_OP_ARG_U8:
  704.             /* op with argument */
  705.             value = resolve_expr(atom->u.op.arg);
  706.             if(!is_valid_u8(value))
  707.             {
  708.                 LOG(LOG_ERROR, ("value %d out of range for op $%02X @%p\n",
  709.                                 value, atom->u.op.code, atom));
  710.                 exit(1);
  711.             }
  712.             LOG(LOG_DEBUG, ("output: $%02X $%02X\n",
  713.                             atom->u.op.code, value & 255));
  714.             membuf_append_char(out, atom->u.op.code);
  715.             membuf_append_char(out, value);
  716.             break;
  717.         case ATOM_TYPE_OP_ARG_I8:
  718.             /* op with argument */
  719.             value = resolve_expr(atom->u.op.arg);
  720.             if(!is_valid_i8(value))
  721.             {
  722.                 LOG(LOG_ERROR, ("value %d out of range for op $%02X @%p\n",
  723.                                 value, atom->u.op.code, atom));
  724.                 exit(1);
  725.             }
  726.             LOG(LOG_DEBUG, ("output: $%02X $%02X\n",
  727.                             atom->u.op.code, value & 255));
  728.             membuf_append_char(out, atom->u.op.code);
  729.             membuf_append_char(out, value);
  730.             break;
  731.         case ATOM_TYPE_OP_ARG_UI8:
  732.             /* op with argument */
  733.             value = resolve_expr(atom->u.op.arg);
  734.             if(!is_valid_ui8(value))
  735.             {
  736.                 LOG(LOG_ERROR, ("value %d out of range for op $%02X @%p\n",
  737.                                 value, atom->u.op.code, atom));
  738.                 exit(1);
  739.             }
  740.             LOG(LOG_DEBUG, ("output: $%02X $%02X\n",
  741.                             atom->u.op.code, value & 255));
  742.             membuf_append_char(out, atom->u.op.code);
  743.             membuf_append_char(out, value);
  744.             break;
  745.         case ATOM_TYPE_OP_ARG_U16:
  746.             /* op with argument */
  747.             value = resolve_expr(atom->u.op.arg);
  748.             if(!is_valid_u16(value))
  749.             {
  750.                 LOG(LOG_ERROR, ("value %d out of range for op $%02X @%p\n",
  751.                                 value, atom->u.op.code, atom));
  752.                 exit(1);
  753.             }
  754.             value2 = value / 256;
  755.             value = value % 256;
  756.             LOG(LOG_DEBUG, ("output: $%02X $%02X $%02X\n",
  757.                             atom->u.op.code,
  758.                             value, value2));
  759.             membuf_append_char(out, atom->u.op.code);
  760.             membuf_append_char(out, value);
  761.             membuf_append_char(out, value2);
  762.             break;
  763.         case ATOM_TYPE_RES:
  764.             /* reserve memory statement */
  765.             value = resolve_expr(atom->u.res.length);
  766.             if(!is_valid_u16(value))
  767.             {
  768.                 LOG(LOG_ERROR, ("length %d for .res(length, value) "
  769.                                 "is out of range\n", value));
  770.                 exit(1);
  771.             }
  772.             value2 = resolve_expr(atom->u.res.value);
  773.             if(!is_valid_ui8(value2))
  774.             {
  775.                 LOG(LOG_ERROR, ("value %d for .res(length, value) "
  776.                                 "is out of range\n", value));
  777.                 exit(1);
  778.             }
  779.             LOG(LOG_DEBUG, ("output: .RES %d, %d\n", value, value2));
  780.             while(--value >= 0)
  781.             {
  782.                 membuf_append_char(out, value2);
  783.             }
  784.             break;
  785.         case ATOM_TYPE_BUFFER:
  786.             /* include binary file statement */
  787.             value = atom->u.buffer.skip;
  788.             if(!is_valid_u16(value))
  789.             {
  790.                 LOG(LOG_ERROR, ("value %d for .res(length, value) "
  791.                                 "is out of range\n", value));
  792.                 exit(1);
  793.             }
  794.             value2 = atom->u.buffer.length;
  795.             if(!is_valid_u16(value2))
  796.             {
  797.                 LOG(LOG_ERROR, ("length %d for .incbin(name, skip, length) "
  798.                                 "is out of range\n", value2));
  799.                 exit(1);
  800.             }
  801.             LOG(LOG_DEBUG, ("output: .INCBIN \"%s\", %d, %d\n",
  802.                             atom->u.buffer.name, value, value2));
  803.             in = get_named_buffer(atom->u.buffer.name);
  804.             p = membuf_get(in);
  805.             p += value;
  806.             while(--value2 >= 0)
  807.             {
  808.                 membuf_append_char(out, *p++);
  809.             }
  810.             break;
  811.         case ATOM_TYPE_WORD_EXPRS:
  812.             vec_get_iterator(atom->u.exprs, i2);
  813.             while((exprp = vec_iterator_next(i2)) != NULL)
  814.             {
  815.                 expr = *exprp;
  816.                 value = resolve_expr(expr);
  817.                 if(!is_valid_ui16(value))
  818.                 {
  819.                     LOG(LOG_ERROR, ("value %d for .word(value, ...) "
  820.                                     "is out of range\n", value));
  821.                 }
  822.                 value2 = value / 256;
  823.                 value = value % 256;
  824.                 membuf_append_char(out, value);
  825.                 membuf_append_char(out, value2);
  826.             }
  827.             LOG(LOG_DEBUG, ("output: %d words\n", vec_count(atom->u.exprs)));
  828.             break;
  829.         case ATOM_TYPE_BYTE_EXPRS:
  830.             vec_get_iterator(atom->u.exprs, i2);
  831.             while((exprp = vec_iterator_next(i2)) != NULL)
  832.             {
  833.                 expr = *exprp;
  834.                 value = resolve_expr(expr);
  835.                 if(!is_valid_ui8(value))
  836.                 {
  837.                     LOG(LOG_ERROR, ("value %d for .byte(value, ...) "
  838.                                     "is out of range\n", value));
  839.                 }
  840.                 membuf_append_char(out, value);
  841.             }
  842.             LOG(LOG_DEBUG, ("output: %d bytes\n", vec_count(atom->u.exprs)));
  843.             break;
  844.         default:
  845.             LOG(LOG_ERROR, ("invalid atom_type %d @%p\n",
  846.                             atom->type, atom));
  847.             exit(1);
  848.         }
  849.     }
  850. }
  851.