/* * picasm -- config.c * * Copyright 1995-2004 Timo Rossi, * See the file LICENSE for license terms. * * The code in this file handles configuration fuse * setting with the CONFIG-directive * */ #include #include #include #include "picasm.h" #include "token.h" #include "symtab.h" /* * parse the CONFIG directive * * This basically repeatedly expands the __do_config macro with * the appropriate parameters. * */ void parse_config(void) { static char keyword[260]; struct symbol *config_macro_sym; char *args[2]; int npairs; #define MAX_PAIRS 30 char *keywords[MAX_PAIRS]; char *values[MAX_PAIRS]; int i; if(pic_instr_set == PIC_NONE) fatal_error("PIC device type not set"); config_macro_sym = lookup_symbol("__do_config", SYMTAB_GLOBAL); if(config_macro_sym == NULL || config_macro_sym->type != SYM_MACRO) { error(1, "__do_config not defined, cannot set configuration bits"); return; } npairs = 0; for(;;) { if(token_type != TOK_IDENTIFIER) { cfg_error: error(1, "CONFIG syntax error"); return; } strcpy(keyword, token_string); get_token(); /* hmm... this is a little kludge, but as the tokenizer now makes 'local id's from the valid config strings, this must be used... */ if(token_type != TOK_LOCAL_ID) { if(token_type != TOK_EQUAL) { error(1, "'=' expected"); return; } get_token(); if(token_type != TOK_IDENTIFIER) goto cfg_error; } if(npairs >= MAX_PAIRS) { error(0, "Too many config keyword=value pairs"); break; } keywords[npairs] = mem_alloc(strlen(keyword) + 1); strcpy(keywords[npairs], keyword); values[npairs] = mem_alloc(strlen(token_string) + 1); strcpy(values[npairs], token_string); npairs++; get_token(); if(token_type != TOK_COMMA) break; get_token(); } skip_eol(); write_listing_line(0); listing_on = 0; for(i = 0; i < npairs; i++) { args[0] = keywords[i]; args[1] = values[i]; expand_macro_with_args(config_macro_sym, args, 2, 1); mem_free(keywords[i]); mem_free(values[i]); } } void config_done(void) { struct symbol *config_sym; config_sym = lookup_symbol("__config", SYMTAB_GLOBAL); if(config_sym == NULL || config_sym->type != SYM_SET) { error(0, "Internal CONFIG error: __config not defined (or wrong type)"); return; } config_fuses = config_sym->v.value; /* * This causes the config fuses to be output on the "exitm" listing line. * Not very clean, but at least we get the config fuses in the listing. */ list_flags = LIST_VAL; list_val = config_fuses; listing_on = 1; }