1 /* 2 * Client code generation. 3 * 4 * Copyright (C) 2019 Paul Boddie <paul@boddie.org.uk> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA 20 */ 21 22 #include <stdlib.h> 23 #include "client.h" 24 #include "common.h" 25 #include "declaration.h" 26 #include "message.h" 27 #include "templates.h" 28 29 30 31 /* Generate operation signature details for client use. */ 32 33 void write_client_signature(struct signature *sig, const char *following, 34 FILE *fp, struct interface *iface) 35 { 36 char *opname = get_operation_name(iface, sig); 37 38 /* Introduce an initial parameter for the endpoint. */ 39 40 fprintf(fp, client_function_signature_prologue, opname, L4_CAP_TYPE); 41 42 /* Write the remaining parameters. */ 43 44 write_parameter_separator(sig->parameters, fp); 45 write_parameters(sig->parameters, fp, SIGNATURE_ROLE); 46 47 /* End the signature and write any following text. */ 48 49 fputs(")", fp); 50 fputs(following, fp); 51 52 free(opname); 53 } 54 55 /* Generate function source code for each operation signature. */ 56 57 void write_client_function(struct signature *sig, FILE *fp, struct interface *iface) 58 { 59 write_client_signature(sig, BEGIN_FUNCTION, fp, iface); 60 write_client_function_body(sig->parameters, fp, iface, sig); 61 fputs("}\n", fp); 62 } 63 64 /* Generate a function body corresponding to an operation for client use. */ 65 66 void write_client_function_body(struct parameter *param, FILE *fp, 67 struct interface *iface, struct signature *sig) 68 { 69 int input_words, input_items, output_words, output_items; 70 71 /* With a protocol attribute, the opcode is the attribute value. Otherwise, 72 it is the operation code. */ 73 74 char *opname = get_operation_name(iface, sig), 75 *protocol = get_protocol(iface->attributes), 76 *opcode = get_opcode_identifier(protocol, opname); 77 78 /* Generate the prologue. */ 79 80 fputs(client_function_body_prologue, fp); 81 82 /* Count the number of input words, items and output words. */ 83 84 count_parameters(param, &input_words, &input_items, &output_words, &output_items); 85 86 /* Adjust the input words where a protocol is used as the opcode. */ 87 88 if (protocol != NULL) 89 input_words++; 90 91 /* Generate types parameterised with the qualified operation name. */ 92 93 write_accessor_declaration(input_words, output_words, opname, fp); 94 95 /* Initialise the message. */ 96 97 fprintf(fp, "\n ipc_message_new(&msg);\n"); 98 99 /* Generate expected output item requirements. */ 100 101 if (output_items) 102 fprintf(fp, " err = ipc_message_expect(&msg, %d);\n" 103 " if (err)\n" 104 " return err;\n", output_items); 105 106 /* Populate input parameters in the message. Dereference function parameters 107 acting as "inout" parameters. */ 108 109 if (input_words) 110 { 111 /* Reserve space for the words before any items, obtaining a pointer to the 112 words. */ 113 114 write_accessor_initialisation(IN_PARAMETER, CLIENT_ROLE, opname, fp); 115 116 if (protocol != NULL) 117 fprintf(fp, " in_words->_op = %s;\n", opname); 118 119 write_message_access(param, CLIENT_ROLE, IN_PARAMETER, WORD_CLASS, fp); 120 } 121 122 /* Do the same for items. */ 123 124 if (input_items) 125 { 126 fputs("\n", fp); 127 write_message_access(param, CLIENT_ROLE, IN_PARAMETER, ITEM_CLASS, fp); 128 } 129 130 /* Send the request. */ 131 132 fprintf(fp, client_function_body_call, opcode); 133 134 /* Retrieve output parameters from the message. */ 135 136 if (output_words) 137 { 138 write_accessor_initialisation(OUT_PARAMETER, CLIENT_ROLE, opname, fp); 139 write_message_access(param, CLIENT_ROLE, OUT_PARAMETER, WORD_CLASS, fp); 140 } 141 142 /* Do the same for items. */ 143 144 if (output_items) 145 { 146 fputs("\n", fp); 147 write_message_access(param, CLIENT_ROLE, OUT_PARAMETER, ITEM_CLASS, fp); 148 } 149 150 /* Return success. */ 151 152 fprintf(fp, "\n return L4_EOK;\n"); 153 154 /* Free allocated strings. */ 155 156 free(opname); 157 158 if (protocol == NULL) 159 free(opcode); 160 }