demangle-ocaml.c (1460B)
1// SPDX-License-Identifier: GPL-2.0 2#include <string.h> 3#include <stdlib.h> 4#include "util/string2.h" 5 6#include "demangle-ocaml.h" 7 8#include <linux/ctype.h> 9 10static const char *caml_prefix = "caml"; 11static const size_t caml_prefix_len = 4; 12 13/* mangled OCaml symbols start with "caml" followed by an upper-case letter */ 14static bool 15ocaml_is_mangled(const char *sym) 16{ 17 return 0 == strncmp(sym, caml_prefix, caml_prefix_len) 18 && isupper(sym[caml_prefix_len]); 19} 20 21/* 22 * input: 23 * sym: a symbol which may have been mangled by the OCaml compiler 24 * return: 25 * if the input doesn't look like a mangled OCaml symbol, NULL is returned 26 * otherwise, a newly allocated string containing the demangled symbol is returned 27 */ 28char * 29ocaml_demangle_sym(const char *sym) 30{ 31 char *result; 32 int j = 0; 33 int i; 34 int len; 35 36 if (!ocaml_is_mangled(sym)) { 37 return NULL; 38 } 39 40 len = strlen(sym); 41 42 /* the demangled symbol is always smaller than the mangled symbol */ 43 result = malloc(len + 1); 44 if (!result) 45 return NULL; 46 47 /* skip "caml" prefix */ 48 i = caml_prefix_len; 49 50 while (i < len) { 51 if (sym[i] == '_' && sym[i + 1] == '_') { 52 /* "__" -> "." */ 53 result[j++] = '.'; 54 i += 2; 55 } 56 else if (sym[i] == '$' && isxdigit(sym[i + 1]) && isxdigit(sym[i + 2])) { 57 /* "$xx" is a hex-encoded character */ 58 result[j++] = (hex(sym[i + 1]) << 4) | hex(sym[i + 2]); 59 i += 3; 60 } 61 else { 62 result[j++] = sym[i++]; 63 } 64 } 65 result[j] = '\0'; 66 67 return result; 68}