⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tracer.c

📁 realview22.rar
💻 C
📖 第 1 页 / 共 5 页
字号:
    /* else shouldn't occur - return 0 */
    else 
    {
#ifdef VERBOSE
        printf("pop_uint32 - we shouldn't be here - Uh oh!!!!\n");
#endif
        return 0;
    }
}


static void push_u32_const_func(Expr1 e1, Expr1DataItem * data, Trace_Packet * packet)
{
    IGNORE(packet);
    push_uint32(e1, data->u32);
}

static void push_instr_const_func(Expr1 e1, Expr1DataItem * data, Trace_Packet * packet)
{
    IGNORE(data);
    IGNORE(packet);
    push_instr(e1);
}

static void push_pc_const_func(Expr1 e1, Expr1DataItem * data, Trace_Packet * packet)
{
    IGNORE(packet);
    IGNORE(data);
    push_pc(e1);
}


/* Returns 1 if (i1 > i2) else 0. */
static int ident_bigger(Expr1Ident *i1, Expr1Ident *i2)
{
        assert(i1->name!=NULL && i2->name!=NULL);
    return (strcmp(i1->name,i2->name)>0);
}


/* Does string compare of i1, i2. */
static int ident_name_eq(Expr1Ident *i1, char const *name)
{
  int size;
  assert(i1 != NULL && i1->name!=NULL && name!=NULL);
#ifdef VERBOSE
  printf("Comparing %s with ident %s\n",name, i1->name);
#endif
/* added to ensure that == and != get compared properly. */
  size = strlen(name);
  return (strncmp(i1->name,name,size)==0);

}


static Expr1Ident *findoper(Expr1 e1, char const *itxt)
{
    CVector *v1 = &e1->idents;
    unsigned i, n = CVector_Count(v1);
#ifdef VERBOSE
    printf("findoper: Vector_Count = %u, text = %s\n",n, itxt);
#endif
    for (i = 0; i < n; i++)
    {
        if (ident_name_eq(CVector_At(v1,i),itxt))
             return CVector_At(v1,i); 
   }
    return NULL;
}


/* Insert into e1->idents, sorted.
 * (where longer strings come after shorter ones. ) */
static void add_ident(Expr1 e1, Expr1Ident *i1)
{
    CVector *v1 = &e1->idents;
    unsigned i, n = CVector_Count(v1);
    for (i = 0; i < n; i++)
    {
        if (ident_bigger(CVector_At(v1,i),i1))
            break;
    }
    CVector_Insert(v1,i,i1);
}

static void add_binop(Expr1 e1,char const *opname ,Expr1Func *func, int pri)
{
    Expr1Ident i1;
    memset(&i1,0,sizeof(i1));
    i1.name = opname;
    /* Grouping L to R gives lpri > rpri. */
    i1.lpri = pri * 2 + 1;
    i1.rpri = pri * 2;
    i1.func = func;
    add_ident(e1,&i1);
}


/* These all group L to R.
 * Low pri is more important in expression evaluation */
#define OP_LIST \
    BINOP(*,u32times,2)\
    BINOP(/,u32divide,2)\
    BINOP(%,u32mod,2)\
    BINOP(+,u32plus,3) \
    BINOP(-,u32minus,3)\
    BINOP(<<,u32lsh,4)\
    BINOP(>>,u32rsh,4)\
    BINOP(==,u32eq,6)\
    BINOP(!=,u32ne,6)\
    BINOP(>=,u32ge,5)\
    BINOP(<=,u32le,5)\
    BINOP(>,u32gt,5)\
    BINOP(<,u32lt,5)\
    BINOP(||, u32lor,10) \
    BINOP(&&, u32land, 10) \
    BINOP(&,u32and,7)\
    BINOP(^,u32xor,8)\
    BINOP(|,u32or,9)

/* DECLARE FUNCTIONS */
/* to ensure operators like << and >> work, have to pop d2, then d1 */
#define BINOP(opername,funcname,pri) \
static void funcname(Expr1 e1, Expr1DataItem *pd, Trace_Packet *packet) {\
  uint32 d2 = pop_uint32(e1,packet);  uint32 d1 = pop_uint32(e1,packet); \
  uint32 d3 = (d1 opername d2); \
  push_uint32(e1, d3); (void)pd;  }

/* removed print line to prevent compile warnings */
/*  printf("%u %s %u -> %u\n", d1,stringify(opername),d2,d3);  
*/

