<'
# Copyright (c) 2013-2014, 2024, 2026 LAAS/CNRS
# All rights reserved.
#
# Redistribution and use  in source  and binary  forms,  with or without
# modification, are permitted provided that the following conditions are
# met:
#
#   1. Redistributions of  source  code must retain the  above copyright
#      notice and this list of conditions.
#   2. Redistributions in binary form must reproduce the above copyright
#      notice and  this list of  conditions in the  documentation and/or
#      other materials provided with the distribution.
#
#                                      Anthony Mallet on Fri Mar 22 2013
#

args components
lang c

# get exceptions with details, uniquifying on mangled name
set edict [dict create]
foreach c $component {
  foreach t [$c types public] {
    if {[$t kind] ne "exception"} continue
    if {![llength [$t members]]} continue

    dict set edict [$t mangle] $t
  }
}
'>
#ifndef H_GENOM_EXCEPTION
#define H_GENOM_EXCEPTION

#include <assert.h>

#include "typeops-c.h"

union genom_exception_details {
<'if {![dict size $edict]} {'>
  char none;
<'}'>
<'dict for {m e} $edict {'>
  <"[$e declarator ${m}_]">;
<'}'>
};

struct genom_exception_data {
  genom_event e;
  char detail[sizeof(union genom_exception_details)];
};


/* --- genom_raise --------------------------------------------------------- */

/* Register exception in the given context.
 */
static inline genom_event
genom_raise(genom_event e, const void *detail, size_t size,
            struct genom_exception_data *data)
{
  assert(size <= sizeof(data->detail));

  if (data->e) genom_tfiniex(data->e, (void *)data->detail);
  data->e = e;
  if (genom_tcopyex(e, (void *)data->detail, detail)) return genom_fatal;
  return e;
}

static inline const void *
genom_raised(genom_event *e, const struct genom_exception_data *data)
{
  if (e) *e = data->e;
  return (void *)data->detail;
}

#endif /* H_GENOM_EXCEPTION */
