paul@100 | 1 | /* |
paul@100 | 2 | * Generation of declaration elements such as parameters and members. |
paul@100 | 3 | * |
paul@100 | 4 | * Copyright (C) 2019 Paul Boddie <paul@boddie.org.uk> |
paul@100 | 5 | * |
paul@100 | 6 | * This program is free software; you can redistribute it and/or |
paul@100 | 7 | * modify it under the terms of the GNU General Public License as |
paul@100 | 8 | * published by the Free Software Foundation; either version 2 of |
paul@100 | 9 | * the License, or (at your option) any later version. |
paul@100 | 10 | * |
paul@100 | 11 | * This program is distributed in the hope that it will be useful, |
paul@100 | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
paul@100 | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
paul@100 | 14 | * GNU General Public License for more details. |
paul@100 | 15 | * |
paul@100 | 16 | * You should have received a copy of the GNU General Public License |
paul@100 | 17 | * along with this program; if not, write to the Free Software |
paul@100 | 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, |
paul@100 | 19 | * Boston, MA 02110-1301, USA |
paul@100 | 20 | */ |
paul@100 | 21 | |
paul@110 | 22 | #include <stdlib.h> |
paul@110 | 23 | #include "common.h" |
paul@126 | 24 | #include "config.h" |
paul@100 | 25 | #include "declaration.h" |
paul@116 | 26 | #include "templates.h" |
paul@100 | 27 | |
paul@110 | 28 | |
paul@110 | 29 | |
paul@110 | 30 | /* Generate each operation signature for use in defining an interface. */ |
paul@110 | 31 | |
paul@110 | 32 | void write_interface_signature(struct signature *sig, enum signature_role role, |
paul@186 | 33 | enum component_role component, |
paul@186 | 34 | enum function_role function, FILE *fp, |
paul@110 | 35 | struct interface *iface) |
paul@110 | 36 | { |
paul@126 | 37 | int cpp = (conf.language == CPP_LANGUAGE); |
paul@126 | 38 | int have_init_param = (conf.language == C_LANGUAGE); |
paul@117 | 39 | int declaration = (role & DECLARATION_ROLE); |
paul@117 | 40 | int member = (role & MEMBER_ROLE); |
paul@114 | 41 | int server = (component == SERVER_ROLE); |
paul@186 | 42 | |
paul@186 | 43 | /* Explicit completion functions only employ input/inout parameters. */ |
paul@186 | 44 | |
paul@186 | 45 | int completion = (function == COMPLETION_ROLE); |
paul@186 | 46 | enum specifier direction = completion ? IN_PARAMETER : ANY_PARAMETER; |
paul@110 | 47 | |
paul@110 | 48 | /* Indent and provide a qualifier for C++ class declarations. */ |
paul@110 | 49 | |
paul@117 | 50 | char *qualifier = (cpp && declaration) ? " virtual " : member ? " " : ""; |
paul@110 | 51 | |
paul@110 | 52 | /* Structure the function name appropriately. */ |
paul@110 | 53 | |
paul@115 | 54 | char *opname = get_signature_operation_name(iface, sig, component, role, |
paul@126 | 55 | conf.language); |
paul@110 | 56 | |
paul@110 | 57 | /* Introduce an initial parameter for the component state. */ |
paul@110 | 58 | |
paul@117 | 59 | if (!cpp && member) |
paul@117 | 60 | fprintf(fp, interface_struct_member_function_signature_prologue, opname); |
paul@117 | 61 | else |
paul@117 | 62 | fprintf(fp, interface_function_signature_prologue, qualifier, opname); |
paul@116 | 63 | |
paul@116 | 64 | if (have_init_param) |
paul@117 | 65 | write_initial_parameter(iface->name, fp); |
paul@110 | 66 | |
paul@110 | 67 | /* Emit the parameters. */ |
paul@110 | 68 | |
paul@139 | 69 | write_parameters(sig->parameters, fp, SIGNATURE_ROLE, function, direction, |
paul@129 | 70 | have_init_param); |
paul@110 | 71 | |
paul@110 | 72 | fputs(")", fp); |
paul@110 | 73 | |
paul@139 | 74 | /* Add a body for the function, this being used to define unimplemented |
paul@114 | 75 | methods in C++. The client has method definitions and therefore normal |
paul@114 | 76 | virtual methods. */ |
paul@110 | 77 | |
paul@114 | 78 | if (cpp && declaration && server) |
paul@139 | 79 | write_interface_unimplemented_method(sig, direction, fp); |
paul@139 | 80 | else |
paul@139 | 81 | fputs(get_signature_terminator(role), fp); |
paul@110 | 82 | |
paul@110 | 83 | free(opname); |
paul@110 | 84 | } |
paul@110 | 85 | |
paul@139 | 86 | /* Write an unimplemented member function body for a C++ interface. */ |
paul@139 | 87 | |
paul@139 | 88 | void write_interface_unimplemented_method(struct signature *sig, |
paul@139 | 89 | enum specifier direction, FILE *fp) |
paul@139 | 90 | { |
paul@139 | 91 | struct parameter *param; |
paul@139 | 92 | |
paul@139 | 93 | fputs(interface_unimplemented_method_prologue_cpp, fp); |
paul@139 | 94 | |
paul@139 | 95 | for (param = sig->parameters; param != NULL; param = param->tail) |
paul@139 | 96 | { |
paul@139 | 97 | if (param->specifier & direction) |
paul@139 | 98 | fprintf(fp, interface_unused_parameter, get_parameter_name(param->identifiers)); |
paul@139 | 99 | } |
paul@139 | 100 | |
paul@139 | 101 | fputs(interface_unimplemented_method_epilogue_cpp, fp); |
paul@139 | 102 | } |
paul@139 | 103 | |
paul@117 | 104 | /* Write the initial parameter in an interface signature. */ |
paul@117 | 105 | |
paul@117 | 106 | void write_initial_parameter(const char *name, FILE *fp) |
paul@117 | 107 | { |
paul@126 | 108 | if (conf.language == CPP_LANGUAGE) |
paul@117 | 109 | fprintf(fp, "%s *_self", name); |
paul@117 | 110 | else |
paul@117 | 111 | fprintf(fp, "ref_%s _self", name); |
paul@117 | 112 | } |
paul@117 | 113 | |
paul@113 | 114 | /* Generate signatures. */ |
paul@113 | 115 | |
paul@117 | 116 | void write_signatures(struct signature *sig, enum signature_role role, FILE *fp, |
paul@117 | 117 | struct interface *iface, |
paul@113 | 118 | void (*write_signature)(struct signature *, |
paul@113 | 119 | enum signature_role role, |
paul@113 | 120 | FILE *, struct interface *)) |
paul@113 | 121 | { |
paul@113 | 122 | if (sig == NULL) |
paul@113 | 123 | return; |
paul@113 | 124 | |
paul@117 | 125 | write_signature(sig, role, fp, iface); |
paul@117 | 126 | write_signatures(sig->tail, role, fp, iface, write_signature); |
paul@113 | 127 | } |
paul@113 | 128 | |
paul@113 | 129 | |
paul@113 | 130 | |
paul@100 | 131 | /* Generate parameters in each function signature. */ |
paul@100 | 132 | |
paul@125 | 133 | void write_parameters(struct parameter *param, FILE *fp, enum parameter_role role, |
paul@139 | 134 | enum function_role function, enum specifier direction, |
paul@129 | 135 | int continuing) |
paul@100 | 136 | { |
paul@125 | 137 | for (; param != NULL; param = param->tail) |
paul@125 | 138 | { |
paul@139 | 139 | if (param->specifier & direction) |
paul@125 | 140 | { |
paul@125 | 141 | if (continuing) |
paul@125 | 142 | fputs(", ", fp); |
paul@125 | 143 | else |
paul@125 | 144 | continuing = 1; |
paul@100 | 145 | |
paul@129 | 146 | write_parameter(param, fp, role, function); |
paul@125 | 147 | } |
paul@125 | 148 | } |
paul@100 | 149 | } |
paul@100 | 150 | |
paul@125 | 151 | /* Generate a parameter in a signature or invocation. */ |
paul@100 | 152 | |
paul@129 | 153 | void write_parameter(struct parameter *param, FILE *fp, |
paul@129 | 154 | enum parameter_role role, enum function_role function) |
paul@100 | 155 | { |
paul@100 | 156 | struct identifier *ident = param->identifiers; |
paul@100 | 157 | char *type; |
paul@125 | 158 | int invocation = (role == INVOCATION_ROLE); |
paul@100 | 159 | int first = 1; |
paul@100 | 160 | |
paul@100 | 161 | while (ident != NULL) |
paul@100 | 162 | { |
paul@125 | 163 | /* Put spaces between each type identifier. */ |
paul@100 | 164 | |
paul@125 | 165 | if (!invocation) |
paul@125 | 166 | { |
paul@125 | 167 | if (first) |
paul@125 | 168 | first = 0; |
paul@125 | 169 | else |
paul@125 | 170 | fputs(" ", fp); |
paul@125 | 171 | } |
paul@125 | 172 | |
paul@125 | 173 | /* Emit type identifiers for signatures. */ |
paul@100 | 174 | |
paul@100 | 175 | if (ident->tail != NULL) |
paul@125 | 176 | { |
paul@125 | 177 | if (!invocation) |
paul@125 | 178 | fputs(ident->identifier, fp); |
paul@125 | 179 | } |
paul@100 | 180 | |
paul@100 | 181 | /* Emit the parameter name. */ |
paul@100 | 182 | |
paul@100 | 183 | else |
paul@100 | 184 | { |
paul@100 | 185 | /* Items must have their type identifiers restored. */ |
paul@100 | 186 | |
paul@125 | 187 | if ((param->cls & ITEM_CLASS) && !invocation) |
paul@100 | 188 | { |
paul@100 | 189 | type = param->cls == FPAGE_ITEM ? L4_FPAGE_TYPE : L4_CAP_TYPE; |
paul@100 | 190 | fputs(type, fp); |
paul@100 | 191 | fputs(" ", fp); |
paul@100 | 192 | } |
paul@100 | 193 | |
paul@125 | 194 | /* Emit the decoration and parameter name. */ |
paul@125 | 195 | |
paul@129 | 196 | fprintf(fp, "%s%s", get_parameter_decoration(param, role, function), |
paul@129 | 197 | ident->identifier); |
paul@100 | 198 | } |
paul@100 | 199 | |
paul@100 | 200 | ident = ident->tail; |
paul@100 | 201 | } |
paul@100 | 202 | } |
paul@100 | 203 | |
paul@100 | 204 | /* Write structure members for word data structures or variable declarations for |
paul@100 | 205 | parameters. */ |
paul@100 | 206 | |
paul@100 | 207 | void write_declarations(struct parameter *param, enum specifier direction, |
paul@100 | 208 | enum parameter_class cls, FILE *fp) |
paul@100 | 209 | { |
paul@100 | 210 | for (; param != NULL; param = param->tail) |
paul@100 | 211 | { |
paul@100 | 212 | if ((param->specifier & direction) && (param->cls & cls)) |
paul@100 | 213 | { |
paul@117 | 214 | fputs(INDENT_MEMBER, fp); |
paul@129 | 215 | write_parameter(param, fp, STRUCTURE_ROLE, GENERAL_FUNCTION_ROLE); |
paul@117 | 216 | fputs(COMPLETE_MEMBER, fp); |
paul@100 | 217 | } |
paul@100 | 218 | } |
paul@100 | 219 | } |