L4Re/idl4re

Annotated interface.c

216:c24e354011ac
23 months ago Paul Boddie Updated the roadmap, removing issues that are now resolved by the introduction of interface composition syntax and multiple input file processing.
paul@113 1
/*
paul@113 2
 * Generation of interface headers.
paul@113 3
 *
paul@214 4
 * Copyright (C) 2019, 2022 Paul Boddie <paul@boddie.org.uk>
paul@113 5
 *
paul@113 6
 * This program is free software; you can redistribute it and/or
paul@113 7
 * modify it under the terms of the GNU General Public License as
paul@113 8
 * published by the Free Software Foundation; either version 2 of
paul@113 9
 * the License, or (at your option) any later version.
paul@113 10
 *
paul@113 11
 * This program is distributed in the hope that it will be useful,
paul@113 12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
paul@113 13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
paul@113 14
 * GNU General Public License for more details.
paul@113 15
 *
paul@113 16
 * You should have received a copy of the GNU General Public License
paul@113 17
 * along with this program; if not, write to the Free Software
paul@113 18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
paul@113 19
 * Boston, MA  02110-1301, USA
paul@113 20
 */
paul@113 21
paul@115 22
#include <stdlib.h>
paul@214 23
#include <string.h>
paul@113 24
#include "client.h"
paul@113 25
#include "common.h"
paul@126 26
#include "config.h"
paul@113 27
#include "declaration.h"
paul@113 28
#include "includes.h"
paul@113 29
#include "interface.h"
paul@113 30
#include "server.h"
paul@120 31
#include "structure.h"
paul@113 32
#include "templates.h"
paul@113 33
paul@113 34
paul@113 35
paul@214 36
/* Emit compound interface includes. */
paul@214 37
paul@214 38
static void write_compound_includes(FILE *fp, struct interface *iface)
paul@214 39
{
paul@214 40
  struct interface_ref *base;
paul@214 41
paul@214 42
  for (base = iface->bases; base != NULL; base = base->tail)
paul@214 43
  {
paul@214 44
    /* Only output includes where the base resides in a different file. */
paul@214 45
paul@214 46
    if (strcmp(iface->output_basename, base->iface->output_basename))
paul@214 47
      fprintf(fp, compound_interface_include, base->iface->output_basename);
paul@214 48
  }
paul@214 49
}
paul@214 50
paul@214 51
/* Write the reference type members. */
paul@214 52
paul@214 53
static void write_reference_type_members(FILE *fp, struct interface_ref *base)
paul@214 54
{
paul@214 55
  if (base == NULL)
paul@214 56
    return;
paul@214 57
paul@214 58
  /* Reverse the list by processing subsequent members first. */
paul@214 59
paul@214 60
  write_reference_type_members(fp, base->tail);
paul@214 61
paul@214 62
  fprintf(fp, compound_ref_type_definition_member_c,
paul@214 63
          base->name, base->name);
paul@214 64
}
paul@214 65
    
paul@214 66
/* Generate a reference type for C language interfaces. */
paul@214 67
paul@214 68
static void write_reference_type(FILE *fp, struct interface *iface)
paul@214 69
{
paul@214 70
  struct interface *i;
paul@214 71
paul@214 72
  if (is_compound_interface(iface))
paul@214 73
  { 
paul@214 74
    fprintf(fp, compound_ref_type_definition_prologue_c, L4_CAP_TYPE);
paul@214 75
paul@214 76
    write_reference_type_members(fp, iface->bases);
paul@214 77
paul@214 78
    fprintf(fp, compound_ref_type_definition_epilogue_c,
paul@214 79
            iface->name);
paul@214 80
  }
paul@214 81
  else
paul@214 82
    fprintf(fp, ref_type_definition_c, L4_CAP_TYPE, iface->name);
paul@214 83
}
paul@214 84
paul@214 85
/* Augment compound interface class declarations. */
paul@214 86
paul@214 87
static void write_compound_interface_bases_c(FILE *fp, struct interface *iface)
paul@214 88
{
paul@214 89
  struct interface_ref *base;
paul@214 90
paul@214 91
  for (base = iface->bases; base != NULL; base = base->tail)
paul@214 92
    fprintf(fp, interface_body_base_c, base->name, base->name);
paul@214 93
}
paul@214 94
paul@214 95
/* Augment compound interface type declarations. */
paul@214 96
paul@214 97
static void write_compound_interface_bases_cpp(FILE *fp, struct interface *iface)
paul@214 98
{
paul@214 99
  struct interface_ref *base;
paul@214 100
  int first;
paul@214 101
paul@214 102
  for (base = iface->bases, first = 1; base != NULL; base = base->tail, first = 0)
paul@214 103
    fprintf(fp, interface_prologue_base_cpp, first ? " : " : ", ", base->name);
paul@214 104
}
paul@214 105
paul@214 106
paul@214 107
paul@113 108
/* Write the definition of an interface to the given file for use by client or
paul@113 109
   server components. Client headers employ such definitions as do server
paul@113 110
   interface headers, whereas server wrapper headers employ other descriptions
paul@113 111
   of their operations. */
paul@113 112
paul@113 113
void write_interface_definition(struct interface *iface,
paul@113 114
                                enum component_role component, FILE *fp)
