示例#1
0
文件: macro.c 项目: mnemnion/imp
void append_type(struct prog_info *pi, char *name, int c, char *value)
{
	int p, l;
	struct def *def;

	p = strlen(name);
	name[p++] = '_';

	if(c == 0)
	{
		name[p++] = 'v';
		name[p] = '\0';
		return;
	}

	l = strlen(value);
	if ((l==2 || l==3) && (tolower(value[0])=='r') && isdigit(value[1]) && (l==3?isdigit(value[2]):1) && (atoi(&value[1])<32))
	{
		itoa((c*8),&name[p],10);
		return;
	}
			

	for(def = pi->first_def; def; def = def->next)
		if(!nocase_strcmp(def->name, value))
		{
			itoa((c*8),&name[p],10);
			return;
		}

	name[p++] = 'i';
	name[p] = '\0';
}
示例#2
0
文件: macro.c 项目: mnemnion/imp
struct macro *get_macro(struct prog_info *pi, char *name)
{
	struct macro *macro;

	for(macro = pi->first_macro; macro; macro = macro->next)	
		if(!nocase_strcmp(macro->name, name))
			return(macro);
	return(NULL);
}
示例#3
0
文件: device.c 项目: Synapseware/avra
struct device *get_device(struct prog_info *pi, char *name)
{
	int i = 1;

