1: // Copyright (C) 1994-1998 by Symantec
2: // Copyright (C) 2000-2009 by Digital Mars
3: // All Rights Reserved
4: // http://www.digitalmars.com
5: // Written by Walter Bright
6: /*
7: * This source file is made available for personal use
8: * only. The license is in /dmd/src/dmd/backendlicense.txt
9: * or /dm/src/dmd/backendlicense.txt
10: * For any other uses, please contact Digital Mars.
11: */
12:
13: // Output buffer
14:
15: #include <string.h>
16: #include <stdlib.h>
17: #include <time.h>
18:
19: #include "cc.h"
20:
21: #include "outbuf.h"
22: #include "mem.h"
23:
24: #if DEBUG
25: static char __file__[] = __FILE__; // for tassert.h
26: #include "tassert.h"
27: #endif
28:
29: Outbuffer::Outbuffer()
30: {
31: buf = NULL;
32: pend = NULL;
33: p = NULL;
34: len = 0;
35: inc = 0;
36: }
37:
38: Outbuffer::Outbuffer(unsigned bufinc)
39: {
40: buf = NULL;
41: pend = NULL;
42: p = NULL;
43: len = 0;
44: inc = bufinc;
45: }
46:
47: Outbuffer::~Outbuffer()
48: {
49: #if MEM_DEBUG
50: mem_free(buf);
51: #else
52: if (buf)
53: free(buf);
54: #endif
55: }
56:
57: void Outbuffer::reset()
58: {
59: p = buf;
60: }
61:
62: // Reserve nbytes in buffer
63: void Outbuffer::reserve(unsigned nbytes)
64: {
65: if (pend - p < nbytes)
warning C4018: '<' : signed/unsigned mismatch
66: { unsigned oldlen = len;
67: unsigned used = p - buf;
68:
69: if (inc > nbytes)
70: {
71: len = used + inc;
72: }
73: else
74: {
75: len = used + nbytes;
76: if (len < 2 * oldlen)
77: { len = 2 * oldlen;
78: if (len < 8)
79: len = 8;
80: }
81: }
82: #if MEM_DEBUG
83: buf = (unsigned char *)mem_realloc(buf, len);
84: #else
85: if (buf)
86: buf = (unsigned char *) realloc(buf,len);
warning C6308: 'realloc' might return null pointer: assigning null pointer to 'buf', which is passed as an argument to 'realloc', will cause the original memory block to be leaked
87: else
88: buf = (unsigned char *) malloc(len);
89: #endif
90: pend = buf + len;
91: p = buf + used;
92: }
93: }
94:
95: // Position buffer for output at a specified location and size.
96: // If data will extend buffer size, reserve space
97: // If data will rewrite existing data
98: // position for write and return previous buffer size
99: //
100: // If data will append to buffer
101: // position for write and return new size
102: int Outbuffer::position(unsigned pos, unsigned nbytes)
103: {
104: int current_sz = size();
105: unsigned char *fend = buf+pos+nbytes; // future end of buffer
106: if (fend >= pend)
107: {
108: reserve (fend - pend);
109: }
110: setsize(pos);
111: return pos+nbytes > current_sz ? pos+nbytes : current_sz;
warning C4018: '>' : signed/unsigned mismatch
112: }
113:
114: // Write an array to the buffer.
115: void Outbuffer::write(const void *b, int len)
116: {
117: if (pend - p < len)
118: reserve(len);
119: memcpy(p,b,len);
120: p += len;
121: }
122:
123: // Write n zeros to the buffer.
124: void *Outbuffer::writezeros(unsigned len)
125: {
126: if (pend - p < len)
warning C4018: '<' : signed/unsigned mismatch
127: reserve(len);
128: void *pstart = memset(p,0,len);
129: p += len;
130: return pstart;
131: }
132:
133: /**
134: * Writes an 8 bit byte.
135: */
136: void Outbuffer::writeByte(int v)
137: {
138: if (pend == p)
139: reserve(1);
140: *p++ = v;
141: }
142:
143: /**
144: * Writes a 32 bit int.
145: */
146: void Outbuffer::write32(int v)
147: {
148: if (pend - p < 4)
149: reserve(4);
150: *(int *)p = v;
151: p += 4;
152: }
153:
154: /**
155: * Writes a 64 bit long.
156: */
157:
158: #if __INTSIZE == 4
159: void Outbuffer::write64(long long v)
160: {
161: if (pend - p < 8)
162: reserve(8);
163: *(long long *)p = v;
164: p += 8;
165: }
166: #endif
167:
168: /**
169: * Writes a 32 bit float.
170: */
171: void Outbuffer::writeFloat(float v)
172: {
173: if (pend - p < sizeof(float))
174: reserve(sizeof(float));
175: *(float *)p = v;
176: p += sizeof(float);
177: }
178:
179: /**
180: * Writes a 64 bit double.
181: */
182: void Outbuffer::writeDouble(double v)
183: {
184: if (pend - p < sizeof(double))
185: reserve(sizeof(double));
186: *(double *)p = v;
187: p += sizeof(double);
188: }
189:
190: /**
191: * Writes a String as a sequence of bytes.
192: */
193: void Outbuffer::write(const char *s)
194: {
195: write(s,strlen(s));
196: }
197:
198:
199: /**
200: * Writes a String as a sequence of bytes.
201: */
202: void Outbuffer::write(const unsigned char *s)
203: {
204: write(s,strlen((const char *)s));
205: }
206:
207:
208: /**
209: * Writes a NULL terminated String
210: */
211: void Outbuffer::writeString(const char *s)
212: {
213: write(s,strlen(s)+1);
214: }
215:
216: /**
217: * Inserts string at beginning of buffer.
218: */
219:
220: void Outbuffer::prependBytes(const char *s)
221: {
222: size_t len = strlen(s);
223:
224: reserve(len);
225: memmove(buf + len,buf,p - buf);
226: memcpy(buf,s,len);
227: p += len;
228: }
229:
230: /**
231: */
232:
233: void Outbuffer::bracket(char c1,char c2)
234: {
235: reserve(2);
236: memmove(buf + 1,buf,p - buf);
237: buf[0] = c1;
238: p[1] = c2;
239: p += 2;
240: }
241:
242: /**
243: * Convert to a string.
244: */
245:
246: char *Outbuffer::toString()
247: {
248: if (pend == p)
249: reserve(1);
250: *p = 0; // terminate string
251: return (char *)buf;
252: }
253:
254: /**
255: * Set current size of buffer.
256: */
257:
258: void Outbuffer::setsize(unsigned size)
259: {
260: p = buf + size;
261: }
262:
263: void Outbuffer::writesLEB128(int value)
264: {
265: while (1)
266: {
267: unsigned char b = value & 0x7F;
268:
269: value >>= 7; // arithmetic right shift
270: if (value == 0 && !(b & 0x40) ||
271: value == -1 && (b & 0x40))
272: {
273: writeByte(b);
274: break;
275: }
276: writeByte(b | 0x80);
277: }
278: }
279:
280: void Outbuffer::writeuLEB128(unsigned value)
281: {
282: do
283: { unsigned char b = value & 0x7F;
284:
285: value >>= 7;
286: if (value)
287: b |= 0x80;
288: writeByte(b);
289: } while (value);
290: }
291:
292: