1 /* Marshalling and unmarshalling.
2    Copyright (C) 2014-2018 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
unmarshall_check(connection * conn,unsigned long long check)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
marshall_intlike(connection * conn,unsigned long long val)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
unmarshall_intlike(connection * conn,unsigned long long * result)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
marshall(connection * conn,const char * str)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
unmarshall(connection * conn,char ** result)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
marshall_array_start(connection * conn,char id,size_t n_elements)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
marshall_array_elmts(connection * conn,size_t n_bytes,void * elements)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
unmarshall_array_start(connection * conn,char id,size_t * n_elements)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
unmarshall_array_elmts(connection * conn,size_t n_bytes,void * elements)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
marshall(connection * conn,const gcc_type_array * a)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
unmarshall(connection * conn,gcc_type_array ** result)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