    LastDevice = 0;
	if(name == NULL) {
        def_dev(pi);
	    return(&device_list[0]);
	}
	while(device_list[i].name) {
		if(!nocase_strcmp(name, device_list[i].name)) {
			LastDevice=i;
            def_dev(pi);
			return(&device_list[i]);
		}
		i++;
	}
	def_dev(pi);
	return(NULL);
}
示例#4
0
文件: parser.c 项目: mnemnion/imp
int parse_line(struct prog_info *pi, char *line) 
{
	char *ptr=NULL;
	int k;
	int flag=0, i;
	int global_label = False;
	char temp[LINEBUFFER_LENGTH];
	struct label *label = NULL;
	struct macro_call *macro_call;

	while(IS_HOR_SPACE(*line)) line++;			/* At first remove leading spaces / tabs */
	if(IS_END_OR_COMMENT(*line))				/* Skip comment line or empty line */
		return(True);
								/* Filter out .stab debugging information */
								/* .stabs sometimes contains colon : symbol - might be interpreted as label */
	if(*line == '.') {					/* minimal slowdown of existing code */
		if(strncmp(temp,".stabs ",7) == 0 ) {		/* compiler output is always lower case */
			strcpy(temp,line);			/* TODO : Do we need this temp variable ? Please check */
			return parse_stabs( pi, temp );
		}
		if(strncmp(temp,".stabn ",7) == 0 ) {
			strcpy(temp,line);
			return parse_stabn( pi, temp );
		}
	}
								/* Meta information translation */
	ptr=line;
	k=0;
	while((ptr=strchr(ptr, '%')) != NULL) {
		if(!strncmp(ptr, "%MINUTE%", 8) ) {		/* Replacement always shorter than tag -> no length check */
			k=strftime(ptr,3,"%M", localtime(&pi->time));
			strcpy(ptr+k,ptr+8); 
			ptr+=k;
			continue;
		}
		if(!strncmp(ptr, "%HOUR%", 6) ) {			
			k=strftime(ptr,3,"%H", localtime(&pi->time));
			strcpy(ptr+k,ptr+6); 
			ptr+=k;
			continue;
		}
		if(!strncmp(ptr, "%DAY%", 5) ) {
			k=strftime(ptr,3,"%d", localtime(&pi->time));
			strcpy(ptr+k,ptr+5); 
			ptr+=k;
			continue;
		}
		if(!strncmp(ptr, "%MONTH%", 7) ) {
			k=strftime(ptr,3,"%m", localtime(&pi->time));
			strcpy(ptr+k,ptr+7); 
			ptr+=k;
			continue;
		}
		if(!strncmp(ptr, "%YEAR%", 6) ) {
			k=strftime(ptr,5,"%Y", localtime(&pi->time));
			strcpy(ptr+k,ptr+6); 
			ptr+=k;
			continue;
		}
		ptr++;
	}

//	if(pi->pass == PASS_2)		// TODO : Test
//		strcpy(pi->list_line, line);

	strcpy(pi->fi->scratch,line);

	for(i = 0; IS_LABEL(pi->fi->scratch[i]) || (pi->fi->scratch[i] == ':'); i++)
		if(pi->fi->scratch[i] == ':') {	/* it is a label */
			pi->fi->scratch[i] = '\0';
			if(pi->pass == PASS_1) {
				for(macro_call = pi->macro_call; macro_call; macro_call = macro_call->prev_on_stack) {
					for(label = pi->macro_call->first_label; label; label = label->next) {
						if(!nocase_strcmp(label->name, &pi->fi->scratch[0])) {
							print_msg(pi, MSGTYPE_ERROR, "Can't redefine local label %s", &pi->fi->scratch[0]);
							break;
						}
					}
				}
				if(test_label(pi,&pi->fi->scratch[0],"Can't redefine label %s")!=NULL) 
					break;
				if(test_variable(pi,&pi->fi->scratch[0],"%s have already been defined as a .SET variable")!=NULL) 
					break;
				if(test_constant(pi,&pi->fi->scratch[0],"%s has already been defined as a .EQU constant")!=NULL) 
					break;
				label = malloc(sizeof(struct label));
				if(!label) {
					print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
					return(False);
				}
				label->next = NULL;
				label->name = malloc(strlen(&pi->fi->scratch[0]) + 1);
				if(!label->name) {
					print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
					return(False);
				}
				strcpy(label->name, &pi->fi->scratch[0]);
				switch(pi->segment) {
					case SEGMENT_CODE:
						label->value = pi->cseg_addr;
						break;
					case SEGMENT_DATA:
						label->value = pi->dseg_addr;
						break;
					case SEGMENT_EEPROM:
						label->value = pi->eseg_addr;
						break;
				}
				if(pi->macro_call && !global_label) {
					if(pi->macro_call->last_label)
						pi->macro_call->last_label->next = label;
				  	else
						pi->macro_call->first_label = label;
				  	pi->macro_call->last_label = label;
				} else {
					if(pi->last_label)
				  		pi->last_label->next = label;
					else
						pi->first_label = label;
					pi->last_label = label;
				}
			} 
			i++;
			while(IS_HOR_SPACE(pi->fi->scratch[i]) && !IS_END_OR_COMMENT(pi->fi->scratch[i])) i++;
			if(IS_END_OR_COMMENT(pi->fi->scratch[i])) {
				if((pi->pass == PASS_2) && pi->list_on) { // Diff tilpassing
					fprintf(pi->list_file, "          %s\n", pi->list_line);
					pi->list_line = NULL;
				}
				return(True);
			}
			strcpy(pi->fi->scratch, &pi->fi->scratch[i]);
			break;
		}

#if 0
	if(pi->fi->scratch[0] == '.') {
#else
	if((pi->fi->scratch[0] == '.') || (pi->fi->scratch[0] == '#')) {
#endif
		pi->fi->label = label;
		flag = parse_directive(pi);
		if((pi->pass == PASS_2) && pi->list_on && pi->list_line) { // Diff tilpassing 
  			fprintf(pi->list_file, "          %s\n", pi->list_line);
			pi->list_line = NULL;
		}
		return(flag);
	} else {
		return parse_mnemonic(pi);
	}
}


/*
 * Get the next token, and terminate the last one.
 * Termination identifier is specified.
 */

char *get_next_token(char *data, int term)
{
	int i = 0, j, anti_comma = False;
	switch(term) {
		case TERM_END:
//			while(!IS_END_OR_COMMENT(data[i])) i++; 	Problems with 2. operand == ';'
			while( ((data[i] != ',') || anti_comma) && !(((data[i] == ';') && !anti_comma) || IS_ENDLINE(data[i])) ) {
				if((data[i] == '\'') || (data[i] == '"')) 
					anti_comma = anti_comma ? False : True;
				i++;
			}
			break;
		case TERM_SPACE:
			while(!IS_HOR_SPACE(data[i]) && !IS_END_OR_COMMENT(data[i])) i++;
			break;
		case TERM_DASH:
			while((data[i] != '-') && !IS_END_OR_COMMENT(data[i])) i++;
			break;
		case TERM_COLON:
			while((data[i] != ':') && !IS_ENDLINE(data[i])) i++;
			break;
		case TERM_DOUBLEQUOTE:
			while((data[i] != '"') && !IS_ENDLINE(data[i])) i++;
			break;
		case TERM_COMMA:
			while(((data[i] != ',') || anti_comma) && !(((data[i] == ';') && !anti_comma) || IS_ENDLINE(data[i])) ) {
				if((data[i] == '\'') || (data[i] == '"')) 
					anti_comma = anti_comma ? False : True;
				i++;
			}
			break;
		case TERM_EQUAL:
			while((data[i] != '=') && !IS_END_OR_COMMENT(data[i])) i++;
			break;
	}
	if(IS_END_OR_COMMENT(data[i])) {
		data[i--] = '\0';
		while(IS_HOR_SPACE(data[i])) data[i--] = '\0';
		return(0);
	}
	j = i - 1;
	while(IS_HOR_SPACE(data[j])) data[j--] = '\0';
	data[i++] = '\0';
	while(IS_HOR_SPACE(data[i]) && !IS_END_OR_COMMENT(data[i])) i++;
	if(IS_END_OR_COMMENT(data[i]))
		return(0);
	return(&data[i]);
}
示例#5
0
int parse_directive(struct prog_info *pi)
{
	int directive, pragma;
	int ok = True;
	int i;
	char *next, *data, buf[140];
	struct file_info *fi_bak;

	struct def *def;
	struct data_list *incpath, *dl;

	next = get_next_token(pi->fi->scratch, TERM_SPACE);

	my_strupr(pi->fi->scratch);
	directive = lookup_keyword(directive_list, pi->fi->scratch + 1, True);
	if(directive == -1) {
		print_msg(pi, MSGTYPE_ERROR, "Unknown directive: %s", pi->fi->scratch);
		return(True);
	}
	switch(directive) {
		case DIRECTIVE_BYTE:
			if (!next) {
				print_msg(pi, MSGTYPE_ERROR, ".BYTE needs a size operand");
				return(True);
			}
			if (pi->segment == pi->cseg)
				print_msg(pi, MSGTYPE_ERROR, ".BYTE directive cannot be used within the code segment (.CSEG)");
			get_next_token(next, TERM_END);
			if (!get_expr(pi, next, &i))
				return(False);
			if ((pi->pass == PASS_2) && pi->list_line && pi->list_on) {
				fprintf(pi->list_file, "%c:%06x    %s\n", 
					pi->segment->ident, pi->segment->addr, pi->list_line);
				pi->list_line = NULL;
			}
			if (i > 0) {
					fix_orglist(pi->segment);
					advance_ip(pi->segment, i);
					def_orglist(pi->segment);
			}
			break;
		case DIRECTIVE_CSEG:
			fix_orglist(pi->segment);
			def_orglist(pi->cseg);
			break;
		case DIRECTIVE_CSEGSIZE:
			break;
		case DIRECTIVE_DB:
			if((pi->pass == PASS_2) && pi->list_line && pi->list_on) {
				fprintf(pi->list_file, "          %s\n", pi->list_line);
				pi->list_line = NULL;
			}
			return(parse_db(pi, next));
//			break;
		/* Directive .def */
		case DIRECTIVE_DEF:
			if(!next) {
				print_msg(pi, MSGTYPE_ERROR, ".DEF needs an operand");
				return(True);
			}
			data = get_next_token(next, TERM_EQUAL);
			if(!(data && (tolower(data[0]) == 'r') && isdigit(data[1]))) {
				print_msg(pi, MSGTYPE_ERROR, "%s needs a register (e.g. .def BZZZT = r16)", next);
				return(True);
			}
			i = atoi(&data[1]);
			/* check range of given register */
			if(i > 31)
				print_msg(pi, MSGTYPE_ERROR, "R%d is not a valid register", i);
			/* check if this reg is already assigned */
			for(def = pi->first_def; def; def = def->next) {
				if(def->reg == i && pi->pass == PASS_1 && !pi->NoRegDef) {
				    print_msg(pi, MSGTYPE_WARNING, "r%d is already assigned to '%s'!", i, def->name);
					return(True);
				}
			}
			/* check if this regname is already defined */
			for(def = pi->first_def; def; def = def->next) {
				if(!nocase_strcmp(def->name, next)) {
					if(pi->pass == PASS_1 && !pi->NoRegDef) {
						print_msg(pi, MSGTYPE_WARNING, "'%s' is already assigned as r%d but will now be set to r%i!", next, def->reg, i);
					}
					def->reg = i;
					return(True);
				}
			}
			/* B.A.: Check, if symbol is already defined as a label or constant */
			if(pi->pass == PASS_2) {
				if(get_label(pi,next,NULL))
					print_msg(pi, MSGTYPE_WARNING, "Name '%s' is used for a register and a label", next);
				if(get_constant(pi,next,NULL))
					print_msg(pi, MSGTYPE_WARNING, "Name '%s' is used for a register and a constant", next);
			}

			def = malloc(sizeof(struct def));
			if(!def) {
				print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
				return(False);
			}
			def->next = NULL;
			if(pi->last_def)
				pi->last_def->next = def;
			else
				pi->first_def = def;
			pi->last_def = def;
			def->name = malloc(strlen(next) + 1);
			if(!def->name) {
				print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
				return(False);
			}
			strcpy(def->name, next);
			def->reg = i;
			break;
		case DIRECTIVE_DEVICE:
			if(pi->pass == PASS_2)
				return(True);
			if(!next) {
				print_msg(pi, MSGTYPE_ERROR, ".DEVICE needs an operand");
				return(True);
			}
			if (pi->device->name != NULL) { /* B.A.: Check for multiple device definitions */
				print_msg(pi, MSGTYPE_ERROR, "More than one .DEVICE definition");
			}
			if (pi->cseg->count || pi->dseg->count || pi->eseg->count) { 
				/* B.A.: Check if something was already assembled */
				print_msg(pi, MSGTYPE_ERROR, ".DEVICE definition must be before any code lines");
			} else {
				if ((pi->cseg->addr != pi->cseg->lo_addr ) 
				 || (pi->dseg->addr != pi->dseg->lo_addr )
				 || (pi->eseg->addr != pi->eseg->lo_addr )) { 
					/* B.A.: Check if something was already assembled XXX probably redundant */
					print_msg(pi, MSGTYPE_ERROR, ".DEVICE definition must be before any .ORG directive");
				}
			}

			get_next_token(next, TERM_END);
			pi->device = get_device(pi,next);
			if (!pi->device) {
				print_msg(pi, MSGTYPE_ERROR, "Unknown device: %s", next);
				pi->device = get_device(pi,NULL); /* B.A.: Fix segmentation fault if device is unknown */
			}

			/* Now that we know the device type, we can
			 * start memory allocation from the correct offsets.
			 */
			fix_orglist(pi->segment);
			rewind_segments(pi);
			def_orglist(pi->segment);
			break;
		case DIRECTIVE_DSEG:
			fix_orglist(pi->segment);
			def_orglist(pi->dseg);
			if (pi->dseg->hi_addr == 0) {
				/* XXX move to emit */
				print_msg(pi, MSGTYPE_ERROR, "Can't use .DSEG directive because device has no RAM");
			}
			break;
		case DIRECTIVE_DW:
			if (pi->segment->flags & SEG_BSS_DATA) {
				print_msg(pi, MSGTYPE_ERROR, "Can't use .DW directive in data segment (.DSEG)");
				return(True);
			}
			while (next) {
				data = get_next_token(next, TERM_COMMA);
				if(pi->pass == PASS_2) {
				  if(!get_expr(pi, next, &i))
				    return(False);
				  if((i < -32768) || (i > 65535))
				    print_msg(pi, MSGTYPE_WARNING, "Value %d is out of range (-32768 <= k <= 65535). Will be masked", i);
                }
				if (pi->pass == PASS_2) {
					if (pi->list_line && pi->list_on) {
						fprintf(pi->list_file, "          %s\n", pi->list_line);
						pi->list_line = NULL;
						fprintf(pi->list_file, "%c:%06x %04x\n", 
							pi->segment->ident, pi->segment->addr, i);
					}
					if (pi->segment == pi->eseg) {
						write_ee_byte(pi, pi->eseg->addr, (unsigned char)i);
						write_ee_byte(pi, pi->eseg->addr + 1, (unsigned char)(i >> 8));
					}
					if (pi->segment == pi->cseg) {
						write_prog_word(pi, pi->cseg->addr, i);
					}
				}
				if (pi->segment == pi->eseg) 
					advance_ip(pi->eseg, 2);
				if (pi->segment == pi->cseg) 
					advance_ip(pi->cseg, 1);
				next = data;
			}
			break;
		case DIRECTIVE_ENDM:
		case DIRECTIVE_ENDMACRO:
			print_msg(pi, MSGTYPE_ERROR, "No .MACRO found before .ENDMACRO");
			break;
		case DIRECTIVE_EQU:
			if(!next) {
				print_msg(pi, MSGTYPE_ERROR, ".EQU needs an operand");
				return(True);
			}
			data = get_next_token(next, TERM_EQUAL);
			if(!data) {
				print_msg(pi, MSGTYPE_ERROR, "%s needs an expression (e.g. .EQU BZZZT = 0x2a)", next);
				return(True);
			}
			get_next_token(data, TERM_END);
			if(!get_expr(pi, data, &i))
				return(False);
			if(test_label(pi,next,"%s have already been defined as a label")!=NULL) 
				return(True);
			if(test_variable(pi,next,"%s have already been defined as a .SET variable")!=NULL) 
				return(True);
			/* B.A. : New. Forward references allowed. But check, if everything is ok ... */
			if(pi->pass==PASS_1) { /* Pass 1 */
				if(test_constant(pi,next,"Can't redefine constant %s, use .SET instead")!=NULL) 
					return(True);
				if(def_const(pi, next, i)==False)
					return(False);
			} else { /* Pass 2 */
				int j;
				if(get_constant(pi, next, &j)==False) {   /* Defined in Pass 1 and now missing ? */
					print_msg(pi, MSGTYPE_ERROR, "Constant %s is missing in pass 2", next);
					return(False);
				}
				if(i != j) {
					print_msg(pi, MSGTYPE_ERROR, "Constant %s changed value from %d in pass1 to %d in pass 2", next,j,i);
					return(False);
				}
				/* OK. Definition is unchanged */
			}
			if((pi->pass == PASS_2) && pi->list_line && pi->list_on) {
				fprintf(pi->list_file, "          %s\n", pi->list_line);
				pi->list_line = NULL;
			}
			break;
		case DIRECTIVE_ESEG:
			fix_orglist(pi->segment);
			def_orglist(pi->eseg);
			if(pi->device->eeprom_size == 0) { /* XXX */
				print_msg(pi, MSGTYPE_ERROR, "Can't use .ESEG directive because device has no EEPROM");
			}
			break;
		case DIRECTIVE_EXIT:
			pi->fi->exit_file = True;
			break;
		/*** .include ***/
		case DIRECTIVE_INCLUDE:    
			if(!next) {
				print_msg(pi, MSGTYPE_ERROR, "Nothing to include");
				return(True);
			}
			next = term_string(pi, next);
			if((pi->pass == PASS_2) && pi->list_line && pi->list_on) {
				fprintf(pi->list_file, "          %s\n", pi->list_line);
				pi->list_line = NULL;
			}
			// Test if include is in local directory
			ok = test_include(next);
			data = NULL;
			if(!ok)
				for(incpath = GET_ARG_LIST(pi->args, ARG_INCLUDEPATH); incpath && !ok; incpath = incpath->next) {
					i = strlen(incpath->data);
					if(data)
						free(data);
					data = malloc(i + strlen(next) + 2);
					if(!data) {
						print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
						return(False);
					}
					strcpy(data, incpath->data);
					if((data[i - 1] != '\\') && (data[i - 1] != '/'))
						data[i++] = '/';
					strcpy(&data[i], next);
                    //printf("testing: %s\n", data);
					ok = test_include(data);
				}
			if(ok) {
				fi_bak = pi->fi;
				ok = parse_file(pi, data ? data : next);
				pi->fi = fi_bak;
			}
			else
				print_msg(pi, MSGTYPE_ERROR, "Cannot find include file: %s", next);
			if(data)
				free(data);
			break;
		/*** .includepath ***/
		case DIRECTIVE_INCLUDEPATH:
			if(!next) {
				print_msg(pi, MSGTYPE_ERROR, ".INCLUDEPATH needs an operand");
				return(True);
			}
			data = get_next_token(next, TERM_SPACE);
			if(data) {
				print_msg(pi, MSGTYPE_ERROR, ".INCLUDEPATH needs an operand!!!");
				get_next_token(data, TERM_END);
				if(!get_expr(pi, data, &i))
				        return(False);
			}
			next = term_string(pi, next);
			/* get arg list start pointer */
			incpath = GET_ARG_LIST(pi->args, ARG_INCLUDEPATH);
        /* search for last element */
        if(incpath == NULL) {
         	dl = malloc(sizeof(struct data_list));
         	data = malloc(strlen(next)+1);
	        if(dl && data) {
         		dl->next = NULL;
         		strcpy(data, next);
		        dl->data = data;
            SET_ARG_LIST(pi->args, ARG_INCLUDEPATH, dl);
         	}
         	else {
         		printf("Error: Unable to allocate memory\n");
        		return(False);
         	}
        }
        else
          add_arg(&incpath, next);
			break;
		case DIRECTIVE_LIST:
			if(pi->pass == PASS_2)
				if(pi->list_file)
          pi->list_on = True;
			break;
		case DIRECTIVE_LISTMAC:
			if(pi->pass == PASS_2)
				SET_ARG_I(pi->args, ARG_LISTMAC, True);
			break;
		case DIRECTIVE_MACRO:
			return(read_macro(pi, next));
//			break;
		case DIRECTIVE_NOLIST:
			if(pi->pass == PASS_2)
				pi->list_on = False;
			break;
		case DIRECTIVE_ORG:
			if(!next) {
				print_msg(pi, MSGTYPE_ERROR, ".ORG needs an operand");
				return(True);
			}
			get_next_token(next, TERM_END);
			if(!get_expr(pi, next, &i))
				return(False);
			fix_orglist(pi->segment);
			pi->segment->addr = i; /* XXX advance */
			def_orglist(pi->segment);
			if(pi->fi->label)
				pi->fi->label->value = i;
			if((pi->pass == PASS_2) && pi->list_line && pi->list_on) {
				fprintf(pi->list_file, "          %s\n", pi->list_line);
				pi->list_line = NULL;
			}
			break;
		case DIRECTIVE_SET:
			if(!next) {
				print_msg(pi, MSGTYPE_ERROR, ".SET needs an operand");
				return(True);
			}
			data = get_next_token(next, TERM_EQUAL);
			if(!data) {
				print_msg(pi, MSGTYPE_ERROR, "%s needs an expression (e.g. .SET BZZZT = 0x2a)", next);
				return(True);
			}
			get_next_token(data, TERM_END);
			if(!get_expr(pi, data, &i))
				return(False);

      if(test_label(pi,next,"%s have already been defined as a label")!=NULL) 
        return(True);
      if(test_constant(pi,next,"%s have already been defined as a .EQU constant")!=NULL) 
        return(True);
      return(def_var(pi, next, i));
//			break;
		case DIRECTIVE_DEFINE:
			if(!next) {
				print_msg(pi, MSGTYPE_ERROR, ".DEFINE needs an operand");
				return(True);
			}
			data = get_next_token(next, TERM_SPACE);
			if(data) {
				get_next_token(data, TERM_END);
				if(!get_expr(pi, data, &i))
				        return(False);
			}
			else
				i = 1;
      if(test_label(pi,next,"%s have already been defined as a label")!=NULL) 
        return(True);
      if(test_variable(pi,next,"%s have already been defined as a .SET variable")!=NULL) 
        return(True);
			/* B.A. : New. Forward references allowed. But check, if everything is ok ... */
			if(pi->pass==PASS_1) { /* Pass 1 */
	      if(test_constant(pi,next,"Can't redefine constant %s, use .SET instead")!=NULL) 
  	      return(True);
	      if(def_const(pi, next, i)==False)
    	      return(False);
			} else { /* Pass 2 */
				int j;
				if(get_constant(pi, next, &j)==False) {   /* Defined in Pass 1 and now missing ? */
   	      print_msg(pi, MSGTYPE_ERROR, "Constant %s is missing in pass 2", next);
  	      return(False);
				}
				if(i != j) {
   	      print_msg(pi, MSGTYPE_ERROR, "Constant %s changed value from %d in pass1 to %d in pass 2", next,j,i);
  	      return(False);
				}
				/* OK. Definition is unchanged */
			}
			if((pi->pass == PASS_2) && pi->list_line && pi->list_on) {
				fprintf(pi->list_file, "          %s\n", pi->list_line);
				pi->list_line = NULL;
			}
			break;
		case DIRECTIVE_NOOVERLAP:
			if (pi->pass == PASS_1) {
				fix_orglist(pi->segment);
				pi->segment_overlap = SEG_DONT_OVERLAP;
				def_orglist(pi->segment);
			}
			break;
		case DIRECTIVE_OVERLAP:
			if (pi->pass == PASS_1) {
				fix_orglist(pi->segment);
				pi->segment_overlap = SEG_ALLOW_OVERLAP;
				def_orglist(pi->segment);
			}
			break;
		case DIRECTIVE_PRAGMA:
			if (!next) {
				print_msg(pi, MSGTYPE_ERROR, "PRAGMA needs an operand, %s should be specified",
					snprint_list(buf, sizeof(buf), pragma_list));
				return(True);
			}
			my_strupr(next);
			data = get_next_token(next, TERM_SPACE);
			pragma = lookup_keyword(pragma_list, next, False);
			switch (pragma) {

				case PRAGMA_OVERLAP:
					if (pi->pass == PASS_1) {
						int overlap_setting = OVERLAP_UNDEFINED;
						if (data) {
								my_strupr(data);
								overlap_setting = lookup_keyword(overlap_value, data, False);
						};
						switch (overlap_setting) {
								case OVERLAP_DEFAULT:
									pi->effective_overlap = GET_ARG_I(pi->args, ARG_OVERLAP);
									break;

								case OVERLAP_IGNORE:
								case OVERLAP_WARNING:
								case OVERLAP_ERROR:
									pi->effective_overlap = overlap_setting;
									break;

								default:
									print_msg(pi, MSGTYPE_ERROR, "For PRAGMA %s directive" 
										" %s should be specified as the parameter", next, 
										snprint_list(buf, sizeof(buf), overlap_value));
									return(False);
						}
					}
					return(True);
					break;
				default:
					if(pi->pass == PASS_2)
						print_msg(pi, MSGTYPE_MESSAGE, "PRAGMA %s directive currently ignored", next);
					return(True);
			}
			break;
		case DIRECTIVE_UNDEF: // TODO
			break;
		case DIRECTIVE_IFDEF:
			if(!next)
				{
				print_msg(pi, MSGTYPE_ERROR, ".IFDEF needs an operand");
				return(True);
				}
			get_next_token(next, TERM_END);
			/* B.A. : Forward referenc is not allowed for ifdef and ifndef */
			/* Store undefined symbols in blacklist in pass1 and check, if they are still undefined in pass2 */
			if(get_symbol(pi, next, NULL)) {
#if 0
					// If it's not defined in the first pass, but was defined later
					// then it should be considered OK with regards to ifdef..endif and
					// ifndef..endif code sections. Removed this code.
				if(pi->pass==PASS_2) { /* B.A. : 'Still undefined'-test in pass 2 */
 		          if(test_blacklist(pi,next,"Forward reference (%s) not allowed in .ifdef directive")!=NULL)
					return(False);
				}
#else
				pi->conditional_depth++;
#endif
			} else {
				if(pi->pass==PASS_1) { /* B.A. : Store undefined symbols in pass 1 */
          if(def_blacklist(pi, next)==False) 
   	        return(False);
 				}
				if(!spool_conditional(pi, False))
	        return(False);
			}
			break;
		case DIRECTIVE_IFNDEF:
			if(!next)
				{
				print_msg(pi, MSGTYPE_ERROR, ".IFNDEF needs an operand");
				return(True);
				}
			get_next_token(next, TERM_END);
			/* B.A. : Forward referenc is not allowed for ifdef and ifndef */
			/* Store undefined symbols in blacklist in pass1 and check, if they are still undefined in pass2 */
			if(!get_symbol(pi, next, NULL))
		        {
#if 0
				if(pi->pass==PASS_2) { /* B.A. : 'Still undefined'-test in pass 2 */
					// If it's not defined in the first pass, but was defined later
					// then it should be considered OK with regards to ifdef..endif and
					// ifndef..endif code sections. Removed this code.
 		          if(test_blacklist(pi,next,"Forward reference (%s) not allowed in .ifndef directive")!=NULL)
					return(False);
				}
				if(!spool_conditional(pi, False))
				        return(False);
#else
				pi->conditional_depth++;
#endif
				}
			else {
				if(pi->pass==PASS_1) { /* B.A. : Store undefined symbols in pass 1 */
		          if(def_blacklist(pi, next)==False) 
		   	        return(False);
 				}
				if(!spool_conditional(pi, False))
					return(False);
			}
			break;
		case DIRECTIVE_IF:
			if(!next)
				{
				print_msg(pi, MSGTYPE_ERROR, ".IF needs an expression");
				return(True);
				}
			get_next_token(next, TERM_END);
			if(!get_expr(pi, next, &i))
			        return(False);
			if(i)
				pi->conditional_depth++;
			else
			        {
				if(!spool_conditional(pi, False))
				        return(False);
				}
			break;
		case DIRECTIVE_ELSE:
		case DIRECTIVE_ELIF: 
		case DIRECTIVE_ELSEIF: 
		        if(!spool_conditional(pi, True))
			        return(False);
			break;
		case DIRECTIVE_ENDIF:
		        if(pi->conditional_depth == 0)
			        print_msg(pi, MSGTYPE_ERROR, "Too many .ENDIF");
			else
			        pi->conditional_depth--;
			break;
		case DIRECTIVE_MESSAGE:
			if(pi->pass == PASS_1)
				return(True);
			if(!next) {
				print_msg(pi, MSGTYPE_ERROR, "No message parameter supplied");
				return(True);
			} 
			/* B.A : Extended .MESSAGE. Now a comma separated list like in .db is possible and not only a string */
			print_msg(pi, MSGTYPE_MESSAGE_NO_LF, NULL); 	/* Prints Line Header (filename, linenumber) without trailing /n */
		    while(next) { 	/* Modified code from parse_db(). Thank you :-) */
			  data = get_next_token(next, TERM_COMMA);
				if(next[0] == '\"') { 	/* string parsing */
	              next = term_string(pi, next);
		 		  print_msg(pi, MSGTYPE_APPEND,"%s",next);
			      while(*next != '\0') {
					next++;
	    		  }
				} else {
 		          if(!get_expr(pi, next, &i)) {
			 		print_msg(pi, MSGTYPE_APPEND,"\n"); /* Add newline */
  		            return(False);
				  }
		 		  print_msg(pi, MSGTYPE_APPEND,"0x%02X",i);
	           }			
    	   	next = data;
		    }
	 		print_msg(pi, MSGTYPE_APPEND,"\n"); /* Add newline */
			break;
		case DIRECTIVE_WARNING:
			if(pi->pass == PASS_1)
				return(True);
			if(!next) {
				print_msg(pi, MSGTYPE_ERROR, "No warning string supplied");
				return(True);
			}
			next = term_string(pi, next);
			print_msg(pi, MSGTYPE_WARNING, next);
			break;
		case DIRECTIVE_ERROR:		
			if(!next) { /* B.A : Fix segfault bug if .error without parameter was used */
				print_msg(pi, MSGTYPE_ERROR, "No error string supplied");
				return(True);
		    }
			next = term_string(pi, next);		
			print_msg(pi, MSGTYPE_ERROR, "%s", next);
            pi->error_count = pi->max_errors;
			if(pi->pass == PASS_1)
				return(True);
			break;
	}