home *** CD-ROM | disk | FTP | other *** search
- /*
- * area.c
- * Copyright © 1992 Niklas Röjemo
- */
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <ctype.h>
- #include <string.h>
- #include "lex.h"
- #include "hash.h"
- #include "symbol.h"
- #include "commands.h"
- #include "error.h"
- #include "input.h"
- #include "expr.h"
- #include "area.h"
-
- #define DOUBLE_UP_TO 128*1024
- #define GROWSIZE 16*1024
-
- Symbol *areaCurrent = 0;
- Symbol *areaEntry = 0;
- int areaEntryOffset;
-
- Symbol *areaHead = 0;
-
- static Area *areaNew(int type)
- {
- Area *res = malloc(sizeof(Area));
- if(res) {
- res->next = areaHead;
- res->type = type | AREA_INIT;
- res->imagesize = 0;
- res->image = 0;
- res->norelocs = 0;
- res->relocs = 0;
- res->lits = 0;
- } else
- error(ErrorSerious,FALSE,"Internal areaNew: Out of memory!.");
- return res;
- }
-
- static BOOL areaImage(Area *area,int newsize)
- {
- char *new;
- if(area->imagesize)
- new = realloc(area->image,newsize);
- else
- new = malloc(newsize);
- if(new) {
- area->imagesize = newsize;
- area->image = new;
- return TRUE;
- } else
- return FALSE;
- }
-
-
- void areaGrow(Area *area,int mingrow)
- {
- int inc;
- if(area->imagesize && area->imagesize < DOUBLE_UP_TO)
- inc = area->imagesize;
- else
- inc = GROWSIZE;
- if(inc<mingrow)
- inc = mingrow;
- while(inc > mingrow && !areaImage(area,area->imagesize+inc)) {
- inc = inc/2;
- }
- if(inc<=mingrow)
- if(!areaImage(area,area->imagesize+mingrow))
- error(ErrorSerious,FALSE,"Internal areaGrow: Out of memory, minsize = %d.",mingrow);
- }
-
- void areaInit(void)
- {
- areaCurrent = 0;
- }
-
- void areaFinish(void) /* insert ltorg at end of all areas */
- {
- Symbol *ap;
- for(ap = areaHead; ap; ap = ap->area.info->next) {
- areaCurrent = ap;
- litOrg(ap->area.info->lits);
- }
- }
-
- void c_entry(void)
- {
- if(areaCurrent) {
- if(areaEntry)
- error(ErrorError,FALSE,"More than one entry.");
- else {
- areaEntry = areaCurrent;
- areaEntryOffset = areaCurrent->value.ValueInt.i;
- }
- } else {
- error(ErrorError,FALSE,"No area selected before entry.");
- }
- }
-
-
- void c_align(void) /* !!! Ought to do zero fill */
- {
- Value value;
- skipblanks();
- if(!inputLook() || inputLook() == ';') { /* No expression follows */
- areaCurrent->value.ValueInt.i = (areaCurrent->value.ValueInt.i+3) & ~3;
- } else { /* An expression follows */
- exprBuild();
- value = exprEval(ValueInt);
- switch(value.Tag) {
- case ValueInt:
- areaCurrent->value.ValueInt.i = (areaCurrent->value.ValueInt.i+value.ValueInt.i-1)/value.ValueInt.i;
- areaCurrent->value.ValueInt.i *= value.ValueInt.i;
- break;
- default:
- error(ErrorError,TRUE,"Unresolved align not possible.");
- }
- }
- }
-
- void c_reserve(void) /* !!! Ought to do zero fill */
- {
- Value value;
- exprBuild();
- value = exprEval(ValueInt);
- switch(value.Tag) {
- case ValueInt:
- if(!areaCurrent)
- error(ErrorSerious,TRUE,"No area defined.");
- else
- areaCurrent->value.ValueInt.i += value.ValueInt.i;
- break;
- default:
- error(ErrorError,TRUE,"Unresolved reserve not possible.");
- }
- }
-
- void c_area(void)
- {
- Symbol *sym;
- int oldtype = 0;
- int newtype = 0;
- int c;
-
- sym = symbolGet(lexGetId());
- if(sym->type & SYMBOL_DEFINED) {
- error(ErrorError,TRUE,"Redifinition of label to area %s.",sym->str);
- } else if(sym->type == SYMBOL_AREA) {
- oldtype = sym->area.info->type;
- } else {
- sym->type = SYMBOL_AREA;
- sym->value.Tag = ValueInt;
- sym->value.ValueInt.i = 0;
- sym->area.info = areaNew(0);
- areaHead = sym;
- }
- skipblanks();
- while ((c=inputGet()) == ',') {
- Lex attribute = lexGetId();
- if(!strncmp("CODE",attribute.LexId.str,attribute.LexId.len))
- newtype |= AREA_CODE | AREA_INIT;
- else if(!strncmp("DATA",attribute.LexId.str,attribute.LexId.len))
- newtype |= AREA_DATA | AREA_INIT;
- else if(!strncmp("NOINIT",attribute.LexId.str,attribute.LexId.len))
- newtype |= AREA_UDATA | AREA_INIT;
- else if(!strncmp("READONLY",attribute.LexId.str,attribute.LexId.len))
- newtype |= AREA_READONLY | AREA_INIT;
- else
- error(ErrorError,TRUE,"Illegal area attribute %s.",attribute.LexId.str);
- skipblanks();
- }
- inputUnGet(c);
- if(newtype && oldtype && newtype != oldtype)
- error(ErrorError,TRUE,"Changing attribute of area %s.",sym->str);
- sym->area.info->type |= newtype;
- areaCurrent = sym;
- }
-