1 /*
2 This file is part of GNU APL, a free implementation of the
3 ISO/IEC Standard 13751, "Programming Language APL, Extended"
4
5 Copyright (C) 2008-2016 Dr. Jürgen Sauermann
6
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include <cassert>
22 #include <iostream>
23
24 #include <signal.h>
25 #include <stdio.h>
26 #include <stdint.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <sys/wait.h>
30
31 #include "APmain.hh"
32 #include "CDR_string.hh"
33 #include "Svar_DB.hh"
34 #include "Svar_signals.hh"
35
36 using namespace std;
37
38 //-----------------------------------------------------------------------------
prog_name()39 const char * prog_name()
40 {
41 return "AP100";
42 }
43 //-----------------------------------------------------------------------------
44 struct SVAR_context
45 {
SVAR_contextSVAR_context46 SVAR_context()
47 {}
48 };
49 //-----------------------------------------------------------------------------
50 int
set_ACK(Coupled_var & var,int exco)51 set_ACK(Coupled_var & var, int exco)
52 {
53 const uint8_t _cdr[] =
54 {
55 0x00, 0x00, 0x20, 0x20, // ptr
56 0x00, 0x00, 0x00, 0x20, // nb: total len
57 0x00, 0x00, 0x00, 0x01, // nelm: element count
58 0x01, 0x00, 0x00, 0x00, // type, rank, pad, pad
59 uint8_t(exco), uint8_t(exco>>8), uint8_t(exco>>16), uint8_t(exco>>24),
60 0x00, 0x00, 0x00, 0x00, // pad
61 0x00, 0x00, 0x00, 0x00, // pad
62 0x00, 0x00, 0x00, 0x00, // pad
63 };
64
65 const CDR_string * cdr = new CDR_string(_cdr, sizeof(_cdr));
66 delete var.data;
67 var.data = cdr;
68 Svar_DB::set_state(var.key, true, LOC);
69
70 return exco;
71 }
72 //-----------------------------------------------------------------------------
73 void
handle_var(Coupled_var & var)74 handle_var(Coupled_var & var)
75 {
76 FILE * fp = 0;
77 const CDR_string & cdr = *var.data;
78 const CDR_header & header = cdr.header();
79 if (cdr.size() < 20) // less than min. size of CDR header
80 {
81 get_CERR() << "CDR record too short (" << cdr.size()
82 << " bytes)" << endl;
83 set_ACK(var, 444);
84 return;
85 }
86
87 if (cdr[13] != 1) // not a vector
88 {
89 get_CERR() << "Bad CDR rank (" << int(cdr[13]) << endl;
90 set_ACK(var, 445);
91 return;
92 }
93
94 if (cdr[12] != 4) // not a char vector
95 {
96 get_CERR() << "Bad CDR record type (" << int(cdr[12]) << endl;
97 set_ACK(var, 446);
98 return;
99 }
100
101 const string cmd((const char *)cdr.get_items() + 20, header.get_nelm());
102
103 if (verbose) get_CERR() << pref << " got command[" << cmd.size() << "] '"
104 << cmd << "'" << endl;
105
106 fp = popen(cmd.c_str(), "r");
107 if (fp == 0) // bad command
108 {
109 get_CERR() << pref << " popen() failed" << endl;
110 set_ACK(var, 1); // 1 := INVALID COMMAND
111 return;
112 }
113
114 for (;;)
115 {
116 const int cc = fgetc(fp);
117 if (cc == EOF) break;
118 get_CERR() << char(cc);
119 }
120
121 get_CERR() << flush;
122 const int result = pclose(fp);
123 if (verbose)
124 get_CERR() << pref << " finished command with exit code "
125 << result << endl;
126
127 set_ACK(var, WEXITSTATUS(result));
128 }
129 //-----------------------------------------------------------------------------
130 bool
is_valid_varname(const uint32_t * varname)131 is_valid_varname(const uint32_t * varname)
132 {
133 // AP100 supports all variable names
134 //
135 return *varname; // varname is not empty
136 }
137 //-----------------------------------------------------------------------------
138 bool
initialize(Coupled_var & var)139 initialize(Coupled_var & var)
140 {
141 Svar_DB::set_state(var.key, true, LOC);
142 Svar_DB::set_control(var.key, USE_BY_1);
143 return false; // OK
144 }
145 //-----------------------------------------------------------------------------
146 bool
make_counter_offer(SV_key key)147 make_counter_offer(SV_key key)
148 {
149 return true; // make counter offer
150 }
151 //-----------------------------------------------------------------------------
152
153 APL_error_code
assign_value(Coupled_var & var,const string & data)154 assign_value(Coupled_var & var, const string & data)
155 {
156 // check CDR size, type, and shape of data. We expect a char string
157 // for both the CTL and the DAT variable.
158 //
159 if (data.size() < sizeof(CDR_header)) // too short
160 { error_loc = LOC; return E_LENGTH_ERROR; }
161
162 delete var.data;
163 var.data = new CDR_string((const uint8_t *)data.c_str(), data.size());
164 handle_var(var);
165 return E_NO_ERROR;
166 }
167 //-----------------------------------------------------------------------------
168 APL_error_code
get_value(Coupled_var & var,string & data)169 get_value(Coupled_var & var, string & data)
170 {
171 if (var.data == 0) return E_VALUE_ERROR;
172
173 data = string((const char *)(var.data->get_items()), var.data->size());
174 error_loc = "no_error"; return E_NO_ERROR;
175 }
176 //-----------------------------------------------------------------------------
177 void
retract(Coupled_var & var)178 retract(Coupled_var & var)
179 {
180 SVAR_context * ctx = var.context;
181 if (ctx)
182 {
183 delete ctx;
184 }
185 }
186
187 //-----------------------------------------------------------------------------
188