1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
|
/*
* picasm -- config.c
*
* Copyright 1995-2004 Timo Rossi, <trossi@iki.fi>
* See the file LICENSE for license terms.
*
* The code in this file handles configuration fuse
* setting with the CONFIG-directive
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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;
}
|