1 #include "less.h" 2 #include "xbuf.h" 3 4 /* 5 * Initialize an expandable text buffer. 6 */ 7 public void xbuf_init(struct xbuffer *xbuf) 8 { 9 xbuf->data = NULL; 10 xbuf->size = xbuf->end = 0; 11 } 12 13 public void xbuf_deinit(struct xbuffer *xbuf) 14 { 15 if (xbuf->data != NULL) 16 free(xbuf->data); 17 xbuf_init(xbuf); 18 } 19 20 public void xbuf_reset(struct xbuffer *xbuf) 21 { 22 xbuf->end = 0; 23 } 24 25 /* 26 * Add a byte to an expandable text buffer. 27 */ 28 public void xbuf_add_byte(struct xbuffer *xbuf, unsigned char b) 29 { 30 if (xbuf->end >= xbuf->size) 31 { 32 unsigned char *data; 33 if (ckd_add(&xbuf->size, xbuf->size, xbuf->size ? xbuf->size : 16)) 34 out_of_memory(); 35 data = (unsigned char *) ecalloc(xbuf->size, sizeof(unsigned char)); 36 if (xbuf->data != NULL) 37 { 38 memcpy(data, xbuf->data, xbuf->end); 39 free(xbuf->data); 40 } 41 xbuf->data = data; 42 } 43 xbuf->data[xbuf->end++] = (unsigned char) b; 44 } 45 46 public void xbuf_add_data(struct xbuffer *xbuf, unsigned char *data, int len) 47 { 48 int i; 49 for (i = 0; i < len; i++) 50 xbuf_add_byte(xbuf, data[i]); 51 } 52 53 public int xbuf_pop(struct xbuffer *buf) 54 { 55 if (buf->end == 0) 56 return -1; 57 return (int) buf->data[--(buf->end)]; 58 } 59 60 public void xbuf_set(struct xbuffer *dst, struct xbuffer *src) 61 { 62 xbuf_reset(dst); 63 xbuf_add_data(dst, src->data, src->end); 64 } 65 66 public char * xbuf_char_data(struct xbuffer *xbuf) 67 { 68 return (char *)(xbuf->data); 69 } 70 71 72 /* 73 * Helper functions for the ckd_add and ckd_mul macro substitutes. 74 * These helper functions do not set *R on overflow, and assume that 75 * arguments are nonnegative, that INTMAX_MAX <= UINTMAX_MAX, and that 76 * sizeof is a reliable way to distinguish integer representations. 77 * Despite these limitations they are good enough for 'less' on all 78 * known practical platforms. For more-complicated substitutes 79 * without most of these limitations, see Gnulib's stdckdint module. 80 */ 81 #if !HAVE_STDCKDINT_H 82 /* 83 * If the integer *R can represent VAL, store the value and return FALSE. 84 * Otherwise, possibly set *R to an indeterminate value and return TRUE. 85 * R has size RSIZE, and is signed if and only if RSIGNED is nonzero. 86 */ 87 static int help_fixup(void *r, uintmax val, int rsize, int rsigned) 88 { 89 if (rsigned) 90 { 91 if (rsize == sizeof (int)) 92 { 93 int *pr = r; 94 if (INT_MAX < val) 95 return TRUE; 96 *pr = (int) val; 97 #ifdef LLONG_MAX 98 } else if (rsize == sizeof (long long)) 99 { 100 long long *pr = r; 101 if (LLONG_MAX < val) 102 return TRUE; 103 *pr = val; 104 #endif 105 #ifdef INTMAX_MAX 106 } else if (rsize == sizeof (intmax_t)) { 107 intmax_t *pr = r; 108 if (INTMAX_MAX < val) 109 return TRUE; 110 *pr = val; 111 #endif 112 } else /* rsize == sizeof (long) */ 113 { 114 long *pr = r; 115 if (LONG_MAX < val) 116 return TRUE; 117 *pr = (long) val; 118 } 119 } else { 120 if (rsize == sizeof (unsigned)) { 121 unsigned *pr = r; 122 if (UINT_MAX < val) 123 return TRUE; 124 *pr = (unsigned) val; 125 } else if (rsize == sizeof (unsigned long)) { 126 unsigned long *pr = r; 127 if (ULONG_MAX < val) 128 return TRUE; 129 *pr = (unsigned long) val; 130 #ifdef ULLONG_MAX 131 } else if (rsize == sizeof (unsigned long long)) { 132 long long *pr = r; 133 if (ULLONG_MAX < val) 134 return TRUE; 135 *pr = val; 136 #endif 137 } else /* rsize == sizeof (uintmax) */ 138 { 139 uintmax *pr = r; 140 *pr = val; 141 } 142 } 143 return FALSE; 144 } 145 /* 146 * If *R can represent the mathematical sum of A and B, store the sum 147 * and return FALSE. Otherwise, possibly set *R to an indeterminate 148 * value and return TRUE. R has size RSIZE, and is signed if and only 149 * if RSIGNED is nonzero. 150 */ 151 public int help_ckd_add(void *r, uintmax a, uintmax b, int rsize, int rsigned) 152 { 153 uintmax sum = a + b; 154 return sum < a || help_fixup(r, sum, rsize, rsigned); 155 } 156 /* Likewise, but for the product of A and B. */ 157 public int help_ckd_mul(void *r, uintmax a, uintmax b, int rsize, int rsigned) 158 { 159 uintmax product = a * b; 160 return ((b != 0 && a != product / b) 161 || help_fixup(r, product, rsize, rsigned)); 162 } 163 #endif 164