re-add debugger sources
[fw/altos] / ao-tools / ao-dbg / ao-dbg-main.c
1 /*
2  * Copyright © 2008 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17  */
18
19 #include "ao-dbg.h"
20 #include <unistd.h>
21 #include <sys/types.h>
22 #include <sys/socket.h>
23 #include <netinet/in.h>
24 #include <signal.h>
25 #include <stdarg.h>
26 #include <poll.h>
27
28 static int s51_port = 0;
29 static char *cpu = "8051";
30 static double freq = 11059200;
31 char *s51_prompt = "> ";
32 struct ccdbg *s51_dbg;
33 int s51_interrupted = 0;
34 int s51_monitor = 0;
35
36 static FILE *s51_input;
37 static FILE *s51_output;
38
39 static void
40 usage(void)
41 {
42         fprintf(stderr, "You're doing it wrong.\n");
43         exit(1);
44 }
45
46 void s51_sigint()
47 {
48         s51_interrupted = 1;
49 }
50
51 int
52 main(int argc, char **argv)
53 {
54         int flags, opt;
55         char *endptr;
56         struct sigvec vec, ovec;
57
58         while ((opt = getopt(argc, argv, "PVvHhmt:X:c:r:Z:s:S:p:")) != -1) {
59                 switch (opt) {
60                 case 't':
61                         cpu = optarg;
62                         break;
63                 case 'X':
64                         freq = strtod(optarg, &endptr);
65                         if (endptr == optarg)
66                                 usage();
67                         if (endptr[0] != '\0') {
68                                 if (!strcmp(endptr, "k"))
69                                         freq *= 1000;
70                                 else if (!strcmp(endptr, "M") )
71                                         freq *= 1000000;
72                                 else
73                                         usage ();
74                         }
75                         break;
76                 case 'c':
77                         break;
78                 case 'r':
79                 case 'Z':
80                         s51_port = strtol(optarg, &endptr, 0);
81                         if (endptr == optarg || strlen(endptr) != 0)
82                                 usage();
83                         break;
84                 case 's':
85                         break;
86                 case 'S':
87                         break;
88                 case 'p':
89                         s51_prompt = optarg;
90                         break;
91                 case 'P':
92                         s51_prompt = NULL;
93                         break;
94                 case 'V':
95                         break;
96                 case 'v':
97                         break;
98                 case 'H':
99                         exit (0);
100                         break;
101                 case 'h':
102                         usage ();
103                         break;
104                 case 'm':
105                         s51_monitor = 1;
106                         break;
107                 }
108         }
109         if (s51_port) {
110                 int l, r, one = 1;
111                 int s;
112                 struct sockaddr_in in;
113
114                 l = socket(AF_INET, SOCK_STREAM, 0);
115                 if (l < 0) {
116                         perror ("socket");
117                         exit(1);
118                 }
119                 r = setsockopt(l, SOL_SOCKET, SO_REUSEADDR, &one, sizeof (int));
120                 if (r) {
121                         perror("setsockopt");
122                         exit(1);
123                 }
124                 in.sin_family = AF_INET;
125                 in.sin_port = htons(s51_port);
126                 in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
127                 r = bind(l, (struct sockaddr *) &in, sizeof (in));
128                 if (r) {
129                         perror("bind");
130                         exit(1);
131                 }
132                 r = listen(l, 5);
133                 if (r) {
134                         perror("listen");
135                         exit(1);
136                 }
137                 for (;;) {
138                         struct sockaddr_in client_addr;
139                         socklen_t client_len = sizeof (struct sockaddr_in);
140
141                         s = accept(l, (struct sockaddr *)
142                                    &client_addr, &client_len);
143                         if (s < 0) {
144                                 perror("accept");
145                                 exit(1);
146                         }
147                         s51_input = fdopen(s, "r");
148                         s51_output = fdopen(s, "w");
149                         if (!s51_input || !s51_output) {
150                                 perror("fdopen");
151                                 exit(1);
152                         }
153                         vec.sv_handler = SIG_IGN;
154                         vec.sv_mask = 0;
155                         vec.sv_flags = 0;
156                         sigvec(SIGINT, &vec, &ovec);
157                         command_read();
158                         sigvec(SIGINT, &ovec, NULL);
159                         fclose(s51_input);
160                         fclose(s51_output);
161                 }
162         } else {
163                 s51_input = stdin;
164                 s51_output = stdout;
165                 vec.sv_handler = s51_sigint;
166                 vec.sv_mask = 0;
167                 vec.sv_flags = 0;
168                 sigvec(SIGINT, &vec, &ovec);
169                 command_read();
170         }
171         exit(0);
172 }
173
174 void
175 s51_printf(char *format, ...)
176 {
177         va_list ap;
178
179         va_start(ap, format);
180         vfprintf(s51_output, format, ap);
181         if (s51_monitor)
182                 vfprintf(stdout, format, ap);
183         va_end(ap);
184 }
185
186 void
187 s51_putc(int c)
188 {
189         putc(c, s51_output);
190 }
191
192 #include <readline/readline.h>
193 #include <readline/history.h>
194
195 int
196 s51_read_line(char *line, int len)
197 {
198         int ret;
199         if (s51_output == stdout && s51_input == stdin && s51_prompt) {
200                 char *r;
201
202                 r = readline(s51_prompt);
203                 if (r == NULL)
204                         return 0;
205                 strncpy (line, r, len);
206                 line[len-1] = '\0';
207                 add_history(r);
208                 return 1;
209         } else {
210                 if (s51_prompt)
211                         s51_printf("%s", s51_prompt);
212                 else
213                         s51_putc('\0');
214                 fflush(s51_output);
215                 ret = fgets(line, len, s51_input) != NULL;
216                 if (s51_monitor)
217                         printf("> %s", line);
218                 fflush(stdout);
219         }
220         return ret;
221 }
222
223 int
224 s51_check_input(void)
225 {
226         struct pollfd   input;
227         int r;
228         int c;
229
230         input.fd = fileno(s51_input);
231         input.events = POLLIN;
232         r = poll(&input, 1, 0);
233         if (r > 0) {
234                 char line[256];
235                 (void) s51_read_line(line, sizeof (line));
236                 return 1;
237         }
238         return 0;
239 }