xref: /netbsd-src/external/gpl3/gcc/dist/libcc1/marshall.cc (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1 /* Marshalling and unmarshalling.
2    Copyright (C) 2014-2022 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 #include "rpc.hh"
26 
27 cc1_plugin::status
unmarshall_check(connection * conn,unsigned long long check)28 cc1_plugin::unmarshall_check (connection *conn, unsigned long long check)
29 {
30   unsigned long long r;
31 
32   if (!unmarshall (conn, &r))
33     return FAIL;
34   return check == r ? OK : FAIL;
35 }
36 
37 cc1_plugin::status
marshall_intlike(connection * conn,unsigned long long val)38 cc1_plugin::marshall_intlike (connection *conn, unsigned long long val)
39 {
40   if (!conn->send ('i'))
41     return FAIL;
42   return conn->send (&val, sizeof (val));
43 }
44 
45 cc1_plugin::status
unmarshall_intlike(connection * conn,unsigned long long * result)46 cc1_plugin::unmarshall_intlike (connection *conn, unsigned long long *result)
47 {
48   if (!conn->require ('i'))
49     return FAIL;
50   return conn->get (result, sizeof (*result));
51 }
52 
53 cc1_plugin::status
marshall(connection * conn,const char * str)54 cc1_plugin::marshall (connection *conn, const char *str)
55 {
56   if (!conn->send ('s'))
57     return FAIL;
58 
59   unsigned long long len = str == NULL ? -1ULL : strlen (str);
60   if (!conn->send (&len, sizeof (len)))
61     return FAIL;
62 
63   if (str == NULL)
64     return OK;
65 
66   return conn->send (str, len);
67 }
68 
69 cc1_plugin::status
unmarshall(connection * conn,char ** result)70 cc1_plugin::unmarshall (connection *conn, char **result)
71 {
72   unsigned long long len;
73 
74   if (!conn->require ('s'))
75     return FAIL;
76   if (!conn->get (&len, sizeof (len)))
77     return FAIL;
78 
79   if (len == -1ULL)
80     {
81       *result = NULL;
82       return OK;
83     }
84 
85   char *str = new (std::nothrow) char[len + 1];
86   if (str == NULL)
87     return FAIL;
88 
89   if (!conn->get (str, len))
90     {
91       delete[] str;
92       return FAIL;
93     }
94 
95   str[len] = '\0';
96   *result = str;
97 
98   return OK;
99 }
100 
101 cc1_plugin::status
marshall_array_start(connection * conn,char id,size_t n_elements)102 cc1_plugin::marshall_array_start (connection *conn, char id,
103 				  size_t n_elements)
104 {
105   if (!conn->send (id))
106     return FAIL;
107 
108   unsigned long long r = n_elements;
109   if (!conn->send (&r, sizeof (r)))
110     return FAIL;
111 
112   return OK;
113 }
114 
115 cc1_plugin::status
marshall_array_elmts(connection * conn,size_t n_bytes,void * elements)116 cc1_plugin::marshall_array_elmts (connection *conn, size_t n_bytes,
117 				  void *elements)
118 {
119   return conn->send (elements, n_bytes);
120 }
121 
122 cc1_plugin::status
unmarshall_array_start(connection * conn,char id,size_t * n_elements)123 cc1_plugin::unmarshall_array_start (connection *conn, char id,
124 				    size_t *n_elements)
125 {
126   unsigned long long len;
127 
128   if (!conn->require (id))
129     return FAIL;
130   if (!conn->get (&len, sizeof (len)))
131     return FAIL;
132 
133   *n_elements = len;
134 
135   return OK;
136 }
137 
138 cc1_plugin::status
unmarshall_array_elmts(connection * conn,size_t n_bytes,void * elements)139 cc1_plugin::unmarshall_array_elmts (connection *conn, size_t n_bytes,
140 				    void *elements)
141 {
142   return conn->get (elements, n_bytes);
143 }
144 
145 cc1_plugin::status
marshall(connection * conn,const gcc_type_array * a)146 cc1_plugin::marshall (connection *conn, const gcc_type_array *a)
147 {
148   size_t len;
149 
150   if (a)
151     len = a->n_elements;
152   else
153     len = (size_t)-1;
154 
155   if (!marshall_array_start (conn, 'a', len))
156     return FAIL;
157 
158   if (!a)
159     return OK;
160 
161   return marshall_array_elmts (conn, len * sizeof (a->elements[0]),
162 			       a->elements);
163 }
164 
165 cc1_plugin::status
unmarshall(connection * conn,gcc_type_array ** result)166 cc1_plugin::unmarshall (connection *conn, gcc_type_array **result)
167 {
168   size_t len;
169 
170   if (!unmarshall_array_start (conn, 'a', &len))
171     return FAIL;
172 
173   if (len == (size_t)-1)
174     {
175       *result = NULL;
176       return OK;
177     }
178 
179   cc1_plugin::unique_ptr<gcc_type_array> gta (new gcc_type_array {});
180 
181   gta->n_elements = len;
182   gta->elements = new gcc_type[len];
183 
184   if (!unmarshall_array_elmts (conn,
185 			       len * sizeof (gta->elements[0]),
186 			       gta->elements))
187     return FAIL;
188 
189   *result = gta.release ();
190 
191   return OK;
192 }
193