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

htanaly.cc

Go to the documentation of this file.
00001 /*
00002  *      HT Editor
00003  *      htanaly.cc
00004  *
00005  *      Copyright (C) 1999-2002 Sebastian Biallas (sb@web-productions.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 "analy.h"
00022 #include "analy_names.h"
00023 #include "global.h"
00024 #include "log.h"
00025 #include "htanaly.h"
00026 #include "htctrl.h" // FIXME: globalerror
00027 #include "htdialog.h"
00028 #include "htdisasm.h"
00029 #include "hthist.h"
00030 #include "htidle.h"
00031 #include "htiobox.h"
00032 #include "htkeyb.h"
00033 #include "htmenu.h"
00034 #include "htsearch.h"
00035 #include "htstring.h"
00036 #include "httag.h"
00037 #include "httree.h"
00038 #include "language.h"
00039 #include "textedit.h"
00040 #include "textfile.h"
00041 #include "tools.h"
00042 #include "snprintf.h"
00043 #include "syntax.h"
00044 #include "out.h"
00045 #include "out_ht.h"
00046 #include "out_txt.h"
00047 #include "store.h"
00048 
00049 extern "C" {
00050 #include "evalx.h"
00051 }
00052 
00053 #include <stdlib.h>
00054 #include <string.h>
00055 
00056 /* FIXME: test */
00057 #include "srt.h"
00058 #include "out_html.h"
00059 #include "out_sym.h"
00060 
00061 /*
00062  *   AnalyserInformation
00063  */
00064 void    AnalyserInformation::init(bounds *b, ht_aviewer *a)
00065 {
00066         analy = a;
00067         assert(a);
00068         ht_statictext::init(b, 0, align_left);
00069         register_idle_object(this);
00070         idle();
00071 }
00072 
00073 void AnalyserInformation::done()
00074 {
00075         unregister_idle_object(this);
00076         ht_statictext::done();
00077 }
00078 
00079 char *AnalyserInformation::gettext()
00080 {
00081         ht_snprintf(buf, sizeof buf,
00082                 "Analyser statistics:\n"
00083                 "====================\n\n"          
00084                 "Type: %s\nFile: %s\n"
00085                 "Using disassembler: %s\n\n"
00086                 "Known locations: %d\n"
00087                 "Known symbols: %d\n\n",
00088                 atype, aname,
00089                 adis,
00090                 addrs, labels);
00091         return buf;
00092 }
00093 
00094 bool AnalyserInformation::idle()
00095 {
00096         if (analy && analy->analy) {
00097                 addrs = analy->analy->getLocationCount();
00098                 labels = analy->analy->getSymbolCount();
00099                 atype = analy->analy->getType();
00100                 aname = analy->analy->getName();
00101                 if (analy->analy->disasm) {
00102                         adis = analy->analy->disasm->getName();
00103                 } else {
00104                         adis = "?";
00105                 }
00106                 dirtyview();
00107         }
00108         return false;
00109 }
00110 
00111 /*
00112  *   SymbolBox
00113  */
00114 
00115 void SymbolBox::init(bounds *b, Analyser *Analy)
00116 {
00117         analy = Analy;
00118         ht_listbox::init(b);
00119         str = (char *)smalloc(1024);
00120         symbols = analy->getSymbolCount();
00121         idle_count = 1;
00122 }
00123 
00124 void SymbolBox::done()
00125 {
00126         free(str);
00127         ht_listbox::done();
00128 }
00129 
00130 int  SymbolBox::calcCount()
00131 {
00132         return analy->getSymbolCount();
00133 }
00134 
00135 int  SymbolBox::cursorAdjust()
00136 {
00137         Symbol *l = ((Symbol *)getFirst());
00138         if (!l) return 0;
00139         return l->location->addr->stringSize()+10;
00140 }
00141 
00142 int  SymbolBox::estimateEntryPos(void *entry)
00143 {
00144         return 0;
00145 }
00146 
00147 void *SymbolBox::getFirst()
00148 {
00149         return analy->enumSymbols(NULL);
00150 }
00151 
00152 void *SymbolBox::getLast()
00153 {
00154         return analy->enumSymbolsReverse(NULL);
00155 }
00156 
00157 void *SymbolBox::getNext(void *entry)
00158 {
00159         if (!entry) return NULL;
00160         return analy->enumSymbols((Symbol *)entry);
00161 }
00162 
00163 void *SymbolBox::getPrev(void *entry)
00164 {
00165         if (!entry) return NULL;
00166         return analy->enumSymbolsReverse((Symbol *)entry);
00167 }
00168 
00169 char *SymbolBox::getStr(int col, void *entry)
00170 {
00171         if (!entry) return NULL;
00172         Symbol *l = ((Symbol *)entry);
00173         switch (col) {
00174                 case 0:
00175                         global_analyser_address_string_format = ADDRESS_STRING_FORMAT_LEADING_WHITESPACE;
00176                         ht_snprintf(str, 1024, "%y", l->location->addr);
00177                         break;
00178                 case 1:
00179                         ht_snprintf(str, 1024, "%s", label_type_short(l->type));
00180                         break;
00181                 case 2:
00182                         ht_snprintf(str, 1024, "%s", l->name);
00183                         break;
00184         }
00185         return str;
00186 }
00187 
00188 bool SymbolBox::idle()
00189 {
00190         if ((idle_count % 500)==0) {
00191                 update();
00192                 redraw();
00193                 symbols = analy->getSymbolCount();
00194                 idle_count = 1;
00195                 return 1;
00196         }
00197         idle_count++;
00198         return 0;
00199 }
00200 
00201 int     SymbolBox::numColumns()
00202 {
00203         return 3;
00204 }
00205 
00206 void *SymbolBox::quickfind(char *s)
00207 {
00208         Symbol *tmp = analy->getSymbolByName(s);
00209         if (tmp) return tmp;
00210         tmp = analy->enumSymbolsByName(s);
00211         if (tmp) {
00212                 int slen = strlen(s);
00213                 int tlen = strlen(tmp->name);
00214                 if (slen > tlen) return NULL;
00215                 if (strncmp(tmp->name, s, slen)==0) return tmp;
00216                 return NULL;
00217         } else {
00218                 return NULL;
00219         }
00220 }
00221 
00222 
00223 char    *SymbolBox::quickfindCompletition(char *s)
00224 {
00225         if (analy->getSymbolByName(s)) {
00226                 return ht_strdup(s);
00227         }
00228         Symbol *tmp = analy->enumSymbolsByName(s);
00229         if (!tmp) {
00230                 return ht_strdup(s);
00231         }
00232         Symbol *tmp2 = analy->enumSymbols(tmp);
00233         if (!tmp2) {
00234                 return ht_strdup(tmp->name);
00235         }
00236         int slen = strlen(s);
00237         if (!ht_strncmp(tmp->name, tmp2->name, slen)==0) {
00238                 return ht_strdup(tmp->name);
00239         }
00240         char *res = (char *)smalloc(1024); // buffer bla
00241         strcpy(res, tmp->name);
00242         while (tmp2 && (ht_strncmp(tmp2->name, s, slen)==0)) {
00243 //              fprintf(stdout, "while(%s, %s, %d)\n", tmp2->name, s, slen);
00244                 int a = strccomm(res, tmp2->name);
00245                 res[a] = 0;
00246                 tmp2 = analy->enumSymbols(tmp2);
00247         }
00248         return res;
00249 }
00250 
00251 
00252 /*
00253  *      CLASS CallChain
00254  */
00255 void    CallChain::init(bounds *b, Analyser *Analy, Address *a, char *desc)
00256 {
00257         ht_treeview::init(b, desc);
00258         VIEW_DEBUG_NAME("CallChain");
00259         analy = Analy;
00260         root = createNode(a);
00261 }
00262 
00263 void CallChain_done(CallChainNode *n)
00264 {
00265         while (n) {
00266                 CallChain_done(n->child);
00267                 CallChainNode *temp = n->next;
00268                 free(n);
00269                 n = temp;
00270         }
00271 }
00272 
00273 void    CallChain::done()
00274 {
00275         CallChain_done(root);
00276         ht_treeview::done();
00277 }
00278 
00279 void    CallChain::adjust(void *node, bool expand)
00280 {
00281         ((CallChainNode*)node)->expanded = expand;
00282 }
00283 
00284 CallChainNode *CallChain::createNode(Address *A)
00285 {
00286         CallChainNode *n = (CallChainNode *)smalloc(sizeof(CallChainNode));
00287         n->next = NULL;
00288         n->prev = NULL;
00289         n->child = NULL;
00290         n->examined = false;
00291         n->xa = (Address *)A->duplicate();
00292         n->faddr = analy->getFunctionByAddress(A);
00293         assert(n->faddr);
00294         n->fa = n->faddr->addr;
00295         n->expanded = false;
00296         return n;
00297 }
00298 
00299 void CallChain::examineNode(CallChainNode *n)
00300 {
00301         n->examined = true;
00302         if (has_children(n)) {
00303                 ht_tree *x_tree = n->faddr->xrefs;
00304                 assert(x_tree);
00305                 AddrXRef *x;
00306                 Address *a = (Address *)x_tree->enum_next((Object**)&x, NULL);
00307                 assert(a);
00308                 CallChainNode *nn = n->child = createNode(a);
00309                 while ((a = (Address *)x_tree->enum_next((Object**)&x, a))) {
00310                         nn->next = createNode(a);
00311                         nn = nn->next;
00312                 }
00313         }
00314 }
00315 
00316 void    *CallChain::get_child(void *node, int i)
00317 {
00318         CallChainNode *p;
00319         if (node) {
00320                 if (!((CallChainNode *)node)->examined) examineNode((CallChainNode*)node);
00321                 p = ((CallChainNode *)node)->child;
00322         } else {
00323                 p = root;
00324         }
00325         while (p && (--i)) p = p->next;
00326         return p;
00327 }
00328 
00329 void    *CallChain::get_next_node(void *node)
00330 {
00331         return ((CallChainNode*)node)->next;
00332 }
00333 
00334 void    *CallChain::get_prev_node(void *node)
00335 {
00336         return ((CallChainNode*)node)->prev;
00337 }
00338 
00339 void    *CallChain::get_root()
00340 {
00341         return root;
00342 }
00343 
00344 char    *CallChain::get_text(void *node)
00345 {
00346         static char stupid[1024]; // FIXME: static var
00347         char *s = stupid;
00348         CallChainNode *n=(CallChainNode*)node;
00349         int d = 0;
00350         n->xa->difference(d, n->faddr->addr);
00351         char sign = '+';
00352         if (d<0) {
00353                 d = -d;
00354                 sign = '-';          
00355         }
00356         global_analyser_address_string_format = ADDRESS_STRING_FORMAT_COMPACT | ADDRESS_STRING_FORMAT_ADD_0X;
00357         s+=ht_snprintf(stupid, sizeof stupid, "%s%c%x (%y)", n->faddr->label?n->faddr->label->name:"unknown", sign, d, n->xa);
00358         return stupid;
00359 }
00360 
00361 bool    CallChain::has_children(void *node)
00362 {
00363         return ((CallChainNode*)node)->faddr->xrefs != NULL;
00364 }
00365 
00366 bool    CallChain::is_expanded(void *node)
00367 {
00368         return ((CallChainNode*)node)->expanded;
00369 }
00370 
00371 void    CallChain::select_node(void *node)
00372 {
00373 }
00374 
00375 
00377 
00378 /*
00379  *
00380  */
00381 #define ANALYINFOLINE_DISPLAYFORMAT_LENGTH 1024
00382 void AnalyInfoline::init(bounds *b, ht_aviewer *A, char *Format)
00383 {
00384         ht_statictext::init(b, 0, align_left);
00385         VIEW_DEBUG_NAME("AnalyInfoline");
00386         analy = A;
00387         displayformat = ht_strdup(Format);
00388         s = (char *)smalloc(ANALYINFOLINE_DISPLAYFORMAT_LENGTH);
00389         addr = new InvalidAddress();
00390         fofs = INVALID_FILE_OFS;
00391 }
00392 
00393 void AnalyInfoline::done()
00394 {
00395         free(displayformat);
00396         free(s);
00397         delete addr;
00398         ht_statictext::done();
00399 }
00400 
00401 char *AnalyInfoline::gettext()
00402 {
00403         if (valid()) {
00404                 const char *sec = analy->analy->getSegmentNameByAddress(addr);
00405                 if (fofs != INVALID_FILE_OFS) {
00406                         Location *a = analy->analy->getFunctionByAddress(addr);
00407                         const char *func = analy->analy->getSymbolNameByLocation(a);
00408 
00409                         char *d = displayformat;
00410                         char *ss = s;
00411                         while (*d) {
00412                                 if (*d=='%') {
00413                                         d++;
00414                                         switch (*d) {
00415                                                 case ANALY_STATUS_ARG_SECTION:
00416                                                         if (sec) ss+=ht_snprintf(ss, ANALYINFOLINE_DISPLAYFORMAT_LENGTH-(ss-s), "%s", sec);
00417                                                         break;
00418                                                 case ANALY_STATUS_ARG_FILEOFFSET:
00419                                                         ss+=ht_snprintf(ss, ANALYINFOLINE_DISPLAYFORMAT_LENGTH-(ss-s), "%08x", fofs);
00420                                                         break;
00421                                                 case ANALY_STATUS_ARG_RAW_UNASM: {
00422                                                         int length;
00423                                                         ss+=ht_snprintf(ss, ANALYINFOLINE_DISPLAYFORMAT_LENGTH-(ss-s), "%s", analy->analy->getDisasmStr(addr, length));
00424                                                         break;
00425                                                 }
00426                                                 case ANALY_STATUS_ARG_FUNCTION: {
00427                                                         if (func) {
00428                                                                 int d = 0;
00429                                                                 addr->difference(d, a->addr);
00430                                                                 char sign='+';
00431                                                                 if (d<0) {
00432                                                                         d=-d;
00433                                                                         sign = '-';
00434                                                                 }
00435                                                                 ss+=ht_snprintf(ss, ANALYINFOLINE_DISPLAYFORMAT_LENGTH-(ss-s), "%s%c%x", func, sign, d);
00436                                                         }
00437                                                         break;
00438                                                 }
00439                                                 case ANALY_STATUS_ARG_OFFSET:
00440                                                         global_analyser_address_string_format = ADDRESS_STRING_FORMAT_LEADING_ZEROS;
00441                                                         ss+=ht_snprintf(ss, ANALYINFOLINE_DISPLAYFORMAT_LENGTH-(ss-s), "%y", addr);
00442                                                         break;
00443                                                 case '%':
00444                                                         if (ANALYINFOLINE_DISPLAYFORMAT_LENGTH-(ss-s)) {
00445                                                                 *ss++ = '%';
00446                                                         }
00447                                                         break;
00448                                                 default:
00449                                                         ss += ht_snprintf(ss, ANALYINFOLINE_DISPLAYFORMAT_LENGTH-(ss-s), " error in format ");
00450                                         }
00451                                 } else {
00452                                         if (ANALYINFOLINE_DISPLAYFORMAT_LENGTH-(ss-s)>1) {
00453                                                 // leave space for trailing zero
00454                                                 *ss++ = *d;
00455                                         }
00456                                 }
00457                                 d++;
00458                         }
00459                         *ss = 0;
00460                 } else {
00461                         if (!sec) {
00462                                 ht_snprintf(s, ANALYINFOLINE_DISPLAYFORMAT_LENGTH, "[not in file]");
00463                         } else {
00464                                 ht_snprintf(s, ANALYINFOLINE_DISPLAYFORMAT_LENGTH, "<%s> [not in file]", sec);
00465                         }
00466                 }
00467                 return s;
00468         } else {
00469                 return "<no analyser>";
00470         }
00471 }
00472 
00473 void AnalyInfoline::update(Address *cursor_addr, FILEOFS ecursor_addr)
00474 {
00475         delete addr;
00476         if (valid()) {
00477                 fofs = ecursor_addr;
00478                 addr = (Address *)cursor_addr->duplicate();
00479         } else {
00480                 fofs = INVALID_FILE_OFS;
00481                 addr = new InvalidAddress();
00482         }
00483         dirtyview();
00484         redraw();
00485 }
00486 
00487 bool AnalyInfoline::valid()
00488 {
00489         return ((analy)&&(analy->analy));
00490 }
00491 
00492 /*
00493  *
00494  */
00495 void ht_aviewer::init(bounds *b, char *desc, int caps, ht_streamfile *file, ht_format_group *format_group, Analyser *Analy)
00496 {
00497         analy = Analy;
00498         if (Analy) {
00499                 analy->setDisplayMode(ANALY_SHOW_ADDRESS|ANALY_SHOW_COMMENTS|ANALY_SHOW_LABELS|ANALY_SHOW_XREFS|ANALY_TRANSLATE_SYMBOLS|ANALY_COLLAPSE_XREFS, ANALY_EDIT_BYTES);
00500         }
00501         analy_sub = NULL;
00502         ht_uformat_viewer::init(b, desc, caps, file, format_group);
00503         search_caps |= SEARCHMODE_BIN | SEARCHMODE_EVALSTR | SEARCHMODE_EXPR;
00504         infoline = NULL;
00505         idle_count = 0;
00506         last_active = true;
00507         pause = false;
00508         register_idle_object(this);
00509         one_load_hack = false;
00510 }
00511 
00512 void ht_aviewer::done()
00513 {
00514         unregister_idle_object(this);
00515         ht_uformat_viewer::done();
00516         if (analy) {
00517                 analy->done(); // FIXME: this musnt be here
00518                 delete analy;
00519         }
00520 }
00521 
00522 void ht_aviewer::attachInfoline(AnalyInfoline *V)
00523 {
00524         infoline = V;
00525 }
00526 
00527 bool ht_aviewer::pos_to_offset(viewer_pos p, FILEOFS *ofs)
00528 {
00529         if (analy) {
00530                 Address *addr;
00531                 if (!convertViewerPosToAddress(p, &addr)) return false;
00532                 FILEOFS o=analy->addressToFileofs(addr);
00533                 delete addr;
00534                 if (o!=INVALID_FILE_OFS) {
00535                         *ofs=o;
00536                         return true;
00537                 }
00538         }
00539         return false;
00540 }
00541 
00542 bool ht_aviewer::pos_to_string(viewer_pos p, char *result, int maxlen)
00543 {
00544         if (!analy) return false;
00545         Address *a;
00546         if (!convertViewerPosToAddress(p, &a)) return false;
00547         Location *addr = analy->getLocationByAddress(a);
00548         if (addr && addr->label) {
00549                 // FIXME: strncpy
00550                 ht_snprintf(result, maxlen, "%s", addr->label->name);
00551                 return true;
00552         }
00553         addr = analy->getFunctionByAddress(a);
00554         if (addr && addr->label) {
00555                 int d = 0;
00556                 a->difference(d, addr->addr);
00557                 ht_snprintf(result, maxlen, "%s+0%xh", addr->label->name, d);
00558                 return true;
00559         }
00560         global_analyser_address_string_format = ADDRESS_STRING_FORMAT_LEADING_ZEROS | ADDRESS_STRING_FORMAT_ADD_H;
00561         ht_snprintf(result, maxlen, "%y", a);
00562         return true;
00563 }
00564 
00565 bool ht_aviewer::convertViewerPosToAddress(const viewer_pos &p, Address **a)
00566 {
00567         *a = analy->createAddress();
00568         (*a)->getFromArray((byte*)&(p.u.line_id.id2));
00569         return true;
00570 }
00571 
00572 bool ht_aviewer::convertAddressToViewerPos(Address *a, viewer_pos *p)
00573 {
00574         if (a && a->isValid()) {
00575                 clear_viewer_pos(p);
00576                 p->u.sub = analy_sub;
00577                 a->putIntoArray((byte*)&(p->u.line_id.id2));
00578                 p->u.line_id.id1 = 0;
00579                 return true;
00580         } else {
00581                 return false;
00582         }
00583 }
00584 
00585 char *ht_aviewer::func(UINT i, bool execute)
00586 {
00587         switch (i) {
00588                 case 8: {
00589                         if (execute) {
00590                                 sendmsg(cmd_analyser_symbols);
00591                         }
00592                         return "symbols";
00593                 }
00594                 default:
00595                         return ht_uformat_viewer::func(i, execute);
00596         }
00597         return 0;
00598 }
00599 
00600 static int aviewer_func_addr(eval_scalar *result, eval_str *str)
00601 {
00602         ht_aviewer *aviewer = (ht_aviewer*)eval_get_context();
00603         
00604         Address *addr = aviewer->analy->createAddress();
00605         int l = addr->parseString(str->value, str->len, aviewer->analy);
00606         if (l) {
00607                 // FIXNEW
00608                 qword q = to_qword(0);          
00609                 addr->putIntoArray((byte*)&q);
00610                 scalar_create_int_q(result, q);
00611                 return 1;
00612         } else {
00613                 char buffer[1024];
00614                 bin2str(buffer, str->value, MIN((UINT)str->len, sizeof buffer));
00615                 set_eval_error("invalid address '%s'", buffer);
00616                 return 0;
00617         }
00618 }
00619 
00620 static int aviewer_func_address_of(eval_scalar *result, eval_str *str)
00621 {
00622         ht_aviewer *aviewer = (ht_aviewer*)eval_get_context();
00623         char buffer[1024];
00624         bin2str(buffer, str->value, MIN((UINT)str->len, sizeof buffer));
00625         Symbol *l;
00626         if ((l = aviewer->analy->getSymbolByName(buffer))) {
00627                 // FIXNEW
00628                 qword q = to_qword(0);
00629                 l->location->addr->putIntoArray((byte*)&q);
00630                 scalar_create_int_q(result, q);
00631                 return 1;
00632         } else {
00633                 set_eval_error("invalid label '%s'", buffer);
00634                 return 0;
00635         }
00636 }
00637 
00638 static int aviewer_func_fileofs(eval_scalar *result, eval_int *i)
00639 {
00640         // FIXNEW
00641         ht_aviewer *aviewer = (ht_aviewer*)eval_get_context();
00642         viewer_pos p;
00643         if (aviewer->offset_to_pos(QWORD_GET_INT(i->value), &p)) {
00644                 Address *a;
00645                 qword q = to_qword(0);
00646                 aviewer->convertViewerPosToAddress(p, &a);
00647                 a->putIntoArray((byte*)&q);
00648                 delete a;
00649                 scalar_create_int_q(result, q);
00650                 return 1;
00651         } else {
00652                 set_eval_error("invalid file offset or no corresponding address for '0%xh'", i->value);
00653                 return 0;
00654         }
00655         return 0;
00656 }
00657 
00658 /*
00659  *      for assembler
00660  */
00661 static int ht_aviewer_symbol_to_addr(void *Aviewer, char **s, dword *v)
00662 {
00663         // FIXNEW
00664         ht_aviewer *aviewer = (ht_aviewer*)Aviewer;
00665         Address *a;
00666         if (**s == '@') {
00667                 (*s)++;
00668                 if (bnstr(s, v, 10)) {
00669                         viewer_pos vp;
00670                         if (!aviewer->offset_to_pos(*v, &vp)) {
00671                                 set_eval_error("invalid offset: %08x", v);
00672                                 return false;
00673                         }
00674                         aviewer->convertViewerPosToAddress(vp, &a);
00675                         a->putIntoArray((byte*)v);
00676                         delete a;
00677                         return true;
00678                 }
00679                 // invalid number after @
00680                 return false;
00681         } else {
00682                 char *k=ht_strdup(*s);
00683                 char *t=k;
00684                 while (!strchr("+/-* \t[]", *t) && *t) t++;
00685                 char temp=*t;
00686                 *t=0;
00687                 if ((*k == '$') && (k[1] == 0)) {
00688                         *t=temp;
00689                         *s+= t-k;
00690                         free(k);
00691                         if (aviewer->getCurrentAddress(&a)) {
00692                                 a->putIntoArray((byte*)v);
00693                                 delete a;
00694                                 return true;
00695                         } else {
00696                                 delete a;
00697                                 return false;
00698                         }
00699                 }
00700                 Symbol *l = aviewer->analy->getSymbolByName(k);
00701                 *t=temp;
00702                 if (l) {
00703                         // Label
00704                         *s+=t-k;
00705                         a=l->location->addr;               
00706                         a->putIntoArray((byte*)v);
00707                         free(k);
00708                         return true;
00709                 }
00710                 free(k);
00711         }
00712         return false;
00713 }
00714 
00715 static void setdatastr(ht_view *v, char *str)
00716 {
00717         ht_inputfield_data id;
00718         id.textlen = strlen(str);
00719         id.text = (byte*)str;
00720         v->databuf_set(&id, sizeof id);
00721 }
00722 
00723 static void getdatastr(ht_inputfield_data *id, char *result)
00724 {
00725         memcpy(result, id->text, id->textlen);
00726         result[id->textlen]=0;
00727 }
00728 
00729 struct output_dialog_data {
00730         ht_inputfield_data id1;
00731         ht_listpopup_data lp;
00732         ht_inputfield_data id2;
00733         ht_inputfield_data id3;
00734 };
00735 
00736 void ht_aviewer::generateOutputDialog()
00737 {
00738         if (!analy) return;
00739         if (analy->active) {
00740                 infobox("Please wait until analyser has finished before generating output file!");
00741                 if (analy->active) return;
00742         }
00743 
00744         bounds b;
00745         b.w=50;
00746         b.h=15;
00747         center_bounds(&b);
00748         ht_dialog *dialog;
00749         NEW_OBJECT(dialog, ht_dialog, &b, "generate analyser output", FS_KILLER | FS_TITLE | FS_MOVE);
00750         ht_view *v1, *v2;
00751         BOUNDS_ASSIGN(b, 2, 2, 25, 1);
00752         NEW_OBJECT(v1, ht_strinputfield, &b, 260);
00753         dialog->insert(v1);
00754         BOUNDS_ASSIGN(b, 2, 1, 25, 1);
00755         NEW_OBJECT(v2, ht_label, &b, "output ~filename:", v1);
00756         dialog->insert(v2);
00757 
00758         char pname[HT_NAME_MAX+16];
00759         const char *filename = file->get_filename();
00760         if (filename) {
00761                 pname[HT_NAME_MAX-1] = 0;
00762                 strncpy(pname, filename, HT_NAME_MAX-1);
00763                 char *suffix = sys_filename_suffix(pname);
00764                 if (suffix) {
00765                         strcpy(suffix, "out");
00766                         setdatastr(v1, pname);
00767                 }
00768         }
00769 
00770         BOUNDS_ASSIGN(b, 29, 2, 15, 1);
00771         NEW_OBJECT(v1, ht_listpopup, &b);
00772         ((ht_listpopup*)v1)->insertstring("HTML");
00773         ((ht_listpopup*)v1)->insertstring("plain text");
00774         dialog->insert(v1);
00775         BOUNDS_ASSIGN(b, 29, 1, 15, 1);
00776         NEW_OBJECT(v2, ht_label, &b, "~output format:", v1);
00777         dialog->insert(v2);
00778         BOUNDS_ASSIGN(b, 2, 5, 35, 1);
00779         NEW_OBJECT(v1, ht_strinputfield, &b, 260);
00780         dialog->insert(v1);
00781         BOUNDS_ASSIGN(b, 2, 4, 35, 1);
00782         NEW_OBJECT(v2, ht_label, &b, "~start address:", v1);
00783         viewer_pos cur;
00784         if (get_current_pos(&cur)) {
00785                 char str[1024];
00786                 pos_to_string(cur, str, sizeof str);
00787                 setdatastr(v1, str);
00788         }
00789         dialog->insert(v2);
00790         BOUNDS_ASSIGN(b, 2, 8, 35, 1);
00791         NEW_OBJECT(v1, ht_strinputfield, &b, 260);
00792         dialog->insert(v1);
00793         BOUNDS_ASSIGN(b, 2, 7, 35, 1);
00794         NEW_OBJECT(v2, ht_label, &b, "~end address (or #numberoflines):", v1);
00795         dialog->insert(v2);
00796 //      setdatastr(v1, "#1000");
00797         if (get_current_pos(&cur)) {
00798                 char str[1024];
00799                 pos_to_string(cur, str, sizeof str);
00800                 strcat(str, "+20");
00801                 setdatastr(v1, str);
00802         }
00803         BOUNDS_ASSIGN(b, 13, 11, 9, 2);
00804         NEW_OBJECT(v1, ht_button, &b, "O~k", button_ok);
00805         dialog->insert(v1);
00806         BOUNDS_ASSIGN(b, 27, 11, 9, 2);
00807         NEW_OBJECT(v1, ht_button, &b, "~Cancel", button_cancel);
00808         dialog->insert(v1);
00809         while (dialog->run(false)==button_ok) {
00810                 char filename[260];
00811                 char start_str[1024], end_str[1024];
00812                 viewer_pos start, end;
00813                 bool by_lines;
00814                 output_dialog_data odd;
00815                 dialog->databuf_get(&odd, sizeof odd);
00816                 getdatastr(&odd.id1, filename);
00817                 getdatastr(&odd.id2, start_str);
00818                 getdatastr(&odd.id3, end_str);
00819                 if (!string_to_pos(start_str, &start)) {
00820                         errorbox(globalerror);
00821                         continue;
00822                 }
00823                 UINT end_by_lines;
00824                 if ((by_lines = end_str[0]=='#')) {
00825                         char *pend = &end_str[1];
00826                         bnstr(&pend, &end_by_lines, 10);
00827                 } else {
00828                         if (!string_to_pos(end_str, &end)) {
00829                                 errorbox(globalerror);
00830                                 continue;
00831                         }
00832                 }
00833                 Address *start_addr, *end_addr;
00834                 if (!convertViewerPosToAddress(start, &start_addr) || !convertViewerPosToAddress(end, &end_addr)) {
00835                         errorbox("invalid address");
00836                         continue;
00837                 }
00838                 
00839                 ht_file *s = new ht_file();
00840                 s->init(filename, FAM_WRITE, FOM_CREATE);
00841                 if (s->get_error()) {
00842                         infobox("couldnt create file '%s'.", filename);
00843                         continue;
00844                 } else {
00845                         AnalyserOutput *out;
00846                         switch (odd.lp.cursor_pos) {
00847                                 case 0:
00848                                         out = new AnalyserTxtOutput();
00849                                         ((AnalyserTxtOutput*)out)->init(analy, s);
00850                                         break;
00851                                 case 1:
00852                                         out = new AnalyserTxtOutput();
00853                                         ((AnalyserTxtOutput*)out)->init(analy, s);
00854                                         break;
00855                         }
00856                         out->generateFile(start_addr, end_addr);
00857                         out->done();
00858                         delete out;
00859                 }
00860                 s->done();
00861                 delete s;
00862                 break;
00863         }
00864         dialog->done();
00865         delete dialog;
00866 }
00867 
00868 bool ht_aviewer::canCreateAddress(Address *addr, bool error_msg)
00869 {
00870         Location *ctx = analy->getLocationContextByAddress(addr);
00871         if (ctx && ctx->addr->compareTo(addr)!=0) {
00872                 if (error_msg) {
00873                         global_analyser_address_string_format = ADDRESS_STRING_FORMAT_LEADING_ZEROS;
00874                         errorbox("Can't create new symbol: Address %y belongs to %y (%s)", addr, ctx->addr, ctx->label ? ctx->label->name : "unnamed");
00875                 }
00876                 return false;
00877         }
00878         return true;
00879 }
00880 
00881 void ht_aviewer::dataStringDialog()
00882 {
00883         if (!analy) return;
00884         Address *current_address;
00885         if (!getCurrentAddress(&current_address)) return;
00886         if (!canCreateAddress(current_address, true)) {
00887                 delete current_address;
00888                 return;
00889         }
00890 /*
00891         bounds b;
00892         b.w=50;
00893         b.h=15;
00894         center_bounds(&b);
00895         ht_dialog *dialog;
00896         NEW_OBJECT(dialog, ht_dialog, &b, "interprete data as string", FS_KILLER | FS_TITLE | FS_MOVE);
00897         
00898         while (dialog->run(false)==button_ok) {
00899         }
00900         dialog->done();
00901         delete dialog;*/
00902         
00903         if (analy->validAddress(current_address, scinitialized)) {
00904                 byte buffer[1024];
00905                 Location *a = analy->enumLocations(current_address);
00906                 int d = sizeof buffer;
00907                 if (a) a->addr->difference(d, current_address);
00908                 UINT bz = analy->bufPtr(current_address, buffer, MIN(sizeof buffer, (UINT)d));
00909                 if (bz > 2) {
00910                         analy_string *str = string_test(buffer, bz);
00911                         if (str) {
00912                                 char string1[256], string2[31];
00913                                 str->render_string(string2, sizeof string2);
00914                                 ht_snprintf(string1, sizeof string1, "%s_%s", str->name(), string2);
00915                                 make_valid_name(string2, string1);
00916                                 if (analy->addAddressSymbol(current_address, string2, label_data)) {
00917                                         analy->addComment(current_address, 0, "");
00918                                 }
00919                                 analy->data->setArrayAddressType(current_address, dst_string, str->length());
00920                                 str->done();
00921                                 delete str;
00922                         }
00923                 }
00924         }
00925         delete current_address;
00926 }
00927 
00928 struct export_dialog_data {
00929         ht_inputfield_data id1;
00930         ht_listpopup_data lp;
00931 };
00932 
00933 void ht_aviewer::exportFileDialog()
00934 {
00935         if (!analy) return;
00936         if (analy->active) {
00937                 infobox("Please wait until analyser has finished before exporting file!");
00938                 if (analy->active) return;
00939         }
00940 
00941         bounds b;
00942         b.w=50;
00943         b.h=12;
00944         center_bounds(&b);
00945         ht_dialog *dialog;
00946         NEW_OBJECT(dialog, ht_dialog, &b, "export analyser information", FS_KILLER | FS_TITLE | FS_MOVE);
00947         ht_view *v1, *v2;
00948         BOUNDS_ASSIGN(b, 2, 2, 35, 1);
00949         NEW_OBJECT(v1, ht_strinputfield, &b, 260);
00950         dialog->insert(v1);
00951         BOUNDS_ASSIGN(b, 2, 1, 35, 1);
00952         NEW_OBJECT(v2, ht_label, &b, "output ~filename:", v1);
00953         dialog->insert(v2);
00954 
00955         char pname[HT_NAME_MAX+16];
00956         const char *filename = file->get_filename();
00957         if (filename) {
00958                 pname[HT_NAME_MAX-1] = 0;
00959                 strncpy(pname, filename, HT_NAME_MAX-1);
00960                 char *suffix = sys_filename_suffix(pname);
00961                 if (suffix) {
00962                         strcpy(suffix, "exp");
00963                         setdatastr(v1, pname);
00964                 }
00965         }
00966 
00967         BOUNDS_ASSIGN(b, 2, 5, 25, 1);
00968         NEW_OBJECT(v1, ht_listpopup, &b);
00969         ((ht_listpopup*)v1)->insertstring(".sym symbol file");
00970         dialog->insert(v1);
00971         BOUNDS_ASSIGN(b, 2, 4, 25, 1);
00972         NEW_OBJECT(v2, ht_label, &b, "~export format:", v1);
00973         dialog->insert(v2);
00974         
00975         BOUNDS_ASSIGN(b, 13, 8, 9, 2);
00976         NEW_OBJECT(v1, ht_button, &b, "O~k", button_ok);
00977         dialog->insert(v1);
00978         BOUNDS_ASSIGN(b, 27, 8, 9, 2);
00979         NEW_OBJECT(v1, ht_button, &b, "~Cancel", button_cancel);
00980         dialog->insert(v1);
00981         while (dialog->run(false)==button_ok) {
00982                 char filename[260];
00983                 export_dialog_data edd;
00984                 dialog->databuf_get(&edd, sizeof edd);
00985                 getdatastr(&edd.id1, filename);
00986                 
00987                 ht_file *s = new ht_file();
00988                 s->init(filename, FAM_WRITE, FOM_CREATE);
00989                 if (s->get_error()) {
00990                         infobox("couldnt create file '%s'.", filename);
00991                         continue;
00992                 } else {
00993                         switch (edd.lp.cursor_pos) {
00994                                 case 0:
00995                                         export_to_sym(analy, s);
00996                                         break;
00997                         }
00998                 }
00999                 s->done();
01000                 delete s;
01001                 break;
01002         }
01003         dialog->done();
01004         delete dialog;
01005 }
01006 
01007 bool ht_aviewer::getCurrentAddress(Address **a)
01008 {
01009         viewer_pos vp;
01010         if (!get_current_pos(&vp)) return false;
01011         return convertViewerPosToAddress(vp, a);
01012 }
01013 
01014 bool ht_aviewer::get_current_offset(FILEOFS *ofs)
01015 {
01016         if (ht_uformat_viewer::get_current_offset(ofs)) {
01017                 return true;
01018         } else {
01019                 Address *a;
01020                 if (!getCurrentAddress(&a)) return false;
01021                 *ofs = analy->addressToFileofs(a);
01022                 delete a;
01023                 return *ofs != INVALID_FILE_OFS;
01024         }
01025 }
01026 
01027 bool ht_aviewer::get_hscrollbar_pos(int *pstart, int *psize)
01028 {
01029         if (analy_sub) {
01030                 // FIXNEW
01031 /*              if (analy_sub->highestaddress->difference(s, analy_sub->lowestaddress) && s) {
01032                         int z=MIN(size.h*16, (int)(top.line_id.id1-analy_sub->lowestaddress));
01033                         return scrollbar_pos(top.line_id.id1-analy_sub->lowestaddress, z, s, pstart, psize);
01034                 }*/
01035         }
01036         return false;
01037 }
01038 
01039 void ht_aviewer::get_pindicator_str(char *buf)
01040 {
01041         Address *addr;
01042         if (analy && getCurrentAddress(&addr)) {
01043                 FILEOFS o;
01044                 global_analyser_address_string_format = ADDRESS_STRING_FORMAT_COMPACT;
01045                 if (get_current_offset(&o)) {
01046                         ht_snprintf(buf, 1024, " %y/@%08x%s ", addr, o, (analy->isDirty())?" dirty":"");
01047                 } else {
01048                         ht_snprintf(buf, 1024, " %y%s ", addr, (analy->isDirty())?" dirty":"");
01049                 }
01050                 delete addr;
01051         } else {
01052                 strcpy(buf, "?");
01053         }
01054 }
01055 
01056 bool ht_aviewer::gotoAddress(Address *a, ht_view *source_object)
01057 {
01058         viewer_pos p;
01059         if (analy) {
01060                 if (!analy->validAddress(a, scvalid)) return false;
01061         }
01062         // FIXME: insert a->compare(hi, low address) here
01063         if (convertAddressToViewerPos(a, &p)) {
01064                 return goto_pos(p, source_object);
01065         }
01066         return false;
01067 }
01068 
01069 void ht_aviewer::handlemsg(htmsg *msg)
01070 {
01071         char str[1024];
01072         switch (msg->msg) {
01073                 case msg_contextmenuquery: {
01074                         ht_static_context_menu *m=new ht_static_context_menu();
01075                         m->init("~Analyser");
01076                         m->insert_entry("~Assemble...", "Ctrl-A", cmd_analyser_call_assembler, K_Control_A, 1);
01077                         m->insert_separator();
01078                         ht_static_context_menu *sub=new ht_static_context_menu();
01079                         sub->init("~Control");
01080                         sub->insert_entry("~Information...", 0, cmd_analyser_info, 0, 1);
01081                         sub->insert_separator();
01082                         sub->insert_entry("~Save state", 0, cmd_analyser_save, 0, 1);
01083                         sub->insert_entry("~Export to file...", NULL, cmd_analyser_export_file, 0, 1);
01084                         sub->insert_separator();
01085                         sub->insert_entry("~Continue at address", "c", cmd_analyser_continue, 0, 1);
01086                         sub->insert_entry("~Pause / resume", "p", cmd_analyser_pause_resume, 0, 1);
01087                         m->insert_submenu(sub);
01088                         sub=new ht_static_context_menu();
01089                         sub->init("~Jump");
01090                         sub->insert_entry("~Symbol list", "F8", cmd_analyser_symbols, 0, 1);
01091                         sub->insert_entry("~Function start", "Ctrl-F", cmd_analyser_this_function, K_Control_F, 1);
01092                         sub->insert_entry("Prev ~label", "Ctrl-L", cmd_analyser_previous_label, K_Control_L, 1);
01093                         sub->insert_entry("Follow ~ptr", "f", cmd_analyser_follow, 0, 1);
01094                         m->insert_submenu(sub);
01095                         sub=new ht_static_context_menu();
01096                         sub->init("~Location");
01097                         sub->insert_entry("~Name address (label)...", "n", cmd_analyser_name_addr, 0, 1);
01098                         sub->insert_entry("Edit co~mments", "#", cmd_analyser_comments, 0, 1);
01099                         sub->insert_entry("Show ~xrefs", "x", cmd_analyser_xrefs, 0, 1);
01100                         sub->insert_entry("~Delete location", "Del", cmd_analyser_del_addr_bindings, 0, 1);
01101                         sub->insert_entry("~Callchain", "Ctrl-T", cmd_analyser_call_chain, K_Control_T, 1);
01102                         m->insert_submenu(sub);
01103                         sub=new ht_static_context_menu();
01104                         sub->init("~Data");
01105                         sub->insert_entry("Data ~string", "s", cmd_analyser_data_string, 0, 1);
01106                         m->insert_submenu(sub);
01107                         m->insert_separator();
01108                         m->insert_entry("Symbol reg trace (exp!)", "Alt-Q", cmd_analyser_srt, K_Alt_Q, 1);
01109         
01110                         msg->msg = msg_retval;
01111                         msg->data1.ptr = m;
01112                         return;
01113                 }
01114                 case msg_keypressed:
01115                         switch (msg->data1.integer) {
01116                                 case K_Control_L: {
01117                                         sendmsg(cmd_analyser_previous_label);
01118                                         clearmsg(msg);
01119                                         return;
01120                                 }
01121                                 case K_Control_F: {
01122                                         sendmsg(cmd_analyser_this_function);
01123                                         clearmsg(msg);
01124                                         return;
01125                                 }
01126                                 case K_Control_O: {
01127                                         sendmsg(cmd_analyser_generate_output);
01128                                         clearmsg(msg);
01129                                         return;
01130                                 }
01131                                 case 'c':
01132                                         if (cursor_tag_class == tag_class_sel) {
01133                                                 sendmsg(cmd_analyser_continue);
01134                                                 clearmsg(msg);
01135                                                 return;
01136                                         }
01137                                         break;
01138                                 case '#':
01139                                         sendmsg(cmd_analyser_comments);
01140                                         clearmsg(msg);
01141                                         return;
01142                                 case 'F':
01143                                         if (cursor_tag_class == tag_class_sel) {
01144                                                 sendmsg(cmd_analyser_follow_ex);
01145                                                 clearmsg(msg);
01146                                                 return;
01147                                         }
01148                                         break;
01149                                 case 'f':
01150                                         if (cursor_tag_class == tag_class_sel) {
01151                                                 sendmsg(cmd_analyser_follow);
01152                                                 clearmsg(msg);
01153                                                 return;
01154                                         }
01155                                         break;
01156                                 case 'n':
01157                                         sendmsg(cmd_analyser_name_addr);
01158                                         clearmsg(msg);
01159                                         return;
01160                                 case 'p':
01161                                         sendmsg(cmd_analyser_pause_resume);
01162                                         clearmsg(msg);
01163                                         return;
01164                                 case 's':
01165                                         sendmsg(cmd_analyser_data_string);
01166                                         clearmsg(msg);
01167                                         return;
01168                                 case 'x':
01169                                         sendmsg(cmd_analyser_xrefs);
01170                                         clearmsg(msg);
01171                                         return;
01172                                 case K_Control_D:
01173                                 case K_Delete:
01174                                         sendmsg(cmd_analyser_del_addr_bindings);
01175                                         clearmsg(msg);
01176                                         return;
01177                         }
01178                         break;
01179                 case cmd_analyser_call_assembler: {
01180                         if (!analy) break;
01181                         Assembler *a = analy->createAssembler();
01182                         if (!a) {
01183                                 // FIXME: select assembler for list
01184                                 infobox("no assembler available.");
01185                                 clearmsg(msg);
01186                                 return;
01187                         }
01188                         viewer_pos current_pos;
01189                         Address *current_address;
01190                         if (get_current_pos(&current_pos) && getCurrentAddress(&current_address)) {
01191                                 a->set_imm_eval_proc((int(*)(void *context, char **s, dword *v))ht_aviewer_symbol_to_addr, (void*)this);
01192                                 int want_length;
01193                                 analy->getDisasmStr(current_address, want_length);
01194                                 dialog_assemble(this, current_pos, analy->mapAddr(current_address), a, analy->disasm, analy->getDisasmStrFormatted(current_address), want_length);
01195                                 delete current_address;
01196                         }                       
01197                         a->done();
01198                         delete a;
01199                         clearmsg(msg);
01200                         return;
01201                 }
01202                 case cmd_analyser_this_function: {
01203                         if (!analy) break;
01204                         Address *c;
01205                         if (!getCurrentAddress(&c)) break;
01206                         Location *a = analy->getFunctionByAddress(c);
01207                         if (a) {
01208                                 gotoAddress(a->addr, this);
01209                         } else {
01210                                 global_analyser_address_string_format = ADDRESS_STRING_FORMAT_LEADING_ZEROS;
01211                                 errorbox("Address %y doesn't belong to a function.", c);
01212                         }
01213                         delete c;
01214                         clearmsg(msg);
01215                         return;
01216                 }
01217                 case cmd_analyser_previous_label: {
01218                         if (!analy) break;
01219                         Address *c;
01220                         if (!getCurrentAddress(&c)) break;
01221                         Location *a = analy->getPreviousSymbolByAddress(c);
01222                         if (a) {
01223                                 gotoAddress(a->addr, this);
01224                         } else {
01225                                 global_analyser_address_string_format = ADDRESS_STRING_FORMAT_LEADING_ZEROS;
01226                                 errorbox("Address %y doesn't belong to a symbol.", c);
01227                         }
01228                         delete c;
01229                         clearmsg(msg);
01230                         return;
01231                 }
01232                 case cmd_analyser_continue: {
01233                         if (!analy) break;
01234                         Address *a;
01235                         if (!getCurrentAddress(&a)) break;
01236                         analy->continueAnalysisAt(a);
01237                         delete a;
01238                         analy->makeDirty();
01239                         analy_sub->output->invalidateCache();
01240                         clearmsg(msg);
01241                         return;
01242                 }
01243                 case cmd_analyser_comments: {
01244                         if (!analy) break;
01245                         Address *current_address;
01246                         if (getCurrentAddress(&current_address)) {
01247                                 showComments(current_address);
01248                                 delete current_address;
01249                         }
01250                         clearmsg(msg);
01251                         return;
01252                 }
01253                 case cmd_analyser_name_addr: {
01254                         if (!analy) break;
01255                         Address *addr;
01256                         if (!getCurrentAddress(&addr) || !canCreateAddress(addr, true)) {
01257                                 delete addr;
01258                                 clearmsg(msg);
01259                                 return;
01260                         }
01261                         global_analyser_address_string_format = ADDRESS_STRING_FORMAT_LEADING_ZEROS;
01262                         if (analy->validAddress(addr, scvalid)) {
01263                                 char n[255];
01264                                 Symbol *l = analy->getSymbolByAddress(addr);
01265                                 // FIXME strncpy
01266                                 if (l) ht_snprintf(n, sizeof n, "%s", l->name); else n[0] = 0;
01267                                 ht_snprintf(str, sizeof str, "name for address %y", addr);
01268                                 while (inputbox(str, "~label name:", n, 255, HISTATOM_NAME_ADDR)) {
01269                                         if (n[0]) {
01270                                                 if (valid_name(n)) {
01271                                                         char *n2 = ht_strdup(n);
01272                                                         if (!analy->assignSymbol(addr, n2, (l)?l->type:label_unknown)) {
01273                                                                 l = analy->getSymbolByName(n);
01274                                                                 global_analyser_address_string_format = ADDRESS_STRING_FORMAT_LEADING_ZEROS;
01275                                                                 errorbox("Label '%s' already exists at address %y!", n, l->location->addr);
01276                                                                 free(n2);
01277                                                         } else {
01278                                                                 analy->makeDirty();
01279                                                                 analy_sub->output->invalidateCache();
01280                                                                 break;
01281                                                         }
01282                                                 } else {
01283                                                         global_analyser_address_string_format = ADDRESS_STRING_FORMAT_LEADING_ZEROS;
01284                                                         if (confirmbox("'%s' is an invalid label name.\nMake valid?", n)==button_yes) {
01285                                                                 char n2[255];
01286                                                                 make_valid_name(n2, n);
01287                                                                 strcpy(n, n2);
01288                                                         }
01289                                                 }
01290                                         } else {
01291                                                 if (l) {
01292                                                         // delete label if applicable
01293                                                         global_analyser_address_string_format = ADDRESS_STRING_FORMAT_LEADING_ZEROS;
01294                                                         if (confirmbox("Really delete label '%s' at address %y?", l->name, addr)==button_yes) {
01295                                                                 analy->deleteSymbol(addr);
01296                                                                 analy->makeDirty();
01297                                                                 analy_sub->output->invalidateCache();
01298                                                         }
01299                                                 }
01300                                                 break;
01301                                         }
01302                                 }
01303                         } else {
01304                                 global_analyser_address_string_format = ADDRESS_STRING_FORMAT_LEADING_ZEROS;
01305                                 errorbox("Address %y is invalid!", addr);
01306                         }
01307                         delete addr;
01308                         clearmsg(msg);
01309                         return;
01310                 }
01311                 case cmd_analyser_xrefs: {
01312                         if (!analy) break;
01313                         Address *a;
01314                         if (!getCurrentAddress(&a)) break;
01315                         showXRefs(a);
01316                         delete a;
01317                         clearmsg(msg);
01318                         return;
01319                 }
01320                 case cmd_analyser_follow: {
01321                         if (!analy) break;
01322                         Address *c, *b;
01323                         if (!getCurrentAddress(&c)) break;
01324                         b = analy->createAddress();
01325                         UINT bz = b->byteSize();
01326                         byte *buf = (byte*)smalloc(bz);
01327                         if (analy->bufPtr(c, buf, bz) != bz) break;
01328                         b->getFromArray(buf);
01329                         if (analy->validAddress(b, scvalid)) {
01330                                 gotoAddress(b, this);
01331                         } else {
01332                                 global_analyser_address_string_format = ADDRESS_STRING_FORMAT_LEADING_ZEROS;
01333                                 errorbox("Follow: address %y is invalid!", b);
01334                         }
01335                         clearmsg(msg);
01336                         return;
01337                 }
01338                 case cmd_analyser_follow_ex:
01339                         if (!analy) break;
01340                         clearmsg(msg);
01341                         return;
01342                 case cmd_analyser_pause_resume:
01343                         if (!analy) break;
01344                         pause = !pause;
01345                         clearmsg(msg);
01346                         return;
01347                 case cmd_analyser_del_addr_bindings: {
01348                         if (!analy) break;
01349                         Address *addr;
01350                         global_analyser_address_string_format = ADDRESS_STRING_FORMAT_LEADING_ZEROS;
01351                         if (getCurrentAddress(&addr)) {
01352                                 if (confirmbox("Forget about address' %y bindings?\n(name, comments, xrefs, etc.)", addr)==button_yes) {
01353                                         analy->deleteLocation(addr);
01354                                         analy->makeDirty();
01355                                         analy_sub->output->invalidateCache();
01356                                 }
01357                                 delete addr;
01358                         }
01359                         clearmsg(msg);
01360                         return;
01361                 }
01362                 case cmd_analyser_generate_output:
01363                         if (!analy) break;
01364                         generateOutputDialog();
01365                         clearmsg(msg);
01366                         return;
01367                 case cmd_analyser_export_file:
01368                         if (!analy) break;
01369                         exportFileDialog();
01370                         clearmsg(msg);
01371                         return;
01372                 case cmd_analyser_data_string:
01373                         if (!analy) break;
01374                         dataStringDialog();
01375                         analy->makeDirty();
01376                         analy_sub->output->invalidateCache();
01377                         dirtyview();
01378                         clearmsg(msg);
01379                         return;
01380                 case cmd_analyser_info:
01381                         if (!analy) break;
01382                         Address *current_address;
01383                         if (!getCurrentAddress(&current_address)) {
01384                                 showInfo(0);
01385                         } else {
01386                                 showInfo(current_address);
01387                                 delete current_address;
01388                         }
01389                         dirtyview();
01390                         clearmsg(msg);               
01391                         return;
01392                 case cmd_analyser_symbols: {
01393                         Address *current_address;
01394                         if (!getCurrentAddress(&current_address)) return;
01395                         showSymbols(current_address);
01396                         delete current_address;
01397                         clearmsg(msg);
01398                         return;
01399                 }
01400                 case cmd_edit_mode:
01401                 case cmd_view_mode:
01402                         if (analy) {
01403                                 if (edit()) {
01404                                         analy->setDisplayMode(ANALY_EDIT_BYTES, 0);
01405                                 } else {
01406                                         analy->setDisplayMode(0, ANALY_EDIT_BYTES);
01407                                 }
01408                         }
01409                         analy_sub->output->invalidateCache();
01410                         break;
01411                 case msg_file_changed: {
01412                         analy_sub->output->invalidateCache();
01413                         break;
01414                 }
01415                 case cmd_analyser_call_chain: {
01416                         if (!analy) break;
01417                         Address *addr;
01418                         if (getCurrentAddress(&addr)) {
01419                                 showCallChain(addr);
01420                                 delete addr;
01421                         }
01422                         return;
01423                 }
01424                 /* FIXME: srt-experimental */
01425                 case cmd_analyser_srt: {
01426                         Address *current_addr;
01427                         if (getCurrentAddress(&current_addr)) {
01428                                 test_srt(analy, current_addr);
01429                                 delete current_addr;
01430                         }
01431                         clearmsg(msg);
01432                         return;
01433                 }
01434                 case msg_get_analyser: {
01435                         msg->msg=msg_retval;
01436                         msg->data1.ptr=analy;
01437                         return;
01438                 }
01439                 case msg_set_analyser: {
01440                         Analyser *a=(Analyser*)msg->data1.ptr;
01441                         if (analy) {
01442                                 analy->done();
01443                                 delete analy;
01444                         }
01445                         a->setDisplayMode(0, ANALY_EDIT_BYTES);
01446                         setAnalyser(a);
01447                         analy_sub->output->invalidateCache();
01448                         clearmsg(msg);
01449                         one_load_hack = true;
01450                         return;
01451                 }
01452                 case msg_postinit: {
01453                         if (analy && !one_load_hack) {
01454                                 analy->beginAnalysis();
01455                                 analy_sub->output->invalidateCache();
01456                         }
01457                         return;
01458                 }
01459         }
01460         ht_uformat_viewer::handlemsg(msg);
01461         switch (msg->msg) {
01462                 case msg_draw:
01463                         if (infoline) {
01464                                 FILEOFS a;
01465                                 Address *addr;
01466                                 if (!getCurrentAddress(&addr)) {
01467                                         addr = new InvalidAddress();
01468                                 }
01469                                 infoline->update(addr, (get_current_real_offset(&a)) ? a : INVALID_FILE_OFS);
01470                                 delete addr;
01471                         }
01472                         break;
01473         }
01474 }
01475 
01476 bool ht_aviewer::idle()
01477 {
01478         if (!analy) return false;
01479         last_active=analy->active;
01480         if (!pause) analy->continueAnalysis();
01481         if (last_active && !analy->active) {
01482                 LOG("%s: analyser finished after %d ops.", analy->getName(), analy->ops_parsed);
01483                 dirtyview();
01484                 app->sendmsg(msg_draw, 0);
01485         }
01486         idle_count++;
01487 /*      if (idle_count % 565 == 0) {
01488                 analy_sub->output->invalidateCache();
01489                 dirtyview();
01490                 app->sendmsg(msg_draw, 0);
01491         }*/
01492         if (analy->active) {
01493                 if (idle_count%53==0) {
01494                         analy_sub->output->invalidateCache();
01495                         dirtyview();
01496                         app->sendmsg(msg_draw, 0);
01497                 }
01498         }
01499         return last_active && !pause;
01500 }
01501 
01502 bool ht_aviewer::offset_to_pos(FILEOFS ofs, viewer_pos *p)
01503 {
01504         if (!analy) return false;
01505         Address *a = analy->fileofsToAddress(ofs);
01506         bool res = convertAddressToViewerPos(a, p);
01507         delete a;
01508         return res;
01509 }
01510 
01511 int ht_aviewer::ref_sel(LINE_ID *id)
01512 {
01513         if ((id->id1 | id->id2 |  id->id3 |id->id4) == 0) return 0;
01514         switch (id->id4) {
01515                 case 0:
01516                         if (analy) {
01517                                 Address *a = analy->createAddress();
01518                                 a->getFromArray((byte*)&id->id1);
01519                                 bool res = gotoAddress(a, this);
01520                                 delete a;
01521                                 return res;
01522                         } else {
01523                                 return 0;
01524                         }
01525                 case 1:
01526                         if (analy) {
01527                                 Address *a = analy->createAddress();
01528                                 a->getFromArray((byte*)&id->id1);
01529                                 showXRefs(a);
01530                                 delete a;
01531                         }
01532                         return 0;
01533         }
01534         return 0;
01535 }
01536 
01537 void ht_aviewer::reloadpalette()
01538 {
01539         ht_uformat_viewer::reloadpalette();
01540         if (analy_sub) analy_sub->output->changeConfig();
01541 }
01542 
01543 void ht_aviewer::searchForXRefs(Address *Addr)
01544 {
01545 // FIXME: viewer_pos && FIXNEW
01546         char str[100];
01547         global_analyser_address_string_format = ADDRESS_STRING_FORMAT_COMPACT;
01548         ht_snprintf(str, sizeof str, "%y", Addr);
01549         ht_regex_search_request *q=new ht_regex_search_request(SC_VISUAL, SF_REGEX_CASEINSENSITIVE, str);
01550         viewer_pos vp_start, vp_end;
01551         convertAddressToViewerPos(analy_sub->lowestaddress, &vp_start);
01552         convertAddressToViewerPos(analy_sub->highestaddress, &vp_end);
01553         int oldmode = analy->getDisplayMode();
01554         analy->setDisplayMode(0, -1);
01555         analy_sub->output->invalidateCache();
01556         ht_visual_search_result *r = (ht_visual_search_result *)vsearch(q, vp_start, vp_end);
01557         while (r) {
01558                 Address *to;
01559                 convertViewerPosToAddress(r->pos, &to);
01560                 analy->addXRef(Addr, to, xrefoffset);
01561                 viewer_pos na;
01562                 next_logical_pos(r->pos, &na);
01563                 delete to;
01564                 delete r;
01565                 r = (ht_visual_search_result *)vsearch(q, na, vp_end);
01566         }
01567         analy->setDisplayMode(oldmode, -1);
01568         analy->makeDirty();
01569         analy_sub->output->invalidateCache();
01570         delete q;
01571 }
01572 
01573 void ht_aviewer::showCallChain(Address *Addr)
01574 {
01575         Location *a = analy->getFunctionByAddress(Addr);
01576         if (!a) return;
01577         bounds b;
01578         b.w = 60;
01579         b.h = 16;
01580         center_bounds(&b);
01581         char str[256];
01582         global_analyser_address_string_format = ADDRESS_STRING_FORMAT_LEADING_ZEROS;
01583         ht_snprintf(str, sizeof str, "call chain of address %y", Addr);
01584         ht_dialog *dialog = new ht_dialog();
01585         dialog->init(&b, str, FS_KILLER | FS_TITLE | FS_MOVE);
01586         BOUNDS_ASSIGN(b, 1, 0, 56, 10);
01587         ht_statictext *text = new ht_statictext();
01588         if (a->label) {
01589                 ht_snprintf(str, sizeof str, "function %s %s", a->label->name, "is referenced by ..");
01590         } else {
01591                 ht_snprintf(str, sizeof str, "address %y %s", a->addr, "is referenced by ..");
01592         }
01593         text->init(&b, str, align_left);
01594         dialog->insert(text);
01595         BOUNDS_ASSIGN(b, 1, 1, 56, 10);
01596         CallChain *cc;
01597         NEW_OBJECT(cc, CallChain, &b, analy, Addr, NULL);
01598         cc->adjust(cc->get_root(), true);
01599         dialog->insert(cc);
01600         BOUNDS_ASSIGN(b, 15, 12, 9, 2);
01601         ht_button *bt;
01602         NEW_OBJECT(bt, ht_button, &b, "O~k", button_ok);
01603         dialog->insert(bt);
01604         BOUNDS_ASSIGN(b, 35, 12, 9, 2);
01605         NEW_OBJECT(bt, ht_button, &b, "~Cancel", button_cancel);
01606         dialog->insert(bt);
01607         int r = dialog->run(false);
01608         if (r == button_ok) {
01609                 ht_treeview_data tvd;
01610                 dialog->databuf_get(&tvd, sizeof tvd);
01611                 gotoAddress(((CallChainNode*)tvd.selected)->xa, this);
01612         }
01613         dialog->done();
01614         delete dialog;
01615 }
01616 
01617 void ht_aviewer::showComments(Address *Addr)
01618 {
01619         if (!analy) return;
01620         if (!canCreateAddress(Addr, true)) {
01621                 return;
01622         }
01623         CommentList *comment = analy->getComments(Addr);
01624 
01625         // prepare mem_file
01626         ht_mem_file *mem_file = new ht_mem_file();
01627         mem_file->init();
01628         if (comment) {
01629                 int c1 = comment->count();
01630                 for (int i=0; i < c1; i++) {
01631                         const char *c = comment->getName(i);
01632                         int len = strlen(c);
01633                         if (len) mem_file->write(c, len);
01634                         if (i+1<c1) mem_file->write((void*)"\n", 1);
01635                 }
01636         }
01637         
01638 /*     ht_c_syntax_lexer *lexer = new ht_c_syntax_lexer();
01639         lexer->init();*/
01640         
01641         // prepare textfile
01642         ht_ltextfile *text_file = new ht_ltextfile();
01643         text_file->init(mem_file, true, NULL);
01644 
01645         // create dialog
01646         bounds b;
01647         b.w = 60;
01648         b.h = 16;
01649         center_bounds(&b);
01650         ht_dialog *dialog = new ht_dialog();
01651         dialog->init(&b, "edit comments", FS_KILLER | FS_TITLE | FS_MOVE);
01652 
01653         BOUNDS_ASSIGN(b, 1, 1, 55, 10);
01654         ht_text_editor *text_editor = new ht_text_editor();
01655         text_editor->init(&b, false, text_file, NULL, TEXTEDITOPT_UNDO);
01656         dialog->insert(text_editor);
01657 
01658         /* FIXME: scrollbar
01659         BOUNDS_ASSIGN(b, 56, 1, 1, 10);
01660         */
01661         
01662         ht_button *b1;
01663         BOUNDS_ASSIGN(b, 18, 12, 9, 2);
01664         NEW_OBJECT(b1, ht_button, &b, "O~k", button_ok);
01665         dialog->insert(b1);
01666         BOUNDS_ASSIGN(b, 32, 12, 9, 2);
01667         NEW_OBJECT(b1, ht_button, &b, "~Cancel", button_cancel);
01668         dialog->insert(b1);
01669 
01670         if (dialog->run(false)==button_ok) {
01671                 Location *a=analy->getLocationByAddress(Addr);
01672                 if (a) analy->freeComments(a);
01673                 UINT c=text_file->linecount();
01674                 char buf[1024];
01675                 bool empty=false;
01676                 if (c==1) {
01677                         UINT l = 0;
01678                         text_file->getline(0, 0, buf, 1024, &l, NULL);
01679                         empty=(l==0);
01680                 }
01681                 if (!empty) {
01682                         for (UINT i=0; i<c; i++) {
01683                                 UINT l;
01684                                 if (text_file->getline(i, 0, buf, 1024, &l, NULL)) {
01685                                         buf[l]=0;
01686                                         analy->addComment(Addr, 0, buf);
01687                                 }
01688                         }
01689                 }
01690                 analy->makeDirty();
01691                 analy_sub->output->invalidateCache();
01692         }
01693 
01694         dialog->done();
01695         delete dialog;
01696         text_file->done();
01697         delete text_file;
01698 }
01699 
01700 void ht_aviewer::showInfo(Address *Addr)
01701 {
01702         bounds c, b;
01703         app->getbounds(&c);
01704         b.w=c.w*5/6;
01705         b.h=c.h*5/6;
01706         center_bounds(&b);
01707         char str[100];
01708         strcpy(str, "Analyser information");
01709         ht_dialog *dialog = new ht_dialog();
01710         dialog->init(&b, str, FS_KILLER | FS_TITLE | FS_MOVE);
01711         BOUNDS_ASSIGN(b, 1, 0, b.w-4, 10);
01712         AnalyserInformation *text = new AnalyserInformation();
01713         text->init(&b, this);
01714         dialog->insert(text);
01715         
01716         dialog->run(false);
01717         
01718         dialog->done();
01719         delete dialog;
01720 }
01721 
01722 void ht_aviewer::showSymbols(Address *addr)
01723 {
01724         if (!analy) return;
01725         
01726         Location *loc = analy->getPreviousSymbolByAddress(addr);
01727                                 
01728         bounds b;
01729         b.w = 60;
01730         b.h = 15;
01731         center_bounds(&b);
01732         ht_dialog *dialog = new ht_dialog();
01733         dialog->init(&b, "symbols", FS_KILLER | FS_TITLE | FS_MOVE | FS_RESIZE);
01734         /* pull down */
01735         BOUNDS_ASSIGN(b, 30, 0, 20, 1);
01736 /*                              ht_listpopup *lp = new ht_listpopup();
01737                                 lp->init(&b);
01738                                 lp->insertstring("show all");
01739                                 lp->insertstring("only functions");
01740                                 lp->insertstring("only labels");
01741                                 lp->insertstring("only offsets (code)");
01742                                 lp->insertstring("only data");
01743                                 dialog->insert(lp);*/
01744         /* text */
01745         BOUNDS_ASSIGN(b, 1, 0, 56, 1);
01746         ht_listbox_title *text = new ht_listbox_title();
01747         text->init(&b);
01748         text->setText(3, "Address", "Type", "Name");
01749         /* list */
01750         BOUNDS_ASSIGN(b, 1, 1, 56, 12);
01751         SymbolBox *sym = new SymbolBox();
01752         sym->init(&b, analy);
01753         if (loc && loc->label) {
01754                 sym->gotoItemByEntry(sym->quickfind(loc->label->name));
01755         }
01756         dialog->insert(sym);
01757         dialog->insert(text);
01758         sym->attachTitle(text);
01759         register_idle_object(sym);
01760         int r = dialog->run(false);
01761         unregister_idle_object(sym);
01762         if (r == button_ok) {
01763                 // goto selected symbol
01764                 ht_listbox_data d;
01765                 sym->databuf_get(&d, sizeof d);
01766                 if (d.cursor_ptr) gotoAddress(((Symbol *)d.cursor_ptr)->location->addr, this);
01767         }
01768         dialog->done();
01769         delete dialog;
01770 }
01771 
01772 void ht_aviewer::showXRefs(Address *Addr)
01773 {
01774         ht_tree *x_tree = analy->getXRefs(Addr);
01775         if (x_tree) {
01776 restart2:
01777                 bounds c, b;
01778                 app->getbounds(&c);
01779                 b.w = c.w*5/6;
01780                 b.h = c.h*5/6;
01781                 center_bounds(&b);
01782 restart:
01783                 UINT bw = b.w;
01784                 UINT bh = b.h;
01785                 char str[256];
01786                 global_analyser_address_string_format = ADDRESS_STRING_FORMAT_LEADING_ZEROS;
01787                 ht_snprintf(str, sizeof str, "xrefs of address %y", Addr);
01788                 ht_dialog *dialog = new ht_dialog();
01789                 dialog->init(&b, str, FS_KILLER | FS_TITLE | FS_MOVE | FS_RESIZE);
01790                 BOUNDS_ASSIGN(b, 1, 0, bw-4, 1);
01791                 ht_listbox_title *text = new ht_listbox_title();
01792                 text->init(&b);
01793                 text->setText(3, "xref to", "type", "from function");
01794                 b.y = 1;          
01795                 b.h = bh-6;
01796                 ht_text_listbox *list;
01797                 NEW_OBJECT(list, ht_text_listbox, &b, 3, 2);
01798                 BOUNDS_ASSIGN(b, 2, bh-4, 26, 2);
01799                 ht_button *search_for_xrefs;
01800                 NEW_OBJECT(search_for_xrefs, ht_button, &b, "~Search for more XRefs", 666);
01801                 search_for_xrefs->growmode = MK_GM(GMH_LEFT, GMV_BOTTOM);
01802                 BOUNDS_ASSIGN(b, 29, bh-4, 11, 2);
01803                 ht_button *delete_xref;
01804                 NEW_OBJECT(delete_xref, ht_button, &b, "~Delete", 667);
01805                 delete_xref->growmode = MK_GM(GMH_LEFT, GMV_BOTTOM);
01806                 // FIXME: disable button when possible
01807                 BOUNDS_ASSIGN(b, 41, bh-4, 10, 2);
01808                 ht_button *new_xref;
01809                 NEW_OBJECT(new_xref, ht_button, &b, "~Add", 668);
01810                 new_xref->growmode = MK_GM(GMH_LEFT, GMV_BOTTOM);
01811                 char str2[1024];
01812                 AddrXRef *x;
01813                 Address *xa = (Address*)x_tree->enum_next((Object**)&x, NULL);
01814                 int xcount=0;
01815                 while (xa) {
01816                         xcount++;
01817                         ht_snprintf(str, sizeof str, "%y", xa);
01818                         Location *a = analy->getFunctionByAddress(xa);
01819                         const char *func = analy->getSymbolNameByLocation(a);
01820                         if (func) {
01821                                 int d=0;
01822                                 xa->difference(d, a->addr);
01823                                 char sign='+';
01824                                 if (d<0) {
01825                                         d=-d;
01826                                         sign='-';
01827                                 }
01828                                 ht_snprintf(str2, sizeof str2, "%s%c%x", func, sign, d);
01829                         } else {
01830                                 strcpy(str2, "?");
01831                         }
01832                         list->insert_str((int)xa, str, xref_type(x->type), str2);
01833                         xa = (Address*)x_tree->enum_next((Object**)&x, xa);
01834                 }
01835                 list->attachTitle(text);
01836                 list->update();
01837                 dialog->insert(text);
01838                 dialog->insert(list);
01839                 dialog->insert(search_for_xrefs);
01840                 dialog->insert(delete_xref);
01841                 dialog->insert(new_xref);
01842                 int r = dialog->run(false);
01843                 ht_listbox_data data;
01844                 list->databuf_get(&data, sizeof data);
01845                 switch (r) {
01846                         case 666:
01847                                 searchForXRefs(Addr);
01848                                 break;
01849                         case 667:
01850                                 if (xcount) {
01851                                         analy->deleteXRef(Addr, (Address*)list->getID(data.cursor_ptr));
01852                                         analy->makeDirty();
01853                                         analy_sub->output->invalidateCache();
01854                                 }
01855                                 break;
01856                         case 668: {
01857                                 char result[256];
01858                                 ht_snprintf(str, sizeof str, "add xref from %y", Addr);
01859                                 result[0] = 0;
01860                                 while (inputbox(str, "to ~address: ", result, 255, HISTATOM_GOTO)) {
01861                                         viewer_pos res_pos;
01862                                         if (!string_to_pos(result, &res_pos)) {
01863                                                 errorbox(globalerror);
01864                                                 continue;
01865                                         }
01866                                         Address *a;
01867                                         if (!convertViewerPosToAddress(res_pos, &a)) {
01868                                                 errorbox("invalid address");
01869                                                 delete a;
01870                                                 continue;
01871                                         }
01872                                         if (!analy->addXRef(Addr, a, xrefoffset)) {
01873                                                 // FIXME: some error msg
01874                                         }
01875                                         delete a;
01876                                         analy->makeDirty();
01877                                         analy_sub->output->invalidateCache();
01878                                         break;
01879                                 }
01880                                 break;
01881                         }
01882                         case button_ok:
01883                                 if (xcount) gotoAddress((Address*)list->getID(data.cursor_ptr), this);
01884                                 break;
01885                 }
01886                 dialog->getbounds(&b);
01887                 dialog->done();
01888                 delete dialog;
01889                 if ((r >= 666) && (r <= 668)) goto restart;
01890         } else {
01891                 if (confirmbox("No xrefs for address %y!\nSearch for xrefs?", Addr)==button_yes) {
01892                         searchForXRefs(Addr);
01893                         x_tree = analy->getXRefs(Addr);
01894                         if (x_tree) goto restart2;
01895                 }
01896         }
01897 }
01898 
01899 int ht_aviewer::func_handler(eval_scalar *result, char *name, eval_scalarlist *params)
01900 {
01901         eval_func myfuncs[] = {
01902                 {"addressOf", (void*)&aviewer_func_address_of, {SCALAR_STR}},
01903                 {"fileofs", (void*)&aviewer_func_fileofs, {SCALAR_INT}},
01904                 {"addr", (void*)&aviewer_func_addr, {SCALAR_STR}},
01905                 {NULL}
01906         };
01907         if (std_eval_func_handler(result, name, params, myfuncs)) return 1;
01908         return ht_uformat_viewer::func_handler(result, name, params);
01909 }
01910 
01911 int ht_aviewer::symbol_handler(eval_scalar *result, char *name)
01912 {
01913         qword v;
01914         viewer_pos vp;
01915         Address *w;
01916         if (*name == '@') {
01917                 name++;
01918                 if (bnstr(&name, &v, 10)) {
01919                         if (*name) return 0;
01920                         // FIXME: no QWORD_GET_LO
01921                         if (!offset_to_pos(QWORD_GET_LO(v), &vp)) {
01922                                 set_eval_error("invalid offset: %08x", v);
01923                                 return 0;
01924                         }
01925                         convertViewerPosToAddress(vp, &w);
01926                         qword b = to_qword(0);
01927                         w->putIntoArray((byte*)&b);
01928                         delete w;
01929                         scalar_create_int_q(result, b);
01930                         return 1;
01931                 }
01932                 // invalid number after @
01933         } else {
01934                 if (strcmp(name, "$")==0) {
01935                         if (getCurrentAddress(&w)) {
01936                                 qword b = to_qword(0);
01937                                 w->putIntoArray((byte*)&b);
01938                                 scalar_create_int_q(result, b);
01939                                 delete w;
01940                                 return 1;
01941                         } else {
01942                                 delete w;
01943                                 return 0;
01944                         }
01945                 }
01946                 Symbol *l = analy->getSymbolByName(name);
01947                 if (l) {
01948                         w=l->location->addr;
01949                         qword b;
01950                         w->putIntoArray((byte*)&b);
01951                         scalar_create_int_q(result, b);
01952                         return 1;
01953                 }
01954         }
01955         return ht_uformat_viewer::symbol_handler(result, name);
01956 }
01957         
01958 bool ht_aviewer::qword_to_pos(qword q, viewer_pos *pos)
01959 {
01960         if (!analy) return false;
01961         Address *a=analy->createAddress();
01962         // FIXME: this is just plain wrong!!
01963         if (a->byteSize()==8) {
01964                 a->getFromArray((byte*)&q);
01965         } else {
01966                 dword ii = QWORD_GET_INT(q);
01967                 a->getFromArray((byte*)&ii);
01968         }
01969         if (analy->validAddress(a, scvalid)) {
01970                 bool res = convertAddressToViewerPos(a, pos);
01971                 delete a;
01972                 return res;
01973         } else {
01974                 global_analyser_address_string_format = ADDRESS_STRING_FORMAT_LEADING_ZEROS;
01975                 ht_snprintf(globalerror, GLOBAL_ERROR_SIZE, "address %y is invalid", a);
01976         }
01977         delete a;
01978         return false;
01979 }
01980 
01981 /*
01982  *      CLASS ht_analy_sub
01983  */
01984 
01985 void ht_analy_sub::init(ht_streamfile *file, ht_aviewer *A, Analyser *analyser, Address *Lowestaddress, Address *Highestaddress)
01986 {
01987         ht_sub::init(file);
01988         aviewer = A;
01989         analy = analyser;
01990         output = new AnalyserHTOutput();
01991         ((AnalyserHTOutput*)output)->init(analy);
01992         lowestaddress = (Address *)Lowestaddress->duplicate();
01993         highestaddress = (Address *)Highestaddress->duplicate();
01994 }
01995 
01996 void ht_analy_sub::done()
01997 {
01998         delete lowestaddress;
01999         delete highestaddress;
02000         output->done();
02001         delete output;
02002         ht_sub::done();
02003 }
02004 
02005 bool ht_analy_sub::closest_line_id(LINE_ID *line_id)
02006 {
02007         if (!prev_line_id(line_id, 1)) {
02008                 if (!next_line_id(line_id, 1)) {
02009                         first_line_id(line_id);
02010                 }
02011         }
02012         return true;
02013 }
02014 
02015 bool ht_analy_sub::convert_ofs_to_id(const FILEOFS offset, LINE_ID *line_id)
02016 {
02017         viewer_pos a;
02018         if (!uformat_viewer->offset_to_pos(offset, &a)) return false;
02019         *line_id = a.u.line_id;
02020         return true;
02021 }
02022 
02023 void    ht_analy_sub::first_line_id(LINE_ID *line_id)
02024 {
02025         clear_line_id(line_id);
02026         lowestaddress->putIntoArray((byte*)&(line_id->id2));
02027 }
02028 
02029 bool ht_analy_sub::getline(char *line, const LINE_ID line_id)
02030 {
02031         if (!analy) return false;
02032         Address *a = analy->createAddress();
02033         a->getFromArray((byte*)&(line_id.id2));
02034         bool res = output->getLineString(line, 1024, a, (int)line_id.id1);
02035         delete a;
02036         return res;
02037 }
02038 
02039 void    ht_analy_sub::last_line_id(LINE_ID *line_id)
02040 {
02041         clear_line_id(line_id);
02042         highestaddress->putIntoArray((byte*)&(line_id->id2));
02043 }
02044 
02045 int ht_analy_sub::next_line_id(LINE_ID *line_id, int n)
02046 {
02047         if (!analy) return false;
02048         Address *a = analy->createAddress();
02049         a->getFromArray((byte*)&(line_id->id2));
02050         int line = line_id->id1;
02051         int res = output->nextLine(a, line, n, highestaddress);
02052         if (res) {
02053                 line_id->id1 = line;
02054                 a->putIntoArray((byte*)&(line_id->id2));
02055         }
02056         delete a;
02057         return res;
02058 }
02059 
02060 int     ht_analy_sub::prev_line_id(LINE_ID *line_id, int n)
02061 {
02062         if (!analy) return false;
02063         Address *a = analy->createAddress();
02064         a->getFromArray((byte*)&(line_id->id2));
02065         int line = line_id->id1;
02066         int res = output->prevLine(a, line, n, lowestaddress);
02067         if (res) {
02068                 line_id->id1 = line;
02069                 a->putIntoArray((byte*)&(line_id->id2));
02070         }
02071         delete a;
02072         return res;
02073 }
02074 
02075 ht_search_result *ht_analy_sub::search(ht_search_request *search, FILEOFS start, FILEOFS end)
02076 {
02077 // FIXME: viewer pos     
02078         Address *st = NULL;
02079         ht_search_result *r = NULL;
02080         while (!r) {
02081                 st = (Address *)analy->initialized->findNext(st);
02082                 if (!st) break;
02083                 area_s *s = analy->initialized->getArea(st);
02084                 if (!s) break;
02085                 st = (Address *)s->end;
02086                 FILEOFS fstart, fend;
02087                 dword fsize;
02088                 viewer_pos vp_start, vp_end;
02089                 aviewer->convertAddressToViewerPos((Address *)s->start, &vp_start);
02090                 if (!aviewer->pos_to_offset(vp_start, &fstart)) assert(0);
02091                 Address *send = (Address *)s->end->duplicate();
02092                 send->add(-1);
02093                 aviewer->convertAddressToViewerPos(send, &vp_end);
02094                 delete send;
02095                 if (!aviewer->pos_to_offset(vp_end, &fend)) assert(0);
02096                 fsize = fend-fstart;
02097                 if ((search->search_class==SC_PHYSICAL) && (search->type==ST_EXPR)) {
02098                         r = linear_expr_search(search, start, end, this, uformat_viewer, fstart, fsize);
02099                 } else if ((search->search_class==SC_PHYSICAL) && (search->type==ST_FXBIN)) {
02100                         r = linear_bin_search(search, start, end, file, fstart, fsize);
02101                 }
02102         }
02103         return r;
02104 }
02105 
02106 void    ht_analy_sub::setAnalyser(Analyser *Analy)
02107 {
02108         analy = Analy;
02109         output->analy = Analy;
02110         output->invalidateCache();
02111 }
02112 
02113 

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