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