1 /* Marshalling and unmarshalling. 2 Copyright (C) 2014-2020 Free Software Foundation, Inc. 3 4 This file is part of GCC. 5 6 GCC is free software; you can redistribute it and/or modify it under 7 the terms of the GNU General Public License as published by the Free 8 Software Foundation; either version 3, or (at your option) any later 9 version. 10 11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 12 WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GCC; see the file COPYING3. If not see 18 <http://www.gnu.org/licenses/>. */ 19 20 #include <cc1plugin-config.h> 21 #include <new> 22 #include <string.h> 23 #include "marshall.hh" 24 #include "connection.hh" 25 26 cc1_plugin::status 27 cc1_plugin::unmarshall_check (connection *conn, unsigned long long check) 28 { 29 unsigned long long r; 30 31 if (!unmarshall (conn, &r)) 32 return FAIL; 33 return check == r ? OK : FAIL; 34 } 35 36 cc1_plugin::status 37 cc1_plugin::marshall_intlike (connection *conn, unsigned long long val) 38 { 39 if (!conn->send ('i')) 40 return FAIL; 41 return conn->send (&val, sizeof (val)); 42 } 43 44 cc1_plugin::status 45 cc1_plugin::unmarshall_intlike (connection *conn, unsigned long long *result) 46 { 47 if (!conn->require ('i')) 48 return FAIL; 49 return conn->get (result, sizeof (*result)); 50 } 51 52 cc1_plugin::status 53 cc1_plugin::marshall (connection *conn, const char *str) 54 { 55 if (!conn->send ('s')) 56 return FAIL; 57 58 unsigned long long len = str == NULL ? -1ULL : strlen (str); 59 if (!conn->send (&len, sizeof (len))) 60 return FAIL; 61 62 if (str == NULL) 63 return OK; 64 65 return conn->send (str, len); 66 } 67 68 cc1_plugin::status 69 cc1_plugin::unmarshall (connection *conn, char **result) 70 { 71 unsigned long long len; 72 73 if (!conn->require ('s')) 74 return FAIL; 75 if (!conn->get (&len, sizeof (len))) 76 return FAIL; 77 78 if (len == -1ULL) 79 { 80 *result = NULL; 81 return OK; 82 } 83 84 char *str = new (std::nothrow) char[len + 1]; 85 if (str == NULL) 86 return FAIL; 87 88 if (!conn->get (str, len)) 89 { 90 delete[] str; 91 return FAIL; 92 } 93 94 str[len] = '\0'; 95 *result = str; 96 97 return OK; 98 } 99 100 cc1_plugin::status 101 cc1_plugin::marshall_array_start (connection *conn, char id, 102 size_t n_elements) 103 { 104 if (!conn->send (id)) 105 return FAIL; 106 107 unsigned long long r = n_elements; 108 if (!conn->send (&r, sizeof (r))) 109 return FAIL; 110 111 return OK; 112 } 113 114 cc1_plugin::status 115 cc1_plugin::marshall_array_elmts (connection *conn, size_t n_bytes, 116 void *elements) 117 { 118 return conn->send (elements, n_bytes); 119 } 120 121 cc1_plugin::status 122 cc1_plugin::unmarshall_array_start (connection *conn, char id, 123 size_t *n_elements) 124 { 125 unsigned long long len; 126 127 if (!conn->require (id)) 128 return FAIL; 129 if (!conn->get (&len, sizeof (len))) 130 return FAIL; 131 132 *n_elements = len; 133 134 return OK; 135 } 136 137 cc1_plugin::status 138 cc1_plugin::unmarshall_array_elmts (connection *conn, size_t n_bytes, 139 void *elements) 140 { 141 return conn->get (elements, n_bytes); 142 } 143 144 cc1_plugin::status 145 cc1_plugin::marshall (connection *conn, const gcc_type_array *a) 146 { 147 size_t len; 148 149 if (a) 150 len = a->n_elements; 151 else 152 len = (size_t)-1; 153 154 if (!marshall_array_start (conn, 'a', len)) 155 return FAIL; 156 157 if (!a) 158 return OK; 159 160 return marshall_array_elmts (conn, len * sizeof (a->elements[0]), 161 a->elements); 162 } 163 164 cc1_plugin::status 165 cc1_plugin::unmarshall (connection *conn, gcc_type_array **result) 166 { 167 size_t len; 168 169 if (!unmarshall_array_start (conn, 'a', &len)) 170 return FAIL; 171 172 if (len == (size_t)-1) 173 { 174 *result = NULL; 175 return OK; 176 } 177 178 gcc_type_array *gta = new gcc_type_array; 179 180 gta->n_elements = len; 181 gta->elements = new gcc_type[len]; 182 183 if (!unmarshall_array_elmts (conn, 184 len * sizeof (gta->elements[0]), 185 gta->elements)) 186 { 187 delete[] gta->elements; 188 delete *result; 189 return FAIL; 190 } 191 192 *result = gta; 193 194 return OK; 195 } 196