mirror of
https://github.com/uffejakobsen/acme.git
synced 2025-01-12 05:31:19 +00:00
refactoring - now all pseudo opcodes are back together in one file. no change in functionality.
git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@53 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
parent
2331709a35
commit
4bcae073f9
@ -17,15 +17,15 @@
|
||||
|
||||
#define RELEASE "0.95.4" // update before release (FIXME)
|
||||
#define CODENAME "Fenchurch" // update before release
|
||||
#define CHANGE_DATE "16 Dec" // update before release
|
||||
#define CHANGE_DATE "22 Dec" // update before release
|
||||
#define CHANGE_YEAR "2014" // update before release
|
||||
//#define HOME_PAGE "http://home.pages.de/~mac_bacon/smorbrod/acme/" // FIXME
|
||||
#define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME
|
||||
|
||||
#include "acme.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "acme.h"
|
||||
#include "alu.h"
|
||||
#include "cliargs.h"
|
||||
#include "config.h"
|
||||
@ -254,7 +254,7 @@ static int perform_pass(void)
|
||||
// Process toplevel files
|
||||
for (ii = 0; ii < toplevel_src_count; ++ii) {
|
||||
if ((fd = fopen(toplevel_sources[ii], FILE_READBINARY))) {
|
||||
Parse_and_close_file(fd, toplevel_sources[ii]);
|
||||
flow_parse_and_close_file(fd, toplevel_sources[ii]);
|
||||
} else {
|
||||
fprintf(stderr, "Error: Cannot open toplevel file \"%s\".\n", toplevel_sources[ii]);
|
||||
// FIXME - if "filename" starts with "-", tell user to give options FIRST, files SECOND!
|
||||
@ -558,7 +558,6 @@ int main(int argc, const char *argv[])
|
||||
cliargs_get_rest(&toplevel_src_count, &toplevel_sources, "No top level sources given");
|
||||
// Init modules (most of them will just build keyword trees)
|
||||
ALU_init();
|
||||
Flow_init();
|
||||
Macro_init();
|
||||
Mnemo_init();
|
||||
Output_init(fill_value);
|
||||
|
@ -11,10 +11,10 @@
|
||||
// 7 May 2014 C-style "==" operators are now recognized (but
|
||||
// give a warning).
|
||||
// 31 May 2014 Added "0b" binary number prefix as alternative to "%".
|
||||
#include "alu.h"
|
||||
#include <stdlib.h>
|
||||
#include <math.h> // only for fp support
|
||||
#include "platform.h"
|
||||
#include "alu.h"
|
||||
#include "dynabuf.h"
|
||||
#include "encoding.h"
|
||||
#include "global.h"
|
||||
|
@ -3,10 +3,10 @@
|
||||
// Have a look at "acme.c" for further info
|
||||
//
|
||||
// CLI argument stuff
|
||||
#include "cliargs.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "config.h"
|
||||
#include "cliargs.h"
|
||||
|
||||
|
||||
// constants
|
||||
|
@ -3,15 +3,14 @@
|
||||
// Have a look at "acme.c" for further info
|
||||
//
|
||||
// CPU type stuff
|
||||
#include "cpu.h"
|
||||
#include "config.h"
|
||||
#include "alu.h"
|
||||
#include "cpu.h"
|
||||
#include "dynabuf.h"
|
||||
#include "global.h" // FIXME - remove when no longer needed
|
||||
#include "input.h"
|
||||
#include "mnemo.h"
|
||||
#include "output.h"
|
||||
#include "pseudoopcodes.h" // FIXME - remove when no longer needed
|
||||
#include "tree.h"
|
||||
|
||||
|
||||
|
@ -3,12 +3,12 @@
|
||||
// Have a look at "acme.c" for further info
|
||||
//
|
||||
// Dynamic buffer stuff
|
||||
#include "dynabuf.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "acme.h"
|
||||
#include "global.h"
|
||||
#include "dynabuf.h"
|
||||
#include "input.h"
|
||||
|
||||
|
||||
|
@ -3,15 +3,14 @@
|
||||
// Have a look at "acme.c" for further info
|
||||
//
|
||||
// Character encoding stuff
|
||||
#include "encoding.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "alu.h"
|
||||
#include "acme.h"
|
||||
#include "dynabuf.h"
|
||||
#include "encoding.h"
|
||||
#include "global.h" // FIXME - remove when no longer needed
|
||||
#include "output.h"
|
||||
#include "pseudoopcodes.h" // FIXME - remove when no longer needed
|
||||
#include "input.h"
|
||||
#include "tree.h"
|
||||
|
||||
|
240
src/flow.c
240
src/flow.c
@ -11,6 +11,7 @@
|
||||
// function uses the same technique to parse the top level file.
|
||||
//
|
||||
// 24 Nov 2007 Added "!ifndef"
|
||||
#include "flow.h"
|
||||
#include <string.h>
|
||||
#include "acme.h"
|
||||
#include "alu.h"
|
||||
@ -19,39 +20,72 @@
|
||||
#include "global.h" // FIXME - remove when no longer needed
|
||||
#include "input.h"
|
||||
#include "mnemo.h"
|
||||
#include "pseudoopcodes.h" // FIXME - remove when no longer needed
|
||||
#include "symbol.h"
|
||||
#include "tree.h"
|
||||
|
||||
|
||||
// type definitions
|
||||
|
||||
struct loop_condition {
|
||||
int line; // original line number
|
||||
int is_until; // actually bool (0 for WHILE, 1 for UNTIL)
|
||||
char *body; // pointer to actual expression
|
||||
};
|
||||
|
||||
|
||||
// helper functions for "!for" and "!do"
|
||||
|
||||
// parse a loop body (could also be used for macro body)
|
||||
static void parse_ram_block(int line_number, char *body)
|
||||
// parse a loop body (TODO - also use for macro body?)
|
||||
static void parse_ram_block(struct block *block)
|
||||
{
|
||||
Input_now->line_number = line_number; // set line number to loop start
|
||||
Input_now->src.ram_ptr = body; // set RAM read pointer to loop
|
||||
// parse loop body
|
||||
Input_now->line_number = block->start; // set line number to loop start
|
||||
Input_now->src.ram_ptr = block->body; // set RAM read pointer to loop
|
||||
// parse block
|
||||
Parse_until_eob_or_eof();
|
||||
if (GotByte != CHAR_EOB)
|
||||
Bug_found("IllegalBlockTerminator", GotByte);
|
||||
}
|
||||
|
||||
|
||||
// back end function for "!for" pseudo opcode
|
||||
void flow_forloop(struct for_loop *loop)
|
||||
{
|
||||
struct input loop_input,
|
||||
*outer_input;
|
||||
struct result loop_counter;
|
||||
|
||||
// switching input makes us lose GotByte. But we know it's '}' anyway!
|
||||
// set up new input
|
||||
loop_input = *Input_now; // copy current input structure into new
|
||||
loop_input.source_is_ram = TRUE; // set new byte source
|
||||
// remember old input
|
||||
outer_input = Input_now;
|
||||
// activate new input
|
||||
// (not yet useable; pointer and line number are still missing)
|
||||
Input_now = &loop_input;
|
||||
// init counter
|
||||
loop_counter.flags = MVALUE_DEFINED | MVALUE_EXISTS;
|
||||
loop_counter.val.intval = loop->counter_first;
|
||||
symbol_set_value(loop->symbol, &loop_counter, TRUE);
|
||||
if (loop->old_algo) {
|
||||
// old algo for old syntax:
|
||||
// if count == 0, skip loop
|
||||
if (loop->counter_last) {
|
||||
do {
|
||||
loop_counter.val.intval += loop->counter_increment;
|
||||
symbol_set_value(loop->symbol, &loop_counter, TRUE);
|
||||
parse_ram_block(&loop->block);
|
||||
} while (loop_counter.val.intval < loop->counter_last);
|
||||
}
|
||||
} else {
|
||||
// new algo for new syntax:
|
||||
do {
|
||||
parse_ram_block(&loop->block);
|
||||
loop_counter.val.intval += loop->counter_increment;
|
||||
symbol_set_value(loop->symbol, &loop_counter, TRUE);
|
||||
} while (loop_counter.val.intval != (loop->counter_last + loop->counter_increment));
|
||||
}
|
||||
// restore previous input:
|
||||
Input_now = outer_input;
|
||||
}
|
||||
|
||||
|
||||
// try to read a condition into DynaBuf and store copy pointer in
|
||||
// given loop_condition structure.
|
||||
// if no condition given, NULL is written to structure.
|
||||
// call with GotByte = first interesting character
|
||||
static void store_condition(struct loop_condition *condition, char terminator)
|
||||
void flow_store_doloop_condition(struct loop_condition *condition, char terminator)
|
||||
{
|
||||
// write line number
|
||||
condition->line = Input_now->line_number;
|
||||
@ -102,19 +136,11 @@ static int check_condition(struct loop_condition *condition)
|
||||
}
|
||||
|
||||
|
||||
struct loop_total {
|
||||
struct loop_condition head_cond;
|
||||
int start; // line number of loop pseudo opcode
|
||||
char *body;
|
||||
struct loop_condition tail_cond;
|
||||
};
|
||||
|
||||
// back end function for "!do" pseudo opcode
|
||||
static void do_loop(struct loop_total *loop)
|
||||
void flow_doloop(struct do_loop *loop)
|
||||
{
|
||||
struct input loop_input;
|
||||
struct input *outer_input;
|
||||
int go_on;
|
||||
|
||||
// set up new input
|
||||
loop_input = *Input_now; // copy current input structure into new
|
||||
@ -124,19 +150,15 @@ static void do_loop(struct loop_total *loop)
|
||||
// activate new input (not useable yet, as pointer and
|
||||
// line number are not yet set up)
|
||||
Input_now = &loop_input;
|
||||
do {
|
||||
for (;;) {
|
||||
// check head condition
|
||||
go_on = check_condition(&loop->head_cond);
|
||||
if (go_on) {
|
||||
parse_ram_block(loop->start, loop->body);
|
||||
// check tail condition
|
||||
go_on = check_condition(&loop->tail_cond);
|
||||
}
|
||||
} while (go_on);
|
||||
// free memory
|
||||
free(loop->head_cond.body);
|
||||
free(loop->body);
|
||||
free(loop->tail_cond.body);
|
||||
if (!check_condition(&loop->head_cond))
|
||||
break;
|
||||
parse_ram_block(&loop->block);
|
||||
// check tail condition
|
||||
if (!check_condition(&loop->tail_cond))
|
||||
break;
|
||||
}
|
||||
// restore previous input:
|
||||
Input_now = outer_input;
|
||||
GotByte = CHAR_EOS; // CAUTION! Very ugly kluge.
|
||||
@ -147,133 +169,6 @@ static void do_loop(struct loop_total *loop)
|
||||
}
|
||||
|
||||
|
||||
// move to pseudoopcodes.c:
|
||||
|
||||
// looping assembly ("!do"). has to be re-entrant.
|
||||
static enum eos po_do(void) // now GotByte = illegal char
|
||||
{
|
||||
struct loop_total loop;
|
||||
|
||||
// init
|
||||
loop.head_cond.is_until = FALSE;
|
||||
loop.head_cond.body = NULL;
|
||||
loop.tail_cond.is_until = FALSE;
|
||||
loop.tail_cond.body = NULL;
|
||||
|
||||
// read head condition to buffer
|
||||
SKIPSPACE();
|
||||
store_condition(&loop.head_cond, CHAR_SOB);
|
||||
if (GotByte != CHAR_SOB)
|
||||
Throw_serious_error(exception_no_left_brace);
|
||||
// remember line number of loop body,
|
||||
// then read block and get copy
|
||||
loop.start = Input_now->line_number;
|
||||
loop.body = Input_skip_or_store_block(TRUE); // changes line number!
|
||||
// now GotByte = '}'
|
||||
NEXTANDSKIPSPACE(); // now GotByte = first non-blank char after block
|
||||
// read tail condition to buffer
|
||||
store_condition(&loop.tail_cond, CHAR_EOS);
|
||||
// now GotByte = CHAR_EOS
|
||||
do_loop(&loop);
|
||||
return AT_EOS_ANYWAY;
|
||||
}
|
||||
|
||||
|
||||
// looping assembly ("!for"). has to be re-entrant.
|
||||
// old syntax: !for VAR, END { BLOCK } VAR counts from 1 to END
|
||||
// new syntax: !for VAR, START, END { BLOCK } VAR counts from START to END
|
||||
static enum eos po_for(void) // now GotByte = illegal char
|
||||
{
|
||||
struct input loop_input,
|
||||
*outer_input;
|
||||
struct result loop_counter;
|
||||
intval_t first_arg,
|
||||
counter_first,
|
||||
counter_last,
|
||||
counter_increment;
|
||||
int old_algo; // actually bool
|
||||
char *loop_body; // pointer to loop's body block
|
||||
struct symbol *symbol;
|
||||
zone_t zone;
|
||||
int force_bit,
|
||||
loop_start; // line number of "!for" pseudo opcode
|
||||
|
||||
if (Input_read_zone_and_keyword(&zone) == 0) // skips spaces before
|
||||
return SKIP_REMAINDER;
|
||||
|
||||
// now GotByte = illegal char
|
||||
force_bit = Input_get_force_bit(); // skips spaces after
|
||||
symbol = symbol_find(zone, force_bit);
|
||||
if (!Input_accept_comma()) {
|
||||
Throw_error(exception_syntax);
|
||||
return SKIP_REMAINDER;
|
||||
}
|
||||
|
||||
first_arg = ALU_defined_int();
|
||||
if (Input_accept_comma()) {
|
||||
old_algo = FALSE; // new format - yay!
|
||||
if (!warn_on_old_for)
|
||||
Throw_first_pass_warning("Found new \"!for\" syntax.");
|
||||
counter_first = first_arg; // use given argument
|
||||
counter_last = ALU_defined_int(); // read second argument
|
||||
counter_increment = (counter_last < counter_first) ? -1 : 1;
|
||||
} else {
|
||||
old_algo = TRUE; // old format - booo!
|
||||
if (warn_on_old_for)
|
||||
Throw_first_pass_warning("Found old \"!for\" syntax.");
|
||||
if (first_arg < 0)
|
||||
Throw_serious_error("Loop count is negative.");
|
||||
counter_first = 0; // CAUTION - old algo pre-increments and therefore starts with 1!
|
||||
counter_last = first_arg; // use given argument
|
||||
counter_increment = 1;
|
||||
}
|
||||
if (GotByte != CHAR_SOB)
|
||||
Throw_serious_error(exception_no_left_brace);
|
||||
// remember line number of loop pseudo opcode
|
||||
loop_start = Input_now->line_number;
|
||||
// read loop body into DynaBuf and get copy
|
||||
loop_body = Input_skip_or_store_block(TRUE); // changes line number!
|
||||
// switching input makes us lose GotByte. But we know it's '}' anyway!
|
||||
// set up new input
|
||||
loop_input = *Input_now; // copy current input structure into new
|
||||
loop_input.source_is_ram = TRUE; // set new byte source
|
||||
// remember old input
|
||||
outer_input = Input_now;
|
||||
// activate new input
|
||||
// (not yet useable; pointer and line number are still missing)
|
||||
Input_now = &loop_input;
|
||||
// init counter
|
||||
loop_counter.flags = MVALUE_DEFINED | MVALUE_EXISTS;
|
||||
loop_counter.val.intval = counter_first;
|
||||
symbol_set_value(symbol, &loop_counter, TRUE);
|
||||
if (old_algo) {
|
||||
// old algo for old syntax:
|
||||
// if count == 0, skip loop
|
||||
if (counter_last) {
|
||||
do {
|
||||
loop_counter.val.intval += counter_increment;
|
||||
symbol_set_value(symbol, &loop_counter, TRUE);
|
||||
parse_ram_block(loop_start, loop_body);
|
||||
} while (loop_counter.val.intval < counter_last);
|
||||
}
|
||||
} else {
|
||||
// new algo for new syntax:
|
||||
do {
|
||||
parse_ram_block(loop_start, loop_body);
|
||||
loop_counter.val.intval += counter_increment;
|
||||
symbol_set_value(symbol, &loop_counter, TRUE);
|
||||
} while (loop_counter.val.intval != (counter_last + counter_increment));
|
||||
}
|
||||
// free memory
|
||||
free(loop_body);
|
||||
// restore previous input:
|
||||
Input_now = outer_input;
|
||||
// GotByte of OuterInput would be '}' (if it would still exist)
|
||||
GetByte(); // fetch next byte
|
||||
return ENSURE_EOS;
|
||||
}
|
||||
|
||||
|
||||
// helper functions for "!if", "!ifdef" and "!ifndef"
|
||||
|
||||
// parse or skip a block. Returns whether block's '}' terminator was missing.
|
||||
@ -326,7 +221,7 @@ void flow_parse_block_else_block(int parse_first)
|
||||
|
||||
|
||||
// parse a whole source code file
|
||||
void Parse_and_close_file(FILE *fd, const char *filename)
|
||||
void flow_parse_and_close_file(FILE *fd, const char *filename)
|
||||
{
|
||||
// be verbose
|
||||
if (Process_verbosity > 2)
|
||||
@ -340,18 +235,3 @@ void Parse_and_close_file(FILE *fd, const char *filename)
|
||||
// close sublevel src
|
||||
fclose(Input_now->src.fd);
|
||||
}
|
||||
|
||||
|
||||
// pseudo opcode table
|
||||
static struct ronode pseudo_opcodes[] = {
|
||||
PREDEFNODE("do", po_do),
|
||||
PREDEFLAST("for", po_for),
|
||||
// ^^^^ this marks the last element
|
||||
};
|
||||
|
||||
|
||||
// register pseudo opcodes
|
||||
void Flow_init(void)
|
||||
{
|
||||
Tree_add_table(&pseudo_opcode_tree, pseudo_opcodes);
|
||||
}
|
||||
|
43
src/flow.h
43
src/flow.h
@ -2,7 +2,7 @@
|
||||
// Copyright (C) 1998-2009 Marco Baye
|
||||
// Have a look at "acme.c" for further info
|
||||
//
|
||||
// Flow control stuff (loops, conditional assembly etc.)
|
||||
// flow control stuff (loops, conditional assembly etc.)
|
||||
#ifndef flow_H
|
||||
#define flow_H
|
||||
|
||||
@ -11,12 +11,45 @@
|
||||
#include "config.h"
|
||||
|
||||
|
||||
// Prototypes
|
||||
struct block {
|
||||
int start; // line number of start of block
|
||||
char *body;
|
||||
};
|
||||
|
||||
// register pseudo opcodes
|
||||
extern void Flow_init(void);
|
||||
// struct to pass "!for" loop stuff from pseudoopcodes.c to flow.c
|
||||
struct for_loop {
|
||||
struct symbol *symbol;
|
||||
int old_algo; // actually bool
|
||||
intval_t counter_first,
|
||||
counter_last,
|
||||
counter_increment;
|
||||
struct block block;
|
||||
};
|
||||
|
||||
// structs to pass "!do" loop stuff from pseudoopcodes.c to flow.c
|
||||
struct loop_condition {
|
||||
int line; // original line number
|
||||
int is_until; // actually bool (0 for WHILE, 1 for UNTIL)
|
||||
char *body; // pointer to actual expression
|
||||
};
|
||||
struct do_loop {
|
||||
struct loop_condition head_cond;
|
||||
struct block block;
|
||||
struct loop_condition tail_cond;
|
||||
};
|
||||
|
||||
|
||||
// back end function for "!for" pseudo opcode
|
||||
extern void flow_forloop(struct for_loop *loop);
|
||||
// try to read a condition into DynaBuf and store copy pointer in
|
||||
// given loop_condition structure.
|
||||
// if no condition given, NULL is written to structure.
|
||||
// call with GotByte = first interesting character
|
||||
extern void flow_store_doloop_condition(struct loop_condition *condition, char terminator);
|
||||
// back end function for "!do" pseudo opcode
|
||||
extern void flow_doloop(struct do_loop *loop);
|
||||
// parse a whole source code file
|
||||
extern void Parse_and_close_file(FILE *fd, const char *filename);
|
||||
extern void flow_parse_and_close_file(FILE *fd, const char *filename);
|
||||
// parse {block} [else {block}]
|
||||
extern void flow_parse_block_else_block(int parse_first);
|
||||
|
||||
|
@ -8,12 +8,12 @@
|
||||
// 2 Jun 2014 Added warn_on_old_for and warn_on_type_mismatch
|
||||
// 19 Nov 2014 Merged Johann Klasek's report listing generator patch
|
||||
// 23 Nov 2014 Merged Martin Piper's "--msvc" error output patch
|
||||
#include "global.h"
|
||||
#include <stdio.h>
|
||||
#include "platform.h"
|
||||
#include "acme.h"
|
||||
#include "cpu.h"
|
||||
#include "dynabuf.h"
|
||||
#include "global.h"
|
||||
#include "input.h"
|
||||
#include "macro.h"
|
||||
#include "output.h"
|
||||
|
@ -61,14 +61,6 @@ extern const char Byte_flags[];
|
||||
// bits 2, 1 and 0 are currently unused
|
||||
|
||||
|
||||
// structures
|
||||
// different ways to handle end-of-statement: (FIXME - after grouping all pseudo opcodes, move to pseudoopcodes.c)
|
||||
enum eos {
|
||||
SKIP_REMAINDER, // skip remainder of line - (after errors)
|
||||
ENSURE_EOS, // make sure there's nothing left in statement
|
||||
PARSE_REMAINDER, // parse what's left
|
||||
AT_EOS_ANYWAY, // actually, same as PARSE_REMAINDER
|
||||
};
|
||||
extern int pass_count;
|
||||
extern int Process_verbosity; // Level of additional output
|
||||
extern int warn_on_indented_labels; // warn if indented label is encountered
|
||||
|
@ -4,13 +4,12 @@
|
||||
//
|
||||
// Input stuff
|
||||
// 19 Nov 2014 Merged Johann Klasek's report listing generator patch
|
||||
#include "input.h"
|
||||
#include "config.h"
|
||||
#include "alu.h"
|
||||
#include "dynabuf.h"
|
||||
#include "global.h" // FIXME - remove when no longer needed
|
||||
#include "input.h"
|
||||
#include "platform.h"
|
||||
#include "pseudoopcodes.h" // FIXME - remove when no longer needed
|
||||
#include "section.h"
|
||||
#include "tree.h"
|
||||
|
||||
@ -327,6 +326,7 @@ void Input_ensure_EOS(void) // Now GotByte = first char to test
|
||||
// If "Store" is FALSE, NULL is returned.
|
||||
// After calling this function, GotByte holds '}'. Unless EOF was found first,
|
||||
// but then a serious error would have been thrown.
|
||||
// FIXME - use a struct block *ptr argument!
|
||||
char *Input_skip_or_store_block(int store)
|
||||
{
|
||||
char byte;
|
||||
|
@ -7,7 +7,8 @@
|
||||
#define input_H
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdio.h> // for FILE
|
||||
#include "config.h" // for zone_t
|
||||
|
||||
|
||||
// type definitions
|
||||
|
@ -3,6 +3,7 @@
|
||||
// Have a look at "acme.c" for further info
|
||||
//
|
||||
// Macro stuff
|
||||
#include "macro.h"
|
||||
#include <string.h> // needs strlen() + memcpy()
|
||||
#include "config.h"
|
||||
#include "platform.h"
|
||||
@ -14,7 +15,6 @@
|
||||
#include "section.h"
|
||||
#include "symbol.h"
|
||||
#include "tree.h"
|
||||
#include "macro.h"
|
||||
|
||||
|
||||
// Constants
|
||||
|
@ -3,6 +3,7 @@
|
||||
// Have a look at "acme.c" for further info
|
||||
//
|
||||
// Mnemonics stuff
|
||||
#include "mnemo.h"
|
||||
#include "config.h"
|
||||
#include "alu.h"
|
||||
#include "cpu.h"
|
||||
|
@ -7,8 +7,8 @@
|
||||
// 25 Sep 2011 Fixed bug in !to (colons in filename could be interpreted as EOS)
|
||||
// 5 Mar 2014 Fixed bug where setting *>0xffff resulted in hangups.
|
||||
// 19 Nov 2014 Merged Johann Klasek's report listing generator patch
|
||||
#include "output.h"
|
||||
#include <stdlib.h>
|
||||
//#include <stdio.h>
|
||||
#include <string.h> // for memset()
|
||||
#include "acme.h"
|
||||
#include "alu.h"
|
||||
@ -17,7 +17,6 @@
|
||||
#include "dynabuf.h"
|
||||
#include "global.h"
|
||||
#include "input.h"
|
||||
#include "output.h"
|
||||
#include "platform.h"
|
||||
#include "tree.h"
|
||||
|
||||
|
@ -3,8 +3,8 @@
|
||||
// Have a look at "acme.c" for further info
|
||||
//
|
||||
// Platform specific stuff
|
||||
#include "config.h"
|
||||
#include "platform.h"
|
||||
#include "config.h"
|
||||
|
||||
|
||||
// Amiga
|
||||
|
@ -3,6 +3,7 @@
|
||||
// Have a look at "acme.c" for further info
|
||||
//
|
||||
// pseudo opcode stuff
|
||||
#include "pseudoopcodes.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "acme.h"
|
||||
@ -20,9 +21,16 @@
|
||||
#include "symbol.h"
|
||||
#include "tree.h"
|
||||
#include "typesystem.h"
|
||||
#include "pseudoopcodes.h"
|
||||
|
||||
|
||||
// different ways to handle end-of-statement:
|
||||
enum eos {
|
||||
SKIP_REMAINDER, // skip remainder of line - (after errors)
|
||||
ENSURE_EOS, // make sure there's nothing left in statement
|
||||
PARSE_REMAINDER, // parse what's left
|
||||
AT_EOS_ANYWAY // actually, same as PARSE_REMAINDER
|
||||
};
|
||||
|
||||
// constants
|
||||
static const char s_08[] = "08";
|
||||
#define s_8 (s_08 + 1) // Yes, I know I'm sick
|
||||
@ -32,7 +40,7 @@ static const char s_08[] = "08";
|
||||
|
||||
|
||||
// variables
|
||||
struct ronode *pseudo_opcode_tree = NULL; // tree to hold pseudo opcodes
|
||||
static struct ronode *pseudo_opcode_tree = NULL; // tree to hold pseudo opcodes
|
||||
|
||||
|
||||
// not really a pseudo opcode, but close enough to be put here:
|
||||
@ -637,7 +645,7 @@ static enum eos po_source(void) // now GotByte = illegal char
|
||||
outer_input = Input_now; // remember old input
|
||||
local_gotbyte = GotByte; // CAUTION - ugly kluge
|
||||
Input_now = &new_input; // activate new input
|
||||
Parse_and_close_file(fd, filename);
|
||||
flow_parse_and_close_file(fd, filename);
|
||||
Input_now = outer_input; // restore previous input
|
||||
GotByte = local_gotbyte; // CAUTION - ugly kluge
|
||||
} else {
|
||||
@ -708,6 +716,92 @@ static enum eos po_ifndef(void) // now GotByte = illegal char
|
||||
}
|
||||
|
||||
|
||||
// looping assembly ("!for"). has to be re-entrant.
|
||||
// old syntax: !for VAR, END { BLOCK } VAR counts from 1 to END
|
||||
// new syntax: !for VAR, START, END { BLOCK } VAR counts from START to END
|
||||
static enum eos po_for(void) // now GotByte = illegal char
|
||||
{
|
||||
zone_t zone;
|
||||
int force_bit;
|
||||
intval_t first_arg;
|
||||
struct for_loop loop;
|
||||
|
||||
if (Input_read_zone_and_keyword(&zone) == 0) // skips spaces before
|
||||
return SKIP_REMAINDER;
|
||||
|
||||
// now GotByte = illegal char
|
||||
force_bit = Input_get_force_bit(); // skips spaces after
|
||||
loop.symbol = symbol_find(zone, force_bit);
|
||||
if (!Input_accept_comma()) {
|
||||
Throw_error(exception_syntax);
|
||||
return SKIP_REMAINDER;
|
||||
}
|
||||
|
||||
first_arg = ALU_defined_int();
|
||||
if (Input_accept_comma()) {
|
||||
loop.old_algo = FALSE; // new format - yay!
|
||||
if (!warn_on_old_for)
|
||||
Throw_first_pass_warning("Found new \"!for\" syntax.");
|
||||
loop.counter_first = first_arg; // use given argument
|
||||
loop.counter_last = ALU_defined_int(); // read second argument
|
||||
loop.counter_increment = (loop.counter_last < loop.counter_first) ? -1 : 1;
|
||||
} else {
|
||||
loop.old_algo = TRUE; // old format - booo!
|
||||
if (warn_on_old_for)
|
||||
Throw_first_pass_warning("Found old \"!for\" syntax.");
|
||||
if (first_arg < 0)
|
||||
Throw_serious_error("Loop count is negative.");
|
||||
loop.counter_first = 0; // CAUTION - old algo pre-increments and therefore starts with 1!
|
||||
loop.counter_last = first_arg; // use given argument
|
||||
loop.counter_increment = 1;
|
||||
}
|
||||
if (GotByte != CHAR_SOB)
|
||||
Throw_serious_error(exception_no_left_brace);
|
||||
|
||||
// remember line number of loop pseudo opcode
|
||||
loop.block.start = Input_now->line_number;
|
||||
// read loop body into DynaBuf and get copy
|
||||
loop.block.body = Input_skip_or_store_block(TRUE); // changes line number!
|
||||
|
||||
flow_forloop(&loop);
|
||||
// free memory
|
||||
free(loop.block.body);
|
||||
|
||||
// GotByte of OuterInput would be '}' (if it would still exist)
|
||||
GetByte(); // fetch next byte
|
||||
return ENSURE_EOS;
|
||||
}
|
||||
|
||||
|
||||
// looping assembly ("!do"). has to be re-entrant.
|
||||
static enum eos po_do(void) // now GotByte = illegal char
|
||||
{
|
||||
struct do_loop loop;
|
||||
|
||||
// read head condition to buffer
|
||||
SKIPSPACE();
|
||||
flow_store_doloop_condition(&loop.head_cond, CHAR_SOB); // must be freed!
|
||||
if (GotByte != CHAR_SOB)
|
||||
Throw_serious_error(exception_no_left_brace);
|
||||
// remember line number of loop body,
|
||||
// then read block and get copy
|
||||
loop.block.start = Input_now->line_number;
|
||||
// reading block changes line number!
|
||||
loop.block.body = Input_skip_or_store_block(TRUE); // must be freed!
|
||||
// now GotByte = '}'
|
||||
NEXTANDSKIPSPACE(); // now GotByte = first non-blank char after block
|
||||
// read tail condition to buffer
|
||||
flow_store_doloop_condition(&loop.tail_cond, CHAR_EOS); // must be freed!
|
||||
// now GotByte = CHAR_EOS
|
||||
flow_doloop(&loop);
|
||||
// free memory
|
||||
free(loop.head_cond.body);
|
||||
free(loop.block.body);
|
||||
free(loop.tail_cond.body);
|
||||
return AT_EOS_ANYWAY;
|
||||
}
|
||||
|
||||
|
||||
// macro definition ("!macro").
|
||||
static enum eos po_macro(void) // now GotByte = illegal char
|
||||
{
|
||||
@ -879,6 +973,8 @@ static struct ronode pseudo_opcode_list[] = {
|
||||
PREDEFNODE("if", po_if),
|
||||
PREDEFNODE("ifdef", po_ifdef),
|
||||
PREDEFNODE("ifndef", po_ifndef),
|
||||
PREDEFNODE("for", po_for),
|
||||
PREDEFNODE("do", po_do),
|
||||
PREDEFNODE("macro", po_macro),
|
||||
// PREDEFNODE("debug", po_debug),
|
||||
// PREDEFNODE("info", po_info),
|
||||
|
@ -7,10 +7,6 @@
|
||||
#define pseudoopcodes_H
|
||||
|
||||
|
||||
// FIXME - after grouping all pseudo opcodes in .c file, make this static:
|
||||
extern struct ronode *pseudo_opcode_tree; // tree to hold pseudo opcodes
|
||||
|
||||
|
||||
// call when "* = EXPRESSION" is parsed
|
||||
extern void notreallypo_setpc(void);
|
||||
// register pseudo opcodes
|
||||
|
@ -3,13 +3,12 @@
|
||||
// Have a look at "acme.c" for further info
|
||||
//
|
||||
// Section stuff
|
||||
#include "section.h"
|
||||
#include "config.h"
|
||||
#include "dynabuf.h"
|
||||
#include "global.h" // FIXME - remove when no longer needed
|
||||
#include "input.h"
|
||||
#include "pseudoopcodes.h" // FIXME - remove when no longer needed
|
||||
#include "tree.h"
|
||||
#include "section.h"
|
||||
|
||||
|
||||
// fake section structure (for error msgs before any real section is in use)
|
||||
|
@ -7,6 +7,7 @@
|
||||
// 22 Nov 2007 "warn on indented labels" is now a CLI switch
|
||||
// 25 Sep 2011 Fixed bug in !sl (colons in filename could be interpreted as EOS)
|
||||
// 23 Nov 2014 Added label output in VICE format
|
||||
#include "symbol.h"
|
||||
#include <stdio.h>
|
||||
#include "acme.h"
|
||||
#include "alu.h"
|
||||
@ -15,9 +16,7 @@
|
||||
#include "input.h"
|
||||
#include "output.h"
|
||||
#include "platform.h"
|
||||
#include "pseudoopcodes.h" // FIXME - remove when no longer needed
|
||||
#include "section.h"
|
||||
#include "symbol.h"
|
||||
#include "tree.h"
|
||||
#include "typesystem.h"
|
||||
|
||||
|
@ -2,11 +2,11 @@
|
||||
// Copyright (C) 1998-2014 Marco Baye
|
||||
// Have a look at "acme.c" for further info
|
||||
//
|
||||
// Tree stuff
|
||||
// tree stuff
|
||||
#include "tree.h"
|
||||
#include "config.h"
|
||||
#include "dynabuf.h"
|
||||
#include "global.h"
|
||||
#include "tree.h"
|
||||
#include "platform.h"
|
||||
|
||||
|
||||
|
10
src/tree.h
10
src/tree.h
@ -2,16 +2,15 @@
|
||||
// Copyright (C) 1998-2014 Marco Baye
|
||||
// Have a look at "acme.c" for further info
|
||||
//
|
||||
// Tree stuff
|
||||
// tree stuff
|
||||
#ifndef tree_H
|
||||
#define tree_H
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "config.h"
|
||||
#include <stdio.h> // for FILE
|
||||
|
||||
|
||||
// Macros for pre-defining tree node tables
|
||||
// macros for pre-defining tree node tables
|
||||
#define PREDEFNODE(s, v) {NULL, NULL, 1, s, (void *) (v)}
|
||||
#define PREDEFLAST(s, v) {NULL, NULL, 0, s, (void *) (v)}
|
||||
|
||||
@ -40,12 +39,13 @@ struct rwnode {
|
||||
};
|
||||
|
||||
|
||||
// Prototypes
|
||||
// prototypes
|
||||
|
||||
// Add predefined tree items to given tree.
|
||||
extern void Tree_add_table(struct ronode **tree, struct ronode *table_to_add);
|
||||
// Search for a given ID string in a given tree. Store "body" component in
|
||||
// node_body and return TRUE. Return FALSE if no matching item found.
|
||||
struct dynabuf;
|
||||
extern int Tree_easy_scan(struct ronode *tree, void **node_body, struct dynabuf *dyna_buf);
|
||||
// Search for a "RAM tree" item. Save pointer to found tree item in given
|
||||
// location. If no matching item is found, check the "create" flag: If set,
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Copyright (C) 1998-2014 Marco Baye
|
||||
// Have a look at "acme.c" for further info
|
||||
//
|
||||
// Type system stuff
|
||||
// type system stuff
|
||||
#include "typesystem.h"
|
||||
#include "config.h"
|
||||
#include "alu.h"
|
||||
|
Loading…
x
Reference in New Issue
Block a user