// Signal handling part of i77 perms.

#define _POSIX_C_SOURCE 200809L

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <setjmp.h>
#include <unistd.h>
#include <string.h>

#include "internalfile.h"
#include "psignal.h"

// Setting this up so that *all* IMP %signal calls map to linux signal SUGUSR1
// Any other Linux signals (such as generated by say divide-by-zero) will need
// to be trapped and converted into an IMP signal.

_imp_eventfm _imp_event;
sig_atomic_t _imp_last_signal = 0;

/* Jump to the current innermost active event frame. */

// croak() is an attempt to enable writing error messages from within
// signal service routines.  Hence why it is very basic.
static inline void croak(const char *msg) {
  write(2, msg, (unsigned int)strlen(msg));
  _exit(1);
}

void _imp_signal_handler(int sig) {
  //if (_imp_event == NULL) croak("NULL _imp_event\n");
  _imp_last_signal = sig; // C signal type such as SIGUSR1
  siglongjmp(_imp_event.env, 1);
}

_imp_eventfm *_imp_on_event_enter(_imp_eventfm *f) {
  static int initialized = 0;
  if (!initialized) {  
    struct sigaction sa;
    sigemptyset(&sa.sa_mask);
    sa.sa_handler = _imp_signal_handler;
    sa.sa_flags = 0;
    if (sigaction(SIGUSR1, &sa, NULL) < 0) croak("sigaction(SIGUSR1, &sa, NULL) < 0\n");
    initialized = 1;
  }
  f->prev = &_imp_event;
  _imp_event = *f;
  return f;
  // "return sigsetjmp(f->env, 1);" CAUSES A SEGFAULT.  MOVING IT TO THE POINT OF CALL FIXES THAT.
}

void _imp_on_event_leave(_imp_eventfm *f) {
  _imp_eventfm *lost = &_imp_event;
  _imp_event = *f->prev;
  free(lost);
}

// To be retooled for new c-signal based system:

void _signal_event(_imp_string file,
                   int line,
                   _imp_string message,
                   int event, int subevent, int extra) {
}
