?? asm.c
字號:
* Assume InputPointer is at start of symbol name.
* Advance InputPointer past symbol name.
* Turn that character into a '\0', returning its former value.
* This allows a string compare of the symbol name.
* There will always be a char following symbol name, because all good
* lines end in end-of-line.
*/
static char get_symbol_end()
{
register char c;
while (is_part_of_name(c = *InputPointer++));
*--InputPointer = 0;
return (c);
}
/*
* We expect the following sanitation has already been done.
* No comments, reduce a comment to a space.
* Reduce a tab to a space unless it is 1st char of line.
* All multiple tabs and spaces collapsed into 1 char. Tab only
* legal if 1st char of line.
* # line file statements converted to .line x;.file y; statements.
* Escaped newlines at end of line: remove them but add as many newlines
* to end of statement as you removed in the middle, to synch line numbers.
*/
#define BEFORE_STRING ("\n")
#define AFTER_STRING ("\0") /* bcopy of 0 chars might choke. */
#define BEFORE_SIZE (1)
#define AFTER_SIZE (1)
static char *buffer_start; /* -> 1st char of full buffer area. */
static char *partial_where; /* -> after last full line in buffer. */
static int partial_size;/* >=0. Number of chars in partial line in buffer. */
/* Because we need AFTER_STRING just after last full line, it clobbers 1st part of
partial line. So we preserve 1st part of partial line here. */
static char save_source[AFTER_SIZE];
/* What is the largest size buffer that input_file_give_next_buffer()
could return to us? */
static int buffer_length;
/*
We must track the physical file and line number for error messages.
We also track a "logical" file and line number corresponding to lcc
source line numbers.
*/
static int physical_input_line;
static void InitAsmInput(void)
{
buffer_length = BUFFER_SIZE;
buffer_start = xmalloc((long) (BEFORE_SIZE + buffer_length + buffer_length + AFTER_SIZE));
bcopy(BEFORE_STRING, buffer_start, (int) BEFORE_SIZE);
/* Line number things. */
physical_input_line = 0;
partial_size = 0;
}
static void SetObjFileName(char *filename)
{
char *p;
if (OutputFileName == NULL) {
OutputFileName = xmalloc(256);
p = strrchr(filename,'\\');
if (p == NULL) p = filename;
else p++;
strcpy(OutputFileName,p);
p = strrchr(OutputFileName,'.');
if (p) *p = 0;
strcat(OutputFileName,".obj");
}
if (!strcmp(OutputFileName,filename)) {
InternalError(1114); /* input and output file names are the same? */
}
}
static void bump_line_counters(void)
{
++physical_input_line;
}
/* Nonzero if we've hit a 'bad error', and should not write an obj file,
and exit with a nonzero error code */
static int bad_error = 0;
void InternalError(int err)
{
if (err < 2000) {
fprintf(stderr,StrTab[393],err);// <Internal error %d\t>
}
else if (err < 3000) {
fprintf(stderr,StrTab[394],err);// <Internal error %d\t>
bad_error++;
}
else if (err < 4000) {
fprintf(stderr,StrTab[395],err);// <Warning %d\t>
}
printf("line %d\n",physical_input_line);
if (err < 2000) exit(err);
}
void WriteError(void)
{
fprintf(stderr,StrTab[396]);// <Write error. Disk Full?\n>
exit(1);
}
/* obstack.c - subroutines used implicitly by object stack macros */
/* Determine default alignment. */
struct fooalign {
char x;
double d;
};
#define DEFAULT_ALIGNMENT ((char *)&((struct fooalign *) 0)->d - (char *)0)
/* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT.
But in fact it might be less smart and round addresses to as much as
DEFAULT_ROUNDING. So we prepare for it to do that. */
#define DEFAULT_ROUNDING 4
/* When we copy a long block of data, this is the unit to do it with. */
#ifndef COPYING_UNIT
#define COPYING_UNIT int
#endif
static void _obstack_begin(struct obstack * h, int size, int alignment, void *(*chunkfun) (int), void (*freefun) (void *))
{
register struct _obstack_chunk *chunk; /* points to new chunk */
if (alignment == 0)
alignment = DEFAULT_ALIGNMENT;
if (size == 0) {
/* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc. Use the
values for range checking, because if range checking is off, the
extra bytes won't be missed terribly, but if range checking is on
and we used a larger request, a whole extra 4096 bytes would be
allocated.
These number are irrelevant to the new GNU malloc. I suspect it is
less sensitive to the size of the request. */
int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
+ 4 + DEFAULT_ROUNDING - 1)
& ~(DEFAULT_ROUNDING - 1));
size = 4096 - extra;
}
h->chunkfun = (struct _obstack_chunk * (*) (int)) chunkfun;
h->freefun = freefun;
h->chunk_size = size;
h->alignment_mask = alignment - 1;
chunk = h->chunk = (*h->chunkfun) (h->chunk_size);
h->next_free = h->object_base = chunk->contents;
h->chunk_limit = chunk->limit
= (char *) chunk + h->chunk_size;
chunk->prev = 0;
}
/* Allocate a new current chunk for the obstack *H on the assumption that LENGTH
bytes need to be added to the current object, or a new object of length LENGTH
allocated. Copies any partial object from the end of the old chunk to the
beginning of the new one.
*/
static void _obstack_newchunk(struct obstack * h, int length)
{
register struct _obstack_chunk *old_chunk = h->chunk;
register struct _obstack_chunk *new_chunk;
register long new_size;
register int obj_size = h->next_free - h->object_base;
register int i;
int already;
/* Compute size for new chunk. */
new_size = (obj_size + length) + (obj_size >> 3) + 100;
if (new_size < h->chunk_size)
new_size = h->chunk_size;
/* Allocate and initialize the new chunk. */
new_chunk = h->chunk = (*h->chunkfun) (new_size);
new_chunk->prev = old_chunk;
new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
/* Move the existing object to the new chunk. Word at a time is fast and
is safe if the object is sufficiently aligned. */
if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT) {
for (i = obj_size / sizeof(COPYING_UNIT) - 1;
i >= 0; i--)
((COPYING_UNIT *) new_chunk->contents)[i]
= ((COPYING_UNIT *) h->object_base)[i];
/* We used to copy the odd few remaining bytes as one extra
COPYING_UNIT, but that can cross a page boundary on a machine which
does not do strict alignment for COPYING_UNITS. */
already = obj_size / sizeof(COPYING_UNIT) * sizeof(COPYING_UNIT);
}
else
already = 0;
/* Copy remaining bytes one by one. */
for (i = already; i < obj_size; i++)
new_chunk->contents[i] = h->object_base[i];
/* If the object just copied was the only data in OLD_CHUNK, free that
chunk and remove it from the chain. */
if (h->object_base == old_chunk->contents) {
new_chunk->prev = old_chunk->prev;
(*h->freefun) (old_chunk);
}
h->object_base = new_chunk->contents;
h->next_free = h->object_base + obj_size;
}
/*
* In: a character.
* Out: TRUE if this character ends a line.
*/
#define _ (0)
static const char is_end_of_line[256] = {
_, _, _, _, _, _, _, _, _, _, 99, _, _, _, _, _, /* @abcdefghijklmno */
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
_, _, _, _, _, _, _, _, _, _, _, 99, _, _, _, _, /* 0123456789:;<=>? */
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ /* */
};
#undef _
static char *hash_insert(struct HASH_LIST * where, char *name, char *data)
{
struct HASH_LIST *rvp, *result,**slots;
register int h;
register char *p = name;
int len;
for (h = 0; *p;)
h = (h << 2) ^ *p++;
h &= HASHSIZE-1;
slots = (struct HASH_LIST **)where->Data;
rvp = slots[h];
len = p - name;
while (rvp) {
if (rvp->len == len && !strcmp(name, rvp->Name)) return(rvp->Name);
rvp = rvp->Next;
}
rvp = slots[h];
result = (struct HASH_LIST *)allocate(sizeof(struct HASH_LIST),4);
result->Next = rvp;
result->Name = name;
result->len = len;
slots[h] = result;
result->Data = data;
return ("");
}
static char *hash_find(struct HASH_LIST * w, char *n)
{
register struct HASH_LIST *rvp;
register int h;
register char *p = n;
for (h = 0; *p;)
h = (h << 2) ^ *p++;
rvp = ((struct HASH_LIST **)w->Data)[h & (HASHSIZE-1)];
h = p - n;
while (rvp) {
if ((rvp->len == h) && !strcmp(n, rvp->Name)) return(rvp->Data);
rvp = rvp->Next;
}
return (NULL);
}
static struct HASH_LIST *hash_new(void)
{
struct HASH_LIST *r;
r = (struct HASH_LIST *) allocate(sizeof(struct HASH_LIST),4);
r->Name = xmalloc(1);
r->Data = xmalloc((HASHSIZE+1)*sizeof(struct HASH_LIST *));
return (r);
}
static void symbol_table_insert(symbolS *symbolP)
{
struct HASH_LIST *rvp;
struct HASH_LIST *result,**slots;
register int h;
register char *p = symbolP->Name;
char *n = p;
for (h = 0; *p;)
h = (h << 2) ^ *p++;
h &= HASHSIZE-1;
slots = (struct HASH_LIST **)sy_hash->Data;
rvp = slots[h];
result = (struct HASH_LIST *) allocate(sizeof(struct HASH_LIST),4);
result->Next = rvp;
result->Name = n;
result->len = p - n;
result->Data = (char *)symbolP;
slots[h] = result;
return;
}
/* set up pseudo-op tables */
static struct hash_control *po_hash = NULL; /* use before set up: NULL->
address error */
static symbolS *CurrentFunctionSymbol;
static char *input_buffer(char *inbuffer,int len)
{
register char *limit; /* -> just after last char of buffer. */
if (partial_size) {
bcopy(partial_where, buffer_start + BEFORE_SIZE, (int) partial_size);
bcopy(save_source, buffer_start + BEFORE_SIZE, (int) AFTER_SIZE);
}
memcpy(buffer_start + BEFORE_SIZE + partial_size,inbuffer,len);
limit = buffer_start + BEFORE_SIZE + partial_size + len;
if (len) {
register char *p; /* Find last newline. */
for (p = limit; *--p != '\n';) {
}
++p;
if (p <= buffer_start + BEFORE_SIZE) {
InternalError(1006);
}
partial_where = p;
partial_size = limit - p;
bcopy(partial_where, save_source, (int) AFTER_SIZE);
bcopy(AFTER_STRING, partial_where, (int) AFTER_SIZE);
}
else {
partial_where = 0;
if (partial_size > 0) {
InternalError(2070);
}
}
return (partial_where);
}
/* AsmReadBuffer()
* File has already been opened, and will be closed by our caller.
* We read the file, putting things into a web that
* represents what we have been reading.
*/
void AsmReadBuffer(char *buffer,int len)
{
register char c;
register char *s; /* string of symbol, '\0' appended */
pseudo_typeS *pop;
buffer_limit = input_buffer(buffer,len); /* We have
another line to parse. */
know(buffer_limit[-1] == '\n'); /* Must have a sentinel. */
InputPointer = buffer_start + BEFORE_SIZE;
contin:
while (InputPointer < buffer_limit) { /* We have more of this
buffer to parse. */
/* We now have InputPointer -> 1st char of next line. If
InputPointer [-1] == '\n' then we just scanned another
line: so bump line counters. */
if (InputPointer[-1] == '\n') {
bump_line_counters();
}
/* We are at the begining of a line, or similar place. We expect
a well-formed assembler statement. A "symbol-name:" is a
statement. */
while ((c = *InputPointer++) == '\t' || c == ' ') {
;
}
know(c != ' '); /* No further leading whitespace. */
/* c is the 1st significant character. InputPointer points
after that character. */
if (c == '\n') {
continue;
}
if (c == ';') {
while (*InputPointer != '\n')
InputPointer++;
continue;
}
if (is_name_beginner(c)) { /* want user-defined label or
pseudo/opcode */
s = --InputPointe
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -