Ejemplo n.º 1
0
static void def_dev(struct prog_info *pi)
{
	def_var(pi,DEV_VAR,LastDevice);
	def_var(pi,FLASH_VAR,device_list[LastDevice].flash_size);
	def_var(pi,EEPROM_VAR,device_list[LastDevice].eeprom_size);
	def_var(pi,RAM_VAR,device_list[LastDevice].ram_size);
}
Ejemplo n.º 2
0
int main(int argc, char** argv) {

    globalLexTable = new LexemTable();
    globalTypeTable = new TypeTable();
    globalValueTable = new ValueTable();

    try {
        while ( (curr_tok = yylex()) != 0 ) {
            switch ( curr_tok ) {
            case TYPE:
                def_var();
                break;
            case ID:
                expr(false);
                break;
            case PRINT:
                print_var();
                break;
            }

            if ( curr_tok != SEMICOLON ) {
                curr_tok = yylex();
                if ( curr_tok != SEMICOLON ) {
                    std::cout << curr_tok << std::endl;
                    throw "; expected";
                }
            }
        }
    } catch(const char* s) {
        std::cout << s << std::endl;
    }

    delete globalLexTable;
    delete globalTypeTable;

    return 0;
}
Ejemplo n.º 3
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;
	}