/* * CIF support code for Tock programs * Copyright (C) 2008 University of Kent * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 2 of the License, or (at * your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library. If not, see . */ #ifndef TOCK_SUPPORT_CIF_H #define TOCK_SUPPORT_CIF_H #include #include #include #include #include #include //{{{ occam_stop #define occam_stop(pos, nargs, format, args...) \ do { \ ExternalCallN (fprintf, 3 + nargs, stderr, \ "Program stopped at %s: " format "\n", \ pos, ##args); \ SetErr (); \ } while (0) //}}} #include //{{{ channel array initialisation static inline void tock_init_chan_array (Channel *, Channel **, int) occam_unused; static inline void tock_init_chan_array (Channel *pointTo, Channel **pointFrom, int count) { for (int i = 0; i < count; i++) { pointFrom[i] = &(pointTo[i]); } } //}}} //{{{ top-level process interface static void tock_tlp_input_bcall (FILE *in, int *ch) occam_unused; static void tock_tlp_input_bcall (FILE *in, int *ch) { *ch = fgetc (in); } static void tock_tlp_input (Workspace wptr) occam_unused; static void tock_tlp_input (Workspace wptr) { Channel *out = ProcGetParam (wptr, 0, Channel *); Channel *kill = ProcGetParam (wptr, 1, Channel *); FILE *in = ProcGetParam (wptr, 2, FILE *); while (true) { int ch = -1; KillableBlockingCallN (wptr, tock_tlp_input_bcall, kill, 2, in, &ch); if (ch == -1) { // The call was killed -- exit. break; } ChanOutChar (wptr, out, ch); } } static void tock_tlp_input_kill (Workspace wptr, Channel *kill) occam_unused; static void tock_tlp_input_kill (Workspace wptr, Channel *kill) { while (true) { // If KillBlockingCall returns -1, the call hasn't started yet, // so we reschedule and try again. (If tock_tlp_input is // blocked on output we should deadlock anyway.) if (KillBlockingCall (wptr, kill) != -1) break; Reschedule (wptr); } } static void tock_tlp_output (Workspace wptr) occam_unused; static void tock_tlp_output (Workspace wptr) { Channel *in = ProcGetParam (wptr, 0, Channel *); Channel *kill = ProcGetParam (wptr, 1, Channel *); FILE *out = ProcGetParam (wptr, 2, FILE *); while (true) { switch (ProcAlt (wptr, in, kill, NULL)) { case 0: { uint8_t ch; ChanIn (wptr, in, &ch, sizeof ch); if (ch == 255) { // FLUSH fflush (out); } else { ExternalCallN (fputc, 2, ch, out); } break; } case 1: { bool b; ChanIn (wptr, kill, &b, sizeof b); return; } } } } static void tock_tlp_output_kill (Workspace wptr, Channel *kill) occam_unused; static void tock_tlp_output_kill (Workspace wptr, Channel *kill) { bool b = true; ChanOut (wptr, kill, &b, sizeof b); } //}}} //{{{ CCSP startup and terminal handling static bool tock_uses_tty; static struct termios tock_saved_termios; static void tock_exit_handler (int status, word core) occam_unused; static void tock_exit_handler (int status, word core) { //{{{ restore terminal if (tock_uses_tty) { if (tcsetattr (0, TCSAFLUSH, &tock_saved_termios) != 0) { fprintf (stderr, "Tock: tcsetattr failed\n"); exit (1); } tock_uses_tty = false; } //}}} ccsp_default_exit_handler (status, core); } static void tock_init_ccsp (bool uses_stdin) occam_unused; static void tock_init_ccsp (bool uses_stdin) { ccsp_set_branding ("Tock"); //{{{ configure terminal tock_uses_tty = uses_stdin && isatty (0); if (tock_uses_tty) { struct termios term; if (tcgetattr (0, &term) != 0) { fprintf (stderr, "Tock: tcgetattr failed\n"); exit (1); } tock_saved_termios = term; // Disable canonicalised input and echoing. term.c_lflag &= ~(ICANON | ECHO); // Satisfy a read request when one character is available. term.c_cc[VMIN] = 1; // Block read requests until VMIN characters are available. term.c_cc[VTIME] = 0; if (tcsetattr (0, TCSANOW, &term) != 0) { fprintf (stderr, "Tock: tcsetattr failed\n"); exit (1); } } //}}} if (!ccsp_init ()) exit (1); ccsp_set_exit_handler (tock_exit_handler); } //}}} #endif