paul@113 115
{
paul@126 116
  int cpp = (conf.language == CPP_LANGUAGE);
paul@114 117
  int client = (component == CLIENT_ROLE);
paul@214 118
  int input_items = get_max_input_items(iface);
paul@115 119
  char *class_name = get_interface_class_name(iface, component);
paul@117 120
  char *name = iface->name;
paul@113 121
paul@113 122
  /* Emit include statements. */
paul@113 123
paul@113 124
  write_includes_separator(iface->includes, fp);
paul@113 125
  write_includes(iface->includes, fp);
paul@214 126
  write_compound_includes(fp, iface);
paul@113 127
paul@120 128
  /* Generate interface abstractions. */
paul@120 129
paul@117 130
  if (!cpp)
paul@115 131
  {
paul@117 132
    /* Define an object reference type for C. */
paul@115 133
paul@117 134
    if (!client)
paul@214 135
      write_reference_type(fp, iface);
paul@115 136
paul@117 137
    /* Define C client signatures representing the client functions. */
paul@115 138
paul@117 139
    else
paul@117 140
      write_signatures(iface->signatures, DECLARATION_ROLE,
paul@117 141
                       fp, iface, write_client_signature);
paul@115 142
  }
paul@113 143
paul@117 144
  /* Begin any namespace, defining the class or type.
paul@117 145
     C++ code employs an abstract server interface and a concrete client
paul@117 146
     interface class.
paul@117 147
     C code only employs a server interface which is instantiated for client
paul@117 148
     use elsewhere by employing the client functions. */
paul@117 149
paul@117 150
  if (cpp || !client)
paul@117 151
  {
paul@117 152
    if (cpp)
paul@117 153
    {
paul@117 154
      fprintf(fp, interface_prologue_cpp, class_name);
paul@116 155
paul@117 156
      /* Inherit from the actual interface in the client. */
paul@116 157
paul@117 158
      if (client)
paul@117 159
        fprintf(fp, client_interface_prologue_cpp, name);
paul@117 160
    }
paul@117 161
    else
paul@117 162
      fputs(interface_prologue_c, fp);
paul@117 163
paul@214 164
    /* Augment the interface declaration with base interfaces for compound
paul@214 165
       interfaces. */
paul@214 166
paul@214 167
    if (!client && cpp && is_compound_interface(iface))
paul@214 168
      write_compound_interface_bases_cpp(fp, iface);
paul@214 169
paul@117 170
    /* Start the class or type body. */
paul@117 171
paul@121 172
    fputs(interface_body_begin, fp);
paul@117 173
paul@214 174
    /* Augment the interface declaration with base interfaces for compound
paul@214 175
       interfaces. */
paul@214 176
paul@214 177
    if (!client && !cpp && is_compound_interface(iface))
paul@214 178
      write_compound_interface_bases_c(fp, iface);
paul@214 179
paul@117 180
    /* Define any state and initialisation details of a class. */
paul@113 181
paul@117 182
    if (cpp)
paul@117 183
    {
paul@117 184
      if (client)
paul@117 185
        fprintf(fp, client_interface_endpoint_declaration_cpp, L4_CAP_TYPE);
paul@117 186
paul@214 187
      if (iface->signatures != NULL)
paul@214 188
        fputs(interface_signatures_prologue_cpp, fp);
paul@117 189
paul@117 190
      /* Define a constructor. */
paul@117 191
paul@117 192
      if (client)
paul@117 193
        fprintf(fp, client_interface_constructor_cpp, class_name, L4_CAP_TYPE);
paul@117 194
    }
paul@114 195
paul@117 196
    /* Emit signatures. */
paul@117 197
paul@117 198
    write_signatures(iface->signatures, MEMBER_DECLARATION_ROLE,
paul@117 199
                     fp, iface,
paul@117 200
                     client ? write_client_signature
paul@117 201
                            : write_server_interface_signature);
paul@113 202
paul@117 203
    /* Terminate the class or type body. */
paul@117 204
paul@117 205
    if (cpp)
paul@117 206
      fputs(interface_epilogue_cpp, fp);
paul@117 207
    else
paul@117 208
      fprintf(fp, interface_epilogue_c, name);
paul@117 209
  }
paul@113 210
paul@115 211
  /* Define the maximum number of expected items for the interface. */
paul@115 212
paul@115 213
  if (!client)
paul@117 214
    fprintf(fp, expected_items_definition, name, input_items);
paul@117 215
paul@117 216
  /* Define an object type for C and declare a client interface. */
paul@117 217
paul@117 218
  if (!cpp && !client)
paul@117 219
    fprintf(fp, object_type_definition_c, name, name, name);
paul@117 220
paul@117 221
  if (!cpp && client)
paul@117 222
    fprintf(fp, client_interface_declaration_c, name, name);
paul@115 223
paul@120 224
  /* Emit opcodes and message access structures with the generic server
paul@120 225
     interface, these being common to both client and server. */
paul@120 226
paul@214 227
  if (!client && (iface->signatures != NULL))
paul@120 228
  {
paul@120 229
    write_opcode_definition(iface, fp);
paul@120 230
    write_structures(iface->signatures, fp, iface);
paul@120 231
  }
paul@120 232
paul@162 233
  /* Emit a conversion macro for compound interface dispatch. */
paul@162 234
paul@169 235
  if (!client)
paul@169 236
  {
paul@169 237
    if (cpp)
paul@169 238
      fprintf(fp, compound_interface_conversion_cpp, name);
paul@169 239
    else
paul@169 240
      fprintf(fp, compound_interface_conversion_c, name, name, name, name);
paul@169 241
  }
paul@162 242
paul@115 243
  free(class_name);
paul@113 244
}