File: config.c

package info (click to toggle)
picasm 1.14-3
  • links: PTS
  • area: main
  • in suites: lenny, squeeze
  • size: 528 kB
  • ctags: 378
  • sloc: ansic: 4,481; asm: 150; makefile: 72
file content (135 lines) | stat: -rw-r--r-- 2,706 bytes parent folder | download | duplicates (2)
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;
}