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 static void write_signature_end(FILE *fp) 32 { 33 fputs(";\n", fp); 34 } 35 36 /* Generate operation signature details for client use. */ 37 38 static void _write_client_signature(struct signature *sig, FILE *fp, struct interface *iface) 39 { 40 char *opname = get_operation_name(iface, sig); 41 42 /* NOTE: Qualifier discarded for now. */ 43 /* Introduce an initial parameter for the endpoint. */ 44 45 fprintf(fp, "\nlong %s(%s _endp", opname, L4_CAP_TYPE); 46 write_parameter_separator(sig->parameters, fp); 47 write_parameters(sig->parameters, fp, SIGNATURE_ROLE); 48 fputs(")", fp); 49 50 free(opname); 51 } 52 53 /* Generate each operation signature or "function prototype" for client use. */ 54 55 void write_client_signature(struct signature *sig, FILE *fp, struct interface *iface) 56 { 57 _write_client_signature(sig, fp, iface); 58 write_signature_end(fp); 59 } 60 61 /* Generate function source code for each operation signature. */ 62 63 void write_client_function(struct signature *sig, FILE *fp, struct interface *iface) 64 { 65 _write_client_signature(sig, fp, iface); 66 fputs("\n{\n", fp); 67 write_client_function_body(sig->parameters, fp, iface, sig); 68 fputs("}\n", fp); 69 } 70 71 /* Generate a function body corresponding to an operation for client use. */ 72 73 void write_client_function_body(struct parameter *param, FILE *fp, 74 struct interface *iface, struct signature *sig) 75 { 76 int input_words, input_items, output_words, output_items; 77 78 /* With a protocol attribute, the opcode is the attribute value. Otherwise, 79 it is the operation code. */ 80 81 char *opname = get_operation_name(iface, sig), 82 *protocol = get_protocol(iface->attributes), 83 *opcode = get_opcode_identifier(protocol, opname); 84 85 /* Generate the prologue. */ 86 87 fputs(client_function_body_prologue, fp); 88 89 /* Count the number of input words, items and output words. */ 90 91 count_parameters(param, &input_words, &input_items, &output_words, &output_items); 92 93 /* Adjust the input words where a protocol is used as the opcode. */ 94 95 if (protocol != NULL) 96 input_words++; 97 98 /* Generate types parameterised with the qualified operation name. */ 99 100 write_accessor_declaration(input_words, output_words, opname, fp); 101 102 /* Initialise the message. */ 103 104 fprintf(fp, "\n ipc_message_new(&msg);\n"); 105 106 /* Generate expected output item requirements. */ 107 108 if (output_items) 109 fprintf(fp, " err = ipc_message_expect(&msg, %d);\n" 110 " if (err)\n" 111 " return err;\n", output_items); 112 113 /* Populate input parameters in the message. Dereference function parameters 114 acting as "inout" parameters. */ 115 116 if (input_words) 117 { 118 /* Reserve space for the words before any items, obtaining a pointer to the 119 words. */ 120 121 write_accessor_initialisation(IN_PARAMETER, CLIENT_ROLE, opname, fp); 122 123 if (protocol != NULL) 124 fprintf(fp, " in_words->_op = %s;\n", opname); 125 126 write_message_access(param, CLIENT_ROLE, IN_PARAMETER, WORD_CLASS, fp); 127 } 128 129 /* Do the same for items. */ 130 131 if (input_items) 132 { 133 fputs("\n", fp); 134 write_message_access(param, CLIENT_ROLE, IN_PARAMETER, ITEM_CLASS, fp); 135 } 136 137 /* Send the request. */ 138 139 fprintf(fp, client_function_body_call, opcode); 140 141 /* Retrieve output parameters from the message. */ 142 143 if (output_words) 144 { 145 write_accessor_initialisation(OUT_PARAMETER, CLIENT_ROLE, opname, fp); 146 write_message_access(param, CLIENT_ROLE, OUT_PARAMETER, WORD_CLASS, fp); 147 } 148 149 /* Do the same for items. */ 150 151 if (output_items) 152 { 153 fputs("\n", fp); 154 write_message_access(param, CLIENT_ROLE, OUT_PARAMETER, ITEM_CLASS, fp); 155 } 156 157 /* Return success. */ 158 159 fprintf(fp, "\n return L4_EOK;\n"); 160 161 /* Free allocated strings. */ 162 163 free(opname); 164 165 if (protocol == NULL) 166 free(opcode); 167 }