diff options
Diffstat (limited to 'gcc/d/dmd/dmacro.c')
-rw-r--r-- | gcc/d/dmd/dmacro.c | 458 |
1 files changed, 0 insertions, 458 deletions
diff --git a/gcc/d/dmd/dmacro.c b/gcc/d/dmd/dmacro.c deleted file mode 100644 index 91cbe50..0000000 --- a/gcc/d/dmd/dmacro.c +++ /dev/null @@ -1,458 +0,0 @@ - -/* Compiler implementation of the D programming language - * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved - * written by Walter Bright - * http://www.digitalmars.com - * Distributed under the Boost Software License, Version 1.0. - * http://www.boost.org/LICENSE_1_0.txt - * https://github.com/D-Programming-Language/dmd/blob/master/src/macro.c - */ - -/* Simple macro text processor. - */ - -#include "root/dsystem.h" - -#include "mars.h" -#include "errors.h" -#include "root/rmem.h" -#include "root/root.h" - -#include "macro.h" - -bool isIdStart(const utf8_t *p); -bool isIdTail(const utf8_t *p); -int utfStride(const utf8_t *p); - -utf8_t *memdup(const utf8_t *p, size_t len) -{ - return (utf8_t *)memcpy(mem.xmalloc(len), p, len); -} - -Macro::Macro(const utf8_t *name, size_t namelen, const utf8_t *text, size_t textlen) -{ - next = NULL; - - this->name = name; - this->namelen = namelen; - - this->text = text; - this->textlen = textlen; - inuse = 0; -} - - -Macro *Macro::search(const utf8_t *name, size_t namelen) -{ Macro *table; - - //printf("Macro::search(%.*s)\n", namelen, name); - for (table = this; table; table = table->next) - { - if (table->namelen == namelen && - memcmp(table->name, name, namelen) == 0) - { - //printf("\tfound %d\n", table->textlen); - break; - } - } - return table; -} - -Macro *Macro::define(Macro **ptable, const utf8_t *name, size_t namelen, const utf8_t *text, size_t textlen) -{ - //printf("Macro::define('%.*s' = '%.*s')\n", namelen, name, textlen, text); - - Macro *table; - - //assert(ptable); - for (table = *ptable; table; table = table->next) - { - if (table->namelen == namelen && - memcmp(table->name, name, namelen) == 0) - { - table->text = text; - table->textlen = textlen; - return table; - } - } - table = new Macro(name, namelen, text, textlen); - table->next = *ptable; - *ptable = table; - return table; -} - -/********************************************************** - * Given buffer p[0..end], extract argument marg[0..marglen]. - * Params: - * n 0: get entire argument - * 1..9: get nth argument - * -1: get 2nd through end - */ - -size_t extractArgN(const utf8_t *p, size_t end, const utf8_t **pmarg, size_t *pmarglen, int n) -{ - /* Scan forward for matching right parenthesis. - * Nest parentheses. - * Skip over "..." and '...' strings inside HTML tags. - * Skip over <!-- ... --> comments. - * Skip over previous macro insertions - * Set marglen. - */ - unsigned parens = 1; - unsigned char instring = 0; - unsigned incomment = 0; - unsigned intag = 0; - unsigned inexp = 0; - int argn = 0; - - size_t v = 0; - - Largstart: - // Skip first space, if any, to find the start of the macro argument - if (n != 1 && v < end && isspace(p[v])) - v++; - *pmarg = p + v; - - for (; v < end; v++) - { utf8_t c = p[v]; - - switch (c) - { - case ',': - if (!inexp && !instring && !incomment && parens == 1) - { - argn++; - if (argn == 1 && n == -1) - { v++; - goto Largstart; - } - if (argn == n) - break; - if (argn + 1 == n) - { v++; - goto Largstart; - } - } - continue; - - case '(': - if (!inexp && !instring && !incomment) - parens++; - continue; - - case ')': - if (!inexp && !instring && !incomment && --parens == 0) - { - break; - } - continue; - - case '"': - case '\'': - if (!inexp && !incomment && intag) - { - if (c == instring) - instring = 0; - else if (!instring) - instring = c; - } - continue; - - case '<': - if (!inexp && !instring && !incomment) - { - if (v + 6 < end && - p[v + 1] == '!' && - p[v + 2] == '-' && - p[v + 3] == '-') - { - incomment = 1; - v += 3; - } - else if (v + 2 < end && - isalpha(p[v + 1])) - intag = 1; - } - continue; - - case '>': - if (!inexp) - intag = 0; - continue; - - case '-': - if (!inexp && - !instring && - incomment && - v + 2 < end && - p[v + 1] == '-' && - p[v + 2] == '>') - { - incomment = 0; - v += 2; - } - continue; - - case 0xFF: - if (v + 1 < end) - { - if (p[v + 1] == '{') - inexp++; - else if (p[v + 1] == '}') - inexp--; - } - continue; - - default: - continue; - } - break; - } - if (argn == 0 && n == -1) - *pmarg = p + v; - *pmarglen = p + v - *pmarg; - //printf("extractArg%d('%.*s') = '%.*s'\n", n, end, p, *pmarglen, *pmarg); - return v; -} - - -/***************************************************** - * Expand macro in place in buf. - * Only look at the text in buf from start to end. - */ - -void Macro::expand(OutBuffer *buf, size_t start, size_t *pend, - const utf8_t *arg, size_t arglen) -{ - // limit recursive expansion - static int nest; - if (nest > global.recursionLimit) - { - error(Loc(), "DDoc macro expansion limit exceeded; more than %d expansions.", - global.recursionLimit); - return; - } - nest++; - - size_t end = *pend; - assert(start <= end); - assert(end <= buf->length()); - - /* First pass - replace $0 - */ - arg = memdup(arg, arglen); - for (size_t u = start; u + 1 < end; ) - { - utf8_t *p = (utf8_t *)buf->slice().ptr; // buf->slice().ptr is not loop invariant - - /* Look for $0, but not $$0, and replace it with arg. - */ - if (p[u] == '$' && (isdigit(p[u + 1]) || p[u + 1] == '+')) - { - if (u > start && p[u - 1] == '$') - { // Don't expand $$0, but replace it with $0 - buf->remove(u - 1, 1); - end--; - u += 1; // now u is one past the closing '1' - continue; - } - - utf8_t c = p[u + 1]; - int n = (c == '+') ? -1 : c - '0'; - - const utf8_t *marg; - size_t marglen; - if (n == 0) - { - marg = arg; - marglen = arglen; - } - else - extractArgN(arg, arglen, &marg, &marglen, n); - if (marglen == 0) - { // Just remove macro invocation - //printf("Replacing '$%c' with '%.*s'\n", p[u + 1], marglen, marg); - buf->remove(u, 2); - end -= 2; - } - else if (c == '+') - { - // Replace '$+' with 'arg' - //printf("Replacing '$%c' with '%.*s'\n", p[u + 1], marglen, marg); - buf->remove(u, 2); - buf->insert(u, marg, marglen); - end += marglen - 2; - - // Scan replaced text for further expansion - size_t mend = u + marglen; - expand(buf, u, &mend, NULL, 0); - end += mend - (u + marglen); - u = mend; - } - else - { - // Replace '$1' with '\xFF{arg\xFF}' - //printf("Replacing '$%c' with '\xFF{%.*s\xFF}'\n", p[u + 1], marglen, marg); - buf->slice().ptr[u] = 0xFF; - buf->slice().ptr[u + 1] = '{'; - buf->insert(u + 2, marg, marglen); - buf->insert(u + 2 + marglen, (const char *)"\xFF}", 2); - end += -2 + 2 + marglen + 2; - - // Scan replaced text for further expansion - size_t mend = u + 2 + marglen; - expand(buf, u + 2, &mend, NULL, 0); - end += mend - (u + 2 + marglen); - u = mend; - } - //printf("u = %d, end = %d\n", u, end); - //printf("#%.*s#\n", end, &buf->slice().ptr[0]); - continue; - } - - u++; - } - - /* Second pass - replace other macros - */ - for (size_t u = start; u + 4 < end; ) - { - utf8_t *p = (utf8_t *)buf->slice().ptr; // buf->slice().ptr is not loop invariant - - /* A valid start of macro expansion is $(c, where c is - * an id start character, and not $$(c. - */ - if (p[u] == '$' && p[u + 1] == '(' && isIdStart(p+u+2)) - { - //printf("\tfound macro start '%c'\n", p[u + 2]); - utf8_t *name = p + u + 2; - size_t namelen = 0; - - const utf8_t *marg; - size_t marglen; - - size_t v; - /* Scan forward to find end of macro name and - * beginning of macro argument (marg). - */ - for (v = u + 2; v < end; v+=utfStride(p+v)) - { - - if (!isIdTail(p+v)) - { // We've gone past the end of the macro name. - namelen = v - (u + 2); - break; - } - } - - v += extractArgN(p + v, end - v, &marg, &marglen, 0); - assert(v <= end); - - if (v < end) - { // v is on the closing ')' - if (u > start && p[u - 1] == '$') - { // Don't expand $$(NAME), but replace it with $(NAME) - buf->remove(u - 1, 1); - end--; - u = v; // now u is one past the closing ')' - continue; - } - - Macro *m = search(name, namelen); - - if (!m) - { - static const char undef[] = "DDOC_UNDEFINED_MACRO"; - m = search((const utf8_t *)undef, strlen(undef)); - if (m) - { - // Macro was not defined, so this is an expansion of - // DDOC_UNDEFINED_MACRO. Prepend macro name to args. - // marg = name[ ] ~ "," ~ marg[ ]; - if (marglen) - { - utf8_t *q = (utf8_t *)mem.xmalloc(namelen + 1 + marglen); - assert(q); - memcpy(q, name, namelen); - q[namelen] = ','; - memcpy(q + namelen + 1, marg, marglen); - marg = q; - marglen += namelen + 1; - } - else - { - marg = name; - marglen = namelen; - } - } - } - - if (m) - { - if (m->inuse && marglen == 0) - { // Remove macro invocation - buf->remove(u, v + 1 - u); - end -= v + 1 - u; - } - else if (m->inuse && - ((arglen == marglen && memcmp(arg, marg, arglen) == 0) || - (arglen + 4 == marglen && - marg[0] == 0xFF && - marg[1] == '{' && - memcmp(arg, marg + 2, arglen) == 0 && - marg[marglen - 2] == 0xFF && - marg[marglen - 1] == '}' - ) - ) - ) - { - /* Recursive expansion: - * marg is same as arg (with blue paint added) - * Just leave in place. - */ - } - else - { - //printf("\tmacro '%.*s'(%.*s) = '%.*s'\n", m->namelen, m->name, marglen, marg, m->textlen, m->text); - marg = memdup(marg, marglen); - // Insert replacement text - buf->spread(v + 1, 2 + m->textlen + 2); - buf->slice().ptr[v + 1] = 0xFF; - buf->slice().ptr[v + 2] = '{'; - memcpy(buf->slice().ptr + v + 3, m->text, m->textlen); - buf->slice().ptr[v + 3 + m->textlen] = 0xFF; - buf->slice().ptr[v + 3 + m->textlen + 1] = '}'; - - end += 2 + m->textlen + 2; - - // Scan replaced text for further expansion - m->inuse++; - size_t mend = v + 1 + 2+m->textlen+2; - expand(buf, v + 1, &mend, marg, marglen); - end += mend - (v + 1 + 2+m->textlen+2); - m->inuse--; - - buf->remove(u, v + 1 - u); - end -= v + 1 - u; - u += mend - (v + 1); - mem.xfree(const_cast<utf8_t *>(marg)); - //printf("u = %d, end = %d\n", u, end); - //printf("#%.*s#\n", end - u, &buf->slice().ptr[u]); - continue; - } - } - else - { - // Replace $(NAME) with nothing - buf->remove(u, v + 1 - u); - end -= (v + 1 - u); - continue; - } - } - } - u++; - } - mem.xfree(const_cast<utf8_t *>(arg)); - *pend = end; - nest--; -} |