mirror of
https://github.com/uffejakobsen/acme.git
synced 2026-01-22 03:19:16 +00:00
the "-D" switch can now assign strings in double quotes (but check your shell's quoting rules!)
git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@433 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
110
src/acme.c
110
src/acme.c
@@ -511,11 +511,19 @@ static void set_starting_cpu(const char cpu_name[])
|
||||
}
|
||||
|
||||
|
||||
static void could_not_parse(const char strange[])
|
||||
// helper function to complain about error in cli args, does not return
|
||||
static void exit__cli_arg_error(const char format[], const char arg[])
|
||||
{
|
||||
fprintf(stderr, "%sCould not parse '%s'.\n", cliargs_error, strange);
|
||||
fprintf(stderr, "%s", cliargs_error);
|
||||
fprintf(stderr, format, arg);
|
||||
fprintf(stderr, "\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
// exit with "Error in CLI arguments: ..." message
|
||||
void ACME_cli_args_error(const char msg[])
|
||||
{
|
||||
exit__cli_arg_error("%s", msg);
|
||||
}
|
||||
|
||||
|
||||
// return signed long representation of string.
|
||||
@@ -544,7 +552,7 @@ static signed long string_to_number(const char *string)
|
||||
}
|
||||
result = strtol(string, &end, base);
|
||||
if (*end)
|
||||
could_not_parse(end);
|
||||
exit__cli_arg_error("Could not parse \"%s\" as number.", end);
|
||||
return result;
|
||||
}
|
||||
// wrapper for fn above: complain about negative numbers
|
||||
@@ -552,10 +560,8 @@ static signed long string_to_nonneg_number(const char *string)
|
||||
{
|
||||
signed long result = string_to_number(string);
|
||||
|
||||
if (result < 0) {
|
||||
fprintf(stderr, "%sInvalid value, number is negative: '%s'.\n", cliargs_error, string);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (result < 0)
|
||||
exit__cli_arg_error("Invalid value, number is negative: \"%s\".", string);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -564,29 +570,64 @@ static signed long string_to_nonneg_number(const char *string)
|
||||
static void set_mem_contents(const char expression[])
|
||||
{
|
||||
config.mem_init_value = string_to_number(expression);
|
||||
if ((config.mem_init_value < -128) || (config.mem_init_value > 255)) {
|
||||
fprintf(stderr, "%sInitmem value out of range (0-0xff).\n", cliargs_error);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if ((config.mem_init_value < -128) || (config.mem_init_value > 255))
|
||||
exit__cli_arg_error("%s", "Initmem value must be in 0..0xff range.");
|
||||
}
|
||||
|
||||
|
||||
// define symbol
|
||||
// FIXME - replace all this with a call to some kind of "hey parser, parse this string" function?
|
||||
// but then we would have to pass a "do backslash escapes even if older dialect selected" flag...
|
||||
static void define_symbol(const char definition[])
|
||||
{
|
||||
const char *walk = definition;
|
||||
signed long value;
|
||||
struct symbol *symbol;
|
||||
signed long intvalue;
|
||||
boolean escaped;
|
||||
|
||||
// copy definition to GlobalDynaBuf until '=' reached
|
||||
// copy symbol name (everything up to the '=' char) to GlobalDynaBuf and add terminator:
|
||||
dynabuf_clear(GlobalDynaBuf);
|
||||
while ((*walk != '=') && (*walk != '\0'))
|
||||
dynabuf_append(GlobalDynaBuf, *walk++);
|
||||
if ((*walk == '\0') || (walk[1] == '\0'))
|
||||
could_not_parse(definition);
|
||||
// TODO - if first char is double quote, maybe interpret as string instead of number?
|
||||
value = string_to_number(walk + 1);
|
||||
dynabuf_append(GlobalDynaBuf, '\0');
|
||||
symbol_define(value);
|
||||
// use name to make symbol
|
||||
symbol = symbol_for_cli_def();
|
||||
// now we can clobber GlobalDynaBuf
|
||||
|
||||
// no '=' or nothing after? then complain and die:
|
||||
if ((*walk == '\0') || (walk[1] == '\0'))
|
||||
exit__cli_arg_error("\"%s\" does not have SYMBOL=VALUE format.", definition);
|
||||
++walk; // eat '='
|
||||
// now check value type (at the moment only integers and strings are possible)
|
||||
if (*walk == '"') {
|
||||
// it starts with a doublequote, so it must be a string
|
||||
++walk; // eat '"'
|
||||
dynabuf_clear(GlobalDynaBuf);
|
||||
escaped = FALSE;
|
||||
for (;;) {
|
||||
if (*walk == '\0')
|
||||
exit__cli_arg_error("Closing quote not found after -D %s.", definition);
|
||||
if (escaped) {
|
||||
// previous byte was backslash, so do not check for closing quote nor backslash
|
||||
escaped = FALSE;
|
||||
} else {
|
||||
// non-escaped: only closing quote and backslash are of interest
|
||||
if (*walk == '"')
|
||||
break; // leave loop
|
||||
if (*walk == '\\')
|
||||
escaped = TRUE;
|
||||
}
|
||||
DYNABUF_APPEND(GlobalDynaBuf, *walk++);
|
||||
}
|
||||
if (walk[1] != '\0')
|
||||
exit__cli_arg_error("Garbage after closing quote at -D %s.", definition);
|
||||
unescape_dynabuf();
|
||||
symbol_define_string(symbol);
|
||||
} else {
|
||||
// integer
|
||||
intvalue = string_to_number(walk);
|
||||
symbol_define_int(symbol, intvalue);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -605,7 +646,7 @@ struct dialect_info dialects[] = {
|
||||
{V0_94_12__NEW_FOR_SYNTAX, "0.94.12", "new \"!for\" syntax"},
|
||||
{V0_95_2__NEW_ANC_OPCODE, "0.95.2", "changed ANC#8 from 0x2b to 0x0b"},
|
||||
{V0_97__BACKSLASH_ESCAPING, "0.97", "backslash escaping and strings"},
|
||||
// {V0_98__PATHS_AND_SYMBOLCHANGE, "0.98", "paths are relative to current file"},
|
||||
{V0_98__PATHS_AND_SYMBOLCHANGE, "0.98", "paths are relative to current file"},
|
||||
// {V__CURRENT_VERSION, "default", "default"},
|
||||
{V__FUTURE_VERSION, "future", "enable all experimental features"},
|
||||
{0, NULL, NULL} // NULLs terminate
|
||||
@@ -758,8 +799,7 @@ static char short_option(const char *argument)
|
||||
config.warn_on_type_mismatch = TRUE;
|
||||
goto done;
|
||||
} else {
|
||||
fprintf(stderr, "%sUnknown warning level.\n", cliargs_error);
|
||||
exit(EXIT_FAILURE);
|
||||
exit__cli_arg_error("Unknown warning level \"%s\".", argument);
|
||||
}
|
||||
break;
|
||||
default: // unknown ones: program termination
|
||||
@@ -794,35 +834,31 @@ int main(int argc, const char *argv[])
|
||||
// this may read the library path from an environment variable.
|
||||
PLATFORM_INIT;
|
||||
// handle command line arguments
|
||||
// (this will handle all "-D SYMBOL=VALUE" assignments)
|
||||
cliargs_handle_options(short_option, long_option);
|
||||
// generate list of files to process
|
||||
cliargs_get_rest(&toplevel_src_count, &toplevel_sources_plat, "No top level sources given");
|
||||
|
||||
// now that we have processed all cli switches, check a few values for
|
||||
// valid range:
|
||||
if ((config.initial_pc != NO_VALUE_GIVEN) && (config.initial_pc >= OUTBUF_MAXSIZE)) {
|
||||
fprintf(stderr, "%sProgram counter exceeds maximum outbuffer size.\n", cliargs_error);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if ((config.outfile_start != NO_VALUE_GIVEN) && (config.outfile_start >= OUTBUF_MAXSIZE)) {
|
||||
fprintf(stderr, "%sStart address of output file exceeds maximum outbuffer size.\n", cliargs_error);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if ((config.initial_pc != NO_VALUE_GIVEN) && (config.initial_pc >= OUTBUF_MAXSIZE))
|
||||
throw_error("Program counter exceeds maximum outbuffer size.");
|
||||
if ((config.outfile_start != NO_VALUE_GIVEN) && (config.outfile_start >= OUTBUF_MAXSIZE))
|
||||
throw_error("Start address of output file exceeds maximum outbuffer size.");
|
||||
// "limit" is end+1 and therefore we need ">" instead of ">=":
|
||||
if ((config.outfile_limit != NO_VALUE_GIVEN) && (config.outfile_limit > OUTBUF_MAXSIZE)) {
|
||||
fprintf(stderr, "%sEnd+1 of output file exceeds maximum outbuffer size.\n", cliargs_error);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if ((config.outfile_limit != NO_VALUE_GIVEN) && (config.outfile_limit > OUTBUF_MAXSIZE))
|
||||
throw_error("End+1 of output file exceeds maximum outbuffer size.");
|
||||
if ((config.outfile_start != NO_VALUE_GIVEN)
|
||||
&& (config.outfile_limit != NO_VALUE_GIVEN)
|
||||
&& (config.outfile_start >= config.outfile_limit)) {
|
||||
fprintf(stderr, "%sStart address of output file exceeds end+1.\n", cliargs_error);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
&& (config.outfile_start >= config.outfile_limit))
|
||||
throw_error("Start address of output file exceeds end+1.");
|
||||
// since version 0.98, "--strict-segments" are default:
|
||||
if (config.dialect >= V0_98__PATHS_AND_SYMBOLCHANGE)
|
||||
config.strict_segments = TRUE;
|
||||
|
||||
// make throw_error() behave normally instead of exiting with "Error in CLI arguments: ..."
|
||||
throw__done_with_cli_args();
|
||||
|
||||
// do the actual work
|
||||
do_actual_work();
|
||||
return ACME_finalize(EXIT_SUCCESS); // dump labels, if wanted
|
||||
|
||||
@@ -15,5 +15,8 @@
|
||||
// tidy up before exiting by saving symbol dump
|
||||
extern int ACME_finalize(int exit_code);
|
||||
|
||||
// exit with "Error in CLI arguments: ..." message
|
||||
extern void ACME_cli_args_error(const char msg[]);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -404,7 +404,8 @@ static void parse_program_counter(void) // now GotByte = "*"
|
||||
|
||||
|
||||
// make new string object
|
||||
static void string_prepare_string(struct object *self, int len)
|
||||
// (exported because symbol.c calls this for strings given on command line)
|
||||
void string_prepare_string(struct object *self, int len)
|
||||
{
|
||||
self->type = &type_string;
|
||||
self->u.string = safe_malloc(sizeof(*(self->u.string)) + len);
|
||||
@@ -1285,6 +1286,7 @@ static void unsupported_operation(const struct object *optional, const struct op
|
||||
|
||||
// int:
|
||||
// create byte-sized int object (for comparison results, converted characters, ...)
|
||||
// FIXME - as this does not set the FITS_BYTE flag, why "byte-sized"?! why not int_create_int?
|
||||
static void int_create_byte(struct object *self, intval_t byte)
|
||||
{
|
||||
self->type = &type_number;
|
||||
|
||||
@@ -52,6 +52,13 @@ struct expression {
|
||||
// labels that are undefined, we can't simply get the addressing mode
|
||||
// from looking at the parameter's value. FIXME - rename to TAINTED :)
|
||||
|
||||
|
||||
// prototypes
|
||||
|
||||
// make new string object
|
||||
// (exported because symbol.c calls this for strings given on command line)
|
||||
extern void string_prepare_string(struct object *self, int len);
|
||||
|
||||
/*
|
||||
// FIXME - replace all the functions below with a single one using a "flags" arg!
|
||||
// its return value would then be "error"/"ok".
|
||||
|
||||
23
src/global.c
23
src/global.c
@@ -527,10 +527,22 @@ static void print_msg(const char *message, const char *ansicolor, const char *ty
|
||||
}
|
||||
}
|
||||
|
||||
// flag, tells throw_error how to behave. set to FALSE by throw__done_with_cli_args().
|
||||
// this is needed because errors like "\xZZ is not a valid backslash sequence" are
|
||||
// handled by calling throw_error(), but they can happen
|
||||
// - in cli args, using the "-D SYMBOL=VALUE" syntax, where we want to exit, and
|
||||
// - in source codes, where we want a "file=F, line=N" output and go on!
|
||||
static boolean error_is_in_cli_args = TRUE;
|
||||
|
||||
// generate debug/info/warning/error message
|
||||
// if the "optional alternative location" given is NULL, the current location is used
|
||||
void throw_message(enum debuglevel level, const char msg[], struct location *opt_alt_loc)
|
||||
{
|
||||
// FIXME: we only expect normal errors in cli args, no warnings or
|
||||
// other stuff, so enable this:
|
||||
//if (error_is_in_cli_args)
|
||||
// BUG("damn");
|
||||
|
||||
// if level is taken from source, ensure valid value:
|
||||
if (level < DEBUGLEVEL_SERIOUS)
|
||||
level = DEBUGLEVEL_SERIOUS;
|
||||
@@ -590,7 +602,10 @@ void throw_warning(const char msg[])
|
||||
// about more than one of his typos at a time.
|
||||
void throw_error(const char msg[])
|
||||
{
|
||||
throw_message(DEBUGLEVEL_ERROR, msg, NULL);
|
||||
if (error_is_in_cli_args)
|
||||
ACME_cli_args_error(msg); // does not return...
|
||||
else
|
||||
throw_message(DEBUGLEVEL_ERROR, msg, NULL);
|
||||
}
|
||||
|
||||
// output a serious error (assembly stops, for example if outbuffer overruns).
|
||||
@@ -649,6 +664,12 @@ void throw_redef_error(const char error_msg[], struct location *old_def, const c
|
||||
section_now->title = buffered_section_title;
|
||||
}
|
||||
|
||||
// ugly kluge, switches throw_error() from cli args mode to normal mode
|
||||
void throw__done_with_cli_args(void)
|
||||
{
|
||||
error_is_in_cli_args = FALSE;
|
||||
}
|
||||
|
||||
// handle bugs
|
||||
// FIXME - use a local buffer and sprintf/snprintf to put error code into message!
|
||||
void BUG(const char *message, int code)
|
||||
|
||||
@@ -242,6 +242,9 @@ extern void throw_finalpass_warning(const char msg[]);
|
||||
// first output error as "error", then location of initial definition as "info"
|
||||
extern void throw_redef_error(const char error_msg[], struct location *old_def, const char info_msg[]);
|
||||
|
||||
// ugly kluge, switches throw_error() from cli args mode to normal mode
|
||||
extern void throw__done_with_cli_args(void);
|
||||
|
||||
// handle bugs
|
||||
extern void BUG(const char *msg, int code);
|
||||
|
||||
|
||||
65
src/input.c
65
src/input.c
@@ -80,7 +80,7 @@ static void report_printline(int line_number)
|
||||
{
|
||||
int ii;
|
||||
char hex_address[HEXBUFSIZE];
|
||||
char hexdump[2 * REPORT_BINBUFSIZE + 2]; // +2 for '.' and terminator
|
||||
char hexdump[2 * REPORT_BINBUFSIZE + 2 + 1]; // +2 for '.' and terminator, +1 to suppress compiler warning
|
||||
|
||||
// suppress empty lines
|
||||
if (report->bin_used == 0) {
|
||||
@@ -649,34 +649,17 @@ enum escape {
|
||||
ESCAPE_HEX1, // after reading "\x", expecting first hex digit
|
||||
ESCAPE_HEX2, // after reading "\x", expecting second hex digit
|
||||
};
|
||||
// clear dynabuf, read string to it until closing quote is found, then
|
||||
// process backslash escapes (so size might shrink)
|
||||
// returns 1 on error (unterminated or escaping error)
|
||||
int input_read_string_literal(char closing_quote)
|
||||
// process backslash escapes in GlobalDynaBuf (so size might shrink)
|
||||
// returns 1 on excaping errors
|
||||
int unescape_dynabuf(void)
|
||||
{
|
||||
int read_index,
|
||||
write_index;
|
||||
int read_index = 0,
|
||||
write_index = 0;
|
||||
char byte;
|
||||
enum escape escape_state;
|
||||
char hexbyte = 0;
|
||||
enum escape escape_state = ESCAPE_NONE;
|
||||
char hexbyte = 0;
|
||||
int err = 0;
|
||||
|
||||
dynabuf_clear(GlobalDynaBuf);
|
||||
if (quoted_to_dynabuf(closing_quote))
|
||||
return 1; // unterminated
|
||||
|
||||
// eat closing quote
|
||||
GetByte();
|
||||
|
||||
if (config.dialect >= V0_97__BACKSLASH_ESCAPING) {
|
||||
// since v0.97 we need to process backslashes (see below)
|
||||
} else {
|
||||
return 0; // older versions did not support backslash escapes, so return "ok"
|
||||
}
|
||||
|
||||
// now un-escape dynabuf contents:
|
||||
read_index = 0;
|
||||
write_index = 0;
|
||||
escape_state = ESCAPE_NONE;
|
||||
// CAUTION - contents of dynabuf are not terminated:
|
||||
while (read_index < GlobalDynaBuf->size) {
|
||||
byte = GLOBALDYNABUF_CURRENT[read_index++];
|
||||
@@ -714,6 +697,7 @@ int input_read_string_literal(char closing_quote)
|
||||
// TODO - 'a' to BEL? others?
|
||||
default:
|
||||
throw_error("Unsupported backslash sequence."); // TODO - add unexpected character to error message?
|
||||
err = 1;
|
||||
}
|
||||
GLOBALDYNABUF_CURRENT[write_index++] = byte;
|
||||
break;
|
||||
@@ -721,13 +705,14 @@ int input_read_string_literal(char closing_quote)
|
||||
hexbyte = 0;
|
||||
if (shift_hex_nibble(&hexbyte, byte)) {
|
||||
escape_state = ESCAPE_NONE; // error -> back to default state
|
||||
err = 1;
|
||||
} else {
|
||||
escape_state = ESCAPE_HEX2; // ok -> expect second hex digit
|
||||
}
|
||||
break;
|
||||
case ESCAPE_HEX2:
|
||||
if (shift_hex_nibble(&hexbyte, byte)) {
|
||||
// error will have been thrown already
|
||||
err = 1;
|
||||
} else {
|
||||
// parsing "\x" has written "x", so overwrite it:
|
||||
GLOBALDYNABUF_CURRENT[write_index - 1] = hexbyte;
|
||||
@@ -738,6 +723,7 @@ int input_read_string_literal(char closing_quote)
|
||||
BUG("StrangeEscapeState1", escape_state);
|
||||
}
|
||||
}
|
||||
GlobalDynaBuf->size = write_index;
|
||||
switch (escape_state) {
|
||||
case ESCAPE_NONE:
|
||||
break;
|
||||
@@ -746,12 +732,33 @@ int input_read_string_literal(char closing_quote)
|
||||
case ESCAPE_HEX1:
|
||||
case ESCAPE_HEX2:
|
||||
throw_error("Expected two hex digits after \\x sequence."); // TODO - add unexpected character to error message?
|
||||
err = 1;
|
||||
break;
|
||||
default:
|
||||
BUG("StrangeEscapeState2", escape_state);
|
||||
}
|
||||
GlobalDynaBuf->size = write_index;
|
||||
return 0; // ok
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
// clear dynabuf, read string to it until closing quote is found, then
|
||||
// process backslash escapes (so size might shrink)
|
||||
// returns 1 on error (unterminated or escaping error)
|
||||
int input_read_string_literal(char closing_quote)
|
||||
{
|
||||
dynabuf_clear(GlobalDynaBuf);
|
||||
if (quoted_to_dynabuf(closing_quote))
|
||||
return 1; // unterminated
|
||||
|
||||
// eat closing quote
|
||||
GetByte();
|
||||
|
||||
// since v0.97 we need to process backslashes:
|
||||
if (config.dialect >= V0_97__BACKSLASH_ESCAPING) {
|
||||
return unescape_dynabuf();
|
||||
} else {
|
||||
return 0; // older versions did not support backslash escapes, so return "ok"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -71,6 +71,10 @@ extern void parser_skip_remainder(void);
|
||||
// after mnemonics using implied addressing.
|
||||
extern void parser_ensure_EOS(void);
|
||||
|
||||
// process backslash escapes in GlobalDynaBuf (so size might shrink)
|
||||
// returns 1 on escaping errors
|
||||
extern int unescape_dynabuf(void);
|
||||
|
||||
// clear dynabuf, read string to it until closing quote is found, then process
|
||||
// backslash escapes (so size might shrink)
|
||||
// returns 1 on error (unterminated or escaping errors)
|
||||
|
||||
31
src/symbol.c
31
src/symbol.c
@@ -9,6 +9,7 @@
|
||||
// 23 Nov 2014 Added label output in VICE format
|
||||
#include "symbol.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h> // for memcpy()
|
||||
#include "alu.h"
|
||||
#include "dynabuf.h"
|
||||
#include "global.h"
|
||||
@@ -222,21 +223,33 @@ void symbol_set_force_bit(struct symbol *symbol, bits force_bit)
|
||||
}
|
||||
|
||||
|
||||
// set global symbol to integer value, no questions asked (for "-D" switch)
|
||||
// Name must be held in GlobalDynaBuf.
|
||||
void symbol_define(intval_t value)
|
||||
// create and return symbol for "-D" command line switch (with NULL type object, CAUTION!).
|
||||
// name must be held in GlobalDynaBuf
|
||||
extern struct symbol *symbol_for_cli_def(void)
|
||||
{
|
||||
struct object result;
|
||||
struct symbol *symbol;
|
||||
|
||||
result.type = &type_number;
|
||||
result.u.number.ntype = NUMTYPE_INT;
|
||||
result.u.number.flags = 0;
|
||||
result.u.number.val.intval = value;
|
||||
symbol = symbol_find(SCOPE_GLOBAL);
|
||||
symbol->object = result;
|
||||
symbol->definition.plat_filename = "\"-D SYMBOL=VALUE\"";
|
||||
symbol->definition.line_number = 1;
|
||||
return symbol;
|
||||
}
|
||||
// set symbol to integer value, no questions asked (for "-D" switch)
|
||||
// FIXME - remove and call int_create_byte instead?
|
||||
void symbol_define_int(struct symbol *symbol, intval_t value)
|
||||
{
|
||||
symbol->object.type = &type_number;
|
||||
symbol->object.u.number.ntype = NUMTYPE_INT;
|
||||
symbol->object.u.number.flags = 0;
|
||||
symbol->object.u.number.val.intval = value;
|
||||
symbol->object.u.number.addr_refs = 0;
|
||||
}
|
||||
// set symbol to string value, no questions asked (for "-D" switch)
|
||||
// string value must be held in GlobalDynaBuf
|
||||
void symbol_define_string(struct symbol *symbol)
|
||||
{
|
||||
string_prepare_string(&symbol->object, GlobalDynaBuf->size);
|
||||
memcpy(symbol->object.u.string->payload, GLOBALDYNABUF_CURRENT, GlobalDynaBuf->size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
11
src/symbol.h
11
src/symbol.h
@@ -49,9 +49,14 @@ extern void symbol_set_object(struct symbol *symbol, struct object *new_obj, bit
|
||||
// set force bit of symbol. trying to change to a different one will raise error.
|
||||
extern void symbol_set_force_bit(struct symbol *symbol, bits force_bit);
|
||||
|
||||
// set global symbol to value, no questions asked (for "-D" switch)
|
||||
// name must be held in GlobalDynaBuf.
|
||||
extern void symbol_define(intval_t value);
|
||||
// create and return symbol for "-D" command line switch (with NULL type object, CAUTION!).
|
||||
// name must be held in GlobalDynaBuf
|
||||
extern struct symbol *symbol_for_cli_def(void);
|
||||
// set symbol to integer value, no questions asked (for "-D" switch)
|
||||
extern void symbol_define_int(struct symbol *symbol, intval_t value);
|
||||
// set symbol to string value, no questions asked (for "-D" switch)
|
||||
// string value must be held in GlobalDynaBuf
|
||||
extern void symbol_define_string(struct symbol *symbol);
|
||||
|
||||
// dump global symbols to file
|
||||
extern void symbols_list(FILE *fd);
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#define RELEASE "0.97" // update before release FIXME
|
||||
#define CODENAME "Zem" // update before release
|
||||
#define CHANGE_DATE "22 Nov" // update before release FIXME
|
||||
#define CHANGE_DATE "23 Nov" // update before release FIXME
|
||||
#define CHANGE_YEAR "2024" // update before release
|
||||
//#define HOME_PAGE "http://home.pages.de/~mac_bacon/smorbrod/acme/"
|
||||
#define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME
|
||||
|
||||
@@ -221,4 +221,8 @@
|
||||
+a '\n' == 10
|
||||
+a '\r' == 13
|
||||
+a '\x41' == 'A'
|
||||
+a '\xa0' == 160
|
||||
+a '\xA0' == 160
|
||||
+a '\xff' == 255
|
||||
+a '\xFF' == 255
|
||||
+a "uv\x41yz" == "uvAyz"
|
||||
|
||||
Reference in New Issue
Block a user