#include "proj.h"
#include "where.h"
#include "lex.h"
#include "malloc.h"
#include "ggc.h"
struct _ffewhere_line_ ffewhere_unknown_line_
=
{NULL, NULL, 0, 0, 0, {0}};
typedef struct _ffewhere_ll_ *ffewhereLL_;
struct _ffewhere_ll_
{
ffewhereLL_ next;
ffewhereLL_ previous;
ffewhereFile wf;
ffewhereLineNumber line_no;
ffewhereLineNumber offset;
};
struct _ffewhere_root_ll_
{
ffewhereLL_ first;
ffewhereLL_ last;
};
struct _ffewhere_root_line_
{
ffewhereLine first;
ffewhereLine last;
ffewhereLineNumber none;
};
static struct _ffewhere_root_ll_ ffewhere_root_ll_;
static struct _ffewhere_root_line_ ffewhere_root_line_;
static ffewhereLL_ ffewhere_ll_lookup_ (ffewhereLineNumber ln);
static ffewhereLL_
ffewhere_ll_lookup_ (ffewhereLineNumber ln)
{
ffewhereLL_ ll;
if (ln == 0)
return ffewhere_root_ll_.first;
for (ll = ffewhere_root_ll_.last;
ll != (ffewhereLL_) &ffewhere_root_ll_.first;
ll = ll->previous)
{
if (ll->line_no <= ln)
return ll;
}
assert ("no line num" == NULL);
return NULL;
}
#define NUM_FFEWHERE_HEAD_FILES 31
static struct ffewhere_ggc_tracker
{
struct ffewhere_ggc_tracker *next;
ffewhereFile files[NUM_FFEWHERE_HEAD_FILES];
} *ffewhere_head = NULL;
static void
mark_ffewhere_head (void *arg)
{
struct ffewhere_ggc_tracker *head;
int i;
for (head = * (struct ffewhere_ggc_tracker **) arg;
head != NULL;
head = head->next)
{
ggc_mark (head);
for (i = 0; i < NUM_FFEWHERE_HEAD_FILES; i++)
ggc_mark (head->files[i]);
}
}
void
ffewhere_file_kill (ffewhereFile wf)
{
struct ffewhere_ggc_tracker *head;
int i;
for (head = ffewhere_head; head != NULL; head = head->next)
for (i = 0; i < NUM_FFEWHERE_HEAD_FILES; i++)
if (head->files[i] == wf)
{
head->files[i] = NULL;
return;
}
abort();
}
ffewhereFile
ffewhere_file_new (const char *name, size_t length)
{
ffewhereFile wf;
int filepos;
wf = ggc_alloc (offsetof (struct _ffewhere_file_, text)
+ length + 1);
wf->length = length;
memcpy (&wf->text[0], name, length);
wf->text[length] = '\0';
if (ffewhere_head == NULL)
{
ggc_add_root (&ffewhere_head, 1, sizeof ffewhere_head,
mark_ffewhere_head);
filepos = NUM_FFEWHERE_HEAD_FILES;
}
else
{
for (filepos = 0; filepos < NUM_FFEWHERE_HEAD_FILES; filepos++)
if (ffewhere_head->files[filepos] == NULL)
{
ffewhere_head->files[filepos] = wf;
break;
}
}
if (filepos == NUM_FFEWHERE_HEAD_FILES)
{
struct ffewhere_ggc_tracker *old_head = ffewhere_head;
int i;
ffewhere_head = ggc_alloc (sizeof (*ffewhere_head));
ffewhere_head->next = old_head;
ffewhere_head->files[0] = wf;
for (i = 1; i < NUM_FFEWHERE_HEAD_FILES; i++)
ffewhere_head->files[i] = NULL;
}
return wf;
}
void
ffewhere_file_set (ffewhereFile wf, bool have_num, ffewhereLineNumber ln)
{
ffewhereLL_ ll;
ll = malloc_new_kp (ffe_pool_file (), "ffewhereLL_", sizeof (*ll));
ll->next = (ffewhereLL_) &ffewhere_root_ll_.first;
ll->previous = ffewhere_root_ll_.last;
ll->next->previous = ll;
ll->previous->next = ll;
if (wf == NULL)
{
if (ll->previous == ll->next)
ll->wf = NULL;
else
ll->wf = ll->previous->wf;
}
else
ll->wf = wf;
ll->line_no = ffelex_line_number ();
if (have_num)
ll->offset = ln;
else
{
if (ll->previous == ll->next)
ll->offset = 1;
else
ll->offset
= ll->line_no - ll->previous->line_no + ll->previous->offset;
}
}
void
ffewhere_init_1 ()
{
ffewhere_root_line_.first = ffewhere_root_line_.last
= (ffewhereLine) &ffewhere_root_line_.first;
ffewhere_root_line_.none = 0;
ffewhere_root_ll_.first = ffewhere_root_ll_.last
= (ffewhereLL_) &ffewhere_root_ll_.first;
}
char *
ffewhere_line_content (ffewhereLine wl)
{
assert (wl != NULL);
return wl->content;
}
ffewhereFile
ffewhere_line_file (ffewhereLine wl)
{
ffewhereLL_ ll;
assert (wl != NULL);
ll = ffewhere_ll_lookup_ (wl->line_num);
return ll->wf;
}
ffewhereLineNumber
ffewhere_line_filelinenum (ffewhereLine wl)
{
ffewhereLL_ ll;
assert (wl != NULL);
ll = ffewhere_ll_lookup_ (wl->line_num);
return wl->line_num + ll->offset - ll->line_no;
}
void
ffewhere_line_kill (ffewhereLine wl)
{
#if 0
if (!ffewhere_line_is_unknown (wl))
fprintf (dmpout, "; ffewhere_line_kill %" ffewhereLineNumber_f "u, uses=%"
ffewhereUses_f_ "u\n",
wl->line_num, wl->uses);
#endif
assert (ffewhere_line_is_unknown (wl) || (wl->uses != 0));
if (!ffewhere_line_is_unknown (wl) && (--wl->uses == 0))
{
wl->previous->next = wl->next;
wl->next->previous = wl->previous;
malloc_kill_ks (ffe_pool_file (), wl,
offsetof (struct _ffewhere_line_, content)
+ wl->length + 1);
}
}
ffewhereLine
ffewhere_line_new (ffewhereLineNumber ln)
{
ffewhereLine wl = ffewhere_root_line_.last;
if (((ln == 0)
|| (wl->line_num != ln))
&& (ffelex_line_number () == ln))
{
#if 0
fprintf (dmpout,
"; ffewhere_line_new %" ffewhereLineNumber_f "u, lexer\n",
ln);
#endif
wl = malloc_new_ks (ffe_pool_file (), "FFEWHERE line",
offsetof (struct _ffewhere_line_, content)
+ (size_t) ffelex_line_length () + 1);
wl->next = (ffewhereLine) &ffewhere_root_line_;
wl->previous = ffewhere_root_line_.last;
wl->previous->next = wl;
wl->next->previous = wl;
wl->line_num = ln;
wl->uses = 1;
wl->length = ffelex_line_length ();
strcpy (wl->content, ffelex_line ());
return wl;
}
while (wl->line_num > ln)
wl = wl->previous;
if (wl->line_num == ln)
{
#if 0
fprintf (dmpout, "; ffewhere_line_new %" ffewhereLineNumber_f "u, uses=%"
ffewhereUses_f_ "u\n", ln,
wl->uses);
#endif
wl->uses++;
return wl;
}
fprintf (stderr,
"(Cannot resurrect line %lu for error reporting purposes.)\n",
ln);
wl = malloc_new_ks (ffe_pool_file (), "FFEWHERE line",
offsetof (struct _ffewhere_line_, content)
+ 1);
wl->next = (ffewhereLine) &ffewhere_root_line_;
wl->previous = ffewhere_root_line_.last;
wl->previous->next = wl;
wl->next->previous = wl;
wl->line_num = ln;
wl->uses = 1;
wl->length = 0;
*(wl->content) = '\0';
return wl;
}
ffewhereLine
ffewhere_line_use (ffewhereLine wl)
{
#if 0
fprintf (dmpout, "; ffewhere_line_use %" ffewhereLineNumber_f "u, uses=%" ffewhereUses_f_
"u\n", wl->line_num, wl->uses);
#endif
assert (ffewhere_line_is_unknown (wl) || (wl->uses != 0));
if (!ffewhere_line_is_unknown (wl))
++wl->uses;
return wl;
}
void
ffewhere_set_from_track (ffewhereLine *wol, ffewhereColumn *woc,
ffewhereLine wrl, ffewhereColumn wrc,
ffewhereTrack wt, ffewhereIndex i)
{
ffewhereLineNumber ln;
ffewhereColumnNumber cn;
ffewhereIndex j;
ffewhereIndex k;
if ((i == 0) || (i >= FFEWHERE_indexMAX))
{
*wol = ffewhere_line_use (wrl);
*woc = ffewhere_column_use (wrc);
}
else
{
ln = ffewhere_line_number (wrl);
cn = ffewhere_column_number (wrc);
for (j = 0, k = 0; j < i; ++j, k += 2)
{
if ((wt[k] == FFEWHERE_indexUNKNOWN)
|| (wt[k + 1] == FFEWHERE_indexUNKNOWN))
{
*wol = ffewhere_line_unknown ();
*woc = ffewhere_column_unknown ();
return;
}
if (wt[k] == 0)
cn += wt[k + 1] + 1;
else
{
ln += wt[k];
cn = wt[k + 1] + 1;
}
}
if (ln == ffewhere_line_number (wrl))
{
*wol = ffewhere_line_use (wrl);
}
else
*wol = ffewhere_line_new (ln);
*woc = ffewhere_column_new (cn);
}
}
void
ffewhere_track (ffewhereLine *wl, ffewhereColumn *wc, ffewhereTrack wt,
ffewhereIndex i, ffewhereLineNumber ln,
ffewhereColumnNumber cn)
{
unsigned int lo;
unsigned int co;
if ((ffewhere_line_is_unknown (*wl))
|| (ffewhere_column_is_unknown (*wc))
|| ((lo = ln - ffewhere_line_number (*wl)) >= FFEWHERE_indexUNKNOWN))
{
wt[i * 2 - 2] = wt[i * 2 - 1] = FFEWHERE_indexUNKNOWN;
ffewhere_line_kill (*wl);
ffewhere_column_kill (*wc);
*wl = FFEWHERE_lineUNKNOWN;
*wc = FFEWHERE_columnUNKNOWN;
}
else if (lo == 0)
{
wt[i * 2 - 2] = 0;
if ((co = cn - ffewhere_column_number (*wc)) > FFEWHERE_indexUNKNOWN)
{
wt[i * 2 - 1] = FFEWHERE_indexUNKNOWN;
ffewhere_line_kill (*wl);
ffewhere_column_kill (*wc);
*wl = FFEWHERE_lineUNKNOWN;
*wc = FFEWHERE_columnUNKNOWN;
}
else
{
wt[i * 2 - 1] = co - 1;
ffewhere_column_kill (*wc);
*wc = ffewhere_column_use (ffewhere_column_new (cn));
}
}
else
{
wt[i * 2 - 2] = lo;
if (cn > FFEWHERE_indexUNKNOWN)
{
wt[i * 2 - 1] = FFEWHERE_indexUNKNOWN;
ffewhere_line_kill (*wl);
ffewhere_column_kill (*wc);
*wl = ffewhere_line_unknown ();
*wc = ffewhere_column_unknown ();
}
else
{
wt[i * 2 - 1] = cn - 1;
ffewhere_line_kill (*wl);
ffewhere_column_kill (*wc);
*wl = ffewhere_line_use (ffewhere_line_new (ln));
*wc = ffewhere_column_use (ffewhere_column_new (cn));
}
}
}
void
ffewhere_track_clear (ffewhereTrack wt, ffewhereIndex length)
{
ffewhereIndex i;
if (length > FFEWHERE_indexMAX)
length = FFEWHERE_indexMAX;
for (i = 1; i < length; ++i)
wt[i * 2 - 2] = wt[i * 2 - 1] = 0;
}
void
ffewhere_track_copy (ffewhereTrack dwt, ffewhereTrack swt, ffewhereIndex start,
ffewhereIndex length)
{
ffewhereIndex i;
ffewhereIndex copy;
if (length > FFEWHERE_indexMAX)
length = FFEWHERE_indexMAX;
if (length + start > FFEWHERE_indexMAX)
copy = FFEWHERE_indexMAX - start;
else
copy = length;
for (i = 1; i < copy; ++i)
{
dwt[i * 2 - 2] = swt[(i + start) * 2 - 2];
dwt[i * 2 - 1] = swt[(i + start) * 2 - 1];
}
for (; i < length; ++i)
{
dwt[i * 2 - 2] = 0;
dwt[i * 2 - 1] = 0;
}
}
void
ffewhere_track_kill (ffewhereLine wrl, ffewhereColumn wrc UNUSED,
ffewhereTrack wt, ffewhereIndex length)
{
ffewhereLineNumber ln;
unsigned int lo;
ffewhereIndex i;
ln = ffewhere_line_number (wrl);
if (length > FFEWHERE_indexMAX)
length = FFEWHERE_indexMAX;
for (i = 0; i < length - 1; ++i)
{
if ((lo = wt[i * 2]) == FFEWHERE_indexUNKNOWN)
break;
else if (lo != 0)
{
ln += lo;
wrl = ffewhere_line_new (ln);
ffewhere_line_kill (wrl);
}
}
}