stackargs = TRUE;
}
- if (veneer_mode) routine_starts_line = -1;
- else routine_starts_line = ErrorReport.line_number
- + FILE_LINE_SCALE_FACTOR*ErrorReport.file_number;
+ if (veneer_mode) routine_starts_line = blank_brief_location;
+ else routine_starts_line = get_brief_location(&ErrorReport);
if (asm_trace_level > 0)
{ printf("\n%5d +%05lx [ %s ", ErrorReport.line_number,
no_termcs; /* Number of terminating characters */
int terminating_characters[32];
-int32 routine_starts_line; /* Source code line on which the current
+brief_location routine_starts_line; /* Source code location where the current
routine starts. (Useful for reporting
"unused variable" warnings on the start
line rather than the end line.) */
make_object(FALSE, NULL, -1, -1, -1);
return FALSE; /* See "objects.c" */
+ /* --------------------------------------------------------------------- */
+ /* Origsource <file> */
+ /* Origsource <file> <line> */
+ /* Origsource <file> <line> <char> */
+ /* Origsource */
+ /* */
+ /* The first three forms declare that all following lines are derived */
+ /* from the named Inform 7 source file (with an optional line number */
+ /* and character number). This will be reported in error messages and */
+ /* in debug output. The declaration holds through the next Origsource */
+ /* directive (but does not apply to included files). */
+ /* */
+ /* The fourth form, with no arguments, clears the declaration. */
+ /* */
+ /* Unlike the Include directive, Origsource does not open the named */
+ /* file or even verify that it exists. The filename is treated as an */
+ /* opaque string. */
+ /* --------------------------------------------------------------------- */
+
+ case ORIGSOURCE_CODE:
+ {
+ char *origsource_file = NULL;
+ int32 origsource_line = 0;
+ int32 origsource_char = 0;
+
+ /* Parse some optional tokens followed by a mandatory semicolon. */
+
+ get_next_token();
+ if (!((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))) {
+ if (token_type != DQ_TT) {
+ return ebf_error_recover("a file name in double-quotes",
+ token_text);
+ }
+ origsource_file = token_text;
+
+ get_next_token();
+ if (!((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))) {
+ if (token_type != NUMBER_TT) {
+ return ebf_error_recover("a file line number",
+ token_text);
+ }
+ origsource_line = token_value;
+ if (origsource_line < 0)
+ origsource_line = 0;
+
+ get_next_token();
+ if (!((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))) {
+ if (token_type != NUMBER_TT) {
+ return ebf_error_recover("a file line number",
+ token_text);
+ }
+ origsource_char = token_value;
+ if (origsource_char < 0)
+ origsource_char = 0;
+
+ get_next_token();
+ }
+ }
+ }
+
+ put_token_back();
+
+ set_origsource_location(origsource_file, origsource_line, origsource_char);
+ }
+ break;
+
/* --------------------------------------------------------------------- */
/* Property [long] [additive] name [alias oldname] */
/* --------------------------------------------------------------------- */
int j, with_extension_flag = FALSE; char *p;
j = ErrorReport.file_number;
- if (j <= 0 || j > input_file) p = ErrorReport.source;
+ if (j <= 0 || j > total_files) p = ErrorReport.source;
else p = InputFiles[j-1].filename;
if (!p) p = "";
if (!(ErrorReport.main_flag)) printf("\"%s\", ", p);
printf("line %d: ", ErrorReport.line_number);
+ if (ErrorReport.orig_file) {
+ char *op;
+ if (ErrorReport.orig_file <= 0 || ErrorReport.orig_file > total_files)
+ op = ErrorReport.orig_source;
+ else
+ op = InputFiles[ErrorReport.orig_file-1].filename;
+ printf("(\"%s\"", op);
+ if (ErrorReport.orig_line) {
+ printf(", %d", ErrorReport.orig_line);
+ if (ErrorReport.orig_char) {
+ printf(":%d", ErrorReport.orig_char);
+ }
+ }
+ printf("): ");
+ }
break;
case 1: /* Microsoft error message format */
error(error_message_buff);
}
-extern void error_named_at(char *s1, char *s2, int32 report_line)
+extern void error_named_at(char *s1, char *s2, brief_location report_line)
{ int i;
ErrorPosition E = ErrorReport;
- if (report_line != -1)
- { ErrorReport.file_number = report_line/FILE_LINE_SCALE_FACTOR;
- ErrorReport.line_number = report_line%FILE_LINE_SCALE_FACTOR;
- ErrorReport.main_flag = (ErrorReport.file_number == 1);
- }
+ export_brief_location(report_line, &ErrorReport);
snprintf(error_message_buff, ERROR_BUFLEN,"%s \"%s\"",s1,s2);
ellipsize_error_message_buff();
message(2,error_message_buff);
}
-extern void dbnu_warning(char *type, char *name, int32 report_line)
+extern void dbnu_warning(char *type, char *name, brief_location report_line)
{ int i;
ErrorPosition E = ErrorReport;
if (nowarnings_switch) { no_suppressed_warnings++; return; }
- if (report_line != -1)
- { ErrorReport.file_number = report_line/FILE_LINE_SCALE_FACTOR;
- ErrorReport.line_number = report_line%FILE_LINE_SCALE_FACTOR;
- ErrorReport.main_flag = (ErrorReport.file_number == 1);
- }
+ export_brief_location(report_line, &ErrorReport);
snprintf(error_message_buff, ERROR_BUFLEN, "%s \"%s\" declared but not used", type, name);
ellipsize_error_message_buff();
i = concise_switch; concise_switch = TRUE;
ErrorReport = E;
}
-extern void uncalled_routine_warning(char *type, char *name, int32 report_line)
+extern void uncalled_routine_warning(char *type, char *name, brief_location report_line)
{ int i;
/* This is called for functions which have been detected by the
track-unused-routines module. These will often (but not always)
than routine addresses. */
ErrorPosition E = ErrorReport;
if (nowarnings_switch) { no_suppressed_warnings++; return; }
- if (report_line != -1)
- { ErrorReport.file_number = report_line/FILE_LINE_SCALE_FACTOR;
- ErrorReport.line_number = report_line%FILE_LINE_SCALE_FACTOR;
- ErrorReport.main_flag = (ErrorReport.file_number == 1);
- }
+ export_brief_location(report_line, &ErrorReport);
if (OMIT_UNUSED_ROUTINES)
snprintf(error_message_buff, ERROR_BUFLEN, "%s \"%s\" unused and omitted", type, name);
else
ErrorReport.file_number = -1;
ErrorReport.source = "<no text read yet>";
ErrorReport.main_flag = FALSE;
+ ErrorReport.orig_source = NULL;
+ ErrorReport.orig_file = 0;
+ ErrorReport.orig_line = 0;
+ ErrorReport.orig_char = 0;
}
extern void errors_allocate_arrays(void)
current_token.symflags = sflags[symbol];
switch(stypes[symbol])
{ case ROUTINE_T:
+ /* Replaced functions must always be backpatched
+ because there could be another definition coming. */
+ if (sflags[symbol] & REPLACE_SFLAG)
+ { current_token.marker = SYMBOL_MV;
+ if (module_switch) import_symbol(symbol);
+ v = symbol;
+ break;
+ }
current_token.marker = IROUTINE_MV;
break;
case GLOBAL_VARIABLE_T:
if ((a.type == ENDEXP_TT) && (b.type == ENDEXP_TT))
{ if (emitter_sp == 0)
- { compiler_error("SR error: emitter stack empty");
+ { error("No expression between brackets '(' and ')'");
+ put_token_back();
return AO;
}
if (emitter_sp > 1)
#include "header.h"
-int input_file; /* Number of source files so far */
+int total_files; /* Number of files so far, including
+ #include and #origsource files */
+int total_input_files; /* Number of source files so far
+ (excludes #origsource) */
+int current_input_file; /* Most recently-opened source file */
+static int current_origsource_file; /* Most recently-used #origsource */
int32 total_chars_read; /* Characters read in (from all
source files put together) */
int x = 0;
FILE *handle;
- if (input_file == MAX_SOURCE_FILES)
+ if (total_files == MAX_SOURCE_FILES)
memoryerror("MAX_SOURCE_FILES", MAX_SOURCE_FILES);
do
{ x = translate_in_filename(x, name, filename_given, same_directory_flag,
- (input_file==0)?1:0);
+ (total_files==0)?1:0);
handle = fopen(name,"r");
} while ((handle == NULL) && (x != 0));
filename_storage_left -= strlen(name)+1;
strcpy(filename_storage_p, name);
- InputFiles[input_file].filename = filename_storage_p;
+ InputFiles[total_files].filename = filename_storage_p;
filename_storage_p += strlen(name)+1;
if (debugfile_switch)
- { debug_file_printf("<source index=\"%d\">", input_file);
+ { debug_file_printf("<source index=\"%d\">", total_files);
debug_file_printf("<given-path>");
debug_file_print_with_entities(filename_given);
debug_file_printf("</given-path>");
debug_file_printf("</source>");
}
- InputFiles[input_file].handle = handle;
- if (InputFiles[input_file].handle==NULL)
+ InputFiles[total_files].handle = handle;
+ if (InputFiles[total_files].handle==NULL)
fatalerror_named("Couldn't open source file", name);
+ InputFiles[total_files].is_input = TRUE;
+
if (line_trace_level > 0) printf("\nOpening file \"%s\"\n",name);
- input_file++;
+ total_files++;
+ total_input_files++;
+ current_input_file = total_files;
}
static void close_sourcefile(int file_number)
extern void close_all_source(void)
{ int i;
- for (i=0; i<input_file; i++) close_sourcefile(i+1);
+ for (i=0; i<total_files; i++) close_sourcefile(i+1);
+}
+
+/* ------------------------------------------------------------------------- */
+/* Register an #origsource filename. This goes in the InputFiles table, */
+/* but we do not open the file or advance current_input_file. */
+/* ------------------------------------------------------------------------- */
+
+extern int register_orig_sourcefile(char *filename)
+{
+ int ix;
+
+ /* If the filename has already been used as an origsource filename,
+ return that entry. We check the most-recently-used file first, and
+ then search the list. */
+ if (current_origsource_file > 0 && current_origsource_file <= total_files) {
+ if (!strcmp(filename, InputFiles[current_origsource_file-1].filename))
+ return current_origsource_file;
+ }
+
+ for (ix=0; ix<total_files; ix++) {
+ if (InputFiles[ix].is_input)
+ continue;
+ if (!strcmp(filename, InputFiles[ix].filename)) {
+ current_origsource_file = ix+1;
+ return current_origsource_file;
+ }
+ }
+
+ /* This filename has never been used before. Allocate a new InputFiles
+ entry. */
+
+ char *name = filename; /* no translation */
+
+ if (total_files == MAX_SOURCE_FILES)
+ memoryerror("MAX_SOURCE_FILES", MAX_SOURCE_FILES);
+
+ if (filename_storage_left <= (int)strlen(name))
+ memoryerror("MAX_SOURCE_FILES", MAX_SOURCE_FILES);
+
+ filename_storage_left -= strlen(name)+1;
+ strcpy(filename_storage_p, name);
+ InputFiles[total_files].filename = filename_storage_p;
+
+ filename_storage_p += strlen(name)+1;
+
+ if (debugfile_switch)
+ { debug_file_printf("<source index=\"%d\">", total_files);
+ debug_file_printf("<given-path>");
+ debug_file_print_with_entities(filename);
+ debug_file_printf("</given-path>");
+ debug_file_printf("<language>Inform 7</language>");
+ debug_file_printf("</source>");
+ }
+
+ InputFiles[total_files].handle = NULL;
+ InputFiles[total_files].is_input = FALSE;
+
+ total_files++;
+ current_origsource_file = total_files;
+ return current_origsource_file;
}
/* ------------------------------------------------------------------------- */
{
int read_in; FILE *handle;
- if (file_number-1 > input_file)
+ if (file_number-1 > total_files)
{ buffer[0] = 0; return 1; }
handle = InputFiles[file_number-1].handle;
}
}
+static void write_debug_location_origsource_internals(debug_location location)
+{ debug_file_printf
+ ("<file-index>%d</file-index>", location.orig_file_index - 1);
+ if (location.orig_beg_line_number)
+ debug_file_printf
+ ("<line>%d</line>", location.orig_beg_line_number);
+ if (location.orig_beg_char_number)
+ debug_file_printf
+ ("<character>%d</character>", location.orig_beg_char_number);
+}
+
extern void write_debug_location(debug_location location)
{ if (location.file_index && location.file_index != 255)
{ debug_file_printf("<source-code-location>");
write_debug_location_internals(location);
debug_file_printf("</source-code-location>");
}
+ if (location.orig_file_index)
+ { debug_file_printf("<source-code-location>");
+ write_debug_location_origsource_internals(location);
+ debug_file_printf("</source-code-location>");
+ }
}
extern void write_debug_locations(debug_locations locations)
write_debug_location_internals(current->location);
debug_file_printf("</source-code-location>");
}
+ if (locations.location.orig_file_index)
+ { debug_file_printf("<source-code-location>");
+ write_debug_location_origsource_internals(locations.location);
+ debug_file_printf("</source-code-location>");
+ }
}
else
{ write_debug_location(locations.location);
}
extern void files_begin_prepass(void)
-{ input_file = 0;
+{
+ total_files = 0;
+ total_input_files = 0;
+ current_input_file = 0;
+ current_origsource_file = 0;
}
extern void files_begin_pass(void)
/* #define ATARIST - for the Atari ST */
/* #define BEOS - for the BeBox */
/* #define LINUX - for Linux under gcc (essentially as Unix) */
-/* #define MACINTOSH - for the Apple Mac under Think C or Codewarrior */
+/* #define MACOS - for the Apple Mac with OS X (another Unix) */
+/* #define MAC_CLASSIC - for the Apple Mac under Think C or Codewarrior */
/* #define MAC_MPW - for MPW under Codewarrior (and maybe Think C) */
/* #define OS2 - for OS/2 32-bit mode under IBM's C Set++ */
-/* #define OSX - for the Apple Mac with OS X (another Unix) */
/* #define PC - for 386+ IBM PCs, eg. Microsoft Visual C/C++ */
/* #define PC_QUICKC - for small IBM PCs under QuickC */
/* #define PC_WIN32 - for Borland C++ or Microsoft Visual C++ */
/* #define UNIX - for Unix under gcc (or big IBM PC under djgpp) */
-/* #define UNIX64 - for 64-bit Unix under gcc */
/* #define VMS - for VAX or ALPHA under DEC C, but not VAX C */
/* */
/* In most cases executables are already available at */
/* Macintosh block */
/* ------------------------------------------------------------------------- */
#ifdef MAC_MPW
-#define MACINTOSH
+#define MAC_CLASSIC
#endif
-#ifdef MACINTOSH
+#ifdef MAC_CLASSIC
/* 1 */
#ifdef MAC_MPW
#define MACHINE_STRING "Macintosh Programmer's Workshop"
#define FN_SEP '/'
#endif
/* ------------------------------------------------------------------------- */
-/* OSX block */
+/* MACOS block */
/* ------------------------------------------------------------------------- */
-#ifdef OSX
+#ifdef MACOS
/* 1 */
-#define MACHINE_STRING "Mac OS X"
+#define MACHINE_STRING "MacOS"
/* 2 */
#define HAS_REALPATH
/* 3 */
-#define DEFAULT_MEMORY_SIZE LARGE_SIZE
+#define DEFAULT_MEMORY_SIZE HUGE_SIZE
/* 4 */
#define FN_SEP '/'
/* 5 */
/* ------------------------------------------------------------------------- */
#ifdef UNIX
/* 1 */
-#define MACHINE_STRING "Unix"
-/* 2 */
-#define USE_TEMPORARY_FILES
-#define HAS_REALPATH
-/* 3 */
-#define DEFAULT_MEMORY_SIZE HUGE_SIZE
-/* 4 */
-#define FN_SEP '/'
-/* 5 */
-#define PATHLEN 512
-#define Temporary_Directory "/tmp"
-#define INCLUDE_TASK_ID
-#ifdef MAIN_INFORM_FILE
-static int32 unique_task_id(void)
-{ return (int32)getpid();
-}
-#endif
-#endif
-/* ------------------------------------------------------------------------- */
-/* UNIX64 block */
-/* ------------------------------------------------------------------------- */
-#ifdef UNIX64
-/* 1 */
#ifndef MACHINE_STRING
#define MACHINE_STRING "Unix"
#endif
/* 2 */
-#define USE_TEMPORARY_FILES
#define HAS_REALPATH
/* 3 */
#define DEFAULT_MEMORY_SIZE HUGE_SIZE
/* 4 */
#define FN_SEP '/'
/* 5 */
-#define Temporary_Directory "/tmp"
#define PATHLEN 512
+#define Temporary_Directory "/tmp"
#define INCLUDE_TASK_ID
#ifdef MAIN_INFORM_FILE
+#include <unistd.h>
static int32 unique_task_id(void)
{ return (int32)getpid();
}
#define GPAGESIZE 256
/* All Glulx memory boundaries must be multiples of GPAGESIZE. */
-/* In many places the compiler encodes a source-code location (file and
- line number) into an int32 value. The encoded value looks like
- file_number + FILE_LINE_SCALE_FACTOR*line_number. This will go
- badly if a source file has more than FILE_LINE_SCALE_FACTOR lines,
- of course. But this value is roughly eight million, which is a lot
- of lines.
-
- There is also potential trouble if we have more than 512 source files;
- perhaps 256, depending on signedness issues. However, there are other
- spots in the compiler that assume no more than 255 source files, so
- we'll stick with this for now.
-*/
-#define FILE_LINE_SCALE_FACTOR (0x800000L)
-
/* ------------------------------------------------------------------------- */
/* Structure definitions (there are a few others local to files) */
/* ------------------------------------------------------------------------- */
int32 end_line_number;
int32 beginning_character_number;
int32 end_character_number;
+ int32 orig_file_index;
+ int32 orig_beg_line_number;
+ int32 orig_beg_char_number;
+ /* We only track the beginning #origsource location, not the end. */
} debug_location;
typedef struct debug_locations_s
int reference_count;
} debug_locations;
+typedef struct brief_location_s
+{ int32 file_index;
+ int32 line_number;
+ int32 orig_file_index;
+ int32 orig_line_number;
+} brief_location;
+
typedef struct debug_location_beginning_s
{ debug_locations *head;
int32 beginning_byte_index;
int32 beginning_line_number;
int32 beginning_character_number;
+ int32 orig_file_index;
+ int32 orig_beg_line_number;
+ int32 orig_beg_char_number;
} debug_location_beginning;
typedef struct keyword_group_s
{ char *filename; /* The filename (after translation) */
FILE *handle; /* Handle of file (when open), or
NULL when closed */
+ int is_input; /* Is this a source file that we are
+ parsing? If not, this is an
+ origsource filename (and handle
+ is NULL). */
} FileId;
typedef struct ErrorPosition_s
char *source;
int line_number;
int main_flag;
+ int orig_file;
+ char *orig_source;
+ int32 orig_line;
+ int32 orig_char;
} ErrorPosition;
/* A memory block can hold at most ALLOC_CHUNK_SIZE * 72: */
#define MESSAGE_CODE 23
#define NEARBY_CODE 24
#define OBJECT_CODE 25
-#define PROPERTY_CODE 26
-#define RELEASE_CODE 27
-#define REPLACE_CODE 28
-#define SERIAL_CODE 29
-#define SWITCHES_CODE 30
-#define STATUSLINE_CODE 31
-#define STUB_CODE 32
-#define SYSTEM_CODE 33
-#define TRACE_CODE 34
-#define UNDEF_CODE 35
-#define VERB_CODE 36
-#define VERSION_CODE 37
-#define ZCHARACTER_CODE 38
+#define ORIGSOURCE_CODE 26
+#define PROPERTY_CODE 27
+#define RELEASE_CODE 28
+#define REPLACE_CODE 29
+#define SERIAL_CODE 30
+#define SWITCHES_CODE 31
+#define STATUSLINE_CODE 32
+#define STUB_CODE 33
+#define SYSTEM_CODE 34
+#define TRACE_CODE 35
+#define UNDEF_CODE 36
+#define VERB_CODE 37
+#define VERSION_CODE 38
+#define ZCHARACTER_CODE 39
#define OPENBLOCK_CODE 100
#define CLOSEBLOCK_CODE 101
/* Extern definitions for "directs" */
/* ------------------------------------------------------------------------- */
-extern int32 routine_starts_line;
+extern brief_location routine_starts_line;
extern int no_routines, no_named_routines, no_locals, no_termcs;
extern int terminating_characters[];
extern void error(char *s);
extern void error_named(char *s1, char *s2);
extern void error_numbered(char *s1, int val);
-extern void error_named_at(char *s1, char *s2, int32 report_line);
+extern void error_named_at(char *s1, char *s2, brief_location report_line);
extern void ebf_error(char *s1, char *s2);
extern void char_error(char *s, int ch);
extern void unicode_char_error(char *s, int32 uni);
extern void warning(char *s);
extern void warning_numbered(char *s1, int val);
extern void warning_named(char *s1, char *s2);
-extern void dbnu_warning(char *type, char *name, int32 report_line);
-extern void uncalled_routine_warning(char *type, char *name, int32 report_line);
+extern void dbnu_warning(char *type, char *name, brief_location report_line);
+extern void uncalled_routine_warning(char *type, char *name, brief_location report_line);
extern void obsolete_warning(char *s1);
extern void link_error(char *s);
extern void link_error_named(char *s1, char *s2);
/* Extern definitions for "files" */
/* ------------------------------------------------------------------------- */
-extern int input_file;
+extern int total_files;
+extern int current_input_file;
+extern int total_input_files;
extern FileId *InputFiles;
extern FILE *Temp1_fp, *Temp2_fp, *Temp3_fp;
extern void load_sourcefile(char *story_name, int style);
extern int file_load_chars(int file_number, char *buffer, int length);
extern void close_all_source(void);
+extern int register_orig_sourcefile(char *filename);
extern void output_file(void);
extern debug_location get_current_debug_location(void);
extern debug_location get_error_report_debug_location(void);
extern int32 get_current_line_start(void);
+extern void set_origsource_location(char *source, int32 line, int32 charnum);
+extern brief_location get_brief_location(ErrorPosition *errpos);
+extern void export_brief_location(brief_location loc, ErrorPosition *errpos);
+extern brief_location blank_brief_location;
extern void put_token_back(void);
extern void get_next_token(void);
extern int32 **symbs;
extern int32 *svals;
extern int *smarks;
-extern int32 *slines;
+extern brief_location *slines;
extern int *sflags;
#ifdef VAX
extern char *stypes;
extern void add_symbol_replacement_mapping(int original, int renamed);
extern int find_symbol_replacement(int *value);
extern void df_note_function_start(char *name, uint32 address,
- int embedded_flag, int32 source_line);
+ int embedded_flag, brief_location source_line);
extern void df_note_function_end(uint32 endaddress);
extern void df_note_function_symbol(int symbol);
extern void locate_dead_functions(void);
result.end_line_number = location->end_line_number;
result.beginning_character_number = location->end_character_number;
result.end_character_number = location->end_character_number;
+ result.orig_file_index = location->orig_file_index;
+ result.orig_beg_line_number = location->orig_beg_line_number;
+ result.orig_beg_char_number = location->orig_beg_char_number;
return result;
}
location.end_line_number;
last_token_location->location.end_character_number =
location.end_character_number;
+ last_token_location->location.orig_file_index =
+ location.orig_file_index;
+ last_token_location->location.orig_beg_line_number =
+ location.orig_beg_line_number;
+ last_token_location->location.orig_beg_char_number =
+ location.orig_beg_char_number;
} else
{ debug_locations*successor =
my_malloc
last_token_location->location.end_line_number;
result.beginning_character_number =
last_token_location->location.end_character_number;
+ result.orig_file_index = last_token_location->location.orig_file_index;
+ result.orig_beg_line_number = last_token_location->location.orig_beg_line_number;
+ result.orig_beg_char_number = last_token_location->location.orig_beg_char_number;
+
return result;
}
result.location.beginning_character_number =
beginning.beginning_character_number;
}
+
+ result.location.orig_file_index =
+ beginning.orig_file_index;
+ result.location.orig_beg_line_number =
+ beginning.orig_beg_line_number;
+ result.location.orig_beg_char_number =
+ beginning.orig_beg_char_number;
+
result.next = beginning.head->next;
result.reference_count = 0;
return result;
"default", "dictionary", "end", "endif", "extend", "fake_action",
"global", "ifdef", "ifndef", "ifnot", "ifv3", "ifv5", "iftrue",
"iffalse", "import", "include", "link", "lowstring", "message",
- "nearby", "object", "property", "release", "replace",
+ "nearby", "object", "origsource", "property", "release", "replace",
"serial", "switches", "statusline", "stub", "system_file", "trace",
"undef", "verb", "version", "zcharacter",
"" },
int file_no; /* Or 255 if not from a
file; used for debug
information */
+ char *orig_source; /* From #origsource direct */
+ int orig_file;
+ int32 orig_line;
+ int32 orig_char;
} LexicalBlock;
static LexicalBlock NoFileOpen =
-{ "<before compilation>", FALSE, FALSE, 0, 0, 0, 255 };
+ { "<before compilation>", FALSE, FALSE, 0, 0, 0, 255, NULL, 0, 0, 0 };
static LexicalBlock MakingOutput =
-{ "<constructing output>", FALSE, FALSE, 0, 0, 0, 255 };
+ { "<constructing output>", FALSE, FALSE, 0, 0, 0, 255, NULL, 0, 0, 0 };
static LexicalBlock StringLB =
-{ "<veneer routine>", FALSE, TRUE, 0, 0, 0, 255 };
+ { "<veneer routine>", FALSE, TRUE, 0, 0, 0, 255, NULL, 0, 0, 0 };
static LexicalBlock *CurrentLB; /* The current lexical
block of input text */
{ return ((CurrentLB->sys_flag)?1:0);
}
+extern void set_origsource_location(char *source, int32 line, int32 charnum)
+{
+ if (!source) {
+ /* Clear the Origsource declaration. */
+ CurrentLB->orig_file = 0;
+ CurrentLB->orig_source = NULL;
+ CurrentLB->orig_line = 0;
+ CurrentLB->orig_char = 0;
+ return;
+ }
+
+ /* Get the file number for a new or existing InputFiles entry. */
+ int file_no = register_orig_sourcefile(source);
+
+ CurrentLB->orig_file = file_no;
+ CurrentLB->orig_source = InputFiles[file_no-1].filename;
+ CurrentLB->orig_line = line;
+ CurrentLB->orig_char = charnum;
+}
+
+/* Error locations. */
+
extern debug_location get_current_debug_location(void)
{ debug_location result;
/* Assume that all input characters are one byte. */
result.beginning_character_number =
CurrentLB->chars_read - CurrentLB->line_start;
result.end_character_number = result.beginning_character_number;
+ result.orig_file_index = CurrentLB->orig_file;
+ result.orig_beg_line_number = CurrentLB->orig_line;
+ result.orig_beg_char_number = CurrentLB->orig_char;
return result;
}
ErrorReport.main_flag = CurrentLB->main_flag;
if (debugfile_switch)
ErrorReport_debug_location = get_current_debug_location();
+ ErrorReport.orig_file = CurrentLB->orig_file;
+ ErrorReport.orig_source = CurrentLB->orig_source;
+ ErrorReport.orig_line = CurrentLB->orig_line;
+ ErrorReport.orig_char = CurrentLB->orig_char;
}
extern debug_location get_error_report_debug_location(void)
{ return CurrentLB->line_start;
}
+brief_location blank_brief_location;
+
+extern brief_location get_brief_location(ErrorPosition *errpos)
+{
+ brief_location loc;
+ loc.file_index = errpos->file_number;
+ loc.line_number = errpos->line_number;
+ loc.orig_file_index = errpos->orig_file;
+ loc.orig_line_number = errpos->orig_line;
+ return loc;
+}
+
+extern void export_brief_location(brief_location loc, ErrorPosition *errpos)
+{
+ if (loc.file_index != -1)
+ { errpos->file_number = loc.file_index;
+ errpos->line_number = loc.line_number;
+ errpos->main_flag = (errpos->file_number == 1);
+ errpos->orig_source = NULL;
+ errpos->orig_file = loc.orig_file_index;
+ errpos->orig_line = loc.orig_line_number;
+ errpos->orig_char = 0;
+ }
+}
+
/* ------------------------------------------------------------------------- */
/* Hash printing and line counting */
/* ------------------------------------------------------------------------- */
static Sourcefile *CF; /* Top entry on stack */
-static int last_no_files;
+static int last_input_file;
static void begin_buffering_file(int i, int file_no)
{ int j, cnt; uchar *p;
FileStack[i].LB.chars_read = LOOKAHEAD_SIZE;
FileStack[i].LB.filename = InputFiles[file_no-1].filename;
FileStack[i].LB.file_no = file_no;
+ FileStack[i].LB.orig_source = NULL; FileStack[i].LB.orig_file = 0;
+ FileStack[i].LB.orig_line = 0; FileStack[i].LB.orig_char = 0;
CurrentLB = &(FileStack[i].LB);
CF = &(FileStack[i]);
{
File_sp = 0;
begin_buffering_file(File_sp++, 1);
- pipeline_made = TRUE; last_no_files = input_file;
+ pipeline_made = TRUE;
+ last_input_file = current_input_file;
}
static int get_next_char_from_pipeline(void)
{ uchar *p;
- while (last_no_files < input_file)
+ while (last_input_file < current_input_file)
{
/* An "Include" file must have opened since the last character
- was read... */
+ was read. Perhaps more than one. We run forward through the
+ list and add them to the include stack. But we ignore
+ "Origsource" files (which were never actually opened for
+ reading). */
+
+ last_input_file++;
+ if (!InputFiles[last_input_file-1].is_input)
+ continue;
- begin_buffering_file(File_sp++, ++last_no_files);
+ begin_buffering_file(File_sp++, last_input_file);
}
- last_no_files = input_file;
+ if (last_input_file != current_input_file)
+ compiler_error("last_input_file did not match after Include");
if (File_sp == 0)
{ lookahead = 0; lookahead2 = 0; lookahead3 = 0; return 0;
extern void init_lexer_vars(void)
{
+ blank_brief_location.file_index = -1;
+ blank_brief_location.line_number = 0;
+ blank_brief_location.orig_file_index = 0;
+ blank_brief_location.orig_line_number = 0;
}
extern void lexer_begin_prepass(void)
first_token_locations->location.end_line_number = 0;
first_token_locations->location.beginning_character_number = 0;
first_token_locations->location.end_character_number = 0;
+ first_token_locations->location.orig_file_index = 0;
+ first_token_locations->location.orig_beg_line_number = 0;
+ first_token_locations->location.orig_beg_char_number = 0;
first_token_locations->next = NULL;
first_token_locations->reference_count = 0;
last_token_location = first_token_locations;
int32 **symbs;
int32 *svals;
int *smarks; /* Glulx-only */
- int32 *slines;
+ brief_location *slines;
int *sflags;
#ifdef VAX
char *stypes; /* In VAX C, insanely, "signed char" is illegal */
unbound-symbol-causes-asm-error? */
sflags[no_symbols] = UNKNOWN_SFLAG;
stypes[no_symbols] = CONSTANT_T;
- slines[no_symbols] = ErrorReport.line_number
- + FILE_LINE_SCALE_FACTOR*ErrorReport.file_number;
+ slines[no_symbols] = get_brief_location(&ErrorReport);
if (debugfile_switch)
{ nullify_debug_file_position
(&symbol_debug_backpatch_positions[no_symbols]);
extern void describe_symbol(int k)
{ printf("%4d %-16s %2d:%04d %04x %s ",
k, (char *) (symbs[k]),
- (int)(slines[k]/FILE_LINE_SCALE_FACTOR),
- (int)(slines[k]%FILE_LINE_SCALE_FACTOR),
+ (int)(slines[k].file_index),
+ (int)(slines[k].line_number),
svals[k], typename(stypes[k]));
describe_flags(sflags[k]);
}
if (sflags[index] & UNKNOWN_SFLAG)
{ sflags[index] &= (~UNKNOWN_SFLAG);
if (is_systemfile()) sflags[index] |= INSF_SFLAG;
- slines[index] = ErrorReport.line_number
- + FILE_LINE_SCALE_FACTOR*ErrorReport.file_number;
+ slines[index] = get_brief_location(&ErrorReport);
}
}
static void create_symbol(char *p, int32 value, int type)
{ int i = symbol_index(p, -1);
- svals[i] = value; stypes[i] = type; slines[i] = 0;
+ svals[i] = value; stypes[i] = type; slines[i] = blank_brief_location;
sflags[i] = USED_SFLAG + SYSTEM_SFLAG;
emit_debug_information_for_predefined_symbol(p, i, value, type);
}
static void create_rsymbol(char *p, int value, int type)
{ int i = symbol_index(p, -1);
- svals[i] = value; stypes[i] = type; slines[i] = 0;
+ svals[i] = value; stypes[i] = type; slines[i] = blank_brief_location;
sflags[i] = USED_SFLAG + SYSTEM_SFLAG + REDEFINABLE_SFLAG;
emit_debug_information_for_predefined_symbol(p, i, value, type);
}
struct df_function_struct {
char *name; /* borrowed reference, generally to the symbs[] table */
- int32 source_line; /* copied from routine_starts_line */
+ brief_location source_line; /* copied from routine_starts_line */
int sysfile; /* does this occur in a system file? */
uint32 address; /* function offset in zcode_area (not the final address) */
uint32 newaddress; /* function offset after stripping */
Any symbol referenced from now on will be associated with the function.
*/
extern void df_note_function_start(char *name, uint32 address,
- int embedded_flag, int32 source_line)
+ int embedded_flag, brief_location source_line)
{
df_function_t *func;
int bucket;
svals = my_calloc(sizeof(int32), MAX_SYMBOLS, "symbol values");
if (glulx_mode)
smarks = my_calloc(sizeof(int), MAX_SYMBOLS, "symbol markers");
- slines = my_calloc(sizeof(int32), MAX_SYMBOLS, "symbol lines");
+ slines = my_calloc(sizeof(brief_location), MAX_SYMBOLS, "symbol lines");
stypes = my_calloc(sizeof(char), MAX_SYMBOLS, "symbol types");
sflags = my_calloc(sizeof(int), MAX_SYMBOLS, "symbol flags");
if (debugfile_switch)
df_functions_sorted = NULL;
df_functions_sorted_count = 0;
- df_note_function_start("<global namespace>", DF_NOT_IN_FUNCTION, FALSE, -1);
+ df_note_function_start("<global namespace>", DF_NOT_IN_FUNCTION, FALSE, blank_brief_location);
df_note_function_end(DF_NOT_IN_FUNCTION);
/* Now df_current_function is df_functions_head. */
}
{ printf("In:\
%3d source code files %6d syntactic lines\n\
%6d textual lines %8ld characters ",
- input_file, no_syntax_lines,
+ total_input_files, no_syntax_lines,
total_source_line_count, (long int) total_chars_read);
if (character_set_unicode) printf("(UTF-8)\n");
else if (character_set_setting == 0) printf("(plain ASCII)\n");
{ printf("In:\
%3d source code files %6d syntactic lines\n\
%6d textual lines %8ld characters ",
- input_file, no_syntax_lines,
+ total_input_files, no_syntax_lines,
total_source_line_count, (long int) total_chars_read);
if (character_set_unicode) printf("(UTF-8)\n");
else if (character_set_setting == 0) printf("(plain ASCII)\n");