|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * ami-rexx.c
5: *
6: * Copyright 1996 Samuel Devulder.
7: */
8:
9: #include <proto/exec.h>
10: #include <proto/alib.h>
11: #include <proto/rexxsyslib.h>
12: #include <proto/dos.h>
13:
14: #include <rexx/storage.h>
15: #include <rexx/errors.h>
16:
17: /* this prevent a conflict between <rexx/rexxio.h> and <sys/dirent.h> */
18: #undef DT_DIR
19:
20: /****************************************************************************/
21:
22: #include "sysconfig.h"
23: #include "sysdeps.h"
24:
25: #include "uae.h"
26: #include "config.h"
27: #include "options.h"
28: #include "../include/memory.h" /* or else gcc includes machdep/memory.h */
29: #include "custom.h"
30: #include "readcpu.h"
31: #include "newcpu.h"
32: #include "disk.h"
33: #include "gui.h"
34: #include "os.h"
35:
36: #include <ctype.h>
37:
38: /****************************************************************************/
39:
40: #define UAE_PORTNAME "UAE"
41: #define RESULT_LEN 1024
42: #define PORT_LEN 80
43: #define CMD_LEN 1024
44:
45: typedef struct
46: {
47: char port[PORT_LEN];
48: char cmd_on[CMD_LEN];
49: char cmd_off[CMD_LEN];
50: } gui_rexx_s;
51:
52: enum {LED_POW, LED_DF0, LED_DF1, LED_DF2, LED_DF3,
53: NAME_DF0, NAME_DF1, NAME_DF2, NAME_DF3,
54: ON_EXIT,
55: GUI_REXX_MAX};
56:
57: /****************************************************************************/
58:
59: int rexx_init(void);
60: void rexx_exit(void);
61: void rexx_led(int led, int on);
62: void rexx_filename(int num, char *name);
63: void rexx_handle_events(void);
64:
65: /****************************************************************************/
66:
67: struct Library *RexxSysBase;
68: static struct MsgPort *ARexxPort;
69: static gui_rexx_s gui_rexx[GUI_REXX_MAX];
70: static char RESULT[RESULT_LEN];
71: static int led_state[5];
72:
73: static int ADDRESS(char *hostname, char *cmd);
74: static int matchstr(char **line,char *pat);
75: static void extractstr(char **line, char *result, int len);
76: static int matchnum(char **line);
77:
78: /****************************************************************************/
79:
80: extern int quit_program; /* ami-gui.c */
81: extern void activate_debugger(void); /* debug.c */
82: extern char *to_unix_path(char *s); /* ami-disk.c */
83: extern char *from_unix_path(char *s); /* ami-disk.c */
84:
85: /****************************************************************************/
86:
87: int rexx_init(void)
88: {
89: quit_program = 0;
90: RexxSysBase = OpenLibrary("rexxsyslib.library",0L);
91: if(!RexxSysBase) {
92: fprintf(stderr, "Can't find rexxsyslib.library!\n");
93: return 1;
94: }
95: if(FindPort(UAE_PORTNAME)) {
96: fprintf(stderr, "Port \"%s\" already exists!\n",UAE_PORTNAME);
97: return 1;
98: }
99: ARexxPort = CreatePort(UAE_PORTNAME,0);
100: if(!ARexxPort) {
101: fprintf(stderr, "Failed to open AREXX port \"%s\"!\n",UAE_PORTNAME);
102: return 1;
103: }
104: fprintf(stderr,"Rexx port \"%s\" installed.\n", UAE_PORTNAME);
105: rexx_handle_events();
106: return 0;
107: }
108:
109: /****************************************************************************/
110:
111: void rexx_exit(void)
112: {
113: if(ARexxPort) {
114: struct RexxMsg *msg;
115: gui_rexx_s *gui = &gui_rexx[ON_EXIT];
116:
117: if(gui->port[0] && gui->cmd_on[0]) {
118: if(ADDRESS(gui->port, gui->cmd_on) != RC_OK) {
119: fprintf(stderr,"%s:%s:%s\n", gui->port,
120: gui->cmd_on,
121: RESULT);
122: }
123: gui->port[0] = '\0';
124: }
125: Forbid();
126: while((msg = (struct RexxMsg*)GetMsg(ARexxPort))) {
127: msg->rm_Result1 = RC_ERROR;
128: msg->rm_Result2 = NULL;
129: ReplyMsg((void*)msg);
130: }
131: DeletePort(ARexxPort);
132: Permit();
133: ARexxPort = NULL;
134: }
135: if(RexxSysBase) {
136: CloseLibrary((void*)RexxSysBase);
137: RexxSysBase = NULL;
138: }
139: }
140:
141: /****************************************************************************/
142:
143: static int EJECT(char *line)
144: {
145: int drive = matchnum(&line);
146: if(drive<0 || drive>3) return RC_WARN;
147: disk_eject(drive);
148: sprintf(RESULT,"Drive %d ejected",drive);
149: return RC_OK;
150: }
151:
152: /****************************************************************************/
153:
154: static int INSERT(char *line)
155: {
156: int drive = matchnum(&line);
157: if(drive<0 || drive>3) return RC_WARN;
158: if(disk_empty(drive)) {
159: char buff[256];
160: char *name;
161: extractstr(&line, buff, 256);
162: name = to_unix_path(buff);
163: disk_insert(drive, name);
164: free(name);
165: } else {
166: sprintf(RESULT,"Drive %d not empty!",drive);
167: return RC_WARN;
168: }
169: return RC_OK;
170: }
171:
172: /****************************************************************************/
173:
174: static void QUIT(void)
175: {
176: broken_in = 1;
177: regs.spcflags |= SPCFLAG_BRK;
178: quit_program = 1;
179: }
180:
181: /****************************************************************************/
182:
183: static int QUERY(char *line)
184: {
185: char *res = NULL;
186: int alc = 0;
187:
188: if (matchstr(&line, "LED_POW")) res = led_state[0]?"1":"0";
189: else if(matchstr(&line, "LED_DF0")) res = led_state[1]?"1":"0";
190: else if(matchstr(&line, "LED_DF1")) res = led_state[2]?"1":"0";
191: else if(matchstr(&line, "LED_DF2")) res = led_state[3]?"1":"0";
192: else if(matchstr(&line, "LED_DF3")) res = led_state[4]?"1":"0";
193: else if(matchstr(&line, "NAME_DF0")) res = from_unix_path(df0), alc = 1;
194: else if(matchstr(&line, "NAME_DF1")) res = from_unix_path(df1), alc = 1;
195: else if(matchstr(&line, "NAME_DF2")) res = from_unix_path(df2), alc = 1;
196: else if(matchstr(&line, "NAME_DF3")) res = from_unix_path(df3), alc = 1;
197: else if(matchstr(&line, "FAKEJOYSTICK")) res = fake_joystick?"1":"0";
198: else if(matchstr(&line, "DISPLAY")) res = inhibit_frame?"0":"1";
199: else if(matchstr(&line, "FRAMERATE")) {
200: sprintf(RESULT,"%d",framerate);
201: return RC_OK;
202: } else if(matchstr(&line, "SOUND")) {
203: sprintf(RESULT,"%d",sound_available?produce_sound:-1);
204: return RC_OK;
205: }
206: else return RC_ERROR;
207:
208: if(res) {
209: strncpy(RESULT, res, RESULT_LEN);
210: if(alc) free(res);
211: }
212: return RC_OK;
213: }
214:
215: /****************************************************************************/
216:
217: static int FEEDBACK(char *line)
218: {
219: gui_rexx_s *gui = NULL;
220:
221: if (matchstr(&line,"LED_POW")) gui = &gui_rexx[LED_POW];
222: else if(matchstr(&line,"LED_DF0")) gui = &gui_rexx[LED_DF0];
223: else if(matchstr(&line,"LED_DF1")) gui = &gui_rexx[LED_DF1];
224: else if(matchstr(&line,"LED_DF2")) gui = &gui_rexx[LED_DF2];
225: else if(matchstr(&line,"LED_DF3")) gui = &gui_rexx[LED_DF3];
226: else if(matchstr(&line,"NAME_DF0")) gui = &gui_rexx[NAME_DF0];
227: else if(matchstr(&line,"NAME_DF1")) gui = &gui_rexx[NAME_DF1];
228: else if(matchstr(&line,"NAME_DF2")) gui = &gui_rexx[NAME_DF2];
229: else if(matchstr(&line,"NAME_DF3")) gui = &gui_rexx[NAME_DF3];
230: else if(matchstr(&line,"ON_EXIT")) gui = &gui_rexx[ON_EXIT];
231: else return RC_ERROR;
232:
233: while(1) {
234: if(matchstr(&line, "ADDRESS") ||
235: matchstr(&line, "PORT")) {
236: extractstr(&line, gui->port, PORT_LEN);
237: } else if(matchstr(&line,"COMMAND") ||
238: matchstr(&line,"CMD") ||
239: matchstr(&line,"CMD_ON")) {
240: extractstr(&line, gui->cmd_on, CMD_LEN);
241: } else if(matchstr(&line,"CMD_OFF")) {
242: extractstr(&line, gui->cmd_off, CMD_LEN);
243: } else break;
244: }
245: return RC_OK;
246: }
247:
248: /****************************************************************************/
249:
250: static int VERSION(char *line)
251: {
252: if(matchstr(&line,"STRING")) {
253: sprintf(RESULT,
254: "UAE-%d.%d.%d � by Bernd Schmidt & contributors, "
255: "Amiga Port by Samuel Devulder.",
256: (version / 100) % 10, (version / 10) % 10, version % 10);
257: } else if(matchstr(&line,"NUM")) {
258: sprintf(RESULT,"%d",version);
259: } else if(matchstr(&line,"AUTHOR")) {
260: sprintf(RESULT,"� by Bernd Schmidt & contributors");
261: } else if(matchstr(&line,"PORT")) {
262: sprintf(RESULT,"Amiga Port by Samuel Devulder");
263: } else return RC_ERROR;
264: return RC_OK;
265: }
266:
267: /****************************************************************************/
268:
269: static int FRAMERATE(char *line)
270: {
271: int num;
272: num = matchnum(&line);
273: if(num>=1 && num<=20) {
274: framerate = num;
275: } else {
276: sprintf(RESULT,"Invalid frame rate: %d\n", num);
277: return RC_WARN;
278: }
279: return RC_OK;
280: }
281:
282: /****************************************************************************/
283:
284: static int FAKEJOYSTICK(char *line)
285: {
286: if (matchstr(&line,"ON")) fake_joystick = 1;
287: else if(matchstr(&line,"OFF")) fake_joystick = 0;
288: else if(matchstr(&line,"TOGGLE")) fake_joystick = fake_joystick?0:1;
289: else return RC_ERROR;
290: return RC_OK;
291: }
292:
293: /****************************************************************************/
294:
295: static int DISPLAY(char *line)
296: {
297: if (matchstr(&line,"ON")) inhibit_frame = 0;
298: else if(matchstr(&line,"OFF")) inhibit_frame = 1;
299: else if(matchstr(&line,"TOGGLE")) inhibit_frame = inhibit_frame?0:1;
300: else return RC_ERROR;
301: return RC_OK;
302: }
303:
304: /****************************************************************************/
305:
306: static int SOUND(char *line)
307: {
308: if(!sound_available) {
309: sprintf(RESULT,"Sound not available!");
310: return RC_WARN;
311: }
312:
313: if (matchstr(&line,"ON")) produce_sound = 2;
314: else if(matchstr(&line,"OFF")) produce_sound = 1;
315: else if(matchstr(&line,"BEST")) produce_sound = 3;
316: else if(matchstr(&line,"TOGGLE")) produce_sound = produce_sound<=1?2:1;
317: else return RC_ERROR;
318: return RC_OK;
319: }
320:
321: /****************************************************************************/
322:
323: static int process_cmd(char *line)
324: {
325: RESULT[0] = '\0';
326: if (matchstr(&line, "EJECT")) return EJECT(line);
327: else if(matchstr(&line, "INSERT")) return INSERT(line);
328: else if(matchstr(&line, "QUERY")) return QUERY(line);
329: else if(matchstr(&line, "FEEDBACK")) return FEEDBACK(line);
330: else if(matchstr(&line, "VERSION")) return VERSION(line);
331: else if(matchstr(&line, "BYE")) QUIT();
332: else if(matchstr(&line, "QUIT")) QUIT();
333: else if(matchstr(&line, "DEBUG")) activate_debugger();
334: else if(matchstr(&line, "RESET")) m68k_reset();
335: else if(matchstr(&line, "DISPLAY")) return DISPLAY(line);
336: else if(matchstr(&line, "FRAMERATE")) return FRAMERATE(line);
337: else if(matchstr(&line, "FAKEJOYSTICK")) return FAKEJOYSTICK(line);
338: else if(matchstr(&line, "SOUND")) return SOUND(line);
339: else return RC_ERROR;
340: return RC_OK;
341: }
342:
343: /****************************************************************************/
344:
345: void rexx_handle_events(void)
346: {
347: struct RexxMsg *msg;
348: while((msg = (struct RexxMsg*)GetMsg(ARexxPort))) {
349: if(!(msg->rm_Action & RXCOMM)) {
350: fprintf(stderr,"Unknown action '%08X' recieved!\n",
351: msg->rm_Action);
352: continue;
353: }
354: msg->rm_Result1 = process_cmd(msg->rm_Args[0]);
355: msg->rm_Result2 = NULL;
356: if(msg->rm_Action & RXFF_RESULT) {
357: msg->rm_Result2 = (LONG)CreateArgstring(RESULT,strlen(RESULT));
358: }
359: ReplyMsg((void*)msg);
360: }
361: }
362:
363: /****************************************************************************/
364:
365: void rexx_led(int led, int on)
366: {
367: gui_rexx_s *gui = NULL;
368:
369: if(led < 0 || led > 4) return;
370: led_state[led] = on;
371:
372: if(led == 0) gui = &gui_rexx[LED_POW];
373: if(led == 1) gui = &gui_rexx[LED_DF0];
374: if(led == 2) gui = &gui_rexx[LED_DF1];
375: if(led == 3) gui = &gui_rexx[LED_DF2];
376: if(led == 4) gui = &gui_rexx[LED_DF3];
377:
378: if(gui->port[0] && gui->cmd_on[0] && gui->cmd_off[0]) {
379: if(ADDRESS(gui->port, on ? gui->cmd_on : gui->cmd_off) != RC_OK) {
380: fprintf(stderr,"%s:%s:%s\n", gui->port,
381: on ? gui->cmd_on : gui->cmd_off,
382: RESULT);
383: }
384: }
385: }
386:
387: /****************************************************************************/
388:
389: void rexx_filename(int num, char *filename)
390: {
391: gui_rexx_s *gui = NULL;
392: if(num < 0 || num > 3) return;
393: gui = &gui_rexx[NAME_DF0 + num];
394: if(gui->port[0] && gui->cmd_on[0]) {
395: char buf[CMD_LEN];
396: if(!(filename = from_unix_path(filename))) return;
397: sprintf(buf, gui->cmd_on, filename);
398: free(filename);
399: if(ADDRESS(gui->port, buf) != RC_OK) {
400: fprintf(stderr,"%s:%s:%s\n", gui->port, buf, RESULT);
401: }
402: }
403: }
404:
405: /****************************************************************************/
406: /* send a message to an AREXX port.
407: */
408: static int ADDRESS(char *hostname, char *cmd)
409: {
410: struct MsgPort *RexxPort,
411: *ReplyPort;
412: struct RexxMsg *HostMsg,
413: *answer;
414: int result = RC_WARN;
415:
416: if(!stricmp(hostname, "COMMAND")) {
417: return SystemTagList(cmd,NULL);
418: }
419:
420: if((RexxPort = (void *)FindPort(hostname))) {
421: if((ReplyPort = (void *)CreateMsgPort())) {
422: if((HostMsg = CreateRexxMsg(ReplyPort, NULL, hostname))) {
423: if((HostMsg->rm_Args[0] = CreateArgstring(cmd,strlen(cmd)))) {
424: HostMsg->rm_Action = RXCOMM | RXFF_RESULT;
425: PutMsg(RexxPort, (void*)HostMsg);
426: WaitPort(ReplyPort);
427: while(!(answer = (void *)GetMsg(ReplyPort)));
428: result = answer->rm_Result1;
429: if(result == RC_OK) {
430: if(answer->rm_Result2) {
431: strncpy(RESULT,(char *)answer->rm_Result2,RESULT_LEN);
432: DeleteArgstring((char *)answer->rm_Result2);
433: } else RESULT[0] = '\0';
434: }
435: DeleteArgstring(HostMsg->rm_Args[0]);
436: } else strcpy(RESULT, "Can't create argstring!");
437: DeleteRexxMsg(HostMsg);
438: } else strcpy(RESULT, "Can't create rexx message!");
439: DeleteMsgPort(ReplyPort);
440: } else strcpy(RESULT, "Can't alloc reply port!");
441: } else sprintf(RESULT, "Port \"%s\" not found!",hostname);
442: return result;
443: }
444:
445: /****************************************************************************/
446: /* argument parsing routines
447: */
448: static int matchstr(char **line,char *pat)
449: {
450: char *s = *line;
451: char match = 0;
452: while(isspace(*s)) ++s;
453: if(*s=='\"' || *s== '\'') match = *s++;
454: while(*s && (tolower(*s)==tolower(*pat)) && (!match || *s!=match)) {++s;++pat;}
455: if(match && *s==match && s[1]) ++s;
456: if(!*pat && (!*s || isspace(*s))) {
457: while(isspace(*s)) ++s;
458: *line = s;
459: return 1;
460: }
461: return 0;
462: }
463:
464: /****************************************************************************/
465:
466: static void extractstr(char **line, char *result, int len)
467: {
468: char *s = *line;
469: char match = 0;
470:
471: while(isspace(*s)) ++s;
472:
473: if(*s=='\"' || *s=='\'') match = *s++;
474: while(*s && *s != match) {
475: if(*s == '\\' && (s[1] == '\'' || s[1] == '\"')) ++s;
476: if(len > 1) {*result++ = *s;--len;}
477: ++s;
478: if(!match && isspace(*s)) break;
479: }
480: if(match && *s == match) ++s;
481: while(isspace(*s)) ++s;
482:
483: *result = '\0';
484: *line = s;
485: }
486:
487: /****************************************************************************/
488:
489: static int matchnum(char **line)
490: {
491: char *s = *line, match = 0;
492: int sign = 1, num = 0;
493:
494: while(isspace(*s)) ++s;
495: if(*s=='\"' || *s=='\'') match = *s++;
496: if(*s=='-') {sign = -1;++s;}
497: if(*s=='+') ++s;
498: while(isspace(*s)) ++s;
499: while(*s>='0' && *s<='9') num = num*10 + (*s++ - '0');
500: if(match && *s==match && s[1]) ++s;
501: while(isspace(*s)) ++s;
502: *line = s;
503: return sign>0?num:-num;
504: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.