-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathagc_cli.c
275 lines (249 loc) · 9.83 KB
/
agc_cli.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
/*
* agc_cli.c
*
* Created on: Nov 30, 2008
* Author: MZ211D
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "agc_cli.h"
#include "agc_engine.h"
#include "agc_symtab.h"
/* Some legacy vars for now */
int FullNameMode = 0;
int QuietMode = 0;
static char CduLog[] = "yaAGC.cdulog";
static Options_t Options;
/**
The command line options try to stay compatible with the early versions of
yaAGC for some time to enable a transition period but will not list them
in the usage for the command help to discourage its usage. Hence the option
--core is somewhat confusing because in the old builds it represents the
executable core-ropes image file but normally gdb uses this for the
core file. */
static void CliShowUsage(void)
{
printf ("Usage:\n"
"\tyaAGC [options] exec-ropes-file [core-resume-file]\n\n"
"Options:\n\n"
"--exec=EXECFILE Use EXECFILE as the exec-ropes-file\n"
"--fullname Output information used by emacs-GDB interface.\n"
"--symbols=SYMFILE Read symbols from SYMFILE generated by yaYUL.\n"
"--quiet Do not print version number on startup.\n"
"--cd=DIR Change current directory to DIR.\n"
"--command=FILE Execute AGC commands from FILE.\n"
"--directory=DIR Search for source files in DIR.\n"
"--port=N Change the server port number (default=19697).\n"
"--nodebug Disables debugging and run just the simulation\n"
"--interlace=N Read the socket interface every N CPU instructions.\n"
"--dump-time=N Create core image every N seconds (default = 10).\n"
"--cdu-log Used only for debugging. Creates the file yaAGC.cdulog\n"
" containing data related to the bandwidth-limiting of\n"
" CDU inputs PCDU and MCDU.\n"
"--debug-dsky Rather than run the core program, go into DSKY-debug\n"
" mode. In this mode send pre-determined codes to\n"
" the DSKY upon receiving DSKY keypresses.\n"
"--debug-deda This mode runs the core program as usual, but also\n"
" responds to messages from yaDEDA and generates fake\n"
" messages to yaDEDA for testing purposes.\n"
"--deda-quiet Used with --debug-deda to eliminate outputs from yaAGC\n"
" to the DEDA. In other words, lets yaAGC parse the\n"
" messages being received from the DEDA, but never to\n"
" send any. That lets \"yaAGC --debug-deda --deda-quiet\"\n"
" to be used alongside yaAGS without conflict.\n"
"--cfg=file The name of a configuration file. Presently, the\n"
" configuration files is used only for --debug-dsky\n"
" mode. It would typically be the same configuration\n"
" file as used for yaDSKY.\n\n"
"Note that the exec-ropes file should contain exactly 36 banks\n"
"(36x1024=36864 words, or 73728 bytes). Other sizes may be accepted,\n"
"but it is unclear what (if any) utility such core-rope images\n"
"would have. (In particular, if the core-rope\n"
"is supposed to be for actual Luminary or Colossus software, then\n"
"the checksums of the missing memory banks would be incorrect, and\n"
"so the built-in self-test would fail.)\n\n");
}
extern FILE *rfopen (const char *Filename, const char *mode);
/**
This function parses the specified configuration file.
It loads its contents not a lot of checking is done here.
It returns 0 on "success" and 1 on known error.
*/
int CliParseCfg (char *Filename)
{
char s[129] = { 0 };
int KeyCode, Channel, Value, Result = 1;
char Logic;
FILE *fin;
fin = rfopen (Filename, "r");
if (fin)
{
Result = 0;
while (NULL != fgets (s, sizeof (s) - 1, fin))
{
char *ss;
/* Find newline or form feed and replace with string termination */
for (ss = s; *ss; ss++) if (*ss == '\n' || *ss == '\r') *ss = 0;
/* Parse string */
if (4 == sscanf(s,"DEBUG %d %o %c %x",&KeyCode,&Channel,&Logic,&Value))
{
/* Ensure valid values are porvided */
if (Channel < 0 || Channel > 255) continue;
if (Logic != '=' && Logic != '&' &&
Logic != '|' && Logic != '^') continue;
if (Value != (Value & 0x7FFF)) continue;
if (KeyCode < 0 || KeyCode > 31) continue;
if (NumDebugRules >= MAX_DEBUG_RULES) break;
/* Set the Debug Rules */
DebugRules[NumDebugRules].KeyCode = KeyCode;
DebugRules[NumDebugRules].Channel = Channel;
DebugRules[NumDebugRules].Logic = Logic;
DebugRules[NumDebugRules].Value = Value;
NumDebugRules++;
}
else if (!strcmp (s, "LMSIM")) CmOrLm = 0;
else if (!strcmp (s, "CMSIM")) CmOrLm = 1;
}
fclose (fin);
}
return (Result);
}
/**
This is a private function of the Cli module. It sets the
internal Options structure members to their default value.
The Option structure handle will be returned through the
commandline parse function. */
static void CliInitializeOptions(void)
{
Options.core = (char*)0;
Options.resume = (char*)0;
Options.cdu_log = (char*)0;
Options.symtab = (char*)0;
Options.directory = (char*)0;
Options.cd = (char*)0;
Options.cfg = (char*)0;
Options.fromfile = (char*)0;
Options.port = 19697;
Options.dump_time = 10;
Options.debug_dsky = 0;
Options.debug_deda = 0;
Options.deda_quiet = 0;
Options.quiet = 0;
Options.fullname = 0;
Options.debug = 1;
Options.resumed = 0;
Options.interlace = 50;
Options.version = 0;
}
/**
This function takes a character string and checks the string for
known command line options. To support both single and double dash
options this function will normalize the double dash to s single dash just
by skipping the first dash. If the token is recognized the function
will return CLI_E_OK else it will return CLI_E_UNKOWNTOKEN.
\param *token The character string
\return The success of failure indication. */
static int CliProcessArgument(char* token)
{
int result = CLI_E_OK;
int j;
/* Transform -- to just - for compatibility */
if (!strncmp(token,"--",2)) token++;
/* Parse the token */
if (!strcmp (token, "-help") || !strcmp (token, "/?")) result = 1;
else if (!strncmp (token, "-nx", 3)) /* Ignore for now */;
else if (!strncmp (token, "-args", 5)) /* Ignore for now */;
else if (!strncmp (token, "-core=", 6))
{
/* If --core is used assume classic behavior is expected */
Options.core = strdup(&token[6]);
/* with classi behavior default is nodebug */
Options.debug = 0;
}
else if (!strncmp (token, "-directory=", 11))Options.directory = strdup(&token[11]);
else if (!strncmp (token, "-cd=", 4))Options.cd = strdup(&token[4]);
else if (!strncmp (token, "-exec=", 6))Options.core = strdup(&token[6]);
else if (!strncmp (token, "-resume=", 8))Options.resume = strdup(&token[8]);
else if (1 == sscanf (token, "-port=%d", &j)) Options.port = j;
else if (1 == sscanf (token, "-dump-time=%d", &j)) Options.dump_time = j;
else if (!strcmp (token, "-debug-dsky")) Options.debug_dsky = 1;
else if (!strcmp (token, "-debug-deda")) Options.debug_deda = 1;
else if (!strcmp (token, "-deda-quiet")) Options.deda_quiet = 1;
else if (!strcmp (token, "-cdu-log")) Options.cdu_log = CduLog;
else if (!strncmp (token, "-cfg=", 5)) Options.cfg = strdup(&token[5]);
else if (!strcmp (token, "-fullname")) Options.fullname = 1;
else if (!strcmp (token, "-quiet"))Options.quiet = 1;
else if (!strcmp (token, "-nodebug")) Options.debug = 0;
else if (!strcmp (token, "-debug")) Options.debug = 1;
else if (!strcmp (token, "-version")) Options.version = 6;
else if (!strncmp (token, "-command=",9)) Options.fromfile = strdup(&token[9]);
else if (!strncmp (token, "-interpreter=",13)) /* Ignore for now */;
else if (!strncmp (token, "-symbols=", 9)) Options.symtab = strdup(&token[9]);
else if (!strncmp (token, "-symtab=", 8)) Options.symtab = strdup(&token[8]);
else if (1 == sscanf (token,"-interlace=%d", &j)) Options.interlace = j;
else if (Options.core == (char*)0) Options.core = strdup(token);
else if (Options.resume == (char*)0) Options.resume = strdup(token);
else result = CLI_E_UNKOWNTOKEN;
return (result);
}
/**
This function takes the command line argument count and argument array
as inputs and returns an Option structure if all parses correctly.
When errors are encountered the parser will return a NULL reference
\param argc The argument count
\param *argv The pointer to the argument array.
\return A handle to an Option structure. */
Options_t* CliParseArguments(int argc, char *argv[])
{
Options_t* result = (Options_t*)0;
int i;
/* Set all the defaults in the option structure */
CliInitializeOptions();
/* Parse the command-line tokens */
for (i = 1; i < argc; i++) if (CliProcessArgument(argv[i])) break;
/* If there is an issue with the provided command line interface
* display the usage message. Otherwise proceed with the automatic
* values based on the core-ropes image name.
*/
if (argc == 1 || i < argc || (!Options.core && !Options.debug_dsky))
{
/* Check if only version info is requested */
if (Options.version) result = &Options;
else /* Show the usage message */
CliShowUsage();
}
else
{
/* If a new working directory is specified then change to it
* immediately */
if (Options.cd > 0) chdir(Options.cd);
/* Options are properly Parsed */
result = &Options;
/* Must have .bin extension to find the symbol table based on the
* core basename with the bin extension.
*/
if (strstr(Options.core,".bin"))
{
int FullPathLength = strlen(Options.core);
/* If Debugging without symtab set default symtab */
if (Options.debug && !Options.symtab)
{
Options.symtab = (char*)calloc(1,FullPathLength + 4);
strcpy(Options.symtab,Options.core);
strcpy(Options.symtab + strlen(Options.core)-3,"symtab");
}
}
/* If a configuration file is specified load its contents */
if (Options.cfg)
{
if (CliParseCfg (Options.cfg))
{
result = (Options_t*)0;
printf("\n*** Unknown configurstion file. ***\n\n");
}
}
}
return (result);
}