Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

hteval.cc

Go to the documentation of this file.
00001 /* 
00002  *      HT Editor
00003  *      hteval.cc
00004  *
00005  *      Copyright (C) 1999-2002 Stefan Weyergraf (stefan@weyergraf.de)
00006  *
00007  *      This program is free software; you can redistribute it and/or modify
00008  *      it under the terms of the GNU General Public License version 2 as
00009  *      published by the Free Software Foundation.
00010  *
00011  *      This program is distributed in the hope that it will be useful,
00012  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *      GNU General Public License for more details.
00015  *
00016  *      You should have received a copy of the GNU General Public License
00017  *      along with this program; if not, write to the Free Software
00018  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019  */
00020 
00021 #include <string.h>
00022 
00023 #include "htatom.h"
00024 #include "htctrl.h"
00025 #include "htendian.h"
00026 #include "hthist.h"
00027 #include "htiobox.h"
00028 #include "htpal.h"
00029 #include "htstring.h"
00030 #include "snprintf.h"
00031 #include "syntax.h"
00032 #include "textedit.h"
00033 #include "textfile.h"
00034 
00035 extern "C" {
00036 #include "evalx.h"
00037 }
00038 
00039 
00040 /*
00041  *      eval help
00042  */
00043 #define FH_HEAD         1
00044 #define FH_DESC         2
00045 
00046 // FIXME: disfunctional...
00047 class ht_help_lexer: public ht_syntax_lexer {
00048 public:
00049 /* overwritten */
00050         virtual vcp getcolor_syntax(UINT pal_index)
00051         {
00052                 return VCP(VC_BLUE, VC_TRANSPARENT);
00053         }
00054 
00055         virtual lexer_state getinitstate()
00056         {
00057                 return FH_HEAD;
00058         }
00059 
00060         virtual lexer_token geterrortoken()
00061         {
00062                 return 3;
00063         }
00064 
00065         virtual char *getname()
00066         {
00067                 return "bla";
00068         }
00069 
00070         virtual lexer_token gettoken(void *buf, UINT buflen, text_pos p, bool start_of_line, lexer_state *ret_state, UINT *ret_len)
00071         {
00072                 *ret_len = buflen;
00073                 int ps = *ret_state;
00074                 if (buflen == 0) *ret_state = FH_HEAD; else *ret_state = FH_DESC;
00075                 return buflen ? ps : 0;
00076         }
00077 
00078         virtual vcp gettoken_color(lexer_token t)
00079         {
00080                 switch (t) {
00081                         case FH_HEAD:
00082                                 return VCP(VC_LIGHT(VC_WHITE), VC_TRANSPARENT);
00083                         case FH_DESC:
00084                                 return VCP(VC_BLACK, VC_TRANSPARENT);
00085                 }
00086                 return VCP(VC_RED, VC_TRANSPARENT);
00087         }
00088 };
00089 
00090 static void dialog_fhelp(ht_streamfile *f)
00091 {
00092         ht_help_lexer *l = new ht_help_lexer();
00093         l->init();
00094 
00095         ht_ltextfile *t = new ht_ltextfile();
00096         t->init(f, true, NULL);
00097 
00098         bounds b, c;
00099         app->getbounds(&c);
00100         b = c;
00101 //      b.w = 70;
00102 //      b.h = 19;
00103         b.x = (c.w - b.w) / 2,
00104         b.y = (c.h - b.h) / 2;
00105         c = b;
00106 
00107         ht_dialog *dialog = new ht_dialog();
00108         dialog->init(&b, "eval() - functions", FS_KILLER | FS_TITLE | FS_MOVE | FS_RESIZE);
00109 
00110         b.x = 0;
00111         b.y = 0;
00112         b.w -= 2;
00113         b.h -= 2;
00114 
00115         ht_text_viewer *v = new ht_text_viewer();
00116         v->init(&b, true, t, NULL);
00117 
00118         v->set_lexer(l, true);
00119 
00120         dialog->insert(v);
00121 
00122         b = c;
00123         b.x = b.w-2;
00124         b.y = 0;
00125         b.w = 1;
00126         b.h-=2;
00127         ht_scrollbar *hs=new ht_scrollbar();
00128         hs->init(&b, &dialog->pal, true);
00129 
00130         dialog->setvscrollbar(hs);
00131 
00132         dialog->setpalette(palkey_generic_cyan);
00133 
00134         dialog->run(0);
00135 
00136         v->done();
00137         delete v;
00138 }
00139 
00140 void dialog_eval_help(eval_func_handler func_handler, eval_symbol_handler symbol_handler, void *context)
00141 {
00142         eval_scalar res;
00143         if (eval(&res, "help()", func_handler, symbol_handler, context)) {
00144                 eval_str s;
00145                 scalar_context_str(&res, &s);
00146                 scalar_destroy(&res);
00147 
00148                 ht_memmap_file *f = new ht_memmap_file();
00149                 f->init((byte*)s.value, s.len);
00150 
00151                 dialog_fhelp(f);
00152 
00153                 string_destroy(&s);
00154         }
00155 }
00156 
00157 /*
00158  *
00159  */
00160 static int sprint_base2(char *x, dword value, bool leading_zeros)
00161 {
00162         char *ix = x;
00163         bool draw = leading_zeros;
00164         for (int i=0; i<32; i++) {
00165                 bool v = value & (1<<(32-i-1));
00166                 if (v) draw = true;
00167                 if (draw) *x++ = v ? '1' : '0';
00168         }
00169         *x = 0;
00170         return x-ix;
00171 }
00172 
00173 static int sprint_base2_0(char *x, dword value, int zeros)
00174 {
00175         char *ix = x;
00176         char vi = 0;
00177         dword m = 0x80000000;
00178         while (zeros < 32) {m >>= 1; zeros++;}
00179         do {
00180                 if (value & m) {
00181                         while (vi--) *(x++)='0';
00182                         vi = 0;
00183                         *x = '1';
00184                         x++;
00185                 } else {
00186                         vi++;
00187                 }
00188                 m >>= 1;
00189         } while (m);
00190         if (!value) *(x++)='0';
00191         *x = 0;
00192         return x-ix;
00193 }
00194 
00195 static void nicify(char *dest, const char *src, int d)
00196 {
00197         *dest = *src;
00198         int l=strlen(src);
00199         if (!l) return;
00200         dest++;
00201         src++;
00202         while (l--) {
00203                 if ((l%d==0) && (l>1)) {
00204                         *dest='\'';
00205                         dest++;
00206                 }
00207                 *(dest++) = *(src++);
00208         }
00209         *dest=0;
00210 }
00211 
00212 #define BUTTON_HELP     100
00213 
00214 static void do_eval(ht_strinputfield *s, ht_statictext *t, char *b)
00215 {
00216         eval_scalar r;
00217         if (eval(&r, b, NULL, NULL, NULL)) {
00218                 switch (r.type) {
00219                         case SCALAR_INT: {
00220                                 char *x = b;
00221                                 char buf1[1024];
00222                                 char buf2[1024];
00223                                 // FIXME
00224                                 dword lo = QWORD_GET_LO(r.scalar.integer.value);
00225                                 dword hi = QWORD_GET_HI(r.scalar.integer.value);
00226                                 x += sprintf(x, "64bit integer:\n");
00227                                 ht_snprintf(buf1, sizeof buf1, "%qx", &r.scalar.integer.value);
00228                                 nicify(buf2, buf1, 4);
00229                                 x += ht_snprintf(x, 64, "hex   %s\n", buf2);
00230                                 ht_snprintf(buf1, sizeof buf1, "%qu", &r.scalar.integer.value);
00231                                 nicify(buf2, buf1, 3);
00232                                 x += ht_snprintf(x, 64, "dec   %s\n", buf2);
00233                                 if (to_sint64(r.scalar.integer.value) < to_sint64(0)) {
00234                                         ht_snprintf(buf1, sizeof buf1, "%qd", &r.scalar.integer.value);
00235                                         nicify(buf2, buf1+1, 3);
00236                                         x += ht_snprintf(x, 64, "sdec  -%s\n", buf2);
00237                                 }
00238                                 ht_snprintf(buf1, sizeof buf1, "%qo", &r.scalar.integer.value);
00239                                 nicify(buf2, buf1, 3);
00240                                 x += ht_snprintf(x, 64, "oct   %s\n", buf2);
00241 
00242                                 sprint_base2(buf1, lo, true);
00243                                 nicify(buf2, buf1, 8);
00244                                 x += ht_snprintf(x, 64, "binlo %s\n", buf2);
00245                                 if (hi) {
00246                                         sprint_base2(buf1, hi, true);
00247                                         nicify(buf2, buf1, 8);
00248                                         x += ht_snprintf(x, 64, "binhi %s\n", buf2);
00249                                 }
00250                                 char bb[4];
00251                                 int i = lo;
00252                                 /* big-endian string */
00253                                 x += sprintf(x, "%s", "string \"");
00254                                 create_foreign_int(bb, i, 4, big_endian);
00255                                 bin2str(x, bb, 4);
00256                                 x += 4;
00257                                 x += sprintf(x, "%s", "\" 32bit big-endian (e.g. network)\n");
00258                                 /* little-endian string */
00259                                 x += sprintf(x, "string \"");
00260                                 create_foreign_int(bb, i, 4, little_endian);
00261                                 bin2str(x, bb, 4);
00262                                 x += 4;
00263                                 x += sprintf(x, "%s", "\" 32bit little-endian (e.g. x86)\n");
00264                                 /* finish */
00265                                 *x = 0;
00266                                 break;
00267                         }
00268                         case SCALAR_STR: {
00269                                 char *x=b;
00270                                 x+=sprintf(x, "string:\n");
00271                                 /* c-escaped */
00272                                 x+=sprintf(x, "c-escaped \"");
00273                                 x+=escape_special(x, 0xff, r.scalar.str.value, r.scalar.str.len, NULL, true);
00274                                 *(x++)='"';
00275                                 *(x++)='\n';
00276                                 /* raw */
00277                                 x+=sprintf(x, "raw       '");
00278                                 int ll = MIN((UINT)r.scalar.str.len, 0xff);
00279                                 bin2str(x, r.scalar.str.value, ll);
00280                                 x+=ll;
00281                                 *(x++)='\'';
00282                                 *(x++)='\n';
00283                                 *x=0;
00284                                 break;
00285                         }
00286                         case SCALAR_FLOAT: {
00287                                 char *x=b;
00288                                 x+=sprintf(b, "val   %.20f\nnorm  %.20e", r.scalar.floatnum.value, r.scalar.floatnum.value);
00289                                 // FIXME: endianess/hardware format
00290                                 float ff = ((float)r.scalar.floatnum.value);
00291                                 dword f = *(dword*)&ff;
00292                                 x += sprintf(x, "\n-- IEEE-754, 32 bit --");
00293                                 x += sprintf(x, "\nhex   %08x\nbin   ", f);
00294                                 x += sprint_base2(x, f, true);
00295                                 x += sprintf(x, "\nsplit %c1.", (f>>31) ? '-' : '+');
00296                                 x += sprint_base2_0(x, f&((1<<23)-1), 23);
00297                                 x += sprintf(x, "b * 2^%d", ((f>>23)&255)-127);
00298                                 break;
00299                         }
00300                         default:
00301                                 strcpy(b, "?");
00302                 }
00303                 scalar_destroy(&r);
00304         } else {
00305                 char *str="?";
00306                 int pos=0;
00307                 get_eval_error(&str, &pos);
00308                 s->isetcursor(pos);
00309                 sprintf(b, "error at pos %d: %s", pos+1, str);
00310         }
00311 
00312         t->settext(b);
00313 }
00314 
00315 void eval_dialog()
00316 {
00317         bounds b, c;
00318         app->getbounds(&c);
00319         b.w=70;
00320         b.h=17;
00321         b.x=(c.w-b.w)/2;
00322         b.y=(c.h-b.h)/2;
00323         ht_dialog *d=new ht_dialog();
00324         c=b;
00325         char *hint="type integer, float or string expression to evaluate";
00326 
00327         d->init(&b, "evaluate", FS_TITLE | FS_MOVE | FS_RESIZE);
00328 
00329         ht_list *ehist=(ht_list*)find_atom(HISTATOM_EVAL_EXPR);
00330 
00331         /* input line */
00332         BOUNDS_ASSIGN(b, 1, 1, c.w-14, 1);
00333         ht_strinputfield *s=new ht_strinputfield();
00334         s->init(&b, 255, ehist);
00335         d->insert(s);
00336         /* help button */
00337         ht_button *bhelp = new ht_button();
00338         BOUNDS_ASSIGN(b, c.w-12, 1, 10, 1);
00339         bhelp->init(&b, "~Functions", BUTTON_HELP);
00340         d->insert(bhelp);
00341         /* result text */
00342         BOUNDS_ASSIGN(b, 1, 3, c.w-4, c.h-5);
00343         ht_statictext *t=new ht_statictext();
00344         t->init(&b, hint, align_left);
00345         t->growmode = MK_GM(GMH_LEFT, GMV_FIT);
00346         d->insert(t);
00347 
00348         int button;
00349         while ((button = d->run(false)) != button_cancel) {
00350                 switch (button) {
00351                 case button_ok:
00352                         ht_strinputfield_data str;
00353                         char b[1024];
00354                         s->databuf_get(&str, sizeof str);
00355                         if (str.textlen) {
00356                                 bin2str(b, str.text, str.textlen);
00357                                 insert_history_entry(ehist, b, 0);
00358                                 do_eval(s, t, b);
00359                         } else {
00360                                 t->settext(hint);
00361                         }
00362                         break;
00363                 case BUTTON_HELP:
00364                         dialog_eval_help(NULL, NULL, NULL);
00365                         break;
00366                 }
00367         }
00368 
00369         d->done();
00370         delete d;
00371 }

Generated on Fri May 7 21:15:33 2004 by doxygen 1.3.5