OP_LIST
#undef BINOP

#define BINOP(opername,funcname,pri) \
   add_binop(e1,stringify(opername),funcname,pri);


#define UNOP(opname, func, lpri, rpri) \
  add_op(e1, opname, func, lpri, rpri, NULL)

#define SKIPWS  while(NOT_END && *txt <= ' ') {txt++;}
#define NOT_END  (*txt && *txt != '\n')

static int isident(int c)
{
    return isalnum(c) || c=='_';
}

static void emitCode(Expr1 e1, Expr1Ident *i1)
{
    Expr1Codon c1;
    c1.func = i1->func;
    c1.data = i1->data;
        c1.name = i1->name;
#ifdef VERBOSE
    printf("emitCode ID:%s\n", i1->name ? i1->name : "ANON");
#endif
    CVector_Append(&e1->code,&c1);
}

static char const *parse1(char const *txt, Expr1 e1, char *errbuf, size_t errbuf_size)
{
    Expr1Ident i1;
    Expr1Ident *i2;
    int masterpri = 0; /* used to cope with brackets */
    
        (void)errbuf_size; /* Shame */

    SKIPWS;
    while (NOT_END)
    {
#ifdef VERBOSE
    printf("\nparse1 txt='%s'\n", txt);
#endif

/* isdigit takes an int, not a char*. Windows doesn't mind being passed
   a char*, but solaris does. So use an explicit cast to compile 
   This not very elegant, but works. */
        if (isdigit((int)*txt)) 
        {
            char numtxt[513]; 
            char *dst = numtxt; 
            char *dst2 = numtxt;
            /* Eat a number */
            while (isalnum((int)*txt))
            {
                *dst++ = *txt++;
            }
            *dst=0;
            i1 = NumericConstantID;
            i1.data.Datatype = Value;
            i1.data.u32 = strtoul(numtxt, &dst2, 0);
            i2= &i1;
#ifdef VERBOSE
            printf("Scanned numeric constant value %u\n", (unsigned)i1.data.u32);
#endif
        }
        else if (isident(*txt))
        {
            /* Eat an ident */
            char itxt[513]; char *dst = itxt;
            /* Eat a number */
/*            while (isalnum(*txt)) */
            while (isalnum((int)*txt))
            {
                *dst++ = *txt++;
            }
            *dst=0;
#ifdef VERBOSE
            printf("Scanned ident <%s>\n", itxt);
#endif
            if ((i2 = findoper(e1, itxt))!= NULL)
            {
                /* OK */
            }
            else
            {
#ifdef VERBOSE
                printf("Oper not found, assuming string %s\n",itxt);
#endif
                /* if oper not found, then we have a string */
                /* the only valid strings are pc, instr */
                /* NB: strcmp returns 0 for success! */
                if (strcmp(itxt,"instr") == 0) {
                    i1 = NumericConstantInstr;
                    i1.data.u32 = 0;
                    i1.data.Datatype = Instruction;
                    i2 =& i1;
                } else if (strcmp(itxt,"pc") == 0) {
                    i1 = NumericConstantPC;
                    i1.data.u32 = 0;
                    i1.data.Datatype = PC;
                    i2 =& i1;
                } else {              
#ifdef VERBOSE
                    printf("Invalid String: %s, ABORT\n",itxt);
                    exit(-2);
#endif
                }
            }
        }
        else
        {
            /* Get longest operator/punctuation we can */
            char itxt[513]; 
            char *dst = itxt;
            Expr1Ident *i3 = NULL;
            do {
                i2 = i3;
                *dst++ = *txt++;
                *dst=0;
#ifdef VERBOSE
                printf("Seeking op '%s'\n", itxt);
#endif
            } while ( (i3 = findoper(e1, itxt)) != NULL && NOT_END);
            if (i3 == NULL)
            {  /* NULL means that we haven't found an op */
                if (itxt[0]=='(')
                {
                    masterpri -= 20;
                    continue; /*skip to next character on input */
                } else if (itxt[0]==')')
                {
                    masterpri += 20;
                    continue; /*skip to next character on input */
                }
            } 

#ifdef VERBOSE
            printf("Found op '%s'\n", itxt);
#endif
            if (i2)
            {
                --txt;
            }
            else 
            {
                sprintf(errbuf,"No such op:%s\n",itxt);
                return txt;
            }
        } /* end if block*/
        SKIPWS;
        /* !WIP!
         * While new operator is less immediate than what's on on our
         *  operator-stack, pop these onto the code[].
         */
        { 
          unsigned n = CVector_Count(&e1->parseStack);
          /* !This assumes *i2 has been copied! */
          i2->lpri += masterpri;
          i2->rpri += masterpri;

          while(n != 0)
          {
              Expr1Ident *i3 = CVector_At(&e1->parseStack, --n);
              /* Lower pri happens first */
              if (i3->rpri < i2->lpri)
              {
                  /* Code the operation */
                  emitCode(e1,i3);
                  /* Drop it off the stack. */
                  CVector_Pop(&e1->parseStack,i3);
              }
              else
              { 
                break;
              }
          }
          
        }
        assert(i2!=NULL);
#ifdef VERBOSE
        printf("ParseStacking %s, new stack depth = %u\n", i2->name, CVector_Count(&e1->parseStack));   
#endif
        /* Then stack new operator. */
        CVector_Append(&e1->parseStack, i2);
        /* !WIP EOF should be a max-pri operator. */
    }  /* end while*/

    /* all stacked operators should now be stored on the code stack. */
    {
      unsigned n = CVector_Count(&e1->parseStack);
      while( n != 0 ) 
        {
          Expr1Ident *i4 = CVector_At(&e1->parseStack, --n);
          emitCode(e1,i4);
          CVector_Pop(&e1->parseStack, i4);
        }
    }

    return txt;
}

