OpenCores
URL https://opencores.org/ocsvn/thor/thor/trunk

Subversion Repositories thor

[/] [thor/] [trunk/] [FT64v5/] [software/] [AS64/] [source/] [Macro.cpp] - Blame information for rev 54

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 48 robfinch
#include "stdafx.h"
2
 
3 54 robfinch
int Macro::inst = 0;
4
 
5 48 robfinch
// Substitute the argument list into the macro body.
6
 
7 54 robfinch
char *Macro::SubArgs(Arglist *al)
8 48 robfinch
{
9
        char *buf, *bdy;
10
        char *p, *q;
11
        int ndx;
12 54 robfinch
        int bufsz;
13 48 robfinch
 
14
        bdy = body;
15 54 robfinch
        buf = new char[16000];
16
        ZeroMemory(buf, 16000);
17
        bufsz = 16000;
18
        for (p = buf; *bdy; bdy++) {
19 48 robfinch
                // If macro instance indicator found, substitute the instance number.
20 54 robfinch
                if (*bdy == '@') {
21
                        p += sprintf_s(p, bufsz - (p - buf), "%d", inst);
22
                        *p = '\0';
23
                }
24 48 robfinch
                else if (*bdy == MACRO_PARM_MARKER) {
25
                        if (isdigit(*(bdy+1))) {
26
                                bdy++;
27
                                ndx = *bdy - '0';
28 54 robfinch
                                if (ndx < parms.count && ndx < al->count) {
29
                                        // Copy the parameter from the arg list to the output buffer.
30
                                        if (&buf[bufsz] - p > al->args[ndx].text.length()) {
31
                                                strcpy(p, (char *)al->args[ndx].text.c_str());
32
                                                while (*p) p++;
33 48 robfinch
                                        }
34
                                }
35
                        }
36
                        else {
37
                                *p = *bdy;
38
                                p++;
39
                        }
40
                }
41
                // Not a parameter marker, just copy text to output.
42
                else {
43
                        *p = *bdy;
44
                        p++;
45
                }
46 54 robfinch
                if (&buf[bufsz] - p < 20) {
47
                        ndx = p - buf;
48
                        q = new char[bufsz + 10000];
49
                        memcpy(q, buf, bufsz);
50
                        bufsz += 10000;
51
                        delete[] buf;
52
                        buf = q;
53
                        p = &buf[ndx];
54
                }
55 48 robfinch
        }
56 54 robfinch
        *p = '\0';
57 48 robfinch
        return (buf);
58
}
59
 
60
 
61 54 robfinch
void SkipBlockComment()
62
{
63
        char c;
64
 
65
        do {
66
                c = *inptr;
67
                inptr++;
68
                if (c == '*') {
69
                        c = *inptr;
70
                        inptr++;
71
                        if (c == '/')
72
                                break;
73
                        --inptr;
74
                }
75
        } while (c > 0);
76
}
77
 
78
int ProcessUnquoted()
79
{
80
        char c;
81
 
82
        c = *inptr;
83
        if (c == '/') {
84
                c = *inptr;
85
                inptr++;
86
                c = *inptr;
87
                inptr++;
88
                // Block comment ?
89
                if (c == '*') {
90
                        SkipBlockComment();
91
                        c = *inptr;
92
                        if (c > 0)
93
                                return (1);
94
                        else {
95
                                printf("End of file in block comment. %d\n", lineno);
96
                                return (0);
97
                        }
98
                }
99
                // Comment to EOL ?
100
                else if (c == '/') {
101
                        ScanToEOL();
102
                        c = *inptr;
103
                        if (c > 0)
104
                                return (0);
105
                }
106
                else {
107
                        c = '/';
108
                        --inptr;
109
                }
110
        }
111
        return (1);
112
}
113
 
114
int CountLeadingSpaces()
115
{
116
        int count;
117
 
118
        count = 0;
119
        while (*inptr == ' ' || *inptr == '\t') {
120
                inptr++;
121
                count++;
122
        }
123
        return (count);
124
}
125
 
126 48 robfinch
// ---------------------------------------------------------------------------
127
//   Description :
128
//      Gets the body of a macro. All macro bodies must be < 2k in size. Macro
129
//   parameters are matched up with their positions in the macro. A $<number>
130
//   (as in $1, $2, etc) is substituted in the macro body in place of the
131
//   parameter name (we don't actually care what the parameter name is).
132
//      Macros continued on the next line with '\' are also processed. The
133
//   newline is removed from the macro.
134
// ----------------------------------------------------------------------------
135
 
