mirror of
https://github.com/uffejakobsen/acme.git
synced 2024-11-25 23:49:25 +00:00
Refactoring only; no change in functionality.
git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@48 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
parent
c53505915d
commit
de896f41f2
@ -17,7 +17,7 @@
|
||||
|
||||
#define RELEASE "0.95.4" // update before release (FIXME)
|
||||
#define CODENAME "Fenchurch" // update before release
|
||||
#define CHANGE_DATE "3 Dec" // update before release
|
||||
#define CHANGE_DATE "4 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
|
||||
@ -562,7 +562,6 @@ int main(int argc, const char *argv[])
|
||||
Mnemo_init();
|
||||
Output_init(fill_value);
|
||||
pseudoopcodes_init(); // setup keyword tree for pseudo opcodes
|
||||
Section_init();
|
||||
if (do_actual_work())
|
||||
save_output_file();
|
||||
return ACME_finalize(EXIT_SUCCESS); // dump labels, if wanted
|
||||
|
37
src/global.c
37
src/global.c
@ -37,6 +37,9 @@ const char s_eor[] = "eor";
|
||||
const char s_error[] = "error";
|
||||
const char s_lsr[] = "lsr";
|
||||
const char s_scrxor[] = "scrxor";
|
||||
char s_untitled[] = "<untitled>"; // FIXME - this is actually const
|
||||
const char s_Zone[] = "Zone";
|
||||
const char s_subzone[] = "subzone";
|
||||
// Exception messages during assembly
|
||||
const char exception_cannot_open_input_file[] = "Cannot open input file.";
|
||||
const char exception_missing_string[] = "No string given.";
|
||||
@ -145,38 +148,6 @@ static void parse_pc_def(void) // Now GotByte = "*"
|
||||
}
|
||||
|
||||
|
||||
// Parse pseudo opcodes. Has to be re-entrant.
|
||||
static void parse_pseudo_opcode(void) // Now GotByte = "!"
|
||||
{
|
||||
void *node_body;
|
||||
enum eos (*fn)(void),
|
||||
then = SKIP_REMAINDER; // prepare for errors
|
||||
|
||||
GetByte(); // read next byte
|
||||
// on missing keyword, return (complaining will have been done)
|
||||
if (Input_read_and_lower_keyword()) {
|
||||
|
||||
// move this to pseudoopcodes.c:
|
||||
// search for tree item
|
||||
if ((Tree_easy_scan(pseudo_opcode_tree, &node_body, GlobalDynaBuf))
|
||||
&& node_body) {
|
||||
fn = (enum eos (*)(void)) node_body;
|
||||
SKIPSPACE();
|
||||
// call function
|
||||
then = fn();
|
||||
} else {
|
||||
Throw_error("Unknown pseudo opcode.");
|
||||
}
|
||||
}
|
||||
if (then == SKIP_REMAINDER)
|
||||
Input_skip_remainder();
|
||||
else if (then == ENSURE_EOS)
|
||||
Input_ensure_EOS();
|
||||
// the other two possibilities (PARSE_REMAINDER and AT_EOS_ANYWAY)
|
||||
// will lead to the remainder of the line being parsed by the mainloop.
|
||||
}
|
||||
|
||||
|
||||
// Check and return whether first label of statement. Complain if not.
|
||||
static int first_label_of_statement(int *statement_flags)
|
||||
{
|
||||
@ -292,7 +263,7 @@ void Parse_until_eob_or_eof(void)
|
||||
parse_forward_anon_def(&statement_flags);
|
||||
break;
|
||||
case PSEUDO_OPCODE_PREFIX:
|
||||
parse_pseudo_opcode();
|
||||
pseudoopcode_parse();
|
||||
break;
|
||||
case '*':
|
||||
parse_pc_def();
|
||||
|
16
src/global.h
16
src/global.h
@ -32,7 +32,11 @@ extern const char s_eor[];
|
||||
extern const char s_error[];
|
||||
extern const char s_lsr[];
|
||||
extern const char s_scrxor[];
|
||||
// Error messages during assembly
|
||||
extern char s_untitled[];
|
||||
extern const char s_Zone[];
|
||||
#define s_zone (s_subzone + 3) // Yes, I know I'm sick
|
||||
extern const char s_subzone[];
|
||||
// error messages during assembly
|
||||
extern const char exception_cannot_open_input_file[];
|
||||
extern const char exception_missing_string[];
|
||||
extern const char exception_no_left_brace[];
|
||||
@ -42,7 +46,7 @@ extern const char exception_no_right_brace[];
|
||||
extern const char exception_number_out_of_range[];
|
||||
extern const char exception_pc_undefined[];
|
||||
extern const char exception_syntax[];
|
||||
// Byte flags table
|
||||
// byte flags table
|
||||
extern const char Byte_flags[];
|
||||
#define BYTEFLAGS(c) (Byte_flags[(unsigned char) c])
|
||||
#define STARTS_KEYWORD (1u << 7) // Byte is allowed to start a keyword
|
||||
@ -55,7 +59,7 @@ extern const char Byte_flags[];
|
||||
|
||||
|
||||
// structures
|
||||
// different ways to handle end-of-statement:
|
||||
// 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
|
||||
@ -68,7 +72,7 @@ extern int warn_on_indented_labels; // warn if indented label is encountered
|
||||
extern int warn_on_old_for; // warn if "!for" with old syntax is found
|
||||
extern int warn_on_type_mismatch; // use type-checking system
|
||||
extern char GotByte; // Last byte read (processed)
|
||||
// Global counters
|
||||
// global counters
|
||||
extern int pass_undefined_count; // "NeedValue" type errors in current pass
|
||||
extern int pass_real_errors; // Errors yet
|
||||
extern signed long max_errors; // errors before giving up
|
||||
@ -104,7 +108,7 @@ do { \
|
||||
|
||||
// Prototypes
|
||||
|
||||
// Allocate memory and die if not available
|
||||
// allocate memory and die if not available
|
||||
extern void *safe_malloc(size_t);
|
||||
// Parse block, beginning with next byte.
|
||||
// End reason (either CHAR_EOB or CHAR_EOF) can be found in GotByte afterwards
|
||||
@ -132,7 +136,7 @@ extern void Throw_error(const char *);
|
||||
// assembly. Example: "!fill" without a parameter - the program counter cannot
|
||||
// be set correctly in this case, so proceeding would be of no use at all.
|
||||
extern void Throw_serious_error(const char *);
|
||||
// Handle bugs
|
||||
// handle bugs
|
||||
extern void Bug_found(const char *, int);
|
||||
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "input.h"
|
||||
#include "global.h"
|
||||
#include "output.h"
|
||||
#include "section.h"
|
||||
#include "tree.h"
|
||||
#include "typesystem.h"
|
||||
#include "pseudoopcodes.h"
|
||||
@ -251,6 +252,51 @@ static enum eos po_skip(void) // now GotByte = illegal char
|
||||
}
|
||||
*/
|
||||
|
||||
// switch to new zone ("!zone" or "!zn"). has to be re-entrant.
|
||||
static enum eos po_zone(void)
|
||||
{
|
||||
struct section entry_values; // buffer for outer zone
|
||||
char *new_title;
|
||||
int allocated;
|
||||
|
||||
// remember everything about current structure
|
||||
entry_values = *Section_now;
|
||||
// set default values in case there is no valid title
|
||||
new_title = s_untitled;
|
||||
allocated = FALSE;
|
||||
// Check whether a zone title is given. If yes and it can be read,
|
||||
// get copy, remember pointer and remember to free it later on.
|
||||
if (BYTEFLAGS(GotByte) & CONTS_KEYWORD) {
|
||||
// Because we know of one character for sure,
|
||||
// there's no need to check the return value.
|
||||
Input_read_keyword();
|
||||
new_title = DynaBuf_get_copy(GlobalDynaBuf);
|
||||
allocated = TRUE;
|
||||
}
|
||||
// setup new section
|
||||
// section type is "subzone", just in case a block follows
|
||||
Section_new_zone(Section_now, "Subzone", new_title, allocated);
|
||||
if (Parse_optional_block()) {
|
||||
// Block has been parsed, so it was a SUBzone.
|
||||
Section_finalize(Section_now); // end inner zone
|
||||
*Section_now = entry_values; // restore entry values
|
||||
} else {
|
||||
// no block found, so it's a normal zone change
|
||||
Section_finalize(&entry_values); // end outer zone
|
||||
Section_now->type = s_Zone; // change type to "Zone"
|
||||
}
|
||||
return ENSURE_EOS;
|
||||
}
|
||||
|
||||
// "!subzone" or "!sz" pseudo opcode (now obsolete)
|
||||
static enum eos po_subzone(void)
|
||||
{
|
||||
Throw_error("\"!subzone {}\" is obsolete; use \"!zone {}\" instead.");
|
||||
// call "!zone" instead
|
||||
return po_zone();
|
||||
}
|
||||
|
||||
|
||||
// constants
|
||||
#define USERMSG_DYNABUF_INITIALSIZE 80
|
||||
|
||||
@ -364,6 +410,10 @@ static struct ronode pseudo_opcodes[] = {
|
||||
PREDEFNODE("addr", po_addr),
|
||||
PREDEFNODE("address", po_addr),
|
||||
// PREDEFNODE("skip", po_skip),
|
||||
PREDEFNODE(s_zone, po_zone),
|
||||
PREDEFNODE("zn", po_zone),
|
||||
PREDEFNODE(s_subzone, po_subzone),
|
||||
PREDEFNODE("sz", po_subzone),
|
||||
// PREDEFNODE("debug", po_debug),
|
||||
// PREDEFNODE("info", po_info),
|
||||
PREDEFNODE("warn", po_warn),
|
||||
@ -379,3 +429,33 @@ void pseudoopcodes_init(void)
|
||||
user_message = DynaBuf_create(USERMSG_DYNABUF_INITIALSIZE);
|
||||
Tree_add_table(&pseudo_opcode_tree, pseudo_opcodes);
|
||||
}
|
||||
|
||||
|
||||
// parse a pseudo opcode. has to be re-entrant.
|
||||
void pseudoopcode_parse(void) // Now GotByte = "!"
|
||||
{
|
||||
void *node_body;
|
||||
enum eos (*fn)(void),
|
||||
then = SKIP_REMAINDER; // prepare for errors
|
||||
|
||||
GetByte(); // read next byte
|
||||
// on missing keyword, return (complaining will have been done)
|
||||
if (Input_read_and_lower_keyword()) {
|
||||
// search for tree item
|
||||
if ((Tree_easy_scan(pseudo_opcode_tree, &node_body, GlobalDynaBuf))
|
||||
&& node_body) {
|
||||
fn = (enum eos (*)(void)) node_body;
|
||||
SKIPSPACE();
|
||||
// call function
|
||||
then = fn();
|
||||
} else {
|
||||
Throw_error("Unknown pseudo opcode.");
|
||||
}
|
||||
}
|
||||
if (then == SKIP_REMAINDER)
|
||||
Input_skip_remainder();
|
||||
else if (then == ENSURE_EOS)
|
||||
Input_ensure_EOS();
|
||||
// the other two possibilities (PARSE_REMAINDER and AT_EOS_ANYWAY)
|
||||
// will lead to the remainder of the line being parsed by the mainloop.
|
||||
}
|
||||
|
@ -15,6 +15,8 @@ extern struct ronode *pseudo_opcode_tree; // tree to hold pseudo opcodes
|
||||
extern void notreallypo_setpc(void);
|
||||
// register pseudo opcodes
|
||||
extern void pseudoopcodes_init(void);
|
||||
// parse pseudo opcode. has to be re-entrant.
|
||||
extern void pseudoopcode_parse(void);
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -12,13 +12,6 @@
|
||||
#include "section.h"
|
||||
|
||||
|
||||
// Constants
|
||||
static const char type_zone[] = "Zone";
|
||||
static const char s_subzone[] = "subzone";
|
||||
#define s_zone (s_subzone + 3) // Yes, I know I'm sick
|
||||
static char untitled[] = "<untitled>";
|
||||
// ...is actually constant, but flagging it "const" results in heap of warnings
|
||||
|
||||
// fake section structure (for error msgs before any real section is in use)
|
||||
static struct section initial_section = {
|
||||
0, // zone value
|
||||
@ -53,68 +46,9 @@ void Section_finalize(struct section *section)
|
||||
free(section->title);
|
||||
}
|
||||
|
||||
// Switch to new zone ("!zone" or "!zn"). Has to be re-entrant.
|
||||
static enum eos PO_zone(void)
|
||||
{
|
||||
struct section entry_values; // buffer for outer zone
|
||||
char *new_title;
|
||||
int allocated;
|
||||
|
||||
// remember everything about current structure
|
||||
entry_values = *Section_now;
|
||||
// set default values in case there is no valid title
|
||||
new_title = untitled;
|
||||
allocated = FALSE;
|
||||
// Check whether a zone title is given. If yes and it can be read,
|
||||
// get copy, remember pointer and remember to free it later on.
|
||||
if (BYTEFLAGS(GotByte) & CONTS_KEYWORD) {
|
||||
// Because we know of one character for sure,
|
||||
// there's no need to check the return value.
|
||||
Input_read_keyword();
|
||||
new_title = DynaBuf_get_copy(GlobalDynaBuf);
|
||||
allocated = TRUE;
|
||||
}
|
||||
// setup new section
|
||||
// section type is "subzone", just in case a block follows
|
||||
Section_new_zone(Section_now, "Subzone", new_title, allocated);
|
||||
if (Parse_optional_block()) {
|
||||
// Block has been parsed, so it was a SUBzone.
|
||||
Section_finalize(Section_now); // end inner zone
|
||||
*Section_now = entry_values; // restore entry values
|
||||
} else {
|
||||
// no block found, so it's a normal zone change
|
||||
Section_finalize(&entry_values); // end outer zone
|
||||
Section_now->type = type_zone; // change type to "zone"
|
||||
}
|
||||
return ENSURE_EOS;
|
||||
}
|
||||
|
||||
// "!subzone" or "!sz" pseudo opcode (now obsolete)
|
||||
static enum eos PO_subzone(void)
|
||||
{
|
||||
Throw_error("\"!subzone {}\" is obsolete; use \"!zone {}\" instead.");
|
||||
// call "!zone" instead
|
||||
return PO_zone();
|
||||
}
|
||||
|
||||
// predefined stuff
|
||||
static struct ronode pseudo_opcodes[] = {
|
||||
PREDEFNODE(s_zone, PO_zone),
|
||||
PREDEFNODE("zn", PO_zone),
|
||||
PREDEFNODE(s_subzone, PO_subzone),
|
||||
PREDEFLAST("sz", PO_subzone),
|
||||
// ^^^^ this marks the last element
|
||||
};
|
||||
|
||||
// register pseudo opcodes
|
||||
void Section_init(void)
|
||||
{
|
||||
Tree_add_table(&pseudo_opcode_tree, pseudo_opcodes);
|
||||
}
|
||||
|
||||
// Setup outermost section
|
||||
void Section_passinit(void)
|
||||
{
|
||||
zone_max = ZONE_GLOBAL; // will be incremented by next line
|
||||
Section_new_zone(&outer_section, type_zone, untitled, FALSE);
|
||||
Section_new_zone(&outer_section, s_Zone, s_untitled, FALSE);
|
||||
}
|
||||
|
@ -33,8 +33,6 @@ extern struct section *Section_now;
|
||||
|
||||
// Write given info into given zone structure and activate it
|
||||
extern void Section_new_zone(struct section *section, const char *type, char *title, int allocated);
|
||||
// register pseudo opcodes
|
||||
extern void Section_init(void);
|
||||
// Setup outermost section
|
||||
extern void Section_passinit(void);
|
||||
// Tidy up: If necessary, release section title.
|
||||
|
Loading…
Reference in New Issue
Block a user