1 /*
2 * Simulator of microcontrollers (utils.cc)
3 *
4 * Copyright (C) 1997,16 Drotos Daniel, Talker Bt.
5 *
6 * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
7 *
8 */
9
10 /* This file is part of microcontroller simulator: ucsim.
11
12 UCSIM is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 UCSIM is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with UCSIM; see the file COPYING. If not, write to the Free
24 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 02111-1307, USA. */
26 /*@1@*/
27
28 #include "ddconfig.h"
29
30 #if defined(HAVE_VASPRINTF) && !defined(_GNU_SOURCE)
31 /* define before including stdio.h to enable vasprintf() declaration */
32 #define _GNU_SOURCE
33 #endif
34 #include <stdio.h>
35 #include <ctype.h>
36 #include <stdarg.h>
37 #include <stdlib.h>
38 #include <unistd.h>
39 #include <sys/time.h>
40 #include "i_string.h"
41
42 // prj
43 #include "stypes.h"
44 #include "pobjcl.h"
45
46 #include "utils.h"
47
48
49 int
get_sub_opt(char ** option,const char * const * tokens,char ** valuep)50 get_sub_opt(char **option, const char * const *tokens, char **valuep)
51 {
52 char *end, *equ;
53 int i;
54
55 if (!(end= strchr(*option, ',')))
56 end= *option + strlen(*option);
57 else
58 *end++= '\0';
59 if ((equ= strchr(*option, '=')))
60 {
61 *valuep= equ+1;
62 *equ= '\0';
63 }
64 else
65 *valuep= 0;
66 i= 0;
67 while (tokens[i] &&
68 strcmp(*option, tokens[i]))
69 i++;
70 if (!tokens[i])
71 *valuep= *option;
72 *option= end;
73 return tokens[i]?i:-1;
74 }
75
76
77 char *
get_id_string(struct id_element * ids,int id)78 get_id_string(struct id_element *ids, int id)
79 {
80 int i= 0;
81
82 while (ids[i].id_string &&
83 id != ids[i].id)
84 i++;
85 return(cchars(ids[i].id_string));
86 }
87
88 char *
get_id_string(struct id_element * ids,int id,char * def)89 get_id_string(struct id_element *ids, int id, char *def)
90 {
91 char *s= get_id_string(ids, id);
92
93 return(s?s:def);
94 }
95
96 int
get_string_id(struct id_element * ids,char * str)97 get_string_id(struct id_element *ids, char *str)
98 {
99 int i= 0;
100
101 while (ids[i].id_string &&
102 strcmp(ids[i].id_string, str) != 0)
103 i++;
104 return(ids[i].id);
105 }
106
107 int
get_string_id(struct id_element * ids,char * str,int def)108 get_string_id(struct id_element *ids, char *str, int def)
109 {
110 int i= 0;
111
112 while (ids[i].id_string &&
113 strcmp(ids[i].id_string, str) != 0)
114 i++;
115 return(ids[i].id_string?ids[i].id:def);
116 }
117
118
119 char *
vformat_string(const char * format,va_list ap)120 vformat_string(const char *format, va_list ap)
121 {
122 char *msg= NULL;
123 #ifdef HAVE_VASPRINTF
124 if (0 > vasprintf(&msg, format, ap))
125 msg = NULL;
126 return(msg);
127 #else
128 msg = (char*)malloc(80*25);
129 vsnprintf(msg, 80*25, format, ap);
130 #endif
131 return(msg);
132 }
133
134 char *
format_string(const char * format,...)135 format_string(const char *format, ...)
136 {
137 va_list ap;
138
139 va_start(ap, format);
140 char *s= vformat_string(format, ap);
141 va_end(ap);
142 return(s);
143 }
144
145
146 void
print_char_octal(char c,FILE * f)147 print_char_octal(char c, FILE *f)
148 {
149 if (strchr("\a\b\f\n\r\t\v\"", c))
150 switch (c)
151 {
152 case '\a': fprintf(f, "\a"); break;
153 case '\b': fprintf(f, "\b"); break;
154 case '\f': fprintf(f, "\f"); break;
155 case '\n': fprintf(f, "\n"); break;
156 case '\r': fprintf(f, "\r"); break;
157 case '\t': fprintf(f, "\t"); break;
158 case '\v': fprintf(f, "\v"); break;
159 case '\"': fprintf(f, "\""); break;
160 }
161 else if (isprint(c))
162 fprintf(f, "%c", c);
163 else
164 fprintf(f, "\\%03o", (int)c);
165 }
166
167
168 const char *
object_name(class cl_base * o)169 object_name(class cl_base *o)
170 {
171 const char *name= 0;
172
173 if (o)
174 name= o->get_name();
175 if (name &&
176 *name)
177 return(name);
178 return(cchars("(unknown)"));
179 }
180
181
182 char *
case_string(enum letter_case lcase,char * str)183 case_string(enum letter_case lcase, char *str)
184 {
185 char *p= strdup(str);
186 char *s= p;
187
188 switch (lcase)
189 {
190 case case_upper:
191 while (p && *p) {
192 *p= toupper(*p);
193 p++;
194 }
195 break;
196 case case_lower:
197 while (p && *p) {
198 *p= tolower(*p);
199 p++;
200 }
201 break;
202 case case_case:
203 if (!p || *p == '\0')
204 break;
205 while (isspace(*p)) p++;
206 if (*p)
207 *p= toupper(*p);
208 break;
209 }
210 return(s);
211 }
212
213 chars
cbin(long data,int bits)214 cbin(long data, int bits)
215 {
216 long mask= 1;
217 chars c= "";
218
219 mask= mask << ((bits >= 1)?(bits-1):0);
220 while (bits--)
221 {
222 c+= (data&mask)?'1':'0';
223 mask>>= 1;
224 }
225 return c;
226 }
227
228 /*char *
229 case_string(enum letter_case lcase, const char *str)
230 {
231 char *p= NIL;
232
233 if (!str ||
234 !*str)
235 return(NIL);
236 p= strdup(str);
237 return case_string(lcase, p);
238 }*/
239
240 double
dnow(void)241 dnow(void)
242 {
243 struct timeval tv;
244 gettimeofday(&tv, NULL);
245 return (double)tv.tv_sec + ((double)tv.tv_usec/1000000.0);
246 }
247
248 int
strispn(char * s,char c)249 strispn(char *s, char c)
250 {
251 if (!s || !*s)
252 return 0;
253 char *p= strchr(s, c);
254 if (!p)
255 return -1;
256 return p-s;
257 }
258
259 /* Return true if "serach_in" string ends with string "what" */
260
261 bool
strend(char * search_in,char * what)262 strend(char *search_in, char *what)
263 {
264 if (!search_in ||
265 !what ||
266 !*search_in ||
267 !*what)
268 return false;
269 char *start= strstr(search_in, what);
270 if (start == NULL)
271 return false;
272 if (start[strlen(what)] == '\0')
273 return true;
274 return false;
275 }
276
277 bool
valid_sym_name(char * s)278 valid_sym_name(char *s)
279 {
280 if (!s || !*s)
281 return false;
282 if (!isalpha(*s) &&
283 (*s != '_'))
284 return false;
285 char *p= s+1;
286 for (; *p; p++)
287 {
288 if (!isalnum(*p) &&
289 (*p != '_'))
290 return false;
291 }
292 return true;
293 }
294
295
296 bool
is_hex_file(class cl_f * f)297 is_hex_file(class cl_f *f)
298 {
299 char *n;
300 if (!f)
301 return false;
302 n= f->get_file_name();
303 if (!n ||
304 !*n)
305 return false;
306
307 if (strend(n, cchars(".ihx")) ||
308 strend(n, cchars(".hex")) ||
309 strend(n, cchars(".ihex")))
310 return true;
311
312 return false;
313 }
314
315 bool
is_omf_file(class cl_f * f)316 is_omf_file(class cl_f *f)
317 {
318 char *n;
319 if (!f)
320 return false;
321 n= f->get_file_name();
322 if (!n ||
323 !*n)
324 return false;
325
326 if (strend(n, cchars(".omf")))
327 return true;
328
329 return false;
330 }
331
332 bool
is_cdb_file(class cl_f * f)333 is_cdb_file(class cl_f *f)
334 {
335 char *n;
336 if (!f)
337 return false;
338 n= f->get_file_name();
339 if (!n ||
340 !*n)
341 return false;
342
343 if (strend(n, cchars(".cdb")))
344 return true;
345
346 return false;
347 }
348
349 /*
350 option_name=col_opt:col_opt
351
352 option_name=
353 prompt prompt_console command answer
354 dump_address dump_number dump_char
355
356 col_opt=
357 B bold
358 F faint
359 I italic
360 U underline
361 D double_underline
362 C crossedout
363 O overline
364 KL blink
365
366 col_opt=
367 black red green yellow blue magenta cyan white
368 bblack bred bgreen byellow bblue bmagenta bcyan bwhite
369 #RGB
370
371 */
372
373 enum col_ctype_t
374 {
375 ct_none= 0,
376 ct_bold= 0x01,
377 ct_faint= 0x02,
378 ct_italic= 0x04,
379 ct_underl= 0x08,
380 ct_dunderl= 0x10,
381 ct_crossed= 0x20,
382 ct_overl= 0x40,
383 ct_blink= 0x80
384 };
385
386 chars
colopt2ansiseq(char * opt)387 colopt2ansiseq(char *opt)
388 {
389 bool fg_rgb= false, bg_rgb= false;
390 bool fg_bright= false, bg_bright= false;
391 chars r= "";
392 int fg= -1, bg= -1;
393 int ctype= ct_none;
394 chars o;
395
396 if (!opt ||
397 !*opt)
398 return r;
399 o= opt;
400 char *s= strtok((char*)o, ":");
401 while (s)
402 {
403 if (strcmp(s, "black") == 0)
404 {
405 if (fg<0)
406 fg= 0;
407 else
408 bg= 0;
409 }
410 else if (strcmp(s, "bblack") == 0)
411 {
412 if (fg<0)
413 fg= 0, fg_bright= true;
414 else
415 bg= 0, bg_bright= true;
416 }
417 else if (strcmp(s, "red") == 0)
418 {
419 if (fg<0)
420 fg= 1;
421 else
422 bg= 1;
423 }
424 else if (strcmp(s, "bred") == 0)
425 {
426 if (fg<0)
427 fg= 1, fg_bright= true;
428 else
429 bg= 1, bg_bright= true;
430 }
431 else if (strcmp(s, "green") == 0)
432 {
433 if (fg<0)
434 fg= 2;
435 else
436 bg= 2;
437 }
438 else if (strcmp(s, "bgreen") == 0)
439 {
440 if (fg<0)
441 fg= 2, fg_bright= true;
442 else
443 bg= 2, bg_bright= true;
444 }
445 else if (strcmp(s, "yellow") == 0)
446 {
447 if (fg<0)
448 fg= 3;
449 else
450 bg= 3;
451 }
452 else if (strcmp(s, "byellow") == 0)
453 {
454 if (fg<0)
455 fg= 3, fg_bright= true;
456 else
457 bg= 3, bg_bright= true;
458 }
459 else if (strcmp(s, "blue") == 0)
460 {
461 if (fg<0)
462 fg= 4;
463 else
464 bg= 4;
465 }
466 else if (strcmp(s, "bblue") == 0)
467 {
468 if (fg<0)
469 fg= 4, fg_bright= true;
470 else
471 bg= 4, bg_bright= true;
472 }
473 else if (strcmp(s, "magenta") == 0)
474 {
475 if (fg<0)
476 fg= 5;
477 else
478 bg= 5;
479 }
480 else if (strcmp(s, "bmagenta") == 0)
481 {
482 if (fg<0)
483 fg= 5, fg_bright= true;
484 else
485 bg= 5, bg_bright= true;
486 }
487 else if (strcmp(s, "cyan") == 0)
488 {
489 if (fg<0)
490 fg= 6;
491 else
492 bg= 6;
493 }
494 else if (strcmp(s, "bcyan") == 0)
495 {
496 if (fg<0)
497 fg= 6, fg_bright= true;
498 else
499 bg= 6, bg_bright= true;
500 }
501 else if (strcmp(s, "white") == 0)
502 {
503 if (fg<0)
504 fg= 7;
505 else
506 bg= 7;
507 }
508 else if (strcmp(s, "bwhite") == 0)
509 {
510 if (fg<0)
511 fg= 7, fg_bright= true;
512 else
513 bg= 7, bg_bright= true;
514 }
515 else if (*s == '#')
516 {
517 int c= strtol(&s[1], NULL, 16);
518 if (fg<0)
519 fg= c, fg_rgb= true;
520 else
521 bg= c, bg_rgb= true;
522 }
523 else if (strspn(s, "bBfFiIuUdDcCoOkKlL") > 0)
524 {
525 int i;
526 for (i=0; s[i]; i++)
527 {
528 switch (toupper(s[i]))
529 {
530 case 'B': ctype|= ct_bold; break;
531 case 'F': ctype|= ct_faint; break;
532 case 'I': ctype|= ct_italic; break;
533 case 'U': ctype|= ct_underl; break;
534 case 'D': ctype|= ct_dunderl; break;
535 case 'C': ctype|= ct_crossed; break;
536 case 'O': ctype|= ct_overl; break;
537 case 'K': ctype|= ct_blink; break;
538 case 'L': ctype|= ct_blink; break;
539 }
540 }
541 }
542 s= strtok(NULL, ":");
543 }
544
545 /* set character rendering mode */
546 if (ctype != ct_none)
547 {
548 if (ctype & ct_bold) r.append("\033[1m");
549 if (ctype & ct_faint) r.append("\033[2m");
550 if (ctype & ct_italic) r.append("\033[3m");
551 if (ctype & ct_underl) r.append("\033[4m");
552 if (ctype & ct_dunderl) r.append("\033[21m");
553 if (ctype & ct_crossed) r.append("\033[9m");
554 if (ctype & ct_overl) r.append("\033[53m");
555 if (ctype & ct_blink) r.append("\033[5m");
556 }
557
558 /* Background color */
559 if (bg >= 0)
560 {
561 if (bg_rgb)
562 {
563 r.append("\033[48;2;%d;%d;%dm", (bg>>16)&0xff, (bg>>8)&0xff, bg&0xff);
564 }
565 else
566 {
567 int i= 40+bg;
568 if (bg_bright)
569 i= 100+bg;
570 r.append("\033[%dm", i);
571 }
572 }
573
574 /* Foreground color */
575 if (fg >= 0)
576 {
577 if (fg_rgb)
578 {
579 r.append("\033[38;2;%d;%d;%dm", (fg>>16)&0xff, (fg>>8)&0xff, fg&0xff);
580 }
581 else
582 {
583 int i= 30+fg;
584 if (fg_bright)
585 i= 90+fg;
586 r.append("\033[%dm", i);
587 }
588 }
589
590 return r;
591 }
592
593
594 /* End of utils.cc */
595