1 /* udis86 - libudis86/input.c 2 * 3 * Copyright (c) 2002-2009 Vivek Thampi 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without modification, 7 * are permitted provided that the following conditions are met: 8 * 9 * * Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * * Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 #include "extern.h" 27 #include "types.h" 28 #include "input.h" 29 #include "udint.h" 30 31 /* 32 * inp_init 33 * Initializes the input system. 34 */ 35 static void 36 inp_init(struct ud *u) 37 { 38 u->inp_curr = 0; 39 u->inp_fill = 0; 40 u->inp_ctr = 0; 41 u->inp_end = 0; 42 } 43 44 45 /* ----------------------------------------------------------------------------- 46 * inp_buff_hook() - Hook for buffered inputs. 47 * ----------------------------------------------------------------------------- 48 */ 49 static int 50 inp_buff_hook(struct ud* u) 51 { 52 if (u->inp_buff < u->inp_buff_end) 53 return *u->inp_buff++; 54 else return -1; 55 } 56 57 #ifndef __UD_STANDALONE__ 58 /* ----------------------------------------------------------------------------- 59 * inp_file_hook() - Hook for FILE inputs. 60 * ----------------------------------------------------------------------------- 61 */ 62 static int 63 inp_file_hook(struct ud* u) 64 { 65 return fgetc(u->inp_file); 66 } 67 #endif /* __UD_STANDALONE__*/ 68 69 /* ============================================================================= 70 * ud_inp_set_hook() - Sets input hook. 71 * ============================================================================= 72 */ 73 void 74 ud_set_input_hook(register struct ud* u, int (*hook)(struct ud*)) 75 { 76 u->inp_hook = hook; 77 inp_init(u); 78 } 79 80 /* ============================================================================= 81 * ud_inp_set_buffer() - Set buffer as input. 82 * ============================================================================= 83 */ 84 void 85 ud_set_input_buffer(register struct ud* u, const uint8_t* buf, size_t len) 86 { 87 u->inp_hook = inp_buff_hook; 88 u->inp_buff = buf; 89 u->inp_buff_end = buf + len; 90 inp_init(u); 91 } 92 93 #ifndef __UD_STANDALONE__ 94 /* ============================================================================= 95 * ud_input_set_file() - Set buffer as input. 96 * ============================================================================= 97 */ 98 void 99 ud_set_input_file(register struct ud* u, FILE* f) 100 { 101 u->inp_hook = inp_file_hook; 102 u->inp_file = f; 103 inp_init(u); 104 } 105 #endif /* __UD_STANDALONE__ */ 106 107 /* ============================================================================= 108 * ud_input_skip() - Skip n input bytes. 109 * ============================================================================= 110 */ 111 void 112 ud_input_skip(struct ud* u, size_t n) 113 { 114 while (n--) { 115 u->inp_hook(u); 116 } 117 } 118 119 /* ============================================================================= 120 * ud_input_end() - Test for end of input. 121 * ============================================================================= 122 */ 123 int 124 ud_input_end(const struct ud* u) 125 { 126 return (u->inp_curr == u->inp_fill) && u->inp_end; 127 } 128 129 130 /* 131 * ud_inp_next 132 * Loads and returns the next byte from input. 133 * 134 * inp_curr and inp_fill are pointers to the cache. The program is 135 * written based on the property that they are 8-bits in size, and 136 * will eventually wrap around forming a circular buffer. So, the 137 * size of the cache is 256 in size, kind of unnecessary yet 138 * optimal. 139 * 140 * A buffer inp_sess stores the bytes disassembled for a single 141 * session. 142 */ 143 uint8_t 144 ud_inp_next(struct ud* u) 145 { 146 int c = -1; 147 /* if current pointer is not upto the fill point in the 148 * input cache. 149 */ 150 if (u->inp_curr != u->inp_fill) { 151 c = u->inp_cache[ ++u->inp_curr ]; 152 /* if !end-of-input, call the input hook and get a byte */ 153 } else if (u->inp_end || (c = u->inp_hook(u)) == -1) { 154 /* end-of-input, mark it as an error, since the decoder, 155 * expected a byte more. 156 */ 157 UDERR(u, "byte expected, eoi received"); 158 /* flag end of input */ 159 u->inp_end = 1; 160 return 0; 161 } else { 162 /* increment pointers, we have a new byte. */ 163 u->inp_curr = ++u->inp_fill; 164 /* add the byte to the cache */ 165 u->inp_cache[u->inp_fill] = c; 166 } 167 /* record bytes input per decode-session. */ 168 u->inp_sess[u->inp_ctr++] = c; 169 /* return byte */ 170 return (uint8_t) c; 171 } 172 173 /* 174 vim: set ts=2 sw=2 expandtab 175 */ 176