#include <u.h>
#include <libc.h>
#include <bio.h>
#include <ctype.h>
#include <mach.h>
#define Extern extern
#include "acid.h"
#include "y.tab.h"

char afmt = 'X';
static int syren;

Lsym*
unique(char *buf, Sym *s)
{
       Lsym *l;
       int i, renamed;

       renamed = 0;
       strcpy(buf, s->name);
       for(;;) {
               l = look(buf);
               if(l == 0 || (l->lexval == Tid && l->v->set == 0))
                       break;

               if(syren == 0 && !quiet) {
                       print("Symbol renames:\n");
                       syren = 1;
               }
               i = strlen(buf)+1;
               memmove(buf+1, buf, i);
               buf[0] = '$';
               renamed++;
               if(renamed > 5 && !quiet) {
                       print("Too many renames; must be X source!\n");
                       break;
               }
       }
       if(renamed && !quiet)
               print("\t%s=%s %c/%llux\n", s->name, buf, s->type, s->value);
       if(l == 0)
               l = enter(buf, Tid);
       return l;
}

void
varsym(void)
{
       int i;
       Sym *s;
       long n;
       Lsym *l;
       uvlong v;
       char buf[1024];
       List *list, **tail, *l2, *tl;

       tail = &l2;
       l2 = 0;

       symbase(&n);
       for(i = 0; i < n; i++) {
               s = getsym(i);
               switch(s->type) {
               case 'T':
               case 'L':
               case 'D':
               case 'B':
               case 'b':
               case 'd':
               case 'l':
               case 't':
                       if(s->name[0] == '.')
                               continue;

                       if(strlen(s->name) >= sizeof(buf)-6){
                               if(!quiet)
                                       print("Symbol name too long: %s\n", s->name);
                               continue;
                       }

                       v = s->value;
                       tl = al(TLIST);
                       *tail = tl;
                       tail = &tl->next;

                       l = unique(buf, s);

                       l->v->set = 1;
                       l->v->type = TINT;
                       l->v->ival = v;
                       if(l->v->comt == 0)
                               l->v->fmt = 'A';

                       /* Enter as list of { name, type, value } */
                       list = al(TSTRING);
                       tl->l = list;
                       list->string = strnode(buf);
                       list->fmt = 's';
                       list->next = al(TINT);
                       list = list->next;
                       list->fmt = 'c';
                       list->ival = s->type;
                       list->next = al(TINT);
                       list = list->next;
                       list->fmt = l->v->fmt;
                       list->ival = v;

               }
       }
       l = mkvar("symbols");
       l->v->set = 1;
       l->v->type = TLIST;
       l->v->l = l2;
       if(l2 == 0)
               print("no symbol information\n");
}

void
varreg(void)
{
       Lsym *l;
       Value *v;
       Reglist *r;
       List **tail, *li;

       if(mach->szaddr == 8){
               afmt = 'Y';
               fsize['a'] = fsize[afmt];
               fsize['A'] = fsize[afmt];
       }

       l = mkvar("registers");
       v = l->v;
       v->set = 1;
       v->type = TLIST;
       v->l = 0;
       tail = &v->l;

       for(r = mach->reglist; r->rname; r++) {
               l = mkvar(r->rname);
               v = l->v;
               v->set = 1;
               v->ival = r->roffs;
               v->fmt = r->rformat;
               v->type = TINT;

               li = al(TSTRING);
               li->string = strnode(r->rname);
               li->fmt = 's';
               *tail = li;
               tail = &li->next;
       }

       if(machdata == 0)
               return;

       l = mkvar("bpinst");    /* Breakpoint text */
       v = l->v;
       v->type = TSTRING;
       v->fmt = 's';
       v->set = 1;
       v->string = gmalloc(sizeof(String));
       v->string->len = machdata->bpsize;
       v->string->string = gmalloc(machdata->bpsize);
       memmove(v->string->string, machdata->bpinst, machdata->bpsize);
}

void
loadvars(void)
{
       Lsym *l;
       Value *v;

       l =  mkvar("proc");
       v = l->v;
       v->type = TINT;
       v->fmt = 'X';
       v->set = 1;
       v->ival = 0;

       l = mkvar("pid");               /* Current process */
       v = l->v;
       v->type = TINT;
       v->fmt = 'D';
       v->set = 1;
       v->ival = 0;

       mkvar("notes");                 /* Pending notes */

       l = mkvar("proclist");          /* Attached processes */
       l->v->type = TLIST;
       l->v->set = 1;
}

uvlong
rget(Map *map, char *reg)
{
       Lsym *s;
       ulong x;
       uvlong v;
       int ret;

       s = look(reg);
       if(s == 0)
               fatal("rget: %s\n", reg);

       switch(s->v->fmt){
       default:
               ret = get4(map, s->v->ival, &x);
               v = x;
               break;
       case 'V':
       case 'W':
       case 'Y':
       case 'Z':
               ret = get8(map, s->v->ival, &v);
               break;
       }
       if(ret < 0)
               error("can't get register %s: %r", reg);
       return v;
}

String*
strnodlen(char *name, int len)
{
       String *s;

       s = gmalloc(sizeof(String)+len+1);
       s->string = (char*)s+sizeof(String);
       s->len = len;
       if(name != 0)
               memmove(s->string, name, len);
       s->string[len] = '\0';

       s->gclink = gcl;
       gcl = s;

       return s;
}

String*
strnode(char *name)
{
       return strnodlen(name, strlen(name));
}

String*
runenode(Rune *name)
{
       int len;
       Rune *p;
       String *s;

       p = name;
       for(len = 0; *p; p++)
               len++;

       len++;
       len *= sizeof(Rune);
       s = gmalloc(sizeof(String)+len);
       s->string = (char*)s+sizeof(String);
       s->len = len;
       memmove(s->string, name, len);

       s->gclink = gcl;
       gcl = s;

       return s;
}

String*
stradd(String *l, String *r)
{
       int len;
       String *s;

       len = l->len+r->len;
       s = gmalloc(sizeof(String)+len+1);
       s->gclink = gcl;
       gcl = s;
       s->len = len;
       s->string = (char*)s+sizeof(String);
       memmove(s->string, l->string, l->len);
       memmove(s->string+l->len, r->string, r->len);
       s->string[s->len] = 0;
       return s;
}

String*
straddrune(String *l, Rune r)
{
       int len;
       String *s;

       len = l->len+runelen(r);
       s = gmalloc(sizeof(String)+len+1);
       s->gclink = gcl;
       gcl = s;
       s->len = len;
       s->string = (char*)s+sizeof(String);
       memmove(s->string, l->string, l->len);
       runetochar(s->string+l->len, &r);
       s->string[s->len] = 0;
       return s;
}

int
scmp(String *sr, String *sl)
{
       if(sr->len != sl->len)
               return 0;

       if(memcmp(sr->string, sl->string, sl->len))
               return 0;

       return 1;
}