136 54 robfinch
char *Macro::GetBody()
137 48 robfinch
{
138 54 robfinch
        char *b, *id = NULL, *p1, *p2;
139
        char *buf;
140
        int ii, found, c;
141
        int InQuote = 0;
142
        int count = 16000;
143
        bool abort = false;
144 48 robfinch
 
145 54 robfinch
        try {
146
                buf = new char[count];
147
                ZeroMemory(buf, count);
148
                SkipSpaces();
149
                for (b = buf; count >= 0; )
150
                {
151
                        // First search for an identifier to substitute with parameter
152
                        if (parms.count > 0) {
153
                                ii = CountLeadingSpaces();
154
                                count -= ii;
155
                                if (count < 0)
156
                                        break;
157
                                memcpy(b, inptr - ii, ii);
158
                                b += ii;
159
                                p1 = inptr;
160
                                NextToken();
161
                                p2 = inptr;
162
                                if (token == tk_endm)
163
                                        break;
164
                                if (token == tk_id) {
165
                                        for (found = ii = 0; ii < parms.count && !abort; ii++) {
166
                                                if (parms.args[ii].text.compare(lastid) == 0) {
167
                                                        *b = '\x14';
168
                                                        b++;
169
                                                        count--;
170
                                                        if (count < 0) {
171
                                                                abort = true;
172
                                                        }
173
                                                        else {
174
                                                                *b = '0' + (char)ii;
175
                                                                b++;
176
                                                                found = 1;
177
                                                                break;
178
                                                        }
179
                                                }
180
                                        }
181
                                        if (abort)
182
                                                break;
183
                                        // if the identifier was not a parameter then just copy it to
184
                                        // the macro body
185
                                        if (!found) {
186
                                                count -= p2 - p1;
187
                                                if (count < 0)
188
                                                        break;
189
                                                memcpy(b, p1, p2 - p1);
190
                                                b += p2 - p1;
191
                                        }
192
                                }
193
                                else
194
                                        inptr = p1;    // reset inptr if no identifier found
195
                        }
196
                        if (token == tk_endm)
197
                                break;
198
                        if (token != tk_id) {
199
                                memcpy(b, p1, p2 - p1);
200
                                b += p2 - p1;
201
                                inptr = p2;
202 48 robfinch
                                c = *inptr;
203 54 robfinch
                                //inptr++;
204
                                if (c == '"') {
205
                                        inptr++;
206
                                        InQuote = !InQuote;
207
                                }
208
                                if (!InQuote) {
209
                                        p1 = inptr;
210
                                        c = ProcessUnquoted();
211
                                        if (count - (inptr - p1) < 0) {
212
                                                count = -1;
213
                                                break;
214
                                        }
215
                                        memcpy(b, p1, (inptr - p1));
216
                                        b += (inptr - p1);
217
                                        if (c == 0)
218
                                                break;
219
                                        c = inptr[-1];
220
                                }
221
                                if (c < 1) {
222
                                        if (InQuote)
223
                                                printf("End of file in quote. %d\n", lineno);
224
                                        break;
225
                                }
226
                        }
227
                }
228
 
229
                if (count < 0) {
230
                        delete[] buf;
231
                        printf("Expanded macro is too large. %d\n", lineno);
232
                        body = new char[20];
233
                        strcpy(body, "<too large>");
234
                        return (body);
235
                }
236
                else {
237
                        *b = '\0';
238
                        --b;
239
                        // Trim off trailing spaces.
240
                        while ((*b == ' ' || *b == '\t') && b > buf) {
241
                                b--;
242
                        }
243
                        b++;
244
                        *b = '\0';
245
                        body = new char[strlen(buf) + 10];
246
                        strcpy(body, buf);
247
                        delete[] buf;
248
                        return (body);
249
                }
250
        }
251
        catch (...) {
252
                printf("Thrown error\n");
253
        }
254 48 robfinch
}
255
 
256
 
257
void Arg::Clear()
258
{
259 54 robfinch
        text = "";
260 48 robfinch
}
261
 
262
// ---------------------------------------------------------------------------
263
//   Description :
264
//      Gets an argument to be substituted into a macro body. Note that the
265
//   round bracket nesting level is kept track of so that a comma in the
266
//   middle of an argument isn't inadvertently picked up as an argument
267
//   separator.
268
// ---------------------------------------------------------------------------
269
 
