mirror of
https://github.com/uffejakobsen/acme.git
synced 2024-11-22 03:30:46 +00:00
added "output pass", to ease adding of new features.
I had to modify two regression tests because they barfed in the second pass, but real-world code would not do this, so I'm okay with this incompatibility. git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@400 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
parent
0af42c7a8a
commit
df7f1bf06b
79
src/acme.c
79
src/acme.c
@ -162,17 +162,16 @@ static void report_init(struct report *report)
|
|||||||
report->bin_used = 0;
|
report->bin_used = 0;
|
||||||
}
|
}
|
||||||
// open report file
|
// open report file
|
||||||
static int report_open(struct report *report, const char *filename)
|
static void report_open(struct report *report, const char *filename)
|
||||||
{
|
{
|
||||||
// show filename _now_ because I do not want to massage it into perror()
|
// show filename _now_ because I do not want to massage it into perror()
|
||||||
printf("Opening report file \"%s\".\n", filename);
|
printf("Opening report file \"%s\".\n", filename);
|
||||||
report->fd = fopen(filename, FILE_WRITETEXT);
|
report->fd = fopen(filename, FILE_WRITETEXT);
|
||||||
if (report->fd == NULL) {
|
if (report->fd == NULL) {
|
||||||
perror("Error: Cannot open report file");
|
perror("Error: Cannot open report file");
|
||||||
return 1;
|
exit(ACME_finalize(EXIT_FAILURE));
|
||||||
}
|
}
|
||||||
input_set_report_enabled(TRUE);
|
input_set_report_enabled(TRUE);
|
||||||
return 0; // success
|
|
||||||
}
|
}
|
||||||
// close report file
|
// close report file
|
||||||
static void report_close(struct report *report)
|
static void report_close(struct report *report)
|
||||||
@ -330,24 +329,38 @@ static void save_output_file(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// definitions for pass flags:
|
||||||
|
#define PF_COMPLAIN_ABOUT_UNDEFINEDS (1u << 0) // throw "Symbol not defined" errors
|
||||||
|
#define PF_THROW_SEGMENT_MESSAGES (1u << 1) // throw segment warnings/errors
|
||||||
|
#define PF_GENERATE_OUTPUT (1u << 2) // generate output and/or report file
|
||||||
// perform a single pass
|
// perform a single pass
|
||||||
static void perform_pass(void)
|
static void perform_pass(bits passflags)
|
||||||
{
|
{
|
||||||
FILE *fd;
|
FILE *fd;
|
||||||
int ii;
|
int ii;
|
||||||
|
|
||||||
|
// init variables
|
||||||
|
pass.counters.undefineds = 0;
|
||||||
|
//pass.counters.needvalue = 0; FIXME - use
|
||||||
|
pass.counters.symbolchanges = 0;
|
||||||
|
pass.counters.errors = 0;
|
||||||
|
pass.counters.warnings = 0;
|
||||||
|
pass.flags.complain_about_undefined = !!(passflags & PF_COMPLAIN_ABOUT_UNDEFINEDS);
|
||||||
|
pass.flags.throw_segment_messages = !!(passflags & PF_THROW_SEGMENT_MESSAGES);
|
||||||
|
pass.flags.generate_output = !!(passflags & PF_GENERATE_OUTPUT);
|
||||||
|
|
||||||
if (config.process_verbosity >= 2)
|
if (config.process_verbosity >= 2)
|
||||||
printf("Pass %d:\n", pass.number);
|
printf("Pass %d:\n", pass.number);
|
||||||
|
|
||||||
|
if (pass.flags.generate_output) {
|
||||||
|
// if wanted, open report listing
|
||||||
|
if (config.report_filename)
|
||||||
|
report_open(report, config.report_filename);
|
||||||
|
}
|
||||||
cputype_passinit(); // set default cpu type
|
cputype_passinit(); // set default cpu type
|
||||||
output_passinit(); // set initial pc or start with undefined pc
|
output_passinit(); // set initial pc or start with undefined pc
|
||||||
encoding_passinit(); // set default encoding
|
encoding_passinit(); // set default encoding
|
||||||
section_passinit(); // set initial zone (untitled)
|
section_passinit(); // set initial zone (untitled)
|
||||||
// init variables
|
|
||||||
pass.counters.undefineds = 0;
|
|
||||||
//pass.counters.needvalue = 0; FIXME - use
|
|
||||||
pass.counters.symbolchanges = 0;
|
|
||||||
pass.counters.errors = 0;
|
|
||||||
pass.counters.warnings = 0;
|
|
||||||
// process toplevel files
|
// process toplevel files
|
||||||
for (ii = 0; ii < toplevel_src_count; ++ii) {
|
for (ii = 0; ii < toplevel_src_count; ++ii) {
|
||||||
fd = fopen(toplevel_sources_plat[ii], FILE_READBINARY);
|
fd = fopen(toplevel_sources_plat[ii], FILE_READBINARY);
|
||||||
@ -367,8 +380,17 @@ static void perform_pass(void)
|
|||||||
// they would need to be evaluated.
|
// they would need to be evaluated.
|
||||||
if (config.process_verbosity >= 8)
|
if (config.process_verbosity >= 8)
|
||||||
printf("Undefined expressions: %d. Symbol updates: %d.\n", pass.counters.undefineds, pass.counters.symbolchanges);
|
printf("Undefined expressions: %d. Symbol updates: %d.\n", pass.counters.undefineds, pass.counters.symbolchanges);
|
||||||
|
// FIXME - make this into next if's "else" block:
|
||||||
if (pass.counters.errors)
|
if (pass.counters.errors)
|
||||||
exit(ACME_finalize(EXIT_FAILURE));
|
exit(ACME_finalize(EXIT_FAILURE));
|
||||||
|
|
||||||
|
if (pass.flags.generate_output) {
|
||||||
|
// FIXME - add some code here to do "if there were errors, call BUG()"
|
||||||
|
// if report listing is open, close it
|
||||||
|
if (config.report_filename)
|
||||||
|
report_close(report);
|
||||||
|
save_output_file();
|
||||||
|
}
|
||||||
// now increment pass number
|
// now increment pass number
|
||||||
// this must be done _after_ the pass because assignments done via
|
// this must be done _after_ the pass because assignments done via
|
||||||
// "-DSYMBOL=VALUE" cli args must be handled as if they were done at the
|
// "-DSYMBOL=VALUE" cli args must be handled as if they were done at the
|
||||||
@ -387,21 +409,21 @@ static void do_actual_work(void)
|
|||||||
report = &global_report; // let global pointer point to something
|
report = &global_report; // let global pointer point to something
|
||||||
report_init(report); // we must init struct before doing passes
|
report_init(report); // we must init struct before doing passes
|
||||||
|
|
||||||
sanity.macro_recursions_left = config.sanity_limit;
|
sanity.macro_recursions_left = config.sanity_limit;
|
||||||
sanity.source_recursions_left = config.sanity_limit;
|
sanity.source_recursions_left = config.sanity_limit;
|
||||||
sanity.passes_left = config.sanity_limit;
|
sanity.passes_left = config.sanity_limit;
|
||||||
|
|
||||||
pass.flags.complain_about_undefined = FALSE; // disable until error pass needed
|
// first pass:
|
||||||
pass.flags.do_segment_checks = TRUE; // FIXME - do in _last_ pass instead!
|
perform_pass(PF_THROW_SEGMENT_MESSAGES); // FIXME - check segments in all passes, but only throw errors/warnings in final pass!
|
||||||
perform_pass(); // first pass
|
|
||||||
pass.flags.do_segment_checks = FALSE; // FIXME - do in _last_ pass instead!
|
|
||||||
// pretend there has been a previous pass, with one more undefined result
|
// pretend there has been a previous pass, with one more undefined result
|
||||||
undefs_before = pass.counters.undefineds + 1;
|
undefs_before = pass.counters.undefineds + 1;
|
||||||
|
|
||||||
|
// further passes:
|
||||||
// keep doing passes as long as the number of undefined results keeps decreasing.
|
// keep doing passes as long as the number of undefined results keeps decreasing.
|
||||||
// stop on zero (FIXME - zero-check pass.counters.needvalue instead!)
|
// stop on zero (FIXME - zero-check pass.counters.needvalue instead!)
|
||||||
while ((pass.counters.undefineds && (pass.counters.undefineds < undefs_before)) || pass.counters.symbolchanges) {
|
while ((pass.counters.undefineds && (pass.counters.undefineds < undefs_before)) || pass.counters.symbolchanges) {
|
||||||
undefs_before = pass.counters.undefineds;
|
undefs_before = pass.counters.undefineds;
|
||||||
perform_pass();
|
perform_pass(0);
|
||||||
if (--sanity.passes_left < 0) {
|
if (--sanity.passes_left < 0) {
|
||||||
// FIXME - exit with error
|
// FIXME - exit with error
|
||||||
// ...or maybe do one additional pass where all errors are reported, including "not defined" and "value has changed".
|
// ...or maybe do one additional pass where all errors are reported, including "not defined" and "value has changed".
|
||||||
@ -409,27 +431,20 @@ static void do_actual_work(void)
|
|||||||
//break;
|
//break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// last pass:
|
||||||
// any errors left?
|
// any errors left?
|
||||||
if (pass.counters.undefineds == 0) { // FIXME - use pass.counters.needvalue instead!
|
if (pass.counters.undefineds == 0) { // FIXME - use pass.counters.needvalue instead!
|
||||||
// if listing report is wanted and there were no errors,
|
// victory lap
|
||||||
// do another pass to generate listing report
|
if (config.process_verbosity >= 2)
|
||||||
if (config.report_filename) {
|
puts("Extra pass to generate output.");
|
||||||
if (config.process_verbosity >= 2)
|
perform_pass(PF_GENERATE_OUTPUT);
|
||||||
puts("Extra pass to generate listing report.");
|
|
||||||
if (report_open(report, config.report_filename) == 0) {
|
|
||||||
perform_pass();
|
|
||||||
report_close(report);
|
|
||||||
}
|
|
||||||
// FIXME - add some code here to do "if there were errors, call BUG()"
|
|
||||||
}
|
|
||||||
save_output_file();
|
|
||||||
} else {
|
} else {
|
||||||
// There are still errors (unsolvable by doing further passes),
|
// There are still errors (unsolvable by doing further passes),
|
||||||
// so perform additional pass to find and show them.
|
// so perform additional pass to find and show them.
|
||||||
if (config.process_verbosity >= 2)
|
if (config.process_verbosity >= 2)
|
||||||
puts("Extra pass to display errors.");
|
puts("Extra pass to display errors.");
|
||||||
pass.flags.complain_about_undefined = TRUE; // activate error output
|
perform_pass(PF_COMPLAIN_ABOUT_UNDEFINEDS); // perform pass, but now show "value undefined"
|
||||||
perform_pass(); // perform pass, but now show "value undefined"
|
|
||||||
// FIXME - perform_pass() calls exit() when there were errors,
|
// FIXME - perform_pass() calls exit() when there were errors,
|
||||||
// so if controls returns here, call BUG()!
|
// so if controls returns here, call BUG()!
|
||||||
// (this can be triggered using ifdef/ifndef)
|
// (this can be triggered using ifdef/ifndef)
|
||||||
|
@ -118,8 +118,9 @@ struct pass {
|
|||||||
// error output pass.
|
// error output pass.
|
||||||
} counters;
|
} counters;
|
||||||
struct {
|
struct {
|
||||||
char complain_about_undefined; // will be FALSE until error pass is needed
|
boolean complain_about_undefined; // will be FALSE until error pass is needed
|
||||||
char do_segment_checks; // atm only used in pass 1, should be used in _last_ pass!
|
boolean throw_segment_messages; // atm only used in pass 1, should be used in _last_ pass!
|
||||||
|
boolean generate_output; // create output and/or report file
|
||||||
} flags;
|
} flags;
|
||||||
};
|
};
|
||||||
extern struct pass pass;
|
extern struct pass pass;
|
||||||
|
55
src/output.c
55
src/output.c
@ -99,7 +99,7 @@ static void border_crossed(int current_offset)
|
|||||||
// further:
|
// further:
|
||||||
if (current_offset >= config.outbuf_size)
|
if (current_offset >= config.outbuf_size)
|
||||||
Throw_serious_error("Reached memory limit.");
|
Throw_serious_error("Reached memory limit.");
|
||||||
if (pass.flags.do_segment_checks) {
|
if (pass.flags.throw_segment_messages) {
|
||||||
throw_message(config.debuglevel_segmentprobs, "Segment reached another one, overwriting it.", NULL);
|
throw_message(config.debuglevel_segmentprobs, "Segment reached another one, overwriting it.", NULL);
|
||||||
find_segment_max(current_offset + 1); // find new (next) limit
|
find_segment_max(current_offset + 1); // find new (next) limit
|
||||||
}
|
}
|
||||||
@ -177,29 +177,6 @@ void output_skip(int size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// fill output buffer with given byte value
|
|
||||||
static void fill_completely(char value)
|
|
||||||
{
|
|
||||||
memset(out->buffer, value, config.outbuf_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// default value for empty memory has changed (called by "!initmem" pseudo opcode)
|
|
||||||
void output_newdefault(void)
|
|
||||||
{
|
|
||||||
// init memory
|
|
||||||
fill_completely(config.mem_init_value);
|
|
||||||
// enforce another pass (FIXME - no, just do a separate output pass anyway!)
|
|
||||||
if (pass.counters.undefineds == 0)
|
|
||||||
pass.counters.undefineds = 1;
|
|
||||||
//if (pass.counters.needvalue == 0) FIXME - use? instead or additionally?
|
|
||||||
// pass.counters.needvalue = 1;
|
|
||||||
// enforcing another pass is not needed if there hasn't been any
|
|
||||||
// output yet. But that's tricky to detect without too much overhead.
|
|
||||||
// The old solution was to add &&(out->lowest_written < out->highest_written+1) to "if" above
|
|
||||||
// in future, just allocate and init outbuf at the start of the "last" pass!
|
|
||||||
}
|
|
||||||
|
|
||||||
// remember current outbuf index as start/limit of output file
|
// remember current outbuf index as start/limit of output file
|
||||||
static boolean force_file_start = FALSE;
|
static boolean force_file_start = FALSE;
|
||||||
static intval_t forced_start_idx;
|
static intval_t forced_start_idx;
|
||||||
@ -228,16 +205,10 @@ void outbuf_set_outfile_limit(void)
|
|||||||
|
|
||||||
|
|
||||||
// init output struct
|
// init output struct
|
||||||
|
// FIXME - remove this, create the buffer at start of final pass instead!
|
||||||
void output_createbuffer(void)
|
void output_createbuffer(void)
|
||||||
{
|
{
|
||||||
out->buffer = safe_malloc(config.outbuf_size);
|
out->buffer = safe_malloc(config.outbuf_size);
|
||||||
// FIXME - in future, do both of these only at start of "last" pass:
|
|
||||||
// fill memory with initial value
|
|
||||||
if (config.mem_init_value == NO_VALUE_GIVEN) {
|
|
||||||
fill_completely(0); // default value
|
|
||||||
} else {
|
|
||||||
fill_completely(config.mem_init_value & 0xff);
|
|
||||||
}
|
|
||||||
// init ring list of segments
|
// init ring list of segments
|
||||||
out->segm.list_head.next = &out->segm.list_head;
|
out->segm.list_head.next = &out->segm.list_head;
|
||||||
out->segm.list_head.prev = &out->segm.list_head;
|
out->segm.list_head.prev = &out->segm.list_head;
|
||||||
@ -272,6 +243,7 @@ static void link_segment(intval_t start, intval_t length)
|
|||||||
// check whether given PC is inside segment.
|
// check whether given PC is inside segment.
|
||||||
// only call in first pass, otherwise too many warnings might be thrown
|
// only call in first pass, otherwise too many warnings might be thrown
|
||||||
// FIXME - do it the other way round and only complain if there were no other errors!
|
// FIXME - do it the other way round and only complain if there were no other errors!
|
||||||
|
// FIXME - move this fn to its single caller!
|
||||||
static void check_segment(intval_t new_pc)
|
static void check_segment(intval_t new_pc)
|
||||||
{
|
{
|
||||||
struct segment *test_segment = out->segm.list_head.next;
|
struct segment *test_segment = out->segm.list_head.next;
|
||||||
@ -297,9 +269,23 @@ void output_passinit(void)
|
|||||||
{
|
{
|
||||||
// struct segment *temp;
|
// struct segment *temp;
|
||||||
|
|
||||||
|
// are we supposed to actually generate correct output?
|
||||||
|
if (pass.flags.generate_output) {
|
||||||
|
// FIXME - allocate output buffer using size info gathered in previous pass!
|
||||||
|
// fill output buffer with initial byte value
|
||||||
|
if (config.mem_init_value == NO_VALUE_GIVEN) {
|
||||||
|
memset(out->buffer, 0, config.outbuf_size); // default value
|
||||||
|
} else {
|
||||||
|
memset(out->buffer, config.mem_init_value & 0xff, config.outbuf_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//FIXME - why clear ring list in every pass?
|
//FIXME - why clear ring list in every pass?
|
||||||
// Because later pass shouldn't complain about overwriting the same segment from earlier pass!
|
// Because later pass shouldn't complain about overwriting the same segment from earlier pass!
|
||||||
// Currently this does not happen because segment warnings are only generated in first pass. FIXME!
|
// Currently this does not happen because segment warnings are only generated in first pass.
|
||||||
|
// FIXME - in future we want to _output_ the errors/warnings in the final pass only,
|
||||||
|
// but we need to _check_ for them in every pass because only the results of the second-to-last
|
||||||
|
// pass are important. so for the time being, keep this code:
|
||||||
// delete segment list (and free blocks)
|
// delete segment list (and free blocks)
|
||||||
// while ((temp = segment_list)) {
|
// while ((temp = segment_list)) {
|
||||||
// segment_list = segment_list->next;
|
// segment_list = segment_list->next;
|
||||||
@ -347,7 +333,8 @@ static void end_segment(void)
|
|||||||
intval_t amount;
|
intval_t amount;
|
||||||
|
|
||||||
// only do in first or last pass
|
// only do in first or last pass
|
||||||
if (!pass.flags.do_segment_checks)
|
// FIXME - do the _checking_ in all passes, but only throw errors/warnings in final pass!
|
||||||
|
if (!pass.flags.throw_segment_messages)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// if there is no segment, there is nothing to do
|
// if there is no segment, there is nothing to do
|
||||||
@ -396,7 +383,7 @@ static void start_segment(intval_t address_change, bits segment_flags)
|
|||||||
// allow writing to output buffer
|
// allow writing to output buffer
|
||||||
output_byte = real_output;
|
output_byte = real_output;
|
||||||
// in first/last pass, check for other segments and maybe issue warning
|
// in first/last pass, check for other segments and maybe issue warning
|
||||||
if (pass.flags.do_segment_checks) {
|
if (pass.flags.throw_segment_messages) {
|
||||||
if (!(segment_flags & SEGMENT_FLAG_OVERLAY))
|
if (!(segment_flags & SEGMENT_FLAG_OVERLAY))
|
||||||
check_segment(out->segm.start);
|
check_segment(out->segm.start);
|
||||||
find_segment_max(out->segm.start);
|
find_segment_max(out->segm.start);
|
||||||
|
@ -34,9 +34,6 @@ extern void output_skip(int size);
|
|||||||
// FIXME - replace by output_sequence(char *src, size_t size)
|
// FIXME - replace by output_sequence(char *src, size_t size)
|
||||||
extern void (*output_byte)(intval_t);
|
extern void (*output_byte)(intval_t);
|
||||||
|
|
||||||
// default value for empty memory has changed (called by "!initmem" pseudo opcode)
|
|
||||||
extern void output_newdefault(void);
|
|
||||||
|
|
||||||
// remember current outbuf index as start/limit of output file
|
// remember current outbuf index as start/limit of output file
|
||||||
extern void outbuf_set_outfile_start(void);
|
extern void outbuf_set_outfile_start(void);
|
||||||
extern void outbuf_set_outfile_limit(void);
|
extern void outbuf_set_outfile_limit(void);
|
||||||
|
@ -72,9 +72,6 @@ static enum eos po_initmem(void)
|
|||||||
// remember value
|
// remember value
|
||||||
config.mem_init_value = intresult.val.intval & 0xff;
|
config.mem_init_value = intresult.val.intval & 0xff;
|
||||||
|
|
||||||
// fill outbuffer and enforce another pass
|
|
||||||
output_newdefault(); // FIXME - remove when outbuffer gets initialized only right before "last" pass!
|
|
||||||
|
|
||||||
return ENSURE_EOS;
|
return ENSURE_EOS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -537,6 +534,7 @@ static enum eos po_binary(void)
|
|||||||
int byte;
|
int byte;
|
||||||
struct number size,
|
struct number size,
|
||||||
skip;
|
skip;
|
||||||
|
int amount;
|
||||||
|
|
||||||
size.val.intval = -1; // means "not given" => "until EOF"
|
size.val.intval = -1; // means "not given" => "until EOF"
|
||||||
skip.val.intval = 0;
|
skip.val.intval = 0;
|
||||||
@ -571,8 +569,7 @@ static enum eos po_binary(void)
|
|||||||
// check whether including is a waste of time
|
// check whether including is a waste of time
|
||||||
// FIXME - future changes ("several-projects-at-once")
|
// FIXME - future changes ("several-projects-at-once")
|
||||||
// may be incompatible with this!
|
// may be incompatible with this!
|
||||||
if ((size.val.intval >= 0) && (pass.counters.undefineds || pass.counters.errors)) {
|
if ((size.val.intval >= 0) && (!pass.flags.generate_output)) {
|
||||||
//if ((size.val.intval >= 0) && (pass.counters.needvalue || pass.counters.errors)) { FIXME - use!
|
|
||||||
output_skip(size.val.intval); // really including is useless anyway
|
output_skip(size.val.intval); // really including is useless anyway
|
||||||
} else {
|
} else {
|
||||||
// really insert file
|
// really insert file
|
||||||
@ -593,16 +590,14 @@ static enum eos po_binary(void)
|
|||||||
output_byte(0);
|
output_byte(0);
|
||||||
} while (--size.val.intval);
|
} while (--size.val.intval);
|
||||||
}
|
}
|
||||||
|
// if verbose, produce some output
|
||||||
|
if (config.process_verbosity >= 2) {
|
||||||
|
amount = output_get_statement_size();
|
||||||
|
printf("Loaded %d (0x%04x) bytes from file offset %d (0x%04x).\n",
|
||||||
|
amount, amount, skip.val.intval, skip.val.intval);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fclose(stream);
|
fclose(stream);
|
||||||
// if verbose, produce some output
|
|
||||||
// FIXME - do in _last_ pass instead of first!
|
|
||||||
if ((pass.number == 1) && (config.process_verbosity >= 2)) {
|
|
||||||
int amount = output_get_statement_size();
|
|
||||||
|
|
||||||
printf("Loaded %d (0x%04x) bytes from file offset %d (0x%04x).\n",
|
|
||||||
amount, amount, skip.val.intval, skip.val.intval);
|
|
||||||
}
|
|
||||||
return ENSURE_EOS;
|
return ENSURE_EOS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
#define RELEASE "0.97" // update before release FIXME
|
#define RELEASE "0.97" // update before release FIXME
|
||||||
#define CODENAME "Zem" // update before release
|
#define CODENAME "Zem" // update before release
|
||||||
#define CHANGE_DATE "2 Aug" // update before release FIXME
|
#define CHANGE_DATE "3 Aug" // update before release FIXME
|
||||||
#define CHANGE_YEAR "2024" // update before release
|
#define CHANGE_YEAR "2024" // update before release
|
||||||
//#define HOME_PAGE "http://home.pages.de/~mac_bacon/smorbrod/acme/"
|
//#define HOME_PAGE "http://home.pages.de/~mac_bacon/smorbrod/acme/"
|
||||||
#define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME
|
#define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
otherstring = "Ford"
|
otherstring = "Ford"
|
||||||
+a otherstring + emptystring + somestring == "FordArthur"
|
+a otherstring + emptystring + somestring == "FordArthur"
|
||||||
|
|
||||||
collection = []
|
!set collection = []
|
||||||
!for c in "Trillian" {
|
!for c in "Trillian" {
|
||||||
!set collection = collection + [c]
|
!set collection = collection + [c]
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ label4
|
|||||||
lda d
|
lda d
|
||||||
+a * - label4 == 3
|
+a * - label4 == 3
|
||||||
label5
|
label5
|
||||||
e+2=5
|
!set e+2=5
|
||||||
!for e+2, 17, 17 {
|
!for e+2, 17, 17 {
|
||||||
lda e
|
lda e
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user