Expr1 Expr1_ParseString(char const *txt, char *errbuf, size_t errbuf_size)
{
    Expr1 e1 = Expr1_New();
   /* Trace_Packet *packet;*/
    /* Fill in builtins */
    OP_LIST;
/* - no longer needed - brackets coped with using priorities, not functions.
    UNOP("(",NULL,0,99);
    UNOP(")",NULL,99,0);
*/
    /* Parse each token until the end of the string, */
    (void)parse1(txt,e1,errbuf, errbuf_size);

#ifdef VERBOSE
    printf("Expr1_ParseString after parse1");
#endif

    if (*txt >= ' ' && !*errbuf)
    {
        strncpy(errbuf,"Syntax error",errbuf_size);
    }
    return e1;
}

#undef BINOP

/* need packet to pass to evaluation of instr, pc */
uint32 Expr1_EvalUint32(Expr1 e1, Trace_Packet *packet)
{
    /* + Clear the data-stack? */
    unsigned i, n = CVector_Count(&e1->code);
#ifdef VERYVERBOSE
    printf("Expr1_EvalUint32 n:%u\n", n);
    printf("Number of elements captured: %u\n", CVector_Count(&e1->parseStack));
#endif
    for (i = 0; i < n; i++)
    {
        Expr1Codon *c1 = CVector_At(&e1->code,i);
#ifdef VERYVERBOSE
        printf("Looping: i=%d, data value = %u\n",i, c1->data.u32);
#endif
        if (c1 != NULL) {
          c1->func(e1,&c1->data, packet);
        } else {
#ifdef WARN
          printf("WARNING: CVector_At returned a NULL pointer\n");
#endif
        }
    }
    /* Pop the single data item off the stack and return
     * it as a uint32 */
    return (pop_uint32(e1, packet));
}


/* !Todo: If we've copied strings, clear them too.! */
void Expr1_Destroy(Expr1 *p_e1)
{
    if (p_e1 && *p_e1)
    {
        Expr1 e1 = *p_e1;
        CVector_Clear(&e1->idents);
        CVector_Clear(&e1->code);
        CVector_Clear(&e1->dataStack);
        CVector_Clear(&e1->parseStack);
        free(e1);
        *p_e1 = NULL;
    }
}

/* END conditional trace functions */
/***********************************/
/***********************************/


/*
 * The trace function generates a stream of packets, which are either
 * logged into a file or sent to a socket.
 */

static char *cb_proc(
    dis_cb_type t, int32 offset, unsigned32 addr, int width, void *arg,
    char *buf)
{
  UNUSEDARG(t); UNUSEDARG(offset); UNUSEDARG(addr); UNUSEDARG(width); UNUSEDARG(arg);
  return buf;
}

static int Tracer_Acc(ATracer *as, ARMul_acc acc, unsigned32 addr,
                      int packet_type)
{
  TracerState *ts = as->ts;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -