1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright 2017 Jason King
  14  */
  15 
  16 #include <string.h>
  17 #include <errno.h>
  18 #include "sysdemangle.h"
  19 #include "sysdemangle_int.h"
  20 
  21 
  22 static sysdem_lang_t
  23 detect_lang(const char *str)
  24 {
  25         size_t n = strlen(str);
  26 
  27         if (n < 3 || str[0] != '_')
  28                 return (SYSDEM_LANG_AUTO);
  29 
  30         switch (str[1]) {
  31         case 'Z':
  32                 return (SYSDEM_LANG_CPP);
  33 
  34         case '_':
  35                 break;
  36 
  37         default:
  38                 return (SYSDEM_LANG_AUTO);
  39         }
  40 
  41         /* why they use ___Z sometimes is puzzling.. *sigh* */
  42         if (str[2] == '_' && str[3] == 'Z')
  43                 return (SYSDEM_LANG_CPP);
  44 
  45         return (SYSDEM_LANG_AUTO);
  46 }
  47 
  48 char *
  49 sysdemangle(const char *str, sysdem_lang_t lang, sysdem_ops_t *ops)
  50 {
  51 
  52         if (ops == NULL)
  53                 ops = sysdem_ops_default;
  54 
  55         if (lang == SYSDEM_LANG_AUTO) {
  56                 lang = detect_lang(str);
  57                 if (lang == SYSDEM_LANG_AUTO) {
  58                         errno = ENOSYS;
  59                         return (NULL);
  60                 }
  61         }
  62 
  63         switch (lang) {
  64         case SYSDEM_LANG_CPP:
  65                 return (cpp_demangle(str, ops));
  66 
  67         default:
  68                 break;
  69         }
  70 
  71         /* XXX: better return value? */
  72         errno = ENOSYS;
  73         return (NULL);
  74 }