1 2 /* Compiler implementation of the D programming language 3 * Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved 4 * written by Walter Bright 5 * http://www.digitalmars.com 6 * Distributed under the Boost Software License, Version 1.0. 7 * http://www.boost.org/LICENSE_1_0.txt 8 * https://github.com/D-Programming-Language/dmd/blob/master/src/identifier.c 9 */ 10 11 #include "root/dsystem.h" 12 #include "root/root.h" 13 14 #include "identifier.h" 15 #include "mars.h" 16 #include "id.h" 17 #include "tokens.h" 18 #include "utf.h" 19 20 Identifier::Identifier(const char *string, size_t length, int value) 21 { 22 //printf("Identifier('%s', %d)\n", string, value); 23 this->string = string; 24 this->value = value; 25 this->len = length; 26 } 27 28 Identifier::Identifier(const char *string) 29 { 30 //printf("Identifier('%s')\n", string); 31 this->string = string; 32 this->value = TOKidentifier; 33 this->len = strlen(string); 34 } 35 36 Identifier *Identifier::create(const char *string) 37 { 38 return new Identifier(string); 39 } 40 41 bool Identifier::equals(RootObject *o) 42 { 43 return this == o || strncmp(string,o->toChars(),len+1) == 0; 44 } 45 46 int Identifier::compare(RootObject *o) 47 { 48 return strncmp(string, o->toChars(), len + 1); 49 } 50 51 const char *Identifier::toChars() 52 { 53 return string; 54 } 55 56 int Identifier::getValue() const 57 { 58 return value; 59 } 60 61 const char *Identifier::toHChars2() 62 { 63 const char *p = NULL; 64 65 if (this == Id::ctor) p = "this"; 66 else if (this == Id::dtor) p = "~this"; 67 else if (this == Id::unitTest) p = "unittest"; 68 else if (this == Id::dollar) p = "$"; 69 else if (this == Id::withSym) p = "with"; 70 else if (this == Id::result) p = "result"; 71 else if (this == Id::returnLabel) p = "return"; 72 else 73 { p = toChars(); 74 if (*p == '_') 75 { 76 if (strncmp(p, "_staticCtor", 11) == 0) 77 p = "static this"; 78 else if (strncmp(p, "_staticDtor", 11) == 0) 79 p = "static ~this"; 80 else if (strncmp(p, "__invariant", 11) == 0) 81 p = "invariant"; 82 } 83 } 84 85 return p; 86 } 87 88 void Identifier::print() 89 { 90 fprintf(stderr, "%s",string); 91 } 92 93 int Identifier::dyncast() const 94 { 95 return DYNCAST_IDENTIFIER; 96 } 97 98 StringTable Identifier::stringtable; 99 100 Identifier *Identifier::generateId(const char *prefix) 101 { 102 static size_t i; 103 104 return generateId(prefix, ++i); 105 } 106 107 Identifier *Identifier::generateId(const char *prefix, size_t i) 108 { OutBuffer buf; 109 110 buf.writestring(prefix); 111 buf.printf("%llu", (ulonglong)i); 112 113 char *id = buf.peekString(); 114 return idPool(id); 115 } 116 117 /******************************************** 118 * Create an identifier in the string table. 119 */ 120 121 Identifier *Identifier::idPool(const char *s, size_t len) 122 { 123 StringValue *sv = stringtable.update(s, len); 124 Identifier *id = (Identifier *) sv->ptrvalue; 125 if (!id) 126 { 127 id = new Identifier(sv->toDchars(), len, TOKidentifier); 128 sv->ptrvalue = (char *)id; 129 } 130 return id; 131 } 132 133 Identifier *Identifier::idPool(const char *s, size_t len, int value) 134 { 135 StringValue *sv = stringtable.insert(s, len, NULL); 136 assert(sv); 137 Identifier *id = new Identifier(sv->toDchars(), len, value); 138 sv->ptrvalue = (char *)id; 139 return id; 140 } 141 142 /********************************** 143 * Determine if string is a valid Identifier. 144 * Returns: 145 * 0 invalid 146 */ 147 148 bool Identifier::isValidIdentifier(const char *p) 149 { 150 size_t len; 151 size_t idx; 152 153 if (!p || !*p) 154 goto Linvalid; 155 156 if (*p >= '0' && *p <= '9') // beware of isdigit() on signed chars 157 goto Linvalid; 158 159 len = strlen(p); 160 idx = 0; 161 while (p[idx]) 162 { 163 dchar_t dc; 164 const char *q = utf_decodeChar((const utf8_t *)p, len, &idx, &dc); 165 if (q) 166 goto Linvalid; 167 168 if (!((dc >= 0x80 && isUniAlpha(dc)) || isalnum(dc) || dc == '_')) 169 goto Linvalid; 170 } 171 return true; 172 173 Linvalid: 174 return false; 175 } 176 177 Identifier *Identifier::lookup(const char *s, size_t len) 178 { 179 StringValue *sv = stringtable.lookup(s, len); 180 if (!sv) 181 return NULL; 182 return (Identifier *)sv->ptrvalue; 183 } 184 185 void Identifier::initTable() 186 { 187 stringtable._init(28000); 188 } 189