270
void Arg::Get()
271
{
272 54 robfinch
        int Depth = 0;
273
        int c;
274
        char ch;
275
        char *st;
276 48 robfinch
 
277 54 robfinch
        SkipSpaces();
278
        st = inptr;
279
        while(1)
280
        {
281
    c = *inptr;
282 48 robfinch
          inptr++;
283 54 robfinch
                if (c < 1) {
284
                        if (Depth > 0)
285
                                printf("err16\r\n");
286
                        break;
287
                }
288
                if (c == '(')
289
                        Depth++;
290
                else if (c == ')') {
291
                        if (Depth < 1) {  // check if we hit the end of the arg list
292
                                --inptr;
293
                                break;
294
                        }
295
                        Depth--;
296
                }
297
                else if (Depth == 0 && c == ',') {   // comma at outermost level means
298
                        --inptr;
299
                        break;                           // end of argument has been found
300
                }
301
                else if (Depth == 0 && (c=='\r' || c=='\n')) {
302
                        --inptr;
303
                        break;
304 48 robfinch
          }
305
   }
306 54 robfinch
         ch = *inptr;
307
         *inptr = '\0';
308
         text = std::string(st);
309
         *inptr = ch;
310 48 robfinch
//   if (argbuf[0])
311
//         if (fdbg) fprintf(fdbg,"    macro arg<%s>\r\n",argbuf);
312
   return;
313
}
314
 
315
void Arglist::Get()
316
{
317
        int nn;
318
        char lastch;
319 54 robfinch
        bool done = false;
320 48 robfinch
 
321
        for (nn = 0; nn < 10; nn++)
322 54 robfinch
                args[nn].Clear();
323
        count = 0;
324
j1:
325
        SkipSpaces();
326
        switch (*inptr) {
327
        case '\n':
328
                lineno++;
329
        case '\r':
330
                inptr++;
331
                goto j1;
332
        case '(':
333
                inptr++;
334
                SkipSpaces();
335
                for (; count < 10 && !done; count++) {
336
                        args[count].Get();
337
                        switch (*inptr) {
338
                                // Arg list can continue on next line
339
                        case '\n':
340
                                lineno++;
341
                        case '\r':
342
                                inptr++;
343
                                continue;
344
                        case ')':
345
                                done = true;
346
                                inptr++;
347
                                break;
348
                        case ',':
349
                                inptr++;
350
                                SkipSpaces();
351
                                continue;
352
                        case '\0':
353
                                break;
354
                        default:
355
                                inptr++;
356
                        }
357 48 robfinch
                }
358 54 robfinch
                break;
359
        default:;
360 48 robfinch
        }
361
}
362
 
363
// ---------------------------------------------------------------------------
364
//   Description :
365
//      Used during the definition of a macro to get the associated parameter
366
//   list.
367
//
368
//   Returns
369
//      pointer to first parameter in list.
370
// ----------------------------------------------------------------------------
371
 
372 54 robfinch
int Macro::GetParmList()
373 48 robfinch
{
374 54 robfinch
        int id;
375
        int Depth = 0, c;
376 48 robfinch
 
377 54 robfinch
        parms.count = 0;
378
        while(1)
379
        {
380
                NextToken();
381
                if (token==tk_id) {
382
                        if (parms.count >= 20) {
383
                                printf("Too many macro parameters %d.\n", lineno);
384
                                goto errxit;
385
                        }
386
                        parms.args[parms.count].text = std::string(lastid);
387
                        parms.count++;
388
                }
389 48 robfinch
          do {
390
                        SkipSpaces();
391
                        c = *inptr;
392
                        inptr++;
393
                        if (c=='\\') {
394
                                ScanToEOL();
395
                                inptr++;
396
                        }
397
                }
398
                while (c=='\\');
399 54 robfinch
    if (c == ')') {   // we've gotten our last parameter
400
      inptr--;
401
      break;
402
    }
403
    if (c != ',') {
404
                        printf("Expecting ',' in macro parameter list %d.\n", lineno);
405
      goto errxit;
406
    }
407
  }
408 48 robfinch
errxit:;
409 54 robfinch
   return (parms.count);
410 48 robfinch
}
411
 
412
 
413
// -----------------------------------------------------------------------------
414
//   Description :
415
//      Copies a macro into the input buffer. Resets the input buffer pointer
416
//   to the start of the macro.
417
//
418
//   slen; - the number of characters being substituted
419
// -----------------------------------------------------------------------------
420
 
421 54 robfinch
void Macro::Substitute(char *what, int slen)
422 48 robfinch
{
423 54 robfinch
        int mlen, dif, nchars;
424
        int nn;
425
        char *p;
426 48 robfinch
 
427 54 robfinch
        mlen = strlen(what);          // macro length
428
        dif = mlen - slen;
429
        nchars = inptr - masterFile;         // calculate number of characters that could be remaining
430
        if (dif > 10000) {
431
                p = new char[masterFileLength + dif + 10000];
432
                memcpy(p, masterFile, masterFileLength);
433
                masterFile = p;
434
                masterFileLength = masterFileLength + dif + 10000;
435
                inptr = &masterFile[nchars];
436
        }
437
        memmove(inptr+dif, inptr, masterFileLength-500-nchars-dif);  // shift open space in input buffer
438
        inptr -= slen;                // reset input pointer to start of replaced text
439
        memcpy(inptr, what, mlen);    // copy macro body in place over identifier
440
        inst++;
441 48 robfinch
}
442
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.