Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <string.h>
0003 #include <stdlib.h>
0004 #include "util/string2.h"
0005 
0006 #include "demangle-ocaml.h"
0007 
0008 #include <linux/ctype.h>
0009 
0010 static const char *caml_prefix = "caml";
0011 static const size_t caml_prefix_len = 4;
0012 
0013 /* mangled OCaml symbols start with "caml" followed by an upper-case letter */
0014 static bool
0015 ocaml_is_mangled(const char *sym)
0016 {
0017     return 0 == strncmp(sym, caml_prefix, caml_prefix_len)
0018         && isupper(sym[caml_prefix_len]);
0019 }
0020 
0021 /*
0022  * input:
0023  *     sym: a symbol which may have been mangled by the OCaml compiler
0024  * return:
0025  *     if the input doesn't look like a mangled OCaml symbol, NULL is returned
0026  *     otherwise, a newly allocated string containing the demangled symbol is returned
0027  */
0028 char *
0029 ocaml_demangle_sym(const char *sym)
0030 {
0031     char *result;
0032     int j = 0;
0033     int i;
0034     int len;
0035 
0036     if (!ocaml_is_mangled(sym)) {
0037         return NULL;
0038     }
0039 
0040     len = strlen(sym);
0041 
0042     /* the demangled symbol is always smaller than the mangled symbol */
0043     result = malloc(len + 1);
0044     if (!result)
0045         return NULL;
0046 
0047     /* skip "caml" prefix */
0048     i = caml_prefix_len;
0049 
0050     while (i < len) {
0051         if (sym[i] == '_' && sym[i + 1] == '_') {
0052             /* "__" -> "." */
0053             result[j++] = '.';
0054             i += 2;
0055         }
0056         else if (sym[i] == '$' && isxdigit(sym[i + 1]) && isxdigit(sym[i + 2])) {
0057             /* "$xx" is a hex-encoded character */
0058             result[j++] = (hex(sym[i + 1]) << 4) | hex(sym[i + 2]);
0059             i += 3;
0060         }
0061         else {
0062             result[j++] = sym[i++];
0063         }
0064     }
0065     result[j] = '\0';
0066 
0067     return result;
0068 }