1 /** 2 * Utility subroutines 3 * 4 * Only used for DMD 5 * 6 * Compiler implementation of the 7 * $(LINK2 https://www.dlang.org, D programming language). 8 * 9 * Copyright: Copyright (C) 1984-1998 by Symantec 10 * Copyright (C) 2000-2023 by The D Language Foundation, All Rights Reserved 11 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) 12 * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 13 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/backend/util2.d, backend/util2.d) 14 */ 15 16 module dmd.backend.util2; 17 18 import core.stdc.stdio; 19 import core.stdc.stdlib; 20 import core.stdc.string; 21 22 import dmd.backend.cc; 23 import dmd.backend.cdef; 24 import dmd.backend.global; 25 import dmd.backend.mem; 26 27 extern (C++): 28 29 nothrow: 30 @safe: 31 32 void *ph_malloc(size_t nbytes); 33 void *ph_calloc(size_t nbytes); 34 void ph_free(void *p); 35 void *ph_realloc(void *p , size_t nbytes); 36 37 void file_progress() 38 { 39 } 40 41 /**************************** 42 * Clean up and exit program. 43 */ 44 45 void err_exit() 46 { 47 util_exit(EXIT_FAILURE); 48 } 49 50 /******************************** 51 * Clean up and exit program. 52 */ 53 54 void err_break() 55 { 56 util_exit(255); 57 } 58 59 60 /**************************** 61 * Clean up and exit program. 62 */ 63 @trusted 64 void util_exit(int exitcode) 65 { 66 exit(exitcode); /* terminate abnormally */ 67 } 68 69 version (CRuntime_DigitalMars) 70 { 71 72 extern (C) extern __gshared int controlc_saw; 73 74 /******************************** 75 * Control C interrupts go here. 76 */ 77 @trusted 78 private extern (C) void controlc_handler() 79 { 80 //printf("saw controlc\n"); 81 controlc_saw = 1; 82 } 83 84 /********************************* 85 * Trap control C interrupts. 86 */ 87 88 version (MARS) { } else 89 { 90 91 extern (C) 92 { 93 void controlc_open(); 94 void controlc_close(); 95 alias _controlc_handler_t = void function(); 96 extern __gshared _controlc_handler_t _controlc_handler; 97 98 void _STI_controlc() 99 { 100 //printf("_STI_controlc()\n"); 101 _controlc_handler = &controlc_handler; 102 controlc_open(); /* trap control C */ 103 } 104 105 void _STD_controlc() 106 { 107 //printf("_STD_controlc()\n"); 108 controlc_close(); 109 } 110 } 111 112 } 113 } 114 115 /*********************************** 116 * Send progress report. 117 */ 118 119 void util_progress() 120 { 121 version (MARS) { } else { 122 version (CRuntime_DigitalMars) 123 { 124 if (controlc_saw) 125 err_break(); 126 } 127 } 128 } 129 130 void util_progress(int linnum) 131 { 132 version (MARS) { } else { 133 version (CRuntime_DigitalMars) 134 { 135 if (controlc_saw) 136 err_break(); 137 } 138 } 139 } 140 141 142 /********************************** 143 * Binary string search. 144 * Input: 145 * p . string of characters 146 * tab array of pointers to strings 147 * n = number of pointers in the array 148 * Returns: 149 * index (0..n-1) into tab[] if we found a string match 150 * else -1 151 */ 152 153 version (X86) version (CRuntime_DigitalMars) 154 version = X86asm; 155 156 @trusted 157 int binary(const(char)* p, const(char)* *table,int high) 158 { 159 version (X86asm) 160 { 161 alias len = high; // reuse parameter storage 162 asm nothrow 163 { 164 165 // First find the length of the identifier. 166 xor EAX,EAX ; // Scan for a 0. 167 mov EDI,p ; 168 mov ECX,EAX ; 169 dec ECX ; // Longest possible string. 170 repne ; 171 scasb ; 172 mov EDX,high ; // EDX = high 173 not ECX ; // length of the id including '/0', stays in ECX 174 dec EDX ; // high-- 175 js short Lnotfound ; 176 dec EAX ; // EAX = -1, so that eventually EBX = low (0) 177 mov len,ECX ; 178 179 even ; 180 L4D: lea EBX,[EAX + 1] ; // low = mid + 1 181 cmp EBX,EDX ; 182 jg Lnotfound ; 183 184 even ; 185 L15: lea EAX,[EBX + EDX] ; // EAX = low + high 186 187 // Do the string compare. 188 189 mov EDI,table ; 190 sar EAX,1 ; // mid = (low + high) >> 1 191 mov ESI,p ; 192 mov EDI,[4*EAX+EDI] ; // Load table[mid] 193 mov ECX,len ; // length of id 194 repe ; 195 cmpsb ; 196 197 je short L63 ; // return mid if equal 198 jns short L4D ; // if (cond < 0) 199 lea EDX,-1[EAX] ; // high = mid - 1 200 cmp EBX,EDX ; 201 jle L15 ; 202 203 Lnotfound: 204 mov EAX,-1 ; // Return -1. 205 206 even ; 207 L63: ; 208 } 209 } 210 else 211 { 212 int low = 0; 213 char cp = *p; 214 high--; 215 p++; 216 217 while (low <= high) 218 { 219 int mid = low + ((high - low) >> 1); 220 int cond = table[mid][0] - cp; 221 if (cond == 0) 222 cond = strcmp(table[mid] + 1,p); 223 if (cond > 0) 224 high = mid - 1; 225 else if (cond < 0) 226 low = mid + 1; 227 else 228 return mid; /* match index */ 229 } 230 return -1; 231 } 232 } 233 234 235 // search table[0 .. high] for p[0 .. len] (where p.length not necessairily equal to len) 236 @trusted 237 int binary(const(char)* p, size_t len, const(char)** table, int high) 238 { 239 int low = 0; 240 char cp = *p; 241 high--; 242 p++; 243 len--; 244 245 while (low <= high) 246 { 247 int mid = low + ((high - low) >> 1); 248 int cond = table[mid][0] - cp; 249 250 if (cond == 0) 251 { 252 cond = strncmp(table[mid] + 1, p, len); 253 if (cond == 0) 254 cond = table[mid][len+1]; // same as: if (table[mid][len+1] != '\0') cond = 1; 255 } 256 257 if (cond > 0) 258 high = mid - 1; 259 else if (cond < 0) 260 low = mid + 1; 261 else 262 return mid; /* match index */ 263 } 264 return -1; 265 } 266 267 /********************** 268 * If c is a power of 2, return that power else -1. 269 */ 270 271 int ispow2(ulong c) 272 { int i; 273 274 if (c == 0 || (c & (c - 1))) 275 i = -1; 276 else 277 for (i = 0; c >>= 1; i++) 278 { } 279 return i; 280 } 281 282 /*************************** 283 */ 284 285 enum UTIL_PH = true; 286 287 version (MEM_DEBUG) 288 enum MEM_DEBUG = false; //true; 289 else 290 enum MEM_DEBUG = false; 291 292 version (Windows) 293 { 294 void *util_malloc(uint n,uint size) 295 { 296 static if (MEM_DEBUG) 297 { 298 void *p; 299 300 p = mem_malloc(n * size); 301 //dbg_printf("util_calloc(%d) = %p\n",n * size,p); 302 return p; 303 } 304 else static if (UTIL_PH) 305 { 306 return ph_malloc(n * size); 307 } 308 else 309 { 310 size_t nbytes = cast(size_t)n * cast(size_t)size; 311 void *p = malloc(nbytes); 312 if (!p && nbytes) 313 err_nomem(); 314 return p; 315 } 316 } 317 } 318 319 /*************************** 320 */ 321 322 version (Windows) 323 { 324 void *util_calloc(uint n,uint size) 325 { 326 static if (MEM_DEBUG) 327 { 328 void *p; 329 330 p = mem_calloc(n * size); 331 //dbg_printf("util_calloc(%d) = %p\n",n * size,p); 332 return p; 333 } 334 else static if (UTIL_PH) 335 { 336 return ph_calloc(n * size); 337 } 338 else 339 { 340 size_t nbytes = cast(size_t) n * cast(size_t) size; 341 void *p = calloc(n,size); 342 if (!p && nbytes) 343 err_nomem(); 344 return p; 345 } 346 } 347 } 348 349 /*************************** 350 */ 351 352 version (Windows) 353 { 354 void util_free(void *p) 355 { 356 //dbg_printf("util_free(%p)\n",p); 357 static if (MEM_DEBUG) 358 { 359 mem_free(p); 360 } 361 else static if (UTIL_PH) 362 { 363 ph_free(p); 364 } 365 else 366 { 367 free(p); 368 } 369 } 370 } 371 372 /*************************** 373 */ 374 375 version (Windows) 376 { 377 void *util_realloc(void *oldp,size_t n,size_t size) 378 { 379 static if (MEM_DEBUG) 380 { 381 //dbg_printf("util_realloc(%p,%d)\n",oldp,n * size); 382 return mem_realloc(oldp,n * size); 383 } 384 else static if (UTIL_PH) 385 { 386 return ph_realloc(oldp,n * size); 387 } 388 else 389 { 390 const nbytes = n * size; 391 void *p = realloc(oldp,nbytes); 392 if (!p && nbytes) 393 err_nomem(); 394 return p; 395 } 396 } 397 } 398 399 /***************************** 400 */ 401 void *mem_malloc2(uint size) 402 { 403 return mem_malloc(size); 404 }