1635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com#include "lightsymbols.h"
2635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com
3635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.comLightSymbol::PLightSymbol LightSymbol::lsFrames[1000];
4635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.comHANDLE LightSymbol::handleFrames[1000];
5635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.comSZ* LightSymbol::fileNames;
6635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.combool LightSymbol::busted = false;
7635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com
8635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com
9635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.comLightSymbol::LightSymbol(const char* sym, int fileId, int lineNumber) {
10635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  while (busted) {
11635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    busted = busted;
12635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  }
13635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  this->sym = sym;
14635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  this->fileId = fileId;
15635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  this->lineNumber = lineNumber;
16635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com
17635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  LightSymbol** container = getThreadFrameContainer();
18635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com
19635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  parentFrame = *container;
20635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  *container = this; // shortcut for get+set current frame
21635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com}
22635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com
23635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.comLightSymbol::~LightSymbol() {
24635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com
25635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com// assert  if (GetCurrentFrame() != this) {
26635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com
27635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  SetCurrentFrame(parentFrame);
28635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com}
29635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com
30635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.combool LightSymbol::GetCallStack(char* sz, int len, const char* separator) {
31635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  LightSymbol* ls = GetCurrentFrame();
32635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  if (ls == 0) {
33635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    return false;
34635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  } else {
35635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    return ls->GetCallStackCore(sz, len, separator);
36635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  }
37635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com}
38635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com
39635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.comLightSymbol** LightSymbol::getThreadFrameContainer() {
40635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  //pthread_t t = pthread_self();
41635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  HANDLE h = (HANDLE)GetCurrentThreadId(); // f, keep handle so I don't have to recompie tyhe whole app; update toi DWORD one I really need changes in header file
42635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  int i = 0;
43635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  while (handleFrames[i] != h && handleFrames[i] != NULL && i < 1000 - 1) {
44635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    i++;
45635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  }
46635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  if (handleFrames[i] == h) {
47635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    return &lsFrames[i];
48635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  }
49635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  handleFrames[i] = h;
50635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  return &lsFrames[i];
51635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com}
52635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com
53635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.combool LightSymbol::GetCallStackCore(char* sz, int len, const char* separator) const {
54635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  if (busted) {
55635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    return false;
56635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  }
57635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  if (fileNames == NULL) { // f multithreading synchr
58635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    FILE* log = fopen("d:\\edisonn\\log.txt", "wt");
59635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com
60635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    if (log) { fprintf(log, "build\n");fflush(log); }
61635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com
62635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    char szLine[10000];
63635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    FILE* file = fopen(getenv(LIGHT_SYMBOLS_FILE), "rt");
64635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    if (file == NULL) {
65635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com      busted = true;
66635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com      return false;
67635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    }
68635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com
69635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    const char* trimed;
70635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com
71635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    // count number of lines
72635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    int id;
73635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    int entries = 0;
74635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    while (true) {
75635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com      id = -1;
76635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com      if (fscanf(file, "%i", &id) == 0) break;
77635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com      if (id == -1) break;
78635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com      if (entries <= id + 1) {
79635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com        entries = id + 1;
80635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com      }
81635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com      *szLine = '\0';
82635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com      fgets(szLine, 10000, file);
83635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com      trimed = trim(szLine);
84635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    }
85635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com
86635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    fclose(file);
87635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    file = fopen(getenv(LIGHT_SYMBOLS_FILE), "rt");
88635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    if (file == NULL) {
89635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com      busted = true;
90635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com      return false; // f this
91635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    }
92635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com
93635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    if (log) { fprintf(log, "entries: %i\n", entries);fflush(log); }
94635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com
95635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    SZ* __fileNames = new SZ[entries];
96635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com
97635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    while (true) {
98635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com      id = -1;
99635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com      if (fscanf(file, "%i", &id) == 0) break;
100635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com      if (id == -1) break;
101635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com      *szLine = '\0';
102635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com      fgets(szLine, 10000, file);
103635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com      trimed = trim(szLine);
104635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com
105635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com      if (log) { fprintf(log, "%i, %s", id, trimed); }
106635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com
107635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com      // ass u me the file is correct
108635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com
109635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com      __fileNames[id] = new char[strlen(trimed) + 1];
110635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com      if (log) { fprintf(log, " - ");fflush(log); }
111635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com      strcpy(__fileNames[id], trimed);
112635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com      if (log) { fprintf(log, " _ \n");fflush(log); }
113635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    }
114635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    fclose(file);
115635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    fileNames = __fileNames;
116635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    if (log) { fclose(log); }
117635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  }
118635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com
119635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  const LightSymbol* ls = this;
120635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  char* szOut = sz;
121635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  // f security
122635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  while (ls != NULL && len > 1000) {
123635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    sprintf(szOut, "%s, %s:%i%s", ls->sym, fileNames[ls->fileId], ls->lineNumber, separator);
124635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    while (*szOut && len > 0) {
125635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com      szOut++;
126635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com      len--;
127635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    }
128635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    ls = ls->parentFrame;
129635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  }
130635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com
131635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  int more = 0;
132635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  while (ls != NULL) {
133635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    ls = ls->parentFrame;
134635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  }
135635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com
136635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  if (more > 0) {
137635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    sprintf(szOut, " ... %i more frames. allocate more memory!", more);
138635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  }
139635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com
140635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  return true;
141635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com}
142635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com
143635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.comLightSymbol* LightSymbol::GetCurrentFrame() {
144635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  return *getThreadFrameContainer();
145635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com}
146635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com
147635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.comvoid LightSymbol::SetCurrentFrame(LightSymbol* ls) {
148635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  *getThreadFrameContainer() = ls;
149635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com}
150635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com
151635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.comconst char* LightSymbol::trim(char* sz) {
152635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  if (sz == NULL) return NULL;
153635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com
154635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  while (*sz == ' ' || *sz == '\t' || *sz == '\r' || *sz == '\n' || *sz == ',')
155635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    sz++;
156635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com
157635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  if (*sz == '\0') return sz;
158635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com
159635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  int len = strlen(sz);
160635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  char* start = sz;
161635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  sz = sz + (len - 1);
162635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com
163635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  while (sz >= start && (*sz == ' ' || *sz == '\t' || *sz == '\r' || *sz == '\n' || *sz == ',')) {
164635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    *sz = '\0';
165635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com    sz--;
166635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  }
167635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com
168635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com  return start;
169635c331b29ae9c9be8e0e4059881558acd660cc9edisonn@google.com}
170