The left side doesn't look unbalanced.
#define F6502_C 0x01 /* C flag */
/* Function to call any machine language subroutine. All registers in the
- * regs structure are passed into the routine and the results are passed
- * out. The B flag is ignored on input. The called routine must end with
- * an RTS.
- */
+** regs structure are passed into the routine and the results are passed
+** out. The B flag is ignored on input. The called routine must end with
+** an RTS.
+*/
void __fastcall__ _sys (struct regs* r);
/* Set and reset the break vector. The given user function is called if
- * a break occurs. The values of the registers may be read from the brk_...
- * variables. The value in brk_pc will point to the address that contains
- * the brk instruction.
- * The set_brk function will install an exit handler that will reset the
- * vector if the program ends.
- */
+** a break occurs. The values of the registers may be read from the brk_...
+** variables. The value in brk_pc will point to the address that contains
+** the brk instruction.
+** The set_brk function will install an exit handler that will reset the
+** vector if the program ends.
+*/
extern unsigned char brk_a; /* A register value */
extern unsigned char brk_x; /* X register value */
/* Define a structure with the 6522 register offsets.
- * NOTE: The timer registers are not declared as 16 bit registers, because
- * the order in which the two 8 bit halves are written is important, and
- * the compiler doesn't guarantee any order when writing 16 bit values.
- */
+** NOTE: The timer registers are not declared as 16 bit registers, because
+** the order in which the two 8 bit halves are written is important, and
+** the compiler doesn't guarantee any order when writing 16 bit values.
+*/
struct __6522 {
unsigned char prb; /* Port register B */
unsigned char pra; /* Port register A */
/* Define a structure with the 6525 register offsets. The shadow registers
- * (if port C is unused) are currently not implemented, we would need a
- * union to do that, however that would introduce an additional name.
- */
+** (if port C is unused) are currently not implemented, we would need a
+** union to do that, however that would introduce an additional name.
+*/
struct __6525 {
unsigned char pra; /* Port register A */
unsigned char prb; /* Port register B */
/* Define a structure with the 6526 register offsets.
- * NOTE: The timer registers are not declared as 16 bit registers, because
- * the order in which the two 8 bit halves are written is important, and
- * the compiler doesn't guarantee any order when writing 16 bit values.
- */
+** NOTE: The timer registers are not declared as 16 bit registers, because
+** the order in which the two 8 bit halves are written is important, and
+** the compiler doesn't guarantee any order when writing 16 bit values.
+*/
struct __6526 {
unsigned char pra; /* Port register A */
unsigned char prb; /* Port register B */
/*
- * _heap.h
- *
- * Ullrich von Bassewitz, 1998-06-03, 2004-12-19
- *
- */
+** _heap.h
+**
+** Ullrich von Bassewitz, 1998-06-03, 2004-12-19
+**
+*/
-/* Structure that preceeds a user block in most cases.
- * The aligned_malloc function may generate blocks where the start pointer
- * and size are splitted to handle a memory hole that is needed for
- * alignment.
- */
+/* Structure that preceeds a user block in most cases.
+** The aligned_malloc function may generate blocks where the start pointer
+** and size are splitted to handle a memory hole that is needed for
+** alignment.
+*/
struct usedblock {
unsigned size;
struct usedblock* start;
#define HEAP_ADMIN_SPACE sizeof (struct usedblock)
/* The data type used to implement the free list.
- * Beware: Field order is significant!
- */
+** Beware: Field order is significant!
+*/
struct freeblock {
unsigned size;
struct freeblock* next;
/* Define a structure with the vic register offsets. In cc65 mode, there
- * are aliases for the field accessible as arrays.
- */
+** are aliases for the field accessible as arrays.
+*/
#if __CC65_STD__ == __CC65_STD_CC65__
struct __vic2 {
union {
extern unsigned char _dos_type;
/* Valid _dos_type values:
- *
- * AppleDOS 3.3 - 0x00
- * ProDOS 8 1.0.1 - 0x10
- * ProDOS 8 1.0.2 - 0x10
- * ProDOS 8 1.1.1 - 0x11
- * ProDOS 8 1.2 - 0x12
- * ProDOS 8 1.3 - 0x13
- * ProDOS 8 1.4 - 0x14
- * ProDOS 8 1.5 - 0x15
- * ProDOS 8 1.6 - 0x16
- * ProDOS 8 1.7 - 0x17
- * ProDOS 8 1.8 - 0x18
- * ProDOS 8 1.9 - 0x18 (!)
- * ProDOS 8 2.0.1 - 0x21
- * ProDOS 8 2.0.2 - 0x22
- * ProDOS 8 2.0.3 - 0x23
- */
+**
+** AppleDOS 3.3 - 0x00
+** ProDOS 8 1.0.1 - 0x10
+** ProDOS 8 1.0.2 - 0x10
+** ProDOS 8 1.1.1 - 0x11
+** ProDOS 8 1.2 - 0x12
+** ProDOS 8 1.3 - 0x13
+** ProDOS 8 1.4 - 0x14
+** ProDOS 8 1.5 - 0x15
+** ProDOS 8 1.6 - 0x16
+** ProDOS 8 1.7 - 0x17
+** ProDOS 8 1.8 - 0x18
+** ProDOS 8 1.9 - 0x18 (!)
+** ProDOS 8 2.0.1 - 0x21
+** ProDOS 8 2.0.2 - 0x22
+** ProDOS 8 2.0.3 - 0x23
+*/
/* The file stream implementation and the POSIX I/O functions will use the
- * following variables to determine the file type, aux type and creation time
- * stamp to use.
- */
+** following variables to determine the file type, aux type and creation time
+** stamp to use.
+*/
extern unsigned char _filetype; /* Default: 6 */
extern unsigned int _auxtype; /* Default: 0 */
extern struct {
#define ser_apple2_slot(num) ser_ioctl (0, (void*) (num))
/* Select a slot number from 1 to 7 prior to ser_open.
- * The default slot number is 2.
- */
+** The default slot number is 2.
+*/
#define tgi_apple2_mix(onoff) tgi_ioctl (0, (void*) (onoff))
/* If onoff is 1, graphics/text mixed mode is enabled.
- * If onoff is 0, graphics/text mixed mode is disabled.
- */
+** If onoff is 0, graphics/text mixed mode is disabled.
+*/
/* The following #defines will cause the matching functions calls in conio.h
- * to be overlaid by macros with the same names, saving the function call
- * overhead.
- */
+** to be overlaid by macros with the same names, saving the function call
+** overhead.
+*/
#define _textcolor(color) COLOR_WHITE
#define _bgcolor(color) COLOR_BLACK
#define _bordercolor(color) COLOR_BLACK
void __fastcall__ textframe (unsigned char width, unsigned char height,
unsigned char style);
/* Output a frame on the text screen with the given width and height
- * starting at the current cursor position and using the given style.
- */
+** starting at the current cursor position and using the given style.
+*/
void __fastcall__ textframexy (unsigned char x, unsigned char y,
unsigned char width, unsigned char height,
unsigned __fastcall__ videomode (unsigned mode);
/* Set the video mode, return the old mode. Call with one of the VIDEOMODE_xx
- * constants.
- */
+** constants.
+*/
unsigned __fastcall__ videomode (unsigned Mode);
/* Set the video mode, return the old mode. Call with one of the VIDEOMODE_xx
- * constants.
- */
+** constants.
+*/
void toggle_videomode (void);
/* Toggle the video mode between 40 and 80 chars (calls SWAPPER).
- * THIS FUNCTION IS DEPRECATED, please use videomode instead!
- */
+** THIS FUNCTION IS DEPRECATED, please use videomode instead!
+*/
void c64mode (void);
/* Switch the C128 into C64 mode. Note: This function will not return! */
void fast (void);
/* Switch the CPU into 2MHz mode. Note: This will disable video when in
- * 40 column mode.
- */
+** 40 column mode.
+*/
void slow (void);
/* Switch the CPU into 1MHz mode. */
/* The file stream implementation and the POSIX I/O functions will
- * use the following variable to determine the file type to use.
- */
+** use the following variable to determine the file type to use.
+*/
extern char _filetype; /* Defaults to 's' */
/* Constants to use with cbm_open() for openning a file for reading or
- * writing without the need to append ",r" or ",w" to the filename.
- *
- * e.g., cbm_open(2, 8, CBM_READ, "0:data,s");
- */
+** writing without the need to append ",r" or ",w" to the filename.
+**
+** e.g., cbm_open(2, 8, CBM_READ, "0:data,s");
+*/
#define CBM_READ 0 /* default is ",p" */
#define CBM_WRITE 1 /* ditto */
#define CBM_SEQ 2 /* default is ",r" -- or ",s" when writing */
/* The cbm_* I/O functions below set _oserror (see errno.h),
- * in case of an error.
- *
- * error-code BASIC error
- * ---------- -----------
- * 1 = too many files
- * 2 = file open
- * 3 = file not open
- * 4 = file not found
- * 5 = device not present
- * 6 = not input-file
- * 7 = not output-file
- * 8 = missing file-name
- * 9 = illegal device-number
- *
- * 10 = STOP-key pushed
- * 11 = general I/O-error
- */
+** in case of an error.
+**
+** error-code BASIC error
+** ---------- -----------
+** 1 = too many files
+** 2 = file open
+** 3 = file not open
+** 4 = file not found
+** 5 = device not present
+** 6 = not input-file
+** 7 = not output-file
+** 8 = missing file-name
+** 9 = illegal device-number
+**
+** 10 = STOP-key pushed
+** 11 = general I/O-error
+*/
unsigned int cbm_load (const char* name, unsigned char device, void* data);
/* Loads file "name", from given device, to given address -- or, to the load
- * address of the file if "data" is the null pointer (like load"name",8,1
- * in BASIC).
- * Returns number of bytes that were loaded if loading was successful;
- * otherwise 0, "_oserror" contains an error-code, then (see table above).
- */
+** address of the file if "data" is the null pointer (like load"name",8,1
+** in BASIC).
+** Returns number of bytes that were loaded if loading was successful;
+** otherwise 0, "_oserror" contains an error-code, then (see table above).
+*/
unsigned char __fastcall__ cbm_save (const char* name, unsigned char device,
const void* addr, unsigned int size);
/* Saves "size" bytes, starting at "addr", to a file.
- * Returns 0 if saving was successful, otherwise an error-code (see table
- * above).
- */
+** Returns 0 if saving was successful, otherwise an error-code (see table
+** above).
+*/
unsigned char __fastcall__ cbm_open (unsigned char lfn, unsigned char device,
unsigned char sec_addr, const char* name);
/* Opens a file. Works just like the BASIC command.
- * Returns 0 if openning was successful, otherwise an error-code (see table
- * above).
- */
+** Returns 0 if openning was successful, otherwise an error-code (see table
+** above).
+*/
void __fastcall__ cbm_close (unsigned char lfn);
/* Closes a file */
int __fastcall__ cbm_read (unsigned char lfn, void* buffer, unsigned int size);
/* Reads up to "size" bytes from a file into "buffer".
- * Returns the number of actually-read bytes, 0 if there are no bytes left.
- * -1 in case of an error; then, _oserror contains an error-code (see table
- * above). (Remember: 0 means end-of-file; -1 means error.)
- */
+** Returns the number of actually-read bytes, 0 if there are no bytes left.
+** -1 in case of an error; then, _oserror contains an error-code (see table
+** above). (Remember: 0 means end-of-file; -1 means error.)
+*/
int __fastcall__ cbm_write (unsigned char lfn, const void* buffer,
unsigned int size);
/* Writes up to "size" bytes from "buffer" to a file.
- * Returns the number of actually-written bytes, or -1 in case of an error;
- * _oserror contains an error-code, then (see above table).
- */
+** Returns the number of actually-written bytes, or -1 in case of an error;
+** _oserror contains an error-code, then (see above table).
+*/
unsigned char cbm_opendir (unsigned char lfn, unsigned char device, ...);
/* Opens directory listing. Returns 0 if opening directory was successful;
- * otherwise, an error-code corresponding to cbm_open(). As an optional
- * argument, the name of the directory may be passed to the function. If
- * no explicit name is specified, "$" is used.
- */
+** otherwise, an error-code corresponding to cbm_open(). As an optional
+** argument, the name of the directory may be passed to the function. If
+** no explicit name is specified, "$" is used.
+*/
unsigned char __fastcall__ cbm_readdir (unsigned char lfn,
struct cbm_dirent* l_dirent);
/* Reads one directory line into cbm_dirent structure.
- * Returns 0 if reading directory-line was successful.
- * Returns non-zero if reading directory failed, or no more file-names to read.
- * Returns 2 on last line. Then, l_dirent->size = the number of "blocks free."
- */
+** Returns 0 if reading directory-line was successful.
+** Returns non-zero if reading directory failed, or no more file-names to read.
+** Returns 2 on last line. Then, l_dirent->size = the number of "blocks free."
+*/
void __fastcall__ cbm_closedir (unsigned char lfn);
/* Closes directory by cbm_close(lfn) */
/* The following #defines will cause the matching functions calls in conio.h
- * to be overlaid by macros with the same names, saving the function call
- * overhead.
- */
+** to be overlaid by macros with the same names, saving the function call
+** overhead.
+*/
#define _textcolor(color) COLOR_WHITE
#define _bgcolor(color) COLOR_BLACK
#define _bordercolor(color) COLOR_BLACK
/* CBM FILE TYPES. The definitions are used within standard headers, so we
- * be careful with identifiers in the user name space.
- * "Regular" files have a special bit set so it's easier to pick them out.
- */
+** be careful with identifiers in the user name space.
+** "Regular" files have a special bit set so it's easier to pick them out.
+*/
#define _CBM_T_REG 0x10U /* Bit set for regular files */
#define _CBM_T_SEQ 0x10U
#define _CBM_T_PRG 0x11U
unsigned char __fastcall__ _cbm_filetype (unsigned char c);
/* Map the start character for a file type to one of the file types above.
- * Note: 'd' will always mapped to CBM_T_DEL. The calling function has to
- * look at the following character to determine if the file type is actually
- * CBM_T_DIR.
- * This is a function used by the implementation. There is usually no need
- * to call it from user code.
- */
+** Note: 'd' will always mapped to CBM_T_DEL. The calling function has to
+** look at the following character to determine if the file type is actually
+** CBM_T_DIR.
+** This is a function used by the implementation. There is usually no need
+** to call it from user code.
+*/
long __fastcall__ cc65_idiv32by16r16 (long rhs, int lhs);
/* Divide a 32 bit signed value by a 16 bit signed value yielding a 16
- * bit result and a 16 bit remainder. The former is returned in the lower 16
- * bit of the result, the latter in the upper. If you don't need the
- * remainder, just assign (or cast) to an int.
- */
+** bit result and a 16 bit remainder. The former is returned in the lower 16
+** bit of the result, the latter in the upper. If you don't need the
+** remainder, just assign (or cast) to an int.
+*/
unsigned long __fastcall__ cc65_udiv32by16r16 (unsigned long rhs, unsigned lhs);
/* Divide a 32 bit unsigned value by a 16 bit unsigned value yielding a 16
- * bit result and a 16 bit remainder. The former is returned in the lower 16
- * bit of the result, the latter in the upper. If you don't need the
- * remainder, just assign (or cast) to an unsigned.
- */
+** bit result and a 16 bit remainder. The former is returned in the lower 16
+** bit of the result, the latter in the upper. If you don't need the
+** remainder, just assign (or cast) to an unsigned.
+*/
int __fastcall__ cc65_imul8x8r16 (signed char lhs, signed char rhs);
/* Multiplicate two signed 8 bit to yield an signed 16 bit result */
unsigned long __fastcall__ cc65_umul16x8r32 (unsigned lhs, unsigned char rhs);
/* Multiplicate an unsigned 16 bit by an unsigned 8 bit number yielding a 24
- * bit unsigned result that is extended to 32 bits for easier handling from C.
- */
+** bit unsigned result that is extended to 32 bits for easier handling from C.
+*/
unsigned long __fastcall__ cc65_umul16x16r32 (unsigned lhs, unsigned rhs);
/* Multiplicate two unsigned 16 bit to yield an unsigned 32 bit result */
int __fastcall__ cc65_sin (unsigned x);
/* Return the sine of the argument, which must be in range 0..360. The result
- * is in 8.8 fixed point format, which means that 1.0 = $100 and -1.0 = $FF00.
- */
+** is in 8.8 fixed point format, which means that 1.0 = $100 and -1.0 = $FF00.
+*/
int __fastcall__ cc65_cos (unsigned x);
/* Return the cosine of the argument, which must be in range 0..360. The result
- * is in 8.8 fixed point format, which means that 1.0 = $100 and -1.0 = $FF00.
- */
+** is in 8.8 fixed point format, which means that 1.0 = $100 and -1.0 = $FF00.
+*/
/*
- * This is the direct console interface for cc65. I do not like the function
- * names very much, but the first version started as a rewrite of Borland's
- * conio, and, even if the interface has changed, the names did not.
- *
- * The interface does direct screen I/O, so it is fast enough for most
- * programs. I did not implement text windows, since many applications do
- * not need them and should not pay for the additional overhead. It should
- * be easy to add text windows on a higher level if needed,
- *
- * Most routines do not check the parameters. This may be unfortunate but is
- * also related to speed. The coordinates are always 0/0 based.
- */
+** This is the direct console interface for cc65. I do not like the function
+** names very much, but the first version started as a rewrite of Borland's
+** conio, and, even if the interface has changed, the names did not.
+**
+** The interface does direct screen I/O, so it is fast enough for most
+** programs. I did not implement text windows, since many applications do
+** not need them and should not pay for the additional overhead. It should
+** be easy to add text windows on a higher level if needed,
+**
+** Most routines do not check the parameters. This may be unfortunate but is
+** also related to speed. The coordinates are always 0/0 based.
+*/
char cgetc (void);
/* Return a character from the keyboard. If there is no character available,
- * the function waits until the user does press a key. If cursor is set to
- * 1 (see below), a blinking cursor is displayed while waiting.
- */
+** the function waits until the user does press a key. If cursor is set to
+** 1 (see below), a blinking cursor is displayed while waiting.
+*/
int cscanf (const char* format, ...);
/* Like scanf(), but uses direct keyboard input */
unsigned char __fastcall__ cursor (unsigned char onoff);
/* If onoff is 1, a cursor is displayed when waiting for keyboard input. If
- * onoff is 0, the cursor is hidden when waiting for keyboard input. The
- * function returns the old cursor setting.
- */
+** onoff is 0, the cursor is hidden when waiting for keyboard input. The
+** function returns the old cursor setting.
+*/
unsigned char __fastcall__ revers (unsigned char onoff);
/* Enable/disable reverse character display. This may not be supported by
- * the output device. Return the old setting.
- */
+** the output device. Return the old setting.
+*/
unsigned char __fastcall__ textcolor (unsigned char color);
/* Set the color for text output. The old color setting is returned. */
void __fastcall__ chline (unsigned char length);
/* Output a horizontal line with the given length starting at the current
- * cursor position.
- */
+** cursor position.
+*/
void __fastcall__ chlinexy (unsigned char x, unsigned char y, unsigned char length);
/* Same as "gotoxy (x, y); chline (length);" */
void __fastcall__ cvline (unsigned char length);
/* Output a vertical line with the given length at the current cursor
- * position.
- */
+** position.
+*/
void __fastcall__ cvlinexy (unsigned char x, unsigned char y, unsigned char length);
/* Same as "gotoxy (x, y); cvline (length);" */
/* On some platforms, functions are not available or are dummys. To suppress
- * the call to these functions completely, the platform header files may
- * define macros for these functions that start with an underline. If such a
- * macro exists, a new macro is defined here, that expands to the one with the
- * underline. The reason for this two stepped approach is that it is sometimes
- * necessary to take the address of the function, which is not possible when
- * using a macro. Since the function prototype is still present, #undefining
- * the macro will give access to the actual function.
- */
+** the call to these functions completely, the platform header files may
+** define macros for these functions that start with an underline. If such a
+** macro exists, a new macro is defined here, that expands to the one with the
+** underline. The reason for this two stepped approach is that it is sometimes
+** necessary to take the address of the function, which is not possible when
+** using a macro. Since the function prototype is still present, #undefining
+** the macro will give access to the actual function.
+*/
#if defined(_textcolor)
# define textcolor(x) _textcolor(x)
/* When inlining-of-known-functions is enabled, overload most of the above
- * functions by macroes. The function prototypes are available again after
- * #undef'ing the macroes.
- * Please note that the following macroes do NOT handle EOF correctly, as
- * stated in the manual. If you need correct behaviour for EOF, don't
- * use -Os, or #undefine the following macroes.
- */
+** functions by macroes. The function prototypes are available again after
+** #undef'ing the macroes.
+** Please note that the following macroes do NOT handle EOF correctly, as
+** stated in the manual. If you need correct behaviour for EOF, don't
+** use -Os, or #undefine the following macroes.
+*/
#ifdef __OPT_s__
#define isalnum(c) (__AX__ = (c), \
/*
- * This is the interface to the cc65 debugger. Since many of the functions
- * used for the debugger are quite usable even in another context, they
- * are declared here.
- *
- * To use the debugger, just call DbgInit in your application. Once it has
- * been called, the debugger will catch any BRK opcode. Use the BREAK macro
- * defined below to insert breakpoints into your code.
- *
- * There are currently a lot of things that cannot be debugged, graphical
- * applications are an example. The debugger does not save your screen
- * contents, so even your text screen gets destroyed. However, you can
- * debug the C and runtime library, even if the debugger is using this
- * stuff itself.
- *
- * Note: When using the debugger, there are some other identifiers with
- * external linkage, that start with Dbg. Avoid those names if you use the
- * module.
- */
+** This is the interface to the cc65 debugger. Since many of the functions
+** used for the debugger are quite usable even in another context, they
+** are declared here.
+**
+** To use the debugger, just call DbgInit in your application. Once it has
+** been called, the debugger will catch any BRK opcode. Use the BREAK macro
+** defined below to insert breakpoints into your code.
+**
+** There are currently a lot of things that cannot be debugged, graphical
+** applications are an example. The debugger does not save your screen
+** contents, so even your text screen gets destroyed. However, you can
+** debug the C and runtime library, even if the debugger is using this
+** stuff itself.
+**
+** Note: When using the debugger, there are some other identifiers with
+** external linkage, that start with Dbg. Avoid those names if you use the
+** module.
+*/
unsigned __fastcall__ DbgDisAsm (unsigned Addr, char* Buf, unsigned char Len);
/* Disassemble one instruction at address addr into the given buffer.
- * The resulting line has the format, "AAAA__BB_BB_BB___OPC_OPERAND",
- * where AAAA is the hexadecimal representation of addr, BB are the
- * bytes (in hex) that make the instruction, OPC is the mnemonic, and
- * OPERAND is an operand for the instruction.
- * The buffer is filled with spaces up to the given length and terminated as
- * a usual C string. NOTE: Buf must be able to hold Len+1 characters.
- * The function returns the length of the disassembled instruction, so,
- * to disassemble the next instruction, add the return value to addr
- * and call the function again.
- */
+** The resulting line has the format, "AAAA__BB_BB_BB___OPC_OPERAND",
+** where AAAA is the hexadecimal representation of addr, BB are the
+** bytes (in hex) that make the instruction, OPC is the mnemonic, and
+** OPERAND is an operand for the instruction.
+** The buffer is filled with spaces up to the given length and terminated as
+** a usual C string. NOTE: Buf must be able to hold Len+1 characters.
+** The function returns the length of the disassembled instruction, so,
+** to disassemble the next instruction, add the return value to addr
+** and call the function again.
+*/
unsigned __fastcall__ DbgDisAsmLen (unsigned Addr);
/* Disassemble one instruction, but do only return the length, do not
- * create a visible representation. This function is useful when
- * disassembling backwards, it is much faster than DbgDisAsm.
- */
+** create a visible representation. This function is useful when
+** disassembling backwards, it is much faster than DbgDisAsm.
+*/
int __fastcall__ DbgIsRAM (unsigned Addr);
/* Return true if we can read and write the given address */
char* DbgMemDump (unsigned Addr, char* Buf, unsigned char Len);
/* Create a line of a memory dump in the given buffer. The buffer contains
- * the starting address (4 digits hex), then Len bytes in this format:
- * "AAAA__XX_YY_ZZ_...". The passed char buffer must hold Len*3+5 bytes
- * plus a terminator byte.
- * The function does not work correctly if the created string is longer
- * than 255 bytes.
- * The return value is Buf.
- */
+** the starting address (4 digits hex), then Len bytes in this format:
+** "AAAA__XX_YY_ZZ_...". The passed char buffer must hold Len*3+5 bytes
+** plus a terminator byte.
+** The function does not work correctly if the created string is longer
+** than 255 bytes.
+** The return value is Buf.
+*/
void __fastcall__ DbgInit (unsigned unused);
/* Initialize the debugger. Use 0 as parameter. The debugger will popup on
- * next brk encountered.
- */
+** next brk encountered.
+*/
#define BREAK() __asm__ ("brk")
/* Use this to insert breakpoints into your code */
/* Please note: All functions in this file will set _oserror *and* return its
- * value. The only exception is dio_open, which will return NULL, but _oserror
- * will be set. All function will also set _oserror in case of successful
- * execution, effectively clearing it.
- */
+** value. The only exception is dio_open, which will return NULL, but _oserror
+** will be set. All function will also set _oserror in case of successful
+** execution, effectively clearing it.
+*/
#define EM_ERR_INSTALLED 5 /* A driver is already installed */
/* Parameters for the em_copy_... functions. NOTE: The first seven bytes
- * have the same order and alignment as needed for the Commodore REU, so
- * don't change the order without changing the assembler file that defines
- * the struct offsets and the code in the REU driver.
- */
+** have the same order and alignment as needed for the Commodore REU, so
+** don't change the order without changing the assembler file that defines
+** the struct offsets and the code in the REU driver.
+*/
struct em_copy {
void* buf; /* Memory buffer to copy from or to */
unsigned char offs; /* Offset into page */
unsigned char em_uninstall (void);
/* Uninstall the currently loaded driver and return an error code.
- * Note: This call does not free allocated memory.
- */
+** Note: This call does not free allocated memory.
+*/
unsigned em_pagecount (void);
/* Return the total number of 256 byte pages available in extended memory. */
void* __fastcall__ em_map (unsigned page);
/* Unmap the current page from memory and map a new one. The function returns
- * a pointer to the location of the page in memory. Note: Without calling
- * em_commit, the old contents of the memory window may be lost!
- */
+** a pointer to the location of the page in memory. Note: Without calling
+** em_commit, the old contents of the memory window may be lost!
+*/
void* __fastcall__ em_use (unsigned page);
/* Tell the driver that the memory window is associated with a given page.
- * This call is very similar to em_map. The difference is that the driver
- * does not necessarily transfer the current contents of the extended
- * memory into the returned window. If you're going to just write to the
- * window and the current contents of the window are invalid or no longer
- * use, this call may perform better than em_map.
- */
+** This call is very similar to em_map. The difference is that the driver
+** does not necessarily transfer the current contents of the extended
+** memory into the returned window. If you're going to just write to the
+** window and the current contents of the window are invalid or no longer
+** use, this call may perform better than em_map.
+*/
void em_commit (void);
/* Commit changes in the memory window to extended storage. If the contents
- * of the memory window have been changed, these changes may be lost if
- * em_map, em_copyfrom or em_copyto are called without calling em_commit
- * first. Note: Not calling em_commit does not mean that the changes are
- * discarded, it does just mean that some drivers will discard the changes.
- */
+** of the memory window have been changed, these changes may be lost if
+** em_map, em_copyfrom or em_copyto are called without calling em_commit
+** first. Note: Not calling em_commit does not mean that the changes are
+** discarded, it does just mean that some drivers will discard the changes.
+*/
void __fastcall__ em_copyfrom (const struct em_copy* copy_data);
/* Copy from extended into linear memory. Note: This may invalidate the
- * currently mapped page.
- */
+** currently mapped page.
+*/
void __fastcall__ em_copyto (const struct em_copy* copy_data);
/* Copy from linear into extended memory. Note: This may invalidate the
- * currently mapped page.
- */
+** currently mapped page.
+*/
/* */
/* */
/* (C) 2002-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* A structure that describes the header of an extended memory driver loaded
- * into memory.
- */
+** into memory.
+*/
typedef struct {
/* Driver header */
int __fastcall__ _osmaperrno (unsigned char oserror);
/* Map an operating system specific error code (for example from _oserror)
- * into one of the E... codes above. It is user callable.
- */
+** into one of the E... codes above. It is user callable.
+*/
unsigned char __fastcall__ _seterrno (unsigned char code);
/* Set errno to a specific error code and return zero. Used by the library */
int __fastcall__ _directerrno (unsigned char code);
/* Set errno to a specific error code, clear _oserror and return -1. Used
- * by the library.
- */
+** by the library.
+*/
int __fastcall__ _mappederrno (unsigned char code);
/* Set _oserror to the given platform specific error code. If it is a real
- * error code (not zero) set errno to the corresponding system error code
- * and return -1. Otherwise return zero.
- * Used by the library.
- */
+** error code (not zero) set errno to the corresponding system error code
+** and return -1. Otherwise return zero.
+** Used by the library.
+*/
/* Note: This file is not fully ISO 9899-1999 compliant because cc65 lacks
- * a 64 bit data types and is not able to return structs > 4 bytes. The
- * declarations have been adjusted accordingly or left out.
- */
+** a 64 bit data types and is not able to return structs > 4 bytes. The
+** declarations have been adjusted accordingly or left out.
+*/
unsigned char joy_uninstall (void);
/* Uninstall the currently loaded driver and return an error code.
- * Note: This call does not free allocated memory.
- */
+** Note: This call does not free allocated memory.
+*/
unsigned char joy_count (void);
/* Return the number of joysticks supported by the driver */
/* */
/* */
/* (C) 2002-2006, Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* A structure that describes the header of a joystick driver loaded into
- * memory.
- */
+** memory.
+*/
typedef struct {
/* Driver header */
-
/* Exports structures and functions to load relocatable o65 modules at
- * runtime.
- */
+** runtime.
+*/
/* The following struct is passed to the module loader. It contains stuff,
- * the loader needs to work, and another area where the loader will place
- * informational data if it was successful. You will have to check the return
- * code of mod_load before accessing any of these additional struct members.
- */
+** the loader needs to work, and another area where the loader will place
+** informational data if it was successful. You will have to check the return
+** code of mod_load before accessing any of these additional struct members.
+*/
struct mod_ctrl {
/* Parameters passed into the loader routine. The member callerdata
- * is an opaque 16 bit datatype that may be used by the caller to
- * pass data through to the read routine. The read routine is used by the
- * loader to load any required data. There are several calls where the
- * read routine is passed a count of 1, so you may choose to make this
- * a special case when implementing read(). The read() should return the
- * number of bytes actually read. If the return value differs from the
- * passed count, this is considered an error.
- * NOTE: read() is designed so that the POSIX read() routine can be used
- * for this vector, if you're loading from disk.
- */
+ ** is an opaque 16 bit datatype that may be used by the caller to
+ ** pass data through to the read routine. The read routine is used by the
+ ** loader to load any required data. There are several calls where the
+ ** read routine is passed a count of 1, so you may choose to make this
+ ** a special case when implementing read(). The read() should return the
+ ** number of bytes actually read. If the return value differs from the
+ ** passed count, this is considered an error.
+ ** NOTE: read() is designed so that the POSIX read() routine can be used
+ ** for this vector, if you're loading from disk.
+ */
int __fastcall__ (*read) (int callerdata, void* buffer, unsigned count);
int callerdata;
unsigned char __fastcall__ mod_load (struct mod_ctrl* ctrl);
/* Load a module into memory and relocate it. The function will return an
- * error code (see below). If MLOAD_OK is returned, the outgoing fields in
- * the passed mod_ctrl struct contain information about the module just
- * loaded.
- */
+** error code (see below). If MLOAD_OK is returned, the outgoing fields in
+** the passed mod_ctrl struct contain information about the module just
+** loaded.
+*/
void __fastcall__ mod_free (void* module);
/* Free a loaded module. Note: The given pointer is the pointer to the
- * module memory, not a pointer to a control structure.
- */
+** module memory, not a pointer to a control structure.
+*/
};
/* Structure containing mouse callback functions. These functions are declared
- * in C notation here, but they cannot be C functions (at least not easily),
- * since they may be called from within an interrupt.
- */
+** in C notation here, but they cannot be C functions (at least not easily),
+** since they may be called from within an interrupt.
+*/
struct mouse_callbacks {
void (*hide) (void);
void (*prep) (void);
/* Prepare to move the mouse cursor. This function is called,
- * even when the cursor is currently invisible.
- */
+ ** even when the cursor is currently invisible.
+ */
void (*draw) (void);
/* Draw the mouse cursor. This function is called,
- * even when the cursor is currently invisible.
- */
+ ** even when the cursor is currently invisible.
+ */
void __fastcall__ (*movex) (int x);
/* Move the mouse cursor to the new X coordinate. This function is called,
- * even when the cursor is currently invisible.
- */
+ ** even when the cursor is currently invisible.
+ */
void __fastcall__ (*movey) (int y);
/* Move the mouse cursor to the new Y coordinate. This function is called,
- * even when the cursor is currently invisible.
- */
+ ** even when the cursor is currently invisible.
+ */
};
void mouse_hide (void);
/* Hide the mouse. The function manages a counter and may be called more than
- * once. For each call to mouse_hide there must be a call to mouse_show to make
- * the mouse visible again.
- */
+** once. For each call to mouse_hide there must be a call to mouse_show to make
+** the mouse visible again.
+*/
void mouse_show (void);
/* Show the mouse. See mouse_hide() for more information. */
void __fastcall__ mouse_setbox (const struct mouse_box* box);
/* Set the bounding box for the mouse pointer movement. The mouse X and Y
- * coordinates will never go outside the given box.
- * NOTE: The function does *not* check if the mouse is currently inside the
- * given margins. The proper way to use this function therefore is:
- *
- * - Hide the mouse
- * - Set the bounding box
- * - Place the mouse at the desired position
- * - Show the mouse again.
- *
- * NOTE2: When setting the box to something that is larger than the actual
- * screen, the positioning of the mouse cursor can fail. If such margins
- * are really what you want, you have to use your own cursor routines.
- */
+** coordinates will never go outside the given box.
+** NOTE: The function does *not* check if the mouse is currently inside the
+** given margins. The proper way to use this function therefore is:
+**
+** - Hide the mouse
+** - Set the bounding box
+** - Place the mouse at the desired position
+** - Show the mouse again.
+**
+** NOTE2: When setting the box to something that is larger than the actual
+** screen, the positioning of the mouse cursor can fail. If such margins
+** are really what you want, you have to use your own cursor routines.
+*/
void __fastcall__ mouse_getbox (struct mouse_box* box);
/* Get the current bounding box for the mouse pointer movement. */
void __fastcall__ mouse_move (int x, int y);
/* Set the mouse cursor to the given position. If a mouse cursor is defined
- * and currently visible, the mouse cursor is also moved.
- * NOTE: This function does not check if the given position is valid and
- * inside the bounding box.
- */
+** and currently visible, the mouse cursor is also moved.
+** NOTE: This function does not check if the given position is valid and
+** inside the bounding box.
+*/
unsigned char mouse_buttons (void);
/* Return a bit mask encoding the states of the mouse buttons. Use the
- * MOUSE_BTN_XXX flags to decode a specific button.
- */
+** MOUSE_BTN_XXX flags to decode a specific button.
+*/
void __fastcall__ mouse_pos (struct mouse_pos* pos);
/* Return the current mouse position. */
unsigned char __fastcall__ mouse_ioctl (unsigned char code, void* data);
/* Call the driver-specific ioctl function. Return an error code.
- * NON-PORTABLE!
- */
+** NON-PORTABLE!
+*/
/* This files exports structures and constants to handle the o65 relocatable
- * file format as defined by Andre Fachat. See the original document under
- *
- * http://www.6502.org/users/andre/o65/fileformat.html
- *
- * for more information.
- */
+** file format as defined by Andre Fachat. See the original document under
+**
+** http://www.6502.org/users/andre/o65/fileformat.html
+**
+** for more information.
+*/
void __fastcall__ pen_calibrate (unsigned char *XOffset);
/* Ask the user to help to calibrate a lightpen. Changes the screen!
- * A pointer to this function can be put into pen_adjuster.
- */
+** A pointer to this function can be put into pen_adjuster.
+*/
void __fastcall__ pen_adjust (const char *filename);
/* Get a lightpen calibration value from a file if it exists. Otherwise, call
- * pen_calibrate() to create a value; then, write it into a file, so that it
- * will be available at the next time that the lightpen is used.
- * Might change the screen.
- * pen_adjust() is optional; if you want to use its feature,
- * then it must be called before a driver is installed.
- * Note: This function merely saves the file-name pointer, and sets
- * the pen_adjuster pointer. The file will be read only when a driver
- * is installed, and only if that driver wants to be calibrated.
- */
+** pen_calibrate() to create a value; then, write it into a file, so that it
+** will be available at the next time that the lightpen is used.
+** Might change the screen.
+** pen_adjust() is optional; if you want to use its feature,
+** then it must be called before a driver is installed.
+** Note: This function merely saves the file-name pointer, and sets
+** the pen_adjuster pointer. The file will be read only when a driver
+** is installed, and only if that driver wants to be calibrated.
+*/
/* */
/* */
/* (C) 1998-2005 Ullrich von Bassewitz */
-/* Römerstraße 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* The following #defines will cause the matching functions calls in conio.h
- * to be overlaid by macros with the same names, saving the function call
- * overhead.
- */
+** to be overlaid by macros with the same names, saving the function call
+** overhead.
+*/
#define _textcolor(color) COLOR_WHITE
#define _bgcolor(color) COLOR_BLACK
#define _bordercolor(color) COLOR_BLACK
#define SER_HS_SW 0x02 /* Software handshake */
/* Bit masks to mask out things from the status returned by ser_status.
- * These are 6551 specific and must be mapped by drivers for other chips.
- */
+** These are 6551 specific and must be mapped by drivers for other chips.
+*/
#define SER_STATUS_PE 0x01 /* Parity error */
#define SER_STATUS_FE 0x02 /* Framing error */
#define SER_STATUS_OE 0x04 /* Overrun error */
unsigned char ser_uninstall (void);
/* Uninstall the currently loaded driver and return an error code.
- * Note: This call does not free allocated memory.
- */
+** Note: This call does not free allocated memory.
+*/
unsigned char __fastcall__ ser_open (const struct ser_params* params);
/* "Open" the port by setting the port parameters and enable interrupts. */
unsigned char __fastcall__ ser_get (char* b);
/* Get a character from the serial port. If no characters are available, the
- * function will return SER_ERR_NO_DATA, so this is not a fatal error.
- */
+** function will return SER_ERR_NO_DATA, so this is not a fatal error.
+*/
unsigned char __fastcall__ ser_put (char b);
/* Send a character via the serial port. There is a transmit buffer, but
- * transmitting is not done via interrupt. The function returns
- * SER_ERR_OVERFLOW if there is no space left in the transmit buffer.
- */
+** transmitting is not done via interrupt. The function returns
+** SER_ERR_OVERFLOW if there is no space left in the transmit buffer.
+*/
unsigned char __fastcall__ ser_status (unsigned char* status);
/* Return the serial port status. */
/* Note: This file is not fully ISO 9899-1999 compliant because cc65 lacks
- * a 64 bit data types. The declarations have been adjusted accordingly.
- */
+** a 64 bit data types. The declarations have been adjusted accordingly.
+*/
#if __CC65_STD__ == __CC65_STD_CC65__
int __fastcall__ posix_memalign (void** memptr, size_t alignment, size_t size);
/* Allocate a block of memory with the given "size", which is aligned to a
- * memory address that is a multiple of "alignment". "alignment" MUST NOT be
- * zero, and MUST be a power of two; otherwise, this function will return
- * EINVAL. The function returns ENOMEM if not enough memory is available
- * to satisfy the request. "memptr" must point to a variable; that variable
- * will return the address of the allocated memory. Use free() to release that
- * allocated block.
- */
+** memory address that is a multiple of "alignment". "alignment" MUST NOT be
+** zero, and MUST be a power of two; otherwise, this function will return
+** EINVAL. The function returns ENOMEM if not enough memory is available
+** to satisfy the request. "memptr" must point to a variable; that variable
+** will return the address of the allocated memory. Use free() to release that
+** allocated block.
+*/
#endif
void __fastcall__ _heapadd (void* mem, size_t size);
void* __fastcall__ memset (void* s, int c, size_t count);
/* The following is an internal function, the compiler will replace memset
- * with it if the fill value is zero. Never use this one directly!
- */
+** with it if the fill value is zero. Never use this one directly!
+*/
void* __fastcall__ _bzero (void* ptr, size_t n);
/* Non standard: */
/* Counters incremented asynchronously!
- * If you want more complex, copy the crt0.s file from the libsrc/supervision
- * directory and code them yourself (in assembler)
- */
+** If you want more complex, copy the crt0.s file from the libsrc/supervision
+** directory and code them yourself (in assembler)
+*/
extern unsigned char sv_nmi_counter;
extern unsigned char sv_timer_irq_counter;
extern unsigned char sv_timer_dma_counter;
/* */
/* */
/* (C) 2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/*
- * Suggested field contents:
- *
- * sysname
- * Should contain the name of the underlying operating system, or "cc65"
- * if the program runs on the bare machine.
- *
- * nodename
- * Is empty or may be defined by the implementor.
- *
- * release
- * Contains the operating system release or the major/minor cc65 version
- * if sysname contains "cc65".
- *
- * version
- * Contains the operating system version or the cc65 patch version if
- * sysname contains "cc65".
- *
- * machine
- * Contains the complete name of the machine, like "Commodore 64",
- * "Oric Atmos" or similar.
- *
- * Beware: The library sources written in assembler have knowledge about this
- * struct!
- */
+** Suggested field contents:
+**
+** sysname
+** Should contain the name of the underlying operating system, or "cc65"
+** if the program runs on the bare machine.
+**
+** nodename
+** Is empty or may be defined by the implementor.
+**
+** release
+** Contains the operating system release or the major/minor cc65 version
+** if sysname contains "cc65".
+**
+** version
+** Contains the operating system version or the cc65 patch version if
+** sysname contains "cc65".
+**
+** machine
+** Contains the complete name of the machine, like "Commodore 64",
+** "Oric Atmos" or similar.
+**
+** Beware: The library sources written in assembler have knowledge about this
+** struct!
+*/
struct utsname {
char sysname[17];
char nodename[9];
void tgi_unload (void);
/* Uninstall, then unload the currently loaded driver. Will call tgi_done if
- * necessary.
- */
+** necessary.
+*/
void __fastcall__ tgi_install (void* driver);
/* Install an already loaded driver. */
void tgi_uninstall (void);
/* Uninstall the currently loaded driver but do not unload it. Will call
- * tgi_done if necessary.
- */
+** tgi_done if necessary.
+*/
void tgi_init (void);
/* Initialize the already loaded graphics driver. */
void tgi_done (void);
/* End graphics mode, switch back to text mode. Will NOT uninstall or unload
- * the driver!
- */
+** the driver!
+*/
const tgi_vectorfont* __fastcall__ tgi_load_vectorfont (const char* name);
/* Load a vector font into memory and return it. In case of errors, NULL is
- * returned and an error is set, which can be retrieved using tgi_geterror.
- * To use the font, it has to be installed using tgi_install_vectorfont.
- */
+** returned and an error is set, which can be retrieved using tgi_geterror.
+** To use the font, it has to be installed using tgi_install_vectorfont.
+*/
void __fastcall__ tgi_install_vectorfont (const tgi_vectorfont* font);
/* Install a vector font for use. More than one vector font can be loaded,
- * but only one can be active. This function is used to tell which one. Call
- * with a NULL pointer to uninstall the currently installed font.
- */
+** but only one can be active. This function is used to tell which one. Call
+** with a NULL pointer to uninstall the currently installed font.
+*/
void __fastcall__ tgi_free_vectorfont (const tgi_vectorfont* font);
/* Free a vector font that was previously loaded into memory. */
unsigned char tgi_geterror (void);
/* Return the error code for the last operation. This will also clear the
- * error.
- */
+** error.
+*/
const char* __fastcall__ tgi_geterrormsg (unsigned char code);
/* Get an error message describing the error in code. */
unsigned char tgi_getmaxcolor (void);
/* Return the maximum supported color number (the number of colors would
- * then be getmaxcolor()+1).
- */
+** then be getmaxcolor()+1).
+*/
void __fastcall__ tgi_setcolor (unsigned char color);
/* Set the current drawing color. */
void __fastcall__ tgi_setpalette (const unsigned char* palette);
/* Set the palette (not available with all drivers/hardware). palette is
- * a pointer to as many entries as there are colors.
- */
+** a pointer to as many entries as there are colors.
+*/
const unsigned char* tgi_getpalette (void);
/* Return the current palette. */
unsigned tgi_getmaxx (void);
/* Return the maximum x coordinate. The resolution in x direction is
- * getmaxx() + 1
- */
+** getmaxx() + 1
+*/
unsigned tgi_getyres (void);
/* Return the resolution in Y direction. */
unsigned tgi_getmaxy (void);
/* Return the maximum y coordinate. The resolution in y direction is
- * getmaxy() + 1
- */
+** getmaxy() + 1
+*/
unsigned tgi_getaspectratio (void);
/* Returns the aspect ratio for the loaded driver. The aspect ratio is an
- * 8.8 fixed point value.
- */
+** 8.8 fixed point value.
+*/
void __fastcall__ tgi_setaspectratio (unsigned aspectratio);
/* Set a new aspect ratio for the loaded driver. The aspect ratio is an
- * 8.8 fixed point value.
- */
+** 8.8 fixed point value.
+*/
unsigned char __fastcall__ tgi_getpixel (int x, int y);
/* Get the color value of a pixel. */
void __fastcall__ tgi_line (int x1, int y1, int x2, int y2);
/* Draw a line in the current drawing color. The graphics cursor will
- * be set to x2/y2 by this call.
- */
+** be set to x2/y2 by this call.
+*/
void __fastcall__ tgi_lineto (int x2, int y2);
/* Draw a line in the current drawing color from the graphics cursor to the
- * new end point. The graphics cursor will be updated to x2/y2.
- */
+** new end point. The graphics cursor will be updated to x2/y2.
+*/
void __fastcall__ tgi_circle (int x, int y, unsigned char radius);
/* Draw a circle in the current drawing color. */
void __fastcall__ tgi_ellipse (int x, int y, unsigned char rx, unsigned char ry);
/* Draw a full ellipse with center at x/y and radii rx/ry using the current
- * drawing color.
- */
+** drawing color.
+*/
void __fastcall__ tgi_arc (int x, int y, unsigned char rx, unsigned char ry,
unsigned sa, unsigned ea);
/* Draw an ellipse arc with center at x/y and radii rx/ry using the current
- * drawing color. The arc covers the angle between sa and ea (startangle and
- * endangle), which must be in the range 0..360 (otherwise the function may
- * bevave unextectedly).
- */
+** drawing color. The arc covers the angle between sa and ea (startangle and
+** endangle), which must be in the range 0..360 (otherwise the function may
+** bevave unextectedly).
+*/
void __fastcall__ tgi_pieslice (int x, int y, unsigned char rx, unsigned char ry,
unsigned sa, unsigned ea);
/* Draw an ellipse pie slice with center at x/y and radii rx/ry using the
- * current drawing color. The pie slice covers the angle between sa and ea
- * (startangle and endangle), which must be in the range 0..360 (otherwise the
- * function may behave unextectedly).
- */
+** current drawing color. The pie slice covers the angle between sa and ea
+** (startangle and endangle), which must be in the range 0..360 (otherwise the
+** function may behave unextectedly).
+*/
void __fastcall__ tgi_bar (int x1, int y1, int x2, int y2);
/* Draw a bar (a filled rectangle) using the current color. */
void __fastcall__ tgi_settextdir (unsigned char dir);
/* Set the direction for text output. dir is one of the TGI_TEXT_XXX
- * constants.
- */
+** constants.
+*/
void __fastcall__ tgi_settextscale (unsigned width, unsigned height);
/* Set the scaling for text output. The scaling factors for width and height
- * are 8.8 fixed point values. This means that $100 = 1 $200 = 2 etc.
- */
+** are 8.8 fixed point values. This means that $100 = 1 $200 = 2 etc.
+*/
void __fastcall__ tgi_settextstyle (unsigned width, unsigned height,
unsigned char dir, unsigned char font);
/* Set the style for text output. The scaling factors for width and height
- * are 8.8 fixed point values. This means that $100 = 1 $200 = 2 etc.
- * dir is one of the TGI_TEXT_XXX constants. font is one of the TGI_FONT_XXX
- * constants.
- */
+** are 8.8 fixed point values. This means that $100 = 1 $200 = 2 etc.
+** dir is one of the TGI_TEXT_XXX constants. font is one of the TGI_FONT_XXX
+** constants.
+*/
unsigned __fastcall__ tgi_gettextwidth (const char* s);
/* Calculate the width of the text in pixels according to the current text
- * style.
- */
+** style.
+*/
unsigned __fastcall__ tgi_gettextheight (const char* s);
/* Calculate the height of the text in pixels according to the current text
- * style.
- */
+** style.
+*/
void __fastcall__ tgi_outtext (const char* s);
/* Output text at the current graphics cursor position. The graphics cursor
- * is moved to the end of the text.
- */
+** is moved to the end of the text.
+*/
void __fastcall__ tgi_outtextxy (int x, int y, const char* s);
/* Output text at the given cursor position. The graphics cursor is moved to
- * the end of the text.
- */
+** the end of the text.
+*/
unsigned __fastcall__ tgi_ioctl (unsigned char code, void* data);
/* Call the driver specific control function. What this function does for
- * a specific code depends on the driver. The driver will set an error
- * for unknown codes or values.
- */
+** a specific code depends on the driver. The driver will set an error
+** for unknown codes or values.
+*/
int __fastcall__ tgi_imulround (int rhs, int lhs);
/* Helper function for functions using sine/cosine: Multiply two values, one
- * being an 8.8 fixed point one, and return the rounded and scaled result.
- */
+** being an 8.8 fixed point one, and return the rounded and scaled result.
+*/
void __fastcall__ tgi_vectorchar (char C);
/* Draw one character of the vector font at the current graphics cursor
- * position using the current font magnification.
- */
+** position using the current font magnification.
+*/
/* */
/* */
/* (C) 1998-2012 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
# define CLOCKS_PER_SEC 1 /* ANSI */
#elif defined(__LYNX__)
/* The clock-rate depends on the video scan-rate;
-** so, read it at run-time. */
+** so, read it at run-time.
+*/
extern clock_t _clk_tck (void);
# define CLK_TCK _clk_tck()
# define CLOCKS_PER_SEC _clk_tck()
time_t _systime (void);
/* Similar to time(), but:
- * - Is not ISO C
- * - Does not take the additional pointer
- * - Does not set errno when returning -1
- */
+** - Is not ISO C
+** - Does not take the additional pointer
+** - Does not set errno when returning -1
+*/
/* ISO C function prototypes */
char* __fastcall__ asctime (const struct tm* timep);
;
; time_t _systime (void);
; /* Similar to time(), but:
-; * - Is not ISO C
-; * - Does not take the additional pointer
-; * - Does not set errno when returning -1
-; */
+; ** - Is not ISO C
+; ** - Does not take the additional pointer
+; ** - Does not set errno when returning -1
+; */
;
.include "time.inc"
; This file defines the EXE file "trailer" which sets the entry point
.export __AUTOSTART__: absolute = 1
- .import start
+ .import start
.include "atari.inc"
end:
.ifndef __ATARIXL__
-tmp: ; outside of the load chunk, some kind of poor man's .bss
+tmp: ; outside of the load chunk, some kind of poor man's .bss
.endif
; ------------------------------------------------------------------------
;
; time_t _systime (void);
; /* Similar to time(), but:
-; * - Is not ISO C
-; * - Does not take the additional pointer
-; * - Does not set errno when returning -1
-; */
+; ** - Is not ISO C
+; ** - Does not take the additional pointer
+; ** - Does not set errno when returning -1
+; */
;
.export __systime
/* w2cas.c -- write file to cassette
- *
- * This program writes a boot file (typically linked with
- * 'atari-cassette.cfg') to the cassette.
- * Only files < 32K are supported, since the loading of
- * larger files requires a special loader inside the program.
- *
- * Christian Groessler, chris@groessler.org, 2014
- */
+**
+** This program writes a boot file (typically linked with
+** 'atari-cassette.cfg') to the cassette.
+** Only files < 32K are supported, since the loading of
+** larger files requires a special loader inside the program.
+**
+** Christian Groessler, chris@groessler.org, 2014
+*/
#include <stdio.h>
#include <stdlib.h>
;
; time_t _systime (void);
; /* Similar to time(), but:
-; * - Is not ISO C
-; * - Does not take the additional pointer
-; * - Does not set errno when returning -1
-; */
+; ** - Is not ISO C
+; ** - Does not take the additional pointer
+; ** - Does not set errno when returning -1
+; */
;
.export __systime
;
; void fast (void);
; /* Switch the CPU into 2MHz mode. Note: This will disable video when in
-; * 40 column mode.
-; */
+; ** 40 column mode.
+; */
;
.export _fast
;
; time_t _systime (void);
; /* Similar to time(), but:
-; * - Is not ISO C
-; * - Does not take the additional pointer
-; * - Does not set errno when returning -1
-; */
+; ** - Is not ISO C
+; ** - Does not take the additional pointer
+; ** - Does not set errno when returning -1
+; */
;
.include "time.inc"
;
; time_t _systime (void);
; /* Similar to time(), but:
-; * - Is not ISO C
-; * - Does not take the additional pointer
-; * - Does not set errno when returning -1
-; */
+; ** - Is not ISO C
+; ** - Does not take the additional pointer
+; ** - Does not set errno when returning -1
+; */
;
.export __systime
;
; time_t _systime (void);
; /* Similar to time(), but:
-; * - Is not ISO C
-; * - Does not take the additional pointer
-; * - Does not set errno when returning -1
-; */
+; ** - Is not ISO C
+; ** - Does not take the additional pointer
+; ** - Does not set errno when returning -1
+; */
;
.include "time.inc"
/*
- * Marc 'BlackJack' Rintsch, 06.03.2001
- *
- * unsigned int cbm_load(const char* name,
- * unsigned char device,
- * const unsigned char* data);
- */
+** Marc 'BlackJack' Rintsch, 06.03.2001
+**
+** unsigned int cbm_load(const char* name,
+** unsigned char device,
+** const unsigned char* data);
+*/
#include <cbm.h>
/* loads file "name" from given device to given address or to the load address
- * of the file if "data" is 0
- */
+** of the file if "data" is 0
+*/
unsigned int cbm_load(const char* name, unsigned char device, void* data)
{
- /* LFN is set to 0 but it's not needed for loading.
- * (BASIC V2 sets it to the value of the SA for LOAD) */
+ /* LFN is set to 0; but, it's not needed for loading
+ ** (BASIC V2 sets it to the value of the SA for LOAD).
+ */
cbm_k_setlfs(0, device, data == 0);
cbm_k_setnam(name);
return (cbm_k_load(0, (unsigned int)data) - (unsigned int)data);
; unsigned char sec_addr,
; const char* name);
; /* Opens a file. Works just like the BASIC command.
-; * Returns 0 if opening was successful, otherwise an errorcode (see table
-; * below).
-; */
+; ** Returns 0 if opening was successful, otherwise an errorcode (see table
+; ** below).
+; */
; {
; cbm_k_setlfs(lfn, device, sec_addr);
; cbm_k_setnam(name);
;
; int __fastcall__ cbm_read (unsigned char lfn, void* buffer, unsigned int size)
; /* Reads up to "size" bytes from a file to "buffer".
-; * Returns the number of actually read bytes, 0 if there are no bytes left
-; * (EOF) or -1 in case of an error. _oserror contains an errorcode then (see
-; * table below).
-; */
+; ** Returns the number of actually read bytes, 0 if there are no bytes left
+; ** (EOF) or -1 in case of an error. _oserror contains an errorcode then (see
+; ** table below).
+; */
; {
; static unsigned int bytesread;
; static unsigned char tmp;
; tmp = cbm_k_basin();
;
; /* the kernal routine BASIN sets ST to EOF if the end of file
-; * is reached the first time, then we have store tmp.
-; * every subsequent call returns EOF and READ ERROR in ST, then
-; * we have to exit the loop here immidiatly. */
+; ** is reached the first time, then we have store tmp.
+; ** every subsequent call returns EOF and READ ERROR in ST, then
+; ** we have to exit the loop here immediatly.
+; */
; if (cbm_k_readst() & 0xBF) break;
;
; ((unsigned char*)buffer)[bytesread++] = tmp;
/*
- * Marc 'BlackJack' Rintsch, 11.03.2001
- *
- * unsigned char cbm_save(const char* name,
- * char device,
- * unsigned char* data,
- * unsigned int size);
- */
+** Marc 'BlackJack' Rintsch, 11.03.2001
+**
+** unsigned char cbm_save(const char* name,
+** char device,
+** unsigned char* data,
+** unsigned int size);
+*/
#include <cbm.h>
#include <errno.h>
/* saves a memory area from start to end-1 to a file.
- */
+*/
unsigned char __fastcall__ cbm_save (const char* name,
unsigned char device,
const void* data,
/*
- * Internal include file, do not use directly.
- * Written by Ullrich von Bassewitz. Based on code by Groepaz.
- */
+** Internal include file, do not use directly.
+** Written by Ullrich von Bassewitz. Based on code by Groepaz.
+*/
unsigned char __fastcall__ _dirread (DIR* dir, void* buf, unsigned char count);
/* Read characters from the directory into the supplied buffer. Makes sure,
- * errno is set in case of a short read. Return true if the read was
- * successful and false otherwise.
- */
+** errno is set in case of a short read. Return true if the read was
+** successful and false otherwise.
+*/
unsigned char __fastcall__ _dirread1 (DIR* dir, void* buf);
/* Read one byte from the directory into the supplied buffer. Makes sure,
- * errno is set in case of a short read. Return true if the read was
- * successful and false otherwise.
- */
+** errno is set in case of a short read. Return true if the read was
+** successful and false otherwise.
+*/
;
; unsigned char __fastcall__ _dirread1 (DIR* dir, void* buf);
; /* Read one byte from the directory into the supplied buffer. Makes sure,
-; * errno is set in case of a short read. Return true if the read was
-; * successful and false otherwise.
-; */
+; ** errno is set in case of a short read. Return true if the read was
+; ** successful and false otherwise.
+; */
__dirread1:
;
; unsigned char __fastcall__ _dirread (DIR* dir, void* buf, unsigned char count);
; /* Read characters from the directory into the supplied buffer. Makes sure,
-; * errno is set in case of a short read. Return true if the read was
-; * successful and false otherwise.
-; */
+; ** errno is set in case of a short read. Return true if the read was
+; ** successful and false otherwise.
+; */
__dirread:
/*
- * Ullrich von Bassewitz, 2012-05-30. Based on code by Groepaz.
- */
+** Ullrich von Bassewitz, 2012-05-30. Based on code by Groepaz.
+*/
#include <stdlib.h>
#include <string.h>
DIR d;
/* Setup the actual file name that is sent to the disk. We accept "0:",
- * "1:" and "." as directory names.
- */
+ ** "1:" and "." as directory names.
+ */
d.name[0] = '$';
if (name == 0 || name[0] == '\0' || (name[0] == '.' && name[1] == '\0')) {
d.name[1] = '\0';
/*
- * Ullrich von Bassewitz, 2012-05-30. Based on code by Groepaz.
- */
+** Ullrich von Bassewitz, 2012-05-30. Based on code by Groepaz.
+*/
dir->off += count + 4;
/* End of directory is reached if the buffer contains "blocks free". It is
- * sufficient here to check for the leading 'b'. buffer will contain at
- * least one byte if we come here.
- */
+ ** sufficient here to check for the leading 'b'. buffer will contain at
+ ** least one byte if we come here.
+ */
if (buffer[0] == 'b') {
goto exitpoint;
}
/*
- * Ullrich von Bassewitz, 2012-06-03. Based on code by Groepaz.
- */
+** Ullrich von Bassewitz, 2012-06-03. Based on code by Groepaz.
+*/
#include <fcntl.h>
#include <unistd.h>
;
; time_t _systime (void);
; /* Similar to time(), but:
-; * - Is not ISO C
-; * - Does not take the additional pointer
-; * - Does not set errno when returning -1
-; */
+; ** - Is not ISO C
+; ** - Does not take the additional pointer
+; ** - Does not set errno when returning -1
+; */
;
.include "time.inc"
;
; time_t _systime (void);
; /* Similar to time(), but:
-; * - Is not ISO C
-; * - Does not take the additional pointer
-; * - Does not set errno when returning -1
-; */
+; ** - Is not ISO C
+; ** - Does not take the additional pointer
+; ** - Does not set errno when returning -1
+; */
;
.include "time.inc"
/*
- * _afailed.c
- *
- * Ullrich von Bassewitz, 06.06.1998
- */
+** _afailed.c
+**
+** Ullrich von Bassewitz, 06.06.1998
+*/
/*
- * _file.h
- *
- * (C) Copyright 1998, 2002 Ullrich von Bassewitz (uz@cc65.org)
- *
- */
+** _file.h
+**
+** (C) Copyright 1998, 2002 Ullrich von Bassewitz (uz@cc65.org)
+**
+*/
/*
- * Ullrich von Bassewitz, 11.08.1998
- *
- * Hex conversion table. Must be in C since the compiler will convert
- * to the correct character set for the target platform.
- */
+** Ullrich von Bassewitz, 11.08.1998
+**
+** Hex conversion table. Must be in C since the compiler will convert
+** to the correct character set for the target platform.
+*/
/*
- * Ullrich von Bassewitz, 2012-11-26
- *
- * Minimum value of a long. Is used in ascii conversions, since this value
- * has no positive counterpart than can be represented in 32 bits. In C,
- * since the compiler will convert to the correct character set for the
- * target platform.
- */
+** Ullrich von Bassewitz, 2012-11-26
+**
+** Minimum value of a long. Is used in ascii conversions, since this value
+** has no positive counterpart than can be represented in 32 bits. In C,
+** since the compiler will convert to the correct character set for the
+** target platform.
+*/
/*
- * _printf.h
- *
- * (C) Copyright 1998 Ullrich von Bassewitz (uz@cc65.org)
- *
- */
+** _printf.h
+**
+** (C) Copyright 1998 Ullrich von Bassewitz (uz@cc65.org)
+**
+*/
/* Control structure passed to the low level worker function.
- * Beware: This function will access the structure on the assembly level,
- * so check this when altering the structure.
- */
+** Beware: This function will access the structure on the assembly level,
+** so check this when altering the structure.
+*/
struct outdesc {
int ccount; /* Character counter */
outfunc fout; /* Routine used to output data */
/*
- * _scanf.c
- *
- * (c) Copyright 2001-2005, Ullrich von Bassewitz <uz@cc65.org>
- * 2005-01-24, Greg King <gngking@erols.com>
- *
- * This is the basic layer for all scanf-type functions. It should be
- * rewritten in assembly, at some time in the future. So, some of the code
- * is not as elegant as it could be.
- */
+** _scanf.c
+**
+** (c) Copyright 2001-2005, Ullrich von Bassewitz <uz@cc65.org>
+** 2005-01-24, Greg King <greg.king5@ver5z6n.net>
+**
+** This is the basic layer for all scanf-type functions. It should be
+** rewritten in assembly, at some time in the future. So, some of the code
+** is not as elegant as it could be.
+*/
};
/* We need C to be 16 bits since we cannot check for EOF otherwise.
- * Unfortunately, this causes the code to be quite larger, even if for most
- * purposes, checking the low byte would be enough, since if C is EOF, the
- * low byte will not match any useful character anyway (at least for the
- * supported platforms - I know that this is not portable). So the following
- * macro is used to access just the low byte of C.
- */
+** Unfortunately, this causes the code to be quite larger, even if for most
+** purposes, checking the low byte would be enough, since if C is EOF, the
+** low byte will not match any useful character anyway (at least for the
+** supported platforms - I know that this is not portable). So the following
+** macro is used to access just the low byte of C.
+*/
#define CHAR(c) (*((unsigned char*)&(c)))
/* We don't want the optimizer to ruin our "perfect" ;-)
- * assembly code!
- */
+** assembly code!
+*/
#pragma optimize (push, off)
static unsigned FindBit (void)
/* Locate the character's bit in the charset array.
- * < .A - Argument character
- * > .X - Offset of the byte in the character-set mask
- * > .A - Bit-mask
- */
+** < .A - Argument character
+** > .X - Offset of the byte in the character-set mask
+** > .A - Bit-mask
+*/
{
asm ("pha");
asm ("lsr a"); /* Divide by CHAR_BIT */
asm ("stx %v+1", C);
/* If C is EOF, don't bump the character counter.
- * Only the high-byte needs to be checked.
- */
+ ** Only the high-byte needs to be checked.
+ */
asm ("inx");
asm ("beq %g", Done);
static void ReadSign (void)
/* Read an optional sign and skip it. Store 1 in Positive if the value is
- * positive, store 0 otherwise.
- */
+** positive, store 0 otherwise.
+*/
{
/* We can ignore the high byte of C here, since if it is EOF, the lower
- * byte won't match anyway.
- */
+ ** byte won't match anyway.
+ */
asm ("lda %v", C);
asm ("cmp #'-'");
asm ("bne %g", NotNeg);
static void AssignInt (void)
/* Assign the integer value in Val to the next argument. The function makes
- * several non-portable assumptions, to reduce code size:
- * - signed and unsigned types have the same representation.
- * - short and int have the same representation.
- * - all pointer types have the same representation.
- */
+** several non-portable assumptions, to reduce code size:
+** - signed and unsigned types have the same representation.
+** - short and int have the same representation.
+** - all pointer types have the same representation.
+*/
{
if (NoAssign == false) {
static void __fastcall__ ScanInt (unsigned char Base)
/* Scan an integer including white space, sign and optional base spec,
- * and store it into IntVal.
- */
+** and store it into IntVal.
+*/
{
/* Skip whitespace */
SkipWhite ();
Base = 8;
/* Restart at the beginning of the number because it might
- * be only a single zero digit (which already was read).
- */
+ ** be only a single zero digit (which already was read).
+ */
PushBack ();
C = '0';
}
int __fastcall__ _scanf (const struct scanfdata* D,
const char* format_, va_list ap_)
/* This is the routine used to do the actual work. It is called from several
- * types of wrappers to implement the actual ISO xxscanf functions.
- */
+** types of wrappers to implement the actual ISO xxscanf functions.
+*/
{
register char* S;
bool HaveWidth; /* True if a width was given */
char Start; /* Walks over a range */
/* Place copies of the arguments into global variables. This is not very
- * nice, but on a 6502 platform it gives better code, since the values
- * do not have to be passed as parameters.
- */
+ ** nice, but on a 6502 platform it gives better code, since the values
+ ** do not have to be passed as parameters.
+ */
D_ = D;
format = format_;
ap = ap_;
CharCount = 0;
/* Set up the jump "label". CheckEnd() will use that label when EOF
- * is reached. ReadInt() will use it when number-conversion fails.
- */
+ ** is reached. ReadInt() will use it when number-conversion fails.
+ */
if ((unsigned char) setjmp (JumpBuf) == RC_OK) {
Again:
if ((bool) isspace ((int) F)) {
/* Special white space handling: Any whitespace in the
- * format string matches any amount of whitespace including
- * none(!). So this match will never fail.
- */
+ ** format string matches any amount of whitespace including
+ ** none(!). So this match will never fail.
+ */
SkipWhite ();
continue;
}
if (C != (int) F) {
/* A mismatch -- we will stop scanning the input,
- * and return the number of assigned conversions.
- */
+ ** and return the number of assigned conversions.
+ */
goto NoConv;
}
if (Width == 0) {
/* Invalid specification */
/* Note: This method of leaving the function might seem
- * to be crude, but it optimizes very well because
- * the four exits can share this code.
- */
+ ** to be crude, but it optimizes very well because
+ ** the four exits can share this code.
+ */
_seterrno (EINVAL);
Assignments = EOF;
PushBack ();
return Assignments;
}
/* Increment-and-test makes better code than test-and-decrement
- * does. So, change the width into a form that can be used in
- * that way.
- */
+ ** does. So, change the width into a form that can be used in
+ ** that way.
+ */
Width = ~Width;
/* 3. Length modifier */
/* 4. Conversion specifier */
switch (F) {
/* 'd' and 'u' conversions are actually the same, since the
- * standard says that even the 'u' modifier allows an
- * optionally signed integer.
- */
+ ** standard says that even the 'u' modifier allows an
+ ** optionally signed integer.
+ */
case 'd': /* Optionally signed decimal integer */
case 'u':
ScanInt (10);
if (NoAssign == false) {
S = va_arg (ap, char*);
/* ## This loop is convenient for us, but it isn't
- * standard C. The standard implies that a failure
- * shouldn't put anything into the array argument.
- */
+ ** standard C. The standard implies that a failure
+ ** shouldn't put anything into the array argument.
+ */
while (++Width) {
CheckEnd (); /* Is it a matching failure? */
*S++ = C;
}
if (F == ']') {
/* Empty sets aren't allowed; so, a right-bracket
- * at the beginning must be a member of the set.
- */
+ ** at the beginning must be a member of the set.
+ */
AddCharToSet (F);
GetFormat ();
}
break;
default:
/* Include all characters
- * that are in the range.
- */
+ ** that are in the range.
+ */
while (1) {
AddCharToSet (Start);
if (Start == F) {
}
/* We have the set in CharSet. Read characters and
- * store them into a string while they are part of
- * the set.
- */
+ ** store them into a string while they are part of
+ ** the set.
+ */
Match = false;
if (NoAssign == false) {
S = va_arg (ap, char*);
case 'p':
/* Pointer, general format is 0xABCD.
- * %hhp --> zero-page pointer
- * %hp --> near pointer
- * %lp --> far pointer
- */
+ ** %hhp --> zero-page pointer
+ ** %hp --> near pointer
+ ** %lp --> far pointer
+ */
SkipWhite ();
if (CHAR (C) != '0') {
goto NoConv;
case 'n':
/* Store the number of characters consumed so far
- * (the read-ahead character hasn't been consumed).
- */
+ ** (the read-ahead character hasn't been consumed).
+ */
IntVal = (long) (CharCount - (C == EOF ? 0u : 1u));
AssignInt ();
/* Don't count it. */
NoConv:
/* Coming here means a failure. If that happens at EOF, with no
- * conversion attempts, then it is considered an error; otherwise,
- * the number of assignments is returned (the default behaviour).
- */
+ ** conversion attempts, then it is considered an error; otherwise,
+ ** the number of assignments is returned (the default behaviour).
+ */
if (C == EOF && Converted == false) {
Assignments = EOF; /* Special case: error */
}
/*
- * _scanf.h
- *
- * (c) Copyright 2004, Ullrich von Bassewitz <uz@cc65.org>
- *
- */
+** _scanf.h
+**
+** (c) Copyright 2004, Ullrich von Bassewitz <uz@cc65.org>
+**
+*/
/* Type of the function that is called to input data. The function will
- * return EOF if no more data is available.
- */
+** return EOF if no more data is available.
+*/
typedef int __fastcall__ (*getfunc) (void* data);
/* Type of the function that is called to put back unused data */
/* Control structure passed to the low level worker function.
- * Beware: This structure is mirrored in the _scanf.inc assembler include
- * file, so check this when altering the structure.
- */
+** Beware: This structure is mirrored in the _scanf.inc assembler include
+** file, so check this when altering the structure.
+*/
struct scanfdata {
getfunc get; /* Pointer to input routine */
ungetfunc unget; /* Pointer to pushback routine */
/*
- * abort.c
- *
- * Ullrich von Bassewitz, 02.06.1998
- */
+** abort.c
+**
+** Ullrich von Bassewitz, 02.06.1998
+*/
/*
- * bsearch.c
- *
- * Ullrich von Bassewitz, 17.06.1998
- */
+** bsearch.c
+**
+** Ullrich von Bassewitz, 17.06.1998
+*/
last = current - 1;
if (result == 0) {
/* Found one entry that matches the search key. However there may be
- * more than one entry with the same key value and ANSI guarantees
- * that we return the first of a row of items with the same key.
- */
+ ** more than one entry with the same key value and ANSI guarantees
+ ** that we return the first of a row of items with the same key.
+ */
found = 1;
}
}
; ----------------------------------------------------------------------------
; int __fastcall__ _directerrno (unsigned char code);
; /* Set errno to a specific error code, clear _oserror and return -1. Used
-; * by the library.
-; */
+; ** by the library.
+; */
__directerrno:
jsr __seterrno ; Set errno, returns with A = 0
; ----------------------------------------------------------------------------
; int __fastcall__ _mappederrno (unsigned char code);
; /* Set _oserror to the given platform specific error code. If it is a real
-; * error code (not zero) set errno to the corresponding system error code
-; * and return -1. Otherwise return zero.
-; * Used by the library.
-; */
+; ** error code (not zero) set errno to the corresponding system error code
+; ** and return -1. Otherwise return zero.
+; ** Used by the library.
+; */
__mappederrno:
sta __oserror ; Store the error code
/*
- * errormsg.c
- *
- * Ullrich von Bassewitz, 17.05.2000
- *
- * Must be a C function, since we have otherwise problems with the different
- * character sets.
- */
+** errormsg.c
+**
+** Ullrich von Bassewitz, 17.05.2000
+*/
/*
- * fdopen.c
- *
- * Ullrich von Bassewitz, 17.06.1998
- */
+** fdopen.c
+**
+** Ullrich von Bassewitz, 17.06.1998
+*/
/*
- * fgetc.c
- *
- * (C) Copyright 1998, 2002 Ullrich von Bassewitz (uz@cc65.org)
- *
- */
+** fgetc.c
+**
+** (C) Copyright 1998, 2002 Ullrich von Bassewitz (uz@cc65.org)
+**
+*/
/*
- * fgetpos.c
- *
- * Christian Groessler, 07-Aug-2000
- */
+** fgetpos.c
+**
+** Christian Groessler, 07-Aug-2000
+*/
/*
- * Ullrich von Bassewitz, 11.08.1998
- *
- * char* fgets (char* s, int size, FILE* f);
- */
+** Ullrich von Bassewitz, 11.08.1998
+**
+** char* fgets (char* s, int size, FILE* f);
+*/
/*
- * fputc.c
- *
- * Ullrich von Bassewitz, 02.06.1998
- */
+** fputc.c
+**
+** Ullrich von Bassewitz, 02.06.1998
+*/
/*
- * int fputs (const char* s, FILE* f);
- *
- * Ullrich von Bassewitz, 11.08.1998
- */
+** int fputs (const char* s, FILE* f);
+**
+** Ullrich von Bassewitz, 11.08.1998
+*/
;
; void free (void* block)
; /* Release an allocated memory block. The function will accept NULL pointers
-; * (and do nothing in this case).
-; */
+; ** (and do nothing in this case).
+; */
; {
; unsigned* b;
; unsigned size;
; _hptr = (unsigned*) (((int) _hptr) - size);
;
; /* Check if the last block in the freelist is now at heap top. If so,
-; * remove this block from the freelist.
-; */
+; ** remove this block from the freelist.
+; */
; if (f = _hlast) {
; if (((int) f) + f->size == (int) _hptr) {
; /* Remove the last block */
;
; void _hadd (void* mem, size_t size)
; /* Add an arbitrary memory block to the heap. This function is used by
-; * free(), but it does also allow usage of otherwise unused memory
-; * blocks as heap space. The given block is entered in the free list
-; * without any checks, so beware!
-; */
+; ** free(), but it does also allow usage of otherwise unused memory
+; ** blocks as heap space. The given block is entered in the free list
+; ** without any checks, so beware!
+; */
; {
; struct freeblock* f;
; struct freeblock* left;
; } else {
;
; /* We have to search the free list. As we are doing so, we check
-; * if it is possible to combine this block with another already
-; * existing block. Beware: The block may be the "missing link"
-; * between *two* other blocks.
-; */
+; ** if it is possible to combine this block with another already
+; ** existing block. Beware: The block may be the "missing link"
+; ** between *two* other blocks.
+; */
; left = 0;
; right = _hfirst;
; while (right && f > right) {
; }
;
;
-; /* Ok, the current block must be inserted between left and right (but
-; * beware: one of the two may be zero!). Also check for the condition
-; * that we have to merge two or three blocks.
-; */
+; /* OK, the current block must be inserted between left and right (but
+; ** beware: one of the two may be zero!). Also check for the condition
+; ** that we have to merge two or three blocks.
+; */
; if (right) {
; /* Check if we must merge the block with the right one */
; if (((unsigned) f) + size == (unsigned) right) {
/*
- * freopen.c
- *
- * Ullrich von Bassewitz, 17.06.1998
- */
+** freopen.c
+**
+** Ullrich von Bassewitz, 17.06.1998
+*/
}
/* Close the file. Don't bother setting the flag, it will get
- * overwritten by _fopen.
- */
+ ** overwritten by _fopen.
+ */
if (close (f->f_fd) < 0) {
/* An error occured, errno is already set */
return 0;
; va_start (ap, format);
;
; /* Call vfscanf(). Since we know that va_end won't do anything, we will
-; * save the call and return the value directly.
-; */
+; ** save the call and return the value directly.
+; */
; return vfscanf (f, format, ap);
; }
;
/*
- * fseek.c
- *
- * Christian Groessler, 2000-08-07
- * Ullrich von Bassewitz, 2004-05-12
- */
+** fseek.c
+**
+** Christian Groessler, 2000-08-07
+** Ullrich von Bassewitz, 2004-05-12
+*/
}
/* If we have a pushed back character, and whence is relative to the
- * current position, correct the offset.
- */
+ ** current position, correct the offset.
+ */
if ((f->f_flags & _FPUSHBACK) && whence == SEEK_CUR) {
--offset;
}
res = lseek(f->f_fd, offset, whence);
/* If the seek was successful. Discard any effects of the ungetc function,
- * and clear the end-of-file indicator. Otherwise set the error indicator
- * on the stream, and return -1. We will check for >= 0 here, because that
- * saves some code, and we don't have files with 2 gigabytes in size
- * anyway:-)
- */
+ ** and clear the end-of-file indicator. Otherwise set the error indicator
+ ** on the stream, and return -1. We will check for >= 0 here, because that
+ ** saves some code, and we don't have files with 2 gigabytes in size
+ ** anyway:-)
+ */
if (res >= 0) {
f->f_flags &= ~(_FEOF | _FPUSHBACK);
return 0;
/*
- * fsetpos.c
- *
- * Christian Groessler, 07-Aug-2000
- */
+** fsetpos.c
+**
+** Christian Groessler, 07-Aug-2000
+*/
/*
- * ftell.c
- *
- * Christian Groessler, 2000-08-07
- * Ullrich von Bassewitz, 2004-05-13
- */
+** ftell.c
+**
+** Christian Groessler, 2000-08-07
+** Ullrich von Bassewitz, 2004-05-13
+*/
pos = lseek (f->f_fd, 0L, SEEK_CUR);
/* If we didn't have an error, correct the return value in case we have
- * a pushed back character.
- */
+ ** a pushed back character.
+ */
if (pos > 0 && (f->f_flags & _FPUSHBACK)) {
--pos;
}
/*
- * getchar.c
- *
- * Ullrich von Bassewitz, 11.12.1998
- */
+** getchar.c
+**
+** Ullrich von Bassewitz, 11.12.1998
+*/
/*
- * This is part of a changed public domain getopt implementation that
- * had the following text on top:
- *
- * I got this off net.sources from Henry Spencer.
- * It is a public domain getopt(3) like in System V.
- * I have made the following modifications:
- *
- * A test main program was added, ifdeffed by GETOPT.
- * This main program is a public domain implementation
- * of the getopt(1) program like in System V. The getopt
- * program can be used to standardize shell option handling.
- * e.g. cc -DGETOPT getopt.c -o getopt
- */
+** This is part of a changed public domain getopt implementation that
+** had the following text on top:
+**
+** I got this off net.sources from Henry Spencer.
+** It is a public domain getopt(3) like in System V.
+** I have made the following modifications:
+**
+** A test main program was added, ifdeffed by GETOPT.
+** This main program is a public domain implementation
+** of the getopt(1) program like in System V. The getopt
+** program can be used to standardize shell option handling.
+** e.g. cc -DGETOPT getopt.c -o getopt
+*/
#include <stdio.h>
#include <stdlib.h>
/*
- * gets.c
- *
- * Ullrich von Bassewitz, 11.08.1998
- */
+** gets.c
+**
+** Ullrich von Bassewitz, 11.08.1998
+*/
/*
- * locale.c
- *
- * Ullrich von Bassewitz, 11.12.1998
- */
+** locale.c
+**
+** Ullrich von Bassewitz, 11.12.1998
+*/
}
/* Since our ints are just 16 bits, split the given time into seconds,
- * hours and days. Each of the values will fit in a 16 bit variable.
- * The mktime routine will then do the rest.
- */
+ ** hours and days. Each of the values will fit in a 16 bit variable.
+ ** The mktime routine will then do the rest.
+ */
timebuf.tm_sec = t % 3600;
timebuf.tm_min = 0;
timebuf.tm_hour = (t / 3600) % 24;
;
; void* malloc (size_t size)
; /* Allocate memory from the given heap. The function returns a pointer to the
-; * allocated memory block or a NULL pointer if not enough memory is available.
-; * Allocating a zero size block is not allowed.
-; */
+; ** allocated memory block or a NULL pointer if not enough memory is available.
+; ** Allocating a zero size block is not allowed.
+; */
; {
; struct freeblock* f;
; unsigned* p;
;
;
; /* Check for a size of zero, then add the administration space and round
-; * up the size if needed.
-; */
+; ** up the size if needed.
+; */
; if (size == 0) {
; return 0;
; }
; if (f) {
;
; /* We found a block big enough. If the block can hold just the
-; * requested size, use the block in full. Beware: When slicing blocks,
-; * there must be space enough to create a new one! If this is not the
-; * case, then use the complete block.
-; */
+; ** requested size, use the block in full. Beware: When slicing blocks,
+; ** there must be space enough to create a new one! If this is not the
+; ** case, then use the complete block.
+; */
; if (f->size - size < sizeof (struct freeblock)) {
;
; /* Use the actual size */
;
; } else {
;
-; /* We must slice the block found. Cut off space from the upper
-; * end, so we can leave the actual free block chain intact.
-; */
+; /* We must slice the block found. Cut off space from the upper
+; ** end, so we can leave the actual free block chain intact.
+; */
;
; /* Decrement the size of the block */
; f->size -= size;
; } else {
;
; /* We did not find a block big enough. Try to use new space from the
-; * heap top.
-; */
+; ** heap top.
+; */
; if (((unsigned) _hend) - ((unsigned) _hptr) < size) {
; /* Out of heap space */
; return 0;
time_t __fastcall__ mktime (register struct tm* TM)
/* Make a time in seconds since 1/1/1970 from the broken down time in TM.
- * A call to mktime does also correct the time in TM to contain correct
- * values.
- */
+** A call to mktime does also correct the time in TM to contain correct
+** values.
+*/
{
register div_t D;
int Max;
TM->tm_mday += D.quot;
/* Adjust month and year. This is an iterative process, since changing
- * the month will change the allowed days for this month.
- */
+ ** the month will change the allowed days for this month.
+ */
while (1) {
/* Make sure, month is in the range 0..11 */
TM->tm_year += D.quot;
/* Now check if mday is in the correct range, if not, correct month
- * and eventually year and repeat the process.
- */
+ ** and eventually year and repeat the process.
+ */
if (TM->tm_mon == FEBRUARY && IsLeapYear (TM->tm_year + 1900)) {
Max = 29;
} else {
}
/* Ok, all time/date fields are now correct. Calculate the days in this
- * year.
- */
+ ** year.
+ */
TM->tm_yday = MonthDays[TM->tm_mon] + TM->tm_mday - 1;
if (TM->tm_mon > FEBRUARY && IsLeapYear (TM->tm_year + 1900)) {
++TM->tm_yday;
}
/* Calculate days since 1/1/1970. In the complete epoch (1/1/1970 to
- * somewhere in 2038) all years dividable by 4 are leap years, so
- * dividing by 4 gives the days that must be added cause of leap years.
- * (and the last leap year before 1970 was 1968)
- */
+ ** somewhere in 2038) all years dividable by 4 are leap years, so
+ ** dividing by 4 gives the days that must be added cause of leap years.
+ ** (and the last leap year before 1970 was 1968)
+ */
DayCount = ((unsigned) (TM->tm_year-70)) * 365U +
(((unsigned) (TM->tm_year-(68+1))) / 4) +
TM->tm_yday;
/* */
/* */
/* (C) 2004-2005 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* This is a very simple version of an aligned memory allocator. We will
- * allocate a greater block, so that we can place the aligned block (that is
- * returned) within it. We use our knowledge about the internal heap
- * structures to free the unused parts of the bigger block (the two chunks
- * below and above the aligned block).
- */
+** allocate a greater block, so that we can place the aligned block (that is
+** returned) within it. We use our knowledge about the internal heap
+** structures to free the unused parts of the bigger block (the two chunks
+** below and above the aligned block).
+*/
int __fastcall__ posix_memalign (void** memptr, size_t alignment, size_t size)
/* Allocate a block of memory with the given "size", which is aligned to a
- * memory address that is a multiple of "alignment". "alignment" MUST NOT be
- * zero, and MUST be a power of two; otherwise, this function will return
- * EINVAL. The function returns ENOMEM if not enough memory is available
- * to satisfy the request. "memptr" must point to a variable; that variable
- * will return the address of the allocated memory. Use free() to release that
- * allocated block.
- */
+** memory address that is a multiple of "alignment". "alignment" MUST NOT be
+** zero, and MUST be a power of two; otherwise, this function will return
+** EINVAL. The function returns ENOMEM if not enough memory is available
+** to satisfy the request. "memptr" must point to a variable; that variable
+** will return the address of the allocated memory. Use free() to release that
+** allocated block.
+*/
{
size_t rawsize;
size_t uppersize;
}
/* Augment the block size up to the alignment, and allocate memory.
- * We don't need to account for the additional admin. data that's needed to
- * manage the used block, because the block returned by malloc() has that
- * overhead added one time; and, the worst thing that might happen is that
- * we cannot free the upper and lower blocks.
- */
+ ** We don't need to account for the additional admin. data that's needed to
+ ** manage the used block, because the block returned by malloc() has that
+ ** overhead added one time; and, the worst thing that might happen is that
+ ** we cannot free the upper and lower blocks.
+ */
b = malloc (size + alignment);
/* Handle out-of-memory */
}
/* Create (and return) a new pointer that points to the user-visible
- * aligned block.
- */
+ ** aligned block.
+ */
u = *memptr = (struct usedblock*) (((unsigned)b + alignment) & ~alignment);
/* Get a pointer to the (raw) upper block */
p = (struct usedblock*) ((char*)u + size);
/* Get the raw-block pointer, which is located just below the visible
- * unaligned block. The first word of this raw block is the total size
- * of the block, including the admin. space.
- */
+ ** unaligned block. The first word of this raw block is the total size
+ ** of the block, including the admin. space.
+ */
b = (b-1)->start;
rawsize = b->size;
/* Check if we can free the space above the user block. That is the case
- * if the size of the block is at least sizeof (struct freeblock) bytes,
- * and the size of the remaining block is at least that size, too.
- * If the upper block is smaller, then we just will pass it to the caller,
- * together with the requested aligned block.
- */
+ ** if the size of the block is at least sizeof (struct freeblock) bytes,
+ ** and the size of the remaining block is at least that size, too.
+ ** If the upper block is smaller, then we just will pass it to the caller,
+ ** together with the requested aligned block.
+ */
uppersize = rawsize - (lowersize = (char*)p - (char*)b);
if (uppersize >= sizeof (struct freeblock) &&
lowersize >= sizeof (struct freeblock)) {
}
/* Check if we can free the space below the user block. That is the case
- * if the size of the block is at least sizeof (struct freeblock) bytes,
- * and the size of the remaining block is at least that size, too. If the
- * lower block is smaller, we just will pass it to the caller, together
- * with the requested aligned block.
- * Beware: We need an additional struct usedblock, in the lower block,
- * which is part of the block that is passed back to the caller.
- */
+ ** if the size of the block is at least sizeof (struct freeblock) bytes,
+ ** and the size of the remaining block is at least that size, too. If the
+ ** lower block is smaller, we just will pass it to the caller, together
+ ** with the requested aligned block.
+ ** Beware: We need an additional struct usedblock, in the lower block,
+ ** which is part of the block that is passed back to the caller.
+ */
lowersize = ((char*)u - (char*)b) - sizeof (struct usedblock);
if ( lowersize >= sizeof (struct freeblock) &&
(rawsize - lowersize) >= sizeof (struct freeblock)) {
/* b already points to the raw lower-block.
- * Set up the usedblock structure.
- */
+ ** Set up the usedblock structure.
+ */
b->size = lowersize;
b->start = b;
}
/* u points to the user-visible block, while b points to the raw block,
- * and rawsize contains the length of the raw block. Set up the usedblock
- * structure, but beware: If we didn't free the lower block, then it is
- * split; which means that we must use b to write the size,
- * and u to write the start field.
- */
+ ** and rawsize contains the length of the raw block. Set up the usedblock
+ ** structure, but beware: If we didn't free the lower block, then it is
+ ** split; which means that we must use b to write the size,
+ ** and u to write the start field.
+ */
b->size = rawsize;
(u-1)->start = b;
/*
- * puts.c
- *
- * Ullrich von Bassewitz, 11.08.1998
- */
+** puts.c
+**
+** Ullrich von Bassewitz, 11.08.1998
+*/
/*
- * qsort.c
- *
- * Ullrich von Bassewitz, 09.12.1998
- */
+** qsort.c
+**
+** Ullrich von Bassewitz, 09.12.1998
+*/
register size_t Size,
int (*Compare)(const void*, const void*))
/* Internal recursive function. Works with ints, but this shouldn't be
- * a problem.
- */
+** a problem.
+*/
{
int I, J;
-
-
}
/* The word below the user block contains a pointer to the start of the
- * raw memory block. The first word of this raw memory block is the full
- * size of the block. Get a pointer to the real block, get the old block
- * size.
- */
+ ** raw memory block. The first word of this raw memory block is the full
+ ** size of the block. Get a pointer to the real block, get the old block
+ ** size.
+ */
b = (((struct usedblock*) block) - 1)->start;
oldsize = b->size;
}
/* The given block was not located on top of the heap, or there's no
- * room left. Try to allocate a new block and copy the data.
- */
+ ** room left. Try to allocate a new block and copy the data.
+ */
if (newblock = malloc (size)) {
/* Adjust the old size to the user visible portion */
oldsize -= HEAP_ADMIN_SPACE;
/* If the new block is larger than the old one, copy the old
- * data only
- */
+ ** data only
+ */
if (size > oldsize) {
size = oldsize;
}
-
/*
- * rewind.c
- *
- * Christian Groessler, 07-Aug-2000
- */
+** rewind.c
+**
+** Christian Groessler, 07-Aug-2000
+*/
/*
- * sleep.c
- *
- * Stefan Haubenthal, 2003-06-11
- * Ullrich von Bassewitz, 2003-06-12
- *
- */
+** sleep.c
+**
+** Stefan Haubenthal, 2003-06-11
+** Ullrich von Bassewitz, 2003-06-12
+**
+*/
; va_start (ap, format);
;
; /* Call vsscanf(). Since we know that va_end won't do anything, we will
-; * save the call and return the value directly.
-; */
+; ** save the call and return the value directly.
+; */
; return vsscanf (str, format, ap);
; }
;
/*
- * strqtok() is like strtok(): It finds pieces of text, in a string, that are
- * surrounded by given delimiter characters. It returns each piece, in turn,
- * as a string, until every piece has been found. Then, it returns NULL. But,
- * strqtok() recognizes quotation marks. A mark makes delimiters look ordinary
- * until another quotation mark is seen. That allows us to include delimiters
- * in tokens. (This version doesn't allow escaped quotation marks.)
- *
- * 2014-04-19, Daniel Serpell
- * 2014-04-21, Paul Foerster
- * 2014-04-25, Greg King
- */
+** strqtok() is like strtok(): It finds pieces of text, in a string, that are
+** surrounded by given delimiter characters. It returns each piece, in turn,
+** as a string, until every piece has been found. Then, it returns NULL. But,
+** strqtok() recognizes quotation marks. A mark makes delimiters look ordinary
+** until another quotation mark is seen. That allows us to include delimiters
+** in tokens. (This version doesn't allow escaped quotation marks.)
+**
+** 2014-04-19, Daniel Serpell
+** 2014-04-21, Paul Foerster
+** 2014-04-25, Greg King
+*/
#include <string.h>
}
if (c == '\0') {
/* The end of the last token is the end of the token list;
- * don't go beyond it.
- */
+ ** don't go beyond it.
+ */
goto found;
}
/* Search for the end of a quoted token. */
if ((s1 = strchr (s1, '\"')) == NULL) {
/* The quoted token ended with '\0'; therefore, point to a '\0',
- * so that the next call will return NULL.
- */
+ ** so that the next call will return NULL.
+ */
next = "";
return start;
}
/*
- * strtok.c
- *
- * Ullrich von Bassewitz, 11.12.1998
- */
+** strtok.c
+**
+** Ullrich von Bassewitz, 11.12.1998
+*/
}
/* Search the address of the first element in s1 that equals none
- * of the characters in s2.
- */
+ ** of the characters in s2.
+ */
while ((c = *s1) && strchr (s2, c) != 0) {
++s1;
}
}
/* If base is zero, we may have a 0 or 0x prefix. If base is 16, we may
- * have a 0x prefix.
- */
+ ** have a 0x prefix.
+ */
if (base == 0) {
if (*S == '0') {
++S;
}
/* Determine the maximum valid number and (if the number is equal to this
- * value) the maximum valid digit.
- */
+ ** value) the maximum valid digit.
+ */
if (Minus) {
MaxVal = LONG_MIN;
} else {
}
/* Store the end pointer. If no conversion was performed, the value of
- * nptr is returned in endptr.
- */
+ ** nptr is returned in endptr.
+ */
if (endptr) {
if (CvtCount > 0) {
*endptr = (char*) S;
}
/* If base is zero, we may have a 0 or 0x prefix. If base is 16, we may
- * have a 0x prefix.
- */
+ ** have a 0x prefix.
+ */
if (base == 0) {
if (*S == '0') {
++S;
}
/* Determine the maximum valid number and (if the number is equal to this
- * value) the maximum valid digit.
- */
+ ** value) the maximum valid digit.
+ */
MaxDigit = ULONG_MAX % base;
MaxVal = ULONG_MAX / base;
}
/* Store the end pointer. If no conversion was performed, the value of
- * nptr is returned in endptr.
- */
+ ** nptr is returned in endptr.
+ */
if (endptr) {
if (CvtCount > 0) {
*endptr = (char*) S;
/*
- * strxfrm.c
- *
- * Ullrich von Bassewitz, 11.12.1998
- */
+** strxfrm.c
+**
+** Ullrich von Bassewitz, 11.12.1998
+*/
/*
- * system.c
- *
- * Stefan Haubenthal, 2003-05-26
- * Ullrich von Bassewitz, 2003-05-27
- */
+** system.c
+**
+** Stefan Haubenthal, 2003-05-26
+** Ullrich von Bassewitz, 2003-05-27
+*/
#include <stdio.h>
#include <stdlib.h>
; /* Standard C function */
; {
; /* Initialize the data struct. We do only need the given file as user data,
-; * because the (getfunc) and (ungetfunc) functions are crafted so that they
-; * match the standard-I/O fgetc() and ungetc().
-; */
+; ** because the (getfunc) and (ungetfunc) functions are crafted so that they
+; ** match the standard-I/O fgetc() and ungetc().
+; */
; static struct scanfdata d = {
; ( getfunc) fgetc,
; (ungetfunc) ungetc
; /* Push back a character onto the input stream */
; {
; /* We do assume here that the _scanf routine will not push back anything
-; * not read, so we can ignore c safely and won't check the index.
-; */
+; ** not read, so we can ignore c safely and won't check the index.
+; */
; --d->index;
; return c;
; }
; /* Standard C function */
; {
; /* Initialize the data structs. The sscanfdata struct will be passed back
-; * to the get and unget functions by _scanf().
-; */
+; ** to the get and unget functions by _scanf().
+; */
; static struct sscanfdata sd;
; static const struct scanfdata d = {
; ( getfunc) get,
/*
- * dbg.c
- *
- * Ullrich von Bassewitz, 08.08.1998
- *
- */
+** dbg.c
+**
+** Ullrich von Bassewitz, 08.08.1998
+**
+*/
BreakPoint* DbgIsBreak (unsigned Addr);
/* Check if there is a user breakpoint at the given address, if so, return
- * a pointer to the slot, else return 0.
- */
+** a pointer to the slot, else return 0.
+*/
static unsigned char DbgTmpBreaksOk (void)
/* Check if the temporary breakpoints can be set, if so, return 1, if not,
- * reset them all and return 0.
- */
+** reset them all and return 0.
+*/
{
unsigned char i;
BreakPoint* B = DbgBreaks;
static unsigned AsmBack (unsigned mem, unsigned char lines)
/* Go back in the assembler window the given number of lines (calculate
- * new start address).
- */
+** new start address).
+*/
{
unsigned cur;
unsigned adr [32];
return adr [(in - lines - 1) & 0x1F];
} else {
/* The requested address is inside an instruction, go back
- * one more byte and try again.
- */
+ ** one more byte and try again.
+ */
++offs;
break;
}
case OPC_BNE:
case OPC_BEQ:
/* Be sure not to set the breakpoint twice if this is a jump to
- * the following instruction.
- */
+ ** the following instruction.
+ */
Offs = ((signed char*)brk_pc)[1];
if (Offs) {
DbgSetTmpBreak (brk_pc + Offs + 2);
}
/* Only initialize variables here, don't do a display update. The actual
- * display update will be done while waiting for user input.
- */
+ ** display update will be done while waiting for user input.
+ */
AsmHome ();
UpdateReg (); /* Must update this (static later) */
StackHome ();
;----------------------------------------------------------------------------
; unsigned char em_uninstall (void);
; /* Uninstall the currently loaded driver and return an error code.
-; * Note: This call does not free allocated memory.
-; */
+; ** Note: This call does not free allocated memory.
+; */
_em_uninstall:
jsr emd_uninstall ; Call driver routine
;
; void em_commit (void);
; /* Commit changes in the memory window to extended storage. If the contents
-; * of the memory window have been changed, these changes may be lost if
-; * em_map, em_copyfrom or em_copyto are called without calling em_commit
-; * first. Note: Not calling em_commit does not mean that the changes are
-; * discarded, it does just mean that some drivers will discard the changes.
-; */
+; ** of the memory window have been changed, these changes may be lost if
+; ** em_map, em_copyfrom or em_copyto are called without calling em_commit
+; ** first. Note: Not calling em_commit does not mean that the changes are
+; ** discarded, it does just mean that some drivers will discard the changes.
+; */
.include "em-kernel.inc"
;
; void* __fastcall__ em_map (unsigned page);
; /* Unmap the current page from memory and map a new one. The function returns
-; * a pointer to the location of the page in memory.
-; */
+; ** a pointer to the location of the page in memory.
+; */
.include "em-kernel.inc"
;
; void* __fastcall__ em_use (unsigned page);
; /* Tell the driver that the memory window is associated with a given page.
-; * This call is very similar to em_map. The difference is that the driver
-; * does not necessarily transfer the current contents of the extended
-; * memory into the returned window. If you're going to just write to the
-; * window and the current contents of the window are invalid or no longer
-; * use, this call may perform better than em_map.
-; */
+; ** This call is very similar to em_map. The difference is that the driver
+; ** does not necessarily transfer the current contents of the extended
+; ** memory into the returned window. If you're going to just write to the
+; ** window and the current contents of the window are invalid or no longer
+; ** use, this call may perform better than em_map.
+; */
.include "em-kernel.inc"
/*
- * _afailed.c
- *
- * Maciej 'YTM/Elysium' Witkowiak 28.10.2001
- */
+** _afailed.c
+**
+** Maciej 'YTM/Elysium' Witkowiak 28.10.2001
+*/
#include <stdio.h>
#include <stdlib.h>
/*
- * _poserror.c
- *
- * Maciej 'YTM/Elysium' Witkowiak, 25.04.2003
- */
+** _poserror.c
+**
+** Maciej 'YTM/Elysium' Witkowiak, 25.04.2003
+*/
#include <stdio.h>
#include <string.h>
/*
- * abort.c
- *
- * Maciej 'YTM/Elysium' Witkowiak 15.7.2001
- */
+** abort.c
+**
+** Maciej 'YTM/Elysium' Witkowiak 15.7.2001
+*/
#include <stdlib.h>
#include <geos.h>
/*
- * perror.c
- *
- * Maciej 'YTM/Elysium' Witkowiak, 15.07.2001
- */
+** perror.c
+**
+** Maciej 'YTM/Elysium' Witkowiak, 15.07.2001
+*/
#include <stdio.h>
#include <string.h>
/*
- * sleep.c
- *
- * Maciej 'YTM/Elysium' Witkowiak, 16.08.2003
- *
- */
+** sleep.c
+**
+** Maciej 'YTM/Elysium' Witkowiak, 16.08.2003
+**
+*/
#include <geos.h>
-
/*
- * char MessageBox (char mode, const char *format, ...)
- *
- * Maciej 'YTM/Elysium' Witkowiak, 17.08.2003
- *
- */
+** char MessageBox (char mode, const char *format, ...)
+**
+** Maciej 'YTM/Elysium' Witkowiak, 17.08.2003
+**
+*/
#include <geos.h>
#include <stdio.h>
/*
- * systime.c
- *
- * Maciej 'YTM/Elysium' Witkowiak, 22.11.2002
- */
+** systime.c
+**
+** Maciej 'YTM/Elysium' Witkowiak, 22.11.2002
+*/
#include <time.h>
#include <geos.h>
;----------------------------------------------------------------------------
; unsigned char joy_uninstall (void);
; /* Uninstall the currently loaded driver. Note: This call does not free
-; * allocated memory.
-; */
+; ** allocated memory.
+; */
_joy_uninstall:
lda #$60 ; RTS opcode
;
; unsigned char mouse_buttons (void);
; /* Return a bit mask encoding the states of the mouse buttons. Use the
-; * MOUSE_BTN_XXX flags to decode a specific button.
-; */
+; ** MOUSE_BTN_XXX flags to decode a specific button.
+; */
;
.include "mouse-kernel.inc"
;
; void mouse_hide (void);
; /* Hide the mouse. The function manages a counter and may be called more than
-; * once. For each call to mouse_hide there must be a call to mouse_show to make
-; * the mouse visible again.
-; */
+; ** once. For each call to mouse_hide there must be a call to mouse_show to make
+; ** the mouse visible again.
+; */
;
.include "mouse-kernel.inc"
;
; unsigned char __fastcall__ mouse_ioctl (unsigned char code, void* data);
; /* Call the driver specific ioctl function. NON PORTABLE! Returns an error
-; * code.
-; */
+; ** code.
+; */
;
.import popa
;
; void __fastcall__ mouse_move (int x, int y);
; /* Set the mouse cursor to the given position. If a mouse cursor is defined
-; * and currently visible, the mouse cursor is also moved.
-; * NOTE: This function does not check if the given position is valid and
-; * inside the bounding box.
-; */
+; ** and currently visible, the mouse cursor is also moved.
+; ** NOTE: This function does not check if the given position is valid and
+; ** inside the bounding box.
+; */
;
.import incsp2
;
; void __fastcall__ mouse_setbox (const struct mouse_box* box);
; /* Set the bounding box for the mouse pointer movement. The mouse X and Y
-; * coordinates will never go outside the given box.
-; * NOTE: The function does *not* check if the mouse is currently inside the
-; * given margins. The proper way to use this function therefore is:
-; *
-; * - Hide the mouse
-; * - Set the bounding box
-; * - Place the mouse at the desired position
-; * - Show the mouse again.
-; *
-; * NOTE2: When setting the box to something that is larger than the actual
-; * screen, the positioning of the mouse cursor can fail. If such margins
-; * are really what you want, you have to use your own cursor routines.
-; */
+; ** coordinates will never go outside the given box.
+; ** NOTE: The function does *not* check if the mouse is currently inside the
+; ** given margins. The proper way to use this function therefore is:
+; **
+; ** - Hide the mouse
+; ** - Set the bounding box
+; ** - Place the mouse at the desired position
+; ** - Show the mouse again.
+; **
+; ** NOTE2: When setting the box to something that is larger than the actual
+; ** screen, the positioning of the mouse cursor can fail. If such margins
+; ** are really what you want, you have to use your own cursor routines.
+; */
;
;
;
; time_t _systime (void);
; /* Similar to time(), but:
-; * - Is not ISO C
-; * - Does not take the additional pointer
-; * - Does not set errno when returning -1
-; */
+; ** - Is not ISO C
+; ** - Does not take the additional pointer
+; ** - Does not set errno when returning -1
+; */
;
.export __systime
;----------------------------------------------------------------------------
; unsigned char ser_uninstall (void);
; /* Uninstall the currently loaded driver and return an error code.
-; * Note: This call does not free allocated memory.
-; */
+; ** Note: This call does not free allocated memory.
+; */
_ser_uninstall:
jsr ser_uninstall ; Call driver routine
;
; unsigned char __fastcall__ ser_get (char* b);
; /* Get a character from the serial port. If no characters are available, the
-; * function will return SER_ERR_NO_DATA, so this is not a fatal error.
-; */
+; ** function will return SER_ERR_NO_DATA, so this is not a fatal error.
+; */
.importzp ptr1
;
; unsigned char __fastcall__ ser_put (char b);
; /* Send a character via the serial port. There is a transmit buffer, but
-; * transmitting is not done via interrupt. The function returns
-; * SER_ERR_OVERFLOW if there is no space left in the transmit buffer.
-; */
+; ** transmitting is not done via interrupt. The function returns
+; ** SER_ERR_OVERFLOW if there is no space left in the transmit buffer.
+; */
.include "ser-kernel.inc"
;----------------------------------------------------------------------------
; void tgi_uninstall (void);
; /* Uninstall the currently loaded driver but do not unload it. Will call
-; * tgi_done if necessary.
-; */
+; ** tgi_done if necessary.
+; */
_tgi_uninstall:
jsr _tgi_done ; Switch off graphics
void __fastcall__ tgi_arc (int x, int y, unsigned char rx, unsigned char ry,
unsigned sa, unsigned ea)
/* Draw an ellipse arc with center at x/y and radii rx/ry using the current
- * drawing color. The arc covers the angle between sa and ea (startangle and
- * endangle), which must be in the range 0..360 (otherwise the function may
- * bevave unextectedly).
- */
+** drawing color. The arc covers the angle between sa and ea (startangle and
+** endangle), which must be in the range 0..360 (otherwise the function may
+** bevave unextectedly).
+*/
{
int x1, y1, x2, y2;
unsigned char inc;
;
; void __fastcall__ tgi_ellipse (int x, int y, unsigned char rx, unsigned char ry);
; /* Draw a full ellipse with center at x/y and radii rx/ry using the current
-; * drawing color.
-; */
+; ** drawing color.
+; */
;
;
; unsigned tgi_getaspectratio (void);
; /* Returns the aspect ratio for the loaded driver. The aspect ratio is an
-; * 8.8 fixed point value.
-; */
+; ** 8.8 fixed point value.
+; */
;
.include "tgi-kernel.inc"
;
; const unsigned char* tgi_getdefpalette (void);
; /* Return the default palette. Will return NULL for drivers that do not
-; * support palettes.
-; */
+; ** support palettes.
+; */
;
.include "tgi-kernel.inc"
;
; unsigned char tgi_geterror (void);
; /* Return the error code for the last operation. This will also clear the
-; * error.
-; */
+; ** error.
+; */
.include "tgi-kernel.inc"
;
; unsigned char tgi_getmaxcolor (void);
; /* Return the maximum supported color number (the number of colors would
-; * then be getmaxcolor()+1).
-; */
+; ** then be getmaxcolor()+1).
+; */
;
.include "tgi-kernel.inc"
;
; unsigned tgi_getmaxx (void);
; /* Return the maximum x coordinate. The resolution in x direction is
-; * getmaxx() + 1
-; */
+; ** getmaxx() + 1
+; */
.include "tgi-kernel.inc"
;
; unsigned tgi_getmaxy (void);
; /* Return the maximum y coordinate. The resolution in y direction is
-; * getmaxy() + 1
-; */
+; ** getmaxy() + 1
+; */
.include "tgi-kernel.inc"
;
; const unsigned char* tgi_getpalette (void);
; /* Return the current palette. Will return NULL for drivers that do not
-; * support palettes.
-; */
+; ** support palettes.
+; */
;
.include "tgi-kernel.inc"
;-----------------------------------------------------------------------------
; unsigned __fastcall__ tgi_gettextheight (const char* s);
; /* Calculate the height of the text in pixels according to the current text
-; * style.
-; */
+; ** style.
+; */
;
.proc _tgi_gettextheight
;-----------------------------------------------------------------------------
; unsigned __fastcall__ tgi_gettextwidth (const char* s);
; /* Calculate the width of the text in pixels according to the current text
-; * style.
-; */
+; ** style.
+; */
;
; Result is strlen (s) * tgi_textmagw * tgi_fontsizex
;
;-----------------------------------------------------------------------------
; void __fastcall__ tgi_install_vectorfont (const tgi_vectorfont* font);
; /* Install a vector font for use. More than one vector font can be loaded,
-; * but only one can be active. This function is used to tell which one. Call
-; * with a NULL pointer to uninstall the currently installed font.
-; */
+; ** but only one can be active. This function is used to tell which one. Call
+; ** with a NULL pointer to uninstall the currently installed font.
+; */
;
.code
;
; unsigned __fastcall__ tgi_ioctl (unsigned char code, void* data);
; /* Call the driver specific control function. What this function does for
-; * a specific code depends on the driver. The driver will set an error
-; * for unknown codes or values.
-; */
+; ** a specific code depends on the driver. The driver will set an error
+; ** for unknown codes or values.
+; */
;
.include "tgi-kernel.inc"
;
; void __fastcall__ tgi_lineto (int x2, int y2);
; /* Draw a line in the current drawing color from the graphics cursor to the
-; * new end point.
-; */
+; ** new end point.
+; */
.include "tgi-kernel.inc"
const tgi_vectorfont* __fastcall__ tgi_load_vectorfont (const char* name)
/* Load a vector font into memory and return it. In case of errors, NULL is
- * returned and an error is set, which can be retrieved using tgi_geterror.
- * To use the font, it has to be installed using tgi_install_vectorfont.
- */
+** returned and an error is set, which can be retrieved using tgi_geterror.
+** To use the font, it has to be installed using tgi_install_vectorfont.
+*/
{
static const char Magic[4] = {
0x54, 0x43, 0x48, TGI_VF_VERSION
close (F);
/* Fix the offset pointers. When loaded, they contain numeric offsets
- * into the VectorOps, with the start of the VectorOps at offset zero.
- * We will add a pointer to the VectorOps to make them actual pointers
- * that may be used independently from anything else.
- */
+ ** into the VectorOps, with the start of the VectorOps at offset zero.
+ ** We will add a pointer to the VectorOps to make them actual pointers
+ ** that may be used independently from anything else.
+ */
V = (unsigned) &Font->vec_ops;
for (I = 0; I < TGI_VF_CCOUNT; ++I) {
Font->chars[I] += V;
LoadError:
/* Some sort of load problem. If the file is still open, be sure to
- * close it
- */
+ ** close it
+ */
if (F >= 0) {
close (F);
}
void __fastcall__ tgi_pieslice (int x, int y, unsigned char rx, unsigned char ry,
unsigned sa, unsigned ea)
/* Draw an ellipse pie slice with center at x/y and radii rx/ry using the
- * current drawing color. The pie slice covers the angle between sa and ea
- * (startangle and endangle), which must be in the range 0..360 (otherwise the
- * function may behave unextectedly).
- */
+** current drawing color. The pie slice covers the angle between sa and ea
+** (startangle and endangle), which must be in the range 0..360 (otherwise the
+** function may behave unexpectedly).
+*/
{
/* Draw an arc ... */
tgi_arc (x, y, rx, ry, sa, ea);
;
; void __fastcall__ tgi_setaspectratio (unsigned aspectratio);
; /* Set a new aspect ratio for the loaded driver. The aspect ratio is an
-; * 8.8 fixed point value.
-; */
+; ** 8.8 fixed point value.
+; */
;
.include "tgi-kernel.inc"
;
; void __fastcall__ tgi_setpalette (const unsigned char* palette);
; /* Set the palette (not available with all drivers/hardware). palette is
-; * a pointer to as many entries as there are colors.
-; */
+; ** a pointer to as many entries as there are colors.
+; */
;
.include "tgi-kernel.inc"
;-----------------------------------------------------------------------------
; void __fastcall__ tgi_settextdir (unsigned char dir);
; /* Set the direction for text output. dir is one of the TGI_TEXT_XXX
-; * constants.
-; */
+; ** constants.
+; */
;
.proc _tgi_settextdir
; void __fastcall__ tgi_settextstyle (unsigned width, unsigned height,
; unsigned char dir, unsigned char font);
; /* Set the style for text output. The scaling factors for width and height
-; * are 8.8 fixed point values. This means that $100 = 1 $200 = 2 etc.
-; * dir is one of the TGI_TEXT_XXX constants. font is one of the TGI_FONT_XXX
-; * constants.
-; */
+; ** are 8.8 fixed point values. This means that $100 = 1 $200 = 2 etc.
+; ** dir is one of the TGI_TEXT_XXX constants. font is one of the TGI_FONT_XXX
+; ** constants.
+; */
;
.proc _tgi_settextstyle
;-----------------------------------------------------------------------------
; void __fastcall__ tgi_settextscale (unsigned width, unsigned height);
; /* Set the scaling for text output. The scaling factors for width and height
-; * are 8.8 fixed point values. This means that $100 = 1 $200 = 2 etc.
-; */
+; ** are 8.8 fixed point values. This means that $100 = 1 $200 = 2 etc.
+; */
.proc _tgi_settextscale
;
; void __fastcall__ tgi_vectorchar (const unsigned char* Ops);
; /* Draw one character of the vector font at the current graphics cursor
-; * position using the current font magnification.
-; */
+; ** position using the current font magnification.
+; */
;
.import imul16x16r32, umul16x16r32, negax, negeax
/*
- * uncompress.c
- *
- * Piotr Fusik, 18.11.2001
- */
+** uncompress.c
+**
+** Piotr Fusik, 18.11.2001
+*/
#include <zlib.h>
/*
- * Enumerate devices, directories and files.
- *
- * 2012-10-15, Oliver Schmidt (ol.sc@web.de)
- *
- */
+** Enumerate devices, directories and files.
+**
+** 2012-10-15, Oliver Schmidt (ol.sc@web.de)
+**
+*/
if (chdir (newdir)) {
/* If chdir() fails we just print the
- * directory name - as done for files.
- */
+ ** directory name - as done for files.
+ */
printf (" Dir %s\n", newdir);
return;
}
/* We call getcwd() in order to print the
- * absolute pathname for a subdirectory.
- */
+ ** absolute pathname for a subdirectory.
+ */
getcwd (curdir, sizeof (curdir));
printf (" Dir %s:\n", curdir);
/* Calling opendir() always with "." avoids
- * fiddling around with pathname separators.
- */
+ ** fiddling around with pathname separators.
+ */
dir = opendir (".");
while (ent = readdir (dir)) {
}
/* We defer handling of subdirectories until we're done with the
- * current one as several targets don't support other disk i/o
- * while reading a directory (see cc65 readdir() doc for more).
- */
+ ** current one as several targets don't support other disk i/o
+ ** while reading a directory (see cc65 readdir() doc for more).
+ */
if (_DE_ISDIR (ent->d_type)) {
subdirs = realloc (subdirs, FILENAME_MAX * (dirnum + 1));
strcpy (subdirs + FILENAME_MAX * dirnum++, ent->d_name);
char devicedir[FILENAME_MAX];
/* Calling getfirstdevice()/getnextdevice() does _not_ turn on the motor
- * of a drive-type device and does _not_ check for a disk in the drive.
- */
+ ** of a drive-type device and does _not_ check for a disk in the drive.
+ */
device = getfirstdevice ();
while (device != INVALID_DEVICE) {
printf ("Device %d:\n", device);
/* Calling getdevicedir() _does_ check for a (formatted) disk in a
- * floppy-disk-type device and returns NULL if that check fails.
- */
+ ** floppy-disk-type device and returns NULL if that check fails.
+ */
if (getdevicedir (device, devicedir, sizeof (devicedir))) {
printdir (devicedir);
} else {
-/*****************************************************************************
- * fire test program for cc65. *
- * *
- * (w)2002 by groepaz/hitmen *
- * *
- * Cleanup and porting by Ullrich von Bassewitz. *
- * 2004-06-08, Greg King *
- * *
- *****************************************************************************/
+/*****************************************************************************\
+** fire test program for cc65. **
+** **
+** (w)2002 by groepaz/hitmen **
+** **
+** Cleanup and porting by Ullrich von Bassewitz. **
+** 2004-06-08, Greg King **
+** **
+\*****************************************************************************/
#endif
#if defined(__C128__)
/* Save and change some flags, so that kernal/basic interrupt handler will
- * not interfere with our routine.
- */
+ ** not interfere with our routine.
+ */
initflag = *(unsigned char*) 0xA04;
*(unsigned char*) 0xA04 &= 0xFE;
graphflag = *(unsigned char*) 0xD8;
/*
- * Minimalistic GEOSLib bitmap demo program
- *
- * 2012-06-10, Oliver Schmidt (ol.sc@web.de)
- *
- * To create bitmap.c use the sp65 sprite and bitmap utility:
- * sp65 -r logo.pcx -c geos-bitmap -w bitmap.c,ident=bitmap
- *
- */
+** Minimalistic GEOSLib bitmap demo program
+**
+** 2012-06-10, Oliver Schmidt (ol.sc@web.de)
+**
+** To create bitmap.c use the sp65 sprite and bitmap utility:
+** sp65 -r logo.pcx -c geos-bitmap -w bitmap.c,ident=bitmap
+**
+*/
#include <conio.h>
/* Note:
- * This is just a sample piece of code that shows how to use some structs -
- * it may not even run.
- */
+** This is just a sample piece of code that shows how to use some structs -
+** it may not even run.
+*/
#include <geos.h>
/* Note:
- * This is just a sample piece of code that shows how to use some structs -
- * it may not even run.
- */
+** This is just a sample piece of code that shows how to use some structs -
+** it may not even run.
+*/
#include <geos.h>
/* Note:
- * This is just a sample piece of code that shows how to use some structs -
- * it may not even run.
- */
+** This is just a sample piece of code that shows how to use some structs -
+** it may not even run.
+*/
#include <geos.h>
/* Note:
- * This is just a sample piece of code that shows how to use some structs -
- * it may not even run.
- */
+** This is just a sample piece of code that shows how to use some structs -
+** it may not even run.
+*/
#include <geos.h>
/*
- * Minimalistic GEOSLib overlay demo program
- *
- * 2012-01-01, Oliver Schmidt (ol.sc@web.de)
- *
- */
+** Minimalistic GEOSLib overlay demo program
+**
+** 2012-01-01, Oliver Schmidt (ol.sc@web.de)
+**
+*/
#include <stdio.h>
/* Functions resident in an overlay can call back functions resident in the
- * main program at any time without any precautions. The function show() is
- * an example for such a function resident in the main program.
- */
+** main program at any time without any precautions. The function show() is
+** an example for such a function resident in the main program.
+*/
void show(char *name)
{
char line1[40];
}
/* In a real-world overlay program one would probably not use a #pragma but
- * rather place the all the code of certain source files into the overlay by
- * compiling them with --code-name OVERLAY1.
- */
+** rather place the all the code of certain source files into the overlay by
+** compiling them with --code-name OVERLAY1.
+*/
#pragma code-name(push, "OVERLAY1");
void foo(void)
{
/* Functions resident in an overlay can access all program variables and
- * constants at any time without any precautions because those are never
- * placed in overlays. The string constant "One" is an example for such
- * a constant resident in the main program.
- */
+ ** constants at any time without any precautions because those are never
+ ** placed in overlays. The string constant "One" is an example for such
+ ** a constant resident in the main program.
+ */
show("One");
}
}
/* The macro definitions OVERLAY_ADDR and OVERLAY_SIZE were generated in
- * overlay-demores.h by grc65. They contain the overlay area address and
- * size specific to a certain program.
- */
+ ** overlay-demores.h by grc65. They contain the overlay area address and
+ ** size specific to a certain program.
+ */
if (ReadRecord(OVERLAY_ADDR, OVERLAY_SIZE)) {
_poserror("ReadRecord.1");
return;
}
/* The linker makes sure that the call to foo() ends up at the right mem
- * addr. However it's up to user to make sure that the - right - overlay
- * is actually loaded before making the the call.
- */
+ ** addr. However, it's up to user to make sure that the -- right -- overlay
+ ** actually is loaded before making the call.
+ */
foo();
DlgBoxOk(CBOLDON "Overlay Demo - Main" CPLAINTEXT,
}
/* Replacing one overlay with another one can only happen from the main
- * program. This implies that an overlay can never load another overlay.
- */
+ ** program. This implies that an overlay can never load another overlay.
+ */
if (ReadRecord(OVERLAY_ADDR, OVERLAY_SIZE)) {
_poserror("ReadRecord.2");
return;
/*
- * gunzip65 - a gunzip utility for 6502-based machines.
- *
- * Piotr Fusik <fox@scene.pl>
- *
- * This should be considered as a test of my zlib-compatible library
- * rather than a real application.
- * It's not user-friendly, fault-tolerant, whatever.
- * However, it really works for real GZIP files, provided they are small
- * enough to fit in buffer[] (after decompression!).
- */
+** gunzip65 - a gunzip utility for 6502-based machines.
+**
+** Piotr Fusik <fox@scene.pl>
+**
+** This should be considered as a test of my zlib-compatible library
+** rather than a real application.
+** It's not user-friendly, fault-tolerant, whatever.
+** However, it really works for real GZIP files, provided they are small
+** enough to fit in buffer[] (after decompression!).
+*/
#include <stdio.h>
#include <string.h>
#ifndef __CC65__
/*
- * Emulate inflatemem() if using original zlib.
- * As you can see, this program is quite portable.
- */
+** Emulate inflatemem() if using original zlib.
+** As you can see, this program is quite portable.
+*/
unsigned inflatemem(char* dest, const char* source)
{
z_stream stream;
#endif /* __CC65__ */
/*
- * Structure of a GZIP file:
- *
- * 1. GZIP header:
- * Offset 0: Signature (2 bytes: 0x1f, 0x8b)
- * Offset 2: Compression method (1 byte: 8 == "deflate")
- * Offset 3: Flags (1 byte: see below)
- * Offset 4: File date and time (4 bytes)
- * Offset 8: Extra flags (1 byte)
- * Offset 9: Target OS (1 byte: DOS, Amiga, Unix, etc.)
- * if (flags & FEXTRA) { 2 bytes of length, then length bytes }
- * if (flags & FNAME) { ASCIIZ filename }
- * if (flags & FCOMMENT) { ASCIIZ comment }
- * if (flags & FHCRC) { 2 bytes of CRC }
- *
- * 2. Deflate compressed data.
- *
- * 3. GZIP trailer:
- * Offset 0: CRC-32 (4 bytes)
- * Offset 4: uncompressed file length (4 bytes)
- */
+** Structure of a GZIP file:
+**
+** 1. GZIP header:
+** Offset 0: Signature (2 bytes: 0x1f, 0x8b)
+** Offset 2: Compression method (1 byte: 8 == "deflate")
+** Offset 3: Flags (1 byte: see below)
+** Offset 4: File date and time (4 bytes)
+** Offset 8: Extra flags (1 byte)
+** Offset 9: Target OS (1 byte: DOS, Amiga, Unix, etc.)
+** if (flags & FEXTRA) { 2 bytes of length, then length bytes }
+** if (flags & FNAME) { ASCIIZ filename }
+** if (flags & FCOMMENT) { ASCIIZ comment }
+** if (flags & FHCRC) { 2 bytes of CRC }
+**
+** 2. Deflate compressed data.
+**
+** 3. GZIP trailer:
+** Offset 0: CRC-32 (4 bytes)
+** Offset 4: uncompressed file length (4 bytes)
+*/
/* Flags in the GZIP header. */
#define FTEXT 1 /* Extra text */
#define FCOMMENT 16 /* File comment */
/*
- * We read whole GZIP file into this buffer.
- * Then we use this buffer for the decompressed data.
- */
+** We read whole GZIP file into this buffer.
+** Then we use this buffer for the decompressed data.
+*/
static unsigned char buffer[26000];
/*
- * Get a 16-bit little-endian unsigned number, using unsigned char* p.
- * On many machines this could be (*(unsigned short*) p),
- * but I really like portability. :-)
- */
+** Get a 16-bit little-endian unsigned number, using unsigned char* p.
+** On many machines this could be (*(unsigned short*) p),
+** but I really like portability. :-)
+*/
#define GET_WORD(p) (*(p) + ((unsigned) (p)[1] << 8))
/* Likewise, for a 32-bit number. */
#define GET_LONG(p) (GET_WORD(p) + ((unsigned long) GET_WORD(p + 2) << 16))
/*
- * Uncompress a GZIP file.
- * On entry, buffer[] should contain the whole GZIP file contents,
- * and the argument complen should be equal to the length of the GZIP file.
- * On return, buffer[] contains the uncompressed data, and the returned
- * value is the length of the uncompressed data.
- */
+** Uncompress a GZIP file.
+** On entry, buffer[] should contain the whole GZIP file contents,
+** and the argument complen should be equal to the length of the GZIP file.
+** On return, buffer[] contains the uncompressed data, and the returned
+** value is the length of the uncompressed data.
+*/
unsigned uncompress_buffer(unsigned complen)
{
unsigned char* ptr;
ptr += 2;
/*
- * calculate length of raw "deflate" data
- * (without the GZIP header and 8-byte trailer)
- */
+ ** calculate length of raw "deflate" data
+ ** (without the GZIP header and 8-byte trailer)
+ */
complen -= (ptr - buffer) + 8;
/*
- * We will move the compressed data to the end of buffer[].
- * Thus the compressed data and the decompressed data (written from
- * the beginning of buffer[]) may overlap, as long as the decompressed
- * data doesn't go further than unread compressed data.
- * ptr2 points to the beginning of compressed data at the end
- * of buffer[].
- */
+ ** We will move the compressed data to the end of buffer[].
+ ** Thus the compressed data and the decompressed data (written from
+ ** the beginning of buffer[]) may overlap, as long as the decompressed
+ ** data doesn't go further than unread compressed data.
+ ** ptr2 points to the beginning of compressed data at the end
+ ** of buffer[].
+ */
ptr2 = buffer + sizeof(buffer) - complen;
/* move the compressed data to end of buffer[] */
memmove(ptr2, ptr, complen);
}
/*
- * Get a filename from standard input.
- */
+** Get a filename from standard input.
+*/
char* get_fname(void)
{
static char filename[100];
/*
- * Fancy hello world program using cc65.
- *
- * Ullrich von Bassewitz (ullrich@von-bassewitz.de)
- *
- */
+** Fancy hello world program using cc65.
+**
+** Ullrich von Bassewitz (ullrich@von-bassewitz.de)
+**
+*/
-/*****************************************************************************
- * mandelbrot sample program for cc65. *
- * *
- * (w)2002 by groepaz/hitmen, TGI support by Stefan Haubenthal *
- *****************************************************************************/
+/*****************************************************************************\
+** mandelbrot sample program for cc65. **
+** **
+** (w) 2002 by groepaz/hitmen, TGI support by Stefan Haubenthal **
+\*****************************************************************************/
/*
- * Extended memory overlay demo program.
- *
- * Shows how to combine multiple cc65 features
- * incl. overlays and extended memory drivers.
- *
- * 2012-17-07, Oliver Schmidt (ol.sc@web.de)
- *
- */
+** Extended memory overlay demo program.
+**
+** Shows how to combine multiple cc65 features
+** incl. overlays and extended memory drivers.
+**
+** 2012-17-07, Oliver Schmidt (ol.sc@web.de)
+**
+*/
/* The symbols _OVERLAY?_LOAD__ and _OVERLAY?_SIZE__ were generated by the
- * linker. They contain the overlay area address and size specific to a
- * certain program.
- */
+** linker. They contain the overlay area address and size specific to a
+** certain program.
+*/
extern void _OVERLAY1_LOAD__[], _OVERLAY1_SIZE__[];
extern void _OVERLAY2_LOAD__[], _OVERLAY2_SIZE__[];
extern void _OVERLAY3_LOAD__[], _OVERLAY3_SIZE__[];
/* Functions resident in an overlay can call back functions resident in the
- * main program at any time without any precautions. The function log() is
- * an example for such a function resident in the main program.
- */
+** main program at any time without any precautions. The function log() is
+** an example for such a function resident in the main program.
+*/
void log (char *msg)
{
/* Functions resident in an overlay can access all program variables and
- * constants at any time without any precautions because those are never
- * placed in overlays. The string constant below is an example for such
- * a constant resident in the main program.
- */
+ ** constants at any time without any precautions because those are never
+ ** placed in overlays. The string constant below is an example for such
+ ** a constant resident in the main program.
+ */
printf ("Log: %s\n", msg);
}
/* In a real-world overlay program one would probably not use a #pragma but
- * rather place all the code of certain source files into the overlay by
- * compiling them with --code-name OVERLAY1.
- */
+** rather place all the code of certain source files into the overlay by
+** compiling them with --code-name OVERLAY1.
+*/
#pragma code-name (push, "OVERLAY1");
void foo (void)
log ("Calling overlay 1 from main");
/* The linker makes sure that the call to foo() ends up at the right mem
- * addr. However it's up to user to make sure that the - right - overlay
- * is actually loaded before making the the call.
- */
+ ** addr. However it's up to user to make sure that the - right - overlay
+ ** is actually loaded before making the the call.
+ */
foo ();
}
/* Replacing one overlay with another one can only happen from the main
- * program. This implies that an overlay can never load another overlay.
- */
+ ** program. This implies that an overlay can never load another overlay.
+ */
if (loadoverlay (2)) {
log ("Calling overlay 2 from main");
bar ();
/*
- * "Eine kleine Nachtmusik" by Wolfgang Amadeus Mozart, KV 525
- *
- * First version in 1987 by
- * Joachim von Bassewitz (joachim@von-bassewitz.de) and
- * Ullrich von Bassewitz (ullrich@von-bassewitz.de).
- *
- * C conversion in 1998 by
- * Ullrich von Bassewitz (ullrich@von-bassewitz.de)
- *
- */
+** "Eine kleine Nachtmusik" by Wolfgang Amadeus Mozart, KV 525
+**
+** First version in 1987 by
+** Joachim von Bassewitz (joachim@von-bassewitz.de) and
+** Ullrich von Bassewitz (ullrich@von-bassewitz.de).
+**
+** C conversion in 1998 by
+** Ullrich von Bassewitz (ullrich@von-bassewitz.de)
+**
+*/
/* Tables with voice data.
- *
- * Bit Description
- * -------------------------------------------
- * 15 Pause bit.
- * 12-14 Octave
- * 8-11 Tone (index into frequency table)
- * 7 Unused. Was thought as a control bit in the original version to
- * change SID parameters, but this was never implemented.
- * 0-6 Length of the tone in ticks.
- *
- */
+**
+** Bit Description
+** -------------------------------------------
+** 15 Pause bit.
+** 12-14 Octave
+** 8-11 Tone (index into frequency table)
+** 7 Unused. Was thought as a control bit in the original version to
+** change SID parameters, but this was never implemented.
+** 0-6 Length of the tone in ticks.
+**
+*/
#define TICKS_PER_TONE 4
/* Done flag. Contains one bit for each voice. Will contain 0x07 if all
- * voices have finished playing.
- */
+** voices have finished playing.
+*/
static unsigned char Done;
/* On the 510/610, the SID is in another bank (the system bank), so we cannot
- * just write to the memory space.
- */
+** just write to the memory space.
+*/
#if defined(__CBM510__) || defined(__CBM610__)
# define outb(addr,val) pokebsys ((unsigned)(addr), val)
# define outw(addr,val) pokewsys ((unsigned)(addr), val)
}
} else {
/* Decrement the ticks. If this is the last tick of a tone,
- * reset bit 0 of the trigger value and write it back to the
- * SID to start the release phase.
- */
+ ** reset bit 0 of the trigger value and write it back to the
+ ** SID to start the release phase.
+ */
if (--(VC->Ticks) == 0) {
outb (&Voice->ctrl, VC->Trigger & 0xFE);
}
/*
- * Minimalistic overlay demo program.
- *
- * Shows how to load overlay files from disk.
- *
- * 2009-10-02, Oliver Schmidt (ol.sc@web.de)
- *
- */
+** Minimalistic overlay demo program.
+**
+** Shows how to load overlay files from disk.
+**
+** 2009-10-02, Oliver Schmidt (ol.sc@web.de)
+**
+*/
/* Functions resident in an overlay can call back functions resident in the
- * main program at any time without any precautions. The function log() is
- * an example for such a function resident in the main program.
- */
+** main program at any time without any precautions. The function log() is
+** an example for such a function resident in the main program.
+*/
void log (char *msg)
{
printf ("Log: %s\n", msg);
/* In a real-world overlay program one would probably not use a #pragma but
- * rather place all the code of certain source files into the overlay by
- * compiling them with --code-name OVERLAY1.
- */
+** rather place all the code of certain source files into the overlay by
+** compiling them with --code-name OVERLAY1.
+*/
#pragma code-name (push, "OVERLAY1");
void foo (void)
{
/* Functions resident in an overlay can access all program variables and
- * constants at any time without any precautions because those are never
- * placed in overlays. The string constant below is an example for such
- * a constant resident in the main program.
- */
+ ** constants at any time without any precautions because those are never
+ ** placed in overlays. The string constant below is an example for such
+ ** a constant resident in the main program.
+ */
log ("Calling main from overlay 1");
}
log ("Calling overlay 1 from main");
/* The symbols _OVERLAY1_LOAD__ and _OVERLAY1_SIZE__ were generated by the
- * linker. They contain the overlay area address and size specific to a
- * certain program.
- */
+ ** linker. They contain the overlay area address and size specific to a
+ ** certain program.
+ */
if (loadfile ("ovrldemo.1", _OVERLAY1_LOAD__, _OVERLAY1_SIZE__)) {
/* The linker makes sure that the call to foo() ends up at the right mem
- * addr. However it's up to user to make sure that the - right - overlay
- * is actually loaded before making the the call.
- */
+ ** addr. However it's up to user to make sure that the - right - overlay
+ ** is actually loaded before making the the call.
+ */
foo ();
}
log ("Calling overlay 2 from main");
/* Replacing one overlay with another one can only happen from the main
- * program. This implies that an overlay can never load another overlay.
- */
+ ** program. This implies that an overlay can never load another overlay.
+ */
if (loadfile ("ovrldemo.2", _OVERLAY2_LOAD__, _OVERLAY2_SIZE__)) {
bar ();
}
-/*****************************************************************************
- * plasma test program for cc65. *
- * *
- * (w)2001 by groepaz/hitmen *
- * *
- * Cleanup and porting by Ullrich von Bassewitz. *
- * *
- *****************************************************************************/
+/*****************************************************************************\
+** plasma test program for cc65. **
+** **
+** (w)2001 by groepaz/hitmen **
+** **
+** Cleanup and porting by Ullrich von Bassewitz. **
+** **
+\*****************************************************************************/
c2B -= 3;
for (ii = 0; ii < 25; ++ii) {
/* Unrolling the following loop will give a speed increase of
- * nearly 100% (~24fps), but it will also increase the code
- * size a lot.
- */
+ ** nearly 100% (~24fps), but it will also increase the code
+ ** size a lot.
+ */
for (i = 0; i < 40; ++i, ++scrn) {
*scrn = (xbuf[i] + ybuf[ii]);
}
outb (&CIA2.pra, (block & 0xFC) | ((SCREEN1 >> 14) ^ 0x03));
#endif
#if defined(__C128__)
- /* Save and change some flags, so that kernal/basic interupt handler will
- * not interfere with our routine.
- */
+ /* Save and change some flags, so that kernal/basic interrupt handler will
+ ** not interfere with our routine.
+ */
initflag = *(unsigned char*) 0xA04;
*(unsigned char*) 0xA04 &= 0xFE;
graphflag = *(unsigned char*) 0xD8;
/*
- * Calculate all primes up to a specific number.
- */
+** Calculate all primes up to a specific number.
+*/
const ObjData* ExpFind (const char* Name)
/* Check for an identifier in the list. Return NULL if not found, otherwise
- * return a pointer to the module, that exports the identifer.
- */
+** return a pointer to the module, that exports the identifer.
+*/
{
/* Get a pointer to the list with the symbols hash value */
HashEntry* L = HashTab [HashStr (Name) % HASHTAB_SIZE];
const struct ObjData* ExpFind (const char* Name);
/* Check for an identifier in the list. Return NULL if not found, otherwise
- * return a pointer to the module, that exports the identifer.
- */
+** return a pointer to the module, that exports the identifer.
+*/
/* */
/* */
/* (C) 1998-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* Write a variable sized value to the file in special encoding */
{
/* We will write the value to the file in 7 bit chunks. If the 8th bit
- * is clear, we're done, if it is set, another chunk follows. This will
- * allow us to encode smaller values with less bytes, at the expense of
- * needing 5 bytes if a 32 bit value is written to file.
- */
+ ** is clear, we're done, if it is set, another chunk follows. This will
+ ** allow us to encode smaller values with less bytes, at the expense of
+ ** needing 5 bytes if a 32 bit value is written to file.
+ */
do {
unsigned char C = (V & 0x7F);
V >>= 7;
/* Read a variable size value from the file */
{
/* The value was written to the file in 7 bit chunks LSB first. If there
- * are more bytes, bit 8 is set, otherwise it is clear.
- */
+ ** are more bytes, bit 8 is set, otherwise it is clear.
+ */
unsigned char C;
unsigned long V = 0;
unsigned Shift = 0;
void LibOpen (const char* Name, int MustExist, int NeedTemp)
/* Open an existing library and a temporary copy. If MustExist is true, the
- * old library is expected to exist. If NeedTemp is true, a temporary library
- * is created.
- */
+** old library is expected to exist. If NeedTemp is true, a temporary library
+** is created.
+*/
{
/* Remember the name */
LibName = xstrdup (Name);
unsigned long LibCopyTo (FILE* F, unsigned long Bytes)
/* Copy data from F to the temp library file, return the start position in
- * the temporary library file.
- */
+** the temporary library file.
+*/
{
unsigned char Buf [4096];
static void LibCheckExports (ObjData* O)
/* Insert all exports from the given object file into the global list
- * checking for duplicates.
- */
+** checking for duplicates.
+*/
{
unsigned I;
void LibClose (void)
/* Write remaining data, close both files and copy the temp file to the old
- * filename
- */
+** filename
+*/
{
/* Do we have a temporary library? */
if (NewLib) {
size_t Count;
/* Walk through the object file list, inserting exports into the
- * export list checking for duplicates. Copy any data that is still
- * in the old library into the new one.
- */
+ ** export list checking for duplicates. Copy any data that is still
+ ** in the old library into the new one.
+ */
for (I = 0; I < CollCount (&ObjPool); ++I) {
/* Get a pointer to the object */
void LibOpen (const char* Name, int MustExist, int NeedTemp);
/* Open an existing library and a temporary copy. If MustExist is true, the
- * old library is expected to exist. If NeedTemp is true, a temporary library
- * is created.
- */
+** old library is expected to exist. If NeedTemp is true, a temporary library
+** is created.
+*/
unsigned long LibCopyTo (FILE* F, unsigned long Bytes);
/* Copy data from F to the temp library file, return the start position in
- * the temporary library file.
- */
+** the temporary library file.
+*/
void LibCopyFrom (unsigned long Pos, unsigned long Bytes, FILE* F);
/* Copy data from the library file into another file */
void LibClose (void);
/* Write remaining data, close both files and copy the temp file to the old
- * filename
- */
+** filename
+*/
ObjData* FindObjData (const char* Module)
/* Search for the module with the given name and return it. Return NULL if the
- * module is not in the list.
- */
+** module is not in the list.
+*/
{
unsigned I;
ObjData* FindObjData (const char* Module);
/* Search for the module with the given name and return it. Return NULL if the
- * module is not in the list.
- */
+** module is not in the list.
+*/
void DelObjData (const char* Module);
/* Delete the object module from the list */
void ObjReadData (FILE* F, ObjData* O)
/* Read object file data from the given file. The function expects the Name
- * and Start fields to be valid. Header and basic data are read.
- */
+** and Start fields to be valid. Header and basic data are read.
+*/
{
unsigned long Count;
Error ("Could not open `%s': %s", Name, strerror (errno));
}
- /* Get the modification time of the object file. There a race condition
- * here, since we cannot use fileno() (non standard identifier in standard
- * header file), and therefore not fstat. When using stat with the
- * file name, there's a risk that the file was deleted and recreated
- * while it was open. Since mtime and size are only used to check
- * if a file has changed in the debugger, we will ignore this problem
- * here.
- */
+ /* Get the modification time of the object file. There's a race condition
+ ** here, since we cannot use fileno() (non-standard identifier in standard
+ ** header file), and therefore not fstat. When using stat with the
+ ** file name, there's a risk that the file was deleted and recreated
+ ** while it was open. Since mtime and size are only used to check
+ ** if a file has changed in the debugger, we will ignore this problem
+ ** here.
+ */
if (FileStat (Name, &StatBuf) != 0) {
Error ("Cannot stat object file `%s': %s", Name, strerror (errno));
}
O = NewObjData ();
} else {
/* Found - check the file modification times of the internal copy
- * and the external one.
- */
+ ** and the external one.
+ */
if (difftime ((time_t)O->MTime, StatBuf.st_mtime) > 0.0) {
Warning ("Replacing module `%s' by older version in library `%s'",
O->Name, LibName);
ObjReadData (Obj, O);
/* Copy the complete object data to the library file and update the
- * starting offset
- */
+ ** starting offset
+ */
fseek (Obj, 0, SEEK_SET);
O->Start = LibCopyTo (Obj, O->Size);
}
/* Copy the complete object file data from the library to the new object
- * file.
- */
+ ** file.
+ */
LibCopyFrom (O->Start, O->Size, Obj);
/* Close the file */
void ObjReadData (FILE* F, struct ObjData* O);
/* Read object file data from the given file. The function expects the Name
- * and Start fields to be valid. Header and basic data are read.
- */
+** and Start fields to be valid. Header and basic data are read.
+*/
void ObjAdd (const char* Name);
/* Add an object file to the library */
StrBuf* AnonName (StrBuf* Buf, const char* Spec)
/* Get a name for an anonymous scope, variable or type. Size is the size of
- * the buffer passed to the function, Spec will be used as part of the
- * identifier if given. A pointer to the buffer is returned.
- */
+** the buffer passed to the function, Spec will be used as part of the
+** identifier if given. A pointer to the buffer is returned.
+*/
{
static unsigned ACount = 0;
SB_Printf (Buf, "%s-%s-%04X", AnonTag, Spec, ++ACount);
StrBuf* AnonName (StrBuf* Buf, const char* Spec);
/* Get a name for an anonymous scope, variable or type. Size is the size of
- * the buffer passed to the function, Spec will be used as part of the
- * identifier if given. A pointer to the buffer is returned.
- */
+** the buffer passed to the function, Spec will be used as part of the
+** identifier if given. A pointer to the buffer is returned.
+*/
int IsAnonName (const StrBuf* Name);
/* Check if the given symbol name is that of an anonymous symbol */
/* Get the overall condition based on all conditions on the stack. */
{
/* Since the last entry contains the overall condition of the parent, we
- * must check it in combination of the current condition. If there is no
- * last entry, the overall condition is true.
- */
+ ** must check it in combination of the current condition. If there is no
+ ** last entry, the overall condition is true.
+ */
return (IfCount == 0) ||
((IfStack[IfCount-1].Flags & (ifCond | ifParentCond)) == (ifCond | ifParentCond));
}
static void CalcOverallIfCond (void)
-/* Caclulate the overall condition based on all conditions on the stack. */
+/* Calculate the overall condition, based on all conditions on the stack. */
{
IfCond = GetOverallIfCond ();
}
NextTok ();
/* Ignore the new condition if we are inside a false .ELSE
- * branch. This way we won't get any errors about undefined
- * symbols or similar...
- */
+ ** branch. This way we won't get any errors about undefined
+ ** symbols or similar...
+ */
if (IfCond) {
SetIfCond (D, ConstExpression ());
ExpectSep ();
FreeIf ();
/* Be sure not to read the next token until the .IF stack
- * has been cleanup up, since we may be at end of file.
- */
+ ** has been cleanup up, since we may be at end of file.
+ */
NextTok ();
ExpectSep ();
int CheckConditionals (void)
/* Check if the current token is one that starts a conditional directive, and
- * call DoConditionals if so. Return true if a conditional directive was found,
- * return false otherwise.
- */
+** call DoConditionals if so. Return true if a conditional directive was found,
+** return false otherwise.
+*/
{
switch (CurTok.Tok) {
case TOK_ELSE:
void CheckOpenIfs (void)
/* Called from the scanner before closing an input file. Will check for any
- * open .ifs in this file.
- */
+** open .ifs in this file.
+*/
{
const LineInfo* LI;
while (1) {
/* Get the current file number and check if the topmost entry on the
- * .IF stack was inserted with this file number
- */
+ ** .IF stack was inserted with this file number
+ */
IfDesc* D = GetCurrentIf ();
if (D == 0) {
/* There are no open .IFs */
int CheckConditionals (void);
/* Check if the current token is one that starts a conditional directive, and
- * call DoConditionals if so. Return true if a conditional directive was found,
- * return false otherwise.
- */
+** call DoConditionals if so. Return true if a conditional directive was found,
+** return false otherwise.
+*/
void CheckOpenIfs (void);
/* Called from the scanner before closing an input file. Will check for any
- * open .ifs in this file.
- */
+** open .ifs in this file.
+*/
unsigned GetIfStack (void);
/* Get the current .IF stack pointer */
static int ValidateType (StrBuf* Type)
/* Check if the given type is valid and if so, return a string id for it. If
- * the type isn't valid, return -1. Type is overwritten when checking.
- */
+** the type isn't valid, return -1. Type is overwritten when checking.
+*/
{
unsigned I;
const char* A;
}
/* If a parameters follow, this is actual line info. If no parameters
- * follow, the last line info is terminated.
- */
+ ** follow, the last line info is terminated.
+ */
if (CurTok.Tok == TOK_SEP) {
return;
}
/* Do checks on all hll debug info symbols when assembly is complete */
{
/* When parsing the debug statements for HLL symbols, we have already
- * tagged the functions to their asm counterparts. This wasn't done for
- * C symbols, since we will allow forward declarations. So we have to
- * resolve the normal C symbols now.
- */
+ ** tagged the functions to their asm counterparts. This wasn't done for
+ ** C symbols, since we will allow forward declarations. So we have to
+ ** resolve the normal C symbols now.
+ */
unsigned I;
for (I = 0; I < CollCount (&HLLDbgSyms); ++I) {
HLLDbgSym* S = CollAtUnchecked (&HLLDbgSyms, I);
/* Ignore functions and auto symbols, because the later live on the
- * stack and don't have corresponding asm symbols.
- */
+ ** stack and don't have corresponding asm symbols.
+ */
if (HLL_IS_FUNC (S->Flags) || HLL_GET_SC (S->Flags) == HLL_SC_AUTO) {
continue;
}
unsigned SC = HLL_GET_SC (S->Flags);
/* Remember if the symbol has debug info attached
- * ### This should go into DbgInfoCheck
- */
+ ** ### This should go into DbgInfoCheck
+ */
if (S->Sym && S->Sym->DebugSymId != ~0U) {
S->Flags |= HLL_DATA_SYM;
}
} else {
/* Remaining stuff:
- *
- * adr
- * adr,x
- * adr,y
- * adr,s
- */
+ **
+ ** adr
+ ** adr,x
+ ** adr,y
+ ** adr,s
+ */
A->Expr = Expression ();
if (CurTok.Tok == TOK_COMMA) {
static long RegNum ()
/* Try to read a register number specified not as a register (Rx) but as a
- * numeric value between 0 and 15. Return the register number or -1 on
- * failure.
- */
+** numeric value between 0 and 15. Return the register number or -1 on
+** failure.
+*/
{
long Val;
ExprNode* Expr = Expression ();
A->AddrModeSet = AMSW16_BRA;
/* If the value is a constant between 0 and 15, it may also be a
- * register number.
- */
+ ** register number.
+ */
if (IsConstExpr (A->Expr, &Reg) && Reg >= 0 && Reg <= 15) {
FreeExpr (A->Expr);
A->Reg = (unsigned) Reg;
unsigned Skipped;
/* The basic line info is always in slot zero. It has been used to
- * output the actual error or warning. The following slots may contain
- * more information. Check them and print additional notifications if
- * they're present, but limit the number to a reasonable value.
- */
+ ** output the actual error or warning. The following slots may contain
+ ** more information. Check them and print additional notifications if
+ ** they're present, but limit the number to a reasonable value.
+ */
for (I = 1, Output = 0, Skipped = 0; I < CollCount (LineInfos); ++I) {
/* Get next line info */
const LineInfo* LI = CollConstAt (LineInfos, I);
/* Since all expressions are first packed into expression trees, and each
- * expression tree node is allocated on the heap, we add some type of special
- * purpose memory allocation here: Instead of freeing the nodes, we save some
- * number of freed nodes for later and remember them in a single linked list
- * using the Left link.
- */
+** expression tree node is allocated on the heap, we add some type of special
+** purpose memory allocation here: Instead of freeing the nodes, we save some
+** number of freed nodes for later and remember them in a single linked list
+** using the Left link.
+*/
#define MAX_FREE_NODES 64
static ExprNode* FreeExprNodes = 0;
static unsigned FreeNodeCount = 0;
int IsEasyConst (const ExprNode* E, long* Val)
/* Do some light checking if the given node is a constant. Don't care if E is
- * a complex expression. If E is a constant, return true and place its value
- * into Val, provided that Val is not NULL.
- */
+** a complex expression. If E is a constant, return true and place its value
+** into Val, provided that Val is not NULL.
+*/
{
/* Resolve symbols, follow symbol chains */
while (E->Op == EXPR_SYMBOL) {
/* Mark the symbol as referenced */
SymRef (S);
/* If the symbol is a variable, return just its value, otherwise
- * return a reference to the symbol.
- */
+ ** return a reference to the symbol.
+ */
if (SymIsVar (S)) {
return CloneExpr (GetSymExpr (S));
} else {
/* Handle the .BLANK builtin function */
{
/* We have a list of tokens that ends with the closing paren. Skip
- * the tokens, and count them. Allow optionally curly braces.
- */
+ ** the tokens, and count them. Allow optionally curly braces.
+ */
token_t Term = GetTokListTerm (TOK_RPAREN);
unsigned Count = 0;
while (CurTok.Tok != Term) {
/* Check for end of line or end of input. Since the calling function
- * will check for the closing paren, we don't need to print an error
- * here, just bail out.
- */
+ ** will check for the closing paren, we don't need to print an error
+ ** here, just bail out.
+ */
if (TokIsSep (CurTok.Tok)) {
break;
}
TokNode* Node;
/* A list of tokens follows. Read this list and remember it building a
- * single linked list of tokens including attributes. The list is
- * either enclosed in curly braces, or terminated by a comma.
- */
+ ** single linked list of tokens including attributes. The list is
+ ** either enclosed in curly braces, or terminated by a comma.
+ */
token_t Term = GetTokListTerm (TOK_COMMA);
while (CurTok.Tok != Term) {
}
/* Read the second list which is optionally enclosed in curly braces and
- * terminated by the right parenthesis. Compare each token against the
- * one in the first list.
- */
+ ** terminated by the right parenthesis. Compare each token against the
+ ** one in the first list.
+ */
Term = GetTokListTerm (TOK_RPAREN);
Result = 1;
Node = Root;
}
/* If ScopeName is empty, no explicit scope was specified. We have to
- * search upper scope levels in this case.
- */
+ ** search upper scope levels in this case.
+ */
NoScope = SB_IsEmpty (&ScopeName);
/* First search for a scope with the given name */
}
/* If we did find a scope with the name, read the symbol defining the
- * size, otherwise search for a symbol entry with the name and scope.
- */
+ ** size, otherwise search for a symbol entry with the name and scope.
+ */
if (Scope) {
/* Yep, it's a scope */
SizeSym = GetSizeOfScope (Scope);
}
/* Get the char, handle as unsigned. Be sure to translate it into
- * the target character set.
- */
+ ** the target character set.
+ */
C = TgtTranslateChar (SB_At (&Str, (unsigned)Index));
ExitPoint:
/* Handle the .TCOUNT function */
{
/* We have a list of tokens that ends with the closing paren. Skip
- * the tokens, and count them. Allow optionally curly braces.
- */
+ ** the tokens, and count them. Allow optionally curly braces.
+ */
token_t Term = GetTokListTerm (TOK_RPAREN);
int Count = 0;
while (CurTok.Tok != Term) {
/* Check for end of line or end of input. Since the calling function
- * will check for the closing paren, we don't need to print an error
- * here, just bail out.
- */
+ ** will check for the closing paren, we don't need to print an error
+ ** here, just bail out.
+ */
if (TokIsSep (CurTok.Tok)) {
break;
}
}
/* Generate a literal expression and delete the old left and
- * right sides.
- */
+ ** right sides.
+ */
FreeExpr (Left);
FreeExpr (Right);
Root = GenLiteralExpr (Val);
}
/* Generate a literal expression and delete the old left and
- * right sides.
- */
+ ** right sides.
+ */
FreeExpr (Left);
FreeExpr (Right);
Root = GenLiteralExpr (Val);
}
/* Generate a literal expression and delete the old left and
- * right sides.
- */
+ ** right sides.
+ */
FreeExpr (Left);
FreeExpr (Right);
Root = GenLiteralExpr (Val);
}
/* Generate a literal expression and delete the old left and
- * right sides.
- */
+ ** right sides.
+ */
FreeExpr (Left);
FreeExpr (Right);
Root = GenLiteralExpr (Val);
}
/* Generate a literal expression and delete the old left and
- * right sides.
- */
+ ** right sides.
+ */
FreeExpr (Left);
FreeExpr (Right);
Root = GenLiteralExpr (Val);
ExprNode* Expression (void)
/* Evaluate an expression, build the expression tree on the heap and return
- * a pointer to the root of the tree.
- */
+** a pointer to the root of the tree.
+*/
{
return Expr0 ();
}
long ConstExpression (void)
/* Parse an expression. Check if the expression is const, and print an error
- * message if not. Return the value of the expression, or a dummy, if it is
- * not constant.
- */
+** message if not. Return the value of the expression, or a dummy, if it is
+** not constant.
+*/
{
long Val;
ExprNode* GenBranchExpr (unsigned Offs)
/* Return an expression that encodes the difference between current PC plus
- * offset and the target expression (that is, Expression() - (*+Offs) ).
- */
+** offset and the target expression (that is, Expression() - (*+Offs) ).
+*/
{
ExprNode* N;
ExprNode* Root;
FreeExpr (N);
/* Generate the final expression:
- * Val - (* + Offs)
- * Val - ((Seg + PC) + Offs)
- * Val - Seg - PC - Offs
- * (Val - PC - Offs) - Seg
- */
+ ** Val - (* + Offs)
+ ** Val - ((Seg + PC) + Offs)
+ ** Val - Seg - PC - Offs
+ ** (Val - PC - Offs) - Seg
+ */
Root = GenLiteralExpr (Val - GetPC () - Offs);
if (GetRelocMode ()) {
N = Root;
} else {
/* Generate the expression:
- * N - (* + Offs)
- * N - ((Seg + PC) + Offs)
- * N - Seg - PC - Offs
- * N - (PC + Offs) - Seg
- */
+ ** N - (* + Offs)
+ ** N - ((Seg + PC) + Offs)
+ ** N - Seg - PC - Offs
+ ** N - (PC + Offs) - Seg
+ */
Root = NewExprNode (EXPR_MINUS);
Root->Left = N;
Root->Right = GenLiteralExpr (GetPC () + Offs);
int IsConstExpr (ExprNode* Expr, long* Val)
/* Return true if the given expression is a constant expression, that is, one
- * with no references to external symbols. If Val is not NULL and the
- * expression is constant, the constant value is stored here.
- */
+** with no references to external symbols. If Val is not NULL and the
+** expression is constant, the constant value is stored here.
+*/
{
int IsConst;
ExprNode* CloneExpr (ExprNode* Expr)
/* Clone the given expression tree. The function will simply clone symbol
- * nodes, it will not resolve them.
- */
+** nodes, it will not resolve them.
+*/
{
ExprNode* Clone;
}
/* If the is a leafnode, write the expression attribute, otherwise
- * write the expression operands.
- */
+ ** write the expression operands.
+ */
switch (Expr->Op) {
case EXPR_LITERAL:
void ExprGuessedAddrSize (const ExprNode* Expr, unsigned char AddrSize)
/* Mark the address size of the given expression tree as guessed. The address
- * size passed as argument is the one NOT used, because the actual address
- * size wasn't known. Example: Zero page addressing was not used because symbol
- * is undefined, and absolute addressing was available.
- * This function will actually parse the expression tree for undefined symbols,
- * and mark these symbols accordingly.
- */
+** size passed as argument is the one NOT used, because the actual address
+** size wasn't known. Example: Zero page addressing was not used because symbol
+** is undefined, and absolute addressing was available.
+** This function will actually parse the expression tree for undefined symbols,
+** and mark these symbols accordingly.
+*/
{
/* Accept NULL expressions */
if (Expr == 0) {
ExprNode* Expression (void);
/* Evaluate an expression, build the expression tree on the heap and return
- * a pointer to the root of the tree.
- */
+** a pointer to the root of the tree.
+*/
long ConstExpression (void);
/* Parse an expression. Check if the expression is const, and print an error
- * message if not. Return the value of the expression, or a dummy, if it is
- * not constant.
- */
+** message if not. Return the value of the expression, or a dummy, if it is
+** not constant.
+*/
void FreeExpr (ExprNode* Root);
/* Free the expression tree, Root is pointing to. */
ExprNode* GenBranchExpr (unsigned Offs);
/* Return an expression that encodes the difference between current PC plus
- * offset and the target expression (that is, Expression() - (*+Offs) ).
- */
+** offset and the target expression (that is, Expression() - (*+Offs) ).
+*/
ExprNode* GenULabelExpr (unsigned Num);
/* Return an expression for an unnamed label with the given index */
int IsConstExpr (ExprNode* Expr, long* Val);
/* Return true if the given expression is a constant expression, that is, one
- * with no references to external symbols. If Val is not NULL and the
- * expression is constant, the constant value is stored here.
- */
+** with no references to external symbols. If Val is not NULL and the
+** expression is constant, the constant value is stored here.
+*/
int IsByteExpr (ExprNode* Root);
/* Return true if this is a byte expression */
int IsEasyConst (const ExprNode* E, long* Val);
/* Do some light checking if the given node is a constant. Don't care if E is
- * a complex expression. If E is a constant, return true and place its value
- * into Val, provided that Val is not NULL.
- */
+** a complex expression. If E is a constant, return true and place its value
+** into Val, provided that Val is not NULL.
+*/
ExprNode* CloneExpr (ExprNode* Expr);
/* Clone the given expression tree. The function will simply clone symbol
- * nodes, it will not resolve them.
- */
+** nodes, it will not resolve them.
+*/
void WriteExpr (ExprNode* Expr);
/* Write the given expression to the object file */
void ExprGuessedAddrSize (const ExprNode* Expr, unsigned char AddrSize);
/* Mark the address size of the given expression tree as guessed. The address
- * size passed as argument is the one NOT used, because the actual address
- * size wasn't known. Example: Zero page addressing was not used because symbol
- * is undefined, and absolute addressing was available.
- * This function will actually parse the expression tree for undefined symbols,
- * and mark these symbols accordingly.
- */
+** size passed as argument is the one NOT used, because the actual address
+** size wasn't known. Example: Zero page addressing was not used because symbol
+** is undefined, and absolute addressing was available.
+** This function will actually parse the expression tree for undefined symbols,
+** and mark these symbols accordingly.
+*/
ExprNode* FuncBankByte (void);
/* Handle the .BANKBYTE builtin function */
feature_t FindFeature (const StrBuf* Key)
/* Find the feature in a table and return the corresponding enum value. If the
- * feature is invalid, return FEAT_UNKNOWN.
- */
+** feature is invalid, return FEAT_UNKNOWN.
+*/
{
feature_t F;
feature_t SetFeature (const StrBuf* Key)
/* Find the feature and set the corresponding flag if the feature is known.
- * In any case, return the feature found. An invalid Key will return
- * FEAT_UNKNOWN.
- */
+** In any case, return the feature found. An invalid Key will return
+** FEAT_UNKNOWN.
+*/
{
/* Map the string to an enum value */
feature_t Feature = FindFeature (Key);
feature_t FindFeature (const StrBuf* Key);
/* Find the feature in a table and return the corresponding enum value. If the
- * feature is invalid, return FEAT_UNKNOWN.
- */
+** feature is invalid, return FEAT_UNKNOWN.
+*/
feature_t SetFeature (const StrBuf* Key);
/* Find the feature and set the corresponding flag if the feature is known.
- * In any case, return the feature found. An invalid Key will return
- * FEAT_UNKNOWN.
- */
+** In any case, return the feature found. An invalid Key will return
+** FEAT_UNKNOWN.
+*/
static int HT_Compare (const void* Key1, const void* Key2);
/* Compare two keys. The function must return a value less than zero if
- * Key1 is smaller than Key2, zero if both are equal, and a value greater
- * than zero if Key1 is greater then Key2.
- */
+** Key1 is smaller than Key2, zero if both are equal, and a value greater
+** than zero if Key1 is greater then Key2.
+*/
static int HT_Compare (const void* Key1, const void* Key2)
/* Compare two keys. The function must return a value less than zero if
- * Key1 is smaller than Key2, zero if both are equal, and a value greater
- * than zero if Key1 is greater then Key2.
- */
+** Key1 is smaller than Key2, zero if both are equal, and a value greater
+** than zero if Key1 is greater then Key2.
+*/
{
return (int)*(const unsigned*)Key1 - (int)*(const unsigned*)Key2;
}
if (Name == 0) {
/* Name was defined outside any file scope, use the name of the first
- * file instead. Errors are then reported with a file position of
- * line zero in the first file.
- */
+ ** file instead. Errors are then reported with a file position of
+ ** line zero in the first file.
+ */
if (CollCount (&FileTab) == 0) {
/* No files defined until now */
return &ErrorMsg;
unsigned AddFile (const StrBuf* Name, FileType Type,
unsigned long Size, unsigned long MTime)
/* Add a new file to the list of input files. Return the index of the file in
- * the table.
- */
+** the table.
+*/
{
/* Create a new file entry and insert it into the tables */
FileEntry* F = NewFileEntry (GetStrBufId (Name), Type, Size, MTime);
static void CreateDepFile (const char* Name, FileType Types)
/* Create a dependency file with the given name and place dependencies for
- * all files with the given types there.
- */
+** all files with the given types there.
+*/
{
/* Open the file */
FILE* F = fopen (Name, "w");
/* An enum that describes different types of input files. The members are
- * choosen so that it is possible to combine them to bitsets
- */
+** choosen so that it is possible to combine them to bitsets
+*/
typedef enum {
FT_MAIN = 0x01, /* Main input file */
FT_INCLUDE = 0x02, /* Normal include file */
unsigned AddFile (const StrBuf* Name, FileType Type,
unsigned long Size, unsigned long MTime);
/* Add a new file to the list of input files. Return the index of the file in
- * the table.
- */
+** the table.
+*/
void WriteFiles (void);
/* Write the list of input files to the object file */
Fragment* NewFragment (unsigned char Type, unsigned short Len)
/* Create, initialize and return a new fragment. The fragment will be inserted
- * into the current segment.
- */
+** into the current segment.
+*/
{
/* Create a new fragment */
Fragment* F = xmalloc (sizeof (*F));
Fragment* NewFragment (unsigned char Type, unsigned short Len);
/* Create, initialize and return a new fragment. The fragment will be inserted
- * into the current segment.
- */
+** into the current segment.
+*/
static void PutTAMn (const InsDesc* Ins);
/* Emit a TAMn instruction (HuC6280). Since this is a two byte instruction with
- * implicit addressing mode, the opcode byte in the table is actually the
- * second operand byte. The TAM instruction is the more generic form, it takes
- * an immediate argument.
- */
+** implicit addressing mode, the opcode byte in the table is actually the
+** second operand byte. The TAM instruction is the more generic form, it takes
+** an immediate argument.
+*/
static void PutTMA (const InsDesc* Ins);
/* Emit a TMA instruction (HuC6280) with an immediate argument. Only one bit
- * in the argument byte may be set.
- */
+** in the argument byte may be set.
+*/
static void PutTMAn (const InsDesc* Ins);
/* Emit a TMAn instruction (HuC6280). Since this is a two byte instruction with
- * implicit addressing mode, the opcode byte in the table is actually the
- * second operand byte. The TAM instruction is the more generic form, it takes
- * an immediate argument.
- */
+** implicit addressing mode, the opcode byte in the table is actually the
+** second operand byte. The TAM instruction is the more generic form, it takes
+** an immediate argument.
+*/
static void PutTST (const InsDesc* Ins);
/* Emit a TST instruction (HuC6280). */
static void PutJMP (const InsDesc* Ins);
/* Handle the jump instruction for the 6502. Problem is that these chips have
- * a bug: If the address crosses a page, the upper byte gets not corrected and
- * the instruction will fail. The PutJmp function will add a linker assertion
- * to check for this case and is otherwise identical to PutAll.
- */
+** a bug: If the address crosses a page, the upper byte gets not corrected and
+** the instruction will fail. The PutJmp function will add a linker assertion
+** to check for this case and is otherwise identical to PutAll.
+*/
static void PutRTS (const InsDesc* Ins attribute ((unused)));
/* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if
- * the enclosing scope is FAR.
- */
+** the enclosing scope is FAR.
+*/
static void PutAll (const InsDesc* Ins);
/* Handle all other instructions */
const InsTable* InsTab = (const InsTable*) &InsTab6502;
/* Table to build the effective 65xx opcode from a base opcode and an
- * addressing mode.
- */
+** addressing mode.
+*/
static unsigned char EATab[10][AM65I_COUNT] = {
{ /* Table 0 */
0x00, 0x00, 0x05, 0x0D, 0x0F, 0x15, 0x1D, 0x1F,
};
/* Table to build the effective SWEET16 opcode from a base opcode and an
- * addressing mode.
- */
+** addressing mode.
+*/
static unsigned char Sweet16EATab[2][AMSW16I_COUNT] = {
{ /* Table 0 */
0x00, 0x00, 0x00, 0x00, 0x00,
static int EvalEA (const InsDesc* Ins, EffAddr* A)
/* Evaluate the effective address. All fields in A will be valid after calling
- * this function. The function returns true on success and false on errors.
- */
+** this function. The function returns true on success and false on errors.
+*/
{
/* Get the set of possible addressing modes */
GetEA (A);
/* From the possible addressing modes, remove the ones that are invalid
- * for this instruction or CPU.
- */
+ ** for this instruction or CPU.
+ */
A->AddrModeSet &= Ins->AddrMode;
/* If we have an expression, check it and remove any addressing modes that
- * are too small for the expression size. Since we have to study the
- * expression anyway, do also replace it by a simpler one if possible.
- */
+ ** are too small for the expression size. Since we have to study the
+ ** expression anyway, do also replace it by a simpler one if possible.
+ */
if (A->Expr) {
ExprDesc ED;
ED_Init (&ED);
if (ED.AddrSize == ADDR_SIZE_DEFAULT) {
/* We don't know how big the expression is. If the instruction
- * allows just one addressing mode, assume this as address size
- * for the expression. Otherwise assume the default address size
- * for data.
- */
+ ** allows just one addressing mode, assume this as address size
+ ** for the expression. Otherwise assume the default address size
+ ** for data.
+ */
if ((A->AddrModeSet & ~AM65_ALL_ZP) == 0) {
ED.AddrSize = ADDR_SIZE_ZP;
} else if ((A->AddrModeSet & ~AM65_ALL_ABS) == 0) {
} else {
ED.AddrSize = DataAddrSize;
/* If the default address size of the data segment is unequal
- * to zero page addressing, but zero page addressing is
- * allowed by the instruction, mark all symbols in the
- * expression tree. This mark will be checked at end of
- * assembly, and a warning is issued, if a zero page symbol
- * was guessed wrong here.
- */
+ ** to zero page addressing, but zero page addressing is
+ ** allowed by the instruction, mark all symbols in the
+ ** expression tree. This mark will be checked at end of
+ ** assembly, and a warning is issued, if a zero page symbol
+ ** was guessed wrong here.
+ */
if (ED.AddrSize > ADDR_SIZE_ZP && (A->AddrModeSet & AM65_SET_ZP)) {
ExprGuessedAddrSize (A->Expr, ADDR_SIZE_ZP);
}
A->AddrModeBit = (0x01UL << A->AddrMode);
/* If the instruction has a one byte operand and immediate addressing is
- * allowed but not used, check for an operand expression in the form
- * <label or >label, where label is a far or absolute label. If found,
- * emit a warning. This warning protects against a typo, where the '#'
- * for the immediate operand is omitted.
- */
+ ** allowed but not used, check for an operand expression in the form
+ ** <label or >label, where label is a far or absolute label. If found,
+ ** emit a warning. This warning protects against a typo, where the '#'
+ ** for the immediate operand is omitted.
+ */
if (A->Expr && (Ins->AddrMode & AM65_ALL_IMM) &&
(A->AddrModeSet & (AM65_DIR | AM65_ABS | AM65_ABS_LONG)) &&
ExtBytes[A->AddrMode] == 1) {
A->Opcode = Ins->BaseCode | EATab[Ins->ExtCode][A->AddrMode];
/* If feature force_range is active, and we have immediate addressing mode,
- * limit the expression to the maximum possible value.
- */
+ ** limit the expression to the maximum possible value.
+ */
if (A->AddrMode == AM65I_IMM_ACCU || A->AddrMode == AM65I_IMM_INDEX ||
A->AddrMode == AM65I_IMM_IMPLICIT) {
if (ForceRange && A->Expr) {
case 2:
if (CPU == CPU_65816 && (A->AddrModeBit & (AM65_ABS | AM65_ABS_X | AM65_ABS_Y))) {
/* This is a 16 bit mode that uses an address. If in 65816,
- * mode, force this address into 16 bit range to allow
- * addressing inside a 64K segment.
- */
+ ** mode, force this address into 16 bit range to allow
+ ** addressing inside a 64K segment.
+ */
Emit2 (A->Opcode, GenWordExpr (A->Expr));
} else {
Emit2 (A->Opcode, A->Expr);
static long PutImmed8 (const InsDesc* Ins)
/* Parse and emit an immediate 8 bit instruction. Return the value of the
- * operand if it's available and const.
- */
+** operand if it's available and const.
+*/
{
EffAddr A;
long Val = -1;
static void PutTAMn (const InsDesc* Ins)
/* Emit a TAMn instruction (HuC6280). Since this is a two byte instruction with
- * implicit addressing mode, the opcode byte in the table is actually the
- * second operand byte. The TAM instruction is the more generic form, it takes
- * an immediate argument.
- */
+** implicit addressing mode, the opcode byte in the table is actually the
+** second operand byte. The TAM instruction is the more generic form, it takes
+** an immediate argument.
+*/
{
/* Emit the TAM opcode itself */
Emit0 (0x53);
static void PutTMA (const InsDesc* Ins)
/* Emit a TMA instruction (HuC6280) with an immediate argument. Only one bit
- * in the argument byte may be set.
- */
+** in the argument byte may be set.
+*/
{
/* Use the generic handler */
long Val = PutImmed8 (Ins);
static void PutTMAn (const InsDesc* Ins)
/* Emit a TMAn instruction (HuC6280). Since this is a two byte instruction with
- * implicit addressing mode, the opcode byte in the table is actually the
- * second operand byte. The TAM instruction is the more generic form, it takes
- * an immediate argument.
- */
+** implicit addressing mode, the opcode byte in the table is actually the
+** second operand byte. The TAM instruction is the more generic form, it takes
+** an immediate argument.
+*/
{
/* Emit the TMA opcode itself */
Emit0 (0x43);
static void PutJMP (const InsDesc* Ins)
/* Handle the jump instruction for the 6502. Problem is that these chips have
- * a bug: If the address crosses a page, the upper byte gets not corrected and
- * the instruction will fail. The PutJmp function will add a linker assertion
- * to check for this case and is otherwise identical to PutAll.
- */
+** a bug: If the address crosses a page, the upper byte gets not corrected and
+** the instruction will fail. The PutJmp function will add a linker assertion
+** to check for this case and is otherwise identical to PutAll.
+*/
{
EffAddr A;
if (A.AddrModeBit & AM65_ABS_IND) {
/* Compare the low byte of the expression to 0xFF to check for
- * a page cross. Be sure to use a copy of the expression otherwise
- * things will go weird later.
- */
+ ** a page cross. Be sure to use a copy of the expression otherwise
+ ** things will go weird later.
+ */
ExprNode* E = GenNE (GenByteExpr (CloneExpr (A.Expr)), 0xFF);
/* Generate the message */
static void PutRTS (const InsDesc* Ins attribute ((unused)))
/* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if
- * the enclosing scope is FAR.
- */
+** the enclosing scope is FAR.
+*/
{
if (SmartMode && CurrentScope->AddrSize == ADDR_SIZE_FAR) {
Emit0 (0x6B); /* RTL */
GetSweet16EA (&A);
/* From the possible addressing modes, remove the ones that are invalid
- * for this instruction or CPU.
- */
+ ** for this instruction or CPU.
+ */
A.AddrModeSet &= Ins->AddrMode;
/* Check if we have any adressing modes left */
int FindInstruction (const StrBuf* Ident)
/* Check if Ident is a valid mnemonic. If so, return the index in the
- * instruction table. If not, return -1.
- */
+** instruction table. If not, return -1.
+*/
{
unsigned I;
const InsDesc* ID;
char Key[sizeof (ID->Mnemonic)];
/* Shortcut for the "none" CPU: If there are no instructions to search
- * for, bail out early.
- */
+ ** for, bail out early.
+ */
if (InsTab->Count == 0) {
/* Not found */
return -1;
I = 0;
while (I < SB_GetLen (Ident)) {
/* If the identifier is longer than the longest mnemonic, it cannot
- * be one.
- */
+ ** be one.
+ */
if (I >= sizeof (Key) - 1) {
/* Not found, no need for further action */
return -1;
/* Constants for the addressing mode. If an opcode is available in zero page
- * and absolut adressing mode, both bits are set. When checking for valid
- * modes, the zeropage bit is checked first. Similar, the implicit bit is set
- * on accu adressing modes, so the 'A' for accu adressing is not needed (but
- * may be specified).
- * When assembling for the 6502 or 65C02, all addressing modes that are not
- * available on these CPUs are removed before doing any checks.
- */
+** and absolut adressing mode, both bits are set. When checking for valid
+** modes, the zeropage bit is checked first. Similar, the implicit bit is set
+** on accu adressing modes, so the 'A' for accu adressing is not needed (but
+** may be specified).
+** When assembling for the 6502 or 65C02, all addressing modes that are not
+** available on these CPUs are removed before doing any checks.
+*/
#define AM65_IMPLICIT 0x00000003UL
#define AM65_ACCU 0x00000002UL
#define AM65_DIR 0x00000004UL
int FindInstruction (const StrBuf* Ident);
/* Check if Ident is a valid mnemonic. If so, return the index in the
- * instruction table. If not, return -1.
- */
+** instruction table. If not, return -1.
+*/
void HandleInstruction (unsigned Index);
/* Handle the mnemonic with the given index */
/* */
/* */
/* (C) 2000-2003 Ullrich von Bassewitz */
-/* Römerstraße 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
int InputFromStack (void)
/* Try to get input from the input stack. Return true if we had such input,
- * return false otherwise.
- */
+** return false otherwise.
+*/
{
/* Repeatedly call the TOS routine until we have a token or if run out of
- * routines.
- */
+ ** routines.
+ */
while (IStack) {
if (IStack->Func (IStack->Data) != 0) {
/* We have a token */
void CheckInputStack (void)
/* Called from the scanner before closing an input file. Will check for any
- * stuff on the input stack.
- */
+** stuff on the input stack.
+*/
{
if (IStack) {
Error ("Open %s", IStack->Desc);
int InputFromStack (void);
/* Try to get input from the input stack. Return true if we had such input,
- * return false otherwise.
- */
+** return false otherwise.
+*/
int HavePushedInput (void);
/* Return true if we have stacked input available, return false if not */
void CheckInputStack (void);
/* Called from the scanner before closing an input file. Will check for any
- * stuff on the input stack.
- */
+** stuff on the input stack.
+*/
static int HT_Compare (const void* Key1, const void* Key2);
/* Compare two keys. The function must return a value less than zero if
- * Key1 is smaller than Key2, zero if both are equal, and a value greater
- * than zero if Key1 is greater then Key2.
- */
+** Key1 is smaller than Key2, zero if both are equal, and a value greater
+** than zero if Key1 is greater then Key2.
+*/
static int HT_Compare (const void* Key1, const void* Key2)
/* Compare two keys. The function must return a value less than zero if
- * Key1 is smaller than Key2, zero if both are equal, and a value greater
- * than zero if Key1 is greater then Key2.
- */
+** Key1 is smaller than Key2, zero if both are equal, and a value greater
+** than zero if Key1 is greater then Key2.
+*/
{
/* Convert both parameters to FileInfoKey pointers */
const LineInfoKey* K1 = Key1;
CollGrow (&LineInfoList, 200);
/* Create a LineInfo for the default source. This is necessary to allow
- * error message to be generated without any input file open.
- */
+ ** error message to be generated without any input file open.
+ */
AsmLineInfo = StartLine (&DefaultPos, LI_TYPE_ASM, 0);
}
}
/* Walk over the entries in the hash table and sort them into used and
- * unused ones. Add the used ones to the line info list and assign them
- * an id.
- */
+ ** unused ones. Add the used ones to the line info list and assign them
+ ** an id.
+ */
HT_Walk (&LineInfoTab, CheckLineInfo, 0);
}
CloseSpanList (&LI->OpenSpans);
/* Move the spans to the list of all spans for this line, then clear the
- * list of open spans.
- */
+ ** list of open spans.
+ */
CollTransfer (&LI->Spans, &LI->OpenSpans);
CollDeleteAll (&LI->OpenSpans);
/* Line info is no longer active - remove it from the list of current
- * line infos.
- */
+ ** line infos.
+ */
CollDeleteItem (&CurLineInfo, LI);
}
Key.Type = LI_MAKE_TYPE (Type, Count);
/* Try to find a line info with this position and type in the hash table.
- * If so, reuse it. Otherwise create a new one.
- */
+ ** If so, reuse it. Otherwise create a new one.
+ */
LI = HT_Find (&LineInfoTab, &Key);
if (LI == 0) {
/* Allocate a new LineInfo */
void NewAsmLine (void)
/* Start a new assembler input line. Use this function when generating new
- * line of LI_TYPE_ASM. It will check if line and/or file have actually
- * changed, end the old and start the new line as necessary.
- */
+** line of LI_TYPE_ASM. It will check if line and/or file have actually
+** changed, end the old and start the new line as necessary.
+*/
{
/* Check if we can reuse the old line */
if (AsmLineInfo) {
LineInfo* GetAsmLineInfo (void)
/* Return the line info for the current assembler file. The function will
- * bump the reference counter before returning the line info.
- */
+** bump the reference counter before returning the line info.
+*/
{
++AsmLineInfo->RefCount;
return AsmLineInfo;
void GetFullLineInfo (Collection* LineInfos)
/* Return full line infos, that is line infos for currently active Slots. The
- * infos will be added to the given collection, existing entries will be left
- * intact. The reference count of all added entries will be increased.
- */
+** infos will be added to the given collection, existing entries will be left
+** intact. The reference count of all added entries will be increased.
+*/
{
unsigned I;
void ReleaseFullLineInfo (Collection* LineInfos)
/* Decrease the reference count for a collection full of LineInfos, then clear
- * the collection.
- */
+** the collection.
+*/
{
unsigned I;
void NewAsmLine (void);
/* Start a new assembler input line. Use this function when generating new
- * line of LI_TYPE_ASM. It will check if line and/or file have actually
- * changed, end the old and start the new line as necessary.
- */
+** line of LI_TYPE_ASM. It will check if line and/or file have actually
+** changed, end the old and start the new line as necessary.
+*/
LineInfo* GetAsmLineInfo (void);
/* Return the line info for the current assembler file. The function will
- * bump the reference counter before returning the line info.
- */
+** bump the reference counter before returning the line info.
+*/
void ReleaseLineInfo (LineInfo* LI);
/* Decrease the reference count for a line info */
void GetFullLineInfo (Collection* LineInfos);
/* Return full line infos, that is line infos for currently active Slots. The
- * infos will be added to the given collection, existing entries will be left
- * intact. The reference count of all added entries will be increased.
- */
+** infos will be added to the given collection, existing entries will be left
+** intact. The reference count of all added entries will be increased.
+*/
void ReleaseFullLineInfo (Collection* LineInfos);
/* Decrease the reference count for a collection full of LineInfos, then clear
- * the collection.
- */
+** the collection.
+*/
const FilePos* GetSourcePos (const LineInfo* LI);
/* Return the source file position from the given line info */
{
if (SB_GetLen (&ListingName) > 0) {
/* If we're about to enable the listing, do this for the current line
- * also, so we will see the source line that did this.
- */
+ ** also, so we will see the source line that did this.
+ */
if (ListingEnabled++ == 0) {
LineCur->Output = 1;
}
{
if (SB_GetLen (&ListingName) > 0) {
/* Make the last loaded line the current line */
- /* ###### This code is a hack! We really need to do it right
- * as soon as we know, how:-(
- */
+ /* ###### This code is a hack! We really need to do it right --
+ ** as soon as we know how. :-(
+ */
if (LineCur && LineCur->Next && LineCur->Next != LineLast) {
ListLine* L = LineCur;
do {
static void PrintPageHeader (FILE* F, const ListLine* L)
/* Print the header for a new page. It is assumed that the given line is the
- * last line of the previous page.
- */
+** last line of the previous page.
+*/
{
/* Gte a pointer to the current input file */
const StrBuf* CurFile = GetFileName (L->File);
++PageLines;
/* Switch to a new page if needed. Do not switch, if the current line is
- * the last one, to avoid pages that consist of just the header.
- */
+ ** the last one, to avoid pages that consist of just the header.
+ */
if (PageLength > 0 && PageLines >= PageLength && L->Next != 0) {
/* Do a formfeed */
putc ('\f', F);
}
/* Output the data. The format of a listing line is:
- *
- * PPPPPPm I 11 22 33 44
- *
- * where
- *
- * PPPPPP is the PC
- * m is the mode ('r' or empty)
- * I is the include level
- * 11 .. are code or data bytes
- */
+ **
+ ** PPPPPPm I 11 22 33 44
+ **
+ ** where
+ **
+ ** PPPPPP is the PC
+ ** m is the mode ('r' or empty)
+ ** I is the include level
+ ** 11 .. are code or data bytes
+ */
Line = L->Line;
B = Buf;
while (Count) {
Count -= Chunk;
/* Increment the program counter. Since we don't need the PC stored
- * in the LineList object for anything else, just increment this
- * variable.
- */
+ ** in the LineList object for anything else, just increment this
+ ** variable.
+ */
L->PC += Chunk;
/* Copy the bytes into the line */
static int HT_Compare (const void* Key1, const void* Key2);
/* Compare two keys. The function must return a value less than zero if
- * Key1 is smaller than Key2, zero if both are equal, and a value greater
- * than zero if Key1 is greater then Key2.
- */
+** Key1 is smaller than Key2, zero if both are equal, and a value greater
+** than zero if Key1 is greater then Key2.
+*/
static int HT_Compare (const void* Key1, const void* Key2)
/* Compare two keys. The function must return a value less than zero if
- * Key1 is smaller than Key2, zero if both are equal, and a value greater
- * than zero if Key1 is greater then Key2.
- */
+** Key1 is smaller than Key2, zero if both are equal, and a value greater
+** than zero if Key1 is greater then Key2.
+*/
{
return SB_Compare (Key1, Key2);
}
return;
} else if (!UbiquitousIdents && FindInstruction (&CurTok.SVal) >= 0) {
/* The identifier is a name of a 6502 instruction, which is not
- * allowed if not explicitly enabled.
- */
+ ** allowed if not explicitly enabled.
+ */
Error ("Cannot use an instruction as macro name");
MacSkipDef (Style);
return;
NextTok ();
/* If we have a DEFINE style macro, we may have parameters in braces,
- * otherwise we may have parameters without braces.
- */
+ ** otherwise we may have parameters without braces.
+ */
if (Style == MAC_STYLE_CLASSIC) {
HaveParams = 1;
} else {
}
/* For class macros, we expect a separator token, for define style macros,
- * we expect the closing paren.
- */
+ ** we expect the closing paren.
+ */
if (Style == MAC_STYLE_CLASSIC) {
ConsumeSep ();
} else if (HaveParams) {
}
/* Preparse the macro body. We will read the tokens until we reach end of
- * file, or a .endmacro (or end of line for DEFINE style macros) and store
- * them into an token list internal to the macro. For classic macros, there
- * the .LOCAL command is detected and removed at this time.
- */
+ ** file, or a .endmacro (or end of line for DEFINE style macros) and store
+ ** them into an token list internal to the macro. For classic macros, there
+ ** the .LOCAL command is detected and removed at this time.
+ */
while (1) {
/* Check for end of macro */
void MacUndef (const StrBuf* Name, unsigned char Style)
/* Undefine the macro with the given name and style. A style mismatch is
- * treated as if the macro didn't exist.
- */
+** treated as if the macro didn't exist.
+*/
{
/* Search for the macro */
Macro* M = HT_Find (&MacroTab, Name);
static int MacExpand (void* Data)
/* If we're currently expanding a macro, set the the scanner token and
- * attribute to the next value and return true. If we are not expanding
- * a macro, return false.
- */
+** attribute to the next value and return true. If we are not expanding
+** a macro, return false.
+*/
{
/* Cast the Data pointer to the actual data structure */
MacExp* Mac = (MacExp*) Data;
}
/* We're expanding a macro. Check if we are expanding one of the
- * macro parameters.
- */
+ ** macro parameters.
+ */
ExpandParam:
if (Mac->ParamExp) {
}
/* We're not expanding macro parameters. Check if we have tokens left from
- * the macro itself.
- */
+ ** the macro itself.
+ */
if (Mac->Exp) {
/* Use next macro token */
while (I) {
if (SB_Compare (&CurTok.SVal, &I->Id) == 0) {
/* This is in fact a local symbol, change the name. Be sure
- * to generate a local label name if the original name was
- * a local label, and also generate a name that cannot be
- * generated by a user.
- */
+ ** to generate a local label name if the original name was
+ ** a local label, and also generate a name that cannot be
+ ** generated by a user.
+ */
if (SB_At (&I->Id, 0) == LocalStart) {
/* Must generate a local symbol */
SB_Printf (&CurTok.SVal, "%cLOCAL-MACRO_SYMBOL-%04X",
Mac->Final = 0;
/* Problem: When a .define style macro is expanded within the call
- * of a classic one, the latter may be terminated and removed while
- * the expansion of the .define style macro is still active. Because
- * line info slots are "stacked", this runs into a CHECK FAILED. For
- * now, we will fix that by removing the .define style macro expansion
- * immediately, once the final token is placed. The better solution
- * would probably be to not require AllocLineInfoSlot/FreeLineInfoSlot
- * to be called in FIFO order, but this is a bigger change.
- */
+ ** of a classic one, the latter may be terminated and removed while
+ ** the expansion of the .define style macro is still active. Because
+ ** line info slots are "stacked", this runs into a CHECK FAILED. For
+ ** now, we will fix that by removing the .define style macro expansion
+ ** immediately, once the final token is placed. The better solution
+ ** would probably be to not require AllocLineInfoSlot/FreeLineInfoSlot
+ ** to be called in FIFO order, but this is a bigger change.
+ */
/* End of macro expansion and pop the input function */
FreeMacExp (Mac);
PopInput ();
++E->ParamCount;
/* If the macro argument was enclosed in curly braces, end-of-line
- * is an error. Skip the closing curly brace.
- */
+ ** is an error. Skip the closing curly brace.
+ */
if (Term == TOK_RCURLY) {
if (CurTok.Tok == TOK_SEP) {
Error ("End of line encountered within macro argument");
/* Start expanding a DEFINE style macro */
{
/* A define style macro must be called with as many actual parameters
- * as there are formal ones. Get the parameter count.
- */
+ ** as there are formal ones. Get the parameter count.
+ */
unsigned Count = E->M->ParamCount;
/* Skip the current token */
++E->ParamCount;
/* If the macro argument was enclosed in curly braces, end-of-line
- * is an error. Skip the closing curly brace.
- */
+ ** is an error. Skip the closing curly brace.
+ */
if (Term == TOK_RCURLY) {
if (TokIsSep (CurTok.Tok)) {
Error ("End of line encountered within macro argument");
}
/* Macro expansion will overwrite the current token. This is a problem
- * for define style macros since these are called from the scanner level.
- * To avoid it, remember the current token and re-insert it, once macro
- * expansion is done.
- */
+ ** for define style macros since these are called from the scanner level.
+ ** To avoid it, remember the current token and re-insert it, once macro
+ ** expansion is done.
+ */
E->Final = NewTokNode ();
/* Insert a new token input function */
}
/* Don't allow too many nested macro expansions - otherwise it is possible
- * to force an endless loop and assembler crash.
- */
+ ** to force an endless loop and assembler crash.
+ */
if (MacExpansions >= MAX_MACEXPANSIONS) {
Error ("Too many nested macro expansions");
return;
Macro* FindMacro (const StrBuf* Name)
/* Try to find the macro with the given name and return it. If no macro with
- * this name was found, return NULL.
- */
+** this name was found, return NULL.
+*/
{
Macro* M = HT_Find (&MacroTab, Name);
return (M != 0 && M->Style == MAC_STYLE_CLASSIC)? M : 0;
Macro* FindDefine (const StrBuf* Name)
/* Try to find the define style macro with the given name and return it. If no
- * such macro was found, return NULL.
- */
+** such macro was found, return NULL.
+*/
{
Macro* M;
void EnableDefineStyleMacros (void)
/* Re-enable define style macros previously disabled with
- * DisableDefineStyleMacros.
- */
+** DisableDefineStyleMacros.
+*/
{
PRECONDITION (DisableDefines > 0);
--DisableDefines;
void MacUndef (const struct StrBuf* Name, unsigned char Style);
/* Undefine the macro with the given name and style. A style mismatch is
- * treated as if the macro didn't exist.
- */
+** treated as if the macro didn't exist.
+*/
void MacExpandStart (Macro* M);
/* Start expanding a macro */
Macro* FindMacro (const struct StrBuf* Name);
/* Try to find the macro with the given name and return it. If no macro with
- * this name was found, return NULL.
- */
+** this name was found, return NULL.
+*/
Macro* FindDefine (const struct StrBuf* Name);
/* Try to find the define style macro with the given name and return it. If no
- * such macro was found, return NULL.
- */
+** such macro was found, return NULL.
+*/
int InMacExpansion (void);
/* Return true if we're currently expanding a macro */
void EnableDefineStyleMacros (void);
/* Re-enable define style macros previously disabled with
- * DisableDefineStyleMacros.
- */
+** DisableDefineStyleMacros.
+*/
/* Create a listing file */
{
/* Since the meaning of -l and --listing has changed, print an error if
- * the filename is empty or begins with the option char.
- */
+ ** the filename is empty or begins with the option char.
+ */
if (Arg == 0 || *Arg == '\0' || *Arg == '-') {
Fatal ("The meaning of `%s' has changed. It does now "
"expect a file name as argument.", Opt);
int Instr = -1;
/* Initialize the new listing line if we are actually reading from file
- * and not from internally pushed input.
- */
+ ** and not from internally pushed input.
+ */
if (!HavePushedInput ()) {
InitListingLine ();
}
}
/* If the first token on the line is an identifier, check for a macro or
- * an instruction.
- */
+ ** an instruction.
+ */
if (CurTok.Tok == TOK_IDENT) {
if (UbiquitousIdents) {
/* Macros CAN be instructions, so check for them first */
}
/* Handle an identifier. This may be a cheap local symbol, or a fully
- * scoped identifier which may start with a namespace token (for global
- * namespace)
- */
+ ** scoped identifier which may start with a namespace token (for global
+ ** namespace)
+ */
if (CurTok.Tok == TOK_LOCAL_IDENT ||
CurTok.Tok == TOK_NAMESPACE ||
(CurTok.Tok == TOK_IDENT && Instr < 0 && Mac == 0)) {
Sym = ParseAnySymName (SYM_ALLOC_NEW);
/* If a colon follows, this is a label definition. If there
- * is no colon, it's an assignment.
- */
+ ** is no colon, it's an assignment.
+ */
if (CurTok.Tok == TOK_EQ || CurTok.Tok == TOK_ASSIGN) {
/* Determine the symbol flags from the assignment token */
Expr = GenLiteralExpr (ConstExpression ());
/* Define the symbol with the constant expression following
- * the '='
- */
+ ** the '='
+ */
SymDef (Sym, Expr, ADDR_SIZE_DEFAULT, SF_VAR);
/* Don't allow anything after a symbol definition */
} else {
/* A label. Remember the current segment, so we can later
- * determine the size of the data stored under the label.
- */
+ ** determine the size of the data stored under the label.
+ */
Seg = ActiveSeg;
PC = GetPC ();
SymDef (Sym, GenCurrentPC (), ADDR_SIZE_DEFAULT, SF_LABEL);
/* Skip the colon. If NoColonLabels is enabled, allow labels
- * without a colon if there is no whitespace before the
- * identifier.
- */
+ ** without a colon if there is no whitespace before the
+ ** identifier.
+ */
if (CurTok.Tok != TOK_COLON) {
if (HadWS || !NoColonLabels) {
Error ("`:' expected");
}
/* If we come here, a new identifier may be waiting, which may
- * be a macro or instruction.
- */
+ ** be a macro or instruction.
+ */
if (CurTok.Tok == TOK_IDENT) {
if (UbiquitousIdents) {
/* Macros CAN be instructions, so check for them first */
}
/* If we have defined a label, remember its size. Sym is also set by
- * a symbol assignment, but in this case Done is false, so we don't
- * come here.
- */
+ ** a symbol assignment, but in this case Done is false, so we don't
+ ** come here.
+ */
if (Sym) {
unsigned long Size;
if (Seg == ActiveSeg) {
SegInit ();
/* Enter the base lexical level. We must do that here, since we may
- * define symbols using -D.
- */
+ ** define symbols using -D.
+ */
SymEnterLevel (&GlobalNameSpace, SCOPE_FILE, ADDR_SIZE_DEFAULT, 0);
/* Initialize the line infos. Must be done here, since we need line infos
- * for symbol definitions.
- */
+ ** for symbol definitions.
+ */
InitLineInfo ();
/* Check the parameters */
DoneLineInfo ();
/* If we didn't have any errors, create the object, listing and
- * dependency files
- */
+ ** dependency files
+ */
if (ErrorCount == 0) {
CreateObjFile ();
if (SB_GetLen (&ListingName) > 0) {
static int LookAtStrCon (void)
/* Make sure the next token is a string constant. If not, print an error
- * messages skip the remainder of the line and return false. Otherwise return
- * true.
- */
+** messages skip the remainder of the line and return false. Otherwise return
+** true.
+*/
{
if (CurTok.Tok != TOK_STRCON) {
Error ("String constant expected");
static TokList* CollectTokens (unsigned Start, unsigned Count)
/* Read a list of tokens that is optionally enclosed in curly braces and
- * terminated by a right paren. For all tokens starting at the one with index
- * Start, and ending at (Start+Count-1), place them into a token list, and
- * return this token list.
- */
+** terminated by a right paren. For all tokens starting at the one with index
+** Start, and ending at (Start+Count-1), place them into a token list, and
+** return this token list.
+*/
{
/* Create the token list */
}
/* We expect a closing parenthesis, but will not skip it but replace it
- * by the string token just created.
- */
+ ** by the string token just created.
+ */
if (CurTok.Tok != TOK_RPAREN) {
Error ("`)' expected");
} else {
}
/* Check that the string contains a valid identifier. While doing so,
- * determine if it is a cheap local, or global one.
- */
+ ** determine if it is a cheap local, or global one.
+ */
SB_Reset (&CurTok.SVal);
/* Check for a cheap local symbol */
}
/* If anything is ok, save and skip the string. Check that the next token
- * is a right paren, then replace the token by an identifier token.
- */
+ ** is a right paren, then replace the token by an identifier token.
+ */
SB_Copy (&Buf, &CurTok.SVal);
NextTok ();
if (CurTok.Tok != TOK_RPAREN) {
List = CollectTokens (0, (unsigned) Count);
/* Since we want to insert the list before the now current token, we have
- * to save the current token in some way and then skip it. To do this, we
- * will add the current token at the end of the token list (so the list
- * will never be empty), push the token list, and then skip the current
- * token. This will replace the current token by the first token from the
- * list (which will be the old current token in case the list was empty).
- */
+ ** to save the current token in some way and then skip it. To do this, we
+ ** will add the current token at the end of the token list (so the list
+ ** will never be empty), push the token list, and then skip the current
+ ** token. This will replace the current token by the first token from the
+ ** list (which will be the old current token in case the list was empty).
+ */
AddCurTok (List);
/* Insert it into the scanner feed */
ConsumeLParen ();
/* Start argument. Since the start argument can get negative with
- * expressions like ".tcount(arg)-2", we correct it to zero silently.
- */
+ ** expressions like ".tcount(arg)-2", we correct it to zero silently.
+ */
Start = ConstExpression ();
if (Start < 0 || Start > 100) {
Start = 0;
ConsumeComma ();
/* Count argument. Similar as above, we will accept negative counts and
- * correct them to zero silently.
- */
+ ** correct them to zero silently.
+ */
Count = ConstExpression ();
if (Count < 0) {
Count = 0;
List = CollectTokens ((unsigned) Start, (unsigned) Count);
/* Since we want to insert the list before the now current token, we have
- * to save the current token in some way and then skip it. To do this, we
- * will add the current token at the end of the token list (so the list
- * will never be empty), push the token list, and then skip the current
- * token. This will replace the current token by the first token from the
- * list (which will be the old current token in case the list was empty).
- */
+ ** to save the current token in some way and then skip it. To do this, we
+ ** will add the current token at the end of the token list (so the list
+ ** will never be empty), push the token list, and then skip the current
+ ** token. This will replace the current token by the first token from the
+ ** list (which will be the old current token in case the list was empty).
+ */
AddCurTok (List);
/* Insert it into the scanner feed */
}
/* Since we want to insert the list before the now current token, we have
- * to save the current token in some way and then skip it. To do this, we
- * will add the current token at the end of the token list (so the list
- * will never be empty), push the token list, and then skip the current
- * token. This will replace the current token by the first token from the
- * list (which will be the old current token in case the list was empty).
- */
+ ** to save the current token in some way and then skip it. To do this, we
+ ** will add the current token at the end of the token list (so the list
+ ** will never be empty), push the token list, and then skip the current
+ ** token. This will replace the current token by the first token from the
+ ** list (which will be the old current token in case the list was empty).
+ */
AddCurTok (List);
/* Insert it into the scanner feed */
break;
}
- /* Since a format specifier follows, we do expect anotehr argument for
- * the .sprintf function.
- */
+ /* Since a format specifier follows, we do expect another argument for
+ ** the .sprintf function.
+ */
ConsumeComma ();
/* We will copy the format spec into F1 checking for the things we
- * support, and later use xsprintf to do the actual formatting. This
- * is easier than adding another printf implementation...
- */
+ ** support, and later use xsprintf to do the actual formatting. This
+ ** is easier than adding another printf implementation...
+ */
SB_Clear (&F1);
SB_AppendChar (&F1, '%');
case 'X':
case 'x':
/* Our ints are actually longs, so we use the 'l' modifier when
- * calling xsprintf later. Terminate the format string.
- */
+ ** calling xsprintf later. Terminate the format string.
+ */
SB_AppendChar (&F1, 'l');
SB_AppendChar (&F1, SB_Get (&Format));
SB_Terminate (&F1);
}
/* Format this argument according to the spec. Be sure to pass
- * an int as the char value.
- */
+ ** an int as the char value.
+ */
SB_Printf (&R1, SB_GetConstBuf (&F1), (int) IVal);
/* Append the formatted argument to the result */
SB_Terminate (&R);
/* We expect a closing parenthesis, but will not skip it but replace it
- * by the string token just created.
- */
+ ** by the string token just created.
+ */
if (CurTok.Tok != TOK_RPAREN) {
Error ("`)' expected");
} else {
} else if (CurTok.Tok == TOK_NAMESPACE || CurTok.Tok == TOK_IDENT) {
/* Parse a fully qualified symbol name. We cannot use
- * ParseScopedSymName here since the name may be invalid.
- */
+ ** ParseScopedSymName here since the name may be invalid.
+ */
int NameSpace;
do {
NameSpace = (CurTok.Tok == TOK_NAMESPACE);
}
/* We expect a closing parenthesis, but will not skip it but replace it
- * by the string token just created.
- */
+ ** by the string token just created.
+ */
if (CurTok.Tok != TOK_RPAREN) {
Error ("`)' expected");
} else {
NextRawTok ();
/* In raw mode, or when output is suppressed via conditional assembly,
- * pass the token unchanged.
- */
+ ** pass the token unchanged.
+ */
if (RawMode == 0 && IfCond) {
/* Execute token handling functions */
void ExpectSep (void)
/* Check if we've reached a line separator, and output an error if not. Do
- * not skip the line separator.
- */
+** not skip the line separator.
+*/
{
if (!TokIsSep (CurTok.Tok)) {
ErrorSkip ("Unexpected trailing garbage characters");
void EnterRawTokenMode (void)
/* Enter raw token mode. In raw mode, token handling functions are not
- * executed, but the function tokens are passed untouched to the upper
- * layer. Raw token mode is used when storing macro tokens for later
- * use.
- * Calls to EnterRawTokenMode and LeaveRawTokenMode may be nested.
- */
+** executed, but the function tokens are passed untouched to the upper
+** layer. Raw token mode is used when storing macro tokens for later
+** use.
+** Calls to EnterRawTokenMode and LeaveRawTokenMode may be nested.
+*/
{
++RawMode;
}
void ExpectSep (void);
/* Check if we've reached a line separator, and output an error if not. Do
- * not skip the line separator.
- */
+** not skip the line separator.
+*/
void EnterRawTokenMode (void);
/* Enter raw token mode. In raw mode, token handling functions are not
- * executed, but the function tokens are passed untouched to the upper
- * layer. Raw token mode is used when storing macro tokens for later
- * use.
- * Calls to EnterRawTokenMode and LeaveRawTokenMode may be nested.
- */
+** executed, but the function tokens are passed untouched to the upper
+** layer. Raw token mode is used when storing macro tokens for later
+** use.
+** Calls to EnterRawTokenMode and LeaveRawTokenMode may be nested.
+*/
void LeaveRawTokenMode (void);
/* Leave raw token mode. */
static void ObjWriteError (void)
/* Called on a write error. Will try to close and remove the file, then
- * print a fatal error.
- */
+** print a fatal error.
+*/
{
/* Remember the error */
int Error = errno;
/* Do we have a name for the output file? */
if (OutFile == 0) {
/* We don't have an output name explicitly given, construct one from
- * the name of the input file.
- */
+ ** the name of the input file.
+ */
OutFile = MakeFilename (InFile, OBJ_EXT);
}
/* Write a variable sized value to the file in special encoding */
{
/* We will write the value to the file in 7 bit chunks. If the 8th bit
- * is clear, we're done, if it is set, another chunk follows. This will
- * allow us to encode smaller values with less bytes, at the expense of
- * needing 5 bytes if a 32 bit value is written to file.
- */
+ ** is clear, we're done, if it is set, another chunk follows. This will
+ ** allow us to encode smaller values with less bytes, at the expense of
+ ** needing 5 bytes if a 32 bit value is written to file.
+ */
do {
unsigned char C = (V & 0x7F);
V >>= 7;
unsigned Len = strlen (S);
/* Write the string with the length preceeded (this is easier for
- * the reading routine than the C format since the length is known in
- * advance).
- */
+ ** the reading routine than the C format since the length is known in
+ ** advance).
+ */
ObjWriteVar (Len);
ObjWriteData (S, Len);
}
/* Write a string to the object file */
{
/* Write the string with the length preceeded (this is easier for
- * the reading routine than the C format since the length is known in
- * advance).
- */
+ ** the reading routine than the C format since the length is known in
+ ** advance).
+ */
ObjWriteVar (SB_GetLen (S));
ObjWriteData (SB_GetConstBuf (S), SB_GetLen (S));
}
static void DoInvalid (void);
/* Handle a token that is invalid here, since it should have been handled on
- * a much lower level of the expression hierarchy. Getting this sort of token
- * means that the lower level code has bugs.
- * This function differs to DoUnexpected in that the latter may be triggered
- * by the user by using keywords in the wrong location. DoUnexpected is not
- * an error in the assembler itself, while DoInvalid is.
- */
+** a much lower level of the expression hierarchy. Getting this sort of token
+** means that the lower level code has bugs.
+** This function differs to DoUnexpected in that the latter may be triggered
+** by the user by using keywords in the wrong location. DoUnexpected is not
+** an error in the assembler itself, while DoInvalid is.
+*/
static unsigned char OptionalAddrSize (void)
/* If a colon follows, parse an optional address size spec and return it.
- * Otherwise return ADDR_SIZE_DEFAULT.
- */
+** Otherwise return ADDR_SIZE_DEFAULT.
+*/
{
unsigned AddrSize = ADDR_SIZE_DEFAULT;
if (CurTok.Tok == TOK_COLON) {
/* Allow to assign the value of an export in an .export statement */
{
/* The name and optional address size spec may be followed by an assignment
- * or equal token.
- */
+ ** or equal token.
+ */
if (CurTok.Tok == TOK_ASSIGN || CurTok.Tok == TOK_EQ) {
/* Assignment means the symbol is a label */
static long IntArg (long Min, long Max)
/* Read an integer argument and check a range. Accept the token "unlimited"
- * and return -1 in this case.
- */
+** and return -1 in this case.
+*/
{
if (CurTok.Tok == TOK_IDENT && SB_CompareStr (&CurTok.SVal, "unlimited") == 0) {
NextTok ();
const char* ElementType,
unsigned ElementTypeLen)
/* Create an array (or single data) of the given type. SpanSize is the size
- * of the span, ElementType is a string that encodes the element data type.
- * The function returns Type.
- */
+** of the span, ElementType is a string that encodes the element data type.
+** The function returns Type.
+*/
{
/* Get the size of the element type */
unsigned ElementSize = GT_GET_SIZE (ElementType[0]);
NextTok ();
/* We can have an optional message. If no message is present, use
- * "Assertion failed".
- */
+ ** "Assertion failed".
+ */
if (CurTok.Tok == TOK_COMMA) {
/* Skip the comma */
}
/* Translate the message into a string id. We can then skip the input
- * string.
- */
+ ** string.
+ */
Msg = GetStrBufId (&CurTok.SVal);
NextTok ();
fseek (F, 0, SEEK_END);
Size = ftell (F);
- /* Stat the file and remember the values. There a race condition here,
- * since we cannot use fileno() (non standard identifier in standard
- * header file), and therefore not fstat. When using stat with the
- * file name, there's a risk that the file was deleted and recreated
- * while it was open. Since mtime and size are only used to check
- * if a file has changed in the debugger, we will ignore this problem
- * here.
- */
+ /* Stat the file and remember the values. There's a race condition here,
+ ** since we cannot use fileno() (non-standard identifier in standard
+ ** header file), and therefore not fstat. When using stat with the
+ ** file name, there's a risk that the file was deleted and recreated
+ ** while it was open. Since mtime and size are only used to check
+ ** if a file has changed in the debugger, we will ignore this problem
+ ** here.
+ */
SB_Terminate (&Name);
if (FileStat (SB_GetConstBuf (&Name), &StatBuf) != 0) {
Fatal ("Cannot stat input file `%m%p': %s", &Name, strerror (errno));
static void DoInvalid (void)
/* Handle a token that is invalid here, since it should have been handled on
- * a much lower level of the expression hierarchy. Getting this sort of token
- * means that the lower level code has bugs.
- * This function differs to DoUnexpected in that the latter may be triggered
- * by the user by using keywords in the wrong location. DoUnexpected is not
- * an error in the assembler itself, while DoInvalid is.
- */
+** a much lower level of the expression hierarchy. Getting this sort of token
+** means that the lower level code has bugs.
+** This function differs to DoUnexpected in that the latter may be triggered
+** by the user by using keywords in the wrong location. DoUnexpected is not
+** an error in the assembler itself, while DoInvalid is.
+*/
{
Internal ("Unexpected token: %m%p", &Keyword);
}
ErrorSkip ("String constant expected");
} else {
/* Output the string and be sure to flush the output to keep it in
- * sync with any error messages if the output is redirected to a file.
- */
+ ** sync with any error messages if the output is redirected to a file.
+ */
printf ("%.*s\n",
(int) SB_GetLen (&CurTok.SVal),
SB_GetConstBuf (&CurTok.SVal));
SetCPU (CPU);
/* Skip the identifier. If the CPU switch was successful, the scanner
- * will treat the input now correctly for the new CPU.
- */
+ ** will treat the input now correctly for the new CPU.
+ */
NextTok ();
}
}
/* Undefine a define style macro */
{
/* The function is called with the .UNDEF token in place, because we need
- * to disable .define macro expansions before reading the next token.
- * Otherwise the name of the macro would be expanded, so we would never
- * see it.
- */
+ ** to disable .define macro expansions before reading the next token.
+ ** Otherwise the name of the macro would be expanded, so we would never
+ ** see it.
+ */
DisableDefineStyleMacros ();
NextTok ();
EnableDefineStyleMacros ();
static TokList* CollectRepeatTokens (void)
/* Collect all tokens inside the .REPEAT body in a token list and return
- * this list. In case of errors, NULL is returned.
- */
+** this list. In case of errors, NULL is returned.
+*/
{
/* Create the token list */
TokList* List = NewTokList ();
static void RepeatTokenCheck (TokList* L)
/* Called each time a token from a repeat token list is set. Is used to check
- * for and replace identifiers that are the repeat counter.
- */
+** for and replace identifiers that are the repeat counter.
+*/
{
if (CurTok.Tok == TOK_IDENT &&
L->Data != 0 &&
List->Check = RepeatTokenCheck;
/* If the list is empty, or repeat count zero, there is nothing
- * to repeat.
- */
+ ** to repeat.
+ */
if (List->Count == 0 || RepCount == 0) {
FreeTokList (List);
goto Done;
S->Func->NextChar (S);
/* Setup the next token so it will be skipped on the next call to
- * NextRawTok().
- */
+ ** NextRawTok().
+ */
CurTok.Tok = TOK_SEP;
}
}
/* No more data - add an empty line to the listing. This
- * is a small hack needed to keep the PC output in sync.
- */
+ ** is a small hack needed to keep the PC output in sync.
+ */
NewListingLine (&EmptyStrBuf, S->V.File.Pos.Name, FCount);
C = EOF;
return;
/* If we come here, we have a new input line. To avoid problems
- * with strange line terminators, remove all whitespace from the
- * end of the line, the add a single newline.
- */
+ ** with strange line terminators, remove all whitespace from the
+ ** end of the line, the add a single newline.
+ */
Len = SB_GetLen (&S->V.File.Line);
while (Len > 0 && IsSpace (SB_AtUnchecked (&S->V.File.Line, Len-1))) {
--Len;
/* Close the current input file */
{
/* We're at the end of an include file. Check if we have any
- * open .IFs, or any open token lists in this file. This
- * enforcement is artificial, using conditionals that start
- * in one file and end in another are uncommon, and don't
- * allowing these things will help finding errors.
- */
+ ** open .IFs, or any open token lists in this file. This
+ ** enforcement is artificial, using conditionals that start
+ ** in one file and end in another are uncommon, and don't
+ ** allowing these things will help finding errors.
+ */
CheckOpenIfs ();
/* If we've added search paths for this file, remove them */
SB_Done (&S->V.File.Line);
/* Close the input file and decrement the file count. We will ignore
- * errors here, since we were just reading from the file.
- */
+ ** errors here, since we were just reading from the file.
+ */
(void) fclose (S->V.File.F);
--FCount;
}
int NewInputFile (const char* Name)
/* Open a new input file. Returns true if the file could be successfully opened
- * and false otherwise.
- */
+** and false otherwise.
+*/
{
int RetCode = 0; /* Return code. Assume an error. */
char* PathName = 0;
/* If this is the main file, just try to open it. If it's an include file,
- * search for it using the include path list.
- */
+ ** search for it using the include path list.
+ */
if (FCount == 0) {
/* Main file */
F = fopen (Name, "r");
}
} else {
/* We are on include level. Search for the file in the include
- * directories.
- */
+ ** directories.
+ */
PathName = SearchFile (IncSearchPath, Name);
if (PathName == 0 || (F = fopen (PathName, "r")) == 0) {
/* Not found or cannot open, print an error and bail out */
Name = PathName;
}
- /* Stat the file and remember the values. There a race condition here,
- * since we cannot use fileno() (non standard identifier in standard
- * header file), and therefore not fstat. When using stat with the
- * file name, there's a risk that the file was deleted and recreated
- * while it was open. Since mtime and size are only used to check
- * if a file has changed in the debugger, we will ignore this problem
- * here.
- */
+ /* Stat the file and remember the values. There's a race condition here,
+ ** since we cannot use fileno() (non-standard identifier in standard
+ ** header file), and therefore not fstat. When using stat with the
+ ** file name, there's a risk that the file was deleted and recreated
+ ** while it was open. Since mtime and size are only used to check
+ ** if a file has changed in the debugger, we will ignore this problem
+ ** here.
+ */
if (FileStat (Name, &Buf) != 0) {
Fatal ("Cannot stat input file `%s': %s", Name, strerror (errno));
}
static token_t FindDotKeyword (void)
/* Find the dot keyword in SVal. Return the corresponding token if found,
- * return TOK_NONE if not found.
- */
+** return TOK_NONE if not found.
+*/
{
struct DotKeyword K;
struct DotKeyword* R;
static void ReadIdent (void)
/* Read an identifier from the current input position into Ident. Filling SVal
- * starts at the current position with the next character in C. It is assumed
- * that any characters already filled in are ok, and the character in C is
- * checked.
- */
+** starts at the current position with the next character in C. It is assumed
+** that any characters already filled in are ok, and the character in C is
+** checked.
+*/
{
/* Read the identifier */
do {
static int Sweet16Reg (const StrBuf* Id)
/* Check if the given identifier is a sweet16 register. Return -1 if this is
- * not the case, return the register number otherwise.
- */
+** not the case, return the register number otherwise.
+*/
{
unsigned RegNum;
char Check;
}
if (IsXDigit (C)) {
/* Buf is big enough to allow any decimal and hex number to
- * overflow, so ignore excess digits here, they will be detected
- * when we convert the value.
- */
+ ** overflow, so ignore excess digits here, they will be detected
+ ** when we convert the value.
+ */
if (Digits < sizeof (Buf)) {
Buf[Digits++] = C;
}
}
/* An identifier with a dot. Check if it's a define style
- * macro.
- */
+ ** macro.
+ */
if ((M = FindDefine (&CurTok.SVal)) != 0) {
/* This is a define style macro - expand it */
MacExpandStart (M);
}
/* Indirect op for sweet16 cpu. Must check this before checking for local
- * symbols, because these may also use the '@' symbol.
- */
+ ** symbols, because these may also use the '@' symbol.
+ */
if (CPU == CPU_SWEET16 && C == '@') {
NextChar ();
CurTok.Tok = TOK_AT;
ReadIdent ();
/* Check for special names. Bail out if we have identified the type of
- * the token. Go on if the token is an identifier.
- */
+ ** the token. Go on if the token is an identifier.
+ */
if (SB_GetLen (&CurTok.SVal) == 1) {
switch (toupper (SB_AtUnchecked (&CurTok.SVal, 0))) {
case '\'':
/* Hack: If we allow ' as terminating character for strings, read
- * the following stuff as a string, and check for a one character
- * string later.
- */
+ ** the following stuff as a string, and check for a one character
+ ** string later.
+ */
if (LooseStringTerm) {
ReadStringConst ('\'');
if (SB_GetLen (&CurTok.SVal) == 1) {
}
/* If we go here, we could not identify the current character. Skip it
- * and try again.
- */
+ ** and try again.
+ */
Error ("Invalid input character: 0x%02X", C & 0xFF);
NextChar ();
goto Again;
int GetSubKey (const char** Keys, unsigned Count)
/* Search for a subkey in a table of keywords. The current token must be an
- * identifier and all keys must be in upper case. The identifier will be
- * uppercased in the process. The function returns the index of the keyword,
- * or -1 if the keyword was not found.
- */
+** identifier and all keys must be in upper case. The identifier will be
+** uppercased in the process. The function returns the index of the keyword,
+** or -1 if the keyword was not found.
+*/
{
unsigned I;
unsigned char ParseAddrSize (void)
/* Check if the next token is a keyword that denotes an address size specifier.
- * If so, return the corresponding address size constant, otherwise output an
- * error message and return ADDR_SIZE_DEFAULT.
- */
+** If so, return the corresponding address size constant, otherwise output an
+** error message and return ADDR_SIZE_DEFAULT.
+*/
{
unsigned char AddrSize;
int NewInputFile (const char* Name);
/* Open a new input file. Returns true if the file could be successfully opened
- * and false otherwise.
- */
+** and false otherwise.
+*/
void NewInputData (char* Text, int Malloced);
/* Add a chunk of input data to the input stream */
int GetSubKey (const char** Keys, unsigned Count);
/* Search for a subkey in a table of keywords. The current token must be an
- * identifier and all keys must be in upper case. The identifier will be
- * uppercased in the process. The function returns the index of the keyword,
- * or -1 if the keyword was not found.
- */
+** identifier and all keys must be in upper case. The identifier will be
+** uppercased in the process. The function returns the index of the keyword,
+** or -1 if the keyword was not found.
+*/
unsigned char ParseAddrSize (void);
/* Check if the next token is a keyword that denotes an address size specifier.
- * If so, return the corresponding address size constant, otherwise output an
- * error message and return ADDR_SIZE_DEFAULT.
- */
+** If so, return the corresponding address size constant, otherwise output an
+** error message and return ADDR_SIZE_DEFAULT.
+*/
void InitScanner (const char* InFile);
/* Initialize the scanner, open the given input file */
/* If OrgPerSeg is false, all segments share the RelocMode flag and a PC
- * used when in absolute mode. OrgPerSeg may be set by .feature org_per_seg
- */
+** used when in absolute mode. OrgPerSeg may be set by .feature org_per_seg
+*/
static int RelocMode = 1;
static unsigned long AbsPC = 0; /* PC if in absolute mode */
static Segment* NewSegFromDef (SegDef* Def)
/* Create a new segment from a segment definition. Used only internally, no
- * checks.
- */
+** checks.
+*/
{
/* Create a new segment */
Segment* S = xmalloc (sizeof (*S));
void EnterAbsoluteMode (unsigned long PC)
/* Enter absolute (non relocatable mode). Depending on the OrgPerSeg flag,
- * this will either switch the mode globally or for the current segment.
- */
+** this will either switch the mode globally or for the current segment.
+*/
{
if (OrgPerSeg) {
/* Relocatable mode is switched per segment */
void EnterRelocMode (void)
/* Enter relocatable mode. Depending on the OrgPerSeg flag, this will either
- * switch the mode globally or for the current segment.
- */
+** switch the mode globally or for the current segment.
+*/
{
if (OrgPerSeg) {
/* Relocatable mode is switched per segment */
void SegAlign (unsigned long Alignment, int FillVal)
/* Align the PC segment to Alignment. If FillVal is -1, emit fill fragments
- * (the actual fill value will be determined by the linker), otherwise use
- * the given value.
- */
+** (the actual fill value will be determined by the linker), otherwise use
+** the given value.
+*/
{
unsigned char Data [4];
unsigned long CombinedAlignment;
unsigned long Count;
/* The segment must have the combined alignment of all separate alignments
- * in the source. Calculate this alignment and check it for sanity.
- */
+ ** in the source. Calculate this alignment and check it for sanity.
+ */
CombinedAlignment = LeastCommonMultiple (ActiveSeg->Align, Alignment);
if (CombinedAlignment > MAX_ALIGNMENT) {
Error ("Combined alignment for active segment is %lu which exceeds %lu",
CombinedAlignment, MAX_ALIGNMENT);
/* Avoid creating large fills for an object file that is thrown away
- * later.
- */
+ ** later.
+ */
Count = 1;
} else {
} else if (RelaxChecks == 0) {
/* We cannot evaluate the expression now, leave the job for
- * the linker. However, we can check if the address size
- * matches the fragment size. Mismatches are errors in
- * most situations.
- */
+ ** the linker. However, we can check if the address size
+ ** matches the fragment size. Mismatches are errors in
+ ** most situations.
+ */
if ((F->Len == 1 && ED.AddrSize > ADDR_SIZE_ZP) ||
(F->Len == 2 && ED.AddrSize > ADDR_SIZE_ABS) ||
(F->Len == 3 && ED.AddrSize > ADDR_SIZE_FAR)) {
/* Set the default segment sizes according to the memory model */
{
/* Initialize segment sizes. The segment definitions do already contain
- * the correct values for the default case (near), so we must only change
- * things that should be different.
- */
+ ** the correct values for the default case (near), so we must only change
+ ** things that should be different.
+ */
switch (MemoryModel) {
case MMODEL_NEAR:
unsigned long EndPos;
/* Remember the file position, then write a dummy for the size of the
- * following data
- */
+ ** following data
+ */
unsigned long SizePos = ObjGetFilePos ();
ObjWrite32 (0);
ObjWriteVar (Seg->FragCount); /* Number of fragments */
/* Now walk through the fragment list for this segment and write the
- * fragments.
- */
+ ** fragments.
+ */
Frag = Seg->Root;
while (Frag) {
void SegAlign (unsigned long Alignment, int FillVal);
/* Align the PC segment to Alignment. If FillVal is -1, emit fill fragments
- * (the actual fill value will be determined by the linker), otherwise use
- * the given value.
- */
+** (the actual fill value will be determined by the linker), otherwise use
+** the given value.
+*/
unsigned char GetSegAddrSize (unsigned SegNum);
/* Return the address size of the segment with the given number */
void EnterAbsoluteMode (unsigned long AbsPC);
/* Enter absolute (non relocatable mode). Depending on the OrgPerSeg flag,
- * this will either switch the mode globally or for the current segment.
- */
+** this will either switch the mode globally or for the current segment.
+*/
void EnterRelocMode (void);
/* Enter relocatable mode. Depending on the OrgPerSeg flag, this will either
- * switch the mode globally or for the current segment.
- */
+** switch the mode globally or for the current segment.
+*/
void SegDone (void);
/* Check the segments for range and other errors. Do cleanup. */
/* The name of the symbol used to encode the size. The name of this entry is
- * choosen so that it cannot be accessed by the user.
- */
+** choosen so that it cannot be accessed by the user.
+*/
static const StrBuf SizeEntryName = LIT_STRBUF_INITIALIZER (".size");
int IsSizeOfSymbol (const SymEntry* Sym)
/* Return true if the given symbol is the one that encodes the size of some
- * entity. Sym may also be a NULL pointer in which case false is returned.
- */
+** entity. Sym may also be a NULL pointer in which case false is returned.
+*/
{
return (Sym != 0 && SB_Compare (GetSymName (Sym), &SizeEntryName) == 0);
}
SymEntry* FindSizeOfScope (SymTable* Scope)
/* Get the size of a scope. The function returns the symbol table entry that
- * encodes the size or NULL if there is no such entry.
- */
+** encodes the size or NULL if there is no such entry.
+*/
{
return SymFind (Scope, &SizeEntryName, SYM_FIND_EXISTING);
}
SymEntry* FindSizeOfSymbol (SymEntry* Sym)
/* Get the size of a symbol table entry. The function returns the symbol table
- * entry that encodes the size of the symbol or NULL if there is no such entry.
- */
+** entry that encodes the size of the symbol or NULL if there is no such entry.
+*/
{
return SymFindLocal (Sym, &SizeEntryName, SYM_FIND_EXISTING);
}
SymEntry* GetSizeOfScope (SymTable* Scope)
/* Get the size of a scope. The function returns the symbol table entry that
- * encodes the size, and will create a new entry if it does not exist.
- */
+** encodes the size, and will create a new entry if it does not exist.
+*/
{
return SymFind (Scope, &SizeEntryName, SYM_ALLOC_NEW);
}
SymEntry* GetSizeOfSymbol (SymEntry* Sym)
/* Get the size of a symbol table entry. The function returns the symbol table
- * entry that encodes the size of the symbol and will create a new one if it
- * does not exist.
- */
+** entry that encodes the size of the symbol and will create a new one if it
+** does not exist.
+*/
{
return SymFindLocal (Sym, &SizeEntryName, SYM_ALLOC_NEW);
}
int IsSizeOfSymbol (const struct SymEntry* Sym);
/* Return true if the given symbol is the one that encodes the size of some
- * entity. Sym may also be a NULL pointer in which case false is returned.
- */
+** entity. Sym may also be a NULL pointer in which case false is returned.
+*/
struct SymEntry* FindSizeOfScope (struct SymTable* Scope);
/* Get the size of a scope. The function returns the symbol table entry that
- * encodes the size or NULL if there is no such entry.
- */
+** encodes the size or NULL if there is no such entry.
+*/
struct SymEntry* FindSizeOfSymbol (struct SymEntry* Sym);
/* Get the size of a symbol table entry. The function returns the symbol table
- * entry that encodes the size of the symbol or NULL if there is no such entry.
- */
+** entry that encodes the size of the symbol or NULL if there is no such entry.
+*/
struct SymEntry* GetSizeOfScope (struct SymTable* Scope);
/* Get the size of a scope. The function returns the symbol table entry that
- * encodes the size, and will create a new entry if it does not exist.
- */
+** encodes the size, and will create a new entry if it does not exist.
+*/
struct SymEntry* GetSizeOfSymbol (struct SymEntry* Sym);
/* Get the size of a symbol table entry. The function returns the symbol table
- * entry that encodes the size of the symbol and will create a new one if it
- * does not exist.
- */
+** entry that encodes the size of the symbol and will create a new one if it
+** does not exist.
+*/
struct SymEntry* DefSizeOfScope (struct SymTable* Scope, long Size);
/* Define the size of a scope and return the size symbol */
static int HT_Compare (const void* Key1, const void* Key2);
/* Compare two keys. The function must return a value less than zero if
- * Key1 is smaller than Key2, zero if both are equal, and a value greater
- * than zero if Key1 is greater then Key2.
- */
+** Key1 is smaller than Key2, zero if both are equal, and a value greater
+** than zero if Key1 is greater then Key2.
+*/
static int HT_Compare (const void* Key1, const void* Key2)
/* Compare two keys. The function must return a value less than zero if
- * Key1 is smaller than Key2, zero if both are equal, and a value greater
- * than zero if Key1 is greater then Key2.
- */
+** Key1 is smaller than Key2, zero if both are equal, and a value greater
+** than zero if Key1 is greater then Key2.
+*/
{
/* Convert both parameters to Span pointers */
const Span* S1 = Key1;
static Span* NewSpan (Segment* Seg, unsigned long Start, unsigned long End)
/* Create a new span. The segment is set to Seg, Start and End are set to the
- * current PC of the segment.
- */
+** current PC of the segment.
+*/
{
/* Allocate memory */
Span* S = xmalloc (sizeof (Span));
static Span* MergeSpan (Span* S)
/* Check if we have a span with the same data as S already. If so, free S and
- * return the already existing one. If not, remember S and return it.
- */
+** return the already existing one. If not, remember S and return it.
+*/
{
/* Check if we have such a span already. If so use the existing
- * one and free the one from the collection. If not, add the one to
- * the hash table and return it.
- */
+ ** one and free the one from the collection. If not, add the one to
+ ** the hash table and return it.
+ */
Span* E = HT_Find (&SpanTab, S);
if (E) {
/* If S has a type and E not, move the type */
Span* CloseSpan (Span* S)
/* Close the given span. Be sure to replace the passed span by the one
- * returned, since the span will get deleted if it is empty or may be
- * replaced if a duplicate exists.
- */
+** returned, since the span will get deleted if it is empty or may be
+** replaced if a duplicate exists.
+*/
{
/* Set the end offset */
if (S->Start == S->Seg->PC) {
S->End = S->Seg->PC;
/* Check if we have such a span already. If so use the existing
- * one and free the one from the collection. If not, add the one to
- * the hash table and return it.
- */
+ ** one and free the one from the collection. If not, add the one to
+ ** the hash table and return it.
+ */
return MergeSpan (S);
}
}
void OpenSpanList (Collection* Spans)
/* Open a list of spans for all existing segments to the given collection of
- * spans. The currently active segment will be inserted first with all others
- * following.
- */
+** spans. The currently active segment will be inserted first with all others
+** following.
+*/
{
unsigned I;
void CloseSpanList (Collection* Spans)
/* Close a list of spans. This will add new segments to the list, mark the end
- * of existing ones, and remove empty spans from the list.
- */
+** of existing ones, and remove empty spans from the list.
+*/
{
unsigned I, J;
CHECK (S->End > S->Start);
/* Write data for the span We will write the size instead of the
- * end offset to save some bytes, since most spans are expected
- * to be rather small.
- */
+ ** end offset to save some bytes, since most spans are expected
+ ** to be rather small.
+ */
ObjWriteVar (S->Seg->Num);
ObjWriteVar (S->Start);
ObjWriteVar (S->End - S->Start);
Span* CloseSpan (Span* S);
/* Close the given span. Be sure to replace the passed span by the one
- * returned, since the span will get deleted if it is empty or may be
- * replaced if a duplicate exists.
- */
+** returned, since the span will get deleted if it is empty or may be
+** replaced if a duplicate exists.
+*/
void OpenSpanList (Collection* Spans);
/* Open a list of spans for all existing segments to the given collection of
- * spans. The currently active segment will be inserted first with all others
- * following.
- */
+** spans. The currently active segment will be inserted first with all others
+** following.
+*/
void CloseSpanList (Collection* Spans);
/* Close all open spans by setting PC to the current PC for the segment. */
long Size = 0;
/* Outside of other structs, we need a name. Inside another struct or
- * union, the struct may be anonymous, in which case no new lexical level
- * is started.
- */
+ ** union, the struct may be anonymous, in which case no new lexical level
+ ** is started.
+ */
int Anon = (CurTok.Tok != TOK_IDENT);
if (!Anon) {
/* Enter a new scope, then skip the name */
if (CurTok.Tok == TOK_IDENT) {
/* Beware: An identifier may also be a macro, in which case we have
- * to start over.
- */
+ ** to start over.
+ */
Macro* M = FindMacro (&CurTok.SVal);
if (M) {
MacExpandStart (M);
}
/* If this is not a anon struct, enter a special symbol named ".size"
- * into the symbol table of the struct that holds the size of the
- * struct. Since the symbol starts with a dot, it cannot be accessed
- * by user code.
- * Leave the struct scope level.
- */
+ ** into the symbol table of the struct that holds the size of the
+ ** struct. Since the symbol starts with a dot, it cannot be accessed
+ ** by user code.
+ ** Leave the struct scope level.
+ */
if (!Anon) {
/* Add a symbol */
SymEntry* SizeSym = GetSizeOfScope (CurrentScope);
static int ED_IsValid (const ExprDesc* D)
/* Return true if the expression is valid, that is, neither the ERROR nor the
- * TOO_COMPLEX flags are set.
- */
+** TOO_COMPLEX flags are set.
+*/
{
return ((D->Flags & (ED_ERROR | ED_TOO_COMPLEX)) == 0);
}
{
if (ED->AddrSize == ADDR_SIZE_DEFAULT) {
/* If ED is valid, ADDR_SIZE_DEFAULT gets always overridden, otherwise
- * it takes precedence over anything else.
- */
+ ** it takes precedence over anything else.
+ */
if (ED_IsValid (ED)) {
ED->AddrSize = Right->AddrSize;
}
} else if (Right->AddrSize == ADDR_SIZE_DEFAULT) {
/* If Right is valid, ADDR_SIZE_DEFAULT gets always overridden,
- * otherwise it takes precedence over anything else.
- */
+ ** otherwise it takes precedence over anything else.
+ */
if (!ED_IsValid (Right)) {
ED->AddrSize = Right->AddrSize;
}
} else {
/* Neither ED nor Right has a default address size, use the larger of
- * the two.
- */
+ ** the two.
+ */
if (Right->AddrSize > ED->AddrSize) {
ED->AddrSize = Right->AddrSize;
}
static ED_SymRef* ED_FindSymRef (ExprDesc* ED, SymEntry* Sym)
/* Find a symbol reference and return it. Return NULL if the reference does
- * not exist.
- */
+** not exist.
+*/
{
unsigned I;
ED_SymRef* SymRef;
static ED_SecRef* ED_FindSecRef (ExprDesc* ED, unsigned Sec)
/* Find a section reference and return it. Return NULL if the reference does
- * not exist.
- */
+** not exist.
+*/
{
unsigned I;
ED_SecRef* SecRef;
static ED_SymRef* ED_AllocSymRef (ExprDesc* ED, SymEntry* Sym)
/* Allocate a new symbol reference and return it. The count of the new
- * reference will be set to zero, and the reference itself to Sym.
- */
+** reference will be set to zero, and the reference itself to Sym.
+*/
{
ED_SymRef* SymRef;
static ED_SecRef* ED_AllocSecRef (ExprDesc* ED, unsigned Sec)
/* Allocate a new section reference and return it. The count of the new
- * reference will be set to zero, and the reference itself to Sec.
- */
+** reference will be set to zero, and the reference itself to Sec.
+*/
{
ED_SecRef* SecRef;
static ED_SymRef* ED_GetSymRef (ExprDesc* ED, SymEntry* Sym)
/* Get a symbol reference and return it. If the symbol reference does not
- * exist, a new one is created and returned.
- */
+** exist, a new one is created and returned.
+*/
{
ED_SymRef* SymRef = ED_FindSymRef (ED, Sym);
if (SymRef == 0) {
static ED_SecRef* ED_GetSecRef (ExprDesc* ED, unsigned Sec)
/* Get a section reference and return it. If the section reference does not
- * exist, a new one is created and returned.
- */
+** exist, a new one is created and returned.
+*/
{
ED_SecRef* SecRef = ED_FindSecRef (ED, Sec);
if (SecRef == 0) {
static void ED_Move (ExprDesc* From, ExprDesc* To)
/* Move the data from one ExprDesc to another. Old data is freed, and From
- * is prepared to that ED_Done may be called safely.
- */
+** is prepared to that ED_Done may be called safely.
+*/
{
/* Delete old data */
ED_Done (To);
static void StudyBinaryExpr (ExprNode* Expr, ExprDesc* D)
/* Study a binary expression subtree. This is a helper function for StudyExpr
- * used for operations that succeed when both operands are known and constant.
- * It evaluates the two subtrees and checks if they are constant. If they
- * aren't constant, it will set the TOO_COMPLEX flag, and merge references.
- * Otherwise the first value is returned in D->Val, the second one in D->Right,
- * so the actual operation can be done by the caller.
- */
+** used for operations that succeed when both operands are known and constant.
+** It evaluates the two subtrees and checks if they are constant. If they
+** aren't constant, it will set the TOO_COMPLEX flag, and merge references.
+** Otherwise the first value is returned in D->Val, the second one in D->Right,
+** so the actual operation can be done by the caller.
+*/
{
ExprDesc Right;
SymEntry* Sym = Expr->V.Sym;
/* If the symbol is defined somewhere, it has an expression associated.
- * In this case, just study the expression associated with the symbol,
- * but mark the symbol so if we encounter it twice, we know that we have
- * a circular reference.
- */
+ ** In this case, just study the expression associated with the symbol,
+ ** but mark the symbol so if we encounter it twice, we know that we have
+ ** a circular reference.
+ */
if (SymHasExpr (Sym)) {
if (SymHasUserMark (Sym)) {
}
/* If the symbol has an explicit address size, use it. This may
- * lead to range errors later (maybe even in the linker stage), if
- * the user lied about the address size, but for now we trust him.
- */
+ ** lead to range errors later (maybe even in the linker stage), if
+ ** the user lied about the address size, but for now we trust him.
+ */
AddrSize = GetSymAddrSize (Sym);
if (AddrSize != ADDR_SIZE_DEFAULT) {
D->AddrSize = AddrSize;
} else if (SymIsImport (Sym)) {
/* The symbol is an import. Track the symbols used and update the
- * address size.
- */
+ ** address size.
+ */
ED_SymRef* SymRef = ED_GetSymRef (D, Sym);
++SymRef->Count;
ED_UpdateAddrSize (D, GetSymAddrSize (Sym));
SymTable* Parent;
/* The symbol is undefined. Track symbol usage but set the "too
- * complex" flag, since we cannot evaluate the final result.
- */
+ ** complex" flag, since we cannot evaluate the final result.
+ */
ED_SymRef* SymRef = ED_GetSymRef (D, Sym);
++SymRef->Count;
ED_Invalidate (D);
/* Since the symbol may be a forward, and we may need a statement
- * about the address size, check higher lexical levels for a symbol
- * with the same name and use its address size if we find such a
- * symbol which is defined.
- */
+ ** about the address size, check higher lexical levels for a symbol
+ ** with the same name and use its address size if we find such a
+ ** symbol which is defined.
+ */
AddrSize = GetSymAddrSize (Sym);
Parent = GetSymParentScope (Sym);
if (AddrSize == ADDR_SIZE_DEFAULT && Parent != 0) {
/* Study an unnamed label expression node */
{
/* If we can resolve the label, study the expression associated with it,
- * otherwise mark the expression as too complex to evaluate.
- */
+ ** otherwise mark the expression as too complex to evaluate.
+ */
if (ULabCanResolve ()) {
/* We can resolve the label */
StudyExprInternal (ULabResolve (Expr->V.IVal), D);
StudyExprInternal (Expr->Right, &Right);
/* We can handle the operation if at least one of both operands is const
- * and the other one is valid.
- */
+ ** and the other one is valid.
+ */
if (ED_IsConst (D) && ED_IsValid (&Right)) {
/* Multiplicate both, result goes into Right */
}
/* If we don't have an address size, assign one if the expression is a
- * constant.
- */
+ ** constant.
+ */
if (D->AddrSize == ADDR_SIZE_DEFAULT && ED_IsConst (D)) {
D->AddrSize = GetConstAddrSize (D->Val);
}
/* If the expression is valid, throw away the address size and recalculate
- * it using the data we have. This is more exact than the on-the-fly
- * calculation done when evaluating the tree, because symbols may have
- * been removed from the expression, and the final numeric value is now
- * known.
- */
+ ** it using the data we have. This is more exact than the on-the-fly
+ ** calculation done when evaluating the tree, because symbols may have
+ ** been removed from the expression, and the final numeric value is now
+ ** known.
+ */
if (ED_IsValid (D)) {
unsigned char AddrSize;
/* If there are symbols or sections, use the largest one. If the
- * expression resolves to a const, use the address size of the value.
- */
+ ** expression resolves to a const, use the address size of the value.
+ */
if (D->SymCount > 0 || D->SecCount > 0) {
D->AddrSize = ADDR_SIZE_DEFAULT;
SymTable* ParseScopedIdent (StrBuf* Name, StrBuf* FullName)
/* Parse a (possibly scoped) identifer. The scope of the name must exist and
- * is returned as function result, while the last part (the identifier) which
- * may be either a symbol or a scope depending on the context is returned in
- * Name. FullName is a string buffer that is used to store the full name of
- * the identifier including the scope. It is used internally and may be used
- * by the caller for error messages or similar.
- */
+** is returned as function result, while the last part (the identifier) which
+** may be either a symbol or a scope depending on the context is returned in
+** Name. FullName is a string buffer that is used to store the full name of
+** the identifier including the scope. It is used internally and may be used
+** by the caller for error messages or similar.
+*/
{
SymTable* Scope;
SB_Append (FullName, Name);
/* The scope must exist, so search for it starting with the current
- * scope.
- */
+ ** scope.
+ */
Scope = SymFindAnyScope (CurrentScope, Name);
if (Scope == 0) {
/* Scope not found */
NextTok ();
/* If a namespace token follows, we search for another scope, otherwise
- * the name is a symbol and we're done.
- */
+ ** the name is a symbol and we're done.
+ */
if (CurTok.Tok != TOK_NAMESPACE) {
/* Symbol */
return Scope;
SymEntry* ParseScopedSymName (SymFindAction Action)
/* Parse a (possibly scoped) symbol name, search for it in the symbol table
- * and return the symbol table entry.
- */
+** and return the symbol table entry.
+*/
{
StrBuf ScopeName = STATIC_STRBUF_INITIALIZER;
StrBuf Ident = STATIC_STRBUF_INITIALIZER;
SB_Done (&ScopeName);
/* Check if the scope is valid. Errors have already been diagnosed by
- * the routine, so just exit.
- */
+ ** the routine, so just exit.
+ */
if (Scope) {
/* Search for the symbol and return it. If no scope was specified,
- * search also in the upper levels.
- */
+ ** search also in the upper levels.
+ */
if (NoScope && (Action & SYM_ALLOC_NEW) == 0) {
Sym = SymFindAny (Scope, &Ident);
} else {
}
} else {
/* No scope ==> no symbol. To avoid errors in the calling routine that
- * may not expect NULL to be returned if Action contains SYM_ALLOC_NEW,
- * create a new symbol.
- */
+ ** may not expect NULL to be returned if Action contains SYM_ALLOC_NEW,
+ ** create a new symbol.
+ */
if (Action & SYM_ALLOC_NEW) {
Sym = NewSymEntry (&Ident, SF_NONE);
} else {
SymTable* ParseScopedSymTable (void)
/* Parse a (possibly scoped) symbol table (scope) name, search for it in the
- * symbol space and return the symbol table struct.
- */
+** symbol space and return the symbol table struct.
+*/
{
StrBuf ScopeName = STATIC_STRBUF_INITIALIZER;
StrBuf Name = STATIC_STRBUF_INITIALIZER;
SB_Done (&ScopeName);
/* If we got no error, search for the child scope withint the enclosing one.
- * Beware: If no explicit parent scope was specified, search in all upper
- * levels.
- */
+ ** Beware: If no explicit parent scope was specified, search in all upper
+ ** levels.
+ */
if (Scope) {
/* Search for the last scope */
if (NoScope) {
SymEntry* ParseAnySymName (SymFindAction Action)
/* Parse a cheap local symbol or a a (possibly scoped) symbol name, search
- * for it in the symbol table and return the symbol table entry.
- */
+** for it in the symbol table and return the symbol table entry.
+*/
{
SymEntry* Sym;
struct SymTable* ParseScopedIdent (struct StrBuf* Name, struct StrBuf* FullName);
/* Parse a (possibly scoped) identifer. The scope of the name must exist and
- * is returned as function result, while the last part (the identifier) which
- * may be either a symbol or a scope depending on the context is returned in
- * Name. FullName is a string buffer that is used to store the full name of
- * the identifier including the scope. It is used internally and may be used
- * by the caller for error messages or similar.
- */
+** is returned as function result, while the last part (the identifier) which
+** may be either a symbol or a scope depending on the context is returned in
+** Name. FullName is a string buffer that is used to store the full name of
+** the identifier including the scope. It is used internally and may be used
+** by the caller for error messages or similar.
+*/
struct SymEntry* ParseScopedSymName (SymFindAction Action);
/* Parse a (possibly scoped) symbol name, search for it in the symbol table
- * and return the symbol table entry.
- */
+** and return the symbol table entry.
+*/
struct SymTable* ParseScopedSymTable (void);
/* Parse a (possibly scoped) symbol table (scope) name, search for it in the
- * symbol space and return the symbol table struct.
- */
+** symbol space and return the symbol table struct.
+*/
struct SymEntry* ParseAnySymName (SymFindAction Action);
/* Parse a cheap local symbol or a a (possibly scoped) symbol name, search
- * for it in the symbol table and return the symbol table entry.
- */
+** for it in the symbol table and return the symbol table entry.
+*/
int SymSearchTree (SymEntry* T, const StrBuf* Name, SymEntry** E)
/* Search in the given tree for a name. If we find the symbol, the function
- * will return 0 and put the entry pointer into E. If we did not find the
- * symbol, and the tree is empty, E is set to NULL. If the tree is not empty,
- * E will be set to the last entry, and the result of the function is <0 if
- * the entry should be inserted on the left side, and >0 if it should get
- * inserted on the right side.
- */
+** will return 0 and put the entry pointer into E. If we did not find the
+** symbol, and the tree is empty, E is set to NULL. If the tree is not empty,
+** E will be set to the last entry, and the result of the function is <0 if
+** the entry should be inserted on the left side, and >0 if it should get
+** inserted on the right side.
+*/
{
/* Is there a tree? */
if (T == 0) {
CHECK (E->Op == EXPR_SYMBOL && E->V.Sym == S);
/* We cannot touch the root node, since there are pointers to it.
- * Replace it by a literal node.
- */
+ ** Replace it by a literal node.
+ */
E->Op = EXPR_LITERAL;
E->V.IVal = Val;
}
return;
}
/* Delete the current symbol expression, since it will get
- * replaced
- */
+ ** replaced
+ */
FreeExpr (S->Expr);
S->Expr = 0;
}
S->Expr = Expr;
/* In case of a variable symbol, walk over all expressions containing
- * this symbol and replace the (sub-)expression by the literal value of
- * the tree. Be sure to replace the expression node in place, since there
- * may be pointers to it.
- */
+ ** this symbol and replace the (sub-)expression by the literal value of
+ ** the tree. Be sure to replace the expression node in place, since there
+ ** may be pointers to it.
+ */
if (Flags & SF_VAR) {
SymReplaceExprRefs (S);
}
/* If the symbol is marked as global, export it. Address size is checked
- * below.
- */
+ ** below.
+ */
if (S->Flags & SF_GLOBAL) {
S->Flags = (S->Flags & ~SF_GLOBAL) | SF_EXPORT;
ReleaseFullLineInfo (&S->DefLines);
}
/* If no address size is given, use the address size of the enclosing
- * segment.
- */
+ ** segment.
+ */
if (AddrSize == ADDR_SIZE_DEFAULT) {
AddrSize = GetCurrentSegAddrSize ();
}
/* If the symbol is marked as import or global, check the address size,
- * then do silently remove the global flag.
- */
+ ** then do silently remove the global flag.
+ */
if (S->Flags & SF_IMPORT) {
if ((Flags & SF_FORCED) != (S->Flags & SF_FORCED)) {
Error ("Redeclaration mismatch for symbol `%m%p'", GetSymName (S));
S->AddrSize = AddrSize;
/* Mark the position of the import as the position of the definition.
- * Please note: In case of multiple .global or .import statements, the line
- * infos add up.
- */
+ ** Please note: In case of multiple .global or .import statements, the line
+ ** infos add up.
+ */
GetFullLineInfo (&S->DefLines);
}
}
/* If the symbol was marked as global before, remove the global flag and
- * proceed, but check the address size.
- */
+ ** proceed, but check the address size.
+ */
if (S->Flags & SF_GLOBAL) {
if (AddrSize != S->ExportSize) {
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
S->Flags &= ~SF_GLOBAL;
/* .GLOBAL remembers line infos in case an .IMPORT follows. We have
- * to remove these here.
- */
+ ** to remove these here.
+ */
ReleaseFullLineInfo (&S->DefLines);
}
/* If the symbol was already marked as an export, but wasn't defined
- * before, the address sizes in both definitions must match.
- */
+ ** before, the address sizes in both definitions must match.
+ */
if ((S->Flags & (SF_EXPORT|SF_DEFINED)) == SF_EXPORT) {
if (S->ExportSize != AddrSize) {
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
S->ExportSize = AddrSize;
/* If the symbol is already defined, check symbol size against the
- * exported size.
- */
+ ** exported size.
+ */
if (S->Flags & SF_DEFINED) {
if (S->ExportSize == ADDR_SIZE_DEFAULT) {
/* No export size given, use the real size of the symbol */
void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags)
/* Mark the given symbol as a global symbol, that is, as a symbol that is
- * either imported or exported.
- */
+** either imported or exported.
+*/
{
if (S->Flags & SF_VAR) {
/* Variable symbols cannot be exported or imported */
}
/* If the symbol is already marked as import, the address size must match.
- * Apart from that, ignore the global declaration.
- */
+ ** Apart from that, ignore the global declaration.
+ */
if (S->Flags & SF_IMPORT) {
if (AddrSize == ADDR_SIZE_DEFAULT) {
/* Use the size of the current segment */
}
/* If the symbol is already an export: If it is not defined, the address
- * sizes must match.
- */
+ ** sizes must match.
+ */
if (S->Flags & SF_EXPORT) {
if ((S->Flags & SF_DEFINED) == 0) {
/* Symbol is undefined */
}
/* If the symbol is already marked as global, the address size must match.
- * Use the ExportSize here, since it contains the actual address size
- * passed to this function.
- */
+ ** Use the ExportSize here, since it contains the actual address size
+ ** passed to this function.
+ */
if (S->Flags & SF_GLOBAL) {
if (AddrSize != S->ExportSize) {
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
}
/* If we come here, the symbol was neither declared as export, import or
- * global before. Check if it is already defined, in which case it will
- * become an export. If it is not defined, mark it as global and remember
- * the given address sizes.
- */
+ ** global before. Check if it is already defined, in which case it will
+ ** become an export. If it is not defined, mark it as global and remember
+ ** the given address sizes.
+ */
if (S->Flags & SF_DEFINED) {
/* The symbol is defined, export it */
S->ExportSize = AddrSize;
S->Flags |= (SF_EXPORT | Flags);
} else {
/* Since we don't know if the symbol will get exported or imported,
- * remember two different address sizes: One for an import in AddrSize,
- * and the other one for an export in ExportSize.
- */
+ ** remember two different address sizes: One for an import in AddrSize,
+ ** and the other one for an export in ExportSize.
+ */
S->AddrSize = AddrSize;
if (S->AddrSize == ADDR_SIZE_DEFAULT) {
/* Use the size of the current segment */
S->Flags |= (SF_GLOBAL | Flags);
/* Remember the current location as location of definition in case
- * an .IMPORT follows later.
- */
+ ** an .IMPORT follows later.
+ */
GetFullLineInfo (&S->DefLines);
}
}
void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Prio)
/* Mark the given symbol as a module constructor/destructor. This will also
- * mark the symbol as an export. Initializers may never be zero page symbols.
- */
+** mark the symbol as an export. Initializers may never be zero page symbols.
+*/
{
/* Check the parameters */
#if (CD_TYPE_MIN != 0)
}
/* If the symbol was already marked as an export or global, check if
- * this was done specifiying the same address size. In case of a global
- * declaration, silently remove the global flag.
- */
+ ** this was done specifiying the same address size. In case of a global
+ ** declaration, silently remove the global flag.
+ */
if (S->Flags & (SF_EXPORT | SF_GLOBAL)) {
if (S->ExportSize != AddrSize) {
Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
S->ExportSize = AddrSize;
/* If the symbol is already defined, check symbol size against the
- * exported size.
- */
+ ** exported size.
+ */
if (S->Flags & SF_DEFINED) {
if (S->ExportSize == ADDR_SIZE_DEFAULT) {
/* Use the real size of the symbol */
}
/* If the symbol was already declared as a condes, check if the new
- * priority value is the same as the old one.
- */
+ ** priority value is the same as the old one.
+ */
if (S->ConDesPrio[Type] != CD_PRIO_NONE) {
if (S->ConDesPrio[Type] != Prio) {
Error ("Redeclaration mismatch for symbol `%m%p'", GetSymName (S));
void SymGuessedAddrSize (SymEntry* Sym, unsigned char AddrSize)
/* Mark the address size of the given symbol as guessed. The address size
- * passed as argument is the one NOT used, because the actual address size
- * wasn't known. Example: Zero page addressing was not used because symbol
- * is undefined, and absolute addressing was available.
- */
+** passed as argument is the one NOT used, because the actual address size
+** wasn't known. Example: Zero page addressing was not used because symbol
+** is undefined, and absolute addressing was available.
+*/
{
/* We must have a valid address size passed */
PRECONDITION (AddrSize != ADDR_SIZE_DEFAULT);
void SymExportFromGlobal (SymEntry* S)
/* Called at the end of assembly. Converts a global symbol that is defined
- * into an export.
- */
+** into an export.
+*/
{
/* Remove the global flag and make the symbol an export */
S->Flags &= ~SF_GLOBAL;
void SymImportFromGlobal (SymEntry* S)
/* Called at the end of assembly. Converts a global symbol that is undefined
- * into an import.
- */
+** into an import.
+*/
{
/* Remove the global flag and make it an import */
S->Flags &= ~SF_GLOBAL;
int SymIsConst (const SymEntry* S, long* Val)
/* Return true if the given symbol has a constant value. If Val is not NULL
- * and the symbol has a constant value, store it's value there.
- */
+** and the symbol has a constant value, store it's value there.
+*/
{
/* Check for constness */
return (SymHasExpr (S) && IsConstExpr (S->Expr, Val));
SymTable* GetSymParentScope (SymEntry* S)
/* Get the parent scope of the symbol (not the one it is defined in). Return
- * NULL if the symbol is a cheap local, or defined on global level.
- */
+** NULL if the symbol is a cheap local, or defined on global level.
+*/
{
if ((S->Flags & SF_LOCAL) != 0) {
/* This is a cheap local symbol */
return 0;
} else if (S->Sym.Tab == 0) {
/* Symbol not in a table. This may happen if there have been errors
- * before. Return NULL in this case to avoid further errors.
- */
+ ** before. Return NULL in this case to avoid further errors.
+ */
return 0;
} else {
/* This is a global symbol */
const struct ExprNode* SymResolve (const SymEntry* S)
/* Helper function for DumpExpr. Resolves a symbol into an expression or return
- * NULL. Do not call in other contexts!
- */
+** NULL. Do not call in other contexts!
+*/
{
return SymHasExpr (S)? S->Expr : 0;
}
long GetSymVal (SymEntry* S)
/* Return the value of a symbol assuming it's constant. FAIL will be called
- * in case the symbol is undefined or not constant.
- */
+** in case the symbol is undefined or not constant.
+*/
{
long Val;
CHECK (S != 0 && SymHasExpr (S) && IsConstExpr (GetSymExpr (S), &Val));
unsigned GetSymInfoFlags (const SymEntry* S, long* ConstVal)
/* Return a set of flags used when writing symbol information into a file.
- * If the SYM_CONST bit is set, ConstVal will contain the constant value
- * of the symbol. The result does not include the condes count.
- * See common/symdefs.h for more information.
- */
+** If the SYM_CONST bit is set, ConstVal will contain the constant value
+** of the symbol. The result does not include the condes count.
+** See common/symdefs.h for more information.
+*/
{
/* Setup info flags */
unsigned Flags = 0;
Collection DefLines; /* Line infos for definition */
Collection RefLines; /* Line infos for references */
FilePos* GuessedUse[1]; /* File position where symbol
- * address size was guessed, and the
- * smallest possible addressing was NOT
- * used. Currently only for zero page
- * addressing
- */
+ ** address size was guessed, and the
+ ** smallest possible addressing was NOT
+ ** used. Currently only for zero page
+ ** addressing
+ */
struct HLLDbgSym* HLLSym; /* Symbol from high level language */
unsigned Flags; /* Symbol flags */
unsigned DebugSymId; /* Debug symbol id */
int SymSearchTree (SymEntry* T, const StrBuf* Name, SymEntry** E);
/* Search in the given tree for a name. If we find the symbol, the function
- * will return 0 and put the entry pointer into E. If we did not find the
- * symbol, and the tree is empty, E is set to NULL. If the tree is not empty,
- * E will be set to the last entry, and the result of the function is <0 if
- * the entry should be inserted on the left side, and >0 if it should get
- * inserted on the right side.
- */
+** will return 0 and put the entry pointer into E. If we did not find the
+** symbol, and the tree is empty, E is set to NULL. If the tree is not empty,
+** E will be set to the last entry, and the result of the function is <0 if
+** the entry should be inserted on the left side, and >0 if it should get
+** inserted on the right side.
+*/
#if defined(HAVE_INLINE)
INLINE void SymAddExprRef (SymEntry* Sym, struct ExprNode* Expr)
void SymGlobal (SymEntry* Sym, unsigned char AddrSize, unsigned Flags);
/* Mark the given symbol as a global symbol, that is, as a symbol that is
- * either imported or exported.
- */
+** either imported or exported.
+*/
void SymConDes (SymEntry* Sym, unsigned char AddrSize, unsigned Type, unsigned Prio);
/* Mark the given symbol as a module constructor/destructor. This will also
- * mark the symbol as an export. Initializers may never be zero page symbols.
- */
+** mark the symbol as an export. Initializers may never be zero page symbols.
+*/
void SymGuessedAddrSize (SymEntry* Sym, unsigned char AddrSize);
/* Mark the address size of the given symbol as guessed. The address size
- * passed as argument is the one NOT used, because the actual address size
- * wasn't known. Example: Zero page addressing was not used because symbol
- * is undefined, and absolute addressing was available.
- */
+** passed as argument is the one NOT used, because the actual address size
+** wasn't known. Example: Zero page addressing was not used because symbol
+** is undefined, and absolute addressing was available.
+*/
void SymExportFromGlobal (SymEntry* S);
/* Called at the end of assembly. Converts a global symbol that is defined
- * into an export.
- */
+** into an export.
+*/
void SymImportFromGlobal (SymEntry* S);
/* Called at the end of assembly. Converts a global symbol that is undefined
- * into an import.
- */
+** into an import.
+*/
#if defined(HAVE_INLINE)
INLINE int SymIsDef (const SymEntry* S)
int SymIsConst (const SymEntry* Sym, long* Val);
/* Return true if the given symbol has a constant value. If Val is not NULL
- * and the symbol has a constant value, store it's value there.
- */
+** and the symbol has a constant value, store it's value there.
+*/
#if defined(HAVE_INLINE)
INLINE int SymHasExpr (const SymEntry* S)
struct SymTable* GetSymParentScope (SymEntry* S);
/* Get the parent scope of the symbol (not the one it is defined in). Return
- * NULL if the symbol is a cheap local, or defined on global level.
- */
+** NULL if the symbol is a cheap local, or defined on global level.
+*/
struct ExprNode* GetSymExpr (SymEntry* Sym);
/* Get the expression for a non-const symbol */
const struct ExprNode* SymResolve (const SymEntry* Sym);
/* Helper function for DumpExpr. Resolves a symbol into an expression or return
- * NULL. Do not call in other contexts!
- */
+** NULL. Do not call in other contexts!
+*/
#if defined(HAVE_INLINE)
INLINE const StrBuf* GetSymName (const SymEntry* S)
#if defined(HAVE_INLINE)
INLINE unsigned char GetSymAddrSize (const SymEntry* S)
/* Return the address size of the symbol. Beware: This function will just
- * return the AddrSize member, it will not look at the expression!
- */
+** return the AddrSize member, it will not look at the expression!
+*/
{
return S->AddrSize;
}
long GetSymVal (SymEntry* Sym);
/* Return the value of a symbol assuming it's constant. FAIL will be called
- * in case the symbol is undefined or not constant.
- */
+** in case the symbol is undefined or not constant.
+*/
unsigned GetSymImportId (const SymEntry* Sym);
/* Return the import id for the given symbol */
unsigned GetSymInfoFlags (const SymEntry* Sym, long* ConstVal);
/* Return a set of flags used when writing symbol information into a file.
- * If the SYM_CONST bit is set, ConstVal will contain the constant value
- * of the symbol. The result does not include the condes count.
- * See common/symdefs.h for more information.
- */
+** If the SYM_CONST bit is set, ConstVal will contain the constant value
+** of the symbol. The result does not include the condes count.
+** See common/symdefs.h for more information.
+*/
}
/* If we have a current scope, search for the given name and create a
- * new one if it doesn't exist. If this is the root scope, just create it.
- */
+ ** new one if it doesn't exist. If this is the root scope, just create it.
+ */
if (CurrentScope) {
/* Search for the scope, create a new one */
CurrentScope->Label = ScopeLabel;
/* If this is a scope that allows to emit data into segments, add spans
- * for all currently existing segments. Doing this for just a few scope
- * types is not really necessary but an optimization, because it does not
- * allocate memory for useless data (unhandled types here don't occupy
- * space in any segment).
- */
+ ** for all currently existing segments. Doing this for just a few scope
+ ** types is not really necessary but an optimization, because it does not
+ ** allocate memory for useless data (unhandled types here don't occupy
+ ** space in any segment).
+ */
if (CurrentScope->Type <= SCOPE_HAS_DATA) {
OpenSpanList (&CurrentScope->Spans);
}
/* Leave the current lexical level */
{
/* If this is a scope that allows to emit data into segments, close the
- * open the spans.
- */
+ ** open the spans.
+ */
if (CurrentScope->Type <= SCOPE_HAS_DATA) {
CloseSpanList (&CurrentScope->Spans);
}
/* If we have spans, the first one is the segment that was active, when the
- * scope was opened. Set the size of the scope to the number of data bytes
- * emitted into this segment. If we have an owner symbol set the size of
- * this symbol, too.
- */
+ ** scope was opened. Set the size of the scope to the number of data bytes
+ ** emitted into this segment. If we have an owner symbol set the size of
+ ** this symbol, too.
+ */
if (CollCount (&CurrentScope->Spans) > 0) {
const Span* S = CollAtUnchecked (&CurrentScope->Spans, 0);
unsigned long Size = GetSpanSize (S);
SymTable* SymFindAnyScope (SymTable* Parent, const StrBuf* Name)
/* Find a scope in the given or any of its parent scopes. The function will
- * never create a new symbol, since this can only be done in one specific
- * scope.
- */
+** never create a new symbol, since this can only be done in one specific
+** scope.
+*/
{
SymTable* Scope;
do {
SymEntry* SymFindLocal (SymEntry* Parent, const StrBuf* Name, SymFindAction Action)
/* Find a cheap local symbol. If Action contains SYM_ALLOC_NEW and the entry is
- * not found, create a new one. Return the entry found, or the new entry
- * created, or - in case Action is SYM_FIND_EXISTING - return 0.
- */
+** not found, create a new one. Return the entry found, or the new entry
+** created, or - in case Action is SYM_FIND_EXISTING - return 0.
+*/
{
SymEntry* S;
SymEntry* SymFind (SymTable* Scope, const StrBuf* Name, SymFindAction Action)
/* Find a new symbol table entry in the given table. If Action contains
- * SYM_ALLOC_NEW and the entry is not found, create a new one. Return the
- * entry found, or the new entry created, or - in case Action is
- * SYM_FIND_EXISTING - return 0.
- */
+** SYM_ALLOC_NEW and the entry is not found, create a new one. Return the
+** entry found, or the new entry created, or - in case Action is
+** SYM_FIND_EXISTING - return 0.
+*/
{
SymEntry* S;
if (Action & SYM_ALLOC_NEW) {
/* Otherwise create a new entry, insert and return it. If the scope is
- * already closed, mark the symbol as fixed so it won't be resolved
- * by a symbol in the enclosing scopes later.
- */
+ ** already closed, mark the symbol as fixed so it won't be resolved
+ ** by a symbol in the enclosing scopes later.
+ */
SymEntry* N = NewSymEntry (Name, SF_NONE);
if (SymTabIsClosed (Scope)) {
N->Flags |= SF_FIXED;
SymEntry* SymFindAny (SymTable* Scope, const StrBuf* Name)
/* Find a symbol in the given or any of its parent scopes. The function will
- * never create a new symbol, since this can only be done in one specific
- * scope.
- */
+** never create a new symbol, since this can only be done in one specific
+** scope.
+*/
{
/* Generate the name hash */
unsigned Hash = HashBuf (Name);
SymEntry* Sym;
do {
/* Search in the current table. Ignore entries flagged with SF_UNUSED,
- * because for such symbols there is a real entry in one of the parent
- * scopes.
- */
+ ** because for such symbols there is a real entry in one of the parent
+ ** scopes.
+ */
if (SymSearchTree (Scope->Table[Hash % Scope->TableSlots], Name, &Sym) == 0) {
if (Sym->Flags & SF_UNUSED) {
Sym = 0;
/* Handle an undefined symbol */
{
/* Undefined symbol. It may be...
- *
- * - An undefined symbol in a nested lexical level. If the symbol is not
- * fixed to this level, search for the symbol in the higher levels and
- * make the entry a trampoline entry if we find one.
- *
- * - If the symbol is not found, it is a real undefined symbol. If the
- * AutoImport flag is set, make it an import. If the AutoImport flag is
- * not set, it's an error.
- */
+ **
+ ** - An undefined symbol in a nested lexical level. If the symbol is not
+ ** fixed to this level, search for the symbol in the higher levels and
+ ** make the entry a trampoline entry if we find one.
+ **
+ ** - If the symbol is not found, it is a real undefined symbol. If the
+ ** AutoImport flag is set, make it an import. If the AutoImport flag is
+ ** not set, it's an error.
+ */
SymEntry* Sym = 0;
if ((S->Flags & SF_FIXED) == 0) {
SymTable* Tab = GetSymParentScope (S);
Sym = SymFind (Tab, GetStrBuf (S->Name), SYM_FIND_EXISTING | SYM_CHECK_ONLY);
if (Sym && (Sym->Flags & (SF_DEFINED | SF_IMPORT)) != 0) {
/* We've found a symbol in a higher level that is
- * either defined in the source, or an import.
- */
+ ** either defined in the source, or an import.
+ */
break;
}
/* No matching symbol found in this level. Look further */
if (Sym) {
/* We found the symbol in a higher level. Transfer the flags and
- * address size from the local symbol to that in the higher level
- * and check for problems.
- */
+ ** address size from the local symbol to that in the higher level
+ ** and check for problems.
+ */
if (S->Flags & SF_EXPORT) {
if (Sym->Flags & SF_IMPORT) {
/* The symbol is already marked as import */
}
/* First pass: Walk through all symbols, checking for undefined's and
- * changing them to trampoline symbols or make them imports.
- */
+ ** changing them to trampoline symbols or make them imports.
+ */
S = SymList;
while (S) {
/* If the symbol is marked as global, mark it as export, if it is
- * already defined, otherwise mark it as import.
- */
+ ** already defined, otherwise mark it as import.
+ */
if (S->Flags & SF_GLOBAL) {
if (S->Flags & SF_DEFINED) {
SymExportFromGlobal (S);
}
/* Second pass: Walk again through the symbols. Count exports and imports
- * and set address sizes where this has not happened before. Ignore
- * undefined's, since we handled them in the last pass, and ignore unused
- * symbols, since we handled them in the last pass, too.
- */
+ ** and set address sizes where this has not happened before. Ignore
+ ** undefined's, since we handled them in the last pass, and ignore unused
+ ** symbols, since we handled them in the last pass, too.
+ */
S = SymList;
while (S) {
if ((S->Flags & SF_UNUSED) == 0 &&
}
/* If the symbol is defined but has an unknown address size,
- * recalculate it.
- */
+ ** recalculate it.
+ */
if (SymHasExpr (S) && S->AddrSize == ADDR_SIZE_DEFAULT) {
ExprDesc ED;
ED_Init (&ED);
}
/* If the address size of the symbol was guessed, check the guess
- * against the actual address size and print a warning if the two
- * differ.
- */
+ ** against the actual address size and print a warning if the two
+ ** differ.
+ */
if (S->AddrSize != ADDR_SIZE_DEFAULT) {
/* Do we have data for this address size? */
if (S->AddrSize <= sizeof (S->GuessedUse) / sizeof (S->GuessedUse[0])) {
ObjWriteVar (ImportCount);
/* Walk throught list and write all valid imports to the file. An import
- * is considered valid, if it is either referenced, or the forced bit is
- * set. Otherwise, the import is ignored (no need to link in something
- * that isn't used).
- */
+ ** is considered valid, if it is either referenced, or the forced bit is
+ ** set. Otherwise, the import is ignored (no need to link in something
+ ** that isn't used).
+ */
S = SymList;
while (S) {
if ((S->Flags & (SF_UNUSED | SF_IMPORT)) == SF_IMPORT &&
unsigned SymFlags = GetSymInfoFlags (S, &ConstVal);
/* Check if this symbol has a size. If so, remember it in the
- * flags.
- */
+ ** flags.
+ */
long Size;
SymEntry* SizeSym = FindSizeOfSymbol (S);
if (SizeSym != 0 && SymIsConst (SizeSym, &Size)) {
ObjWriteVar (Count);
/* Walk through list and write all symbols to the file. Ignore size
- * symbols.
- */
+ ** symbols.
+ */
S = SymList;
while (S) {
if (IsDbgSym (S)) {
unsigned SymFlags = GetSymInfoFlags (S, &ConstVal);
/* Check if this symbol has a size. If so, remember it in the
- * flags.
- */
+ ** flags.
+ */
long Size;
SymEntry* SizeSym = FindSizeOfSymbol (S);
if (SizeSym != 0 && SymIsConst (SizeSym, &Size)) {
ObjWrite8 (S->AddrSize);
/* Write the id of the parent. For normal symbols, this is a
- * scope (symbol table), for cheap locals, it's a symbol.
- */
+ ** scope (symbol table), for cheap locals, it's a symbol.
+ */
if (SYM_IS_STD (SymFlags)) {
ObjWriteVar (S->Sym.Tab->Id);
} else {
unsigned Flags = 0;
/* Check if this scope has a size. If so, remember it in the
- * flags.
- */
+ ** flags.
+ */
long Size;
SymEntry* SizeSym = FindSizeOfScope (S);
if (SizeSym != 0 && SymIsConst (SizeSym, &Size)) {
SymTable* SymFindAnyScope (SymTable* Parent, const StrBuf* Name);
/* Find a scope in the given or any of its parent scopes. The function will
- * never create a new symbol, since this can only be done in one specific
- * scope.
- */
+** never create a new symbol, since this can only be done in one specific
+** scope.
+*/
SymEntry* SymFindLocal (SymEntry* Parent, const StrBuf* Name, SymFindAction Action);
/* Find a cheap local symbol. If Action contains SYM_ALLOC_NEW and the entry is
- * not found, create a new one. Return the entry found, or the new entry
- * created, or - in case Action is SYM_FIND_EXISTING - return 0.
- */
+** not found, create a new one. Return the entry found, or the new entry
+** created, or - in case Action is SYM_FIND_EXISTING - return 0.
+*/
SymEntry* SymFind (SymTable* Scope, const StrBuf* Name, SymFindAction Action);
/* Find a new symbol table entry in the given table. If Action contains
- * SYM_ALLOC_NEW and the entry is not found, create a new one. Return the
- * entry found, or the new entry created, or - in case Action is
- * SYM_FIND_EXISTING - return 0.
- */
+** SYM_ALLOC_NEW and the entry is not found, create a new one. Return the
+** entry found, or the new entry created, or - in case Action is
+** SYM_FIND_EXISTING - return 0.
+*/
SymEntry* SymFindAny (SymTable* Scope, const StrBuf* Name);
/* Find a symbol in the given or any of its parent scopes. The function will
- * never create a new symbol, since this can only be done in one specific
- * scope.
- */
+** never create a new symbol, since this can only be done in one specific
+** scope.
+*/
#if defined(HAVE_INLINE)
INLINE unsigned char GetSymTabType (const SymTable* S)
void CopyToken (Token* Dst, const Token* Src)
/* Copy a token from Src to Dst. The current value of Dst.SVal is free'd,
- * so Dst must be initialized.
- */
+** so Dst must be initialized.
+*/
{
/* Copy the fields */
Dst->Tok = Src->Tok;
void CopyToken (Token* Dst, const Token* Src);
/* Copy a token. The current value of Dst.SVal is free'd, so Dst must be
- * initialized.
- */
+** initialized.
+*/
enum token_t GetTokListTerm (enum token_t Term)
/* Determine if the following token list is enclosed in curly braces. This is
- * the case if the next token is the opening brace. If so, skip it and return
- * a closing brace, otherwise return Term.
- */
+** the case if the next token is the opening brace. If so, skip it and return
+** a closing brace, otherwise return Term.
+*/
{
if (CurTok.Tok == TOK_LCURLY) {
NextTok ();
static int ReplayTokList (void* List)
/* Function that gets the next token from a token list and sets it. This
- * function may be used together with the PushInput function from the istack
- * module.
- */
+** function may be used together with the PushInput function from the istack
+** module.
+*/
{
/* Cast the generic pointer to an actual list */
TokList* L = List;
/* If there are no more tokens, decrement the repeat counter. If it goes
- * zero, delete the list and remove the function from the stack.
- */
+ ** zero, delete the list and remove the function from the stack.
+ */
if (L->Last == 0) {
if (++L->RepCount >= L->RepMax) {
/* Done with this list */
L->LI = StartLine (&CurTok.Pos, LI_TYPE_ASM, PushCounter);
/* If a check function is defined, call it, so it may look at the token
- * just set and changed it as apropriate.
- */
+ ** just set and changed it as apropriate.
+ */
if (L->Check) {
L->Check (L);
}
void PushTokList (TokList* List, const char* Desc)
/* Push a token list to be used as input for InputFromStack. This includes
- * several initializations needed in the token list structure, so don't use
- * PushInput directly.
- */
+** several initializations needed in the token list structure, so don't use
+** PushInput directly.
+*/
{
/* If the list is empty, just delete it and bail out */
if (List->Count == 0) {
token_t GetTokListTerm (token_t Term);
/* Determine if the following token list is enclosed in curly braces. This is
- * the case if the next token is the opening brace. If so, skip it and return
- * a closing brace, otherwise return Term.
- */
+** the case if the next token is the opening brace. If so, skip it and return
+** a closing brace, otherwise return Term.
+*/
void AddCurTok (TokList* T);
/* Add the current token to the token list */
void PushTokList (TokList* List, const char* Desc);
/* Push a token list to be used as input for InputFromStack. This includes
- * several initializations needed in the token list structure, so don't use
- * PushInput directly.
- */
+** several initializations needed in the token list structure, so don't use
+** PushInput directly.
+*/
static ULabel* NewULabel (ExprNode* Val)
/* Create a new ULabel and insert it into the collection. The created label
- * structure is returned.
- */
+** structure is returned.
+*/
{
/* Allocate memory for the ULabel structure */
ULabel* L = xmalloc (sizeof (ULabel));
ExprNode* ULabRef (int Which)
/* Get an unnamed label. If Which is negative, it is a backreference (a
- * reference to an already defined label), and the function will return a
- * segment relative expression. If Which is positive, it is a forward ref,
- * and the function will return a expression node for an unnamed label that
- * must be resolved later.
- */
+** reference to an already defined label), and the function will return a
+** segment relative expression. If Which is positive, it is a forward ref,
+** and the function will return a expression node for an unnamed label that
+** must be resolved later.
+*/
{
int Index;
ULabel* L;
++L->Ref;
/* If the label is already defined, return its value, otherwise return
- * just a reference.
- */
+ ** just a reference.
+ */
if (L->Val) {
return CloneExpr (L->Val);
} else {
{
if (ULabDefCount < CollCount (&ULabList)) {
/* We did already have a forward reference to this label, so has
- * already been generated, but doesn't have a value. Use the current
- * PC for the label value.
- */
+ ** already been generated, but doesn't have a value. Use the current
+ ** PC for the label value.
+ */
ULabel* L = CollAtUnchecked (&ULabList, ULabDefCount);
CHECK (L->Val == 0);
L->Val = GenCurrentPC ();
ExprNode* ULabResolve (unsigned Index)
/* Return a valid expression for the unnamed label with the given index. This
- * is used to resolve unnamed labels when assembly is done, so it is an error
- * if a label is still undefined in this phase.
- */
+** is used to resolve unnamed labels when assembly is done, so it is an error
+** if a label is still undefined in this phase.
+*/
{
/* Get the label and check that it is defined */
ULabel* L = CollAt (&ULabList, Index);
void ULabDone (void)
/* Run through all unnamed labels, check for anomalies and errors and do
- * necessary cleanups.
- */
+** necessary cleanups.
+*/
{
/* Check if there are undefined labels */
unsigned I = ULabDefCount;
}
/* Walk over all labels and emit a warning if any unreferenced ones
- * are found. Remove line infos because they're no longer needed.
- */
+ ** are found. Remove line infos because they're no longer needed.
+ */
for (I = 0; I < CollCount (&ULabList); ++I) {
ULabel* L = CollAtUnchecked (&ULabList, I);
if (L->Ref == 0) {
ExprNode* ULabRef (int Which);
/* Get an unnamed label. If Which is negative, it is a backreference (a
- * reference to an already defined label), and the function will return a
- * segment relative expression. If Which is positive, it is a forward ref,
- * and the function will return a expression node for an unnamed label that
- * must be resolved later.
- */
+** reference to an already defined label), and the function will return a
+** segment relative expression. If Which is positive, it is a forward ref,
+** and the function will return a expression node for an unnamed label that
+** must be resolved later.
+*/
void ULabDef (void);
/* Define an unnamed label at the current PC */
ExprNode* ULabResolve (unsigned Index);
/* Return a valid expression for the unnamed label with the given index. This
- * is used to resolve unnamed labels when assembly is done, so it is an error
- * if a label is still undefined in this phase.
- */
+** is used to resolve unnamed labels when assembly is done, so it is an error
+** if a label is still undefined in this phase.
+*/
void ULabDone (void);
/* Run through all unnamed labels, check for anomalies and errors and do
- * necessary cleanups.
- */
+** necessary cleanups.
+*/
char* AnonName (char* Buf, const char* Spec)
/* Get a name for an anonymous variable or type. The given buffer is expected
- * to be IDENTSIZE characters long. A pointer to the buffer is returned.
- */
+** to be IDENTSIZE characters long. A pointer to the buffer is returned.
+*/
{
static unsigned ACount = 0;
xsprintf (Buf, IDENTSIZE, "%s-%s-%04X", AnonTag, Spec, ++ACount);
char* AnonName (char* Buf, const char* Spec);
/* Get a name for an anonymous variable or type. The given buffer is expected
- * to be IDENTSIZE characters long. A pointer to the buffer is returned.
- */
+** to be IDENTSIZE characters long. A pointer to the buffer is returned.
+*/
int IsAnonName (const char* Name);
/* Check if the given symbol name is that of an anonymous symbol */
void MoveCode (const CodeMark* Start, const CodeMark* End, const CodeMark* Target)
/* Move the code between Start (inclusive) and End (exclusive) to
- * (before) Target. The code marks aren't updated.
- */
+** (before) Target. The code marks aren't updated.
+*/
{
CS_MoveEntries (CS->Code, Start->Pos, End->Pos - Start->Pos, Target->Pos);
}
void MoveCode (const CodeMark* Start, const CodeMark* End, const CodeMark* Target);
/* Move the code between Start (inclusive) and End (exclusive) to
- * (before) Target. The code marks aren't updated.
- */
+** (before) Target. The code marks aren't updated.
+*/
int CodeRangeIsEmpty (const CodeMark* Start, const CodeMark* End);
/* Return true if the given code range is empty (no code between Start and End) */
const char* LocalLabelName (unsigned L)
/* Make a label name from the given label number. The label name will be
- * created in static storage and overwritten when calling the function
- * again.
- */
+** created in static storage and overwritten when calling the function
+** again.
+*/
{
static char Buf[64];
sprintf (Buf, "L%04X", L);
const char* LocalLabelName (unsigned L);
/* Make a label name from the given label number. The label name will be
- * created in static storage and overwritten when calling the function
- * again.
- */
+** created in static storage and overwritten when calling the function
+** again.
+*/
int IsLocalLabelName (const char* Name);
/* Return true if Name is the name of a local label */
static void AsmErrorSkip (void)
/* Called in case of an error, skips tokens until the closing paren or a
- * semicolon is reached.
- */
+** semicolon is reached.
+*/
{
static const token_t TokenList[] = { TOK_RPAREN, TOK_SEMI };
SkipTokens (TokenList, sizeof(TokenList) / sizeof(TokenList[0]));
static SymEntry* AsmGetSym (unsigned Arg, unsigned Type)
/* Find the symbol with the name currently in NextTok. The symbol must be of
- * the given type. On errors, NULL is returned.
- */
+** the given type. On errors, NULL is returned.
+*/
{
SymEntry* Sym;
}
/* The symbol may be a parameter to a variadic function. In this case, we
- * don't have a fixed stack offset, so check it and bail out with an error
- * if this is the case.
- */
+ ** don't have a fixed stack offset, so check it and bail out with an error
+ ** if this is the case.
+ */
if ((Sym->Flags & SC_PARAM) == SC_PARAM && F_IsVariadic (CurrentFunc)) {
Error ("Argument %u has no fixed stack offset", Arg);
AsmErrorSkip ();
NextToken ();
/* Parse the statement. It may contain several lines and one or more
- * of the following place holders:
- * %b - Numerical 8 bit value
- * %w - Numerical 16 bit value
- * %l - Numerical 32 bit value
- * %v - Assembler name of a (global) variable
- * %o - Stack offset of a (local) variable
- * %g - Assembler name of a C label
- * %s - Any argument converted to a string (almost)
- * %% - The % sign
- */
+ ** of the following place holders:
+ ** %b - Numerical 8 bit value
+ ** %w - Numerical 16 bit value
+ ** %l - Numerical 32 bit value
+ ** %v - Assembler name of a (global) variable
+ ** %o - Stack offset of a (local) variable
+ ** %g - Assembler name of a C label
+ ** %s - Any argument converted to a string (almost)
+ ** %% - The % sign
+ */
Arg = 0;
while ((C = SB_Get (&S)) != '\0') {
void AsmStatement (void)
/* This function parses ASM statements. The syntax of the ASM directive
- * looks like the one defined for C++ (C has no ASM directive), that is,
- * a string literal in parenthesis.
- */
+** looks like the one defined for C++ (C has no ASM directive), that is,
+** a string literal in parenthesis.
+*/
{
/* Skip the ASM */
NextToken ();
Error ("String literal expected");
/* Try some smart error recovery: Skip tokens until we reach the
- * enclosing paren, or a semicolon.
- */
+ ** enclosing paren, or a semicolon.
+ */
AsmErrorSkip ();
} else {
void AsmStatement (void);
/* This function parses ASM statements. The syntax of the ASM directive
- * looks like the one defined for C++ (C has no ASM directive), that is,
- * a string literal in parenthesis.
- */
+** looks like the one defined for C++ (C has no ASM directive), that is,
+** a string literal in parenthesis.
+*/
NextToken ();
/* cc65 does not have full support for handling structs by value. Since
- * assigning structs is one of the more useful operations from this
- * family, allow it here.
- */
+ ** assigning structs is one of the more useful operations from this
+ ** family, allow it here.
+ */
if (IsClassStruct (ltype)) {
/* Get the size of the left hand side. */
unsigned Size = SizeOf (ltype);
/* If the size is that of a basic type (char, int, long), we will copy
- * the struct using the primary register, otherwise we use memcpy. In
- * the former case, push the address only if really needed.
- */
+ ** the struct using the primary register, otherwise we use memcpy. In
+ ** the former case, push the address only if really needed.
+ */
int UseReg = 1;
Type* stype;
switch (Size) {
} else {
/* We have an rvalue. This can only happen if a function returns
- * a struct, since there is no other way to generate an expression
- * that as a struct as an rvalue result. We allow only 1, 2, and 4
- * byte sized structs and do direct assignment.
- */
+ ** a struct, since there is no other way to generate an expression
+ ** that has a struct as an rvalue result. We allow only 1, 2, and 4
+ ** byte sized structs, and do direct assignment.
+ */
if (UseReg) {
/* Do the store */
Store (Expr, stype);
unsigned Flags;
/* If the bit-field fits within one byte, do the following operations
- * with bytes.
- */
+ ** with bytes.
+ */
if (Expr->BitOffs / CHAR_BITS == (Expr->BitOffs + Expr->BitWidth - 1) / CHAR_BITS) {
Expr->Type = type_uchar;
}
MarkedExprWithCheck (hie1, &Expr2);
/* Do type conversion if necessary. Beware: Do not use char type
- * here!
- */
+ ** here!
+ */
TypeConversion (&Expr2, ltype);
/* Special treatment if the value is constant. */
/* Beware: Expr2 may contain side effects, so there must not be
- * code generated for Expr2.
- */
+ ** code generated for Expr2.
+ */
if (ED_IsConstAbsInt (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)) {
/* Get the value and apply the mask */
RemoveCode (&PushPos);
/* If the value is equal to the mask now, all bits are one, and we
- * can remove the mask operation from above.
- */
+ ** can remove the mask operation from above.
+ */
if (Val == Mask) {
RemoveCode (&AndPos);
}
int SearchCaseNode (const Collection* Nodes, unsigned char Key, int* Index)
/* Search for a node in the given collection. If the node has been found,
- * set Index to the index of the node and return true. If the node was not
- * found, set Index the the insertion position of the node and return
- * false.
- */
+** set Index to the index of the node and return true. If the node was not
+** found, set Index the the insertion position of the node and return
+** false.
+*/
{
/* Do a binary search */
int First = 0;
unsigned InsertCaseValue (Collection* Nodes, unsigned long Val, unsigned Depth)
/* Insert a new case value into a CaseNode tree with the given depth. Return
- * the code label for the value.
- */
+** the code label for the value.
+*/
{
CaseNode* N = 0;
unsigned CaseLabel = GetLocalLabel (); /* Code label */
CollInsert (Nodes, N, Index);
/* If this is not the last round, create the collection for
- * the subnodes, otherwise get a label for the code.
- */
+ ** the subnodes, otherwise get a label for the code.
+ */
if (Depth > 0) {
N->Nodes = NewCollection ();
} else {
N = CollAt (Nodes, Index);
/* If this is the last round and we found a node, we have a
- * duplicate case label in a switch.
- */
+ ** duplicate case label in a switch.
+ */
if (Depth == 0) {
Error ("Duplicate case label");
}
int SearchCaseNode (const Collection* Nodes, unsigned char Key, int* Index);
/* Search for a node in the given collection. If the node has been found,
- * set Index to the index of the node and return true. If the node was not
- * found, set Index the the insertion position of the node and return
- * false.
- */
+** set Index to the index of the node and return true. If the node was not
+** found, set Index the the insertion position of the node and return
+** false.
+*/
unsigned InsertCaseValue (Collection* Nodes, unsigned long Val, unsigned Depth);
/* Insert a new case value into a CaseNode tree with the given depth. Return
- * the code label for the value.
- */
+** the code label for the value.
+*/
static int NumArg (const char* Arg, unsigned long* Num)
/* If the given argument is numerical, convert it and return true. Otherwise
- * set Num to zero and return false.
- */
+** set Num to zero and return false.
+*/
{
char* End;
unsigned long Val;
}
/* Convert the value. strtol is not exactly what we want here, but it's
- * cheap and may be replaced by something fancier later.
- */
+ ** cheap and may be replaced by something fancier later.
+ */
Val = strtoul (Arg, &End, Base);
/* Check if the conversion was successful */
const ZPInfo* Info;
/* If this is a subroutine call, or a jump to an external function,
- * lookup the information about this function and use it. The jump itself
- * does not change any registers, so we don't need to use the data from D.
- */
+ ** lookup the information about this function and use it. The jump itself
+ ** does not change any registers, so we don't need to use the data from D.
+ */
if ((E->Info & (OF_UBRA | OF_CALL)) != 0 && E->JumpTo == 0) {
/* A subroutine call or jump to external symbol (function exit) */
GetFuncInfo (E->Arg, &E->Use, &E->Chg);
} else {
/* Some other instruction. Use the values from the opcode description
- * plus addressing mode info.
- */
+ ** plus addressing mode info.
+ */
E->Use = D->Use | GetAMUseInfo (E->AM);
E->Chg = D->Chg;
const char* MakeHexArg (unsigned Num)
/* Convert Num into a string in the form $XY, suitable for passing it as an
- * argument to NewCodeEntry, and return a pointer to the string.
- * BEWARE: The function returns a pointer to a static buffer, so the value is
- * gone if you call it twice (and apart from that it's not thread and signal
- * safe).
- */
+** argument to NewCodeEntry, and return a pointer to the string.
+** BEWARE: The function returns a pointer to a static buffer, so the value is
+** gone if you call it twice (and apart from that it's not thread and signal
+** safe).
+*/
{
static char Buf[16];
xsprintf (Buf, sizeof (Buf), "$%02X", (unsigned char) Num);
void CE_ReplaceOPC (CodeEntry* E, opc_t OPC)
/* Replace the opcode of the instruction. This will also replace related info,
- * Size, Use and Chg, but it will NOT update any arguments or labels.
- */
+** Size, Use and Chg, but it will NOT update any arguments or labels.
+*/
{
/* Get the opcode descriptor */
const OPCDesc* D = GetOPCDesc (OPC);
void CE_ClearJumpTo (CodeEntry* E)
/* Clear the JumpTo entry and the argument (which contained the name of the
- * label). Note: The function will not clear the backpointer from the label,
- * so use it with care.
- */
+** label). Note: The function will not clear the backpointer from the label,
+** so use it with care.
+*/
{
/* Clear the JumpTo entry */
E->JumpTo = 0;
void CE_SetNumArg (CodeEntry* E, long Num)
/* Set a new numeric argument for the given code entry that must already
- * have a numeric argument.
- */
+** have a numeric argument.
+*/
{
char Buf[16];
int CE_IsKnownImm (const CodeEntry* E, unsigned long Num)
/* Return true if the argument of E is a constant immediate value that is
- * equal to Num.
- */
+** equal to Num.
+*/
{
return (E->AM == AM65_IMM && CE_HasNumArg (E) && E->Num == Num);
}
int CE_UseLoadFlags (CodeEntry* E)
/* Return true if the instruction uses any flags that are set by a load of
- * a register (N and Z).
- */
+** a register (N and Z).
+*/
{
/* Follow unconditional branches, but beware of endless loops. After this,
- * E will point to the first entry that is not a branch.
- */
+ ** E will point to the first entry that is not a branch.
+ */
if (E->Info & OF_UBRA) {
Collection C = AUTO_COLLECTION_INITIALIZER;
void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs)
/* Generate register info for this instruction. If an old info exists, it is
- * overwritten.
- */
+** overwritten.
+*/
{
/* Pointers to the register contents */
RegContents* In;
case OP65_ADC:
/* We don't know the value of the carry, so the result is
- * always unknown.
- */
+ ** always unknown.
+ */
Out->RegA = UNKNOWN_REGVAL;
break;
const char* MakeHexArg (unsigned Num);
/* Convert Num into a string in the form $XY, suitable for passing it as an
- * argument to NewCodeEntry, and return a pointer to the string.
- * BEWARE: The function returns a pointer to a static buffer, so the value is
- * gone if you call it twice (and apart from that it's not thread and signal
- * safe).
- */
+** argument to NewCodeEntry, and return a pointer to the string.
+** BEWARE: The function returns a pointer to a static buffer, so the value is
+** gone if you call it twice (and apart from that it's not thread and signal
+** safe).
+*/
CodeEntry* NewCodeEntry (opc_t OPC, am_t AM, const char* Arg,
CodeLabel* JumpTo, LineInfo* LI);
void CE_ReplaceOPC (CodeEntry* E, opc_t OPC);
/* Replace the opcode of the instruction. This will also replace related info,
- * Size, Use and Chg, but it will NOT update any arguments or labels.
- */
+** Size, Use and Chg, but it will NOT update any arguments or labels.
+*/
int CodeEntriesAreEqual (const CodeEntry* E1, const CodeEntry* E2);
/* Check if both code entries are equal */
void CE_ClearJumpTo (CodeEntry* E);
/* Clear the JumpTo entry and the argument (which contained the name of the
- * label). Note: The function will not clear the backpointer from the label,
- * so use it with care.
- */
+** label). Note: The function will not clear the backpointer from the label,
+** so use it with care.
+*/
#if defined(HAVE_INLINE)
INLINE int CE_HasLabel (const CodeEntry* E)
void CE_SetNumArg (CodeEntry* E, long Num);
/* Set a new numeric argument for the given code entry that must already
- * have a numeric argument.
- */
+** have a numeric argument.
+*/
int CE_IsConstImm (const CodeEntry* E);
/* Return true if the argument of E is a constant immediate value */
int CE_IsKnownImm (const CodeEntry* E, unsigned long Num);
/* Return true if the argument of E is a constant immediate value that is
- * equal to Num.
- */
+** equal to Num.
+*/
#if defined(HAVE_INLINE)
INLINE int CE_IsCallTo (const CodeEntry* E, const char* Name)
int CE_UseLoadFlags (CodeEntry* E);
/* Return true if the instruction uses any flags that are set by a load of
- * a register (N and Z).
- */
+** a register (N and Z).
+*/
void CE_FreeRegInfo (CodeEntry* E);
/* Free an existing register info struct */
void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs);
/* Generate register info for this instruction. If an old info exists, it is
- * overwritten.
- */
+** overwritten.
+*/
void CE_Output (const CodeEntry* E);
/* Output the code entry to the output file */
{
if (DebugInfo) {
/* We have to place this into the global text segment, so it will
- * appear before all .dbg line statements.
- */
+ ** appear before all .dbg line statements.
+ */
TS_AddLine (GS->Text, "\t.dbg\t\tfile, \"%s\", %lu, %lu", Name, Size, MTime);
}
}
static unsigned MakeByteOffs (unsigned Flags, unsigned Offs)
/* The value in Offs is an offset to an address in a/x. Make sure, an object
- * of the type given in Flags can be loaded or stored into this address by
- * adding part of the offset to the address in ax, so that the remaining
- * offset fits into an index register. Return the remaining offset.
- */
+** of the type given in Flags can be loaded or stored into this address by
+** adding part of the offset to the address in ax, so that the remaining
+** offset fits into an index register. Return the remaining offset.
+*/
{
/* If the offset is too large for a byte register, add the high byte
- * of the offset to the primary. Beware: We need a special correction
- * if the offset in the low byte will overflow in the operation.
- */
+ ** of the offset to the primary. Beware: We need a special correction
+ ** if the offset in the low byte will overflow in the operation.
+ */
unsigned O = Offs & ~0xFFU;
if ((Offs & 0xFF) > 256 - sizeofarg (Flags)) {
/* We need to add the low byte also */
/* Define label as a local alias for baselabel+offs */
{
/* We need an intermediate buffer here since LocalLabelName uses a
- * static buffer which changes with each call.
- */
+ ** static buffer which changes with each call.
+ */
StrBuf L = AUTO_STRBUF_INITIALIZER;
SB_AppendStr (&L, LocalLabelName (label));
SB_Terminate (&L);
/* Remember the argument size of a function. The variable is set by g_enter
- * and used by g_leave. If the functions gets its argument size by the caller
- * (variable param list or function without prototype), g_enter will set the
- * value to -1.
- */
+** and used by g_leave. If the function gets its argument size by the caller
+** (variable param list or function without prototype), g_enter will set the
+** value to -1.
+*/
static int funcargs;
} else if (StackOffs <= RegOffs) {
/* More bytes, but the relation between the register offset in the
- * register bank and the stack offset allows us to generate short
- * code that uses just one index register.
- */
+ ** register bank and the stack offset allows us to generate short
+ ** code that uses just one index register.
+ */
unsigned Label = GetLocalLabel ();
AddCodeLine ("ldy #$%02X", StackOffs);
g_defcodelabel (Label);
} else {
- /* Ok, this is the generic code. We need to save X because the
- * caller will only save A.
- */
+ /* OK, this is the generic code. We need to save X because the
+ ** caller will only save A.
+ */
unsigned Label = GetLocalLabel ();
AddCodeLine ("stx tmp1");
AddCodeLine ("ldy #$%02X", (unsigned char) (StackOffs + Bytes - 1));
void g_getind (unsigned Flags, unsigned Offs)
/* Fetch the specified object type indirect through the primary register
- * into the primary register
- */
+** into the primary register
+*/
{
/* If the offset is greater than 255, add the part that is > 255 to
- * the primary. This way we get an easy addition and use the low byte
- * as the offset
- */
+ ** the primary. This way we get an easy addition and use the low byte
+ ** as the offset
+ */
Offs = MakeByteOffs (Flags, Offs);
/* Handle the indirect fetch */
void g_leavariadic (int Offs)
/* Fetch the address of a parameter in a variadic function into the primary
- * register
- */
+** register
+*/
{
unsigned ArgSizeOffs;
Offs -= StackPtr;
/* Get the offset of the parameter which is stored at sp+0 on function
- * entry and check if this offset is reachable with a byte offset.
- */
+ ** entry and check if this offset is reachable with a byte offset.
+ */
CHECK (StackPtr <= 0);
ArgSizeOffs = -StackPtr;
CheckLocalOffs (ArgSizeOffs);
void g_putind (unsigned Flags, unsigned Offs)
/* Store the specified object type in the primary register at the address
- * on the top of the stack
- */
+** on the top of the stack
+*/
{
/* We can handle offsets below $100 directly, larger offsets must be added
- * to the address. Since a/x is in use, best code is achieved by adding
- * just the high byte. Be sure to check if the low byte will overflow while
- * while storing.
- */
+ ** to the address. Since a/x is in use, best code is achieved by adding
+ ** just the high byte. Be sure to check if the low byte will overflow while
+ ** while storing.
+ */
if ((Offs & 0xFF) > 256 - sizeofarg (Flags | CF_FORCECHAR)) {
/* Overflow - we need to add the low byte also */
unsigned g_typeadjust (unsigned lhs, unsigned rhs)
/* Adjust the integer operands before doing a binary operation. lhs is a flags
- * value, that corresponds to the value on TOS, rhs corresponds to the value
- * in (e)ax. The return value is the the flags value for the resulting type.
- */
+** value, that corresponds to the value on TOS, rhs corresponds to the value
+** in (e)ax. The return value is the the flags value for the resulting type.
+*/
{
unsigned ltype, rtype;
unsigned result;
}
/* Determine the result type for the operation:
- * - The result is const if both operands are const.
- * - The result is unsigned if one of the operands is unsigned.
- * - The result is long if one of the operands is long.
- * - Otherwise the result is int sized.
- */
+ ** - The result is const if both operands are const.
+ ** - The result is unsigned if one of the operands is unsigned.
+ ** - The result is long if one of the operands is long.
+ ** - Otherwise the result is int sized.
+ */
result = (lhs & CF_CONST) & (rhs & CF_CONST);
result |= (lhs & CF_UNSIGNED) | (rhs & CF_UNSIGNED);
if (rtype == CF_LONG || ltype == CF_LONG) {
unsigned g_typecast (unsigned lhs, unsigned rhs)
/* Cast the value in the primary register to the operand size that is flagged
- * by the lhs value. Return the result value.
- */
+** by the lhs value. Return the result value.
+*/
{
unsigned ltype, rtype;
}
/* Do not need any other action. If the left type is int, and the primary
- * register is long, it will be automagically truncated. If the right hand
- * side is const, it is not located in the primary register and handled by
- * the expression parser code.
- */
+ ** register is long, it will be automagically truncated. If the right hand
+ ** side is const, it is not located in the primary register and handled by
+ ** the expression parser code.
+ */
/* Result is const if the right hand side was const */
lhs |= (rhs & CF_CONST);
/* The resulting type is that of the left hand side (that's why you called
- * this function :-)
- */
+ ** this function :-)
+ */
return lhs;
}
void g_scale (unsigned flags, long val)
/* Scale the value in the primary register by the given value. If val is positive,
- * scale up, is val is negative, scale down. This function is used to scale
- * the operands or results of pointer arithmetic by the size of the type, the
- * pointer points to.
- */
+** scale up, is val is negative, scale down. This function is used to scale
+** the operands or results of pointer arithmetic by the size of the type, the
+** pointer points to.
+*/
{
int p2;
/* Emit += for the location with address in ax */
{
/* If the offset is too large for a byte register, add the high byte
- * of the offset to the primary. Beware: We need a special correction
- * if the offset in the low byte will overflow in the operation.
- */
+ ** of the offset to the primary. Beware: We need a special correction
+ ** if the offset in the low byte will overflow in the operation.
+ */
offs = MakeByteOffs (flags, offs);
/* Check the size and determine operation */
/* Emit -= for the location with address in ax */
{
/* If the offset is too large for a byte register, add the high byte
- * of the offset to the primary. Beware: We need a special correction
- * if the offset in the low byte will overflow in the operation.
- */
+ ** of the offset to the primary. Beware: We need a special correction
+ ** if the offset in the low byte will overflow in the operation.
+ */
offs = MakeByteOffs (flags, offs);
/* Check the size and determine operation */
void g_cmp (unsigned flags, unsigned long val)
/* Immidiate compare. The primary register will not be changed, Z flag
- * will be set.
- */
+** will be set.
+*/
{
unsigned L;
static void oper (unsigned Flags, unsigned long Val, const char** Subs)
/* Encode a binary operation. subs is a pointer to four strings:
- * 0 --> Operate on ints
- * 1 --> Operate on unsigneds
- * 2 --> Operate on longs
- * 3 --> Operate on unsigned longs
- */
+** 0 --> Operate on ints
+** 1 --> Operate on unsigneds
+** 2 --> Operate on longs
+** 3 --> Operate on unsigned longs
+*/
{
/* Determine the offset into the array */
if (Flags & CF_UNSIGNED) {
void g_swap (unsigned flags)
/* Swap the primary register and the top of the stack. flags give the type
- * of *both* values (must have same size).
- */
+** of *both* values (must have same size).
+*/
{
switch (flags & CF_TYPEMASK) {
{
if (Space > 255) {
/* Inline the code since calling addysp repeatedly is quite some
- * overhead.
- */
+ ** overhead.
+ */
AddCodeLine ("pha");
AddCodeLine ("lda #$%02X", (unsigned char) Space);
AddCodeLine ("clc");
g_drop (-Space);
} else if (Space > 255) {
/* Inline the code since calling subysp repeatedly is quite some
- * overhead.
- */
+ ** overhead.
+ */
AddCodeLine ("pha");
AddCodeLine ("lda sp");
AddCodeLine ("sec");
}
/* If the right hand side is const, the lhs is not on stack but still
- * in the primary register.
- */
+ ** in the primary register.
+ */
if (flags & CF_CONST) {
switch (flags & CF_TYPEMASK) {
}
/* If we go here, we didn't emit code. Push the lhs on stack and fall
- * into the normal, non-optimized stuff.
- */
+ ** into the normal, non-optimized stuff.
+ */
flags &= ~CF_FORCECHAR; /* Handle chars as ints */
g_push (flags & ~CF_CONST, 0);
};
/* If the right hand side is const, the lhs is not on stack but still
- * in the primary register.
- */
+ ** in the primary register.
+ */
if (flags & CF_CONST) {
switch (flags & CF_TYPEMASK) {
}
/* If we go here, we didn't emit code. Push the lhs on stack and fall
- * into the normal, non-optimized stuff. Note: The standard stuff will
- * always work with ints.
- */
+ ** into the normal, non-optimized stuff. Note: The standard stuff will
+ ** always work with ints.
+ */
flags &= ~CF_FORCECHAR;
g_push (flags & ~CF_CONST, 0);
}
/* If the right hand side is const, the lhs is not on stack but still
- * in the primary register.
- */
+ ** in the primary register.
+ */
if (flags & CF_CONST) {
switch (flags & CF_TYPEMASK) {
}
/* If we go here, we didn't emit code. Push the lhs on stack and fall
- * into the normal, non-optimized stuff. Note: The standard stuff will
- * always work with ints.
- */
+ ** into the normal, non-optimized stuff. Note: The standard stuff will
+ ** always work with ints.
+ */
flags &= ~CF_FORCECHAR;
g_push (flags & ~CF_CONST, 0);
}
};
/* If the right hand side is const, the lhs is not on stack but still
- * in the primary register.
- */
+ ** in the primary register.
+ */
if (Flags & CF_CONST) {
switch (Flags & CF_TYPEMASK) {
}
/* If we go here, we didn't emit code. Push the lhs on stack and fall
- * into the normal, non-optimized stuff. Note: The standard stuff will
- * always work with ints.
- */
+ ** into the normal, non-optimized stuff. Note: The standard stuff will
+ ** always work with ints.
+ */
Flags &= ~CF_FORCECHAR;
g_push (Flags & ~CF_CONST, 0);
}
};
/* If the right hand side is const, the lhs is not on stack but still
- * in the primary register.
- */
+ ** in the primary register.
+ */
if (flags & CF_CONST) {
switch (flags & CF_TYPEMASK) {
}
/* If we go here, we didn't emit code. Push the lhs on stack and fall
- * into the normal, non-optimized stuff. Note: The standard stuff will
- * always work with ints.
- */
+ ** into the normal, non-optimized stuff. Note: The standard stuff will
+ ** always work with ints.
+ */
flags &= ~CF_FORCECHAR;
g_push (flags & ~CF_CONST, 0);
}
/* If the right hand side is const, the lhs is not on stack but still
- * in the primary register.
- */
+ ** in the primary register.
+ */
if (flags & CF_CONST) {
switch (flags & CF_TYPEMASK) {
}
/* If we go here, we didn't emit code. Push the lhs on stack and fall
- * into the normal, non-optimized stuff. Note: The standard stuff will
- * always work with ints.
- */
+ ** into the normal, non-optimized stuff. Note: The standard stuff will
+ ** always work with ints.
+ */
flags &= ~CF_FORCECHAR;
g_push (flags & ~CF_CONST, 0);
}
/*
- * Following are the conditional operators. They compare the TOS against
- * the primary and put a literal 1 in the primary if the condition is
- * true, otherwise they clear the primary register
- */
+** Following are the conditional operators. They compare the TOS against
+** the primary and put a literal 1 in the primary if the condition is
+** true, otherwise they clear the primary register
+*/
unsigned L;
/* If the right hand side is const, the lhs is not on stack but still
- * in the primary register.
- */
+ ** in the primary register.
+ */
if (flags & CF_CONST) {
switch (flags & CF_TYPEMASK) {
}
/* If we go here, we didn't emit code. Push the lhs on stack and fall
- * into the normal, non-optimized stuff. Note: The standard stuff will
- * always work with ints.
- */
+ ** into the normal, non-optimized stuff. Note: The standard stuff will
+ ** always work with ints.
+ */
flags &= ~CF_FORCECHAR;
g_push (flags & ~CF_CONST, 0);
}
unsigned L;
/* If the right hand side is const, the lhs is not on stack but still
- * in the primary register.
- */
+ ** in the primary register.
+ */
if (flags & CF_CONST) {
switch (flags & CF_TYPEMASK) {
}
/* If we go here, we didn't emit code. Push the lhs on stack and fall
- * into the normal, non-optimized stuff. Note: The standard stuff will
- * always work with ints.
- */
+ ** into the normal, non-optimized stuff. Note: The standard stuff will
+ ** always work with ints.
+ */
flags &= ~CF_FORCECHAR;
g_push (flags & ~CF_CONST, 0);
}
unsigned Label;
/* If the right hand side is const, the lhs is not on stack but still
- * in the primary register.
- */
+ ** in the primary register.
+ */
if (flags & CF_CONST) {
/* Because the handling of the overflow flag is too complex for
- * inlining, we can handle only unsigned compares, and signed
- * compares against zero here.
- */
+ ** inlining, we can handle only unsigned compares, and signed
+ ** compares against zero here.
+ */
if (flags & CF_UNSIGNED) {
/* Give a warning in some special cases */
}
/* If we go here, we didn't emit code. Push the lhs on stack and fall
- * into the normal, non-optimized stuff. Note: The standard stuff will
- * always work with ints.
- */
+ ** into the normal, non-optimized stuff. Note: The standard stuff will
+ ** always work with ints.
+ */
flags &= ~CF_FORCECHAR;
g_push (flags & ~CF_CONST, 0);
}
/* If the right hand side is const, the lhs is not on stack but still
- * in the primary register.
- */
+ ** in the primary register.
+ */
if (flags & CF_CONST) {
/* Look at the type */
/* Unsigned compare */
if (val < 0xFF) {
/* Use < instead of <= because the former gives
- * better code on the 6502 than the latter.
- */
+ ** better code on the 6502 than the latter.
+ */
g_lt (flags, val+1);
} else {
/* Always true */
/* Signed compare */
if ((long) val < 0x7F) {
/* Use < instead of <= because the former gives
- * better code on the 6502 than the latter.
- */
+ ** better code on the 6502 than the latter.
+ */
g_lt (flags, val+1);
} else {
/* Always true */
/* Unsigned compare */
if (val < 0xFFFF) {
/* Use < instead of <= because the former gives
- * better code on the 6502 than the latter.
- */
+ ** better code on the 6502 than the latter.
+ */
g_lt (flags, val+1);
} else {
/* Always true */
/* Unsigned compare */
if (val < 0xFFFFFFFF) {
/* Use < instead of <= because the former gives
- * better code on the 6502 than the latter.
- */
+ ** better code on the 6502 than the latter.
+ */
g_lt (flags, val+1);
} else {
/* Always true */
}
/* If we go here, we didn't emit code. Push the lhs on stack and fall
- * into the normal, non-optimized stuff. Note: The standard stuff will
- * always work with ints.
- */
+ ** into the normal, non-optimized stuff. Note: The standard stuff will
+ ** always work with ints.
+ */
flags &= ~CF_FORCECHAR;
g_push (flags & ~CF_CONST, 0);
}
/* If the right hand side is const, the lhs is not on stack but still
- * in the primary register.
- */
+ ** in the primary register.
+ */
if (flags & CF_CONST) {
/* Look at the type */
if (flags & CF_UNSIGNED) {
if (val == 0) {
/* If we have a compare > 0, we will replace it by
- * != 0 here, since both are identical but the
- * latter is easier to optimize.
- */
+ ** != 0 here, since both are identical but the
+ ** latter is easier to optimize.
+ */
g_ne (flags, val);
} else if (val < 0xFF) {
/* Use >= instead of > because the former gives
- * better code on the 6502 than the latter.
- */
+ ** better code on the 6502 than the latter.
+ */
g_ge (flags, val+1);
} else {
/* Never true */
} else {
if ((long) val < 0x7F) {
/* Use >= instead of > because the former gives
- * better code on the 6502 than the latter.
- */
+ ** better code on the 6502 than the latter.
+ */
g_ge (flags, val+1);
} else {
/* Never true */
/* Unsigned compare */
if (val == 0) {
/* If we have a compare > 0, we will replace it by
- * != 0 here, since both are identical but the latter
- * is easier to optimize.
- */
+ ** != 0 here, since both are identical but the latter
+ ** is easier to optimize.
+ */
g_ne (flags, val);
} else if (val < 0xFFFF) {
/* Use >= instead of > because the former gives better
- * code on the 6502 than the latter.
- */
+ ** code on the 6502 than the latter.
+ */
g_ge (flags, val+1);
} else {
/* Never true */
/* Unsigned compare */
if (val == 0) {
/* If we have a compare > 0, we will replace it by
- * != 0 here, since both are identical but the latter
- * is easier to optimize.
- */
+ ** != 0 here, since both are identical but the latter
+ ** is easier to optimize.
+ */
g_ne (flags, val);
} else if (val < 0xFFFFFFFF) {
/* Use >= instead of > because the former gives better
- * code on the 6502 than the latter.
- */
+ ** code on the 6502 than the latter.
+ */
g_ge (flags, val+1);
} else {
/* Never true */
}
/* If we go here, we didn't emit code. Push the lhs on stack and fall
- * into the normal, non-optimized stuff. Note: The standard stuff will
- * always work with ints.
- */
+ ** into the normal, non-optimized stuff. Note: The standard stuff will
+ ** always work with ints.
+ */
flags &= ~CF_FORCECHAR;
g_push (flags & ~CF_CONST, 0);
}
/* If the right hand side is const, the lhs is not on stack but still
- * in the primary register.
- */
+ ** in the primary register.
+ */
if (flags & CF_CONST) {
/* Because the handling of the overflow flag is too complex for
- * inlining, we can handle only unsigned compares, and signed
- * compares against zero here.
- */
+ ** inlining, we can handle only unsigned compares, and signed
+ ** compares against zero here.
+ */
if (flags & CF_UNSIGNED) {
/* Give a warning in some special cases */
}
/* If we go here, we didn't emit code. Push the lhs on stack and fall
- * into the normal, non-optimized stuff. Note: The standard stuff will
- * always work with ints.
- */
+ ** into the normal, non-optimized stuff. Note: The standard stuff will
+ ** always work with ints.
+ */
flags &= ~CF_FORCECHAR;
g_push (flags & ~CF_CONST, 0);
}
/* Code generator flags.
- * Note: The type flags are designed so that a smaller type may override a
- * larger one by or'ing it into the existing one.
- * Note^2: The actual type including the sign flag is in the lower bits, so
- * we can mask the information and use them as a table index.
- */
+** Note: The type flags are designed so that a smaller type may override a
+** larger one by or'ing it into the existing one.
+** Note^2: The actual type including the sign flag is in the lower bits, so
+** we can mask the information and use them as a table index.
+*/
#define CF_NONE 0x0000 /* No special flags */
/* Values for the actual type */
unsigned g_typeadjust (unsigned lhs, unsigned rhs);
/* Adjust the integer operands before doing a binary operation. lhs is a flags
- * value, that corresponds to the value on TOS, rhs corresponds to the value
- * in (e)ax. The return value is the the flags value for the resulting type.
- */
+** value, that corresponds to the value on TOS, rhs corresponds to the value
+** in (e)ax. The return value is the the flags value for the resulting type.
+*/
unsigned g_typecast (unsigned lhs, unsigned rhs);
/* Cast the value in the primary register to the operand size that is flagged
- * by the lhs value. Return the result value.
- */
+** by the lhs value. Return the result value.
+*/
void g_scale (unsigned flags, long val);
/* Scale the value in the primary register by the given value. If val is positive,
- * scale up, is val is negative, scale down. This function is used to scale
- * the operands or results of pointer arithmetic by the size of the type, the
- * pointer points to.
- */
+** scale up, is val is negative, scale down. This function is used to scale
+** the operands or results of pointer arithmetic by the size of the type, the
+** pointer points to.
+*/
void g_getind (unsigned Flags, unsigned Offs);
/* Fetch the specified object type indirect through the primary register
- * into the primary register
- */
+** into the primary register
+*/
void g_leasp (int Offs);
/* Fetch the address of the specified symbol into the primary register */
void g_leavariadic (int Offs);
/* Fetch the address of a parameter in a variadic function into the primary
- * register
- */
+** register
+*/
void g_putind (unsigned flags, unsigned offs);
/* Store the specified object type in the primary register at the address
- * on the top of the stack
- */
+** on the top of the stack
+*/
void g_cmp (unsigned flags, unsigned long val);
/* Immidiate compare. The primary register will not be changed, Z flag
- * will be set.
- */
+** will be set.
+*/
void g_test (unsigned flags);
/* Test the value in the primary and set the condition codes */
void g_swap (unsigned flags);
/* Swap the primary register and the top of the stack. flags give the type
- * of *both* values (must have same size).
- */
+** of *both* values (must have same size).
+*/
void g_call (unsigned Flags, const char* Label, unsigned ArgSize);
/* Call the specified subroutine name */
};
/* Table listing the function names and code info values for known internally
- * used functions. This table should get auto-generated in the future.
- */
+** used functions. This table should get auto-generated in the future.
+*/
typedef struct FuncInfo FuncInfo;
struct FuncInfo {
const char* Name; /* Function name */
};
/* Note for the shift functions: Shifts are done modulo 32, so all shift
- * routines are marked to use only the A register. The remainder is ignored
- * anyway.
- */
+** routines are marked to use only the A register. The remainder is ignored
+** anyway.
+*/
static const FuncInfo FuncInfoTable[] = {
{ "addeq0sp", REG_AX, REG_AXY },
{ "addeqysp", REG_AXY, REG_AXY },
void GetFuncInfo (const char* Name, unsigned short* Use, unsigned short* Chg)
/* For the given function, lookup register information and store it into
- * the given variables. If the function is unknown, assume it will use and
- * load all registers.
- */
+** the given variables. If the function is unknown, assume it will use and
+** load all registers.
+*/
{
/* If the function name starts with an underline, it is an external
- * function. Search for it in the symbol table. If the function does
- * not start with an underline, it may be a runtime support function.
- * Search for it in the list of builtin functions.
- */
+ ** function. Search for it in the symbol table. If the function does
+ ** not start with an underline, it may be a runtime support function.
+ ** Search for it in the list of builtin functions.
+ */
if (Name[0] == '_') {
/* Search in the symbol table, skip the leading underscore */
FuncDesc* D = E->V.F.Func;
/* A function may use the A or A/X registers if it is a fastcall
- * function. If it is not a fastcall function but a variadic one,
- * it will use the Y register (the parameter size is passed here).
- * In all other cases, no registers are used. However, we assume
- * that any function will destroy all registers.
- */
+ ** function. If it is not a fastcall function but a variadic one,
+ ** it will use the Y register (the parameter size is passed here).
+ ** In all other cases, no registers are used. However, we assume
+ ** that any function will destroy all registers.
+ */
if (IsQualFastcall (E->Type) && D->ParamCount > 0) {
/* Will use registers depending on the last param */
unsigned LastParamSize = CheckedSizeOf (D->LastParam->Type);
} else if (IsDigit (Name[0]) || Name[0] == '$') {
/* A call to a numeric address. Assume that anything gets used and
- * destroyed. This is not a real problem, since numeric addresses
- * are used mostly in inline assembly anyway.
- */
+ ** destroyed. This is not a real problem, since numeric addresses
+ ** are used mostly in inline assembly anyway.
+ */
*Use = REG_ALL;
*Chg = REG_ALL;
return;
*Chg = Info->Chg;
} else {
/* It's an internal function we have no information for. If in
- * debug mode, output an additional warning, so we have a chance
- * to fix it. Otherwise assume that the internal function will
- * use and change all registers.
- */
+ ** debug mode, output an additional warning, so we have a chance
+ ** to fix it. Otherwise assume that the internal function will
+ ** use and change all registers.
+ */
if (Debug) {
fprintf (stderr, "No info about internal function `%s'\n", Name);
}
}
/* Function not found - assume that the primary register is input, and all
- * registers are changed
- */
+ ** registers are changed
+ */
*Use = REG_EAXY;
*Chg = REG_ALL;
}
const ZPInfo* E = (const ZPInfo*) Info;
/* Do the compare. Be careful because of the length (Info may contain
- * more than just the zeropage name).
- */
+ ** more than just the zeropage name).
+ */
if (E->Len == 0) {
/* Do a full compare */
return strcmp (N, E->Name);
const ZPInfo* GetZPInfo (const char* Name)
/* If the given name is a zero page symbol, return a pointer to the info
- * struct for this symbol, otherwise return NULL.
- */
+** struct for this symbol, otherwise return NULL.
+*/
{
/* Search for the zp location in the list */
return bsearch (Name, ZPInfoTable, ZPInfoCount,
unsigned R;
/* Check if we have already visited the current code entry. If so,
- * bail out.
- */
+ ** bail out.
+ */
if (CE_HasMark (E)) {
break;
}
}
if (R != REG_NONE) {
/* We are not interested in the use of any register that has been
- * used before.
- */
+ ** used before.
+ */
R &= ~Unused;
/* Remember the remaining registers */
Used |= R;
/* Evaluate the changed registers */
if ((R = E->Chg) != REG_NONE) {
/* We are not interested in the use of any register that has been
- * used before.
- */
+ ** used before.
+ */
R &= ~Used;
/* Remember the remaining registers */
Unused |= R;
}
/* If we have an unconditional branch, follow this branch if possible,
- * otherwise we're done.
- */
+ ** otherwise we're done.
+ */
if ((E->Info & OF_UBRA) != 0) {
/* Does this jump have a valid target? */
}
/* In case of conditional branches, follow the branch if possible and
- * follow the normal flow (branch not taken) afterwards. If we cannot
- * follow the branch, we're done.
- */
+ ** follow the normal flow (branch not taken) afterwards. If we cannot
+ ** follow the branch, we're done.
+ */
} else if ((E->Info & OF_CBRA) != 0) {
/* Recursively determine register usage at the branch target */
} else {
/* Jump to external label. This will effectively exit the
- * function, so we use the exitregs information here.
- */
+ ** function, so we use the exitregs information here.
+ */
U1 = S->ExitRegs;
}
unsigned GetRegInfo (struct CodeSeg* S, unsigned Index, unsigned Wanted)
/* Determine register usage information for the instructions starting at the
- * given index.
- */
+** given index.
+*/
{
CodeEntry* E;
Collection Visited; /* Visited entries */
unsigned GetKnownReg (unsigned Use, const RegContents* RC)
/* Return the register or zero page location from the set in Use, thats
- * contents are known. If Use does not contain any register, or if the
- * register in question does not have a known value, return REG_NONE.
- */
+** contents are known. If Use does not contain any register, or if the
+** register in question does not have a known value, return REG_NONE.
+*/
{
if ((Use & REG_A) != 0) {
return (RC == 0 || RC->RegA >= 0)? REG_A : REG_NONE;
cmp_t FindBoolCmpCond (const char* Name)
/* Check if the given string is the name of one of the boolean transformer
- * subroutine, and if so, return the condition that is evaluated by this
- * routine. Return CMP_INV if the condition is not recognised.
- */
+** subroutine, and if so, return the condition that is evaluated by this
+** routine. Return CMP_INV if the condition is not recognised.
+*/
{
/* Check for the correct subroutine name */
if (strncmp (Name, "bool", 4) == 0) {
cmp_t FindTosCmpCond (const char* Name)
/* Check if this is a call to one of the TOS compare functions (tosgtax).
- * Return the condition code or CMP_INV on failure.
- */
+** Return the condition code or CMP_INV on failure.
+*/
{
unsigned Len = strlen (Name);
void GetFuncInfo (const char* Name, unsigned short* Use, unsigned short* Chg);
/* For the given function, lookup register information and store it into
- * the given variables. If the function is unknown, assume it will use and
- * load all registers.
- */
+** the given variables. If the function is unknown, assume it will use and
+** load all registers.
+*/
const ZPInfo* GetZPInfo (const char* Name);
/* If the given name is a zero page symbol, return a pointer to the info
- * struct for this symbol, otherwise return NULL.
- */
+** struct for this symbol, otherwise return NULL.
+*/
unsigned GetRegInfo (struct CodeSeg* S, unsigned Index, unsigned Wanted);
/* Determine register usage information for the instructions starting at the
- * given index.
- */
+** given index.
+*/
int RegAUsed (struct CodeSeg* S, unsigned Index);
/* Check if the value in A is used. */
unsigned GetKnownReg (unsigned Use, const struct RegContents* RC);
/* Return the register or zero page location from the set in Use, thats
- * contents are known. If Use does not contain any register, or if the
- * register in question does not have a known value, return REG_NONE.
- */
+** contents are known. If Use does not contain any register, or if the
+** register in question does not have a known value, return REG_NONE.
+*/
cmp_t FindBoolCmpCond (const char* Name);
/* Check if the given string is the name of one of the boolean transformer
- * subroutine, and if so, return the condition that is evaluated by this
- * routine. Return CMP_INV if the condition is not recognised.
- */
+** subroutine, and if so, return the condition that is evaluated by this
+** routine. Return CMP_INV if the condition is not recognised.
+*/
cmp_t FindTosCmpCond (const char* Name);
/* Check if this is a call to one of the TOS compare functions (tosgtax).
- * Return the condition code or CMP_INV on failure.
- */
+** Return the condition code or CMP_INV on failure.
+*/
void CL_MoveRefs (CodeLabel* OldLabel, CodeLabel* NewLabel)
/* Move all references to OldLabel to point to NewLabel. OldLabel will have no
- * more references on return.
- */
+** more references on return.
+*/
{
/* Walk through all instructions referencing the old label */
unsigned Count = CL_GetRefCount (OldLabel);
void CL_MoveRefs (CodeLabel* OldLabel, CodeLabel* NewLabel);
/* Move all references to OldLabel to point to NewLabel. OldLabel will have no
- * more references on return.
- */
+** more references on return.
+*/
void CL_Output (const CodeLabel* L);
/* Output the code label to the output file */
static unsigned OptLoad1 (CodeSeg* S)
/* Search for a call to ldaxysp where X is not used later and replace it by
- * a load of just the A register.
- */
+** a load of just the A register.
+*/
{
unsigned I;
unsigned Changes = 0;
!RegXUsed (S, I+3)) {
/* A/X are stored into memory somewhere and X is not used
- * later
- */
+ ** later
+ */
/* lda (sp),y */
X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "sp", 0, L[0]->LI);
CodeEntry* N;
/* If we had a preceeding load that is identical, remove this one.
- * If it is not identical, or we didn't have one, remember it.
- */
+ ** If it is not identical, or we didn't have one, remember it.
+ */
if (Load != 0 &&
E->OPC == Load->OPC &&
E->AM == Load->AM &&
static unsigned OptDecouple (CodeSeg* S)
/* Decouple operations, that is, do the following replacements:
- *
- * dex -> ldx #imm
- * inx -> ldx #imm
- * dey -> ldy #imm
- * iny -> ldy #imm
- * tax -> ldx #imm
- * txa -> lda #imm
- * tay -> ldy #imm
- * tya -> lda #imm
- * lda zp -> lda #imm
- * ldx zp -> ldx #imm
- * ldy zp -> ldy #imm
- *
- * Provided that the register values are known of course.
- */
+**
+** dex -> ldx #imm
+** inx -> ldx #imm
+** dey -> ldy #imm
+** iny -> ldy #imm
+** tax -> ldx #imm
+** txa -> lda #imm
+** tay -> ldy #imm
+** tya -> lda #imm
+** lda zp -> lda #imm
+** ldx zp -> ldx #imm
+** ldy zp -> ldy #imm
+**
+** Provided that the register values are known of course.
+*/
{
unsigned Changes = 0;
unsigned I;
static unsigned IsDecSP (const CodeEntry* E)
/* Check if this is an insn that decrements the stack pointer. If so, return
- * the decrement. If not, return zero.
- * The function expects E to be a subroutine call.
- */
+** the decrement. If not, return zero.
+** The function expects E to be a subroutine call.
+*/
{
if (strncmp (E->Arg, "decsp", 5) == 0) {
if (E->Arg[5] >= '1' && E->Arg[5] <= '8') {
static unsigned OptStackPtrOps (CodeSeg* S)
/* Merge adjacent calls to decsp into one. NOTE: This function won't merge all
- * known cases!
- */
+** known cases!
+*/
{
unsigned Changes = 0;
unsigned I;
static OptFunc* FindOptFunc (const char* Name)
/* Find an optimizer step by name in the table and return a pointer. Return
- * NULL if no such step is found.
- */
+** NULL if no such step is found.
+*/
{
/* Search for the function in the list */
OptFunc** O = bsearch (Name, OptFuncs, OPTFUNC_COUNT, sizeof (OptFuncs[0]), CmpOptStep);
static OptFunc* GetOptFunc (const char* Name)
/* Find an optimizer step by name in the table and return a pointer. Print an
- * error and call AbEnd if not found.
- */
+** error and call AbEnd if not found.
+*/
{
/* Search for the function in the list */
OptFunc* F = FindOptFunc (Name);
unsigned Changes, C;
/* Don't run the function if it is disabled or if it is prohibited by the
- * code size factor
- */
+ ** code size factor
+ */
if (F->Disabled || F->CodeSizeFactor > S->CodeSizeFactor) {
return 0;
}
static unsigned RunOptGroup1 (CodeSeg* S)
/* Run the first group of optimization steps. These steps translate known
- * patterns emitted by the code generator into more optimal patterns. Order
- * of the steps is important, because some of the steps done earlier cover
- * the same patterns as later steps as subpatterns.
- */
+** patterns emitted by the code generator into more optimal patterns. Order
+** of the steps is important, because some of the steps done earlier cover
+** the same patterns as later steps as subpatterns.
+*/
{
unsigned Changes = 0;
static unsigned RunOptGroup2 (CodeSeg* S)
/* Run one group of optimization steps. This step involves just decoupling
- * instructions by replacing them by instructions that do not depend on
- * previous instructions. This makes it easier to find instructions that
- * aren't used.
- */
+** instructions by replacing them by instructions that do not depend on
+** previous instructions. This makes it easier to find instructions that
+** aren't used.
+*/
{
unsigned Changes = 0;
static unsigned RunOptGroup3 (CodeSeg* S)
/* Run one group of optimization steps. These steps depend on each other,
- * that means that one step may allow another step to do additional work,
- * so we will repeat the steps as long as we see any changes.
- */
+** that means that one step may allow another step to do additional work,
+** so we will repeat the steps as long as we see any changes.
+*/
{
unsigned Changes, C;
static unsigned RunOptGroup4 (CodeSeg* S)
/* Run another round of pattern replacements. These are done late, since there
- * may be better replacements before.
- */
+** may be better replacements before.
+*/
{
unsigned Changes = 0;
Changes += RunOptFunc (S, &DOpt65C02Stores, 1);
if (Changes) {
/* The 65C02 replacement codes do often make the use of a register
- * value unnecessary, so if we have changes, run another load
- * removal pass.
- */
+ ** value unnecessary, so if we have changes, run another load
+ ** removal pass.
+ */
Changes += RunOptFunc (S, &DOptUnusedLoads, 1);
}
}
static unsigned RunOptGroup6 (CodeSeg* S)
/* This one is quite special. It tries to replace "lda (sp),y" by "lda (sp,x)".
- * The latter is ony cycle slower, but if we're able to remove the necessary
- * load of the Y register, because X is zero anyway, we gain 1 cycle and
- * shorten the code by one (transfer) or two bytes (load). So what we do is
- * to replace the insns, remove unused loads, and then change back all insns
- * where Y is still zero (meaning that the load has not been removed).
- */
+** The latter is ony cycle slower, but if we're able to remove the necessary
+** load of the Y register, because X is zero anyway, we gain 1 cycle and
+** shorten the code by one (transfer) or two bytes (load). So what we do is
+** to replace the insns, remove unused loads, and then change back all insns
+** where Y is still zero (meaning that the load has not been removed).
+*/
{
unsigned Changes = 0;
/* This group will only run for a standard 6502, because the 65C02 has a
- * better addressing mode that covers this case.
- */
+ ** better addressing mode that covers this case.
+ */
if ((CPUIsets[CPU] & CPU_ISET_65SC02) == 0) {
Changes += RunOptFunc (S, &DOptIndLoads1, 1);
Changes += RunOptFunc (S, &DOptUnusedLoads, 1);
static unsigned RunOptGroup7 (CodeSeg* S)
/* The last group of optimization steps. Adjust branches, do size optimizations.
- */
+*/
{
unsigned Changes = 0;
unsigned C;
/* Optimize for size, that is replace operations by shorter ones, even
- * if this does hinder further optimizations (no problem since we're
- * done soon).
- */
+ ** if this does hinder further optimizations (no problem since we're
+ ** done soon).
+ */
C = RunOptFunc (S, &DOptSize1, 1);
if (C) {
Changes += C;
/* Run some optimization passes again, since the size optimizations
- * may have opened new oportunities.
- */
+ ** may have opened new oportunities.
+ */
Changes += RunOptFunc (S, &DOptUnusedLoads, 1);
Changes += RunOptFunc (S, &DOptUnusedStores, 1);
Changes += RunOptFunc (S, &DOptJumpTarget1, 5);
if (C) {
Changes += C;
/* Run some optimization passes again, since the size optimizations
- * may have opened new oportunities.
- */
+ ** may have opened new oportunities.
+ */
Changes += RunOptFunc (S, &DOptUnusedLoads, 1);
Changes += RunOptFunc (S, &DOptJumpTarget1, 5);
Changes += RunOptFunc (S, &DOptStore5, 1);
Changes += RunOptFunc (S, &DOptBranchDist, 3);
/* Replace conditional branches to RTS. If we had changes, we must run dead
- * code elimination again, since the change may have introduced dead code.
- */
+ ** code elimination again, since the change may have introduced dead code.
+ */
C = RunOptFunc (S, &DOptRTSJumps2, 1);
Changes += C;
if (C) {
static void CS_MoveLabelsToEntry (CodeSeg* S, CodeEntry* E)
/* Move all labels from the label pool to the given entry and remove them
- * from the pool.
- */
+** from the pool.
+*/
{
/* Transfer the labels if we have any */
unsigned I;
static const char* ReadToken (const char* L, const char* Term,
char* Buf, unsigned BufSize)
/* Read the next token into Buf, return the updated line pointer. The
- * token is terminated by one of the characters given in term.
- */
+** token is terminated by one of the characters given in term.
+*/
{
/* Read/copy the token */
unsigned I = 0;
Buf[I] = *L;
} else if (I == BufSize-1) {
/* Cannot store this character, this is an input error (maybe
- * identifier too long or similar).
- */
+ ** identifier too long or similar).
+ */
Error ("ASM code error: syntax error");
}
++I;
static CodeEntry* ParseInsn (CodeSeg* S, LineInfo* LI, const char* L)
/* Parse an instruction nnd generate a code entry from it. If the line contains
- * errors, output an error message and return NULL.
- * For simplicity, we don't accept the broad range of input a "real" assembler
- * does. The instruction and the argument are expected to be separated by
- * white space, for example.
- */
+** errors, output an error message and return NULL.
+** For simplicity, we don't accept the broad range of input a "real" assembler
+** does. The instruction and the argument are expected to be separated by
+** white space, for example.
+*/
{
char Mnemo[IDENTSIZE+10];
const OPCDesc* OPC;
CS_AddLabel (S, Mnemo);
/* If we have reached end of line, bail out, otherwise a mnemonic
- * may follow.
- */
+ ** may follow.
+ */
if (*L == '\0') {
return 0;
}
}
/* If the instruction is a branch, check for the label and generate it
- * if it does not exist. This may lead to unused labels (if the label
- * is actually an external one) which are removed by the CS_MergeLabels
- * function later.
- */
+ ** if it does not exist. This may lead to unused labels (if the label
+ ** is actually an external one) which are removed by the CS_MergeLabels
+ ** function later.
+ */
Label = 0;
if (AM == AM65_BRA) {
}
/* We do now have the addressing mode in AM. Allocate a new CodeEntry
- * structure and initialize it.
- */
+ ** structure and initialize it.
+ */
E = NewCodeEntry (OPC->OPC, AM, Arg, Label, LI);
/* Return the new code entry */
}
/* If we have a function given, get the return type of the function.
- * Assume ANY return type besides void will use the A and X registers.
- */
+ ** Assume ANY return type besides void will use the A and X registers.
+ */
if (S->Func && !IsTypeVoid ((RetType = GetFuncReturn (Func->Type)))) {
if (SizeOf (RetType) == SizeOf (type_long)) {
S->ExitRegs = REG_EAX;
void CS_InsertEntry (CodeSeg* S, struct CodeEntry* E, unsigned Index)
/* Insert the code entry at the index given. Following code entries will be
- * moved to slots with higher indices.
- */
+** moved to slots with higher indices.
+*/
{
/* Insert the entry into the collection */
CollInsert (&S->Entries, E, Index);
void CS_DelEntry (CodeSeg* S, unsigned Index)
/* Delete an entry from the code segment. This includes moving any associated
- * labels, removing references to labels and even removing the referenced labels
- * if the reference count drops to zero.
- * Note: Labels are moved forward if possible, that is, they are moved to the
- * next insn (not the preceeding one).
- */
+** labels, removing references to labels and even removing the referenced labels
+** if the reference count drops to zero.
+** Note: Labels are moved forward if possible, that is, they are moved to the
+** next insn (not the preceeding one).
+*/
{
/* Get the code entry for the given index */
CodeEntry* E = CS_GetEntry (S, Index);
/* If the entry has a labels, we have to move this label to the next insn.
- * If there is no next insn, move the label into the code segement label
- * pool. The operation is further complicated by the fact that the next
- * insn may already have a label. In that case change all reference to
- * this label and delete the label instead of moving it.
- */
+ ** If there is no next insn, move the label into the code segement label
+ ** pool. The operation is further complicated by the fact that the next
+ ** insn may already have a label. In that case change all reference to
+ ** this label and delete the label instead of moving it.
+ */
unsigned Count = CE_GetLabelCount (E);
if (Count > 0) {
/* The instruction has labels attached. Check if there is a next
- * instruction.
- */
+ ** instruction.
+ */
if (Index == CS_GetEntryCount (S)-1) {
/* No next instruction, move to the codeseg label pool */
}
/* If this insn references a label, remove the reference. And, if the
- * the reference count for this label drops to zero, remove this label.
- */
+ ** the reference count for this label drops to zero, remove this label.
+ */
if (E->JumpTo) {
/* Remove the reference */
CS_RemoveLabelRef (S, E);
void CS_DelEntries (CodeSeg* S, unsigned Start, unsigned Count)
/* Delete a range of code entries. This includes removing references to labels,
- * labels attached to the entries and so on.
- */
+** labels attached to the entries and so on.
+*/
{
/* Start deleting the entries from the rear, because this involves less
- * memory moving.
- */
+ ** memory moving.
+ */
while (Count--) {
CS_DelEntry (S, Start + Count);
}
void CS_MoveEntries (CodeSeg* S, unsigned Start, unsigned Count, unsigned NewPos)
/* Move a range of entries from one position to another. Start is the index
- * of the first entry to move, Count is the number of entries and NewPos is
- * the index of the target entry. The entry with the index Start will later
- * have the index NewPos. All entries with indices NewPos and above are
- * moved to higher indices. If the code block is moved to the end of the
- * current code, and if pending labels exist, these labels will get attached
- * to the first instruction of the moved block (the first one after the
- * current code end)
- */
+** of the first entry to move, Count is the number of entries and NewPos is
+** the index of the target entry. The entry with the index Start will later
+** have the index NewPos. All entries with indices NewPos and above are
+** moved to higher indices. If the code block is moved to the end of the
+** current code, and if pending labels exist, these labels will get attached
+** to the first instruction of the moved block (the first one after the
+** current code end)
+*/
{
/* Transparently handle an empty range */
if (Count == 0) {
}
/* If NewPos is at the end of the code segment, move any labels from the
- * label pool to the first instruction of the moved range.
- */
+ ** label pool to the first instruction of the moved range.
+ */
if (NewPos == CS_GetEntryCount (S)) {
CS_MoveLabelsToEntry (S, CS_GetEntry (S, Start));
}
struct CodeEntry* CS_GetPrevEntry (CodeSeg* S, unsigned Index)
/* Get the code entry preceeding the one with the index Index. If there is no
- * preceeding code entry, return NULL.
- */
+** preceeding code entry, return NULL.
+*/
{
if (Index == 0) {
/* This is the first entry */
struct CodeEntry* CS_GetNextEntry (CodeSeg* S, unsigned Index)
/* Get the code entry following the one with the index Index. If there is no
- * following code entry, return NULL.
- */
+** following code entry, return NULL.
+*/
{
if (Index >= CollCount (&S->Entries)-1) {
/* This is the last entry */
int CS_GetEntries (CodeSeg* S, struct CodeEntry** List,
unsigned Start, unsigned Count)
/* Get Count code entries into List starting at index start. Return true if
- * we got the lines, return false if not enough lines were available.
- */
+** we got the lines, return false if not enough lines were available.
+*/
{
/* Check if enough entries are available */
if (Start + Count > CollCount (&S->Entries)) {
int CS_RangeHasLabel (CodeSeg* S, unsigned Start, unsigned Count)
/* Return true if any of the code entries in the given range has a label
- * attached. If the code segment does not span the given range, check the
- * possible span instead.
- */
+** attached. If the code segment does not span the given range, check the
+** possible span instead.
+*/
{
unsigned EntryCount = CS_GetEntryCount(S);
}
/* Check each entry. Since we have validated the index above, we may
- * use the unchecked access function in the loop which is faster.
- */
+ ** use the unchecked access function in the loop which is faster.
+ */
while (Count--) {
const CodeEntry* E = CollAtUnchecked (&S->Entries, Start++);
if (CE_HasLabel (E)) {
CodeLabel* CS_GenLabel (CodeSeg* S, struct CodeEntry* E)
/* If the code entry E does already have a label, return it. Otherwise
- * create a new label, attach it to E and return it.
- */
+** create a new label, attach it to E and return it.
+*/
{
CodeLabel* L;
CollDeleteAll (&L->JumpFrom);
/* Remove the reference to the owning instruction if it has one. The
- * function may be called for a label without an owner when deleting
- * unfinished parts of the code. This is unfortunate since it allows
- * errors to slip through.
- */
+ ** function may be called for a label without an owner when deleting
+ ** unfinished parts of the code. This is unfortunate since it allows
+ ** errors to slip through.
+ */
if (L->Owner) {
CollDeleteItem (&L->Owner->Labels, L);
}
void CS_MergeLabels (CodeSeg* S)
/* Merge code labels. That means: For each instruction, remove all labels but
- * one and adjust references accordingly.
- */
+** one and adjust references accordingly.
+*/
{
unsigned I;
unsigned J;
/* First, remove all labels from the label symbol table that don't have an
- * owner (this means that they are actually external labels but we didn't
- * know that previously since they may have also been forward references).
- */
+ ** owner (this means that they are actually external labels but we didn't
+ ** know that previously since they may have also been forward references).
+ */
for (I = 0; I < CS_LABEL_HASH_SIZE; ++I) {
/* Get the first label in this hash chain */
/* Get the entry referencing this label */
CodeEntry* E = CL_GetRef (X, J);
/* And remove the reference. Do NOT call CE_ClearJumpTo
- * here, because this will also clear the label name,
- * which is not what we want.
- */
+ ** here, because this will also clear the label name,
+ ** which is not what we want.
+ */
E->JumpTo = 0;
}
RefLab = CE_GetLabel (E, 0);
/* Walk through the remaining labels and change references to these
- * labels to a reference to the one and only label. Delete the labels
- * that are no longer used. To increase performance, walk backwards
- * through the list.
- */
+ ** labels to a reference to the one and only label. Delete the labels
+ ** that are no longer used. To increase performance, walk backwards
+ ** through the list.
+ */
for (J = LabelCount-1; J >= 1; --J) {
/* Get the next label */
}
/* The reference label is the only remaining label. Check if there
- * are any references to this label, and delete it if this is not
- * the case.
- */
+ ** are any references to this label, and delete it if this is not
+ ** the case.
+ */
if (CollCount (&RefLab->JumpFrom) == 0) {
/* Delete the label */
CS_DelLabel (S, RefLab);
void CS_MoveLabels (CodeSeg* S, struct CodeEntry* Old, struct CodeEntry* New)
/* Move all labels from Old to New. The routine will move the labels itself
- * if New does not have any labels, and move references if there is at least
- * a label for new. If references are moved, the old label is deleted
- * afterwards.
- */
+** if New does not have any labels, and move references if there is at least
+** a label for new. If references are moved, the old label is deleted
+** afterwards.
+*/
{
/* Get the number of labels to move */
unsigned OldLabelCount = CE_GetLabelCount (Old);
void CS_RemoveLabelRef (CodeSeg* S, struct CodeEntry* E)
/* Remove the reference between E and the label it jumps to. The reference
- * will be removed on both sides and E->JumpTo will be 0 after that. If
- * the reference was the only one for the label, the label will get
- * deleted.
- */
+** will be removed on both sides and E->JumpTo will be 0 after that. If
+** the reference was the only one for the label, the label will get
+** deleted.
+*/
{
/* Get a pointer to the label and make sure it exists */
CodeLabel* L = E->JumpTo;
void CS_MoveLabelRef (CodeSeg* S, struct CodeEntry* E, CodeLabel* L)
/* Change the reference of E to L instead of the current one. If this
- * was the only reference to the old label, the old label will get
- * deleted.
- */
+** was the only reference to the old label, the old label will get
+** deleted.
+*/
{
/* Get the old label */
CodeLabel* OldLabel = E->JumpTo;
void CS_DelCodeRange (CodeSeg* S, unsigned First, unsigned Last)
/* Delete all entries between first and last, both inclusive. The function
- * can only handle basic blocks (First is the only entry, Last the only exit)
- * and no open labels. It will call FAIL if any of these preconditions are
- * violated.
- */
+** can only handle basic blocks (First is the only entry, Last the only exit)
+** and no open labels. It will call FAIL if any of these preconditions are
+** violated.
+*/
{
unsigned I;
CodeEntry* FirstEntry;
CHECK (First <= Last && Last < CS_GetEntryCount (S));
/* If Last is actually the last insn, call CS_DelCodeAfter instead, which
- * is more flexible in this case.
- */
+ ** is more flexible in this case.
+ */
if (Last == CS_GetEntryCount (S) - 1) {
CS_DelCodeAfter (S, First);
return;
}
/* Get the first entry and check if it has any labels. If it has, move
- * them to the insn following Last. If Last is the last insn of the code
- * segment, make them ownerless and move them to the label pool.
- */
+ ** them to the insn following Last. If Last is the last insn of the code
+ ** segment, make them ownerless and move them to the label pool.
+ */
FirstEntry = CS_GetEntry (S, First);
if (CE_HasLabel (FirstEntry)) {
/* Get the entry following last */
}
/* First pass: Delete all references to labels. If the reference count
- * for a label drops to zero, delete it.
- */
+ ** for a label drops to zero, delete it.
+ */
for (I = Last; I >= First; --I) {
/* Get the next entry */
}
/* Second pass: Delete the instructions. If a label attached to an
- * instruction still has references, it must be references from outside
- * the deleted area, which is an error.
- */
+ ** instruction still has references, it must be references from outside
+ ** the deleted area, which is an error.
+ */
for (I = Last; I >= First; --I) {
/* Get the next entry */
unsigned Count = CS_GetEntryCount (S);
/* First pass: Delete all references to labels. If the reference count
- * for a label drops to zero, delete it.
- */
+ ** for a label drops to zero, delete it.
+ */
unsigned C = Count;
while (Last < C--) {
/* Check if this entry has a label reference */
if (E->JumpTo) {
/* If the label is a label in the label pool and this is the last
- * reference to the label, remove the label from the pool.
- */
+ ** reference to the label, remove the label from the pool.
+ */
CodeLabel* L = E->JumpTo;
int Index = CollIndex (&S->Labels, L);
if (Index >= 0 && CollCount (&L->JumpFrom) == 1) {
}
/* Second pass: Delete the instructions. If a label attached to an
- * instruction still has references, it must be references from outside
- * the deleted area. Don't delete the label in this case, just make it
- * ownerless and move it to the label pool.
- */
+ ** instruction still has references, it must be references from outside
+ ** the deleted area. Don't delete the label in this case, just make it
+ ** ownerless and move it to the label pool.
+ */
C = Count;
while (Last < C--) {
int CS_IsBasicBlock (CodeSeg* S, unsigned First, unsigned Last)
/* Check if the given code segment range is a basic block. That is, check if
- * First is the only entrance and Last is the only exit. This means that no
- * jump/branch inside the block may jump to an insn below First or after(!)
- * Last, and that no insn may jump into this block from the outside.
- */
+** First is the only entrance and Last is the only exit. This means that no
+** jump/branch inside the block may jump to an insn below First or after(!)
+** Last, and that no insn may jump into this block from the outside.
+*/
{
unsigned I;
CS_ResetMarks (S, First, Last);
/* Second pass: Walk over the range checking all labels. Note: There may be
- * label on the first insn which is ok.
- */
+ ** label on the first insn which is ok.
+ */
I = First + 1;
while (I <= Last) {
CodeEntry* E = CS_GetEntry (S, I);
/* Check if this entry has one or more labels, if so, check which
- * entries jump to this label.
- */
+ ** entries jump to this label.
+ */
unsigned LabelCount = CE_GetLabelCount (E);
unsigned LabelIndex;
for (LabelIndex = 0; LabelIndex < LabelCount; ++LabelIndex) {
CodeLabel* L = CE_GetLabel (E, LabelIndex);
/* Walk over all entries that jump to this label. Check for each
- * of the entries if it is out of the range.
- */
+ ** of the entries if it is out of the range.
+ */
unsigned RefCount = CL_GetRefCount (L);
unsigned RefIndex;
for (RefIndex = 0; RefIndex < RefCount; ++RefIndex) {
CodeEntry* Ref = CL_GetRef (L, RefIndex);
/* Walk over out complete range and check if we find the
- * refering entry. This is cheaper than using CS_GetEntryIndex,
- * because CS_GetEntryIndex will search the complete code
- * segment and not just our range.
- */
+ ** refering entry. This is cheaper than using CS_GetEntryIndex,
+ ** because CS_GetEntryIndex will search the complete code
+ ** segment and not just our range.
+ */
unsigned J;
for (J = First; J <= Last; ++J) {
if (Ref == CS_GetEntry (S, J)) {
}
if (J > Last) {
/* We did not find the entry. This means that the jump to
- * out code segment entry E came from outside the range,
- * which in turn means that the given range is not a basic
- * block.
- */
+ ** out code segment entry E came from outside the range,
+ ** which in turn means that the given range is not a basic
+ ** block.
+ */
CS_ResetMarks (S, First, Last);
return 0;
}
/* If we come here, we found the entry. Mark it, so we know
- * that the branch to the label is in range.
- */
+ ** that the branch to the label is in range.
+ */
CE_SetMark (Ref);
}
}
}
/* Third pass: Walk again over the range and check all branches. If we
- * find a branch that is not marked, its target is not inside the range
- * (since we checked all the labels in the range before).
- */
+ ** find a branch that is not marked, its target is not inside the range
+ ** (since we checked all the labels in the range before).
+ */
I = First;
while (I <= Last) {
if (E->Info & (OF_UBRA | OF_CBRA)) {
if (!CE_HasMark (E)) {
/* No mark means not a basic block. Before bailing out, be sure
- * to remove the marks from the remaining entries.
- */
+ ** to remove the marks from the remaining entries.
+ */
CS_ResetMarks (S, I+1, Last);
return 0;
}
void CS_OutputPrologue (const CodeSeg* S)
/* If the given code segment is a code segment for a function, output the
- * assembler prologue into the file. That is: Output a comment header, switch
- * to the correct segment and enter the local function scope. If the code
- * segment is global, do nothing.
- */
+** assembler prologue into the file. That is: Output a comment header, switch
+** to the correct segment and enter the local function scope. If the code
+** segment is global, do nothing.
+*/
{
/* Get the function associated with the code segment */
SymEntry* Func = S->Func;
/* If the code segment is associated with a function, print a function
- * header and enter a local scope. Be sure to switch to the correct
- * segment before outputing the function label.
- */
+ ** header and enter a local scope. Be sure to switch to the correct
+ ** segment before outputing the function label.
+ */
if (Func) {
/* Get the function descriptor */
CS_PrintFunctionHeader (S);
void CS_OutputEpilogue (const CodeSeg* S)
/* If the given code segment is a code segment for a function, output the
- * assembler epilogue into the file. That is: Close the local function scope.
- */
+** assembler epilogue into the file. That is: Close the local function scope.
+*/
{
if (S->Func) {
WriteOutput ("\n.endproc\n\n");
/* Get the next entry */
const CodeEntry* E = CollConstAt (&S->Entries, I);
/* Check if the line info has changed. If so, output the source line
- * if the option is enabled and output debug line info if the debug
- * option is enabled.
- */
+ ** if the option is enabled and output debug line info if the debug
+ ** option is enabled.
+ */
if (E->LI != LI) {
/* Line info has changed, remember the new line info */
LI = E->LI;
/* Add the source line as a comment. Beware: When line continuation
- * was used, the line may contain newlines.
- */
+ ** was used, the line may contain newlines.
+ */
if (AddSource) {
const char* L = LI->Line;
WriteOutput (";\n; ");
CurrentRegs = &Regs;
/* Walk over all insns and note just the changes from one insn to the
- * next one.
- */
+ ** next one.
+ */
WasJump = 0;
for (I = 0; I < CS_GetEntryCount (S); ++I) {
if (LabelCount > 0) {
/* Loop over all entry points that jump here. If these entry
- * points already have register info, check if all values are
- * known and identical. If all values are identical, and the
- * preceeding instruction was not an unconditional branch, check
- * if the register value on exit of the preceeding instruction
- * is also identical. If all these values are identical, the
- * value of a register is known, otherwise it is unknown.
- */
+ ** points already have register info, check if all values are
+ ** known and identical. If all values are identical, and the
+ ** preceeding instruction was not an unconditional branch, check
+ ** if the register value on exit of the preceeding instruction
+ ** is also identical. If all these values are identical, the
+ ** value of a register is known, otherwise it is unknown.
+ */
CodeLabel* Label = CE_GetLabel (E, 0);
unsigned Entry;
if (WasJump) {
CodeEntry* J = CL_GetRef (Label, Entry);
if (J->RI == 0) {
/* No register info for this entry. This means that the
- * instruction that jumps here is at higher addresses and
- * the jump is a backward jump. We need a second run to
- * get the register info right in this case. Until then,
- * assume unknown register contents.
- */
+ ** instruction that jumps here is at higher addresses and
+ ** the jump is a backward jump. We need a second run to
+ ** get the register info right in this case. Until then,
+ ** assume unknown register contents.
+ */
Done = 0;
RC_Invalidate (&Regs);
break;
CurrentRegs = &E->RI->Out;
/* If this insn is a branch on zero flag, we may have more info on
- * register contents for one of both flow directions, but only if
- * there is a previous instruction.
- */
+ ** register contents for one of both flow directions, but only if
+ ** there is a previous instruction.
+ */
if ((E->Info & OF_ZBRA) != 0 && (P = CS_GetPrevEntry (S, I)) != 0) {
/* Get the branch condition */
case OP65_CMP:
/* If this is an immidiate compare, the A register has
- * the value of the compare later.
- */
+ ** the value of the compare later.
+ */
if (CE_IsConstImm (P)) {
if (BC == BC_EQ) {
E->RI->Out2.RegA = (unsigned char)P->Num;
case OP65_CPX:
/* If this is an immidiate compare, the X register has
- * the value of the compare later.
- */
+ ** the value of the compare later.
+ */
if (CE_IsConstImm (P)) {
if (BC == BC_EQ) {
E->RI->Out2.RegX = (unsigned char)P->Num;
case OP65_CPY:
/* If this is an immidiate compare, the Y register has
- * the value of the compare later.
- */
+ ** the value of the compare later.
+ */
if (CE_IsConstImm (P)) {
if (BC == BC_EQ) {
E->RI->Out2.RegY = (unsigned char)P->Num;
case OP65_TAX:
case OP65_TXA:
/* If the branch is a beq, both A and X are zero at the
- * branch target, otherwise they are zero at the next
- * insn.
- */
+ ** branch target, otherwise they are zero at the next
+ ** insn.
+ */
if (BC == BC_EQ) {
E->RI->Out2.RegA = E->RI->Out2.RegX = 0;
} else {
case OP65_TAY:
case OP65_TYA:
/* If the branch is a beq, both A and Y are zero at the
- * branch target, otherwise they are zero at the next
- * insn.
- */
+ ** branch target, otherwise they are zero at the next
+ ** insn.
+ */
if (BC == BC_EQ) {
E->RI->Out2.RegA = E->RI->Out2.RegY = 0;
} else {
void CS_InsertEntry (CodeSeg* S, struct CodeEntry* E, unsigned Index);
/* Insert the code entry at the index given. Following code entries will be
- * moved to slots with higher indices.
- */
+** moved to slots with higher indices.
+*/
void CS_DelEntry (CodeSeg* S, unsigned Index);
/* Delete an entry from the code segment. This includes moving any associated
- * labels, removing references to labels and even removing the referenced labels
- * if the reference count drops to zero.
- * Note: Labels are moved forward if possible, that is, they are moved to the
- * next insn (not the preceeding one).
- */
+** labels, removing references to labels and even removing the referenced labels
+** if the reference count drops to zero.
+** Note: Labels are moved forward if possible, that is, they are moved to the
+** next insn (not the preceeding one).
+*/
void CS_DelEntries (CodeSeg* S, unsigned Start, unsigned Count);
/* Delete a range of code entries. This includes removing references to labels,
- * labels attached to the entries and so on.
- */
+** labels attached to the entries and so on.
+*/
void CS_MoveEntries (CodeSeg* S, unsigned Start, unsigned Count, unsigned NewPos);
/* Move a range of entries from one position to another. Start is the index
- * of the first entry to move, Count is the number of entries and NewPos is
- * the index of the target entry. The entry with the index Start will later
- * have the index NewPos. All entries with indices NewPos and above are
- * moved to higher indices. If the code block is moved to the end of the
- * current code, and if pending labels exist, these labels will get attached
- * to the first instruction of the moved block (the first one after the
- * current code end)
- */
+** of the first entry to move, Count is the number of entries and NewPos is
+** the index of the target entry. The entry with the index Start will later
+** have the index NewPos. All entries with indices NewPos and above are
+** moved to higher indices. If the code block is moved to the end of the
+** current code, and if pending labels exist, these labels will get attached
+** to the first instruction of the moved block (the first one after the
+** current code end)
+*/
#if defined(HAVE_INLINE)
INLINE void CS_MoveEntry (CodeSeg* S, unsigned OldPos, unsigned NewPos)
/* Move an entry from one position to another. OldPos is the current position
- * of the entry, NewPos is the new position of the entry.
- */
+** of the entry, NewPos is the new position of the entry.
+*/
{
CollMove (&S->Entries, OldPos, NewPos);
}
struct CodeEntry* CS_GetPrevEntry (CodeSeg* S, unsigned Index);
/* Get the code entry preceeding the one with the index Index. If there is no
- * preceeding code entry, return NULL.
- */
+** preceeding code entry, return NULL.
+*/
struct CodeEntry* CS_GetNextEntry (CodeSeg* S, unsigned Index);
/* Get the code entry following the one with the index Index. If there is no
- * following code entry, return NULL.
- */
+** following code entry, return NULL.
+*/
int CS_GetEntries (CodeSeg* S, struct CodeEntry** List,
unsigned Start, unsigned Count);
/* Get Count code entries into List starting at index start. Return true if
- * we got the lines, return false if not enough lines were available.
- */
+** we got the lines, return false if not enough lines were available.
+*/
unsigned CS_GetEntryIndex (CodeSeg* S, struct CodeEntry* E);
/* Return the index of a code entry */
int CS_RangeHasLabel (CodeSeg* S, unsigned Start, unsigned Count);
/* Return true if any of the code entries in the given range has a label
- * attached. If the code segment does not span the given range, check the
- * possible span instead.
- */
+** attached. If the code segment does not span the given range, check the
+** possible span instead.
+*/
#if defined(HAVE_INLINE)
INLINE int CS_HavePendingLabel (const CodeSeg* S)
/* Return true if there are open labels that will get attached to the next
- * instruction that is added.
- */
+** instruction that is added.
+*/
{
return (CollCount (&S->Labels) > 0);
}
CodeLabel* CS_GenLabel (CodeSeg* S, struct CodeEntry* E);
/* If the code entry E does already have a label, return it. Otherwise
- * create a new label, attach it to E and return it.
- */
+** create a new label, attach it to E and return it.
+*/
void CS_DelLabel (CodeSeg* S, CodeLabel* L);
/* Remove references from this label and delete it. */
void CS_MergeLabels (CodeSeg* S);
/* Merge code labels. That means: For each instruction, remove all labels but
- * one and adjust references accordingly.
- */
+** one and adjust references accordingly.
+*/
void CS_MoveLabels (CodeSeg* S, struct CodeEntry* Old, struct CodeEntry* New);
/* Move all labels from Old to New. The routine will move the labels itself
- * if New does not have any labels, and move references if there is at least
- * a label for new. If references are moved, the old label is deleted
- * afterwards.
- */
+** if New does not have any labels, and move references if there is at least
+** a label for new. If references are moved, the old label is deleted
+** afterwards.
+*/
void CS_RemoveLabelRef (CodeSeg* S, struct CodeEntry* E);
/* Remove the reference between E and the label it jumps to. The reference
- * will be removed on both sides and E->JumpTo will be 0 after that. If
- * the reference was the only one for the label, the label will get
- * deleted.
- */
+** will be removed on both sides and E->JumpTo will be 0 after that. If
+** the reference was the only one for the label, the label will get
+** deleted.
+*/
void CS_MoveLabelRef (CodeSeg* S, struct CodeEntry* E, CodeLabel* L);
/* Change the reference of E to L instead of the current one. If this
- * was the only reference to the old label, the old label will get
- * deleted.
- */
+** was the only reference to the old label, the old label will get
+** deleted.
+*/
void CS_DelCodeRange (CodeSeg* S, unsigned First, unsigned Last);
/* Delete all entries between first and last, both inclusive. The function
- * can only handle basic blocks (First is the only entry, Last the only exit)
- * and no open labels. It will call FAIL if any of these preconditions are
- * violated.
- */
+** can only handle basic blocks (First is the only entry, Last the only exit)
+** and no open labels. It will call FAIL if any of these preconditions are
+** violated.
+*/
void CS_DelCodeAfter (CodeSeg* S, unsigned Last);
/* Delete all entries including the given one */
int CS_IsBasicBlock (CodeSeg* S, unsigned First, unsigned Last);
/* Check if the given code segment range is a basic block. That is, check if
- * First is the only entrance and Last is the only exit. This means that no
- * jump/branch inside the block may jump to an insn below First or after(!)
- * Last, and that no insn may jump into this block from the outside.
- */
+** First is the only entrance and Last is the only exit. This means that no
+** jump/branch inside the block may jump to an insn below First or after(!)
+** Last, and that no insn may jump into this block from the outside.
+*/
void CS_OutputPrologue (const CodeSeg* S);
/* If the given code segment is a code segment for a function, output the
- * assembler prologue into the file. That is: Output a comment header, switch
- * to the correct segment and enter the local function scope. If the code
- * segment is global, do nothing.
- */
+** assembler prologue into the file. That is: Output a comment header, switch
+** to the correct segment and enter the local function scope. If the code
+** segment is global, do nothing.
+*/
void CS_OutputEpilogue (const CodeSeg* S);
/* If the given code segment is a code segment for a function, output the
- * assembler epilogue into the file. That is: Close the local function scope.
- */
+** assembler epilogue into the file. That is: Close the local function scope.
+*/
void CS_Output (CodeSeg* S);
/* Output the code segment data to a file */
}
/* Check if we must reserve storage for the variable. We do this,
- *
- * - if it is not a typedef or function,
- * - if we don't had a storage class given ("int i")
- * - if the storage class is explicitly specified as static,
- * - or if there is an initialization.
- *
- * This means that "extern int i;" will not get storage allocated.
- */
+ **
+ ** - if it is not a typedef or function,
+ ** - if we don't had a storage class given ("int i")
+ ** - if the storage class is explicitly specified as static,
+ ** - or if there is an initialization.
+ **
+ ** This means that "extern int i;" will not get storage allocated.
+ */
if ((Decl.StorageClass & SC_FUNC) != SC_FUNC &&
(Decl.StorageClass & SC_TYPEMASK) != SC_TYPEDEF &&
((Spec.Flags & DS_DEF_STORAGE) != 0 ||
}
/* If this is a function declarator that is not followed by a comma
- * or semicolon, it must be followed by a function body. If this is
- * the case, convert an empty parameter list into one accepting no
- * parameters (same as void) as required by the standard.
- */
+ ** or semicolon, it must be followed by a function body. If this is
+ ** the case, convert an empty parameter list into one accepting no
+ ** parameters (same as void) as required by the standard.
+ */
if ((Decl.StorageClass & SC_FUNC) != 0 &&
(CurTok.Tok != TOK_COMMA) &&
(CurTok.Tok != TOK_SEMI)) {
if (CurTok.Tok == TOK_ASSIGN) {
/* We cannot initialize types of unknown size, or
- * void types in non ANSI mode.
- */
+ ** void types in ISO modes.
+ */
if (Size == 0) {
if (!IsTypeVoid (Decl.Type)) {
if (!IsTypeArray (Decl.Type)) {
}
/* Switch to the data or rodata segment. For arrays, check
- * the element qualifiers, since not the array but its
- * elements are const.
- */
+ ** the element qualifiers, since not the array but its
+ ** elements are const.
+ */
if (IsQualConst (GetBaseElementType (Decl.Type))) {
g_userodata ();
} else {
struct tm* TM;
/* Since strftime is locale dependent, we need the abbreviated month names
- * in english.
- */
+ ** in english.
+ */
static const char MonthNames[12][4] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
DefineNumericMacro ("__CC65_STD__", IS_Get (&Standard));
/* Optimization macros. Since no source code has been parsed for now, the
- * IS_Get functions access the values in effect now, regardless of any
- * changes using #pragma later.
- */
+ ** IS_Get functions access the values in effect now, regardless of any
+ ** changes using #pragma later.
+ */
if (IS_Get (&Optimize)) {
long CodeSize = IS_Get (&CodeSizeFactor);
DefineNumericMacro ("__OPT__", 1);
unsigned OptAdd1 (CodeSeg* S)
/* Search for the sequence
- *
- * ldy #xx
- * jsr ldaxysp
- * jsr pushax
- * ldy #yy
- * jsr ldaxysp
- * jsr tosaddax
- *
- * and replace it by:
- *
- * ldy #xx-1
- * lda (sp),y
- * ldy #yy-3
- * clc
- * adc (sp),y
- * pha
- * ldy #xx
- * lda (sp),y
- * ldy #yy-2
- * adc (sp),y
- * tax
- * pla
- */
+**
+** ldy #xx
+** jsr ldaxysp
+** jsr pushax
+** ldy #yy
+** jsr ldaxysp
+** jsr tosaddax
+**
+** and replace it by:
+**
+** ldy #xx-1
+** lda (sp),y
+** ldy #yy-3
+** clc
+** adc (sp),y
+** pha
+** ldy #xx
+** lda (sp),y
+** ldy #yy-2
+** adc (sp),y
+** tax
+** pla
+*/
{
unsigned Changes = 0;
unsigned OptAdd2 (CodeSeg* S)
/* Search for the sequence
- *
- * ldy #xx
- * jsr ldaxysp
- * ldy #yy
- * jsr addeqysp
- *
- * and replace it by:
- *
- * ldy #xx-1
- * lda (sp),y
- * ldy #yy
- * clc
- * adc (sp),y
- * sta (sp),y
- * ldy #xx
- * lda (sp),y
- * ldy #yy+1
- * adc (sp),y
- * sta (sp),y
- *
- * provided that a/x is not used later.
- */
+**
+** ldy #xx
+** jsr ldaxysp
+** ldy #yy
+** jsr addeqysp
+**
+** and replace it by:
+**
+** ldy #xx-1
+** lda (sp),y
+** ldy #yy
+** clc
+** adc (sp),y
+** sta (sp),y
+** ldy #xx
+** lda (sp),y
+** ldy #yy+1
+** adc (sp),y
+** sta (sp),y
+**
+** provided that a/x is not used later.
+*/
{
unsigned Changes = 0;
unsigned OptAdd3 (CodeSeg* S)
/* Search for the sequence
- *
- * jsr pushax
- * ldx #$00
- * lda xxx
- * jsr tosaddax
- *
- * and replace it by
- *
- * clc
- * adc xxx
- * bcc L1
- * inx
- * L1:
- */
+**
+** jsr pushax
+** ldx #$00
+** lda xxx
+** jsr tosaddax
+**
+** and replace it by
+**
+** clc
+** adc xxx
+** bcc L1
+** inx
+** L1:
+*/
{
unsigned Changes = 0;
unsigned OptAdd4 (CodeSeg* S)
/* Search for the sequence
- *
- * jsr pushax
- * lda xxx
- * ldx yyy
- * jsr tosaddax
- *
- * and replace it by
- *
- * clc
- * adc xxx
- * pha
- * txa
- * adc yyy
- * tax
- * pla
- */
+**
+** jsr pushax
+** lda xxx
+** ldx yyy
+** jsr tosaddax
+**
+** and replace it by
+**
+** clc
+** adc xxx
+** pha
+** txa
+** adc yyy
+** tax
+** pla
+*/
{
unsigned Changes = 0;
unsigned OptAdd5 (CodeSeg* S)
/* Search for a call to incaxn and replace it by an 8 bit add if the X register
- * is not used later.
- */
+** is not used later.
+*/
{
unsigned Changes = 0;
unsigned OptAdd6 (CodeSeg* S)
/* Search for the sequence
- *
- * adc ...
- * bcc L
- * inx
- * L:
- *
- * and remove the handling of the high byte if X is not used later.
- */
+**
+** adc ...
+** bcc L
+** inx
+** L:
+**
+** and remove the handling of the high byte if X is not used later.
+*/
{
unsigned Changes = 0;
/* */
/* */
/* (C) 2001-2005, Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
unsigned OptAdd1 (CodeSeg* S);
/* Search for the sequence
- *
- * jsr pushax
- * ldy xxx
- * ldx #$00
- * lda (sp),y
- * jsr tosaddax
- *
- * and replace it by:
- *
- * ldy xxx-2
- * clc
- * adc (sp),y
- * bcc L
- * inx
- * L:
- */
+**
+** jsr pushax
+** ldy xxx
+** ldx #$00
+** lda (sp),y
+** jsr tosaddax
+**
+** and replace it by:
+**
+** ldy xxx-2
+** clc
+** adc (sp),y
+** bcc L
+** inx
+** L:
+*/
unsigned OptAdd2 (CodeSeg* S);
/* Search for the sequence
- *
- * ldy #xx
- * lda (sp),y
- * tax
- * dey
- * lda (sp),y
- * ldy #$yy
- * jsr addeqysp
- *
- * and replace it by:
- *
- * ldy #xx-1
- * lda (sp),y
- * ldy #yy
- * clc
- * adc (sp),y
- * sta (sp),y
- * ldy #xx
- * lda (sp),y
- * ldy #yy+1
- * adc (sp),y
- * sta (sp),y
- *
- * provided that a/x is not used later.
- */
+**
+** ldy #xx
+** lda (sp),y
+** tax
+** dey
+** lda (sp),y
+** ldy #$yy
+** jsr addeqysp
+**
+** and replace it by:
+**
+** ldy #xx-1
+** lda (sp),y
+** ldy #yy
+** clc
+** adc (sp),y
+** sta (sp),y
+** ldy #xx
+** lda (sp),y
+** ldy #yy+1
+** adc (sp),y
+** sta (sp),y
+**
+** provided that a/x is not used later.
+*/
unsigned OptAdd3 (CodeSeg* S);
/* Search for the sequence
- *
- * jsr pushax
- * ldx #$00
- * lda xxx
- * jsr tosaddax
- *
- * and replace it by
- *
- * clc
- * adc xxx
- * bcc L1
- * inx
- * L1:
- */
+**
+** jsr pushax
+** ldx #$00
+** lda xxx
+** jsr tosaddax
+**
+** and replace it by
+**
+** clc
+** adc xxx
+** bcc L1
+** inx
+** L1:
+*/
unsigned OptAdd4 (CodeSeg* S);
/* Search for the sequence
- *
- * jsr pushax
- * lda xxx
- * ldx yyy
- * jsr tosaddax
- *
- * and replace it by
- *
- * clc
- * adc xxx
- * pha
- * txa
- * adc yyy
- * tax
- * pla
- */
+**
+** jsr pushax
+** lda xxx
+** ldx yyy
+** jsr tosaddax
+**
+** and replace it by
+**
+** clc
+** adc xxx
+** pha
+** txa
+** adc yyy
+** tax
+** pla
+*/
unsigned OptAdd5 (CodeSeg* S);
/* Search for a call to incaxn and replace it by an 8 bit add if the X register
- * is not used later.
- */
+** is not used later.
+*/
unsigned OptAdd6 (CodeSeg* S);
/* Search for the sequence
- *
- * adc ...
- * bcc L
- * inx
- * L:
- *
- * and remove the handling of the high byte if X is not used later.
- */
+**
+** adc ...
+** bcc L
+** inx
+** L:
+**
+** and remove the handling of the high byte if X is not used later.
+*/
CodeEntry* E = CS_GetEntry (S, I);
/* Check for addressing mode indirect indexed Y where Y is zero.
- * Note: All opcodes that are available as (zp),y are also available
- * as (zp), so we can ignore the actual opcode here.
- */
+ ** Note: All opcodes that are available as (zp),y are also available
+ ** as (zp), so we can ignore the actual opcode here.
+ */
if (E->AM == AM65_ZP_INDY && E->RI->In.RegY == 0) {
/* Replace it by indirect addressing mode */
CodeEntry* E = CS_GetEntry (S, I);
/* Check for a store with a register value of zero and an addressing
- * mode available with STZ.
- */
+ ** mode available with STZ.
+ */
if (((E->OPC == OP65_STA && E->RI->In.RegA == 0) ||
(E->OPC == OP65_STX && E->RI->In.RegX == 0) ||
(E->OPC == OP65_STY && E->RI->In.RegY == 0)) &&
static void ReplaceCmp (CodeSeg* S, unsigned I, cmp_t Cond)
/* Helper function for the replacement of routines that return a boolean
- * followed by a conditional jump. Instead of the boolean value, the condition
- * codes are evaluated directly.
- * I is the index of the conditional branch, the sequence is already checked
- * to be correct.
- */
+** followed by a conditional jump. Instead of the boolean value, the condition
+** codes are evaluated directly.
+** I is the index of the conditional branch, the sequence is already checked
+** to be correct.
+*/
{
CodeEntry* N;
CodeLabel* L;
case CMP_GT:
/* Replace by
- * beq @L
- * jpl Target
- * @L: ...
- */
+ ** beq @L
+ ** jpl Target
+ ** @L: ...
+ */
if ((N = CS_GetNextEntry (S, I)) == 0) {
/* No such entry */
Internal ("Invalid program flow");
case CMP_LE:
/* Replace by
- * jmi Target
- * jeq Target
- */
+ ** jmi Target
+ ** jeq Target
+ */
CE_ReplaceOPC (E, OP65_JMI);
L = E->JumpTo;
N = NewCodeEntry (OP65_JEQ, AM65_BRA, L->Name, L, E->LI);
case CMP_UGT:
/* Replace by
- * beq @L
- * jcs Target
- * @L: ...
- */
+ ** beq @L
+ ** jcs Target
+ ** @L: ...
+ */
if ((N = CS_GetNextEntry (S, I)) == 0) {
/* No such entry */
Internal ("Invalid program flow");
case CMP_ULE:
/* Replace by
- * jcc Target
- * jeq Target
- */
+ ** jcc Target
+ ** jeq Target
+ */
CE_ReplaceOPC (E, OP65_JCC);
L = E->JumpTo;
N = NewCodeEntry (OP65_JEQ, AM65_BRA, L->Name, L, E->LI);
static int IsImmCmp16 (CodeEntry** L)
-/* Check if the instructions at L are an immidiate compare of a/x:
- *
- *
- */
+/* Check if the instructions at L are an immediate compare of a/x:
+**
+**
+*/
{
return (L[0]->OPC == OP65_CPX &&
L[0]->AM == AM65_IMM &&
unsigned OptBoolTrans (CodeSeg* S)
/* Try to remove the call to boolean transformer routines where the call is
- * not really needed.
- */
+** not really needed.
+*/
{
unsigned Changes = 0;
(N->Info & OF_ZBRA) != 0) {
/* Make the boolean transformer unnecessary by changing the
- * the conditional jump to evaluate the condition flags that
- * are set after the compare directly. Note: jeq jumps if
- * the condition is not met, jne jumps if the condition is met.
- * Invert the code if we jump on condition not met.
- */
+ ** the conditional jump to evaluate the condition flags that
+ ** are set after the compare directly. Note: jeq jumps if
+ ** the condition is not met, jne jumps if the condition is met.
+ ** Invert the code if we jump on condition not met.
+ */
if (GetBranchCond (N->OPC) == BC_EQ) {
/* Jumps if condition false, invert condition */
Cond = CmpInvertTab [Cond];
unsigned OptCmp1 (CodeSeg* S)
/* Search for the sequence
- *
- * ldx xx
- * stx tmp1
- * ora tmp1
- *
- * and replace it by
- *
- * ora xx
- */
+**
+** ldx xx
+** stx tmp1
+** ora tmp1
+**
+** and replace it by
+**
+** ora xx
+*/
{
unsigned Changes = 0;
unsigned OptCmp2 (CodeSeg* S)
/* Search for the sequence
- *
- * stx xx
- * stx tmp1
- * ora tmp1
- *
- * and replace it by
- *
- * stx xx
- * ora xx
- */
+**
+** stx xx
+** stx tmp1
+** ora tmp1
+**
+** and replace it by
+**
+** stx xx
+** ora xx
+*/
{
unsigned Changes = 0;
unsigned OptCmp3 (CodeSeg* S)
/* Search for
- *
- * lda/and/ora/eor ...
- * cmp #$00
- * jeq/jne
- * or
- * lda/and/ora/eor ...
- * cmp #$00
- * jsr boolxx
- *
- * and remove the cmp.
- */
+**
+** lda/and/ora/eor ...
+** cmp #$00
+** jeq/jne
+** or
+** lda/and/ora/eor ...
+** cmp #$00
+** jsr boolxx
+**
+** and remove the cmp.
+*/
{
unsigned Changes = 0;
int Delete = 0;
/* Check for the call to boolxx. We only remove the compare if
- * the carry flag is not evaluated later, because the load will
- * not set the carry flag.
- */
+ ** the carry flag is not evaluated later, because the load will
+ ** not set the carry flag.
+ */
if (L[2]->OPC == OP65_JSR) {
switch (FindBoolCmpCond (L[2]->Arg)) {
} else if ((L[2]->Info & OF_FBRA) != 0) {
/* The following insn branches on the condition of the load,
- * so the compare instruction might be removed. For safety,
- * do some more checks if the carry isn't used later, since
- * the compare does set the carry, but the load does not.
- */
+ ** so the compare instruction might be removed. For safety,
+ ** do some more checks if the carry isn't used later, since
+ ** the compare does set the carry, but the load does not.
+ */
CodeEntry* E;
CodeEntry* N;
if ((E = CS_GetNextEntry (S, I+2)) != 0 &&
FindBoolCmpCond (N->Arg) == CMP_INV)) {
/* The following insn branches on the condition of a load,
- * and there's no use of the carry flag in sight, so the
- * compare instruction can be removed.
- */
+ ** and there's no use of the carry flag in sight, so the
+ ** compare instruction can be removed.
+ */
Delete = 1;
}
}
unsigned OptCmp4 (CodeSeg* S)
/* Search for
- *
- * lda x
- * ldx y
- * cpx #a
- * bne L1
- * cmp #b
- * L1: jne/jeq L2
- *
- * If a is zero, we may remove the compare. If a and b are both zero, we may
- * replace it by the sequence
- *
- * lda x
- * ora x+1
- * jne/jeq ...
- *
- * L1 may be either the label at the branch instruction, or the target label
- * of this instruction.
- */
+**
+** lda x
+** ldx y
+** cpx #a
+** bne L1
+** cmp #b
+** L1: jne/jeq L2
+**
+** If a is zero, we may remove the compare. If a and b are both zero, we may
+** replace it by the sequence
+**
+** lda x
+** ora x+1
+** jne/jeq ...
+**
+** L1 may be either the label at the branch instruction, or the target label
+** of this instruction.
+*/
{
unsigned Changes = 0;
CS_DelEntries (S, I+2, 3);
} else {
/* Move the lda instruction after the first branch. This will
- * improve speed, since the load is delayed after the first
- * test.
- */
+ ** improve speed, since the load is delayed after the first
+ ** test.
+ */
CS_MoveEntry (S, I, I+4);
/* We will replace the ldx/cpx by lda/cmp */
CE_ReplaceOPC (L[1], OP65_CMP);
/* Beware: If the first LDA instruction had a label, we have
- * to move this label to the top of the sequence again.
- */
+ ** to move this label to the top of the sequence again.
+ */
if (CE_HasLabel (E)) {
CS_MoveLabels (S, E, L[0]);
}
unsigned OptCmp5 (CodeSeg* S)
/* Optimize compares of local variables:
- *
- * ldy #o
- * jsr ldaxysp
- * cpx #a
- * bne L1
- * cmp #b
- * jne/jeq L2
- */
+**
+** ldy #o
+** jsr ldaxysp
+** cpx #a
+** bne L1
+** cmp #b
+** jne/jeq L2
+*/
{
unsigned Changes = 0;
char Buf[20];
/* The value is zero, we may use the simple code version:
- * ldy #o-1
- * lda (sp),y
- * ldy #o
- * ora (sp),y
- * jne/jeq ...
- */
+ ** ldy #o-1
+ ** lda (sp),y
+ ** ldy #o
+ ** ora (sp),y
+ ** jne/jeq ...
+ */
sprintf (Buf, "$%02X", (int)(L[0]->Num-1));
X = NewCodeEntry (OP65_LDY, AM65_IMM, Buf, 0, L[0]->LI);
CS_InsertEntry (S, X, I+1);
char Buf[20];
/* Change the code to just use the A register. Move the load
- * of the low byte after the first branch if possible:
- *
- * ldy #o
- * lda (sp),y
- * cmp #a
- * bne L1
- * ldy #o-1
- * lda (sp),y
- * cmp #b
- * jne/jeq ...
- */
+ ** of the low byte after the first branch if possible:
+ **
+ ** ldy #o
+ ** lda (sp),y
+ ** cmp #a
+ ** bne L1
+ ** ldy #o-1
+ ** lda (sp),y
+ ** cmp #b
+ ** jne/jeq ...
+ */
X = NewCodeEntry (OP65_LDY, AM65_IMM, L[0]->Arg, 0, L[0]->LI);
CS_InsertEntry (S, X, I+3);
unsigned OptCmp6 (CodeSeg* S)
/* Search for calls to compare subroutines followed by a conditional branch
- * and replace them by cheaper versions, since the branch means that the
- * boolean value returned by these routines is not needed (we may also check
- * that explicitly, but for the current code generator it is always true).
- */
+** and replace them by cheaper versions, since the branch means that the
+** boolean value returned by these routines is not needed (we may also check
+** that explicitly, but for the current code generator it is always true).
+*/
{
unsigned Changes = 0;
!CE_HasLabel (N)) {
/* The tos... functions will return a boolean value in a/x and
- * the Z flag says if this value is zero or not. We will call
- * a cheaper subroutine instead, one that does not return a
- * boolean value but only valid flags. Note: jeq jumps if
- * the condition is not met, jne jumps if the condition is met.
- * Invert the code if we jump on condition not met.
- */
+ ** the Z flag says if this value is zero or not. We will call
+ ** a cheaper subroutine instead, one that does not return a
+ ** boolean value but only valid flags. Note: jeq jumps if
+ ** the condition is not met, jne jumps if the condition is met.
+ ** Invert the code if we jump on condition not met.
+ */
if (GetBranchCond (N->OPC) == BC_EQ) {
/* Jumps if condition false, invert condition */
Cond = CmpInvertTab [Cond];
unsigned OptCmp7 (CodeSeg* S)
/* Search for a sequence ldx/txa/branch and remove the txa if A is not
- * used later.
- */
+** used later.
+*/
{
unsigned Changes = 0;
unsigned OptCmp8 (CodeSeg* S)
/* Check for register compares where the contents of the register and therefore
- * the result of the compare is known.
- */
+** the result of the compare is known.
+*/
{
unsigned Changes = 0;
unsigned I;
CE_IsConstImm (E)) {
/* We are able to evaluate the compare at compile time. Check if
- * one or more branches are ahead.
- */
+ ** one or more branches are ahead.
+ */
unsigned JumpsChanged = 0;
CodeEntry* N;
while ((N = CS_GetNextEntry (S, I)) != 0 && /* Followed by something.. */
case BC_VC:
case BC_VS:
/* Not set by the compare operation, bail out (Note:
- * Just skipping anything here is rather stupid, but
- * the sequence is never generated by the compiler,
- * so it's quite safe to skip).
- */
+ ** Just skipping anything here is rather stupid, but
+ ** the sequence is never generated by the compiler,
+ ** so it's quite safe to skip).
+ */
goto NextEntry;
default:
}
/* If the condition is false, we may remove the jump. Otherwise
- * the branch will always be taken, so we may replace it by a
- * jump (and bail out).
- */
+ ** the branch will always be taken, so we may replace it by a
+ ** jump (and bail out).
+ */
if (!Cond) {
CS_DelEntry (S, I+1);
} else {
unsigned OptCmp9 (CodeSeg* S)
/* Search for the sequence
- *
- * sbc xx
- * bvs/bvc L
- * eor #$80
- * L: asl a
- * bcc/bcs somewhere
- *
- * If A is not used later (which should be the case), we can branch on the N
- * flag instead of the carry flag and remove the asl.
- */
+**
+** sbc xx
+** bvs/bvc L
+** eor #$80
+** L: asl a
+** bcc/bcs somewhere
+**
+** If A is not used later (which should be the case), we can branch on the N
+** flag instead of the carry flag and remove the asl.
+*/
{
unsigned Changes = 0;
unsigned I;
unsigned OptBoolTrans (CodeSeg* S);
/* Try to remove the call to boolean transformer routines where the call is
- * not really needed.
- */
+** not really needed.
+*/
unsigned OptCmp1 (CodeSeg* S);
/* Search for the sequence
- *
- * ldx xx
- * stx tmp1
- * ora tmp1
- *
- * and replace it by
- *
- * ora xx
- */
+**
+** ldx xx
+** stx tmp1
+** ora tmp1
+**
+** and replace it by
+**
+** ora xx
+*/
unsigned OptCmp2 (CodeSeg* S);
/* Search for the sequence
- *
- * stx xx
- * stx tmp1
- * ora tmp1
- *
- * and replace it by
- *
- * stx xx
- * ora xx
- */
+**
+** stx xx
+** stx tmp1
+** ora tmp1
+**
+** and replace it by
+**
+** stx xx
+** ora xx
+*/
unsigned OptCmp3 (CodeSeg* S);
/* Search for
- *
- * lda/and/ora/eor ...
- * cmp #$00
- * jeq/jne
- * or
- * lda/and/ora/eor ...
- * cmp #$00
- * jsr boolxx
- *
- * and remove the cmp.
- */
+**
+** lda/and/ora/eor ...
+** cmp #$00
+** jeq/jne
+** or
+** lda/and/ora/eor ...
+** cmp #$00
+** jsr boolxx
+**
+** and remove the cmp.
+*/
unsigned OptCmp4 (CodeSeg* S);
/* Search for
- *
- * lda x
- * ldx y
- * cpx #a
- * bne L1
- * cmp #b
- * jne/jeq L2
- *
- * If a is zero, we may remove the compare. If a and b are both zero, we may
- * replace it by the sequence
- *
- * lda x
- * ora x+1
- * jne/jeq ...
- *
- * L1 may be either the label at the branch instruction, or the target label
- * of this instruction.
- */
+**
+** lda x
+** ldx y
+** cpx #a
+** bne L1
+** cmp #b
+** jne/jeq L2
+**
+** If a is zero, we may remove the compare. If a and b are both zero, we may
+** replace it by the sequence
+**
+** lda x
+** ora x+1
+** jne/jeq ...
+**
+** L1 may be either the label at the branch instruction, or the target label
+** of this instruction.
+*/
unsigned OptCmp5 (CodeSeg* S);
/* Optimize compares of local variables:
- *
- * ldy #o
- * lda (sp),y
- * tax
- * dey
- * lda (sp),y
- * cpx #a
- * bne L1
- * cmp #b
- * jne/jeq L2
- */
+**
+** ldy #o
+** lda (sp),y
+** tax
+** dey
+** lda (sp),y
+** cpx #a
+** bne L1
+** cmp #b
+** jne/jeq L2
+*/
unsigned OptCmp6 (CodeSeg* S);
/* Search for calls to compare subroutines followed by a conditional branch
- * and replace them by cheaper versions, since the branch means that the
- * boolean value returned by these routines is not needed (we may also check
- * that explicitly, but for the current code generator it is always true).
- */
+** and replace them by cheaper versions, since the branch means that the
+** boolean value returned by these routines is not needed (we may also check
+** that explicitly, but for the current code generator it is always true).
+*/
unsigned OptCmp7 (CodeSeg* S);
/* Search for a sequence ldx/txa/branch and remove the txa if A is not
- * used later.
- */
+** used later.
+*/
unsigned OptCmp8 (CodeSeg* S);
/* Check for register compares where the contents of the register and therefore
- * the result of the compare is known.
- */
+** the result of the compare is known.
+*/
unsigned OptCmp9 (CodeSeg* S);
/* Search for the sequence
- *
- * sbc xx
- * bvs/bvc L
- * eor #$80
- * L: asl a
- * bcc/bcs somewhere
- *
- * If A is not used later (which should be the case), we can branch on the N
- * flag instead of the carry flag and remove the asl.
- */
+**
+** sbc xx
+** bvs/bvc L
+** eor #$80
+** L: asl a
+** bcc/bcs somewhere
+**
+** If A is not used later (which should be the case), we can branch on the N
+** flag instead of the carry flag and remove the asl.
+*/
/* If the argument of N is a zero page location that ends with "+1", we
- * must also check for word accesses to the location without +1.
- */
+ ** must also check for word accesses to the location without +1.
+ */
if (N->AM == AM65_ZP && NLen > 2 && strcmp (N->Arg + NLen - 2, "+1") == 0) {
What |= Base;
}
/* If the argument is zero page indirect, we must also check for accesses
- * to "arg+1"
- */
+ ** to "arg+1"
+ */
if (N->AM == AM65_ZP_INDY || N->AM == AM65_ZPX_IND || N->AM == AM65_ZP_IND) {
What |= Word;
}
CodeEntry* E = CS_GetEntry (S, From);
/* Check if there is an argument and if this argument equals Arg in
- * some variants.
- */
+ ** some variants.
+ */
if (E->Arg[0] != '\0') {
unsigned ELen;
static int GetBranchDist (CodeSeg* S, unsigned From, CodeEntry* To)
/* Get the branch distance between the two entries and return it. The distance
- * will be negative for backward jumps and positive for forward jumps.
- */
+** will be negative for backward jumps and positive for forward jumps.
+*/
{
/* Get the index of the branch target */
unsigned TI = CS_GetEntryIndex (S, To);
/* Get the jump target and the next entry. There's always a next
- * entry, because we don't cover the last entry in the loop.
- */
+ ** entry, because we don't cover the last entry in the loop.
+ */
CodeEntry* X = 0;
CodeEntry* T = E->JumpTo->Owner;
CodeEntry* N = CS_GetNextEntry (S, I);
if (T->OPC == OP65_RTS) {
/* It's a jump to RTS. Create a conditional branch around an
- * RTS insn.
- */
+ ** RTS insn.
+ */
X = NewCodeEntry (OP65_RTS, AM65_IMP, 0, 0, T->LI);
} else if (T->OPC == OP65_JMP && T->JumpTo == 0) {
/* It's a jump to a label outside the function. Create a
- * conditional branch around a jump to the external label.
- */
+ ** conditional branch around a jump to the external label.
+ */
X = NewCodeEntry (OP65_JMP, AM65_ABS, T->Arg, T->JumpTo, T->LI);
}
CS_InsertEntry (S, X, I+1);
/* Create a conditional branch with the inverse condition
- * around the replacement insn
- */
+ ** around the replacement insn
+ */
/* Get the new branch opcode */
NewBranch = MakeShortBranch (GetInverseBranch (E->OPC));
CodeEntry* E = CS_GetEntry (S, I);
/* Check if it's a branch, if it has a local target, and if the target
- * is the next instruction.
- */
+ ** is the next instruction.
+ */
if (E->AM == AM65_BRA &&
E->JumpTo &&
E->JumpTo->Owner == CS_GetNextEntry (S, I)) {
unsigned OptDeadCode (CodeSeg* S)
/* Remove dead code (code that follows an unconditional jump or an rts/rti
- * and has no label)
- */
+** and has no label)
+*/
{
unsigned Changes = 0;
CodeEntry* E = CS_GetEntry (S, I);
/* Check if it's an unconditional branch, and if the next entry has
- * no labels attached, or if the label is just used so that the insn
- * can jump to itself.
- */
+ ** no labels attached, or if the label is just used so that the insn
+ ** can jump to itself.
+ */
if ((E->Info & OF_DEAD) != 0 && /* Dead code follows */
(N = CS_GetNextEntry (S, I)) != 0 && /* Has next entry */
(!CE_HasLabel (N) || /* Don't has a label */
unsigned OptJumpCascades (CodeSeg* S)
/* Optimize jump cascades (jumps to jumps). In such a case, the jump is
- * replaced by a jump to the final location. This will in some cases produce
- * worse code, because some jump targets are no longer reachable by short
- * branches, but this is quite rare, so there are more advantages than
- * disadvantages.
- */
+** replaced by a jump to the final location. This will in some cases produce
+** worse code, because some jump targets are no longer reachable by short
+** branches, but this is quite rare, so there are more advantages than
+** disadvantages.
+*/
{
unsigned Changes = 0;
CodeEntry* E = CS_GetEntry (S, I);
/* Check:
- * - if it's a branch,
- * - if it has a jump label,
- * - if this jump label is not attached to the instruction itself,
- * - if the target instruction is itself a branch,
- * - if either the first branch is unconditional or the target of
- * the second branch is internal to the function.
- * The latter condition will avoid conditional branches to targets
- * outside of the function (usually incspx), which won't simplify the
- * code, since conditional far branches are emulated by a short branch
- * around a jump.
- */
+ ** - if it's a branch,
+ ** - if it has a jump label,
+ ** - if this jump label is not attached to the instruction itself,
+ ** - if the target instruction is itself a branch,
+ ** - if either the first branch is unconditional or the target of
+ ** the second branch is internal to the function.
+ ** The latter condition will avoid conditional branches to targets
+ ** outside of the function (usually incspx), which won't simplify the
+ ** code, since conditional far branches are emulated by a short branch
+ ** around a jump.
+ */
if ((E->Info & OF_BRA) != 0 &&
(OldLabel = E->JumpTo) != 0 &&
(N = OldLabel->Owner) != E &&
((E->Info & OF_CBRA) == 0 ||
N->JumpTo != 0)) {
- /* Check if we can use the final target label. This is the case,
- * if the target branch is an absolut branch, or if it is a
- * conditional branch checking the same condition as the first one.
- */
+ /* Check if we can use the final target label. That is the case,
+ ** if the target branch is an absolute branch; or, if it is a
+ ** conditional branch checking the same condition as the first one.
+ */
if ((N->Info & OF_UBRA) != 0 ||
((E->Info & OF_CBRA) != 0 &&
GetBranchCond (E->OPC) == GetBranchCond (N->OPC))) {
/* This is a jump cascade and we may jump to the final target,
- * provided that the other insn does not jump to itself. If
- * this is the case, we can also jump to ourselves, otherwise
- * insert a jump to the new instruction and remove the old one.
- */
+ ** provided that the other insn does not jump to itself. If
+ ** this is the case, we can also jump to ourselves, otherwise
+ ** insert a jump to the new instruction and remove the old one.
+ */
CodeEntry* X;
CodeLabel* LN = N->JumpTo;
if (LN != 0 && LN->Owner == N) {
/* We found a jump to a jump to itself. Replace our jump
- * by a jump to itself.
- */
+ ** by a jump to itself.
+ */
CodeLabel* LE = CS_GenLabel (S, E);
X = NewCodeEntry (E->OPC, E->AM, LE->Name, LE, E->LI);
++Changes;
/* Check if both are conditional branches, and the condition of
- * the second is the inverse of that of the first. In this case,
- * the second branch will never be taken, and we may jump directly
- * to the instruction behind this one.
- */
+ ** the second is the inverse of that of the first. In this case,
+ ** the second branch will never be taken, and we may jump directly
+ ** to the instruction behind this one.
+ */
} else if ((E->Info & OF_CBRA) != 0 && (N->Info & OF_CBRA) != 0) {
CodeEntry* X; /* Instruction behind N */
}
/* We may jump behind this conditional branch. Get the
- * pointer to the next instruction
- */
+ ** pointer to the next instruction
+ */
if ((X = CS_GetNextEntry (S, CS_GetEntryIndex (S, N))) == 0) {
/* N is the last entry, bail out */
goto NextEntry;
unsigned OptRTS (CodeSeg* S)
/* Optimize subroutine calls followed by an RTS. The subroutine call will get
- * replaced by a jump. Don't bother to delete the RTS if it does not have a
- * label, the dead code elimination should take care of it.
- */
+** replaced by a jump. Don't bother to delete the RTS if it does not have a
+** label, the dead code elimination should take care of it.
+*/
{
unsigned Changes = 0;
unsigned OptJumpTarget1 (CodeSeg* S)
/* If the instruction preceeding an unconditional branch is the same as the
- * instruction preceeding the jump target, the jump target may be moved
- * one entry back. This is a size optimization, since the instruction before
- * the branch gets removed.
- */
+** instruction preceeding the jump target, the jump target may be moved
+** one entry back. This is a size optimization, since the instruction before
+** the branch gets removed.
+*/
{
unsigned Changes = 0;
CodeEntry* E1; /* Entry 1 */
E2 = CS_GetNextEntry (S, I);
/* Check if we have a jump or branch without a label attached, and
- * a jump target, which is not attached to the jump itself
- */
+ ** a jump target, which is not attached to the jump itself
+ */
if (E2 != 0 &&
(E2->Info & OF_UBRA) != 0 &&
!CE_HasLabel (E2) &&
}
/* The entry preceeding the branch target may not be the branch
- * insn.
- */
+ ** insn.
+ */
if (T1 == E2) {
goto NextEntry;
}
}
/* Get the label for the instruction preceeding the jump target.
- * This routine will create a new label if the instruction does
- * not already have one.
- */
+ ** This routine will create a new label if the instruction does
+ ** not already have one.
+ */
TL1 = CS_GenLabel (S, T1);
/* Change the jump target to point to this new label */
CS_MoveLabelRef (S, E2, TL1);
/* If the instruction preceeding the jump has labels attached,
- * move references to this label to the new label.
- */
+ ** move references to this label to the new label.
+ */
if (CE_HasLabel (E1)) {
CS_MoveLabels (S, E1, T1);
}
unsigned OptJumpTarget2 (CodeSeg* S)
/* If a bcs jumps to a sec insn or a bcc jumps to clc, skip this insn, since
- * it's job is already done.
- */
+** it's job is already done.
+*/
{
unsigned Changes = 0;
}
/* Get the owner insn of the jump target and check if it's the one, we
- * will skip if present.
- */
+ ** will skip if present.
+ */
T = E->JumpTo->Owner;
if (T->OPC != OPC) {
goto NextEntry;
}
/* Get the label for the instruction following the jump target.
- * This routine will create a new label if the instruction does
- * not already have one.
- */
+ ** This routine will create a new label if the instruction does
+ ** not already have one.
+ */
L = CS_GenLabel (S, N);
/* Change the jump target to point to this new label */
unsigned OptJumpTarget3 (CodeSeg* S)
/* Jumps to load instructions of a register, that do already have the matching
- * register contents may skip the load instruction, since it's job is already
- * done.
- */
+** register contents may skip the load instruction, since it's job is already
+** done.
+*/
{
unsigned Changes = 0;
unsigned I;
CodeEntry* E = CS_GetEntry (S, I);
/* Check if this is a load insn with a label and the next insn is not
- * a conditional branch that needs the flags from the load.
- */
+ ** a conditional branch that needs the flags from the load.
+ */
if ((E->Info & OF_LOAD) != 0 &&
CE_IsConstImm (E) &&
CE_HasLabel (E) &&
CodeLabel* L = CE_GetLabel (E, J);
/* Loop over all insn that reference this label. Since we may
- * eventually remove a reference in the loop, we must loop
- * from end down to start.
- */
+ ** eventually remove a reference in the loop, we must loop
+ ** from end down to start.
+ */
for (K = CL_GetRefCount (L) - 1; K >= 0; --K) {
/* Get the entry that jumps here */
/* Check if the outgoing value is the one thats's loaded */
if (Val == (unsigned char) E->Num) {
- /* Ok, skip the insn. First, generate a label for the
- * next insn after E.
- */
+ /* OK, skip the insn. First, generate a label for the
+ ** next insn after E.
+ */
if (LN == 0) {
LN = CS_GenLabel (S, N);
}
unsigned OptCondBranches1 (CodeSeg* S)
/* Performs several optimization steps:
- *
- * - If an immidiate load of a register is followed by a conditional jump that
- * is never taken because the load of the register sets the flags in such a
- * manner, remove the conditional branch.
- * - If the conditional branch is always taken because of the register load,
- * replace it by a jmp.
- * - If a conditional branch jumps around an unconditional branch, remove the
- * conditional branch and make the jump a conditional branch with the
- * inverse condition of the first one.
- */
+**
+** - If an immediate load of a register is followed by a conditional jump that
+** is never taken because the load of the register sets the flags in such a
+** manner, remove the conditional branch.
+** - If the conditional branch is always taken because of the register load,
+** replace it by a jmp.
+** - If a conditional branch jumps around an unconditional branch, remove the
+** conditional branch and make the jump a conditional branch with the
+** inverse condition of the first one.
+*/
{
unsigned Changes = 0;
(N = CS_GetNextEntry (S, I)) != 0 && /* There is a following entry */
(N->Info & OF_UBRA) != 0 && /* ..which is an uncond branch, */
!CE_HasLabel (N) && /* ..has no label attached */
- L->Owner == CS_GetNextEntry (S, I+1)) {/* ..and jump target follows */
+ L->Owner == CS_GetNextEntry (S, I+1)) { /* ..and jump target follows */
/* Replace the jump by a conditional branch with the inverse branch
- * condition than the branch around it.
- */
+ ** condition than the branch around it.
+ */
CE_ReplaceOPC (N, GetInverseBranch (E->OPC));
/* Remove the conditional branch */
unsigned OptCondBranches2 (CodeSeg* S)
/* If on entry to a "rol a" instruction the accu is zero, and a beq/bne follows,
- * we can remove the rol and branch on the state of the carry flag.
- */
+** we can remove the rol and branch on the state of the carry flag.
+*/
{
unsigned Changes = 0;
unsigned I;
(E->Chg & REG_ZP) != 0) {
/* Check for the zero page location. We know that there cannot be
- * more than one zero page location involved in the store.
- */
+ ** more than one zero page location involved in the store.
+ */
unsigned R = E->Chg & REG_ZP;
/* Get register usage and check if the register value is used later */
case OP65_STA:
/* If we store into a known zero page location, and this
- * location does already contain the value to be stored,
- * remove the store.
- */
+ ** location does already contain the value to be stored,
+ ** remove the store.
+ */
if (RegValIsKnown (In->RegA) && /* Value of A is known */
E->AM == AM65_ZP && /* Store into zp */
In->RegA == ZPRegVal (E->Chg, In)) { /* Value identical */
case OP65_STX:
/* If we store into a known zero page location, and this
- * location does already contain the value to be stored,
- * remove the store.
- */
+ ** location does already contain the value to be stored,
+ ** remove the store.
+ */
if (RegValIsKnown (In->RegX) && /* Value of A is known */
E->AM == AM65_ZP && /* Store into zp */
In->RegX == ZPRegVal (E->Chg, In)) { /* Value identical */
Delete = 1;
/* If the value in the X register is known and the same as
- * that in the A register, replace the store by a STA. The
- * optimizer will then remove the load instruction for X
- * later. STX does support the zeropage,y addressing mode,
- * so be sure to check for that.
- */
+ ** that in the A register, replace the store by a STA. The
+ ** optimizer will then remove the load instruction for X
+ ** later. STX does support the zeropage,y addressing mode,
+ ** so be sure to check for that.
+ */
} else if (RegValIsKnown (In->RegX) &&
In->RegX == In->RegA &&
E->AM != AM65_ABSY &&
case OP65_STY:
/* If we store into a known zero page location, and this
- * location does already contain the value to be stored,
- * remove the store.
- */
+ ** location does already contain the value to be stored,
+ ** remove the store.
+ */
if (RegValIsKnown (In->RegY) && /* Value of Y is known */
E->AM == AM65_ZP && /* Store into zp */
In->RegY == ZPRegVal (E->Chg, In)) { /* Value identical */
Delete = 1;
/* If the value in the Y register is known and the same as
- * that in the A register, replace the store by a STA. The
- * optimizer will then remove the load instruction for Y
- * later. If replacement by A is not possible try a
- * replacement by X, but check for invalid addressing modes
- * in this case.
- */
+ ** that in the A register, replace the store by a STA. The
+ ** optimizer will then remove the load instruction for Y
+ ** later. If replacement by A is not possible try a
+ ** replacement by X, but check for invalid addressing modes
+ ** in this case.
+ */
} else if (RegValIsKnown (In->RegY)) {
if (In->RegY == In->RegA) {
CE_ReplaceOPC (E, OP65_STA);
case OP65_STZ:
/* If we store into a known zero page location, and this
- * location does already contain the value to be stored,
- * remove the store.
- */
+ ** location does already contain the value to be stored,
+ ** remove the store.
+ */
if ((CPUIsets[CPU] & CPU_ISET_65SC02) != 0 && E->AM == AM65_ZP) {
if (ZPRegVal (E->Chg, In) == 0) {
Delete = 1;
CodeEntry* E = CS_GetEntry (S, I);
/* Check if it is a store instruction followed by a load from the
- * same address which is itself not followed by a conditional branch.
- */
+ ** same address which is itself not followed by a conditional branch.
+ */
if ((E->Info & OF_STORE) != 0 &&
(N = CS_GetNextEntry (S, I)) != 0 &&
!CE_HasLabel (N) &&
(E->OPC == OP65_TYA && N->OPC == OP65_TAY && !RegAUsed (S, I+2))) {
/* If the next insn is a conditional branch, check if the insn
- * preceeding the first xfr will set the flags right, otherwise we
- * may not remove the sequence.
- */
+ ** preceeding the first xfr will set the flags right, otherwise we
+ ** may not remove the sequence.
+ */
if ((X = CS_GetNextEntry (S, I+1)) == 0) {
goto NextEntry;
}
unsigned OptTransfers2 (CodeSeg* S)
/* Replace loads followed by a register transfer by a load with the second
- * register if possible.
- */
+** register if possible.
+*/
{
unsigned Changes = 0;
CodeEntry* E = CS_GetEntry (S, I);
/* Check if we have a load followed by a transfer where the loaded
- * register is not used later.
- */
+ ** register is not used later.
+ */
if ((E->Info & OF_LOAD) != 0 &&
(N = CS_GetNextEntry (S, I)) != 0 &&
!CE_HasLabel (N) &&
X = NewCodeEntry (OP65_LDA, E->AM, E->Arg, 0, N->LI);
} else if (E->OPC == OP65_LDX && N->OPC == OP65_TXA) {
/* LDX/TXA. LDA doesn't support zp,y, so we must map it to
- * abs,y instead.
- */
+ ** abs,y instead.
+ */
am_t AM = (E->AM == AM65_ZPY)? AM65_ABSY : E->AM;
X = NewCodeEntry (OP65_LDA, AM, E->Arg, 0, N->LI);
}
unsigned OptTransfers3 (CodeSeg* S)
/* Replace a register transfer followed by a store of the second register by a
- * store of the first register if this is possible.
- */
+** store of the first register if this is possible.
+*/
{
unsigned Changes = 0;
unsigned UsedRegs = REG_NONE; /* Track used registers */
} State = Initialize;
/* Walk over the entries. Look for a xfer instruction that is followed by
- * a store later, where the value of the register is not used later.
- */
+ ** a store later, where the value of the register is not used later.
+ */
unsigned I = 0;
while (I < CS_GetEntryCount (S)) {
case FoundXfer:
/* If we find a conditional jump, abort the sequence, since
- * handling them makes things really complicated.
- */
+ ** handling them makes things really complicated.
+ */
if (E->Info & OF_CBRA) {
/* Switch back to searching */
} else if ((E->Use & XferEntry->Chg) != 0) {
/* It it's a store instruction, and the block is a basic
- * block, proceed. Otherwise restart
- */
+ ** block, proceed. Otherwise restart
+ */
if ((E->Info & OF_STORE) != 0 &&
CS_IsBasicBlock (S, Xfer, I)) {
Store = I;
} else if (E->Chg & XferEntry->Chg) {
/* We *may* add code here to remove the transfer, but I'm
- * currently not sure about the consequences, so I won't
- * do that and bail out instead.
- */
+ ** currently not sure about the consequences, so I won't
+ ** do that and bail out instead.
+ */
I = Xfer;
State = Initialize;
case FoundStore:
/* We are at the instruction behind the store. If the register
- * isn't used later, and we have an address mode match, we can
- * replace the transfer by a store and remove the store here.
- */
+ ** isn't used later, and we have an address mode match, we can
+ ** replace the transfer by a store and remove the store here.
+ */
if ((GetRegInfo (S, I, XferEntry->Chg) & XferEntry->Chg) == 0 &&
(StoreEntry->AM == AM65_ABS ||
StoreEntry->AM == AM65_ZP) &&
unsigned OptTransfers4 (CodeSeg* S)
/* Replace a load of a register followed by a transfer insn of the same register
- * by a load of the second register if possible.
- */
+** by a load of the second register if possible.
+*/
{
unsigned Changes = 0;
unsigned Load = 0; /* Index of load insn */
} State = Search;
/* Walk over the entries. Look for a load instruction that is followed by
- * a load later.
- */
+ ** a load later.
+ */
unsigned I = 0;
while (I < CS_GetEntryCount (S)) {
case FoundLoad:
/* If we find a conditional jump, abort the sequence, since
- * handling them makes things really complicated.
- */
+ ** handling them makes things really complicated.
+ */
if (E->Info & OF_CBRA) {
/* Switch back to searching */
} else if ((E->Use & LoadEntry->Chg) != 0) {
/* It it's a xfer instruction, and the block is a basic
- * block, proceed. Otherwise restart
- */
+ ** block, proceed. Otherwise restart
+ */
if ((E->Info & OF_XFR) != 0 &&
CS_IsBasicBlock (S, Load, I)) {
Xfer = I;
} else if (E->Chg & LoadEntry->Chg) {
/* We *may* add code here to remove the load, but I'm
- * currently not sure about the consequences, so I won't
- * do that and bail out instead.
- */
+ ** currently not sure about the consequences, so I won't
+ ** do that and bail out instead.
+ */
I = Load;
State = Search;
}
case FoundXfer:
/* We are at the instruction behind the xfer. If the register
- * isn't used later, and we have an address mode match, we can
- * replace the transfer by a load and remove the initial load.
- */
+ ** isn't used later, and we have an address mode match, we can
+ ** replace the transfer by a load and remove the initial load.
+ */
if ((GetRegInfo (S, I, LoadEntry->Chg) & LoadEntry->Chg) == 0 &&
(LoadEntry->AM == AM65_ABS ||
LoadEntry->AM == AM65_ZP ||
} State = Searching;
/* Walk over the entries. Look for a push instruction that is followed by
- * a pop later, where the pop is not followed by an conditional branch,
- * and where the value of the A register is not used later on.
- * Look out for the following problems:
- *
- * - There may be another PHA/PLA inside the sequence: Restart it.
- * - If the PLA has a label, all jumps to this label must be inside
- * the sequence, otherwise we cannot remove the PHA/PLA.
- */
+ ** a pop later, where the pop is not followed by an conditional branch,
+ ** and where the value of the A register is not used later on.
+ ** Look out for the following problems:
+ **
+ ** - There may be another PHA/PLA inside the sequence: Restart it.
+ ** - If the PLA has a label, all jumps to this label must be inside
+ ** the sequence, otherwise we cannot remove the PHA/PLA.
+ */
unsigned I = 0;
while (I < CS_GetEntryCount (S)) {
/* Found a matching pop */
Pop = I;
/* Check that the block between Push and Pop is a basic
- * block (one entry, one exit). Otherwise ignore it.
- */
+ ** block (one entry, one exit). Otherwise ignore it.
+ */
if (CS_IsBasicBlock (S, Push, Pop)) {
State = FoundPop;
} else {
case FoundPop:
/* We're at the instruction after the PLA.
- * Check for the following conditions:
- * - If this instruction is a store of A that doesn't use
- * another register, if the instruction does not have a
- * label, and A is not used later, we may replace the PHA
- * by the store and remove pla if several other conditions
- * are met.
- * - If this instruction is not a conditional branch, and A
- * is either unused later, or not changed by the code
- * between push and pop, we may remove PHA and PLA.
- */
+ ** Check for the following conditions:
+ ** - If this instruction is a store of A that doesn't use
+ ** another register, if the instruction does not have a
+ ** label, and A is not used later, we may replace the PHA
+ ** by the store and remove pla if several other conditions
+ ** are met.
+ ** - If this instruction is not a conditional branch, and A
+ ** is either unused later, or not changed by the code
+ ** between push and pop, we may remove PHA and PLA.
+ */
if (E->OPC == OP65_STA &&
(E->AM == AM65_ABS || E->AM == AM65_ZP) &&
!CE_HasLabel (E) &&
unsigned OptPrecalc (CodeSeg* S)
/* Replace immediate operations with the accu where the current contents are
- * known by a load of the final value.
- */
+** known by a load of the final value.
+*/
{
unsigned Changes = 0;
unsigned I;
case OP65_ADC:
case OP65_SBC:
/* If this is an operation with an immediate operand of zero,
- * and the register is zero, the operation won't give us any
- * results we don't already have (including the flags), so
- * remove it. Something like this is generated as a result of
- * a compare where parts of the values are known to be zero.
- */
+ ** and the register is zero, the operation won't give us any
+ ** results we don't already have (including the flags), so
+ ** remove it. Something like this is generated as a result of
+ ** a compare where parts of the values are known to be zero.
+ */
if (In->RegA == 0 && CE_IsKnownImm (E, 0x00)) {
/* 0-0 or 0+0 -> remove */
CS_DelEntry (S, I);
unsigned OptIndLoads1 (CodeSeg* S)
/* Change
- *
- * lda (zp),y
- *
- * into
- *
- * lda (zp,x)
- *
- * provided that x and y are both zero.
- */
+**
+** lda (zp),y
+**
+** into
+**
+** lda (zp,x)
+**
+** provided that x and y are both zero.
+*/
{
unsigned Changes = 0;
unsigned I;
unsigned OptIndLoads2 (CodeSeg* S)
/* Change
- *
- * lda (zp,x)
- *
- * into
- *
- * lda (zp),y
- *
- * provided that x and y are both zero.
- */
+**
+** lda (zp,x)
+**
+** into
+**
+** lda (zp),y
+**
+** provided that x and y are both zero.
+*/
{
unsigned Changes = 0;
unsigned I;
unsigned OptDeadCode (CodeSeg* S);
/* Remove dead code (code that follows an unconditional jump or an rts/rti
- * and has no label)
- */
+** and has no label)
+*/
unsigned OptJumpCascades (CodeSeg* S);
/* Optimize jump cascades (jumps to jumps). In such a case, the jump is
- * replaced by a jump to the final location. This will in some cases produce
- * worse code, because some jump targets are no longer reachable by short
- * branches, but this is quite rare, so there are more advantages than
- * disadvantages.
- */
+** replaced by a jump to the final location. This will in some cases produce
+** worse code, because some jump targets are no longer reachable by short
+** branches, but this is quite rare, so there are more advantages than
+** disadvantages.
+*/
unsigned OptRTS (CodeSeg* S);
/* Optimize subroutine calls followed by an RTS. The subroutine call will get
- * replaced by a jump. Don't bother to delete the RTS if it does not have a
- * label, the dead code elimination should take care of it.
- */
+** replaced by a jump. Don't bother to delete the RTS if it does not have a
+** label, the dead code elimination should take care of it.
+*/
unsigned OptJumpTarget1 (CodeSeg* S);
/* If the instruction preceeding an unconditional branch is the same as the
- * instruction preceeding the jump target, the jump target may be moved
- * one entry back. This is a size optimization, since the instruction before
- * the branch gets removed.
- */
+** instruction preceeding the jump target, the jump target may be moved
+** one entry back. This is a size optimization, since the instruction before
+** the branch gets removed.
+*/
unsigned OptJumpTarget2 (CodeSeg* S);
/* If a bcs jumps to a sec insn or a bcc jumps to clc, skip this insn, since
- * it's job is already done.
- */
+** it's job is already done.
+*/
unsigned OptJumpTarget3 (CodeSeg* S);
/* Jumps to load instructions of a register, that do already have the matching
- * register contents may skip the load instruction, since it's job is already
- * done.
- */
+** register contents may skip the load instruction, since it's job is already
+** done.
+*/
unsigned OptCondBranches1 (CodeSeg* S);
/* If an immidiate load of a register is followed by a conditional jump that
- * is never taken because the load of the register sets the flags in such a
- * manner, remove the conditional branch.
- */
+** is never taken because the load of the register sets the flags in such a
+** manner, remove the conditional branch.
+*/
unsigned OptCondBranches2 (CodeSeg* S);
/* If on entry to a "rol a" instruction the accu is zero, and a beq/bne follows,
- * we can remove the rol and branch on the state of the carry.
- */
+** we can remove the rol and branch on the state of the carry.
+*/
unsigned OptUnusedLoads (CodeSeg* S);
/* Remove loads of registers where the value loaded is not used later. */
unsigned OptTransfers2 (CodeSeg* S);
/* Replace loads followed by a register transfer by a load with the second
- * register if possible.
- */
+** register if possible.
+*/
unsigned OptTransfers3 (CodeSeg* S);
/* Replace a register transfer followed by a store of the second register by a
- * store of the first register if this is possible.
- */
+** store of the first register if this is possible.
+*/
unsigned OptTransfers4 (CodeSeg* S);
/* Replace a load of a register followed by a transfer insn of the same register
- * by a load of the second register if possible.
- */
+** by a load of the second register if possible.
+*/
unsigned OptPushPop (CodeSeg* S);
/* Remove a PHA/PLA sequence were A is not used later */
unsigned OptPrecalc (CodeSeg* S);
/* Replace immediate operations with the accu where the current contents are
- * known by a load of the final value.
- */
+** known by a load of the final value.
+*/
unsigned OptBranchDist (CodeSeg* S);
/* Change branches for the distance needed. */
unsigned OptIndLoads1 (CodeSeg* S);
/* Change
- *
- * lda (zp),y
- *
- * into
- *
- * lda (zp,x)
- *
- * provided that x and y are both zero.
- */
+**
+** lda (zp),y
+**
+** into
+**
+** lda (zp,x)
+**
+** provided that x and y are both zero.
+*/
unsigned OptIndLoads2 (CodeSeg* S);
/* Change
- *
- * lda (zp,x)
- *
- * into
- *
- * lda (zp),y
- *
- * provided that x and y are both zero.
- */
+**
+** lda (zp,x)
+**
+** into
+**
+** lda (zp),y
+**
+** provided that x and y are both zero.
+*/
unsigned OptBNegA1 (CodeSeg* S)
/* Check for
- *
- * ldx #$00
- * lda ..
- * jsr bnega
- *
- * Remove the ldx if the lda does not use it.
- */
+**
+** ldx #$00
+** lda ..
+** jsr bnega
+**
+** Remove the ldx if the lda does not use it.
+*/
{
unsigned Changes = 0;
unsigned OptBNegA2 (CodeSeg* S)
/* Check for
- *
- * lda ..
- * jsr bnega
- * jeq/jne ..
- *
- * Adjust the conditional branch and remove the call to the subroutine.
- */
+**
+** lda ..
+** jsr bnega
+** jeq/jne ..
+**
+** Adjust the conditional branch and remove the call to the subroutine.
+*/
{
unsigned Changes = 0;
unsigned OptBNegAX1 (CodeSeg* S)
/* On a call to bnegax, if X is zero, the result depends only on the value in
- * A, so change the call to a call to bnega. This will get further optimized
- * later if possible.
- */
+** A, so change the call to a call to bnega. This will get further optimized
+** later if possible.
+*/
{
unsigned Changes = 0;
unsigned I;
unsigned OptBNegAX2 (CodeSeg* S)
/* Search for the sequence:
- *
- * ldy #xx
- * jsr ldaxysp
- * jsr bnegax
- * jne/jeq ...
- *
- * and replace it by
- *
- * ldy #xx
- * lda (sp),y
- * dey
- * ora (sp),y
- * jeq/jne ...
- */
+**
+** ldy #xx
+** jsr ldaxysp
+** jsr bnegax
+** jne/jeq ...
+**
+** and replace it by
+**
+** ldy #xx
+** lda (sp),y
+** dey
+** ora (sp),y
+** jeq/jne ...
+*/
{
unsigned Changes = 0;
unsigned OptBNegAX3 (CodeSeg* S)
/* Search for the sequence:
- *
- * lda xx
- * ldx yy
- * jsr bnegax
- * jne/jeq ...
- *
- * and replace it by
- *
- * lda xx
- * ora xx+1
- * jeq/jne ...
- */
+**
+** lda xx
+** ldx yy
+** jsr bnegax
+** jne/jeq ...
+**
+** and replace it by
+**
+** lda xx
+** ora xx+1
+** jeq/jne ...
+*/
{
unsigned Changes = 0;
unsigned OptBNegAX4 (CodeSeg* S)
/* Search for the sequence:
- *
- * jsr xxx
- * jsr bnega(x)
- * jeq/jne ...
- *
- * and replace it by:
- *
- * jsr xxx
- * <boolean test>
- * jne/jeq ...
- */
+**
+** jsr xxx
+** jsr bnega(x)
+** jeq/jne ...
+**
+** and replace it by:
+**
+** jsr xxx
+** <boolean test>
+** jne/jeq ...
+*/
{
unsigned Changes = 0;
unsigned OptNegAX1 (CodeSeg* S)
/* Search for a call to negax and replace it by
- *
- * eor #$FF
- * clc
- * adc #$01
- *
- * if X isn't used later.
- */
+**
+** eor #$FF
+** clc
+** adc #$01
+**
+** if X isn't used later.
+*/
{
unsigned Changes = 0;
unsigned I;
unsigned OptNegAX2 (CodeSeg* S)
/* Search for a call to negax and replace it by
- *
- * ldx #$FF
- * eor #$FF
- * clc
- * adc #$01
- * bne L1
- * inx
- * L1:
- *
- * if X is known and zero on entry.
- */
+**
+** ldx #$FF
+** eor #$FF
+** clc
+** adc #$01
+** bne L1
+** inx
+** L1:
+**
+** if X is known and zero on entry.
+*/
{
unsigned Changes = 0;
unsigned I;
unsigned OptComplAX1 (CodeSeg* S)
/* Search for a call to complax and replace it by
- *
- * eor #$FF
- *
- * if X isn't used later.
- */
+**
+** eor #$FF
+**
+** if X isn't used later.
+*/
{
unsigned Changes = 0;
unsigned I;
unsigned OptBNegA1 (CodeSeg* S);
/* Check for
- *
- * ldx #$00
- * lda ..
- * jsr bnega
- *
- * Remove the ldx if the lda does not use it.
- */
+**
+** ldx #$00
+** lda ..
+** jsr bnega
+**
+** Remove the ldx if the lda does not use it.
+*/
unsigned OptBNegA2 (CodeSeg* S);
/* Check for
- *
- * lda ..
- * jsr bnega
- * jeq/jne ..
- *
- * Adjust the conditional branch and remove the call to the subroutine.
- */
+**
+** lda ..
+** jsr bnega
+** jeq/jne ..
+**
+** Adjust the conditional branch and remove the call to the subroutine.
+*/
unsigned OptBNegAX1 (CodeSeg* S);
/* On a call to bnegax, if X is zero, the result depends only on the value in
- * A, so change the call to a call to bnega. This will get further optimized
- * later if possible.
- */
+** A, so change the call to a call to bnega. This will get further optimized
+** later if possible.
+*/
unsigned OptBNegAX2 (CodeSeg* S);
/* Search for the sequence:
- *
- * lda (xx),y
- * tax
- * dey
- * lda (xx),y
- * jsr bnegax
- * jne/jeq ...
- *
- * and replace it by
- *
- * lda (xx),y
- * dey
- * ora (xx),y
- * jeq/jne ...
- */
+**
+** lda (xx),y
+** tax
+** dey
+** lda (xx),y
+** jsr bnegax
+** jne/jeq ...
+**
+** and replace it by
+**
+** lda (xx),y
+** dey
+** ora (xx),y
+** jeq/jne ...
+*/
unsigned OptBNegAX3 (CodeSeg* S);
/* Search for the sequence:
- *
- * lda xx
- * ldx yy
- * jsr bnegax
- * jne/jeq ...
- *
- * and replace it by
- *
- * lda xx
- * ora xx+1
- * jeq/jne ...
- */
+**
+** lda xx
+** ldx yy
+** jsr bnegax
+** jne/jeq ...
+**
+** and replace it by
+**
+** lda xx
+** ora xx+1
+** jeq/jne ...
+*/
unsigned OptBNegAX4 (CodeSeg* S);
/* Search for the sequence:
- *
- * jsr xxx
- * jsr bnega(x)
- * jeq/jne ...
- *
- * and replace it by:
- *
- * jsr xxx
- * <boolean test>
- * jne/jeq ...
- */
+**
+** jsr xxx
+** jsr bnega(x)
+** jeq/jne ...
+**
+** and replace it by:
+**
+** jsr xxx
+** <boolean test>
+** jne/jeq ...
+*/
unsigned OptNegAX1 (CodeSeg* S);
/* Search for a call to negax and replace it by
- *
- * eor #$FF
- * clc
- * adc #$01
- *
- * if X isn't used later.
- */
+**
+** eor #$FF
+** clc
+** adc #$01
+**
+** if X isn't used later.
+*/
unsigned OptNegAX2 (CodeSeg* S);
/* Search for a call to negax and replace it by
- *
- * ldx #$FF
- * eor #$FF
- * clc
- * adc #$01
- * bne L1
- * inx
- * L1:
- *
- * if X is known and zero on entry.
- */
+**
+** ldx #$FF
+** eor #$FF
+** clc
+** adc #$01
+** bne L1
+** inx
+** L1:
+**
+** if X is known and zero on entry.
+*/
unsigned OptComplAX1 (CodeSeg* S);
/* Search for a call to complax and replace it by
- *
- * eor #$FF
- *
- * if X isn't used later.
- */
+**
+** eor #$FF
+**
+** if X isn't used later.
+*/
unsigned OptPtrLoad1 (CodeSeg* S)
/* Search for the sequence:
- *
- * clc
- * adc xxx
- * tay
- * txa
- * adc yyy
- * tax
- * tya
- * ldy #$00
- * jsr ldauidx
- *
- * and replace it by:
- *
- * sta ptr1
- * txa
- * clc
- * adc yyy
- * sta ptr1+1
- * ldy xxx
- * ldx #$00
- * lda (ptr1),y
- */
+**
+** clc
+** adc xxx
+** tay
+** txa
+** adc yyy
+** tax
+** tya
+** ldy #$00
+** jsr ldauidx
+**
+** and replace it by:
+**
+** sta ptr1
+** txa
+** clc
+** adc yyy
+** sta ptr1+1
+** ldy xxx
+** ldx #$00
+** lda (ptr1),y
+*/
{
unsigned Changes = 0;
CS_InsertEntry (S, X, IP++);
/* If the instruction before the clc is a ldx, replace the
- * txa by an lda with the same location of the ldx. Otherwise
- * transfer the value in X to A.
- */
+ ** txa by an lda with the same location of the ldx. Otherwise
+ ** transfer the value in X to A.
+ */
if ((P = CS_GetPrevEntry (S, I)) != 0 &&
P->OPC == OP65_LDX &&
!CE_HasLabel (P)) {
unsigned OptPtrLoad2 (CodeSeg* S)
/* Search for the sequence:
- *
- * adc xxx
- * pha
- * txa
- * iny
- * adc yyy
- * tax
- * pla
- * ldy
- * jsr ldauidx
- *
- * and replace it by:
- *
- * adc xxx
- * sta ptr1
- * txa
- * iny
- * adc yyy
- * sta ptr1+1
- * ldy
- * ldx #$00
- * lda (ptr1),y
- */
+**
+** adc xxx
+** pha
+** txa
+** iny
+** adc yyy
+** tax
+** pla
+** ldy
+** jsr ldauidx
+**
+** and replace it by:
+**
+** adc xxx
+** sta ptr1
+** txa
+** iny
+** adc yyy
+** sta ptr1+1
+** ldy
+** ldx #$00
+** lda (ptr1),y
+*/
{
unsigned Changes = 0;
unsigned OptPtrLoad3 (CodeSeg* S)
/* Search for the sequence:
- *
- * lda #<(label+0)
- * ldx #>(label+0)
- * clc
- * adc xxx
- * bcc L
- * inx
- * L: ldy #$00
- * jsr ldauidx
- *
- * and replace it by:
- *
- * ldy xxx
- * ldx #$00
- * lda label,y
- */
+**
+** lda #<(label+0)
+** ldx #>(label+0)
+** clc
+** adc xxx
+** bcc L
+** inx
+** L: ldy #$00
+** jsr ldauidx
+**
+** and replace it by:
+**
+** ldy xxx
+** ldx #$00
+** lda label,y
+*/
{
unsigned Changes = 0;
char* Label;
/* We will create all the new stuff behind the current one so
- * we keep the line references.
- */
+ ** we keep the line references.
+ */
X = NewCodeEntry (OP65_LDY, L[3]->AM, L[3]->Arg, 0, L[0]->LI);
CS_InsertEntry (S, X, I+8);
unsigned OptPtrLoad4 (CodeSeg* S)
/* Search for the sequence:
- *
- * lda #<(label+0)
- * ldx #>(label+0)
- * ldy #$xx
- * clc
- * adc (sp),y
- * bcc L
- * inx
- * L: ldy #$00
- * jsr ldauidx
- *
- * and replace it by:
- *
- * ldy #$xx
- * lda (sp),y
- * tay
- * ldx #$00
- * lda label,y
- */
+**
+** lda #<(label+0)
+** ldx #>(label+0)
+** ldy #$xx
+** clc
+** adc (sp),y
+** bcc L
+** inx
+** L: ldy #$00
+** jsr ldauidx
+**
+** and replace it by:
+**
+** ldy #$xx
+** lda (sp),y
+** tay
+** ldx #$00
+** lda label,y
+*/
{
unsigned Changes = 0;
unsigned OptPtrLoad5 (CodeSeg* S)
/* Search for the sequence:
- *
- * jsr pushax
- * ldx #$00
- * lda yyy
- * jsr tosaddax
- * ldy #$00
- * jsr ldauidx
- *
- * and replace it by:
- *
- * sta ptr1
- * stx ptr1+1
- * ldy yyy
- * ldx #$00
- * lda (ptr1),y
- */
+**
+** jsr pushax
+** ldx #$00
+** lda yyy
+** jsr tosaddax
+** ldy #$00
+** jsr ldauidx
+**
+** and replace it by:
+**
+** sta ptr1
+** stx ptr1+1
+** ldy yyy
+** ldx #$00
+** lda (ptr1),y
+*/
{
unsigned Changes = 0;
unsigned OptPtrLoad6 (CodeSeg* S)
/* Search for the sequence:
- *
- * jsr pushax
- * ldy #xxx
- * ldx #$00
- * lda (sp),y
- * jsr tosaddax
- * ldy #$00
- * jsr ldauidx
- *
- * and replace it by:
- *
- * sta ptr1
- * stx ptr1+1
- * ldy #xxx-2
- * lda (sp),y
- * tay
- * ldx #$00
- * lda (ptr1),y
- */
+**
+** jsr pushax
+** ldy #xxx
+** ldx #$00
+** lda (sp),y
+** jsr tosaddax
+** ldy #$00
+** jsr ldauidx
+**
+** and replace it by:
+**
+** sta ptr1
+** stx ptr1+1
+** ldy #xxx-2
+** lda (sp),y
+** tay
+** ldx #$00
+** lda (ptr1),y
+*/
{
unsigned Changes = 0;
unsigned OptPtrLoad7 (CodeSeg* S)
/* Search for the sequence:
- *
- * jsr aslax1/shlax1
- * clc
- * adc xxx
- * tay
- * txa
- * adc yyy
- * tax
- * tya
- * ldy zzz
- * jsr ldaxidx
- *
- * and replace it by:
- *
- * stx tmp1
- * asl a
- * rol tmp1
- * clc
- * adc xxx
- * sta ptr1
- * lda tmp1
- * adc yyy
- * sta ptr1+1
- * ldy zzz
- * lda (ptr1),y
- * tax
- * dey
- * lda (ptr1),y
- */
+**
+** jsr aslax1/shlax1
+** clc
+** adc xxx
+** tay
+** txa
+** adc yyy
+** tax
+** tya
+** ldy zzz
+** jsr ldaxidx
+**
+** and replace it by:
+**
+** stx tmp1
+** asl a
+** rol tmp1
+** clc
+** adc xxx
+** sta ptr1
+** lda tmp1
+** adc yyy
+** sta ptr1+1
+** ldy zzz
+** lda (ptr1),y
+** tax
+** dey
+** lda (ptr1),y
+*/
{
unsigned Changes = 0;
unsigned I;
/* If X is zero on entry to aslax1, we can generate:
- *
- * asl a
- * bcc L1
- * inx
- * L1: clc
- *
- * instead of the code above. "lda tmp1" needs to be changed
- * to "txa" in this case.
- */
+ **
+ ** asl a
+ ** bcc L1
+ ** inx
+ ** L1: clc
+ **
+ ** instead of the code above. "lda tmp1" needs to be changed
+ ** to "txa" in this case.
+ */
int ShortCode = (L[0]->RI->In.RegX == 0);
if (ShortCode) {
unsigned OptPtrLoad11 (CodeSeg* S)
/* Search for the sequence:
- *
- * clc
- * adc xxx
- * bcc L
- * inx
- * L: ldy #$00
- * jsr ldauidx
- *
- * and replace it by:
- *
- * ldy xxx
- * sta ptr1
- * stx ptr1+1
- * ldx #$00
- * lda (ptr1),y
- */
+**
+** clc
+** adc xxx
+** bcc L
+** inx
+** L: ldy #$00
+** jsr ldauidx
+**
+** and replace it by:
+**
+** ldy xxx
+** sta ptr1
+** stx ptr1+1
+** ldx #$00
+** lda (ptr1),y
+*/
{
unsigned Changes = 0;
CodeEntry* X;
/* We will create all the new stuff behind the current one so
- * we keep the line references.
- */
+ ** we keep the line references.
+ */
X = NewCodeEntry (OP65_LDY, L[1]->AM, L[1]->Arg, 0, L[0]->LI);
CS_InsertEntry (S, X, I+6);
unsigned OptPtrLoad12 (CodeSeg* S)
/* Search for the sequence:
- *
- * lda regbank+n
- * ldx regbank+n+1
- * sta regsave
- * stx regsave+1
- * clc
- * adc #$01
- * bcc L0005
- * inx
- * L: sta regbank+n
- * stx regbank+n+1
- * lda regsave
- * ldx regsave+1
- * ldy #$00
- * jsr ldauidx
- *
- * and replace it by:
- *
- * ldy #$00
- * ldx #$00
- * lda (regbank+n),y
- * inc regbank+n
- * bne L1
- * inc regbank+n+1
- * L1: tay <- only if flags are used
- *
- * This function must execute before OptPtrLoad7!
- *
- */
+**
+** lda regbank+n
+** ldx regbank+n+1
+** sta regsave
+** stx regsave+1
+** clc
+** adc #$01
+** bcc L0005
+** inx
+** L: sta regbank+n
+** stx regbank+n+1
+** lda regsave
+** ldx regsave+1
+** ldy #$00
+** jsr ldauidx
+**
+** and replace it by:
+**
+** ldy #$00
+** ldx #$00
+** lda (regbank+n),y
+** inc regbank+n
+** bne L1
+** inc regbank+n+1
+** L1: tay <- only if flags are used
+**
+** This function must execute before OptPtrLoad7!
+**
+*/
{
unsigned Changes = 0;
CodeLabel* Label;
/* Check if the instruction following the sequence uses the flags
- * set by the load. If so, insert a test of the value in the
- * accumulator.
- */
+ ** set by the load. If so, insert a test of the value in the
+ ** accumulator.
+ */
if (CE_UseLoadFlags (L[14])) {
X = NewCodeEntry (OP65_TAY, AM65_IMP, 0, 0, L[13]->LI);
CS_InsertEntry (S, X, I+14);
}
/* Attach a label to L[14]. This may be either the just inserted
- * instruction, or the one following the sequence.
- */
+ ** instruction, or the one following the sequence.
+ */
Label = CS_GenLabel (S, L[14]);
/* ldy #$xx */
unsigned OptPtrLoad13 (CodeSeg* S)
/* Search for the sequence:
- *
- * lda zp
- * ldx zp+1
- * ldy xx
- * jsr ldauidx
- *
- * and replace it by:
- *
- * ldy xx
- * ldx #$00
- * lda (zp),y
- */
+**
+** lda zp
+** ldx zp+1
+** ldy xx
+** jsr ldauidx
+**
+** and replace it by:
+**
+** ldy xx
+** ldx #$00
+** lda (zp),y
+*/
{
unsigned Changes = 0;
unsigned OptPtrLoad14 (CodeSeg* S)
/* Search for the sequence:
- *
- * lda zp
- * ldx zp+1
- * (anything that doesn't change a/x)
- * ldy xx
- * jsr ldauidx
- *
- * and replace it by:
- *
- * lda zp
- * ldx zp+1
- * (anything that doesn't change a/x)
- * ldy xx
- * ldx #$00
- * lda (zp),y
- *
- */
+**
+** lda zp
+** ldx zp+1
+** (anything that doesn't change a/x)
+** ldy xx
+** jsr ldauidx
+**
+** and replace it by:
+**
+** lda zp
+** ldx zp+1
+** (anything that doesn't change a/x)
+** ldy xx
+** ldx #$00
+** lda (zp),y
+*/
{
unsigned Changes = 0;
unsigned I;
unsigned OptPtrLoad15 (CodeSeg* S)
/* Search for the sequence:
- *
- * lda zp
- * ldx zp+1
- * jsr pushax <- optional
- * ldy xx
- * jsr ldaxidx
- *
- * and replace it by:
- *
- * lda zp <- only if
- * ldx zp+1 <- call to
- * jsr pushax <- pushax present
- * ldy xx
- * lda (zp),y
- * tax
- * dey
- * lda (zp),y
- */
+**
+** lda zp
+** ldx zp+1
+** jsr pushax <- optional
+** ldy xx
+** jsr ldaxidx
+**
+** and replace it by:
+**
+** lda zp <- only if
+** ldx zp+1 <- call to
+** jsr pushax <- pushax present
+** ldy xx
+** lda (zp),y
+** tax
+** dey
+** lda (zp),y
+*/
{
unsigned Changes = 0;
unsigned OptPtrLoad16 (CodeSeg* S)
/* Search for the sequence
- *
- * ldy ...
- * jsr ldauidx
- *
- * and replace it by:
- *
- * stx ptr1+1
- * sta ptr1
- * ldy ...
- * ldx #$00
- * lda (ptr1),y
- *
- * This step must be executed *after* OptPtrLoad1!
- */
+**
+** ldy ...
+** jsr ldauidx
+**
+** and replace it by:
+**
+** stx ptr1+1
+** sta ptr1
+** ldy ...
+** ldx #$00
+** lda (ptr1),y
+**
+** This step must be executed *after* OptPtrLoad1!
+*/
{
unsigned Changes = 0;
unsigned OptPtrLoad17 (CodeSeg* S)
/* Search for the sequence
- *
- * ldy ...
- * jsr ldaxidx
- *
- * and replace it by:
- *
- * sta ptr1
- * stx ptr1+1
- * ldy ...
- * lda (ptr1),y
- * tax
- * dey
- * lda (ptr1),y
- *
- * This step must be executed *after* OptPtrLoad9! While code size increases
- * by more than 200%, inlining will greatly improve visibility for the
- * optimizer, so often part of the code gets improved later. So we will mark
- * the step with less than 200% so it gets executed when -Oi is in effect.
- */
+**
+** ldy ...
+** jsr ldaxidx
+**
+** and replace it by:
+**
+** sta ptr1
+** stx ptr1+1
+** ldy ...
+** lda (ptr1),y
+** tax
+** dey
+** lda (ptr1),y
+**
+** This step must be executed *after* OptPtrLoad9! While code size increases
+** by more than 200%, inlining will greatly improve visibility for the
+** optimizer, so often part of the code gets improved later. So we will mark
+** the step with less than 200% so it gets executed when -Oi is in effect.
+*/
{
unsigned Changes = 0;
unsigned OptPtrLoad1 (CodeSeg* S);
/* Search for the sequence:
- *
- * clc
- * adc xxx
- * tay
- * txa
- * adc yyy
- * tax
- * tya
- * ldy
- * jsr ldauidx
- *
- * and replace it by:
- *
- * clc
- * adc xxx
- * sta ptr1
- * txa
- * adc yyy
- * sta ptr1+1
- * ldy
- * ldx #$00
- * lda (ptr1),y
- */
+**
+** clc
+** adc xxx
+** tay
+** txa
+** adc yyy
+** tax
+** tya
+** ldy
+** jsr ldauidx
+**
+** and replace it by:
+**
+** clc
+** adc xxx
+** sta ptr1
+** txa
+** adc yyy
+** sta ptr1+1
+** ldy
+** ldx #$00
+** lda (ptr1),y
+*/
unsigned OptPtrLoad2 (CodeSeg* S);
/* Search for the sequence:
- *
- * adc xxx
- * pha
- * txa
- * iny
- * adc yyy
- * tax
- * pla
- * ldy
- * jsr ldauidx
- *
- * and replace it by:
- *
- * adc xxx
- * sta ptr1
- * txa
- * iny
- * adc yyy
- * sta ptr1+1
- * ldy
- * ldx #$00
- * lda (ptr1),y
- */
+**
+** adc xxx
+** pha
+** txa
+** iny
+** adc yyy
+** tax
+** pla
+** ldy
+** jsr ldauidx
+**
+** and replace it by:
+**
+** adc xxx
+** sta ptr1
+** txa
+** iny
+** adc yyy
+** sta ptr1+1
+** ldy
+** ldx #$00
+** lda (ptr1),y
+*/
unsigned OptPtrLoad3 (CodeSeg* S);
/* Search for the sequence:
- *
- * lda #<(label+0)
- * ldx #>(label+0)
- * clc
- * adc xxx
- * bcc L
- * inx
- * L: ldy #$00
- * jsr ldauidx
- *
- * and replace it by:
- *
- * ldy xxx
- * ldx #$00
- * lda label,y
- */
+**
+** lda #<(label+0)
+** ldx #>(label+0)
+** clc
+** adc xxx
+** bcc L
+** inx
+** L: ldy #$00
+** jsr ldauidx
+**
+** and replace it by:
+**
+** ldy xxx
+** ldx #$00
+** lda label,y
+*/
unsigned OptPtrLoad4 (CodeSeg* S);
/* Search for the sequence:
- *
- * lda #<(label+0)
- * ldx #>(label+0)
- * ldy #$xx
- * clc
- * adc (sp),y
- * bcc L
- * inx
- * L: ldy #$00
- * jsr ldauidx
- *
- * and replace it by:
- *
- * ldy #$xx
- * lda (sp),y
- * tay
- * ldx #$00
- * lda label,y
- */
+**
+** lda #<(label+0)
+** ldx #>(label+0)
+** ldy #$xx
+** clc
+** adc (sp),y
+** bcc L
+** inx
+** L: ldy #$00
+** jsr ldauidx
+**
+** and replace it by:
+**
+** ldy #$xx
+** lda (sp),y
+** tay
+** ldx #$00
+** lda label,y
+*/
unsigned OptPtrLoad5 (CodeSeg* S);
/* Search for the sequence:
- *
- * jsr pushax
- * ldx #$00
- * lda yyy
- * jsr tosaddax
- * ldy #$00
- * jsr ldauidx
- *
- * and replace it by:
- *
- * sta ptr1
- * stx ptr1+1
- * ldy yyy
- * lda (ptr1),y
- */
+**
+** jsr pushax
+** ldx #$00
+** lda yyy
+** jsr tosaddax
+** ldy #$00
+** jsr ldauidx
+**
+** and replace it by:
+**
+** sta ptr1
+** stx ptr1+1
+** ldy yyy
+** lda (ptr1),y
+*/
unsigned OptPtrLoad6 (CodeSeg* S);
/* Search for the sequence:
- *
- * jsr pushax
- * ldy xxx
- * ldx #$00
- * lda (sp),y
- * jsr tosaddax
- * ldy #$00
- * jsr ldauidx
- *
- * and replace it by:
- *
- * sta ptr1
- * stx ptr1+1
- * ldy xxx
- * lda (sp),y
- * tay
- * lda (ptr1),y
- */
+**
+** jsr pushax
+** ldy xxx
+** ldx #$00
+** lda (sp),y
+** jsr tosaddax
+** ldy #$00
+** jsr ldauidx
+**
+** and replace it by:
+**
+** sta ptr1
+** stx ptr1+1
+** ldy xxx
+** lda (sp),y
+** tay
+** lda (ptr1),y
+*/
unsigned OptPtrLoad7 (CodeSeg* S);
/* Search for the sequence:
- *
- * jsr aslax1/shlax1
- * clc
- * adc xxx
- * tay
- * txa
- * adc yyy
- * tax
- * tya
- * ldy zzz
- * jsr ldaxidx
- *
- * and replace it by:
- *
- * stx tmp1
- * asl a
- * rol tmp1
- * clc
- * adc xxx
- * sta ptr1
- * lda tmp1
- * adc yyy
- * sta ptr1+1
- * ldy zzz
- * lda (ptr1),y
- * tax
- * dey
- * lda (ptr1),y
- */
+**
+** jsr aslax1/shlax1
+** clc
+** adc xxx
+** tay
+** txa
+** adc yyy
+** tax
+** tya
+** ldy zzz
+** jsr ldaxidx
+**
+** and replace it by:
+**
+** stx tmp1
+** asl a
+** rol tmp1
+** clc
+** adc xxx
+** sta ptr1
+** lda tmp1
+** adc yyy
+** sta ptr1+1
+** ldy zzz
+** lda (ptr1),y
+** tax
+** dey
+** lda (ptr1),y
+*/
unsigned OptPtrLoad11 (CodeSeg* S);
/* Search for the sequence:
- *
- * clc
- * adc xxx
- * bcc L
- * inx
- * L: ldy #$00
- * jsr ldauidx
- *
- * and replace it by:
- *
- * ldy xxx
- * sta ptr1
- * stx ptr1+1
- * ldx #$00
- * lda (ptr1),y
- */
+**
+** clc
+** adc xxx
+** bcc L
+** inx
+** L: ldy #$00
+** jsr ldauidx
+**
+** and replace it by:
+**
+** ldy xxx
+** sta ptr1
+** stx ptr1+1
+** ldx #$00
+** lda (ptr1),y
+*/
unsigned OptPtrLoad12 (CodeSeg* S);
/* Search for the sequence:
- *
- * lda regbank+n
- * ldx regbank+n+1
- * sta regsave
- * stx regsave+1
- * clc
- * adc #$01
- * bcc L0005
- * inx
- * L: sta regbank+n
- * stx regbank+n+1
- * lda regsave
- * ldx regsave+1
- * ldy #$00
- * jsr ldauidx
- *
- * and replace it by:
- *
- * ldy #$00
- * ldx #$00
- * lda (regbank+n),y
- * inc regbank+n
- * bne L1
- * inc regbank+n+1
- * L1: tay <- only if flags are used
- *
- * This function must execute before OptPtrLoad7!
- *
- */
+**
+** lda regbank+n
+** ldx regbank+n+1
+** sta regsave
+** stx regsave+1
+** clc
+** adc #$01
+** bcc L0005
+** inx
+** L: sta regbank+n
+** stx regbank+n+1
+** lda regsave
+** ldx regsave+1
+** ldy #$00
+** jsr ldauidx
+**
+** and replace it by:
+**
+** ldy #$00
+** ldx #$00
+** lda (regbank+n),y
+** inc regbank+n
+** bne L1
+** inc regbank+n+1
+** L1: tay <- only if flags are used
+**
+** This function must execute before OptPtrLoad7!
+**
+*/
unsigned OptPtrLoad13 (CodeSeg* S);
/* Search for the sequence:
- *
- * lda zp
- * ldx zp+1
- * ldy xx
- * jsr ldauidx
- *
- * and replace it by:
- *
- * ldy xx
- * ldx #$00
- * lda (zp),y
- */
+**
+** lda zp
+** ldx zp+1
+** ldy xx
+** jsr ldauidx
+**
+** and replace it by:
+**
+** ldy xx
+** ldx #$00
+** lda (zp),y
+*/
unsigned OptPtrLoad14 (CodeSeg* S);
/* Search for the sequence:
- *
- * lda zp
- * ldx zp+1
- * (anything that doesn't change a/x)
- * ldy xx
- * jsr ldauidx
- *
- * and replace it by:
- *
- * lda zp
- * ldx zp+1
- * (anything that doesn't change a/x)
- * ldy xx
- * ldx #$00
- * lda (zp),y
- *
- * Must execute before OptPtrLoad10!
- */
+**
+** lda zp
+** ldx zp+1
+** (anything that doesn't change a/x)
+** ldy xx
+** jsr ldauidx
+**
+** and replace it by:
+**
+** lda zp
+** ldx zp+1
+** (anything that doesn't change a/x)
+** ldy xx
+** ldx #$00
+** lda (zp),y
+**
+** Must execute before OptPtrLoad10!
+*/
unsigned OptPtrLoad15 (CodeSeg* S);
/* Search for the sequence:
- *
- * lda zp
- * ldx zp+1
- * ldy xx
- * jsr ldaxidx
- *
- * and replace it by:
- *
- * ldy xx
- * lda (zp),y
- * tax
- * dey
- * lda (zp),y
- */
+**
+** lda zp
+** ldx zp+1
+** ldy xx
+** jsr ldaxidx
+**
+** and replace it by:
+**
+** ldy xx
+** lda (zp),y
+** tax
+** dey
+** lda (zp),y
+*/
unsigned OptPtrLoad16 (CodeSeg* S);
/* Search for the sequence
- *
- * ldy ...
- * jsr ldauidx
- *
- * and replace it by:
- *
- * ldy ...
- * stx ptr1+1
- * sta ptr1
- * ldx #$00
- * lda (ptr1),y
- *
- * This step must be executed *after* OptPtrLoad1!
- */
+**
+** ldy ...
+** jsr ldauidx
+**
+** and replace it by:
+**
+** ldy ...
+** stx ptr1+1
+** sta ptr1
+** ldx #$00
+** lda (ptr1),y
+**
+** This step must be executed *after* OptPtrLoad1!
+*/
unsigned OptPtrLoad17 (CodeSeg* S);
/* Search for the sequence
- *
- * ldy ...
- * jsr ldaxidx
- *
- * and replace it by:
- *
- * ldy ...
- * sta ptr1
- * stx ptr1+1
- * lda (ptr1),y
- * tax
- * dey
- * lda (ptr1),y
- *
- * This step must be executed *after* OptPtrLoad9! While code size increases
- * by more than 200%, inlining will greatly improve visibility for the
- * optimizer, so often part of the code gets improved later. So we will mark
- * the step with less than 200% so it gets executed when -Oi is in effect.
- */
+**
+** ldy ...
+** jsr ldaxidx
+**
+** and replace it by:
+**
+** ldy ...
+** sta ptr1
+** stx ptr1+1
+** lda (ptr1),y
+** tax
+** dey
+** lda (ptr1),y
+**
+** This step must be executed *after* OptPtrLoad9! While code size increases
+** by more than 200%, inlining will greatly improve visibility for the
+** optimizer, so often part of the code gets improved later. So we will mark
+** the step with less than 200% so it gets executed when -Oi is in effect.
+*/
static const char* LoadAXZP (CodeSeg* S, unsigned I)
/* If the two instructions preceeding S/I are a load of A/X from a two byte
- * zero byte location, return the name of the zero page location. Otherwise
- * return NULL.
- */
+** zero byte location, return the name of the zero page location. Otherwise
+** return NULL.
+*/
{
CodeEntry* L[2];
unsigned Len;
static const char* LoadAXImm (CodeSeg* S, unsigned I)
/* If the instructions preceeding S/I are a load of A/X of a constant value
- * or a word sized address label, return the address of the location as a
- * string.
- * Beware: In case of a numeric value, the result is returned in static
- * storage which is overwritten with each call.
- */
+** or a word sized address label, return the address of the location as a
+** string.
+** Beware: In case of a numeric value, the result is returned in static
+** storage which is overwritten with each call.
+*/
{
static StrBuf Buf = STATIC_STRBUF_INITIALIZER;
CodeEntry* L[2];
}
/* Search back for the two instructions loading A and X. Abort
- * the search if the registers are changed in any other way or
- * if a label is reached while we don't have both loads.
- */
+ ** the search if the registers are changed in any other way or
+ ** if a label is reached while we don't have both loads.
+ */
ALoad = 0;
XLoad = 0;
while (I-- > 0) {
unsigned OptPtrStore1 (CodeSeg* S)
/* Search for the sequence:
- *
- * clc
- * adc xxx
- * bcc L
- * inx
- * L: jsr pushax
- * ldx #$00
- * lda yyy
- * ldy #$00
- * jsr staspidx
- *
- * and replace it by:
- *
- * sta ptr1
- * stx ptr1+1
- * ldy xxx
- * ldx #$00
- * lda yyy
- * sta (ptr1),y
- *
- * or by
- *
- * ldy xxx
- * ldx #$00
- * lda yyy
- * sta (zp),y
- *
- * or by
- *
- * ldy xxx
- * ldx #$00
- * lda yyy
- * sta label,y
- *
- * or by
- *
- * ldy xxx
- * ldx #$00
- * lda yyy
- * sta $xxxx,y
- *
- * depending on the code preceeding the sequence above.
- */
+**
+** clc
+** adc xxx
+** bcc L
+** inx
+** L: jsr pushax
+** ldx #$00
+** lda yyy
+** ldy #$00
+** jsr staspidx
+**
+** and replace it by:
+**
+** sta ptr1
+** stx ptr1+1
+** ldy xxx
+** ldx #$00
+** lda yyy
+** sta (ptr1),y
+**
+** or by
+**
+** ldy xxx
+** ldx #$00
+** lda yyy
+** sta (zp),y
+**
+** or by
+**
+** ldy xxx
+** ldx #$00
+** lda yyy
+** sta label,y
+**
+** or by
+**
+** ldy xxx
+** ldx #$00
+** lda yyy
+** sta $xxxx,y
+**
+** depending on the code preceeding the sequence above.
+*/
{
unsigned Changes = 0;
unsigned I;
unsigned IP = I + 9;
if ((Loc = LoadAXZP (S, I)) != 0) {
/* If the sequence is preceeded by a load of a ZP value,
- * we can use this ZP value as a pointer using ZP
- * indirect Y addressing.
- */
+ ** we can use this ZP value as a pointer using ZP
+ ** indirect Y addressing.
+ */
AM = AM65_ZP_INDY;
} else if ((Loc = LoadAXImm (S, I)) != 0) {
/* If the sequence is preceeded by a load of an immediate
- * value, we can use this absolute value as an address
- * using absolute indexed Y addressing.
- */
+ ** value, we can use this absolute value as an address
+ ** using absolute indexed Y addressing.
+ */
AM = AM65_ABSY;
}
/* If we don't have a store location, we use ptr1 with zp
- * indirect Y addressing. We must store the value in A/X into
- * ptr1 in this case.
- */
+ ** indirect Y addressing. We must store the value in A/X into
+ ** ptr1 in this case.
+ */
if (Loc == 0) {
/* Must use ptr1 */
}
/* If the index is loaded from (zp),y, we cannot do that directly.
- * Note: In this case, the Y register will contain the correct
- * value after removing the old code, so we don't need to load
- * it here.
- */
+ ** Note: In this case, the Y register will contain the correct
+ ** value after removing the old code, so we don't need to load
+ ** it here.
+ */
if (L[1]->AM == AM65_ZP_INDY) {
X = NewCodeEntry (OP65_LDA, L[1]->AM, L[1]->Arg, 0, L[1]->LI);
CS_InsertEntry (S, X, IP++);
unsigned OptPtrStore2 (CodeSeg* S)
/* Search for the sequence:
- *
- * clc
- * adc xxx
- * bcc L
- * inx
- * L: jsr pushax
- * ldy yyy
- * ldx #$00
- * lda (sp),y
- * ldy #$00
- * jsr staspidx
- *
- * and replace it by:
- *
- * sta ptr1
- * stx ptr1+1
- * ldy yyy-2
- * ldx #$00
- * lda (sp),y
- * ldy xxx
- * sta (ptr1),y
- *
- * or by
- *
- * ldy yyy-2
- * ldx #$00
- * lda (sp),y
- * ldy xxx
- * sta (zp),y
- *
- * or by
- *
- * ldy yyy-2
- * ldx #$00
- * lda (sp),y
- * ldy xxx
- * sta label,y
- *
- * or by
- *
- * ldy yyy-2
- * ldx #$00
- * lda (sp),y
- * ldy xxx
- * sta $xxxx,y
- *
- * depending on the code preceeding the sequence above.
- */
+**
+** clc
+** adc xxx
+** bcc L
+** inx
+** L: jsr pushax
+** ldy yyy
+** ldx #$00
+** lda (sp),y
+** ldy #$00
+** jsr staspidx
+**
+** and replace it by:
+**
+** sta ptr1
+** stx ptr1+1
+** ldy yyy-2
+** ldx #$00
+** lda (sp),y
+** ldy xxx
+** sta (ptr1),y
+**
+** or by
+**
+** ldy yyy-2
+** ldx #$00
+** lda (sp),y
+** ldy xxx
+** sta (zp),y
+**
+** or by
+**
+** ldy yyy-2
+** ldx #$00
+** lda (sp),y
+** ldy xxx
+** sta label,y
+**
+** or by
+**
+** ldy yyy-2
+** ldx #$00
+** lda (sp),y
+** ldy xxx
+** sta $xxxx,y
+**
+** depending on the code preceeding the sequence above.
+*/
{
unsigned Changes = 0;
unsigned I;
unsigned IP = I + 10;
if ((Loc = LoadAXZP (S, I)) != 0) {
/* If the sequence is preceeded by a load of a ZP value,
- * we can use this ZP value as a pointer using ZP
- * indirect Y addressing.
- */
+ ** we can use this ZP value as a pointer using ZP
+ ** indirect Y addressing.
+ */
AM = AM65_ZP_INDY;
} else if ((Loc = LoadAXImm (S, I)) != 0) {
/* If the sequence is preceeded by a load of an immediate
- * value, we can use this absolute value as an address
- * using absolute indexed Y addressing.
- */
+ ** value, we can use this absolute value as an address
+ ** using absolute indexed Y addressing.
+ */
AM = AM65_ABSY;
}
/* If we don't have a store location, we use ptr1 with zp
- * indirect Y addressing. We must store the value in A/X into
- * ptr1 in this case.
- */
+ ** indirect Y addressing. We must store the value in A/X into
+ ** ptr1 in this case.
+ */
if (Loc == 0) {
/* Must use ptr1 */
}
/* Generate four different replacements depending on the addressing
- * mode of the store and from where the index is loaded:
- *
- * 1. If the index is not loaded ZP indirect Y, we can use Y for
- * the store index.
- *
- * 2. If the index is loaded ZP indirect Y and we store absolute
- * indexed, we need Y to load the index and will therefore
- * use X as index for the store. The disadvantage is that we
- * need to reload X later.
- *
- * 3. If the index is loaded ZP indirect Y and we store ZP indirect
- * Y, we must use Y for load and store and must therefore save
- * the A register when loading Y the second time.
- */
+ ** mode of the store and from where the index is loaded:
+ **
+ ** 1. If the index is not loaded ZP indirect Y, we can use Y for
+ ** the store index.
+ **
+ ** 2. If the index is loaded ZP indirect Y and we store absolute
+ ** indexed, we need Y to load the index and will therefore
+ ** use X as index for the store. The disadvantage is that we
+ ** need to reload X later.
+ **
+ ** 3. If the index is loaded ZP indirect Y and we store ZP indirect
+ ** Y, we must use Y for load and store and must therefore save
+ ** the A register when loading Y the second time.
+ */
if (L[1]->AM != AM65_ZP_INDY) {
/* Case 1 */
unsigned OptPtrStore3 (CodeSeg* S)
/* Search for the sequence:
- *
- * jsr pushax
- * ldy xxx
- * jsr ldauidx
- * subop
- * ldy yyy
- * jsr staspidx
- *
- * and replace it by:
- *
- * sta ptr1
- * stx ptr1+1
- * ldy xxx
- * ldx #$00
- * lda (ptr1),y
- * subop
- * ldy yyy
- * sta (ptr1),y
- *
- * In case a/x is loaded from the register bank before the pushax, we can even
- * use the register bank instead of ptr1.
- *
- */
+**
+** jsr pushax
+** ldy xxx
+** jsr ldauidx
+** subop
+** ldy yyy
+** jsr staspidx
+**
+** and replace it by:
+**
+** sta ptr1
+** stx ptr1+1
+** ldy xxx
+** ldx #$00
+** lda (ptr1),y
+** subop
+** ldy yyy
+** sta (ptr1),y
+**
+** In case a/x is loaded from the register bank before the pushax, we can even
+** use the register bank instead of ptr1.
+*/
{
unsigned Changes = 0;
/* Get the preceeding two instructions and check them. We check
- * for:
- * lda regbank+n
- * ldx regbank+n+1
- */
+ ** for:
+ ** lda regbank+n
+ ** ldx regbank+n+1
+ */
if (I > 1) {
CodeEntry* P[2];
P[0] = CS_GetEntry (S, I-2);
}
/* Delete more old code. Do it here to keep a label attached to
- * entry I in place.
- */
+ ** entry I in place.
+ */
CS_DelEntry (S, I); /* jsr pushax */
/* Remember, we had changes */
unsigned OptPtrStore1 (CodeSeg* S);
/* Search for the sequence:
- *
- * clc
- * adc xxx
- * bcc L
- * inx
- * L: jsr pushax
- * ldx #$00
- * lda yyy
- * ldy #$00
- * jsr staspidx
- *
- * and replace it by:
- *
- * sta ptr1
- * stx ptr1+1
- * ldy xxx
- * ldx #$00
- * lda yyy
- * sta (ptr1),y
- *
- * or by
- *
- * ldy xxx
- * ldx #$00
- * lda yyy
- * sta (zp),y
- *
- * or by
- *
- * ldy xxx
- * ldx #$00
- * lda yyy
- * sta label,y
- *
- * or by
- *
- * ldy xxx
- * ldx #$00
- * lda yyy
- * sta $xxxx,y
- *
- * depending on the two instructions preceeding the sequence above.
- */
+**
+** clc
+** adc xxx
+** bcc L
+** inx
+** L: jsr pushax
+** ldx #$00
+** lda yyy
+** ldy #$00
+** jsr staspidx
+**
+** and replace it by:
+**
+** sta ptr1
+** stx ptr1+1
+** ldy xxx
+** ldx #$00
+** lda yyy
+** sta (ptr1),y
+**
+** or by
+**
+** ldy xxx
+** ldx #$00
+** lda yyy
+** sta (zp),y
+**
+** or by
+**
+** ldy xxx
+** ldx #$00
+** lda yyy
+** sta label,y
+**
+** or by
+**
+** ldy xxx
+** ldx #$00
+** lda yyy
+** sta $xxxx,y
+**
+** depending on the two instructions preceeding the sequence above.
+*/
unsigned OptPtrStore2 (CodeSeg* S);
/* Search for the sequence:
- *
- * clc
- * adc xxx
- * bcc L
- * inx
- * L: jsr pushax
- * ldy yyy
- * ldx #$00
- * lda (sp),y
- * ldy #$00
- * jsr staspidx
- *
- * and replace it by:
- *
- * sta ptr1
- * stx ptr1+1
- * ldy yyy-2
- * ldx #$00
- * lda (sp),y
- * ldy xxx
- * sta (ptr1),y
- *
- * or by
- *
- * ldy yyy-2
- * ldx #$00
- * lda (sp),y
- * ldy xxx
- * sta (zp),y
- *
- * or by
- *
- * ldy yyy-2
- * ldx #$00
- * lda (sp),y
- * ldy xxx
- * sta label,y
- *
- * or by
- *
- * ldy yyy-2
- * ldx #$00
- * lda (sp),y
- * ldy xxx
- * sta $xxxx,y
- *
- * depending on the code preceeding the sequence above.
- */
+**
+** clc
+** adc xxx
+** bcc L
+** inx
+** L: jsr pushax
+** ldy yyy
+** ldx #$00
+** lda (sp),y
+** ldy #$00
+** jsr staspidx
+**
+** and replace it by:
+**
+** sta ptr1
+** stx ptr1+1
+** ldy yyy-2
+** ldx #$00
+** lda (sp),y
+** ldy xxx
+** sta (ptr1),y
+**
+** or by
+**
+** ldy yyy-2
+** ldx #$00
+** lda (sp),y
+** ldy xxx
+** sta (zp),y
+**
+** or by
+**
+** ldy yyy-2
+** ldx #$00
+** lda (sp),y
+** ldy xxx
+** sta label,y
+**
+** or by
+**
+** ldy yyy-2
+** ldx #$00
+** lda (sp),y
+** ldy xxx
+** sta $xxxx,y
+**
+** depending on the code preceeding the sequence above.
+*/
unsigned OptPtrStore3 (CodeSeg* S);
/* Search for the sequence:
- *
- * jsr pushax
- * ldy xxx
- * jsr ldauidx
- * subop
- * ldy yyy
- * jsr staspidx
- *
- * and replace it by:
- *
- * sta ptr1
- * stx ptr1+1
- * ldy xxx
- * ldx #$00
- * lda (ptr1),y
- * subop
- * ldy yyy
- * sta (ptr1),y
- *
- * In case a/x is loaded from the register bank before the pushax, we can even
- * use the register bank instead of ptr1.
- *
- */
+**
+** jsr pushax
+** ldy xxx
+** jsr ldauidx
+** subop
+** ldy yyy
+** jsr staspidx
+**
+** and replace it by:
+**
+** sta ptr1
+** stx ptr1+1
+** ldy xxx
+** ldx #$00
+** lda (ptr1),y
+** subop
+** ldy yyy
+** sta (ptr1),y
+**
+** In case a/x is loaded from the register bank before the pushax, we can even
+** use the register bank instead of ptr1.
+*/
unsigned OptPush1 (CodeSeg* S)
/* Given a sequence
- *
- * jsr ldaxysp
- * jsr pushax
- *
- * If a/x are not used later, and Y is known, replace that by
- *
- * ldy #xx+2
- * jsr pushwysp
- *
- * saving 3 bytes and several cycles.
- */
+**
+** jsr ldaxysp
+** jsr pushax
+**
+** If a/x are not used later, and Y is known, replace that by
+**
+** ldy #xx+2
+** jsr pushwysp
+**
+** saving 3 bytes and several cycles.
+*/
{
unsigned I;
unsigned Changes = 0;
unsigned OptPush2 (CodeSeg* S)
/* A sequence
- *
- * jsr ldaxidx
- * jsr pushax
- *
- * may get replaced by
- *
- * jsr pushwidx
- *
- */
+**
+** jsr ldaxidx
+** jsr pushax
+**
+** may get replaced by
+**
+** jsr pushwidx
+*/
{
unsigned I;
unsigned Changes = 0;
unsigned OptPush1 (CodeSeg* S);
/* Given a sequence
- *
- * ldy #xx
- * jsr ldaxysp
- * jsr pushax
- *
- * If a/x are not used later, replace that by
- *
- * ldy #xx+2
- * jsr pushwysp
- *
- * saving 3 bytes and several cycles.
- */
+**
+** ldy #xx
+** jsr ldaxysp
+** jsr pushax
+**
+** If a/x are not used later, replace that by
+**
+** ldy #xx+2
+** jsr pushwysp
+**
+** saving 3 bytes and several cycles.
+*/
unsigned OptPush2 (CodeSeg* S);
/* A sequence
- *
- * jsr ldaxidx
- * jsr pushax
- *
- * may get replaced by
- *
- * jsr pushwidx
- *
- */
+**
+** jsr ldaxidx
+** jsr pushax
+**
+** may get replaced by
+**
+** jsr pushwidx
+*/
unsigned OptShift1 (CodeSeg* S)
/* A call to the shlaxN routine may get replaced by one or more asl insns
- * if the value of X is not used later. If X is used later, but it is zero
- * on entry and it's a shift by one, it may get replaced by:
- *
- * asl a
- * bcc L1
- * inx
- * L1:
- *
- */
+** if the value of X is not used later. If X is used later, but it is zero
+** on entry and it's a shift by one, it may get replaced by:
+**
+** asl a
+** bcc L1
+** inx
+** L1:
+*/
{
unsigned Changes = 0;
unsigned I;
}
/* Change into
- *
- * L1: asl a
- * dey
- * bpl L1
- * ror a
- */
+ **
+ ** L1: asl a
+ ** dey
+ ** bpl L1
+ ** ror a
+ */
/* asl a */
X = NewCodeEntry (OP65_ASL, AM65_ACC, "a", 0, E->LI);
unsigned OptShift2(CodeSeg* S)
/* A call to the asrax1 routines may get replaced by something simpler, if
- * X is not used later:
- *
- * cmp #$80
- * ror a
- *
- */
+** X is not used later:
+**
+** cmp #$80
+** ror a
+*/
{
unsigned Changes = 0;
unsigned I;
unsigned OptShift3 (CodeSeg* S)
/* The sequence
- *
- * bcc L
- * inx
- * L: jsr shrax1
- *
- * may get replaced by
- *
- * ror a
- *
- * if X is zero on entry. For shift counts > 1, more
- *
- * shr a
- *
- * must be added.
- */
+**
+** bcc L
+** inx
+** L: jsr shrax1
+**
+** may get replaced by
+**
+** ror a
+**
+** if X is zero on entry. For shift counts > 1, more
+**
+** shr a
+**
+** must be added.
+*/
{
unsigned Changes = 0;
unsigned I;
unsigned OptShift4 (CodeSeg* S)
/* Calls to the asraxN or shraxN routines may get replaced by one or more lsr
- * insns if the value of X is zero.
- */
+** insns if the value of X is zero.
+*/
{
unsigned Changes = 0;
unsigned I;
}
/* Generate:
- *
- * L1: lsr a
- * dey
- * bpl L1
- * rol a
- *
- * A negative shift count or one that is greater or equal than
- * the bit width of the left operand (which is promoted to
- * integer before the operation) causes undefined behaviour, so
- * above transformation is safe.
- */
+ **
+ ** L1: lsr a
+ ** dey
+ ** bpl L1
+ ** rol a
+ **
+ ** A negative shift count or one that is greater or equal than
+ ** the bit width of the left operand (which is promoted to
+ ** integer before the operation) causes undefined behaviour, so
+ ** above transformation is safe.
+ */
/* lsr a */
X = NewCodeEntry (OP65_LSR, AM65_ACC, "a", 0, E->LI);
unsigned OptShift5 (CodeSeg* S)
/* Search for the sequence
- *
- * lda xxx
- * ldx yyy
- * jsr aslax1/asrax1/shlax1/shrax1
- * sta aaa
- * stx bbb
- *
- * and replace it by
- *
- * lda xxx
- * asl a
- * sta aaa
- * lda yyy
- * rol a
- * sta bbb
- *
- * or similar, provided that a/x is not used later
- */
+**
+** lda xxx
+** ldx yyy
+** jsr aslax1/asrax1/shlax1/shrax1
+** sta aaa
+** stx bbb
+**
+** and replace it by
+**
+** lda xxx
+** asl a
+** sta aaa
+** lda yyy
+** rol a
+** sta bbb
+**
+** or similar, provided that a/x is not used later
+*/
{
unsigned Changes = 0;
(Count = SHIFT_COUNT (Shift)) > 0) {
/* Code is:
- *
- * stx tmp1
- * asl a
- * rol tmp1
- * (repeat ShiftCount-1 times)
- * ldx tmp1
- *
- * which makes 4 + 3 * ShiftCount bytes, compared to the original
- * 3 bytes for the subroutine call. However, in most cases, the
- * final load of the X register gets merged with some other insn
- * and replaces a txa, so for a shift count of 1, we get a factor
- * of 200, which matches nicely the CodeSizeFactor enabled with -Oi
- */
+ **
+ ** stx tmp1
+ ** asl a
+ ** rol tmp1
+ ** (repeat ShiftCount-1 times)
+ ** ldx tmp1
+ **
+ ** which makes 4 + 3 * ShiftCount bytes, compared to the original
+ ** 3 bytes for the subroutine call. However, in most cases, the
+ ** final load of the X register gets merged with some other insn
+ ** and replaces a txa, so for a shift count of 1, we get a factor
+ ** of 200, which matches nicely the CodeSizeFactor enabled with -Oi
+ */
if (Count > 1 || S->CodeSizeFactor > 200) {
unsigned Size = 4 + 3 * Count;
if ((Size * 100 / 3) > S->CodeSizeFactor) {
unsigned OptShift1 (CodeSeg* S);
/* A call to the shlaxN routine may get replaced by one or more asl insns
- * if the value of X is not used later. If X is used later, but it is zero
- * on entry and it's a shift by one, it may get replaced by:
- *
- * asl a
- * bcc L1
- * inx
- * L1:
- *
- */
+** if the value of X is not used later. If X is used later, but it is zero
+** on entry and it's a shift by one, it may get replaced by:
+**
+** asl a
+** bcc L1
+** inx
+** L1:
+*/
unsigned OptShift2(CodeSeg* S);
/* A call to the asrax1 routines may get replaced by something simpler, if
- * X is not used later:
- *
- * cmp #$80
- * ror a
- *
- */
+** X is not used later:
+**
+** cmp #$80
+** ror a
+*/
unsigned OptShift3 (CodeSeg* S);
/* The sequence
- *
- * bcc L
- * inx
- * L: jsr shrax1
- *
- * may get replaced by
- *
- * ror a
- *
- * if X is zero on entry and unused later. For shift counts > 1, more
- *
- * shr a
- *
- * must be added.
- */
+**
+** bcc L
+** inx
+** L: jsr shrax1
+**
+** may get replaced by
+**
+** ror a
+**
+** if X is zero on entry and unused later. For shift counts > 1, more
+**
+** shr a
+**
+** must be added.
+*/
unsigned OptShift4 (CodeSeg* S);
/* Calls to the asraxN or shraxN routines may get replaced by one or more lsr
- * insns if the value of X is zero.
- */
+** insns if the value of X is zero.
+*/
unsigned OptShift5 (CodeSeg* S);
/* Search for the sequence
- *
- * lda xxx
- * ldx yyy
- * jsr aslax1/asrax1/shlax1/shrax1
- * sta aaa
- * stx bbb
- *
- * and replace it by
- *
- * lda xxx
- * asl a
- * sta aaa
- * lda yyy
- * rol a
- * sta bbb
- *
- * or similar, provided that a/x is not used later
- */
+**
+** lda xxx
+** ldx yyy
+** jsr aslax1/asrax1/shlax1/shrax1
+** sta aaa
+** stx bbb
+**
+** and replace it by
+**
+** lda xxx
+** asl a
+** sta aaa
+** lda yyy
+** rol a
+** sta bbb
+**
+** or similar, provided that a/x is not used later
+*/
unsigned OptShift6 (CodeSeg* S);
/* Inline the shift subroutines. */
};
/* Note: The table is sorted. If there is more than one entry with the same
- * name, entries are sorted best match first, so when searching linear for
- * a match, the first one can be used because it is also the best one (or
- * at least none of the following ones are better).
- * Note^2: Ptr1 and Tmp1 aren't evaluated, because runtime routines don't
- * expect parameters here.
- */
+** name, entries are sorted best match first, so when searching linear for
+** a match, the first one can be used because it is also the best one (or
+** at least none of the following ones are better).
+** Note^2: Ptr1 and Tmp1 aren't evaluated, because runtime routines don't
+** expect parameters here.
+*/
static const CallDesc CallTable [] = {
/* Name A register X register Y register flags replacement */
{
static const CallDesc* FindCall (const char* Name)
/* Find the function with the given name. Return a pointer to the table entry
- * or NULL if the function was not found.
- */
+** or NULL if the function was not found.
+*/
{
/* Do a binary search */
int First = 0;
Last = Current - 1;
if (Result == 0) {
/* Found. Repeat the procedure until the first of all entries
- * with the same name is found.
- */
+ ** with the same name is found.
+ */
Found = 1;
}
}
static int RegMatch (short Expected, short Actual)
/* Check for a register match. If Expected has a value, it must be identical
- * to Actual.
- */
+** to Actual.
+*/
{
return RegValIsUnknown (Expected) || (Expected == Actual);
}
unsigned OptSize1 (CodeSeg* S)
/* Do size optimization by calling special subroutines that preload registers.
- * This routine does not work standalone, it needs a following register load
- * removal pass.
- */
+** This routine does not work standalone, it needs a following register load
+** removal pass.
+*/
{
CodeEntry* E;
unsigned Changes = 0;
const RegContents* In = &E->RI->In;
/* FindCall finds the first entry that matches our function name.
- * The names are listed in "best match" order, so search for the
- * first one, that fulfills our conditions.
- */
+ ** The names are listed in "best match" order, so search for the
+ ** first one, that fulfills our conditions.
+ */
while (1) {
/* Check the registers and allow slower code only if
- * optimizing for size.
- */
+ ** optimizing for size.
+ */
if ((OptForSize || (D->Flags & F_SLOWER) == 0) &&
RegMatch (D->Regs.RegA, In->RegA) &&
RegMatch (D->Regs.RegX, In->RegX) &&
unsigned OptSize2 (CodeSeg* S)
/* Do size optimization by using shorter code sequences, even if this
- * introduces relations between instructions. This step must be one of the
- * last steps, because it makes further work much more difficult.
- */
+** introduces relations between instructions. This step must be one of the
+** last steps, because it makes further work much more difficult.
+*/
{
unsigned Changes = 0;
unsigned I;
unsigned OptSize1 (CodeSeg* S);
/* Do size optimization by calling special subroutines that preload registers.
- * This routine does not work standalone, it needs a following register load
- * removal pass.
- */
+** This routine does not work standalone, it needs a following register load
+** removal pass.
+*/
unsigned OptSize2 (CodeSeg* S);
/* Do size optimization by using shorter code sequences, even if this
- * introduces relations between instructions. This step must be one of the
- * last steps, because it makes further work much more difficult.
- */
+** introduces relations between instructions. This step must be one of the
+** last steps, because it makes further work much more difficult.
+*/
static void AdjustLoadRegInfo (LoadRegInfo* RI, int Index, int Change)
/* Adjust a load register info struct after deleting or inserting an entry
- * with a given index
- */
+** with a given index
+*/
{
CHECK (abs (Change) == 1);
if (Change < 0) {
CHECK (RI != 0);
/* If we had a load or xfer op before, this is a duplicate load which
- * can cause problems if it encountered between the pushax and the op,
- * so remember it.
- */
+ ** can cause problems if it encountered between the pushax and the op,
+ ** so remember it.
+ */
if (RI->LoadIndex >= 0 || RI->XferIndex >= 0) {
RI->Flags |= LI_DUP_LOAD;
}
RegValIsKnown (E->RI->In.RegY) &&
strcmp (E->Arg, "sp") == 0) {
/* A load from the stack with known offset is also ok, but in this
- * case we must reload the index register later. Please note that
- * a load indirect via other zero page locations is not ok, since
- * these locations may change between the push and the actual
- * operation.
- */
+ ** case we must reload the index register later. Please note that
+ ** a load indirect via other zero page locations is not ok, since
+ ** these locations may change between the push and the actual
+ ** operation.
+ */
RI->Offs = (unsigned char) E->RI->In.RegY;
RI->Flags |= (LI_DIRECT | LI_RELOAD_Y);
}
}
/* If we had a load or xfer op before, this is a duplicate load which
- * can cause problems if it encountered between the pushax and the op,
- * so remember it.
- */
+ ** can cause problems if it encountered between the pushax and the op,
+ ** so remember it.
+ */
if (Tgt->LoadIndex >= 0 || Tgt->XferIndex >= 0) {
Tgt->Flags |= LI_DUP_LOAD;
}
} else if (CE_IsCallTo (E, "ldaxysp") && RegValIsKnown (E->RI->In.RegY)) {
/* If we had a load or xfer op before, this is a duplicate load which
- * can cause problems if it encountered between the pushax and the op,
- * so remember it for both registers involved.
- */
+ ** can cause problems if it encountered between the pushax and the op,
+ ** so remember it for both registers involved.
+ */
if (LI->A.LoadIndex >= 0 || LI->A.XferIndex >= 0) {
LI->A.Flags |= LI_DUP_LOAD;
}
static void InsertEntry (StackOpData* D, CodeEntry* E, int Index)
/* Insert a new entry. Depending on Index, D->PushIndex and D->OpIndex will
- * be adjusted by this function.
- */
+** be adjusted by this function.
+*/
{
/* Insert the entry into the code segment */
CS_InsertEntry (D->Code, E, Index);
static void DelEntry (StackOpData* D, int Index)
/* Delete an entry. Depending on Index, D->PushIndex and D->OpIndex will be
- * adjusted by this function, and PushEntry/OpEntry may get invalidated.
- */
+** adjusted by this function, and PushEntry/OpEntry may get invalidated.
+*/
{
/* Delete the entry from the code segment */
CS_DelEntry (D->Code, Index);
static void AdjustStackOffset (StackOpData* D, unsigned Offs)
/* Adjust the offset for all stack accesses in the range PushIndex to OpIndex.
- * OpIndex is adjusted according to the insertions.
- */
+** OpIndex is adjusted according to the insertions.
+*/
{
/* Walk over all entries */
int I = D->PushIndex + 1;
if (NeedCorrection) {
/* Get the code entry before this one. If it's a LDY, adjust the
- * value.
- */
+ ** value.
+ */
CodeEntry* P = CS_GetPrevEntry (D->Code, I);
if (P && P->OPC == OP65_LDY && CE_IsConstImm (P)) {
}
/* If we have rhs load insns that load from stack, we'll have to adjust
- * the offsets for these also.
- */
+ ** the offsets for these also.
+ */
if (D->Rhs.A.Flags & LI_RELOAD_Y) {
D->Rhs.A.Offs -= Offs;
}
static void ReplacePushByStore (StackOpData* D)
/* Replace the call to the push subroutine by a store into the zero page
- * location (actually, the push is not replaced, because we need it for
- * later, but the name is still ok since the push will get removed at the
- * end of each routine).
- */
+** location (actually, the push is not replaced, because we need it for
+** later, but the name is still ok since the push will get removed at the
+** end of each routine).
+*/
{
/* Store the value into the zeropage instead of pushing it. Check high
- * byte first so that the store is later in A/X order.
- */
+ ** byte first so that the store is later in A/X order.
+ */
if ((D->Lhs.X.Flags & LI_DIRECT) == 0) {
AddStoreX (D);
}
static void AddOpLow (StackOpData* D, opc_t OPC, LoadInfo* LI)
/* Add an op for the low byte of an operator. This function honours the
- * OP_DIRECT and OP_RELOAD_Y flags and generates the necessary instructions.
- * All code is inserted at the current insertion point.
- */
+** OP_DIRECT and OP_RELOAD_Y flags and generates the necessary instructions.
+** All code is inserted at the current insertion point.
+*/
{
CodeEntry* X;
if ((LI->A.Flags & LI_DIRECT) != 0) {
/* Op with a variable location. If the location is on the stack, we
- * need to reload the Y register.
- */
+ ** need to reload the Y register.
+ */
if ((LI->A.Flags & LI_RELOAD_Y) == 0) {
/* opc ... */
static void AddOpHigh (StackOpData* D, opc_t OPC, LoadInfo* LI, int KeepResult)
/* Add an op for the high byte of an operator. Special cases (constant values
- * or similar) have to be checked separately, the function covers only the
- * generic case. Code is inserted at the insertion point.
- */
+** or similar) have to be checked separately, the function covers only the
+** generic case. Code is inserted at the insertion point.
+*/
{
CodeEntry* X;
/* Remove register load insns */
{
/* Both registers may be loaded with one insn, but DelEntry will in this
- * case clear the other one.
- */
+ ** case clear the other one.
+ */
if ((LI->A.Flags & (LI_REMOVE | LI_DONT_REMOVE)) == LI_REMOVE) {
if (LI->A.LoadIndex >= 0) {
DelEntry (D, LI->A.LoadIndex);
static int IsRegVar (StackOpData* D)
/* If the value pushed is that of a zeropage variable, replace ZPLo and ZPHi
- * in the given StackOpData struct by the variable and return true. Otherwise
- * leave D untouched and return false.
- */
+** in the given StackOpData struct by the variable and return true. Otherwise
+** leave D untouched and return false.
+*/
{
CodeEntry* LoadA = D->Lhs.A.LoadEntry;
CodeEntry* LoadX = D->Lhs.X.LoadEntry;
CodeLabel* L;
/* Create a call to the boolean transformer function and a label for this
- * insn. This is needed for all variants. Other insns are inserted *before*
- * the call.
- */
+ ** insn. This is needed for all variants. Other insns are inserted *before*
+ ** the call.
+ */
X = NewCodeEntry (OP65_JSR, AM65_ABS, BoolTransformer, 0, D->OpEntry->LI);
InsertEntry (D, X, D->OpIndex + 1);
L = CS_GenLabel (D->Code, X);
/* If the lhs is direct (but not stack relative), encode compares with lhs
- * effectively reverting the order (which doesn't matter for ==).
- */
+ ** effectively reverting the order (which doesn't matter for ==).
+ */
if ((D->Lhs.A.Flags & (LI_DIRECT | LI_RELOAD_Y)) == LI_DIRECT &&
(D->Lhs.X.Flags & (LI_DIRECT | LI_RELOAD_Y)) == LI_DIRECT) {
ReplacePushByStore (D);
/* If the lhs is direct (but not stack relative), we can just reload the
- * data later.
- */
+ ** data later.
+ */
if ((D->Lhs.A.Flags & (LI_DIRECT | LI_RELOAD_Y)) == LI_DIRECT &&
(D->Lhs.X.Flags & (LI_DIRECT | LI_RELOAD_Y)) == LI_DIRECT) {
AddStoreA (D);
/* Be sure to setup IP after adding the stores, otherwise it will get
- * messed up.
- */
+ ** messed up.
+ */
D->IP = D->OpIndex+1;
/* tay */
}
/* If the return value of __bzero is used, we have to add code to reload
- * a/x from the pointer variable.
- */
+ ** a/x from the pointer variable.
+ */
if (RegAXUsed (D->Code, D->OpIndex+1)) {
X = NewCodeEntry (OP65_LDA, AM65_ZP, D->ZPLo, 0, D->OpEntry->LI);
InsertEntry (D, X, D->OpIndex+1);
}
/* X is always zero, A contains the size of the data area to zero.
- * Note: A may be zero, in which case the operation is null op.
- */
+ ** Note: A may be zero, in which case the operation is null op.
+ */
if (D->OpEntry->RI->In.RegA != 0) {
/* lda #$00 */
InsertEntry (D, X, D->OpIndex+4);
/* If we remove staxspidx, we must restore the Y register to what the
- * function would return.
- */
+ ** function would return.
+ */
X = NewCodeEntry (OP65_LDY, AM65_IMM, "$00", 0, D->OpEntry->LI);
InsertEntry (D, X, D->OpIndex+5);
CHECK (D->NextEntry != 0);
/* Check if the X register is known and zero when the add is done, and
- * if the add is followed by
- *
- * ldy #$00
- * jsr ldauidx ; or ldaidx
- *
- * If this is true, the addition does actually add an offset to a pointer
- * before it is dereferenced. Since both subroutines take an offset in Y,
- * we can pass the offset (instead of #$00) and remove the addition
- * alltogether.
- */
+ ** if the add is followed by
+ **
+ ** ldy #$00
+ ** jsr ldauidx ; or ldaidx
+ **
+ ** If this is true, the addition does actually add an offset to a pointer
+ ** before it is dereferenced. Since both subroutines take an offset in Y,
+ ** we can pass the offset (instead of #$00) and remove the addition
+ ** alltogether.
+ */
if (D->OpEntry->RI->In.RegX == 0 &&
D->NextEntry->OPC == OP65_LDY &&
CE_IsKnownImm (D->NextEntry, 0) &&
AddStoreA (D);
/* Replace the ldy by a tay. Be sure to create the new entry before
- * deleting the ldy, since we will reference the line info from this
- * insn.
- */
+ ** deleting the ldy, since we will reference the line info from this
+ ** insn.
+ */
X = NewCodeEntry (OP65_TAY, AM65_IMP, 0, 0, D->NextEntry->LI);
DelEntry (D, D->OpIndex + 1);
InsertEntry (D, X, D->OpIndex + 1);
/* Replace the call to ldaidx/ldauidx. Since X is already zero, and
- * the ptr is in the zero page location, we just need to load from
- * the pointer, and fix X in case of ldaidx.
- */
+ ** the ptr is in the zero page location, we just need to load from
+ ** the pointer, and fix X in case of ldaidx.
+ */
X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, D->ZPLo, 0, N->LI);
DelEntry (D, D->OpIndex + 2);
InsertEntry (D, X, D->OpIndex + 2);
X = NewCodeEntry (OP65_LDX, AM65_IMM, Arg, 0, D->OpEntry->LI);
} else {
/* Value of first op high byte is unknown. Load from ZP or
- * original storage.
- */
+ ** original storage.
+ */
if (D->Lhs.X.Flags & LI_DIRECT) {
CodeEntry* LoadX = D->Lhs.X.LoadEntry;
X = NewCodeEntry (OP65_LDX, LoadX->AM, LoadX->Arg, 0, D->OpEntry->LI);
static const OptFuncDesc* FindFunc (const char* Name)
/* Find the function with the given name. Return a pointer to the table entry
- * or NULL if the function was not found.
- */
+** or NULL if the function was not found.
+*/
{
return bsearch (Name, FuncTable, FUNC_COUNT, sizeof(OptFuncDesc), CmpFunc);
}
static int HarmlessCall (const char* Name)
/* Check if this is a call to a harmless subroutine that will not interrupt
- * the pushax/op sequence when encountered.
- */
+** the pushax/op sequence when encountered.
+*/
{
static const char* Tab[] = {
"aslax1",
static int PreCondOk (StackOpData* D)
/* Check if the preconditions for a call to the optimizer subfunction are
- * satisfied. As a side effect, this function will also choose the zero page
- * register to use.
- */
+** satisfied. As a side effect, this function will also choose the zero page
+** register to use.
+*/
{
/* Check the flags */
unsigned UnusedRegs = D->OptFunc->UnusedRegs;
Data.Code = S;
/* Look for a call to pushax followed by a call to some other function
- * that takes it's first argument on the stack, and the second argument
- * in the primary register.
- * It depends on the code between the two if we can handle/transform the
- * sequence, so check this code for the following list of things:
- *
- * - the range must be a basic block (one entry, one exit)
- * - there may not be accesses to local variables with unknown
- * offsets (because we have to adjust these offsets).
- * - no subroutine calls
- * - no jump labels
- *
- * Since we need a zero page register later, do also check the
- * intermediate code for zero page use.
- */
+ ** that takes it's first argument on the stack, and the second argument
+ ** in the primary register.
+ ** It depends on the code between the two if we can handle/transform the
+ ** sequence, so check this code for the following list of things:
+ **
+ ** - the range must be a basic block (one entry, one exit)
+ ** - there may not be accesses to local variables with unknown
+ ** offsets (because we have to adjust these offsets).
+ ** - no subroutine calls
+ ** - no jump labels
+ **
+ ** Since we need a zero page register later, do also check the
+ ** intermediate code for zero page use.
+ */
I = 0;
while (I < (int)CS_GetEntryCount (S)) {
case Search:
/* While searching, track register load insns, so we can tell
- * what is in a register once pushax is encountered.
- */
+ ** what is in a register once pushax is encountered.
+ */
if (CE_HasLabel (E)) {
/* Currently we don't track across branches */
ClearLoadInfo (&Data.Lhs);
case FoundPush:
/* We' found a pushax before. Search for a stack op that may
- * follow and in the meantime, track zeropage usage and check
- * for code that will disable us from translating the sequence.
- */
+ ** follow and in the meantime, track zeropage usage and check
+ ** for code that will disable us from translating the sequence.
+ */
if (CE_HasLabel (E)) {
/* Currently we don't track across branches */
ClearLoadInfo (&Data.Rhs);
if (E->OPC == OP65_JSR) {
/* Subroutine call: Check if this is one of the functions,
- * we're going to replace.
- */
+ ** we're going to replace.
+ */
Data.OptFunc = FindFunc (E->Arg);
if (Data.OptFunc) {
/* Remember the op index and go on */
break;
} else if (!HarmlessCall (E->Arg)) {
/* A call to an unkown subroutine: We need to start
- * over after the last pushax. Note: This will also
- * happen if we encounter a call to pushax!
- */
+ ** over after the last pushax. Note: This will also
+ ** happen if we encounter a call to pushax!
+ */
I = Data.PushIndex;
State = Initialize;
break;
} else if (E->Info & OF_STORE && (E->Chg & REG_ZP) == 0) {
/* Too dangerous - there may be a change of a variable
- * within the sequence.
- */
+ ** within the sequence.
+ */
I = Data.PushIndex;
State = Initialize;
break;
E->RI->In.RegY < 2)) {
/* If we are using the stack, and we don't have "indirect Y"
- * addressing mode, or the value of Y is unknown, or less
- * than two, we cannot cope with this piece of code. Having
- * an unknown value of Y means that we cannot correct the
- * stack offset, while having an offset less than two means
- * that the code works with the value on stack which is to
- * be removed.
- */
+ ** addressing mode, or the value of Y is unknown, or less
+ ** than two, we cannot cope with this piece of code. Having
+ ** an unknown value of Y means that we cannot correct the
+ ** stack offset, while having an offset less than two means
+ ** that the code works with the value on stack which is to
+ ** be removed.
+ */
I = Data.PushIndex;
State = Initialize;
break;
TrackLoads (&Data.Rhs, E, I);
}
/* If the registers from the push (A/X) are used before they're
- * changed, we cannot change the sequence, because this would
- * with a high probability change the register contents.
- */
+ ** changed, we cannot change the sequence, because this would
+ ** with a high probability change the register contents.
+ */
UsedRegs |= E->Use;
if ((UsedRegs & ~ChangedRegs) & REG_AX) {
I = Data.PushIndex;
FinalizeLoadInfo (&Data.Rhs, S);
/* If the Lhs loads do load from zeropage, we have to include
- * them into UsedRegs registers used. The Rhs loads have already
- * been tracked.
- */
+ ** them into UsedRegs registers used. The Rhs loads have already
+ ** been tracked.
+ */
if (Data.Lhs.A.LoadEntry && Data.Lhs.A.LoadEntry->AM == AM65_ZP) {
Data.UsedRegs |= Data.Lhs.A.LoadEntry->Use;
}
}
/* Check the preconditions. If they aren't ok, reset the insn
- * pointer to the pushax and start over. We will loose part of
- * load tracking but at least a/x has probably lost between
- * pushax and here and will be tracked again when restarting.
- */
+ ** pointer to the pushax and start over. We will loose part of
+ ** load tracking but at least a/x has probably lost between
+ ** pushax and here and will be tracked again when restarting.
+ */
if (!PreCondOk (&Data)) {
I = Data.PushIndex;
State = Initialize;
AdjustStackOffset (&Data, 2);
/* Regenerate register info, since AdjustStackOffset changed
- * the code
- */
+ ** the code
+ */
CS_GenRegInfo (S);
/* Call the optimizer function */
Changes += Data.OptFunc->Func (&Data);
/* Since the function may have added or deleted entries,
- * correct the index.
- */
+ ** correct the index.
+ */
I += CS_GetEntryCount (S) - OldEntryCount;
/* Regenerate register info */
unsigned OptStore1 (CodeSeg* S)
/* Search for the sequence
- *
- * ldy #n
- * jsr staxysp
- * ldy #n+1
- * jsr ldaxysp
- *
- * and remove the useless load.
- */
+**
+** ldy #n
+** jsr staxysp
+** ldy #n+1
+** jsr ldaxysp
+**
+** and remove the useless load.
+*/
{
unsigned Changes = 0;
unsigned OptStore2 (CodeSeg* S)
/* Search for a call to staxysp. If the ax register is not used later, and
- * the value is constant, just use the A register and store directly into the
- * stack.
- */
+** the value is constant, just use the A register and store directly into the
+** stack.
+*/
{
unsigned I;
unsigned Changes = 0;
unsigned IP = I + 1; /* Insertion point */
/* Replace the store. We will not remove the loads, since this is
- * too complex and will be done by other optimizer steps.
- */
+ ** too complex and will be done by other optimizer steps.
+ */
N = NewCodeEntry (OP65_LDA, AM65_IMM, MakeHexArg (A), 0, E->LI);
CS_InsertEntry (S, N, IP++);
InsertStore (S, &IP, E->LI);
unsigned OptStore3 (CodeSeg* S)
/* Search for a call to steaxysp. If the eax register is not used later, and
- * the value is constant, just use the A register and store directly into the
- * stack.
- */
+** the value is constant, just use the A register and store directly into the
+** stack.
+*/
{
unsigned I;
unsigned Changes = 0;
unsigned IP = I + 1; /* Insertion point */
/* Replace the store. We will not remove the loads, since this is
- * too complex and will be done by other optimizer steps.
- */
+ ** too complex and will be done by other optimizer steps.
+ */
N = NewCodeEntry (OP65_LDA, AM65_IMM, MakeHexArg (A), 0, E->LI);
CS_InsertEntry (S, N, IP++);
InsertStore (S, &IP, E->LI);
unsigned OptStore4 (CodeSeg* S)
/* Search for the sequence
- *
- * sta xx
- * stx yy
- * lda xx
- * ldx yy
- *
- * and remove the useless load, provided that the next insn doesn't use flags
- * from the load.
- */
+**
+** sta xx
+** stx yy
+** lda xx
+** ldx yy
+**
+** and remove the useless load, provided that the next insn doesn't use flags
+** from the load.
+*/
{
unsigned Changes = 0;
unsigned OptStore5 (CodeSeg* S)
/* Search for the sequence
- *
- * lda foo
- * ldx bar
- * sta something
- * stx something-else
- *
- * and replace it by
- *
- * lda foo
- * sta something
- * lda bar
- * sta something-else
- *
- * if X is not used later. This replacement doesn't save any cycles or bytes,
- * but it keeps the value of X, which may be reused later.
- */
+**
+** lda foo
+** ldx bar
+** sta something
+** stx something-else
+**
+** and replace it by
+**
+** lda foo
+** sta something
+** lda bar
+** sta something-else
+**
+** if X is not used later. This replacement doesn't save any cycles or bytes,
+** but it keeps the value of X, which may be reused later.
+*/
{
unsigned Changes = 0;
/* */
/* */
/* (C) 2002-2006, Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
unsigned OptStore1 (CodeSeg* S);
/* Search for the sequence
- *
- * ldy #n
- * jsr staxysp
- * ldy #n+1
- * jsr ldaxysp
- *
- * and remove the useless load, provided that the next insn doesn't use flags
- * from the load.
- */
+**
+** ldy #n
+** jsr staxysp
+** ldy #n+1
+** jsr ldaxysp
+**
+** and remove the useless load, provided that the next insn doesn't use flags
+** from the load.
+*/
unsigned OptStore2 (CodeSeg* S);
/* Search for a call to staxysp. If the ax register is not used later, and
- * the value is constant, just use the A register and store directly into the
- * stack.
- */
+** the value is constant, just use the A register and store directly into the
+** stack.
+*/
unsigned OptStore3 (CodeSeg* S);
/* Search for a call to steaxysp. If the eax register is not used later, and
- * the value is constant, just use the A register and store directly into the
- * stack.
- */
+** the value is constant, just use the A register and store directly into the
+** stack.
+*/
unsigned OptStore4 (CodeSeg* S);
/* Search for the sequence
- *
- * sta xx
- * stx yy
- * lda xx
- * ldx yy
- *
- * and remove the useless load, provided that the next insn doesn't use flags
- * from the load.
- */
+**
+** sta xx
+** stx yy
+** lda xx
+** ldx yy
+**
+** and remove the useless load, provided that the next insn doesn't use flags
+** from the load.
+*/
unsigned OptStore5 (CodeSeg* S);
/* Search for the sequence
- *
- * lda foo
- * ldx bar
- * sta something
- * stx something-else
- *
- * and replace it by
- *
- * lda foo
- * sta something
- * lda bar
- * sta something-else
- *
- * if X is not used later. This replacement doesn't save any cycles or bytes,
- * but it keeps the value of X, which may be reused later.
- */
+**
+** lda foo
+** ldx bar
+** sta something
+** stx something-else
+**
+** and replace it by
+**
+** lda foo
+** sta something
+** lda bar
+** sta something-else
+**
+** if X is not used later. This replacement doesn't save any cycles or bytes,
+** but it keeps the value of X, which may be reused later.
+*/
unsigned OptSub1 (CodeSeg* S)
/* Search for the sequence
- *
- * sbc ...
- * bcs L
- * dex
- * L:
- *
- * and remove the handling of the high byte if X is not used later.
- */
+**
+** sbc ...
+** bcs L
+** dex
+** L:
+**
+** and remove the handling of the high byte if X is not used later.
+*/
{
unsigned Changes = 0;
unsigned OptSub2 (CodeSeg* S)
/* Search for the sequence
- *
- * lda xx
- * sec
- * sta tmp1
- * lda yy
- * sbc tmp1
- * sta yy
- *
- * and replace it by
- *
- * sec
- * lda yy
- * sbc xx
- * sta yy
- */
+**
+** lda xx
+** sec
+** sta tmp1
+** lda yy
+** sbc tmp1
+** sta yy
+**
+** and replace it by
+**
+** sec
+** lda yy
+** sbc xx
+** sta yy
+*/
{
unsigned Changes = 0;
CS_DelEntry (S, I+3);
/* Move the lda to the position of the subtraction and change the
- * op to SBC.
- */
+ ** op to SBC.
+ */
CS_MoveEntry (S, I, I+3);
CE_ReplaceOPC (E, OP65_SBC);
/* If the sequence head had a label, move this label back to the
- * head.
- */
+ ** head.
+ */
if (CE_HasLabel (E)) {
CS_MoveLabels (S, E, L[0]);
}
unsigned OptSub3 (CodeSeg* S)
/* Search for a call to decaxn and replace it by an 8 bit sub if the X register
- * is not used later.
- */
+** is not used later.
+*/
{
unsigned Changes = 0;
/* */
/* */
/* (C) 2001-2006, Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
unsigned OptSub1 (CodeSeg* S);
/* Search for the sequence
- *
- * sbc ...
- * bcs L
- * dex
- * L:
- *
- * and remove the handling of the high byte if X is not used later.
- */
+**
+** sbc ...
+** bcs L
+** dex
+** L:
+**
+** and remove the handling of the high byte if X is not used later.
+*/
unsigned OptSub2 (CodeSeg* S);
/* Search for the sequence
- *
- * lda xx
- * sec
- * sta tmp1
- * lda yy
- * sbc tmp1
- * sta yy
- *
- * and replace it by
- *
- * sec
- * lda yy
- * sbc xx
- * sta yy
- */
+**
+** lda xx
+** sec
+** sta tmp1
+** lda yy
+** sbc tmp1
+** sta yy
+**
+** and replace it by
+**
+** sec
+** lda yy
+** sbc xx
+** sta yy
+*/
unsigned OptSub3 (CodeSeg* S);
/* Search for a call to decaxn and replace it by an 8 bit sub if the X register
- * is not used later.
- */
+** is not used later.
+*/
unsigned OptTest1 (CodeSeg* S)
/* Given a sequence
- *
- * stx xxx
- * ora xxx
- * beq/bne ...
- *
- * If X is zero, the sequence may be changed to
- *
- * cmp #$00
- * beq/bne ...
- *
- * which may be optimized further by another step.
- *
- * If A is zero, the sequence may be changed to
- *
- * txa
- * beq/bne ...
- *
- */
+**
+** stx xxx
+** ora xxx
+** beq/bne ...
+**
+** If X is zero, the sequence may be changed to
+**
+** cmp #$00
+** beq/bne ...
+**
+** which may be optimized further by another step.
+**
+** If A is zero, the sequence may be changed to
+**
+** txa
+** beq/bne ...
+*/
{
unsigned Changes = 0;
unsigned I;
unsigned OptTest2 (CodeSeg* S)
/* Search for an inc/dec operation followed by a load and a conditional
- * branch based on the flags from the load. Remove the load if the insn
- * isn't used later.
- */
+** branch based on the flags from the load. Remove the load if the insn
+** isn't used later.
+*/
{
unsigned Changes = 0;
unsigned OptTest1 (CodeSeg* S);
/* Given a sequence
- *
- * stx xxx
- * ora xxx
- * beq/bne ...
- *
- * If X is zero, the sequence may be changed to
- *
- * cmp #$00
- * beq/bne ...
- *
- * which may be optimized further by another step.
- *
- * If A is zero, the sequence may be changed to
- *
- * txa
- * beq/bne ...
- *
- */
+**
+** stx xxx
+** ora xxx
+** beq/bne ...
+**
+** If X is zero, the sequence may be changed to
+**
+** cmp #$00
+** beq/bne ...
+**
+** which may be optimized further by another step.
+**
+** If A is zero, the sequence may be changed to
+**
+** txa
+** beq/bne ...
+*/
unsigned OptTest2 (CodeSeg* S);
/* Search for an inc/dec operation followed by a load and a conditional
- * branch based on the flags from the load. Remove the load if the insn
- * isn't used later.
- */
+** branch based on the flags from the load. Remove the load if the insn
+** isn't used later.
+*/
Type* TypeAlloc (unsigned Len)
/* Allocate memory for a type string of length Len. Len *must* include the
- * trailing T_END.
- */
+** trailing T_END.
+*/
{
return xmalloc (Len * sizeof (Type));
}
Type* PointerTo (const Type* T)
/* Return a type string that is "pointer to T". The type string is allocated
- * on the heap and may be freed after use.
- */
+** on the heap and may be freed after use.
+*/
{
/* Get the size of the type string including the terminator */
unsigned Size = TypeLen (T) + 1;
static TypeCode PrintTypeComp (FILE* F, TypeCode C, TypeCode Mask, const char* Name)
/* Check for a specific component of the type. If it is there, print the
- * name and remove it. Return the type with the component removed.
- */
+** name and remove it. Return the type with the component removed.
+*/
{
if ((C & Mask) == Mask) {
fprintf (F, "%s ", Name);
unsigned CheckedSizeOf (const Type* T)
/* Return the size of a data type. If the size is zero, emit an error and
- * return some valid size instead (so the rest of the compiler doesn't have
- * to work with invalid sizes).
- */
+** return some valid size instead (so the rest of the compiler doesn't have
+** to work with invalid sizes).
+*/
{
unsigned Size = SizeOf (T);
if (Size == 0) {
unsigned CheckedPSizeOf (const Type* T)
/* Return the size of a data type that is pointed to by a pointer. If the
- * size is zero, emit an error and return some valid size instead (so the
- * rest of the compiler doesn't have to work with invalid sizes).
- */
+** size is zero, emit an error and return some valid size instead (so the
+** rest of the compiler doesn't have to work with invalid sizes).
+*/
{
unsigned Size = PSizeOf (T);
if (Size == 0) {
Type* Indirect (Type* T)
/* Do one indirection for the given type, that is, return the type where the
- * given type points to.
- */
+** given type points to.
+*/
{
/* We are expecting a pointer expression */
CHECK (IsClassPtr (T));
int IsVariadicFunc (const Type* T)
/* Return true if this is a function type or pointer to function type with
- * variable parameter list
- */
+** variable parameter list
+*/
{
FuncDesc* F = GetFuncDesc (T);
return (F->Flags & FD_VARIADIC) != 0;
long GetElementCount (const Type* T)
/* Get the element count of the array specified in T (which must be of
- * array type).
- */
+** array type).
+*/
{
CHECK (IsTypeArray (T));
return T->A.L;
void SetElementCount (Type* T, long Count)
/* Set the element count of the array specified in T (which must be of
- * array type).
- */
+** array type).
+*/
{
CHECK (IsTypeArray (T));
T->A.L = Count;
Type* GetBaseElementType (Type* T)
/* Return the base element type of a given type. If T is not an array, this
- * will return. Otherwise it will return the base element type, which means
- * the element type that is not an array.
- */
+** will return. Otherwise it will return the base element type, which means
+** the element type that is not an array.
+*/
{
while (IsTypeArray (T)) {
++T;
Type* IntPromotion (Type* T)
/* Apply the integer promotions to T and return the result. The returned type
- * string may be T if there is no need to change it.
- */
+** string may be T if there is no need to change it.
+*/
{
/* We must have an int to apply int promotions */
PRECONDITION (IsClassInt (T));
/* An integer can represent all values from either signed or unsigned char,
- * so convert chars to int and leave all other types alone.
- */
+ ** so convert chars to int and leave all other types alone.
+ */
if (IsTypeChar (T)) {
return type_int;
} else {
Type* PtrConversion (Type* T)
/* If the type is a function, convert it to pointer to function. If the
- * expression is an array, convert it to pointer to first element. Otherwise
- * return T.
- */
+** expression is an array, convert it to pointer to first element. Otherwise
+** return T.
+*/
{
if (IsTypeFunc (T)) {
return PointerTo (T);
Type* TypeAlloc (unsigned Len);
/* Allocate memory for a type string of length Len. Len *must* include the
- * trailing T_END.
- */
+** trailing T_END.
+*/
void TypeFree (Type* T);
/* Free a type string */
Type* PointerTo (const Type* T);
/* Return a type string that is "pointer to T". The type string is allocated
- * on the heap and may be freed after use.
- */
+** on the heap and may be freed after use.
+*/
void PrintType (FILE* F, const Type* T);
/* Output translation of type array. */
unsigned CheckedSizeOf (const Type* T);
/* Return the size of a data type. If the size is zero, emit an error and
- * return some valid size instead (so the rest of the compiler doesn't have
- * to work with invalid sizes).
- */
+** return some valid size instead (so the rest of the compiler doesn't have
+** to work with invalid sizes).
+*/
unsigned CheckedPSizeOf (const Type* T);
/* Return the size of a data type that is pointed to by a pointer. If the
- * size is zero, emit an error and return some valid size instead (so the
- * rest of the compiler doesn't have to work with invalid sizes).
- */
+** size is zero, emit an error and return some valid size instead (so the
+** rest of the compiler doesn't have to work with invalid sizes).
+*/
unsigned TypeOf (const Type* T);
/* Get the code generator base type of the object */
Type* Indirect (Type* T);
/* Do one indirection for the given type, that is, return the type where the
- * given type points to.
- */
+** given type points to.
+*/
Type* ArrayToPtr (Type* T);
/* Convert an array to a pointer to it's first element */
int IsVariadicFunc (const Type* T) attribute ((const));
/* Return true if this is a function type or pointer to function type with
- * variable parameter list
- */
+** variable parameter list
+*/
#if defined(HAVE_INLINE)
INLINE TypeCode GetSizeModifier (const Type* T)
long GetElementCount (const Type* T);
/* Get the element count of the array specified in T (which must be of
- * array type).
- */
+** array type).
+*/
void SetElementCount (Type* T, long Count);
/* Set the element count of the array specified in T (which must be of
- * array type).
- */
+** array type).
+*/
Type* GetElementType (Type* T);
/* Return the element type of the given array type. */
Type* GetBaseElementType (Type* T);
/* Return the base element type of a given type. If T is not an array, this
- * will return. Otherwise it will return the base element type, which means
- * the element type that is not an array.
- */
+** will return. Otherwise it will return the base element type, which means
+** the element type that is not an array.
+*/
struct SymEntry* GetSymEntry (const Type* T) attribute ((const));
/* Return a SymEntry pointer from a type */
Type* IntPromotion (Type* T);
/* Apply the integer promotions to T and return the result. The returned type
- * string may be T if there is no need to change it.
- */
+** string may be T if there is no need to change it.
+*/
Type* PtrConversion (Type* T);
/* If the type is a function, convert it to pointer to function. If the
- * expression is an array, convert it to pointer to first element. Otherwise
- * return T.
- */
+** expression is an array, convert it to pointer to first element. Otherwise
+** return T.
+*/
TypeCode AddrSizeQualifier (unsigned AddrSize);
/* Return T_QUAL_NEAR or T_QUAL_FAR depending on the address size */
static TypeCode OptionalQualifiers (TypeCode Allowed)
/* Read type qualifiers if we have any. Allowed specifies the allowed
- * qualifiers.
- */
+** qualifiers.
+*/
{
/* We start without any qualifiers */
TypeCode Q = T_QUAL_NONE;
{
if (D->Index + Count >= MAXTYPELEN) {
/* We must call Fatal() here, since calling Error() will try to
- * continue, and the declaration type is not correctly terminated
- * in case we come here.
- */
+ ** continue, and the declaration type is not correctly terminated
+ ** in case we come here.
+ */
Fatal ("Too many type specifiers");
}
}
TypeCode Q;
/* Using typedefs, it is possible to generate declarations that have
- * type qualifiers attached to an array, not the element type. Go and
- * fix these here.
- */
+ ** type qualifiers attached to an array, not the element type. Go and
+ ** fix these here.
+ */
T = DataType;
Q = T_QUAL_NONE;
while (T->C != T_END) {
/* Pointer to function which is not fastcall? */
if (IsTypeFunc (T+1) && !IsQualFastcall (T+1)) {
/* Move the fastcall qualifier from the pointer to
- * the function.
- */
+ ** the function.
+ */
T[0].C &= ~T_QUAL_FASTCALL;
T[1].C |= T_QUAL_FASTCALL;
} else {
/* No address size qualifiers specified */
if (IsTypeFunc (T+1)) {
/* Pointer to function. Use the qualifier from the function
- * or the default if the function don't has one.
- */
+ ** or the default if the function don't has one.
+ */
Q = (T[1].C & T_QUAL_ADDRSIZE);
if (Q == T_QUAL_NONE) {
Q = CodeAddrSizeQualifier ();
T[0].C |= Q;
} else {
/* We have address size qualifiers. If followed by a function,
- * apply these also to the function.
- */
+ ** apply these also to the function.
+ */
if (IsTypeFunc (T+1)) {
TypeCode FQ = (T[1].C & T_QUAL_ADDRSIZE);
if (FQ == T_QUAL_NONE) {
static int ParseFieldWidth (Declaration* Decl)
/* Parse an optional field width. Returns -1 if no field width is speficied,
- * otherwise the width of the field.
- */
+** otherwise the width of the field.
+*/
{
ExprDesc Expr;
/* Handle a struct or union forward decl */
{
/* Try to find a struct/union with the given name. If there is none,
- * insert a forward declaration into the current lexical level.
- */
+ ** insert a forward declaration into the current lexical level.
+ */
SymEntry* Entry = FindTagSym (Name);
if (Entry == 0) {
Entry = AddStructSym (Name, Type, 0, 0);
static unsigned CopyAnonStructFields (const Declaration* Decl, int Offs)
/* Copy fields from an anon union/struct into the current lexical level. The
- * function returns the size of the embedded struct/union.
- */
+** function returns the size of the embedded struct/union.
+*/
{
/* Get the pointer to the symbol table entry of the anon struct */
SymEntry* Entry = GetSymEntry (Decl->Type);
unsigned Size = Entry->V.S.Size;
/* Get the symbol table containing the fields. If it is empty, there has
- * been an error before, so bail out.
- */
+ ** been an error before, so bail out.
+ */
SymTable* Tab = Entry->V.S.SymTab;
if (Tab == 0) {
/* Incomplete definition - has been flagged before */
}
/* Get a pointer to the list of symbols. Then walk the list adding copies
- * of the embedded struct to the current level.
- */
+ ** of the embedded struct to the current level.
+ */
Entry = Tab->SymHead;
while (Entry) {
/* Enter a copy of this symbol adjusting the offset. We will just
- * reuse the type string here.
- */
+ ** reuse the type string here.
+ */
AddLocalSym (Entry->Name, Entry->Type, SC_STRUCTFIELD, Offs + Entry->V.Offs);
/* Currently, there can not be any attributes, but if there will be
- * some in the future, we want to know this.
- */
+ ** some in the future, we want to know this.
+ */
CHECK (Entry->Attr == 0);
/* Next entry */
/* Check for fields without a name */
if (Decl.Ident[0] == '\0') {
/* In cc65 mode, we allow anonymous structs/unions within
- * a struct.
- */
+ ** a struct.
+ */
if (IS_Get (&Standard) >= STD_CC65 && IsClassStruct (Decl.Type)) {
/* This is an anonymous struct or union. Copy the fields
- * into the current level.
- */
+ ** into the current level.
+ */
CopyAnonStructFields (&Decl, 0);
} else {
ident Ident;
/* If we had a flexible array member before, no other fields can
- * follow.
- */
+ ** follow.
+ */
if (FlexibleMember) {
Error ("Flexible array member must be last field");
FlexibleMember = 0; /* Avoid further errors */
FieldWidth = ParseFieldWidth (&Decl);
/* If this is not a bit field, or the bit field is too large for
- * the remainder of the current member, or we have a bit field
- * with width zero, align the struct to the next member by adding
- * a member with an anonymous name.
- */
+ ** the remainder of the current member, or we have a bit field
+ ** with width zero, align the struct to the next member by adding
+ ** a member with an anonymous name.
+ */
if (BitOffs > 0) {
if (FieldWidth <= 0 || (BitOffs + FieldWidth) > (int) INT_BITS) {
AnonName (Ident, "bit-field");
/* Add an anonymous bit-field that aligns to the next
- * storage unit.
- */
+ ** storage unit.
+ */
AddBitField (Ident, StructSize, BitOffs, INT_BITS - BitOffs);
/* No bits left */
}
/* Apart from the above, a bit field with width 0 is not processed
- * further.
- */
+ ** further.
+ */
if (FieldWidth == 0) {
goto NextMember;
}
/* Check if this field is a flexible array member, and
- * calculate the size of the field.
- */
+ ** calculate the size of the field.
+ */
if (IsTypeArray (Decl.Type) && GetElementCount (Decl.Type) == UNSPECIFIED) {
/* Array with unspecified size */
if (StructSize == 0) {
if (Decl.Ident[0] == '\0') {
if (FieldWidth < 0) {
/* In cc65 mode, we allow anonymous structs/unions within
- * a struct.
- */
+ ** a struct.
+ */
if (IS_Get (&Standard) >= STD_CC65 && IsClassStruct (Decl.Type)) {
/* This is an anonymous struct or union. Copy the
- * fields into the current level.
- */
+ ** fields into the current level.
+ */
StructSize += CopyAnonStructFields (&Decl, StructSize);
} else {
/* Add a field entry to the table */
if (FieldWidth > 0) {
/* Add full byte from the bit offset to the variable offset.
- * This simplifies handling he bit-field as a char type
- * in expressions.
- */
+ ** This simplifies handling he bit-field as a char type
+ ** in expressions.
+ */
unsigned Offs = StructSize + (BitOffs / CHAR_BITS);
AddBitField (Decl.Ident, Offs, BitOffs % CHAR_BITS, FieldWidth);
BitOffs += FieldWidth;
static Type* ParamTypeCvt (Type* T)
/* If T is an array, convert it to a pointer else do nothing. Return the
- * resulting type.
- */
+** resulting type.
+*/
{
if (IsTypeArray (T)) {
T->C = T_PTR;
}
/* Skip right paren. We must explicitly check for one here, since some of
- * the breaks above bail out without checking.
- */
+ ** the breaks above bail out without checking.
+ */
ConsumeRParen ();
/* An optional list of type specifications follows */
ParseDeclSpec (&Spec, SC_AUTO, T_INT);
/* We accept only auto and register as storage class specifiers, but
- * we ignore all this, since we use auto anyway.
- */
+ ** we ignore all this, since we use auto anyway.
+ */
if ((Spec.StorageClass & SC_AUTO) == 0 &&
(Spec.StorageClass & SC_REGISTER) == 0) {
Error ("Illegal storage class");
SymEntry* Sym = FindLocalSym (Decl.Ident);
if (Sym) {
/* Check if we already changed the type for this
- * parameter
- */
+ ** parameter
+ */
if (Sym->Flags & SC_DEFTYPE) {
/* Found it, change the default type to the one given */
ChangeSymType (Sym, ParamTypeCvt (Decl.Type));
}
/* Allow parameters without a name, but remember if we had some to
- * eventually print an error message later.
- */
+ ** eventually print an error message later.
+ */
ParseDecl (&Spec, &Decl, DM_ACCEPT_IDENT);
if (Decl.Ident[0] == '\0') {
/* Unnamed symbol. Generate a name that is not user accessible,
- * then handle the symbol normal.
- */
+ ** then handle the symbol normal.
+ */
AnonName (Decl.Ident, "param");
F->Flags |= FD_UNNAMED_PARAMS;
}
/* Skip right paren. We must explicitly check for one here, since some of
- * the breaks above bail out without checking.
- */
+ ** the breaks above bail out without checking.
+ */
ConsumeRParen ();
}
} else if (CurTok.Tok == TOK_IDENT &&
(NextTok.Tok == TOK_COMMA || NextTok.Tok == TOK_RPAREN)) {
/* If the identifier is a typedef, we have a new style parameter list,
- * if it's some other identifier, it's an old style parameter list.
- */
+ ** if it's some other identifier, it's an old style parameter list.
+ */
Sym = FindSym (CurTok.Ident);
if (Sym == 0 || !SymIsTypeDef (Sym)) {
/* Old style (K&R) function. */
}
/* Remember the last function parameter. We need it later for several
- * purposes, for example when passing stuff to fastcall functions. Since
- * more symbols are added to the table, it is easier if we remember it
- * now, since it is currently the last entry in the symbol table.
- */
+ ** purposes, for example when passing stuff to fastcall functions. Since
+ ** more symbols are added to the table, it is easier if we remember it
+ ** now, since it is currently the last entry in the symbol table.
+ */
F->LastParam = GetSymTab()->SymTail;
/* Assign offsets. If the function has a variable parameter list,
- * there's one additional byte (the arg size).
- */
+ ** there's one additional byte (the arg size).
+ */
Offs = (F->Flags & FD_VARIADIC)? 1 : 0;
Sym = F->LastParam;
while (Sym) {
/* Recursively process declarators. Build a type array in reverse order. */
{
/* Read optional function or pointer qualifiers. These modify the
- * identifier or token to the right. For convenience, we allow the fastcall
- * qualifier also for pointers here. If it is a pointer-to-function, the
- * qualifier will later be transfered to the function itself. If it's a
- * pointer to something else, it will be flagged as an error.
- */
+ ** identifier or token to the right. For convenience, we allow the fastcall
+ ** qualifier also for pointers here. If it is a pointer-to-function, the
+ ** qualifier will later be transfered to the function itself. If it's a
+ ** pointer to something else, it will be flagged as an error.
+ */
TypeCode Qualifiers = OptionalQualifiers (T_QUAL_ADDRSIZE | T_QUAL_FASTCALL);
/* Pointer to something */
ConsumeRParen ();
} else {
/* Things depend on Mode now:
- * - Mode == DM_NEED_IDENT means:
- * we *must* have a type and a variable identifer.
- * - Mode == DM_NO_IDENT means:
- * we must have a type but no variable identifer
- * (if there is one, it's not read).
- * - Mode == DM_ACCEPT_IDENT means:
- * we *may* have an identifier. If there is an identifier,
- * it is read, but it is no error, if there is none.
- */
+ ** - Mode == DM_NEED_IDENT means:
+ ** we *must* have a type and a variable identifer.
+ ** - Mode == DM_NO_IDENT means:
+ ** we must have a type but no variable identifer
+ ** (if there is one, it's not read).
+ ** - Mode == DM_ACCEPT_IDENT means:
+ ** we *may* have an identifier. If there is an identifier,
+ ** it is read, but it is no error, if there is none.
+ */
if (Mode == DM_NO_IDENT) {
D->Ident[0] = '\0';
} else if (CurTok.Tok == TOK_IDENT) {
if ((Spec->Flags & DS_DEF_TYPE) != 0 &&
RetType[0].C == T_INT && RetType[1].C == T_END) {
/* Function has an implicit int return. Output a warning if we don't
- * have the C89 standard enabled explicitly.
- */
+ ** have the C89 standard enabled explicitly.
+ */
if (IS_Get (&Standard) >= STD_C99) {
Warning ("Implicit `int' return type is an obsolete feature");
}
}
/* For anthing that is not a function or typedef, check for an implicit
- * int declaration.
- */
+ ** int declaration.
+ */
if ((D->StorageClass & SC_FUNC) != SC_FUNC &&
(D->StorageClass & SC_TYPEMASK) != SC_TYPEDEF) {
/* If the standard was not set explicitly to C89, print a warning
- * for variables with implicit int type.
- */
+ ** for variables with implicit int type.
+ */
if ((Spec->Flags & DS_DEF_TYPE) != 0 && IS_Get (&Standard) >= STD_C99) {
Warning ("Implicit `int' is an obsolete feature");
}
void CheckEmptyDecl (const DeclSpec* D)
/* Called after an empty type declaration (that is, a type declaration without
- * a variable). Checks if the declaration does really make sense and issues a
- * warning if not.
- */
+** a variable). Checks if the declaration does really make sense and issues a
+** warning if not.
+*/
{
if ((D->Flags & DS_EXTRA_TYPE) == 0) {
Warning ("Useless declaration");
static void SkipInitializer (unsigned BracesExpected)
/* Skip the remainder of an initializer in case of errors. Try to be somewhat
- * smart so we don't have too many following errors.
- */
+** smart so we don't have too many following errors.
+*/
{
while (CurTok.Tok != TOK_CEOF && CurTok.Tok != TOK_SEMI && BracesExpected > 0) {
switch (CurTok.Tok) {
static unsigned OpeningCurlyBraces (unsigned BracesNeeded)
/* Accept any number of opening curly braces around an initialization, skip
- * them and return the number. If the number of curly braces is less than
- * BracesNeeded, issue a warning.
- */
+** them and return the number. If the number of curly braces is less than
+** BracesNeeded, issue a warning.
+*/
{
unsigned BraceCount = 0;
while (CurTok.Tok == TOK_LCURLY) {
static void ClosingCurlyBraces (unsigned BracesExpected)
/* Accept and skip the given number of closing curly braces together with
- * an optional comma. Output an error messages, if the input does not contain
- * the expected number of braces.
- */
+** an optional comma. Output an error messages, if the input does not contain
+** the expected number of braces.
+*/
{
while (BracesExpected) {
if (CurTok.Tok == TOK_RCURLY) {
case E_LOC_REGISTER:
/* Register variable. Taking the address is usually not
- * allowed.
- */
+ ** allowed.
+ */
if (IS_Get (&AllowRegVarAddr) == 0) {
Error ("Cannot take the address of a register variable");
}
static void ParseScalarInitInternal (Type* T, ExprDesc* ED)
/* Parse initializaton for scalar data types. This function will not output the
- * data but return it in ED.
- */
+** data but return it in ED.
+*/
{
/* Optional opening brace */
unsigned BraceCount = OpeningCurlyBraces (0);
/* We warn if an initializer for a scalar contains braces, because this is
- * quite unusual and often a sign for some problem in the input.
- */
+ ** quite unusual and often a sign for some problem in the input.
+ */
if (BraceCount > 0) {
Warning ("Braces around scalar initializer");
}
int NeedParen;
/* If we initializer is enclosed in brackets, remember this fact and
- * skip the opening bracket.
- */
+ ** skip the opening bracket.
+ */
NeedParen = (CurTok.Tok == TOK_LCURLY);
if (NeedParen) {
NextToken ();
TranslateLiteral (CurTok.SVal);
/* If the array is one too small for the string literal, omit the
- * trailing zero.
- */
+ ** trailing zero.
+ */
Count = GetLiteralSize (CurTok.SVal);
if (ElementCount != UNSPECIFIED &&
ElementCount != FLEXIBLE &&
NextToken ();
/* If the initializer was enclosed in curly braces, we need a closing
- * one.
- */
+ ** one.
+ */
if (NeedParen) {
ConsumeRCurly ();
}
Count = 0;
while (CurTok.Tok != TOK_RCURLY) {
/* Flexible array members may not be initialized within
- * an array (because the size of each element may differ
- * otherwise).
- */
+ ** an array (because the size of each element may differ
+ ** otherwise).
+ */
ParseInitInternal (ElementType, 0);
++Count;
if (CurTok.Tok != TOK_COMMA)
ElementCount = Count;
} else if (ElementCount == FLEXIBLE && AllowFlexibleMembers) {
/* In non ANSI mode, allow initialization of flexible array
- * members.
- */
+ ** members.
+ */
ElementCount = Count;
} else if (Count < ElementCount) {
g_zerobytes ((ElementCount - Count) * ElementSize);
SI.Size = Entry->V.S.Size;
/* Check if this struct definition has a field table. If it doesn't, it
- * is an incomplete definition.
- */
+ ** is an incomplete definition.
+ */
Tab = Entry->V.S.SymTab;
if (Tab == 0) {
Error ("Cannot initialize variables with incomplete type");
}
/* Parse initialization of one field. Bit-fields need a special
- * handling.
- */
+ ** handling.
+ */
if (SymIsBitField (Entry)) {
ExprDesc ED;
SI.Offs * CHAR_BITS + SI.ValBits);
/* This may be an anonymous bit-field, in which case it doesn't
- * have an initializer.
- */
+ ** have an initializer.
+ */
if (IsAnonName (Entry->Name)) {
/* Account for the data and output it if we have a full word */
SI.ValBits += Entry->V.B.BitWidth;
goto NextMember;
} else {
/* Read the data, check for a constant integer, do a range
- * check.
- */
+ ** check.
+ */
ParseScalarInitInternal (type_uint, &ED);
if (!ED_IsConstAbsInt (&ED)) {
Error ("Constant initializer expected");
} else {
/* Standard member. We should never have stuff from a
- * bit-field left
- */
+ ** bit-field left
+ */
CHECK (SI.ValBits == 0);
/* Flexible array members may only be initialized if they are
- * the last field (or part of the last struct field).
- */
+ ** the last field (or part of the last struct field).
+ */
SI.Offs += ParseInitInternal (Entry->Type, AllowFlexibleMembers && Entry->NextSym == 0);
}
}
/* Return the actual number of bytes initialized. This number may be
- * larger than sizeof (Struct) if flexible array members are present and
- * were initialized (possible in non ANSI mode).
- */
+ ** larger than sizeof (Struct) if flexible array members are present and
+ ** were initialized (possible in non ANSI mode).
+ */
return SI.Offs;
}
static unsigned ParseVoidInit (void)
/* Parse an initialization of a void variable (special cc65 extension).
- * Return the number of bytes initialized.
- */
+** Return the number of bytes initialized.
+*/
{
ExprDesc Expr;
unsigned Size;
/* Parse initialization of variables. Return the number of data bytes. */
{
/* Parse the initialization. Flexible array members can only be initialized
- * in cc65 mode.
- */
+ ** in cc65 mode.
+ */
unsigned Size = ParseInitInternal (T, IS_Get (&Standard) == STD_CC65);
/* The initialization may not generate code on global level, because code
- * outside function scope will never get executed.
- */
+ ** outside function scope will never get executed.
+ */
if (HaveGlobalCode ()) {
Error ("Non constant initializers");
RemoveGlobalCode ();
void CheckEmptyDecl (const DeclSpec* D);
/* Called after an empty type declaration (that is, a type declaration without
- * a variable). Checks if the declaration does really make sense and issues a
- * warning if not.
- */
+** a variable). Checks if the declaration does really make sense and issues a
+** warning if not.
+*/
unsigned ParseInit (Type* T);
/* Parse initialization of variables. Return the number of initialized data
- * bytes.
- */
+** bytes.
+*/
static const AttrDesc* FindAttribute (const char* Attr)
/* Search the attribute and return the corresponding attribute descriptor.
- * Return NULL if the attribute name is not known.
- */
+** Return NULL if the attribute name is not known.
+*/
{
unsigned A;
}
/* If a comma follows, there's a next attribute. Otherwise this is the
- * end of the attribute list.
- */
+ ** end of the attribute list.
+ */
if (CurTok.Tok != TOK_COMMA) {
break;
}
IntStack* FindWarning (const char* Name)
/* Search for a warning in the WarnMap table and return a pointer to the
- * intstack that holds its state. Return NULL if there is no such warning.
- */
+** intstack that holds its state. Return NULL if there is no such warning.
+*/
{
unsigned I;
IntStack* FindWarning (const char* Name);
/* Search for a warning in the WarnMap table and return a pointer to the
- * intstack that holds its state. Return NULL if there is no such warning.
- */
+** intstack that holds its state. Return NULL if there is no such warning.
+*/
void ListWarnings (FILE* F);
/* Print a list of warning types/names to the given file */
/* expr.c
- *
- * Ullrich von Bassewitz, 21.06.1998
- */
+**
+** Ullrich von Bassewitz, 21.06.1998
+*/
/* Call the expression function */
(*Func) (Expr);
- /* Do some checks if code generation is still constistent */
+ /* Do some checks to see if code generation is still consistent */
if (StackPtr != OldSP) {
if (Debug) {
Error ("Code generation messed up: "
void MarkedExprWithCheck (void (*Func) (ExprDesc*), ExprDesc* Expr)
/* Call an expression function with checks and record start and end of the
- * generated code.
- */
+** generated code.
+*/
{
CodeMark Start, End;
GetCodePos (&Start);
/* In an expression with two ints, return the type of the result */
{
/* Rules for integer types:
- * - If one of the values is a long, the result is long.
- * - If one of the values is unsigned, the result is also unsigned.
- * - Otherwise the result is an int.
- */
+ ** - If one of the values is a long, the result is long.
+ ** - If one of the values is unsigned, the result is also unsigned.
+ ** - Otherwise the result is an int.
+ */
if (IsTypeLong (lhst) || IsTypeLong (rhst)) {
if (IsSignUnsigned (lhst) || IsSignUnsigned (rhst)) {
return type_ulong;
static unsigned typeadjust (ExprDesc* lhs, ExprDesc* rhs, int NoPush)
/* Adjust the two values for a binary operation. lhs is expected on stack or
- * to be constant, rhs is expected to be in the primary register or constant.
- * The function will put the type of the result into lhs and return the
- * code generator flags for the operation.
- * If NoPush is given, it is assumed that the operation does not expect the lhs
- * to be on stack, and that lhs is in a register instead.
- * Beware: The function does only accept int types.
- */
+** to be constant, rhs is expected to be in the primary register or constant.
+** The function will put the type of the result into lhs and return the
+** code generator flags for the operation.
+** If NoPush is given, it is assumed that the operation does not expect the lhs
+** to be on stack, and that lhs is in a register instead.
+** Beware: The function does only accept int types.
+*/
{
unsigned ltype, rtype;
unsigned flags;
static int TypeSpecAhead (void)
/* Return true if some sort of type is waiting (helper for cast and sizeof()
- * in hie10).
- */
+** in hie10).
+*/
{
SymEntry* Entry;
/* There's a type waiting if:
- *
- * We have an opening paren, and
- * a. the next token is a type, or
- * b. the next token is a type qualifier, or
- * c. the next token is a typedef'd type
- */
+ **
+ ** We have an opening paren, and
+ ** a. the next token is a type, or
+ ** b. the next token is a type qualifier, or
+ ** c. the next token is a typedef'd type
+ */
return CurTok.Tok == TOK_LPAREN && (
TokIsType (&NextTok) ||
TokIsTypeQual (&NextTok) ||
void PushAddr (const ExprDesc* Expr)
/* If the expression contains an address that was somehow evaluated,
- * push this address on the stack. This is a helper function for all
- * sorts of implicit or explicit assignment functions where the lvalue
- * must be saved if it's not constant, before evaluating the rhs.
- */
+** push this address on the stack. This is a helper function for all
+** sorts of implicit or explicit assignment functions where the lvalue
+** must be saved if it's not constant, before evaluating the rhs.
+*/
{
/* Get the address on stack if needed */
if (ED_IsLocExpr (Expr)) {
static void WarnConstCompareResult (void)
/* If the result of a comparison is constant, this is suspicious when not in
- * preprocessor mode.
- */
+** preprocessor mode.
+*/
{
if (!Preprocessing && IS_Get (&WarnConstComparison) != 0) {
Warning ("Result of comparison is constant");
static unsigned FunctionParamList (FuncDesc* Func, int IsFastcall)
/* Parse a function parameter list and pass the parameters to the called
- * function. Depending on several criteria this may be done by just pushing
- * each parameter separately, or creating the parameter frame once and then
- * storing into this frame.
- * The function returns the size of the parameters pushed.
- */
+** function. Depending on several criteria this may be done by just pushing
+** each parameter separately, or creating the parameter frame once and then
+** storing into this frame.
+** The function returns the size of the parameters pushed.
+*/
{
ExprDesc Expr;
int Ellipsis = 0; /* Function is variadic */
/* As an optimization, we may allocate the complete parameter frame at
- * once instead of pushing each parameter as it comes. We may do that,
- * if...
- *
- * - optimizations that increase code size are enabled (allocating the
- * stack frame at once gives usually larger code).
- * - we have more than one parameter to push (don't count the last param
- * for __fastcall__ functions).
- *
- * The FrameSize variable will contain a value > 0 if storing into a frame
- * (instead of pushing) is enabled.
- *
- */
+ ** once instead of pushing each parameter as it comes. We may do that,
+ ** if...
+ **
+ ** - optimizations that increase code size are enabled (allocating the
+ ** stack frame at once gives usually larger code).
+ ** - we have more than one parameter to push (don't count the last param
+ ** for __fastcall__ functions).
+ **
+ ** The FrameSize variable will contain a value > 0 if storing into a frame
+ ** (instead of pushing) is enabled.
+ **
+ */
if (IS_Get (&CodeSizeFactor) >= 200) {
/* Calculate the number and size of the parameters */
/* Fetch the pointer to the next argument, check for too many args */
if (ParamCount <= Func->ParamCount) {
/* Beware: If there are parameters with identical names, they
- * cannot go into the same symbol table, which means that in this
- * case of errorneous input, the number of nodes in the symbol
- * table and ParamCount are NOT equal. We have to handle this case
- * below to avoid segmentation violations. Since we know that this
- * problem can only occur if there is more than one parameter,
- * we will just use the last one.
- */
+ ** cannot go into the same symbol table, which means that in this
+ ** case of errorneous input, the number of nodes in the symbol
+ ** table and ParamCount are NOT equal. We have to handle this case
+ ** below to avoid segmentation violations. Since we know that this
+ ** problem can only occur if there is more than one parameter,
+ ** we will just use the last one.
+ */
if (ParamCount == 1) {
/* First argument */
Param = Func->SymTab->SymHead;
Error ("Too many arguments in function call");
}
/* Assume an ellipsis even in case of errors to avoid an error
- * message for each other argument.
- */
+ ** message for each other argument.
+ */
Ellipsis = 1;
}
hie1 (&Expr);
/* If we don't have an argument spec, accept anything, otherwise
- * convert the actual argument to the type needed.
- */
+ ** convert the actual argument to the type needed.
+ */
Flags = CF_NONE;
if (!Ellipsis) {
} else {
/* No prototype available. Convert array to "pointer to first
- * element", and function to "pointer to function".
- */
+ ** element", and function to "pointer to function".
+ */
Expr.Type = PtrConversion (Expr.Type);
}
unsigned ArgSize = sizeofarg (Flags);
if (FrameSize > 0) {
/* We have the space already allocated, store in the frame.
- * Because of invalid type conversions (that have produced an
- * error before), we can end up here with a non aligned stack
- * frame. Since no output will be generated anyway, handle
- * these cases gracefully instead of doing a CHECK.
- */
+ ** Because of invalid type conversions (that have produced an
+ ** error before), we can end up here with a non-aligned stack
+ ** frame. Since no output will be generated anyway, handle
+ ** these cases gracefully instead of doing a CHECK.
+ */
if (FrameSize >= ArgSize) {
FrameSize -= ArgSize;
} else {
}
/* The function returns the size of all parameters pushed onto the stack.
- * However, if there are parameters missing (which is an error and was
- * flagged by the compiler) AND a stack frame was preallocated above,
- * we would loose track of the stackpointer and generate an internal error
- * later. So we correct the value by the parameters that should have been
- * pushed to avoid an internal compiler error. Since an error was
- * generated before, no code will be output anyway.
- */
+ ** However, if there are parameters missing (which is an error and was
+ ** flagged by the compiler) AND a stack frame was preallocated above,
+ ** we would loose track of the stackpointer and generate an internal error
+ ** later. So we correct the value by the parameters that should have been
+ ** pushed to avoid an internal compiler error. Since an error was
+ ** generated before, no code will be output anyway.
+ */
return ParamSize + FrameSize;
}
unsigned ParamSize; /* Number of parameter bytes */
CodeMark Mark;
int PtrOffs = 0; /* Offset of function pointer on stack */
- int IsFastcall = 0; /* True if it's a fast call function */
+ int IsFastcall = 0; /* True if it's a fast-call function */
int PtrOnStack = 0; /* True if a pointer copy is on stack */
/* Skip the left paren */
IsFastcall = IsQualFastcall (Expr->Type + 1) && (Func->ParamCount > 0);
/* Things may be difficult, depending on where the function pointer
- * resides. If the function pointer is an expression of some sort
- * (not a local or global variable), we have to evaluate this
- * expression now and save the result for later. Since calls to
- * function pointers may be nested, we must save it onto the stack.
- * For fastcall functions we do also need to place a copy of the
- * pointer on stack, since we cannot use a/x.
- */
+ ** resides. If the function pointer is an expression of some sort
+ ** (not a local or global variable), we have to evaluate this
+ ** expression now and save the result for later. Since calls to
+ ** function pointers may be nested, we must save it onto the stack.
+ ** For fastcall functions we do also need to place a copy of the
+ ** pointer on stack, since we cannot use a/x.
+ */
PtrOnStack = IsFastcall || !ED_IsConst (Expr);
if (PtrOnStack) {
/* Not a global or local variable, or a fastcall function. Load
- * the pointer into the primary and mark it as an expression.
- */
+ ** the pointer into the primary and mark it as an expression.
+ */
LoadExpr (CF_NONE, Expr);
ED_MakeRValExpr (Expr);
if (IsFuncPtr) {
/* If the function is not a fastcall function, load the pointer to
- * the function into the primary.
- */
+ ** the function into the primary.
+ */
if (!IsFastcall) {
/* Not a fastcall function - we may use the primary */
if (PtrOnStack) {
/* If we have no parameters, the pointer is still in the
- * primary. Remove the code to push it and correct the
- * stack pointer.
- */
+ ** primary. Remove the code to push it and correct the
+ ** stack pointer.
+ */
if (ParamSize == 0) {
RemoveCode (&Mark);
PtrOnStack = 0;
} else {
/* Fastcall function. We cannot use the primary for the function
- * pointer and must therefore use an offset to the stack location.
- * Since fastcall functions may never be variadic, we can use the
- * index register for this purpose.
- */
+ ** pointer and must therefore use an offset to the stack location.
+ ** Since fastcall functions may never be variadic, we can use the
+ ** index register for this purpose.
+ */
g_callind (CF_LOCAL, ParamSize, PtrOffs);
}
}
/* Process parenthesized subexpression by calling the whole parser
- * recursively.
- */
+ ** recursively.
+ */
if (CurTok.Tok == TOK_LPAREN) {
NextToken ();
hie0 (E);
}
/* If we run into an identifier in preprocessing mode, we assume that this
- * is an undefined macro and replace it by a constant value of zero.
- */
+ ** is an undefined macro and replace it by a constant value of zero.
+ */
if (Preprocessing && CurTok.Tok == TOK_IDENT) {
NextToken ();
ED_MakeConstAbsInt (E, 0);
}
/* All others may only be used if the expression evaluation is not called
- * recursively by the preprocessor.
- */
+ ** recursively by the preprocessor.
+ */
if (Preprocessing) {
/* Illegal expression in PP mode */
Error ("Preprocessor expression expected");
E->Name = (unsigned long) Sym->Name;
} else if ((Sym->Flags & SC_AUTO) == SC_AUTO) {
/* Local variable. If this is a parameter for a variadic
- * function, we have to add some address calculations, and the
- * address is not const.
- */
+ ** function, we have to add some address calculations, and the
+ ** address is not const.
+ */
if ((Sym->Flags & SC_PARAM) == SC_PARAM && F_IsVariadic (CurrentFunc)) {
/* Variadic parameter */
g_leavariadic (Sym->V.Offs - F_GetParamSize (CurrentFunc));
}
/* We've made all variables lvalues above. However, this is
- * not always correct: An array is actually the address of its
- * first element, which is a rvalue, and a function is a
- * rvalue, too, because we cannot store anything in a function.
- * So fix the flags depending on the type.
- */
+ ** not always correct: An array is actually the address of its
+ ** first element, which is a rvalue, and a function is a
+ ** rvalue, too, because we cannot store anything in a function.
+ ** So fix the flags depending on the type.
+ */
if (IsTypeArray (E->Type) || IsTypeFunc (E->Type)) {
ED_MakeRVal (E);
}
/* IDENT is either an auto-declared function or an undefined variable. */
if (CurTok.Tok == TOK_LPAREN) {
/* C99 doesn't allow calls to undefined functions, so
- * generate an error and otherwise a warning. Declare a
- * function returning int. For that purpose, prepare a
- * function signature for a function having an empty param
- * list and returning int.
- */
+ ** generate an error and otherwise a warning. Declare a
+ ** function returning int. For that purpose, prepare a
+ ** function signature for a function having an empty param
+ ** list and returning int.
+ */
if (IS_Get (&Standard) >= STD_C99) {
Error ("Call to undefined function `%s'", Ident);
} else {
default:
/* Illegal primary. Be sure to skip the token to avoid endless
- * error loops.
- */
+ ** error loops.
+ */
Error ("Expression expected");
NextToken ();
ED_MakeConstAbsInt (E, 1);
tptr1 = Expr->Type;
/* We can apply a special treatment for arrays that have a const base
- * address. This is true for most arrays and will produce a lot better
- * code. Check if this is a const base address.
- */
+ ** address. This is true for most arrays and will produce a lot better
+ ** code. Check if this is a const base address.
+ */
ConstBaseAddr = ED_IsRVal (Expr) &&
(ED_IsLocConst (Expr) || ED_IsLocStack (Expr));
LoadExpr (CF_NONE, Expr);
/* Get the array pointer on stack. Do not push more than 16
- * bit, even if this value is greater, since we cannot handle
- * other than 16bit stuff when doing indexing.
- */
+ ** bit, even if this value is greater, since we cannot handle
+ ** other than 16bit stuff when doing indexing.
+ */
GetCodePos (&Mark2);
g_push (CF_PTR, 0);
}
MarkedExprWithCheck (hie0, &Subscript);
/* Check the types of array and subscript. We can either have a
- * pointer/array to the left, in which case the subscript must be of an
- * integer type, or we have an integer to the left, in which case the
- * subscript must be a pointer/array.
- * Since we do the necessary checking here, we can rely later on the
- * correct types.
- */
+ ** pointer/array to the left, in which case the subscript must be of an
+ ** integer type, or we have an integer to the left, in which case the
+ ** subscript must be a pointer/array.
+ ** Since we do the necessary checking here, we can rely later on the
+ ** correct types.
+ */
Qualifiers = T_QUAL_NONE;
if (IsClassPtr (Expr->Type)) {
if (!IsClassInt (Subscript.Type)) {
if (!IsClassPtr (Subscript.Type)) {
Error ("Subscripted value is neither array nor pointer");
/* To avoid compiler errors, make the subscript a char[] at
- * address 0.
- */
+ ** address 0.
+ */
ED_MakeConstAbs (&Subscript, 0, GetCharArrayType (1));
} else if (IsTypeArray (Subscript.Type)) {
Qualifiers = GetQualifier (Subscript.Type);
} else {
Error ("Cannot subscript");
/* To avoid compiler errors, fake both the array and the subscript, so
- * we can just proceed.
- */
+ ** we can just proceed.
+ */
ED_MakeConstAbs (Expr, 0, GetCharArrayType (1));
ED_MakeConstAbsInt (&Subscript, 0);
ElementType = Indirect (Expr->Type);
}
/* The element type has the combined qualifiers from itself and the array,
- * it is a member of (if any).
- */
+ ** it is a member of (if any).
+ */
if (GetQualifier (ElementType) != (GetQualifier (ElementType) | Qualifiers)) {
ElementType = TypeDup (ElementType);
ElementType->C |= Qualifiers;
if (ED_IsConstAbs (&Subscript) && ED_CodeRangeIsEmpty (&Subscript)) {
/* The array subscript is a numeric constant. If we had pushed the
- * array base address onto the stack before, we can remove this value,
- * since we can generate expression+offset.
- */
+ ** array base address onto the stack before, we can remove this value,
+ ** since we can generate expression+offset.
+ */
if (!ConstBaseAddr) {
RemoveCode (&Mark2);
} else {
if (IsClassPtr (Expr->Type)) {
/* Lhs is pointer/array. Scale the subscript value according to
- * the element size.
- */
+ ** the element size.
+ */
Subscript.IVal *= CheckedSizeOf (ElementType);
/* Remove the address load code */
RemoveCode (&Mark1);
/* In case of an array, we can adjust the offset of the expression
- * already in Expr. If the base address was a constant, we can even
- * remove the code that loaded the address into the primary.
- */
+ ** already in Expr. If the base address was a constant, we can even
+ ** remove the code that loaded the address into the primary.
+ */
if (IsTypeArray (Expr->Type)) {
/* Adjust the offset */
} else {
/* It's a pointer, so we do have to load it into the primary
- * first (if it's not already there).
- */
+ ** first (if it's not already there).
+ */
if (ConstBaseAddr || ED_IsLVal (Expr)) {
LoadExpr (CF_NONE, Expr);
ED_MakeRValExpr (Expr);
g_scale (TypeOf (tptr1), CheckedSizeOf (ElementType));
/* Add the subscript. Since arrays are indexed by integers,
- * we will ignore the true type of the subscript here and
- * use always an int. #### Use offset but beware of LoadExpr!
- */
+ ** we will ignore the true type of the subscript here and
+ ** use always an int. #### Use offset but beware of LoadExpr!
+ */
g_inc (CF_INT | CF_CONST, Subscript.IVal);
}
if (IsClassPtr (Expr->Type)) {
/* Indexing is based on unsigneds, so we will just use the integer
- * portion of the index (which is in (e)ax, so there's no further
- * action required).
- */
+ ** portion of the index (which is in (e)ax, so there's no further
+ ** action required).
+ */
g_scale (CF_INT, CheckedSizeOf (ElementType));
} else {
/* Get the int value on top. If we come here, we're sure, both
- * values are 16 bit (the first one was truncated if necessary
- * and the second one is a pointer). Note: If ConstBaseAddr is
- * true, we don't have a value on stack, so to "swap" both, just
- * push the subscript.
- */
+ ** values are 16 bit (the first one was truncated if necessary
+ ** and the second one is a pointer). Note: If ConstBaseAddr is
+ ** true, we don't have a value on stack, so to "swap" both, just
+ ** push the subscript.
+ */
if (ConstBaseAddr) {
g_push (CF_INT, 0);
LoadExpr (CF_NONE, Expr);
}
/* The offset is now in the primary register. It we didn't have a
- * constant base address for the lhs, the lhs address is already
- * on stack, and we must add the offset. If the base address was
- * constant, we call special functions to add the address to the
- * offset value.
- */
+ ** constant base address for the lhs, the lhs address is already
+ ** on stack, and we must add the offset. If the base address was
+ ** constant, we call special functions to add the address to the
+ ** offset value.
+ */
if (!ConstBaseAddr) {
/* The array base address is on stack and the subscript is in the
- * primary. Add both.
- */
+ ** primary. Add both.
+ */
g_add (CF_INT, 0);
} else {
/* The subscript is in the primary, and the array base address is
- * in Expr. If the subscript has itself a constant address, it is
- * often a better idea to reverse again the order of the
- * evaluation. This will generate better code if the subscript is
- * a byte sized variable. But beware: This is only possible if the
- * subscript was not scaled, that is, if this was a byte array
- * or pointer.
- */
+ ** in Expr. If the subscript has itself a constant address, it is
+ ** often a better idea to reverse again the order of the
+ ** evaluation. This will generate better code if the subscript is
+ ** a byte sized variable. But beware: This is only possible if the
+ ** subscript was not scaled, that is, if this was a byte array
+ ** or pointer.
+ */
if ((ED_IsLocConst (&Subscript) || ED_IsLocStack (&Subscript)) &&
CheckedSizeOf (ElementType) == SIZEOF_CHAR) {
Expr->Type = ElementType;
/* An array element is actually a variable. So the rules for variables
- * with respect to the reference type apply: If it's an array, it is
- * a rvalue, otherwise it's an lvalue. (A function would also be a rvalue,
- * but an array cannot contain functions).
- */
+ ** with respect to the reference type apply: If it's an array, it is
+ ** a rvalue, otherwise it's an lvalue. (A function would also be a rvalue,
+ ** but an array cannot contain functions).
+ */
if (IsTypeArray (Expr->Type)) {
ED_MakeRVal (Expr);
} else {
}
/* If we have a struct pointer that is an lvalue and not already in the
- * primary, load it now.
- */
+ ** primary, load it now.
+ */
if (ED_IsLVal (Expr) && IsTypePtr (Expr->Type)) {
/* Load into the primary */
}
/* A struct is usually an lvalue. If not, it is a struct in the primary
- * register.
- */
+ ** register.
+ */
if (ED_IsRVal (Expr) && ED_IsLocExpr (Expr) && !IsTypePtr (Expr->Type)) {
unsigned Flags = 0;
}
/* Generate a shift to get the field in the proper position in the
- * primary. For bit fields, mask the value.
- */
+ ** primary. For bit fields, mask the value.
+ */
BitOffs = Field->V.Offs * CHAR_BITS;
if (SymIsBitField (Field)) {
BitOffs += Field->V.B.BitOffs;
g_asr (Flags, BitOffs);
/* Mask the value. This is unnecessary if the shift executed above
- * moved only zeroes into the value.
- */
+ ** moved only zeroes into the value.
+ */
if (BitOffs + Field->V.B.BitWidth != Size * CHAR_BITS) {
g_and (CF_INT | CF_UNSIGNED | CF_CONST,
(0x0001U << Field->V.B.BitWidth) - 1U);
Expr->Type = FinalType;
/* An struct member is actually a variable. So the rules for variables
- * with respect to the reference type apply: If it's an array, it is
- * a rvalue, otherwise it's an lvalue. (A function would also be a rvalue,
- * but a struct field cannot be a function).
- */
+ ** with respect to the reference type apply: If it's an array, it is
+ ** a rvalue, otherwise it's an lvalue. (A function would also be a rvalue,
+ ** but a struct field cannot be a function).
+ */
if (IsTypeArray (Expr->Type)) {
ED_MakeRVal (Expr);
} else {
/* Not a function */
Error ("Illegal function call");
/* Force the type to be a implicitly defined function, one
- * returning an int and taking any number of arguments.
- * Since we don't have a name, invent one.
- */
+ ** returning an int and taking any number of arguments.
+ ** Since we don't have a name, invent one.
+ */
ED_MakeConstAbs (Expr, 0, GetImplicitFuncType ());
Expr->Name = (long) IllegalFunc;
}
void Store (ExprDesc* Expr, const Type* StoreType)
/* Store the primary register into the location denoted by Expr. If StoreType
- * is given, use this type when storing instead of Expr->Type. If StoreType
- * is NULL, use Expr->Type instead.
- */
+** is given, use this type when storing instead of Expr->Type. If StoreType
+** is NULL, use Expr->Type instead.
+*/
{
unsigned Flags;
ExprWithCheck (hie10, Expr);
if (ED_IsLVal (Expr) || !(ED_IsLocConst (Expr) || ED_IsLocStack (Expr))) {
/* Not a const, load it into the primary and make it a
- * calculated value.
- */
+ ** calculated value.
+ */
LoadExpr (CF_NONE, Expr);
ED_MakeRValExpr (Expr);
}
/* If the expression is already a pointer to function, the
- * additional dereferencing operator must be ignored. A function
- * itself is represented as "pointer to function", so any number
- * of dereference operators is legal, since the result will
- * always be converted to "pointer to function".
- */
+ ** additional dereferencing operator must be ignored. A function
+ ** itself is represented as "pointer to function", so any number
+ ** of dereference operators is legal, since the result will
+ ** always be converted to "pointer to function".
+ */
if (IsTypeFuncPtr (Expr->Type) || IsTypeFunc (Expr->Type)) {
/* Expression not storable */
ED_MakeRVal (Expr);
NextToken ();
ExprWithCheck (hie10, Expr);
/* The & operator may be applied to any lvalue, and it may be
- * applied to functions, even if they're no lvalues.
- */
+ ** applied to functions, even if they're no lvalues.
+ */
if (ED_IsRVal (Expr) && !IsTypeFunc (Expr->Type) && !IsTypeArray (Expr->Type)) {
Error ("Illegal address");
} else {
GetCodePos (&Mark);
hie10 (Expr);
/* If the expression is a literal string, release it, so it
- * won't be output as data if not used elsewhere.
- */
+ ** won't be output as data if not used elsewhere.
+ */
if (ED_IsLocLiteral (Expr)) {
ReleaseLiteral (Expr->LVal);
}
/* Constant value */
GetCodePos (&Mark2);
/* If the operator is commutative, don't push the left side, if
- * it's a constant, since we will exchange both operands.
- */
+ ** it's a constant, since we will exchange both operands.
+ */
if ((Gen->Flags & GEN_COMM) == 0) {
g_push (ltype | CF_CONST, Expr->IVal);
}
} else if (lconst && (Gen->Flags & GEN_COMM) && !rconst) {
/* The left side is constant, the right side is not, and the
- * operator allows swapping the operands. We haven't pushed the
- * left side onto the stack in this case, and will reverse the
- * operation because this allows for better code.
- */
+ ** operator allows swapping the operands. We haven't pushed the
+ ** left side onto the stack in this case, and will reverse the
+ ** operation because this allows for better code.
+ */
unsigned rtype = ltype | CF_CONST;
ltype = TypeOf (Expr2.Type); /* Expr2 is now left */
type = CF_CONST;
} else {
/* If the right hand side is constant, and the generator function
- * expects the lhs in the primary, remove the push of the primary
- * now.
- */
+ ** expects the lhs in the primary, remove the push of the primary
+ ** now.
+ */
unsigned rtype = TypeOf (Expr2.Type);
type = 0;
if (rconst) {
} else if (IsClassPtr (Expr->Type)) {
if (IsClassPtr (Expr2.Type)) {
/* Both pointers are allowed in comparison if they point to
- * the same type, or if one of them is a void pointer.
- */
+ ** the same type, or if one of them is a void pointer.
+ */
Type* left = Indirect (Expr->Type);
Type* right = Indirect (Expr2.Type);
if (TypeCmp (left, right) < TC_EQUAL && left->C != T_VOID && right->C != T_VOID) {
if (ED_IsConstAbs (Expr) && rconst) {
/* If the result is constant, this is suspicious when not in
- * preprocessor mode.
- */
+ ** preprocessor mode.
+ */
WarnConstCompareResult ();
/* Both operands are constant, remove the generated code */
int RightSigned = IsSignSigned (Expr2.Type);
/* If the right hand side is constant, and the generator function
- * expects the lhs in the primary, remove the push of the primary
- * now.
- */
+ ** expects the lhs in the primary, remove the push of the primary
+ ** now.
+ */
unsigned flags = 0;
if (rconst) {
flags |= CF_CONST;
if (IsTypeChar (Expr->Type) && rconst) {
/* Left side is unsigned char, right side is constant.
- * Determine the minimum and maximum values
- */
+ ** Determine the minimum and maximum values
+ */
int LeftMin, LeftMax;
if (LeftSigned) {
LeftMin = -128;
LeftMax = 255;
}
/* An integer value is always represented as a signed in the
- * ExprDesc structure. This may lead to false results below,
- * if it is actually unsigned, but interpreted as signed
- * because of the representation. Fortunately, in this case,
- * the actual value doesn't matter, since it's always greater
- * than what can be represented in a char. So correct the
- * value accordingly.
- */
+ ** ExprDesc structure. This may lead to false results below,
+ ** if it is actually unsigned, but interpreted as signed
+ ** because of the representation. Fortunately, in this case,
+ ** the actual value doesn't matter, since it's always greater
+ ** than what can be represented in a char. So correct the
+ ** value accordingly.
+ */
if (!RightSigned && Expr2.IVal < 0) {
/* Correct the value so it is an unsigned. It will then
- * anyway match one of the cases below.
- */
+ ** anyway match one of the cases below.
+ */
Expr2.IVal = LeftMax + 1;
}
/* Comparing a char against a constant may have a constant
- * result. Please note: It is not possible to remove the code
- * for the compare alltogether, because it may have side
- * effects.
- */
+ ** result. Please note: It is not possible to remove the code
+ ** for the compare alltogether, because it may have side
+ ** effects.
+ */
switch (Tok) {
case TOK_EQ:
}
/* If the result is not already constant (as evaluated in the
- * switch above), we can execute the operation as a char op,
- * since the right side constant is in a valid range.
- */
+ ** switch above), we can execute the operation as a char op,
+ ** since the right side constant is in a valid range.
+ */
flags |= (CF_CHAR | CF_FORCECHAR);
if (!LeftSigned) {
flags |= CF_UNSIGNED;
GetSignedness (Expr->Type) == GetSignedness (Expr2.Type)) {
/* Both are chars with the same signedness. We can encode the
- * operation as a char operation.
- */
+ ** operation as a char operation.
+ */
flags |= CF_CHAR;
if (rconst) {
flags |= CF_FORCECHAR;
}
/* If the left side is an unsigned and the right is a constant,
- * we may be able to change the compares to something more
- * effective.
- */
+ ** we may be able to change the compares to something more
+ ** effective.
+ */
if (!LeftSigned && rconst) {
switch (Tok) {
case TOK_LT:
if (Expr2.IVal == 1) {
/* An unsigned compare to one means that the value
- * must be zero.
- */
+ ** must be zero.
+ */
GenFunc = g_eq;
Expr2.IVal = 0;
}
case TOK_LE:
if (Expr2.IVal == 0) {
/* An unsigned compare to zero means that the value
- * must be zero.
- */
+ ** must be zero.
+ */
GenFunc = g_eq;
}
break;
case TOK_GE:
if (Expr2.IVal == 1) {
/* An unsigned compare to one means that the value
- * must not be zero.
- */
+ ** must not be zero.
+ */
GenFunc = g_ne;
Expr2.IVal = 0;
}
case TOK_GT:
if (Expr2.IVal == 0) {
/* An unsigned compare to zero means that the value
- * must not be zero.
- */
+ ** must not be zero.
+ */
GenFunc = g_ne;
}
break;
static void parseadd (ExprDesc* Expr)
/* Parse an expression with the binary plus operator. Expr contains the
- * unprocessed left hand side of the expression and will contain the
- * result of the expression on return.
- */
+** unprocessed left hand side of the expression and will contain the
+** result of the expression on return.
+*/
{
ExprDesc Expr2;
unsigned flags; /* Operation flags */
} else {
/* lhs is a constant and rhs is not constant. Load rhs into
- * the primary.
- */
+ ** the primary.
+ */
LoadExpr (CF_NONE, &Expr2);
/* Beware: The check above (for lhs) lets not only pass numeric
- * constants, but also constant addresses (labels), maybe even
- * with an offset. We have to check for that here.
- */
+ ** constants, but also constant addresses (labels), maybe even
+ ** with an offset. We have to check for that here.
+ */
/* First, get the rhs type. */
rhst = Expr2.Type;
Expr->Type = Expr2.Type;
/* Since we do already have rhs in the primary, if lhs is
- * not a numeric constant, and the scale factor is not one
- * (no scaling), we must take the long way over the stack.
- */
+ ** not a numeric constant, and the scale factor is not one
+ ** (no scaling), we must take the long way over the stack.
+ */
if (ED_IsLocAbs (Expr)) {
/* Numeric constant, scale lhs */
Expr->IVal *= ScaleFactor;
Expr->Type = Expr2.Type;
} else if (IsClassInt (lhst) && IsClassInt (rhst)) {
/* Integer addition. Note: Result is never constant.
- * Problem here is that typeadjust does not know if the
- * variable is an rvalue or lvalue, so if both operands
- * are dereferenced constant numeric addresses, typeadjust
- * thinks the operation works on constants. Removing
- * CF_CONST here means handling the symptoms, however, the
- * whole parser is such a mess that I fear to break anything
- * when trying to apply another solution.
- */
+ ** Problem here is that typeadjust does not know if the
+ ** variable is an rvalue or lvalue, so if both operands
+ ** are dereferenced constant numeric addresses, typeadjust
+ ** thinks the operation works on constants. Removing
+ ** CF_CONST here means handling the symptoms, however, the
+ ** whole parser is such a mess that I fear to break anything
+ ** when trying to apply another solution.
+ */
flags = typeadjust (Expr, &Expr2, 0) & ~CF_CONST;
} else {
/* OOPS */
static void parsesub (ExprDesc* Expr)
/* Parse an expression with the binary minus operator. Expr contains the
- * unprocessed left hand side of the expression and will contain the
- * result of the expression on return.
- */
+** unprocessed left hand side of the expression and will contain the
+** result of the expression on return.
+*/
{
ExprDesc Expr2;
unsigned flags; /* Operation flags */
} else {
/* Left hand side is not constant, right hand side is.
- * Remove pushed value from stack.
- */
+ ** Remove pushed value from stack.
+ */
RemoveCode (&Mark2);
if (IsClassPtr (lhst) && IsClassInt (rhst)) {
Expr->Type = type_int;
} else if (IsClassInt (lhst) && IsClassInt (rhst)) {
/* Integer subtraction. If the left hand side descriptor says that
- * the lhs is const, we have to remove this mark, since this is no
- * longer true, lhs is on stack instead.
- */
+ ** the lhs is const, we have to remove this mark, since this is no
+ ** longer true, lhs is on stack instead.
+ */
if (ED_IsLocAbs (Expr)) {
ED_MakeRValExpr (Expr);
}
static void hieAndPP (ExprDesc* Expr)
/* Process "exp && exp" in preprocessor mode (that is, when the parser is
- * called recursively from the preprocessor.
- */
+** called recursively from the preprocessor.
+*/
{
ExprDesc Expr2;
static void hieOrPP (ExprDesc *Expr)
/* Process "exp || exp" in preprocessor mode (that is, when the parser is
- * called recursively from the preprocessor.
- */
+** called recursively from the preprocessor.
+*/
{
ExprDesc Expr2;
LoadExpr (CF_FORCECHAR, Expr);
/* For each expression jump to TrueLab if true. Beware: If we
- * had && operators, the jump is already in place!
- */
+ ** had && operators, the jump is already in place!
+ */
if (!BoolOp) {
g_truejump (CF_NONE, TrueLab);
}
g_falsejump (CF_NONE, FalseLab);
/* Parse second expression. Remember for later if it is a NULL pointer
- * expression, then load it into the primary.
- */
+ ** expression, then load it into the primary.
+ */
ExprWithCheck (hie1, &Expr2);
Expr2IsNULL = ED_IsNullPtr (&Expr2);
if (!IsTypeVoid (Expr2.Type)) {
g_defcodelabel (FalseLab);
/* Parse third expression. Remember for later if it is a NULL pointer
- * expression, then load it into the primary.
- */
+ ** expression, then load it into the primary.
+ */
ExprWithCheck (hie1, &Expr3);
Expr3IsNULL = ED_IsNullPtr (&Expr3);
if (!IsTypeVoid (Expr3.Type)) {
}
/* Check if any conversions are needed, if so, do them.
- * Conversion rules for ?: expression are:
- * - if both expressions are int expressions, default promotion
- * rules for ints apply.
- * - if both expressions are pointers of the same type, the
- * result of the expression is of this type.
- * - if one of the expressions is a pointer and the other is
- * a zero constant, the resulting type is that of the pointer
- * type.
- * - if both expressions are void expressions, the result is of
- * type void.
- * - all other cases are flagged by an error.
- */
+ ** Conversion rules for ?: expression are:
+ ** - if both expressions are int expressions, default promotion
+ ** rules for ints apply.
+ ** - if both expressions are pointers of the same type, the
+ ** result of the expression is of this type.
+ ** - if one of the expressions is a pointer and the other is
+ ** a zero constant, the resulting type is that of the pointer
+ ** type.
+ ** - if both expressions are void expressions, the result is of
+ ** type void.
+ ** - all other cases are flagged by an error.
+ */
if (IsClassInt (Expr2.Type) && IsClassInt (Expr3.Type)) {
CodeMark CvtCodeStart;
TypeConversion (&Expr3, ResultType);
/* Emit conversion code for the second expression, but remember
- * where it starts end ends.
- */
+ ** where it starts end ends.
+ */
GetCodePos (&CvtCodeStart);
TypeConversion (&Expr2, ResultType);
GetCodePos (&CvtCodeEnd);
if (!IsClassInt (Expr->Type) && !IsTypePtr (Expr->Type)) {
Error ("Invalid left operand type");
/* Continue. Wrong code will be generated, but the compiler won't
- * break, so this is the best error recovery.
- */
+ ** break, so this is the best error recovery.
+ */
}
/* Skip the operator token */
if (!IsClassInt (Expr2.Type)) {
Error ("Invalid right operand for binary operator `%s'", Op);
/* Continue. Wrong code will be generated, but the compiler won't
- * break, so this is the best error recovery.
- */
+ ** break, so this is the best error recovery.
+ */
}
/* Check for a constant expression */
if (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)) {
/* The resulting value is a constant. If the generator has the NOPUSH
- * flag set, don't push the lhs.
- */
+ ** flag set, don't push the lhs.
+ */
if (Gen->Flags & GEN_NOPUSH) {
RemoveCode (&Mark);
}
}
/* If the lhs is character sized, the operation may be later done
- * with characters.
- */
+ ** with characters.
+ */
if (CheckedSizeOf (Expr->Type) == SIZEOF_CHAR) {
flags |= CF_FORCECHAR;
}
}
/* If the lhs is character sized, the operation may be later done
- * with characters.
- */
+ ** with characters.
+ */
if (CheckedSizeOf (Expr->Type) == SIZEOF_CHAR) {
flags |= CF_FORCECHAR;
}
if (!IsClassInt (Expr->Type) && !IsTypePtr (Expr->Type)) {
Error ("Invalid left operand type");
/* Continue. Wrong code will be generated, but the compiler won't
- * break, so this is the best error recovery.
- */
+ ** break, so this is the best error recovery.
+ */
}
/* Skip the operator */
rflags = 0;
/* Evaluate the rhs. We expect an integer here, since float is not
- * supported
- */
+ ** supported
+ */
hie1 (&Expr2);
if (!IsClassInt (Expr2.Type)) {
Error ("Invalid right operand for binary operator `%s'", Op);
/* Continue. Wrong code will be generated, but the compiler won't
- * break, so this is the best error recovery.
- */
+ ** break, so this is the best error recovery.
+ */
}
if (ED_IsConstAbs (&Expr2)) {
/* The resulting value is a constant. Scale it. */
int evalexpr (unsigned Flags, void (*Func) (ExprDesc*), ExprDesc* Expr)
/* Will evaluate an expression via the given function. If the result is a
- * constant, 0 is returned and the value is put in the Expr struct. If the
- * result is not constant, LoadExpr is called to bring the value into the
- * primary register and 1 is returned.
- */
+** constant, 0 is returned and the value is put in the Expr struct. If the
+** result is not constant, LoadExpr is called to bring the value into the
+** primary register and 1 is returned.
+*/
{
/* Evaluate */
ExprWithCheck (Func, Expr);
void ConstExpr (void (*Func) (ExprDesc*), ExprDesc* Expr)
/* Will evaluate an expression via the given function. If the result is not
- * a constant of some sort, a diagnostic will be printed, and the value is
- * replaced by a constant one to make sure there are no internal errors that
- * result from this input error.
- */
+** a constant of some sort, a diagnostic will be printed, and the value is
+** replaced by a constant one to make sure there are no internal errors that
+** result from this input error.
+*/
{
ExprWithCheck (Func, Expr);
if (!ED_IsConst (Expr)) {
void BoolExpr (void (*Func) (ExprDesc*), ExprDesc* Expr)
/* Will evaluate an expression via the given function. If the result is not
- * something that may be evaluated in a boolean context, a diagnostic will be
- * printed, and the value is replaced by a constant one to make sure there
- * are no internal errors that result from this input error.
- */
+** something that may be evaluated in a boolean context, a diagnostic will be
+** printed, and the value is replaced by a constant one to make sure there
+** are no internal errors that result from this input error.
+*/
{
ExprWithCheck (Func, Expr);
if (!ED_IsBool (Expr)) {
void ConstAbsIntExpr (void (*Func) (ExprDesc*), ExprDesc* Expr)
/* Will evaluate an expression via the given function. If the result is not
- * a constant numeric integer value, a diagnostic will be printed, and the
- * value is replaced by a constant one to make sure there are no internal
- * errors that result from this input error.
- */
+** a constant numeric integer value, a diagnostic will be printed, and the
+** value is replaced by a constant one to make sure there are no internal
+** errors that result from this input error.
+*/
{
ExprWithCheck (Func, Expr);
if (!ED_IsConstAbsInt (Expr)) {
/*
- * expr.h
- *
- * Ullrich von Bassewitz, 21.06.1998
- */
+** expr.h
+**
+** Ullrich von Bassewitz, 21.06.1998
+*/
void MarkedExprWithCheck (void (*Func) (ExprDesc*), ExprDesc* Expr);
/* Call an expression function with checks and record start and end of the
- * generated code.
- */
+** generated code.
+*/
void PushAddr (const ExprDesc* Expr);
/* If the expression contains an address that was somehow evaluated,
- * push this address on the stack. This is a helper function for all
- * sorts of implicit or explicit assignment functions where the lvalue
- * must be saved if it's not constant, before evaluating the rhs.
- */
+** push this address on the stack. This is a helper function for all
+** sorts of implicit or explicit assignment functions where the lvalue
+** must be saved if it's not constant, before evaluating the rhs.
+*/
void Store (ExprDesc* Expr, const Type* StoreType);
/* Store the primary register into the location denoted by lval. If StoreType
- * is given, use this type when storing instead of lval->Type. If StoreType
- * is NULL, use lval->Type instead.
- */
+** is given, use this type when storing instead of lval->Type. If StoreType
+** is NULL, use lval->Type instead.
+*/
int evalexpr (unsigned flags, void (*Func) (ExprDesc*), ExprDesc* Expr);
/* Will evaluate an expression via the given function. If the result is a
- * constant, 0 is returned and the value is put in the Expr struct. If the
- * result is not constant, LoadExpr is called to bring the value into the
- * primary register and 1 is returned.
- */
+** constant, 0 is returned and the value is put in the Expr struct. If the
+** result is not constant, LoadExpr is called to bring the value into the
+** primary register and 1 is returned.
+*/
void Expression0 (ExprDesc* Expr);
/* Evaluate an expression via hie0 and put the result into the primary register */
void ConstExpr (void (*Func) (ExprDesc*), ExprDesc* Expr);
/* Will evaluate an expression via the given function. If the result is not
- * a constant of some sort, a diagnostic will be printed, and the value is
- * replaced by a constant one to make sure there are no internal errors that
- * result from this input error.
- */
+** a constant of some sort, a diagnostic will be printed, and the value is
+** replaced by a constant one to make sure there are no internal errors that
+** result from this input error.
+*/
void BoolExpr (void (*Func) (ExprDesc*), ExprDesc* Expr);
/* Will evaluate an expression via the given function. If the result is not
- * something that may be evaluated in a boolean context, a diagnostic will be
- * printed, and the value is replaced by a constant one to make sure there
- * are no internal errors that result from this input error.
- */
+** something that may be evaluated in a boolean context, a diagnostic will be
+** printed, and the value is replaced by a constant one to make sure there
+** are no internal errors that result from this input error.
+*/
void ConstAbsIntExpr (void (*Func) (ExprDesc*), ExprDesc* Expr);
/* Will evaluate an expression via the given function. If the result is not
- * a constant numeric integer value, a diagnostic will be printed, and the
- * value is replaced by a constant one to make sure there are no internal
- * errors that result from this input error.
- */
+** a constant numeric integer value, a diagnostic will be printed, and the
+** value is replaced by a constant one to make sure there are no internal
+** errors that result from this input error.
+*/
void hie10 (ExprDesc* lval);
/* Handle ++, --, !, unary - etc. */
const char* ED_GetLabelName (const ExprDesc* Expr, long Offs)
/* Return the assembler label name of the given expression. Beware: This
- * function may use a static buffer, so the name may get "lost" on the second
- * call to the function.
- */
+** function may use a static buffer, so the name may get "lost" on the second
+** call to the function.
+*/
{
static StrBuf Buf = STATIC_STRBUF_INITIALIZER;
int ED_GetStackOffs (const ExprDesc* Expr, int Offs)
/* Get the stack offset of an address on the stack in Expr taking into account
- * an additional offset in Offs.
- */
+** an additional offset in Offs.
+*/
{
PRECONDITION (ED_IsLocStack (Expr));
Offs += ((int) Expr->IVal) - StackPtr;
ExprDesc* ED_MakeRValExpr (ExprDesc* Expr)
/* Convert Expr into a rvalue which is in the primary register without an
- * offset.
- */
+** offset.
+*/
{
Expr->Sym = 0;
Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE | E_BITFIELD | E_NEED_TEST | E_CC_SET);
ExprDesc* ED_MakeLValExpr (ExprDesc* Expr)
/* Convert Expr into a lvalue which is in the primary register without an
- * offset.
- */
+** offset.
+*/
{
Expr->Sym = 0;
Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE | E_BITFIELD | E_NEED_TEST | E_CC_SET);
int ED_IsConst (const ExprDesc* Expr)
/* Return true if the expression denotes a constant of some sort. This can be a
- * numeric constant, the address of a global variable (maybe with offset) or
- * similar.
- */
+** numeric constant, the address of a global variable (maybe with offset) or
+** similar.
+*/
{
return ED_IsRVal (Expr) && (Expr->Flags & E_LOC_CONST) != 0;
}
int ED_IsBool (const ExprDesc* Expr)
/* Return true of the expression can be treated as a boolean, that is, it can
- * be an operand to a compare operation.
- */
+** be an operand to a compare operation.
+*/
{
/* Either ints, floats, or pointers can be used in a boolean context */
return IsClassInt (Expr->Type) ||
const char* ED_GetLabelName (const ExprDesc* Expr, long Offs);
/* Return the assembler label name of the given expression. Beware: This
- * function may use a static buffer, so the name may get "lost" on the second
- * call to the function.
- */
+** function may use a static buffer, so the name may get "lost" on the second
+** call to the function.
+*/
int ED_GetStackOffs (const ExprDesc* Expr, int Offs);
/* Get the stack offset of an address on the stack in Expr taking into account
- * an additional offset in Offs.
- */
+** an additional offset in Offs.
+*/
ExprDesc* ED_MakeConstAbs (ExprDesc* Expr, long Value, Type* Type);
/* Make Expr an absolute const with the given value and type. */
ExprDesc* ED_MakeRValExpr (ExprDesc* Expr);
/* Convert Expr into a rvalue which is in the primary register without an
- * offset.
- */
+** offset.
+*/
ExprDesc* ED_MakeLValExpr (ExprDesc* Expr);
/* Convert Expr into a lvalue which is in the primary register without an
- * offset.
- */
+** offset.
+*/
int ED_IsConst (const ExprDesc* Expr);
/* Return true if the expression denotes a constant of some sort. This can be a
- * numeric constant, the address of a global variable (maybe with offset) or
- * similar.
- */
+** numeric constant, the address of a global variable (maybe with offset) or
+** similar.
+*/
#if defined(HAVE_INLINE)
INLINE int ED_IsConstAbs (const ExprDesc* Expr)
/* Return true if the expression denotes a constant absolute value. This can be
- * a numeric constant, cast to any type.
- */
+** a numeric constant, cast to any type.
+*/
{
return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL);
}
int ED_IsBool (const ExprDesc* Expr);
/* Return true of the expression can be treated as a boolean, that is, it can
- * be an operand to a compare operation.
- */
+** be an operand to a compare operation.
+*/
void PrintExprDesc (FILE* F, ExprDesc* Expr);
/* Print an ExprDesc */
int F_ReserveLocalSpace (Function* F, unsigned Size)
/* Reserve (but don't allocate) the given local space and return the stack
- * offset.
- */
+** offset.
+*/
{
F->Reserved += Size;
return StackPtr - F->Reserved;
int F_GetStackPtr (const Function* F)
/* Return the current stack pointer including reserved (but not allocated)
- * space on the stack.
- */
+** space on the stack.
+*/
{
return StackPtr - F->Reserved;
}
void F_AllocLocalSpace (Function* F)
/* Allocate any local space previously reserved. The function will do
- * nothing if there is no reserved local space.
- */
+** nothing if there is no reserved local space.
+*/
{
if (F->Reserved > 0) {
int F_AllocRegVar (Function* F, const Type* Type)
/* Allocate a register variable for the given variable type. If the allocation
- * was successful, return the offset of the register variable in the register
- * bank (zero page storage). If there is no register space left, return -1.
- */
+** was successful, return the offset of the register variable in the register
+** bank (zero page storage). If there is no register space left, return -1.
+*/
{
/* Allow register variables only on top level and if enabled */
if (IS_Get (&EnableRegVars) && GetLexicalLevel () == LEX_LEVEL_FUNCTION) {
/* Do we have space left? */
if (F->RegOffs >= Size) {
/* Space left. We allocate the variables from high to low addresses,
- * so the adressing is compatible with the saved values on stack.
- * This allows shorter code when saving/restoring the variables.
- */
+ ** so the addressing is compatible with the saved values on stack.
+ ** This allows shorter code when saving/restoring the variables.
+ */
F->RegOffs -= Size;
return F->RegOffs;
}
ReenterFunctionLevel (D);
/* Check if the function header contains unnamed parameters. These are
- * only allowed in cc65 mode.
- */
+ ** only allowed in cc65 mode.
+ */
if ((D->Flags & FD_UNNAMED_PARAMS) != 0 && (IS_Get (&Standard) != STD_CC65)) {
Error ("Parameter name omitted");
}
/* Declare two special functions symbols: __fixargs__ and __argsize__.
- * The latter is different depending on the type of the function (variadic
- * or not).
- */
+ ** The latter is different depending on the type of the function (variadic
+ ** or not).
+ */
AddConstSym ("__fixargs__", type_uint, SC_DEF | SC_CONST, D->ParamSize);
if (D->Flags & FD_VARIADIC) {
/* Variadic function. The variable must be const. */
}
/* If cc65 extensions aren't enabled, don't allow a main function that
- * doesn't return an int.
- */
+ ** doesn't return an int.
+ */
if (IS_Get (&Standard) != STD_CC65 && CurrentFunc->ReturnType[0].C != T_INT) {
Error ("`main' must always return an int");
}
/* Add a forced import of a symbol that is contained in the startup
- * code. This will force the startup code to be linked in.
- */
+ ** code. This will force the startup code to be linked in.
+ */
g_importstartup ();
/* If main() takes parameters, generate a forced import to a function
- * that will setup these parameters. This way, programs that do not
- * need the additional code will not get it.
- */
+ ** that will setup these parameters. This way, programs that do not
+ ** need the additional code will not get it.
+ */
if (D->ParamCount > 0 || (D->Flags & FD_VARIADIC) != 0) {
g_importmainargs ();
}
/* Determine if this is a main function in a C99 environment that
- * returns an int.
- */
+ ** returns an int.
+ */
if (IsTypeInt (F_GetReturnType (CurrentFunc)) &&
IS_Get (&Standard) == STD_C99) {
C99MainFunc = 1;
StackPtr = 0;
/* Walk through the parameter list and allocate register variable space
- * for parameters declared as register. Generate code to swap the contents
- * of the register bank with the save area on the stack.
- */
+ ** for parameters declared as register. Generate code to swap the contents
+ ** of the register bank with the save area on the stack.
+ */
Param = D->SymTab->SymHead;
while (Param && (Param->Flags & SC_PARAM) != 0) {
DeclareLocals ();
/* Remember the current stack pointer. All variables allocated elsewhere
- * must be dropped when doing a return from an inner block.
- */
+ ** must be dropped when doing a return from an inner block.
+ */
CurrentFunc->TopLevelSP = StackPtr;
/* Now process statements in this block */
}
/* If this is not a void function, and not the main function in a C99
- * environment returning int, output a warning if we didn't see a return
- * statement.
- */
+ ** environment returning int, output a warning if we didn't see a return
+ ** statement.
+ */
if (!F_HasVoidReturn (CurrentFunc) && !F_HasReturn (CurrentFunc) && !C99MainFunc) {
Warning ("Control reaches end of non-void function");
}
/* If this is the main function in a C99 environment returning an int, let
- * it always return zero. Note: Actual return statements jump to the return
- * label defined below.
- * The code is removed by the optimizer if unused.
- */
+ ** it always return zero. Note: Actual return statements jump to the return
+ ** label defined below.
+ ** The code is removed by the optimizer if unused.
+ */
if (C99MainFunc) {
g_getimmed (CF_INT | CF_CONST, 0, 0);
}
int F_ReserveLocalSpace (Function* F, unsigned Size);
/* Reserve (but don't allocate) the given local space and return the stack
- * offset.
- */
+** offset.
+*/
int F_GetStackPtr (const Function* F);
/* Return the current stack pointer including reserved (but not allocated)
- * space on the stack.
- */
+** space on the stack.
+*/
void F_AllocLocalSpace (Function* F);
/* Allocate any local space previously reserved. The function will do
- * nothing if there is no reserved local space.
- */
+** nothing if there is no reserved local space.
+*/
int F_AllocRegVar (Function* F, const Type* Type);
/* Allocate a register variable for the given variable type. If the allocation
- * was successful, return the offset of the register variable in the register
- * bank (zero page storage). If there is no register space left, return -1.
- */
+** was successful, return the offset of the register variable in the register
+** bank (zero page storage). If there is no register space left, return -1.
+*/
void NewFunc (struct SymEntry* Func);
/* Parse argument declarations and function body. */
unsigned HexVal (int C)
/* Convert a hex digit into a value. The function will emit an error for
- * invalid hex digits.
- */
+** invalid hex digits.
+*/
{
if (!IsXDigit (C)) {
Error ("Invalid hexadecimal digit: `%c'", C);
unsigned HexVal (int C);
/* Convert a hex digit into a value. The function will emit an error for
- * invalid hex digits.
- */
+** invalid hex digits.
+*/
static AFile* NewAFile (IFile* IF, FILE* F)
/* Create a new AFile, push it onto the stack, add the path of the file to
- * the path search list, and finally return a pointer to the new AFile struct.
- */
+** the path search list, and finally return a pointer to the new AFile struct.
+*/
{
StrBuf Path = AUTO_STRBUF_INITIALIZER;
AF->Input = IF;
/* Increment the usage counter of the corresponding IFile. If this
- * is the first use, set the file data and output debug info if
- * requested.
- */
+ ** is the first use, set the file data and output debug info if
+ ** requested.
+ */
if (IF->Usage++ == 0) {
/* Get file size and modification time. There a race condition here,
- * since we cannot use fileno() (non standard identifier in standard
- * header file), and therefore not fstat. When using stat with the
- * file name, there's a risk that the file was deleted and recreated
- * while it was open. Since mtime and size are only used to check
- * if a file has changed in the debugger, we will ignore this problem
- * here.
- */
+ ** since we cannot use fileno() (non standard identifier in standard
+ ** header file), and therefore not fstat. When using stat with the
+ ** file name, there's a risk that the file was deleted and recreated
+ ** while it was open. Since mtime and size are only used to check
+ ** if a file has changed in the debugger, we will ignore this problem
+ ** here.
+ */
struct stat Buf;
if (FileStat (IF->Name, &Buf) != 0) {
/* Error */
CollAppend (&AFiles, AF);
/* Get the path of this file and add it as an extra search path.
- * To avoid file search overhead, we will add one path only once.
- * This is checked by the PushSearchPath function.
- */
+ ** To avoid file search overhead, we will add one path only once.
+ ** This is checked by the PushSearchPath function.
+ */
SB_CopyBuf (&Path, IF->Name, FindName (IF->Name) - IF->Name);
SB_Terminate (&Path);
AF->SearchPath = PushSearchPath (UsrIncSearchPath, SB_GetConstBuf (&Path));
static IFile* FindFile (const char* Name)
/* Find the file with the given name in the list of all files. Since the list
- * is not large (usually less than 10), I don't care about using hashes or
- * similar things and do a linear search.
- */
+** is not large (usually less than 10), I don't care about using hashes or
+** similar things and do a linear search.
+*/
{
unsigned I;
for (I = 0; I < CollCount (&IFiles); ++I) {
Line = NewStrBuf ();
/* Update the line infos, so we have a valid line info even at start of
- * the main file before the first line is read.
- */
+ ** the main file before the first line is read.
+ */
UpdateLineInfo (MainFile->Input, MainFile->Line, Line);
}
}
/* Search the list of all input files for this file. If we don't find
- * it, create a new IFile object.
- */
+ ** it, create a new IFile object.
+ */
IF = FindFile (N);
if (IF == 0) {
IF = NewIFile (N, IT);
static void CloseIncludeFile (void)
/* Close an include file and switch to the higher level file. Set Input to
- * NULL if this was the main file.
- */
+** NULL if this was the main file.
+*/
{
AFile* Input;
static void GetInputChar (void)
/* Read the next character from the input stream and make CurC and NextC
- * valid. If end of line is reached, both are set to NUL, no more lines
- * are read by this function.
- */
+** valid. If end of line is reached, both are set to NUL, no more lines
+** are read by this function.
+*/
{
/* Drop all pushed fragments that don't have data left */
while (SB_GetIndex (Line) >= SB_GetLen (Line)) {
void NextChar (void)
/* Skip the current input character and read the next one from the input
- * stream. CurC and NextC are valid after the call. If end of line is
- * reached, both are set to NUL, no more lines are read by this function.
- */
+** stream. CurC and NextC are valid after the call. If end of line is
+** reached, both are set to NUL, no more lines are read by this function.
+*/
{
/* Skip the last character read */
SB_Skip (Line);
StrBuf* InitLine (StrBuf* Buf)
/* Initialize Line from Buf and read CurC and NextC from the new input line.
- * The function returns the old input line.
- */
+** The function returns the old input line.
+*/
{
StrBuf* OldLine = Line;
Line = Buf;
CloseIncludeFile ();
/* If there is no file open, bail out, otherwise get the
- * previous input file and start over.
- */
+ ** previous input file and start over.
+ */
if (CollCount (&AFiles) == 0) {
return 0;
}
++Input->Line;
/* If the \n is preceeded by a \r, remove the \r, so we can read
- * DOS/Windows files under *nix.
- */
+ ** DOS/Windows files under *nix.
+ */
if (SB_LookAtLast (Line) == '\r') {
SB_Drop (Line, 1);
}
/* If we don't have a line continuation character at the end,
- * we're done with this line. Otherwise replace the character
- * by a newline and continue reading.
- */
+ ** we're done with this line. Otherwise replace the character
+ ** by a newline and continue reading.
+ */
if (SB_LookAtLast (Line) == '\\') {
Line->Buf[Line->Len-1] = '\n';
} else {
static void CreateDepFile (const char* Name, InputType Types)
/* Create a dependency file with the given name and place dependencies for
- * all files with the given types there.
- */
+** all files with the given types there.
+*/
{
/* Open the file */
FILE* F = fopen (Name, "w");
}
/* If a dependency target was given, use it, otherwise use the output
- * file name as target, followed by a tab character.
- */
+ ** file name as target, followed by a tab character.
+ */
if (SB_IsEmpty (&DepTarget)) {
WriteEscaped (F, OutputFilename);
} else {
/* An enum that describes different types of input files. The members are
- * choosen so that it is possible to combine them to bitsets
- */
+** choosen so that it is possible to combine them to bitsets
+*/
typedef enum {
IT_MAIN = 0x01, /* Main input file */
IT_SYSINC = 0x02, /* System include file (using <>) */
void NextChar (void);
/* Read the next character from the input stream and make CurC and NextC
- * valid. If end of line is reached, both are set to NUL, no more lines
- * are read by this function.
- */
+** valid. If end of line is reached, both are set to NUL, no more lines
+** are read by this function.
+*/
void ClearLine (void);
/* Clear the current input line */
StrBuf* InitLine (StrBuf* Buf);
/* Initialize Line from Buf and read CurC and NextC from the new input line.
- * The function returns the old input line.
- */
+** The function returns the old input line.
+*/
int NextLine (void);
/* Get a line from the current input. Returns 0 on end of file. */
LI->LineNum = LineNum;
/* Copy the line, replacing tabs by spaces in the given line since tabs
- * will give rather arbitrary results when used in the output later, and
- * if we do it here, we won't need another copy later.
- */
+ ** will give rather arbitrary results when used in the output later, and
+ ** if we do it here, we won't need another copy later.
+ */
T = LI->Line;
while (Len--) {
if (*S == '\t') {
void ReleaseLineInfo (LineInfo* LI)
/* Release a reference to the given line info, free the structure if the
- * reference count drops to zero.
- */
+** reference count drops to zero.
+*/
{
CHECK (LI && LI->RefCount > 0);
if (--LI->RefCount == 0) {
LineInfo* GetCurLineInfo (void)
/* Return a pointer to the current line info. The reference count is NOT
- * increased, use UseLineInfo for that purpose.
- */
+** increased, use UseLineInfo for that purpose.
+*/
{
return CurLineInfo;
}
}
/* If we have intermixed assembly switched off, use an empty line instead
- * of the supplied one to save some memory.
- */
+ ** of the supplied one to save some memory.
+ */
if (!AddSource) {
Line = &EmptyStrBuf;
}
/* The text for the actual line is allocated at the end of the structure, so
- * the size of the structure varies.
- */
+** the size of the structure varies.
+*/
typedef struct LineInfo LineInfo;
struct LineInfo {
unsigned RefCount; /* Reference counter */
void ReleaseLineInfo (LineInfo* LI);
/* Release a reference to the given line info, free the structure if the
- * reference count drops to zero.
- */
+** reference count drops to zero.
+*/
LineInfo* GetCurLineInfo (void);
/* Return a pointer to the current line info. The reference count is NOT
- * increased, use UseLineInfo for that purpose.
- */
+** increased, use UseLineInfo for that purpose.
+*/
void UpdateLineInfo (struct IFile* F, unsigned LineNum, const StrBuf* Line);
/* Update the line info - called if a new line is read */
static LiteralPool* LP = 0;
/* Stack that contains the nested literal pools. Since TOS is in LiteralPool
- * and functions aren't nested in C, the maximum depth is 1. I'm using a
- * collection anyway, so the code is prepared for nested functions or
- * whatever.
- */
+** and functions aren't nested in C, the maximum depth is 1. I'm using a
+** collection anyway, so the code is prepared for nested functions or
+** whatever.
+*/
static Collection LPStack = STATIC_COLLECTION_INITIALIZER;
LiteralPool* PopLiteralPool (void)
/* Pop the last literal pool from TOS and activate it. Return the old
- * literal pool.
- */
+** literal pool.
+*/
{
/* Remember the current literal pool */
LiteralPool* Old = LP;
Literal* L = CollAt (Source, I);
/* If it is referenced and not output, add it to the Target pool,
- * otherwise free it
- */
+ ** otherwise free it
+ */
if (L->RefCount && !L->Output) {
CollAppend (Target, L);
} else {
void MoveLiteralPool (LiteralPool* LocalPool)
/* Move all referenced literals in LocalPool to the global literal pool. This
- * function will free LocalPool after moving the used string literals.
- */
+** function will free LocalPool after moving the used string literals.
+*/
{
/* Move the literals */
MoveLiterals (&LocalPool->WritableLiterals, &GlobalPool->WritableLiterals);
TranslateLiteral (L);
/* Check if this literal is part of another one. Since the literals
- * are sorted by size (larger ones first), it can only be part of a
- * literal with a smaller index.
- * Beware: Only check literals that have actually been referenced.
- */
+ ** are sorted by size (larger ones first), it can only be part of a
+ ** literal with a smaller index.
+ ** Beware: Only check literals that have actually been referenced.
+ */
C = 0;
for (J = 0; J < I; ++J) {
Literal* AddLiteralBuf (const void* Buf, unsigned Len)
/* Add a buffer containing a literal string to the literal pool. Return the
- * literal.
- */
+** literal.
+*/
{
/* Create a new literal */
Literal* L = NewLiteral (Buf, Len);
LiteralPool* PopLiteralPool (void);
/* Pop the last literal pool from TOS and activate it. Return the old
- * literal pool.
- */
+** literal pool.
+*/
void MoveLiteralPool (LiteralPool* LocalPool);
/* Move all referenced literals in LocalPool to the global literal pool. This
- * function will free LocalPool after moving the used string literals.
- */
+** function will free LocalPool after moving the used string literals.
+*/
void OutputLiteralPool (void);
/* Output the literal pool */
Literal* AddLiteralBuf (const void* Buf, unsigned Len);
/* Add a buffer containing a literal string to the literal pool. Return the
- * literal.
- */
+** literal.
+*/
Literal* AddLiteralStr (const StrBuf* S);
/* Add a literal string to the literal pool. Return the literal. */
case E_LOC_REGISTER:
/* Register variable. Taking the address is usually not
- * allowed.
- */
+ ** allowed.
+ */
if (IS_Get (&AllowRegVarAddr) == 0) {
Error ("Cannot take the address of a register variable");
}
if (ED_IsLVal (Expr)) {
/* Dereferenced lvalue. If this is a bit field its type is unsigned.
- * But if the field is completely contained in the lower byte, we will
- * throw away the high byte anyway and may therefore load just the
- * low byte.
- */
+ ** But if the field is completely contained in the lower byte, we will
+ ** throw away the high byte anyway and may therefore load just the
+ ** low byte.
+ */
if (ED_IsBitField (Expr)) {
Flags |= (Expr->BitOffs + Expr->BitWidth <= CHAR_BITS)? CF_CHAR : CF_INT;
Flags |= CF_UNSIGNED;
}
/* Handle bit fields. The actual type may have been casted or
- * converted, so be sure to always use unsigned ints for the
- * operations.
- */
+ ** converted, so be sure to always use unsigned ints for the
+ ** operations.
+ */
if (ED_IsBitField (Expr)) {
unsigned F = CF_INT | CF_UNSIGNED | CF_CONST | (Flags & CF_TEST);
/* Shift right by the bit offset */
if (ED_IsLocExpr (Expr)) {
if (Expr->IVal != 0) {
/* We have an expression in the primary plus a constant
- * offset. Adjust the value in the primary accordingly.
- */
+ ** offset. Adjust the value in the primary accordingly.
+ */
Flags |= TypeOf (Expr->Type);
g_inc (Flags | CF_CONST, Expr->IVal);
}
static void ParseRegisterDecl (Declaration* Decl, int Reg)
/* Parse the declaration of a register variable. Reg is the offset of the
- * variable in the register bank.
- */
+** variable in the register bank.
+*/
{
SymEntry* Sym;
g_save_regvars (Reg, Size);
/* Add the symbol to the symbol table. We do that now, because for register
- * variables the current stack pointer is implicitly used as location for
- * the save area.
- */
+ ** variables the current stack pointer is implicitly used as location for
+ ** the save area.
+ */
Sym = AddLocalSym (Decl->Ident, Decl->Type, Decl->StorageClass, Reg);
/* Check for an optional initialization */
if (IsCompound) {
/* Switch to read only data and define a label for the
- * initialization data.
- */
+ ** initialization data.
+ */
unsigned InitLabel = AllocLabel (g_userodata);
/* Parse the initialization generating a memory image of the
- * data in the RODATA segment. The function does return the size
- * of the initialization data, which may be greater than the
- * actual size of the type, if the type is a structure with a
- * flexible array member that has been initialized. Since we must
- * know the size of the data in advance for register variables,
- * we cannot allow that here.
- */
+ ** data in the RODATA segment. The function does return the size
+ ** of the initialization data, which may be greater than the
+ ** actual size of the type, if the type is a structure with a
+ ** flexible array member that has been initialized. Since we must
+ ** know the size of the data in advance for register variables,
+ ** we cannot allow that here.
+ */
if (ParseInit (Sym->Type) != Size) {
Error ("Cannot initialize flexible array members of storage class `register'");
}
if (IS_Get (&StaticLocals) == 0) {
/* Add the symbol to the symbol table. The stack offset we use here
- * may get corrected later.
- */
+ ** may get corrected later.
+ */
Sym = AddLocalSym (Decl->Ident, Decl->Type,
Decl->StorageClass,
F_GetStackPtr (CurrentFunc) - (int) Size);
if (IsCompound) {
/* Switch to read only data and define a label for the
- * initialization data.
- */
+ ** initialization data.
+ */
unsigned InitLabel = AllocLabel (g_userodata);
/* Parse the initialization generating a memory image of the
- * data in the RODATA segment. The function will return the
- * actual size of the initialization data, which may be
- * greater than the size of the variable if it is a struct
- * that contains a flexible array member and we're not in
- * ANSI mode.
- */
+ ** data in the RODATA segment. The function will return the
+ ** actual size of the initialization data, which may be
+ ** greater than the size of the variable if it is a struct
+ ** that contains a flexible array member and we're not in
+ ** ANSI mode.
+ */
Size = ParseInit (Sym->Type);
/* Now reserve space for the variable on the stack and correct
- * the offset in the symbol table entry.
- */
+ ** the offset in the symbol table entry.
+ */
Sym->V.Offs = F_ReserveLocalSpace (CurrentFunc, Size);
/* Next, allocate the space on the stack. This means that the
- * variable is now located at offset 0 from the current sp.
- */
+ ** variable is now located at offset 0 from the current sp.
+ */
F_AllocLocalSpace (CurrentFunc);
/* Generate code to copy the initialization data into the
- * variable space
- */
+ ** variable space
+ */
g_initauto (InitLabel, Size);
} else {
TypeConversion (&Expr, Sym->Type);
/* If the value is not const, load it into the primary.
- * Otherwise pass the information to the code generator.
- */
+ ** Otherwise pass the information to the code generator.
+ */
if (ED_IsConstAbsInt (&Expr)) {
Flags |= CF_CONST;
} else {
} else {
/* Non-initialized local variable. Just keep track of
- * the space needed.
- */
+ ** the space needed.
+ */
F_ReserveLocalSpace (CurrentFunc, Size);
}
if (IsCompound) {
/* Switch to read only data and define a label for the
- * initialization data.
- */
+ ** initialization data.
+ */
unsigned InitLabel = AllocLabel (g_userodata);
/* Parse the initialization generating a memory image of the
- * data in the RODATA segment.
- */
+ ** data in the RODATA segment.
+ */
Size = ParseInit (Sym->Type);
/* Allocate space for the variable */
if (CurTok.Tok == TOK_ASSIGN) {
/* Initialization ahead, switch to data segment and define the label.
- * For arrays, we need to check the elements of the array for
- * constness, not the array itself.
- */
+ ** For arrays, we need to check the elements of the array for
+ ** constness, not the array itself.
+ */
if (IsQualConst (GetBaseElementType (Sym->Type))) {
g_userodata ();
} else {
}
/* If we don't have a name, this was flagged as an error earlier.
- * To avoid problems later, use an anonymous name here.
- */
+ ** To avoid problems later, use an anonymous name here.
+ */
if (Decl.Ident[0] == '\0') {
AnonName (Decl.Ident, "param");
}
(Decl.StorageClass & SC_TYPEMASK) != SC_TYPEDEF) {
/* If we have a register variable, try to allocate a register and
- * convert the declaration to "auto" if this is not possible.
- */
+ ** convert the declaration to "auto" if this is not possible.
+ */
int Reg = 0; /* Initialize to avoid gcc complains */
if ((Decl.StorageClass & SC_REGISTER) != 0 &&
(Reg = F_AllocRegVar (CurrentFunc, Decl.Type)) < 0) {
while (1) {
/* Check variable declarations. We need to distinguish between a
- * default int type and the end of variable declarations. So we
- * will do the following: If there is no explicit storage class
- * specifier *and* no explicit type given, *and* no type qualifiers
- * have been read, it is assumed that we have reached the end of
- * declarations.
- */
+ ** default int type and the end of variable declarations. So we
+ ** will do the following: If there is no explicit storage class
+ ** specifier *and* no explicit type given, *and* no type qualifiers
+ ** have been read, it is assumed that we have reached the end of
+ ** declarations.
+ */
DeclSpec Spec;
ParseDeclSpec (&Spec, SC_AUTO, T_INT);
if ((Spec.Flags & DS_DEF_STORAGE) != 0 && /* No storage spec */
F_AllocLocalSpace (CurrentFunc);
/* In case we've allocated local variables in this block, emit a call to
- * the stack checking routine if stack checks are enabled.
- */
+ ** the stack checking routine if stack checks are enabled.
+ */
if (IS_Get (&CheckStack) && InitialStack != StackPtr) {
g_cstackcheck ();
}
void RestoreRegVars (int HaveResult);
/* Restore the register variables for the local function if there are any.
- * The parameter tells us if there is a return value in ax, in that case,
- * the accumulator must be saved across the restore.
- */
+** The parameter tells us if there is a return value in ax, in that case,
+** the accumulator must be saved across the restore.
+*/
Macro* NewMacro (const char* Name)
/* Allocate a macro structure with the given name. The structure is not
- * inserted into the macro table.
- */
+** inserted into the macro table.
+*/
{
/* Get the length of the macro name */
unsigned Len = strlen(Name);
void FreeMacro (Macro* M)
/* Delete a macro definition. The function will NOT remove the macro from the
- * table, use UndefineMacro for that.
- */
+** table, use UndefineMacro for that.
+*/
{
unsigned I;
int UndefineMacro (const char* Name)
/* Search for the macro with the given name and remove it from the macro
- * table if it exists. Return 1 if a macro was found and deleted, return
- * 0 otherwise.
- */
+** table if it exists. Return 1 if a macro was found and deleted, return
+** 0 otherwise.
+*/
{
/* Get the hash value of the macro name */
unsigned Hash = HashStr (Name) % MACRO_TAB_SIZE;
int FindMacroArg (Macro* M, const char* Arg)
/* Search for a formal macro argument. If found, return the index of the
- * argument. If the argument was not found, return -1.
- */
+** argument. If the argument was not found, return -1.
+*/
{
unsigned I;
for (I = 0; I < CollCount (&M->FormalArgs); ++I) {
/* Add a formal macro argument. */
{
/* Check if we have a duplicate macro argument, but add it anyway.
- * Beware: Don't use FindMacroArg here, since the actual argument array
- * may not be initialized.
- */
+ ** Beware: Don't use FindMacroArg here, since the actual argument array
+ ** may not be initialized.
+ */
unsigned I;
for (I = 0; I < CollCount (&M->FormalArgs); ++I) {
if (strcmp (CollAtUnchecked (&M->FormalArgs, I), Arg) == 0) {
/* */
/* */
/* (C) 2000-2005, Ullrich von Bassewitz */
-/* Römerstraße 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
Macro* NewMacro (const char* Name);
/* Allocate a macro structure with the given name. The structure is not
- * inserted into the macro table.
- */
+** inserted into the macro table.
+*/
void FreeMacro (Macro* M);
/* Delete a macro definition. The function will NOT remove the macro from the
- * table, use UndefineMacro for that.
- */
+** table, use UndefineMacro for that.
+*/
void DefineNumericMacro (const char* Name, long Val);
/* Define a macro for a numeric constant */
int UndefineMacro (const char* Name);
/* Search for the macro with the given name and remove it from the macro
- * table if it exists. Return 1 if a macro was found and deleted, return
- * 0 otherwise.
- */
+** table if it exists. Return 1 if a macro was found and deleted, return
+** 0 otherwise.
+*/
Macro* FindMacro (const char* Name);
/* Find a macro with the given name. Return the macro definition or NULL */
int FindMacroArg (Macro* M, const char* Arg);
/* Search for a formal macro argument. If found, return the index of the
- * argument. If the argument was not found, return -1.
- */
+** argument. If the argument was not found, return -1.
+*/
void AddMacroArg (Macro* M, const char* Arg);
/* Add a formal macro argument. */
DefineNumericMacro (Def, 1);
} else {
/* We have a value, P points to the '=' character. Since the argument
- * is const, create a copy and replace the '=' in the copy by a zero
- * terminator.
- */
+ ** is const, create a copy and replace the '=' in the copy by a zero
+ ** terminator.
+ */
char* Q;
unsigned Len = strlen (Def)+1;
char* S = (char*) xmalloc (Len);
}
/* Read line by line, ignore empty lines and switch optimization
- * steps on/off.
- */
+ ** steps on/off.
+ */
while (fgets (Buf, sizeof (Buf), F) != 0) {
/* Remove trailing control chars. This will also remove the
- * trailing newline.
- */
+ ** trailing newline.
+ */
unsigned Len = strlen (Buf);
while (Len > 0 && IsControl (Buf[Len-1])) {
--Len;
}
/* Check the first character and enable/disable the step or
- * ignore the line
- */
+ ** ignore the line
+ */
switch (*Line) {
case '\0':
}
/* Close the file, no error check here since we were just reading and
- * this is only a debug function.
- */
+ ** this is only a debug function.
+ */
(void) fclose (F);
}
/* */
/* */
/* (C) 2001-2004 Ullrich von Bassewitz */
-/* Römerstraße 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
OF_SETF | OF_NOIMP /* flags */
},
/* Mark RTI as "uses all registers but doesn't change them", so the
- * optimizer won't remove preceeding loads.
- */
+ ** optimizer won't remove preceeding loads.
+ */
{ OP65_RTI, /* opcode */
"rti", /* mnemonic */
1, /* size */
const OPCDesc* FindOP65 (const char* M)
/* Find the given opcode and return the opcode number. If the opcode was not
- * found, return NULL.
- */
+** found, return NULL.
+*/
{
unsigned I;
unsigned Len;
/* Check the length of the given string, then copy it into local
- * storage, converting it to upper case.
- */
+ ** storage, converting it to upper case.
+ */
char Mnemo[sizeof (OPCTable[0].Mnemo)];
Len = strlen (M);
if (Len >= sizeof (OPCTable[0].Mnemo)) {
unsigned char GetAMUseInfo (am_t AM)
/* Get usage info for the given addressing mode (addressing modes that use
- * index registers return REG_r info for these registers).
- */
+** index registers return REG_r info for these registers).
+*/
{
/* Check the addressing mode. */
switch (AM) {
opc_t MakeShortBranch (opc_t OPC)
/* Return the short version of the given branch. If the branch is already
- * a short branch, return the opcode unchanged.
- */
+** a short branch, return the opcode unchanged.
+*/
{
switch (OPC) {
case OP65_BCC:
opc_t MakeLongBranch (opc_t OPC)
/* Return the long version of the given branch. If the branch is already
- * a long branch, return the opcode unchanged.
- */
+** a long branch, return the opcode unchanged.
+*/
{
switch (OPC) {
case OP65_BCC:
/* */
/* */
/* (C) 2001-2004 Ullrich von Bassewitz */
-/* Römerstraße 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
const OPCDesc* FindOP65 (const char* OPC);
/* Find the given opcode and return the opcode description. If the opcode was
- * not found, NULL is returned.
- */
+** not found, NULL is returned.
+*/
unsigned GetInsnSize (opc_t OPC, am_t AM);
/* Return the size of the given instruction */
unsigned char GetAMUseInfo (am_t AM);
/* Get usage info for the given addressing mode (addressing modes that use
- * index registers return REG_r info for these registers).
- */
+** index registers return REG_r info for these registers).
+*/
opc_t GetInverseBranch (opc_t OPC);
/* Return a branch that reverse the condition of the branch given in OPC */
opc_t MakeShortBranch (opc_t OPC);
/* Return the short version of the given branch. If the branch is already
- * a short branch, return the opcode unchanged.
- */
+** a short branch, return the opcode unchanged.
+*/
opc_t MakeLongBranch (opc_t OPC);
/* Return the long version of the given branch. If the branch is already
- * a long branch, return the opcode unchanged.
- */
+** a long branch, return the opcode unchanged.
+*/
bc_t GetBranchCond (opc_t OPC);
/* Get the condition for the conditional branch in OPC */
void MakeDefaultOutputName (const char* InputFilename)
/* If the name of the output file is empty or NULL, the name of the output
- * file is derived from the input file by adjusting the file name extension.
- */
+** file is derived from the input file by adjusting the file name extension.
+*/
{
if (OutputFilename == 0 || *OutputFilename == '\0') {
/* We don't have an output file for now */
void OpenDebugOutputFile (const char* Name)
/* Open an output file for debugging purposes. Will call Fatal() in case of
- * failures.
- */
+** failures.
+*/
{
/* Output file must not be open and we must have a name*/
PRECONDITION (OutputFile == 0);
int WriteOutput (const char* Format, ...)
/* Write to the output file using printf like formatting. Returns the number
- * of chars written.
- */
+** of chars written.
+*/
{
va_list ap;
int CharCount;
void MakeDefaultOutputName (const char* InputFilename);
/* If the name of the output file is empty or NULL, the name of the output
- * file is derived from the input file by adjusting the file name extension.
- */
+** file is derived from the input file by adjusting the file name extension.
+*/
void OpenOutputFile ();
/* Open the output file. Will call Fatal() in case of failures. */
void OpenDebugOutputFile (const char* Name);
-/* Open an output file for debugging purposes. Will call Fatal() in case of
- * failures.
- */
+/* Open an output file for debugging purposes. Will call Fatal() in case of
+** failures.
+*/
void CloseOutputFile ();
/* Close the output file. Will call Fatal() in case of failures. */
int WriteOutput (const char* Format, ...) attribute ((format (printf, 1, 2)));
/* Write to the output file using printf like formatting. Returns the number
- * of chars written.
- */
+** of chars written.
+*/
/* End of output.h */
static void PragmaErrorSkip (void)
/* Called in case of an error, skips tokens until the closing paren or a
- * semicolon is reached.
- */
+** semicolon is reached.
+*/
{
static const token_t TokenList[] = { TOK_RPAREN, TOK_SEMI };
SkipTokens (TokenList, sizeof(TokenList) / sizeof(TokenList[0]));
static pragma_t FindPragma (const StrBuf* Key)
/* Find a pragma and return the token. Return PRAGMA_ILLEGAL if the keyword is
- * not a valid pragma.
- */
+** not a valid pragma.
+*/
{
struct Pragma* P;
P = bsearch (SB_GetConstBuf (Key), Pragmas, PRAGMA_COUNT, sizeof (Pragmas[0]), CmpKey);
static int GetComma (StrBuf* B)
/* Expects and skips a comma in B. Prints an error and returns zero if no
- * comma is found. Return a value <> 0 otherwise.
- */
+** comma is found. Return a value <> 0 otherwise.
+*/
{
SB_SkipWhite (B);
if (SB_Get (B) != ',') {
static int GetString (StrBuf* B, StrBuf* S)
/* Expects and skips a string in B. Prints an error and returns zero if no
- * string is found. Returns a value <> 0 otherwise.
- */
+** string is found. Returns a value <> 0 otherwise.
+*/
{
if (!SB_GetString (B, S)) {
Error ("String literal expected");
static int GetNumber (StrBuf* B, long* Val)
/* Expects and skips a number in B. Prints an eror and returns zero if no
- * number is found. Returns a value <> 0 otherwise.
- */
+** number is found. Returns a value <> 0 otherwise.
+*/
{
if (!SB_GetNumber (B, Val)) {
Error ("Constant integer expected");
static IntStack* GetWarning (StrBuf* B)
/* Get a warning name from the string buffer. Returns a pointer to the intstack
- * that holds the state of the warning, and NULL in case of errors. The
- * function will output error messages in case of problems.
- */
+** that holds the state of the warning, and NULL in case of errors. The
+** function will output error messages in case of problems.
+*/
{
IntStack* S = 0;
StrBuf W = AUTO_STRBUF_INITIALIZER;
static PushPopResult ParsePushPop (StrBuf* B)
/* Check for and parse the "push" and "pop" keywords. In case of "push", a
- * following comma is expected and skipped.
- */
+** following comma is expected and skipped.
+*/
{
StrBuf Ident = AUTO_STRBUF_INITIALIZER;
PushPopResult Res = PP_NONE;
static int BoolKeyword (StrBuf* Ident)
/* Check if the identifier in Ident is a keyword for a boolean value. Currently
- * accepted are true/false/on/off.
- */
+** accepted are true/false/on/off.
+*/
{
if (SB_CompareStr (Ident, "true") == 0) {
return 1;
/* Do we know this pragma? */
if (Pragma == PRAGMA_ILLEGAL) {
/* According to the ANSI standard, we're not allowed to generate errors
- * for unknown pragmas, but warn about them if enabled (the default).
- */
+ ** for unknown pragmas, but warn about them if enabled (the default).
+ */
if (IS_Get (&WarnUnknownPragma)) {
Warning ("Unknown pragma `%s'", SB_GetConstBuf (&Ident));
}
Error ("String literal expected");
/* Try some smart error recovery: Skip tokens until we reach the
- * enclosing paren, or a semicolon.
- */
+ ** enclosing paren, or a semicolon.
+ */
PragmaErrorSkip ();
} else {
static unsigned Pass1 (StrBuf* Source, StrBuf* Target);
/* Preprocessor pass 1. Remove whitespace. Handle old and new style comments
- * and the "defined" operator.
- */
+** and the "defined" operator.
+*/
static void MacroReplacement (StrBuf* Source, StrBuf* Target);
/* Perform macro replacement. */
static pptoken_t FindPPToken (const char* Ident)
/* Find a preprocessor token and return it. Return PP_ILLEGAL if the identifier
- * is not a valid preprocessor token.
- */
+** is not a valid preprocessor token.
+*/
{
struct PPToken* P;
P = bsearch (Ident, PPTokens, PPTOKEN_COUNT, sizeof (PPTokens[0]), CmpToken);
static void ME_AppendActual (MacroExp* E, StrBuf* Arg)
/* Add a copy of Arg to the list of actual macro arguments.
- * NOTE: This function will clear Arg!
- */
+** NOTE: This function will clear Arg!
+*/
{
/* Create a new string buffer */
StrBuf* A = NewStrBuf ();
static void Stringize (StrBuf* Source, StrBuf* Target)
/* Stringize the given string: Add double quotes at start and end and preceed
- * each occurance of " and \ by a backslash.
- */
+** each occurance of " and \ by a backslash.
+*/
{
char C;
SB_AppendChar (Target, '\"');
/* Replace any characters inside the string may not be part of a string
- * unescaped.
- */
+ ** unescaped.
+ */
while ((C = SB_Get (Source)) != '\0') {
switch (C) {
case '\"':
/* Remove an old style C comment from line. */
{
/* Remember the current line number, so we can output better error
- * messages if the comment is not terminated in the current file.
- */
+ ** messages if the comment is not terminated in the current file.
+ */
unsigned StartingLine = GetCurrentLine();
/* Skip the start of comment chars */
/* Remove a new style C comment from line. */
{
/* Beware: Because line continuation chars are handled when reading
- * lines, we may only skip til the end of the source line, which
- * may not be the same as the end of the input line. The end of the
- * source line is denoted by a lf (\n) character.
- */
+ ** lines, we may only skip til the end of the source line, which
+ ** may not be the same as the end of the input line. The end of the
+ ** source line is denoted by a lf (\n) character.
+ */
do {
NextChar ();
} while (CurC != '\n' && CurC != '\0');
static int SkipWhitespace (int SkipLines)
/* Skip white space in the input stream. Do also skip newlines if SkipLines
- * is true. Return zero if nothing was skipped, otherwise return a
- * value != zero.
- */
+** is true. Return zero if nothing was skipped, otherwise return a
+** value != zero.
+*/
{
int Skipped = 0;
while (1) {
static int MacName (char* Ident)
/* Get a macro symbol name into Ident. If we have an error, print a
- * diagnostic message and clear the line.
- */
+** diagnostic message and clear the line.
+*/
{
if (IsSym (Ident) == 0) {
PPError ("Identifier expected");
NextChar ();
} else if (CurC == ',' && ME_ArgIsVariadic (E)) {
/* It's a comma, but we're inside a variadic macro argument, so
- * just copy it and proceed.
- */
+ ** just copy it and proceed.
+ */
SB_AppendChar (&Arg, CurC);
NextChar ();
} else {
}
/* If this is not the single empty argument for a macro with
- * an empty argument list, remember it.
- */
+ ** an empty argument list, remember it.
+ */
if (CurC != ')' || SB_NotEmpty (&Arg) || E->M->ArgCount > 0) {
ME_AppendActual (E, &Arg);
}
HaveSpace = SkipWhitespace (0);
/* If a ## operator follows, we have to insert the actual
- * argument as is, otherwise it must be macro replaced.
- */
+ ** argument as is, otherwise it must be macro replaced.
+ */
if (CurC == '#' && NextC == '#') {
/* ### Add placemarker if necessary */
} else {
/* Replace the formal argument by a macro replaced copy
- * of the actual.
- */
+ ** of the actual.
+ */
SB_Reset (Arg);
MacroReplacement (Arg, &E->Replacement);
SkipWhitespace (0);
/* Since we need to concatenate the token sequences, remove
- * any whitespace that was added to target, since it must come
- * from the input.
- */
+ ** any whitespace that was added to target, since it must come
+ ** from the input.
+ */
while (IsSpace (SB_LookAtLast (&E->Replacement))) {
SB_Drop (&E->Replacement, 1);
}
/* If the next token is an identifier which is a macro argument,
- * replace it, otherwise do nothing.
- */
+ ** replace it, otherwise do nothing.
+ */
if (IsSym (Ident)) {
/* Check if it's a macro argument */
} else if (CurC == '#' && E->M->ArgCount >= 0) {
/* A # operator within a macro expansion of a function like
- * macro. Read the following identifier and check if it's a
- * macro parameter.
- */
+ ** macro. Read the following identifier and check if it's a
+ ** macro parameter.
+ */
NextChar ();
SkipWhitespace (0);
if (!IsSym (Ident) || (ArgIdx = FindMacroArg (E->M, Ident)) < 0) {
MacroArgSubst (&E);
/* Do macro replacement on the macro that already has the parameters
- * substituted.
- */
+ ** substituted.
+ */
M->Expanding = 1;
MacroReplacement (&E.Replacement, Target);
M->Expanding = 0;
MacroArgSubst (&E);
/* Do macro replacement on the macro that already has the parameters
- * substituted.
- */
+ ** substituted.
+ */
M->Expanding = 1;
MacroReplacement (&E.Replacement, Target);
M->Expanding = 0;
}
/* The next token must be either an identifier, or - if not in
- * C89 mode - the ellipsis.
- */
+ ** C89 mode - the ellipsis.
+ */
if (!C89 && CurC == '.') {
/* Ellipsis */
NextChar ();
NextChar ();
/* Remember that the macro is variadic and use __VA_ARGS__ as
- * the argument name.
- */
+ ** the argument name.
+ */
AddMacroArg (M, "__VA_ARGS__");
M->Variadic = 1;
}
/* If we had an ellipsis, or the next char is not a comma, we've
- * reached the end of the macro argument list.
- */
+ ** reached the end of the macro argument list.
+ */
SkipWhitespace (0);
if (M->Variadic || CurC != ',') {
break;
InsertMacro (M);
/* Remove whitespace and comments from the line, store the preprocessed
- * line into the macro replacement buffer.
- */
+ ** line into the macro replacement buffer.
+ */
Pass1 (Line, &M->Replacement);
/* Remove whitespace from the end of the line */
#endif
/* If we have an existing macro, check if the redefinition is identical.
- * Print a diagnostic if not.
- */
+ ** Print a diagnostic if not.
+ */
if (Existing && MacroCmp (M, Existing) != 0) {
PPError ("Macro redefinition is not identical");
}
static unsigned Pass1 (StrBuf* Source, StrBuf* Target)
/* Preprocessor pass 1. Remove whitespace. Handle old and new style comments
- * and the "defined" operator.
- */
+** and the "defined" operator.
+*/
{
unsigned IdentCount;
ident Ident;
/* Translate one line. */
{
/* Trim whitespace and remove comments. The function returns the number of
- * identifiers found. If there were any, we will have to check for macros.
- */
+ ** identifiers found. If there were any, we will have to check for macros.
+ */
SB_Clear (MLine);
if (Pass1 (Line, MLine) > 0) {
MLine = InitLine (MLine);
ExprDesc Expr;
/* We're about to abuse the compiler expression parser to evaluate the
- * #if expression. Save the current tokens to come back here later.
- * NOTE: Yes, this is a hack, but it saves a complete separate expression
- * evaluation for the preprocessor.
- */
+ ** #if expression. Save the current tokens to come back here later.
+ ** NOTE: Yes, this is a hack, but it saves a complete separate expression
+ ** evaluation for the preprocessor.
+ */
Token SavedCurTok = CurTok;
Token SavedNextTok = NextTok;
PreprocessLine ();
/* Add two semicolons as sentinels to the line, so the following
- * expression evaluation will eat these two tokens but nothing from
- * the following line.
- */
+ ** expression evaluation will eat these two tokens but nothing from
+ ** the following line.
+ */
SB_AppendStr (Line, ";;");
SB_Terminate (Line);
SkipWhitespace (0);
/* Get the next char and check for a valid file name terminator. Setup
- * the include directory spec (SYS/USR) by looking at the terminator.
- */
+ ** the include directory spec (SYS/USR) by looking at the terminator.
+ */
switch (CurC) {
case '\"':
SB_Done (&Filename);
/* Clear the remaining line so the next input will come from the new
- * file (if open)
- */
+ ** file (if open)
+ */
ClearLine ();
}
static void DoPragma (void)
/* Handle a #pragma line by converting the #pragma preprocessor directive into
- * the _Pragma() compiler operator.
- */
+** the _Pragma() compiler operator.
+*/
{
/* Skip blanks following the #pragma directive */
SkipWhitespace (0);
case PP_ENDIF:
if (IfIndex >= 0) {
/* Remove any clauses on top of stack that do not
- * need a terminating #endif.
- */
+ ** need a terminating #endif.
+ */
while (IfIndex >= 0 && (IfStack[IfIndex] & IFCOND_NEEDTERM) == 0) {
--IfIndex;
}
/* */
/* */
/* (C) 2001-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
RegInfo* NewRegInfo (const RegContents* RC)
/* Allocate a new register info, initialize and return it. If RC is not
- * a NULL pointer, it is used to initialize both, the input and output
- * registers. If the pointer is NULL, all registers are set to unknown.
- */
+** a NULL pointer, it is used to initialize both, the input and output
+** registers. If the pointer is NULL, all registers are set to unknown.
+*/
{
/* Allocate memory */
RegInfo* RI = xmalloc (sizeof (RegInfo));
/* */
/* */
/* (C) 2001-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
RegInfo* NewRegInfo (const RegContents* RC);
/* Allocate a new register info, initialize and return it. If RC is not
- * a NULL pointer, it is used to initialize both, the input and output
- * registers. If the pointer is NULL, all registers are set to unknown.
- */
+** a NULL pointer, it is used to initialize both, the input and output
+** registers. If the pointer is NULL, all registers are set to unknown.
+*/
void FreeRegInfo (RegInfo* RI);
/* Free a RegInfo struct */
static token_t FindKey (const char* Key)
/* Find a keyword and return the token. Return IDENT if the token is not a
- * keyword.
- */
+** keyword.
+*/
{
struct Keyword* K;
K = bsearch (Key, Keywords, KEY_COUNT, sizeof (Keywords [0]), CmpKey);
static int SkipWhite (void)
/* Skip white space in the input stream, reading and preprocessing new lines
- * if necessary. Return 0 if end of file is reached, return 1 otherwise.
- */
+** if necessary. Return 0 if end of file is reached, return 1 otherwise.
+*/
{
while (1) {
while (CurC == '\0') {
void SymName (char* S)
/* Read a symbol from the input stream. The first character must have been
- * checked before calling this function. The buffer is expected to be at
- * least of size MAX_IDENTLEN+1.
- */
+** checked before calling this function. The buffer is expected to be at
+** least of size MAX_IDENTLEN+1.
+*/
{
unsigned Len = 0;
do {
Error ("Illegal character constant");
C = ' ';
/* Try to do error recovery, otherwise the compiler will spit
- * out thousands of errors in this place and abort.
- */
+ ** out thousands of errors in this place and abort.
+ */
if (CurC != '\'' && CurC != '\0') {
while (NextC != '\'' && NextC != '\"' && NextC != '\0') {
NextChar ();
NextTok.Tok = TOK_SCONST;
/* Concatenate strings. If at least one of the concenated strings is a wide
- * character literal, the whole string is a wide char literal, otherwise
- * it's a normal string literal.
- */
+ ** character literal, the whole string is a wide char literal, otherwise
+ ** it's a normal string literal.
+ */
while (1) {
/* Check if this is a normal or a wide char string */
unsigned long IVal; /* Value */
/* Check for a leading hex or octal prefix and determine the possible
- * integer types.
- */
+ ** integer types.
+ */
if (CurC == '0') {
/* Gobble 0 and examine next char */
NextChar ();
}
/* Because floating point numbers don't have octal prefixes (a number
- * with a leading zero is decimal), we first have to read the number
- * before converting it, so we can determine if it's a float or an
- * integer.
- */
+ ** with a leading zero is decimal), we first have to read the number
+ ** before converting it, so we can determine if it's a float or an
+ ** integer.
+ */
while (IsXDigit (CurC) && HexVal (CurC) < Base) {
SB_AppendChar (&S, CurC);
NextChar ();
SB_Terminate (&S);
/* The following character tells us if we have an integer or floating
- * point constant. Note: Hexadecimal floating point constants aren't
- * supported in C89.
- */
+ ** point constant. Note: Hexadecimal floating point constants aren't
+ ** supported in C89.
+ */
IsFloat = (CurC == '.' ||
(Base == 10 && toupper (CurC) == 'E') ||
(Base == 16 && toupper (CurC) == 'P' && IS_Get (&Standard) >= STD_C99));
/* If we don't have a floating point type, an octal prefix results in an
- * octal base.
- */
+ ** octal base.
+ */
if (!IsFloat && Prefix == 8) {
Base = 8;
}
/* Since we do now know the correct base, convert the remembered input
- * into a number.
- */
+ ** into a number.
+ */
SB_Reset (&S);
IVal = 0;
while ((C = SB_Get (&S)) != '\0') {
/* Out of range for int */
Types &= ~IT_INT;
/* If the value is in the range 0x8000..0xFFFF, unsigned int is not
- * allowed, and we don't have a type specifying suffix, emit a
- * warning, because the constant is of type long.
- */
+ ** allowed, and we don't have a type specifying suffix, emit a
+ ** warning, because the constant is of type long.
+ */
if (IVal <= 0xFFFF && (Types & IT_UINT) == 0 && !HaveSuffix) {
Warning ("Constant is long");
}
}
/* Read exponent digits. Since we support only 32 bit floats
- * with a maximum exponent of +-/127, we read the exponent
- * part as integer with up to 3 digits and drop the remainder.
- * This avoids an overflow of Exp. The exponent is always
- * decimal, even for hex float consts.
- */
+ ** with a maximum exponent of +-/127, we read the exponent
+ ** part as integer with up to 3 digits and drop the remainder.
+ ** This avoids an overflow of Exp. The exponent is always
+ ** decimal, even for hex float consts.
+ */
Digits = 0;
Exp = 0;
while (IsDigit (CurC)) {
}
/* Check for errors: We must have exponent digits, and not more
- * than three.
- */
+ ** than three.
+ */
if (Digits == 0) {
Error ("Floating constant exponent has no digits");
} else if (Digits > 3) {
ident token;
/* We have to skip white space here before shifting tokens, since the
- * tokens and the current line info is invalid at startup and will get
- * initialized by reading the first time from the file. Remember if
- * we were at end of input and handle that later.
- */
+ ** tokens and the current line info is invalid at startup and will get
+ ** initialized by reading the first time from the file. Remember if
+ ** we were at end of input and handle that later.
+ */
int GotEOF = (SkipWhite() == 0);
/* Current token is the lookahead token */
CurTok = NextTok;
/* When reading the first time from the file, the line info in NextTok,
- * which was copied to CurTok is invalid. Since the information from
- * the token is used for error messages, we must make it valid.
- */
+ ** which was copied to CurTok is invalid. Since the information from
+ ** the token is used for error messages, we must make it valid.
+ */
if (CurTok.LI == 0) {
CurTok.LI = UseLineInfo (GetCurLineInfo ());
}
void SkipTokens (const token_t* TokenList, unsigned TokenCount)
/* Skip tokens until we reach TOK_CEOF or a token in the given token list.
- * This routine is used for error recovery.
- */
+** This routine is used for error recovery.
+*/
{
while (CurTok.Tok != TOK_CEOF) {
int Consume (token_t Token, const char* ErrorMsg)
/* Eat token if it is the next in the input stream, otherwise print an error
- * message. Returns true if the token was found and false otherwise.
- */
+** message. Returns true if the token was found and false otherwise.
+*/
{
if (CurTok.Tok == Token) {
NextToken ();
void SymName (char* S);
/* Read a symbol from the input stream. The first character must have been
- * checked before calling this function. The buffer is expected to be at
- * least of size MAX_IDENTLEN+1.
- */
+** checked before calling this function. The buffer is expected to be at
+** least of size MAX_IDENTLEN+1.
+*/
int IsSym (char* S);
/* If a symbol follows, read it and return 1, otherwise return 0 */
void SkipTokens (const token_t* TokenList, unsigned TokenCount);
/* Skip tokens until we reach TOK_CEOF or a token in the given token list.
- * This routine is used for error recovery.
- */
+** This routine is used for error recovery.
+*/
int Consume (token_t Token, const char* ErrorMsg);
/* Eat token if it is the next in the input stream, otherwise print an error
- * message. Returns true if the token was found and false otherwise.
- */
+** message. Returns true if the token was found and false otherwise.
+*/
int ConsumeColon (void);
/* Check for a colon and skip it. */
int SB_GetSym (StrBuf* B, StrBuf* Ident, const char* SpecialChars)
/* Get a symbol from the string buffer. If SpecialChars is not NULL, it
- * points to a string that contains characters allowed within the string in
- * addition to letters, digits and the underline. Note: The identifier must
- * still begin with a letter.
- * Returns 1 if a symbol was found and 0 otherwise but doesn't output any
- * errors.
- */
+** points to a string that contains characters allowed within the string in
+** addition to letters, digits and the underline. Note: The identifier must
+** still begin with a letter.
+** Returns 1 if a symbol was found and 0 otherwise but doesn't output any
+** errors.
+*/
{
/* Handle a NULL argument for SpecialChars transparently */
if (SpecialChars == 0) {
int SB_GetString (StrBuf* B, StrBuf* S)
/* Get a string from the string buffer. Returns 1 if a string was found and 0
- * otherwise. Errors are only output in case of invalid strings (missing end
- * of string).
- */
+** otherwise. Errors are only output in case of invalid strings (missing end
+** of string).
+*/
{
char C;
int SB_GetNumber (StrBuf* B, long* Val)
/* Get a number from the string buffer. Accepted formats are decimal, octal,
- * hex and character constants. Numeric constants may be preceeded by a
- * minus or plus sign. The function returns 1 if a number was found and
- * zero otherwise. Errors are only output for invalid numbers.
- */
+** hex and character constants. Numeric constants may be preceeded by a
+** minus or plus sign. The function returns 1 if a number was found and
+** zero otherwise. Errors are only output for invalid numbers.
+*/
{
int Sign;
char C;
}
/* Check for a sign. A sign must be followed by a digit, otherwise it's
- * not a number
- */
+ ** not a number
+ */
Sign = 1;
switch (SB_Peek (B)) {
case '-':
int SB_GetSym (StrBuf* B, StrBuf* Ident, const char* SpecialChars);
/* Get a symbol from the string buffer. If SpecialChars is not NULL, it
- * points to a string that contains characters allowed within the string in
- * addition to letters, digits and the underline. Note: The identifier must
- * still begin with a letter.
- * Returns 1 if a symbol was found and 0 otherwise but doesn't output any
- * errors.
- */
+** points to a string that contains characters allowed within the string in
+** addition to letters, digits and the underline. Note: The identifier must
+** still begin with a letter.
+** Returns 1 if a symbol was found and 0 otherwise but doesn't output any
+** errors.
+*/
int SB_GetString (StrBuf* B, StrBuf* S);
/* Get a string from the string buffer. Returns 1 if a string was found and 0
- * otherwise. Errors are only output in case of invalid strings (missing end
- * of string).
- */
+** otherwise. Errors are only output in case of invalid strings (missing end
+** of string).
+*/
int SB_GetNumber (StrBuf* B, long* Val);
/* Get a number from the string buffer. Accepted formats are decimal, octal,
- * hex and character constants. Numeric constants may be preceeded by a
- * minus or plus sign. The function returns 1 if a number was found and
- * zero otherwise. Errors are only output for invalid numbers.
- */
+** hex and character constants. Numeric constants may be preceeded by a
+** minus or plus sign. The function returns 1 if a number was found and
+** zero otherwise. Errors are only output for invalid numbers.
+*/
static StrStack SegmentNames[SEG_COUNT];
/* We're using a collection for the stack instead of a linked list. Since
- * functions may not be nested (at least in the current implementation), the
- * maximum stack depth is 2, so there is not really a need for a better
- * implementation.
- */
+** functions may not be nested (at least in the current implementation), the
+** maximum stack depth is 2, so there is not really a need for a better
+** implementation.
+*/
static Collection SegmentStack = STATIC_COLLECTION_INITIALIZER;
/* */
/* */
/* (C) 2004-2006 Ullrich von Bassewitz */
-/* Römerstraße 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
RemoveCode (&Mark2);
/* If the shift count is greater or equal than the bit count of
- * the operand, the behaviour is undefined according to the
- * standard.
- */
+ ** the operand, the behaviour is undefined according to the
+ ** standard.
+ */
if (Expr2.IVal < 0 || Expr2.IVal >= (long) ExprBits) {
Warning ("Shift count too large for operand type");
}
/* If we're shifting an integer or unsigned to the right, the
- * lhs has a const address, and the shift count is larger than 8,
- * we can load just the high byte as a char with the correct
- * signedness, and reduce the shift count by 8. If the remaining
- * shift count is zero, we're done.
- */
+ ** lhs has a const address, and the shift count is larger than 8,
+ ** we can load just the high byte as a char with the correct
+ ** signedness, and reduce the shift count by 8. If the remaining
+ ** shift count is zero, we're done.
+ */
if (Tok == TOK_SHR &&
IsTypeInt (Expr->Type) &&
ED_IsLVal (Expr) &&
Expr2.IVal -= 8;
/* Replace the type of the expression temporarily by the
- * corresponding char type.
- */
+ ** corresponding char type.
+ */
OldType = Expr->Type;
if (IsSignUnsigned (Expr->Type)) {
Expr->Type = type_uchar;
/* */
/* */
/* (C) 2004 Ullrich von Bassewitz */
-/* Römerstraße 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
standard_t FindStandard (const char* Name)
/* Find a standard by name. Returns one of the constants defined above.
- * STD_UNKNOWN is returned if Name doesn't match a standard.
- */
+** STD_UNKNOWN is returned if Name doesn't match a standard.
+*/
{
unsigned I;
/* */
/* */
/* (C) 2004 Ullrich von Bassewitz */
-/* Römerstraße 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
standard_t FindStandard (const char* Name);
/* Find a standard by name. Returns one of the constants defined above.
- * STD_UNKNOWN is returned if Name doesn't match a standard.
- */
+** STD_UNKNOWN is returned if Name doesn't match a standard.
+*/
/* Table with all known functions and their handlers. Must be sorted
- * alphabetically!
- */
+** alphabetically!
+*/
static struct StdFuncDesc {
const char* Name;
void (*Handler) (FuncDesc*, ExprDesc*);
static long ArrayElementCount (const ArgDesc* Arg)
/* Check if the type of the given argument is an array. If so, and if the
- * element count is known, return it. In all other cases, return UNSPECIFIED.
- */
+** element count is known, return it. In all other cases, return UNSPECIFIED.
+*/
{
long Count;
static void ParseArg (ArgDesc* Arg, Type* Type)
/* Parse one argument but do not push it onto the stack. Make all fields in
- * Arg valid.
- */
+** Arg valid.
+*/
{
/* We have a prototype, so chars may be pushed as chars */
Arg->Flags = CF_FORCECHAR;
GetCodePos (&Arg->Load);
/* If the value is a constant, set the flag, otherwise load it into the
- * primary register.
- */
+ ** primary register.
+ */
if (ED_IsConstAbsInt (&Arg->Expr) && ED_CodeRangeIsEmpty (&Arg->Expr)) {
/* Remember that we have a constant value */
Arg->Flags |= CF_CONST;
ConsumeComma ();
/* Argument #3. Since memcpy is a fastcall function, we must load the
- * arg into the primary if it is not already there. This parameter is
- * also ignored for the calculation of the parameter size, since it is
- * not passed via the stack.
- */
+ ** arg into the primary if it is not already there. This parameter is
+ ** also ignored for the calculation of the parameter size, since it is
+ ** not passed via the stack.
+ */
ParseArg (&Arg3, Arg3Type);
if (Arg3.Flags & CF_CONST) {
LoadExpr (CF_NONE, &Arg3.Expr);
Warning ("Call to memcpy has no effect");
/* Remove all of the generated code but the load of the first
- * argument, which is what memcpy returns.
- */
+ ** argument, which is what memcpy returns.
+ */
RemoveCode (&Arg1.Push);
/* Set the function result to the first argument */
}
/* We've generated the complete code for the function now and know the
- * types of all parameters. Check for situations where better code can
- * be generated. If such a situation is detected, throw away the
- * generated, and emit better code.
- */
+ ** types of all parameters. Check for situations where better code can
+ ** be generated. If such a situation is detected, throw away the
+ ** generated, and emit better code.
+ */
if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) ||
(ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) &&
}
/* memcpy returns the address, so the result is actually identical
- * to the first argument.
- */
+ ** to the first argument.
+ */
*Expr = Arg1.Expr;
} else if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
(Arg1.Expr.IVal - StackPtr) + Arg3.Expr.IVal < 256) {
/* It is possible to just use one index register even if the stack
- * offset is not zero, by adjusting the offset to the constant
- * address accordingly. But we cannot do this if the data in
- * question is in the register space or at an absolute address less
- * than 256. Register space is zero page, which means that the
- * address calculation could overflow in the linker.
- */
+ ** offset is not zero, by adjusting the offset to the constant
+ ** address accordingly. But we cannot do this if the data in
+ ** question is in the register space or at an absolute address less
+ ** than 256. Register space is zero page, which means that the
+ ** address calculation could overflow in the linker.
+ */
int AllowOneIndex = !ED_IsLocRegister (&Arg2.Expr) &&
!(ED_IsLocAbs (&Arg2.Expr) && Arg2.Expr.IVal < 256);
}
/* memcpy returns the address, so the result is actually identical
- * to the first argument.
- */
+ ** to the first argument.
+ */
*Expr = Arg1.Expr;
} else if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) {
/* It is possible to just use one index register even if the stack
- * offset is not zero, by adjusting the offset to the constant
- * address accordingly. But we cannot do this if the data in
- * question is in the register space or at an absolute address less
- * than 256. Register space is zero page, which means that the
- * address calculation could overflow in the linker.
- */
+ ** offset is not zero, by adjusting the offset to the constant
+ ** address accordingly. But we cannot do this if the data in
+ ** question is in the register space or at an absolute address less
+ ** than 256. Register space is zero page, which means that the
+ ** address calculation could overflow in the linker.
+ */
int AllowOneIndex = !ED_IsLocRegister (&Arg1.Expr) &&
!(ED_IsLocAbs (&Arg1.Expr) && Arg1.Expr.IVal < 256);
}
/* memcpy returns the address, so the result is actually identical
- * to the first argument.
- */
+ ** to the first argument.
+ */
*Expr = Arg1.Expr;
} else if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
ConsumeComma ();
/* Argument #2. This argument is special in that we will call another
- * function if it is a constant zero.
- */
+ ** function if it is a constant zero.
+ */
ParseArg (&Arg2, Arg2Type);
if ((Arg2.Flags & CF_CONST) != 0 && Arg2.Expr.IVal == 0) {
/* Don't call memset, call bzero instead */
ConsumeComma ();
/* Argument #3. Since memset is a fastcall function, we must load the
- * arg into the primary if it is not already there. This parameter is
- * also ignored for the calculation of the parameter size, since it is
- * not passed via the stack.
- */
+ ** arg into the primary if it is not already there. This parameter is
+ ** also ignored for the calculation of the parameter size, since it is
+ ** not passed via the stack.
+ */
ParseArg (&Arg3, Arg3Type);
if (Arg3.Flags & CF_CONST) {
LoadExpr (CF_NONE, &Arg3.Expr);
Warning ("Call to memset has no effect");
/* Remove all of the generated code but the load of the first
- * argument, which is what memset returns.
- */
+ ** argument, which is what memset returns.
+ */
RemoveCode (&Arg1.Push);
/* Set the function result to the first argument */
}
/* We've generated the complete code for the function now and know the
- * types of all parameters. Check for situations where better code can
- * be generated. If such a situation is detected, throw away the
- * generated, and emit better code.
- * Note: Lots of improvements would be possible here, but I will
- * concentrate on the most common case: memset with arguments 2 and 3
- * being constant numerical values. Some checks have shown that this
- * covers nearly 90% of all memset calls.
- */
+ ** types of all parameters. Check for situations where better code can
+ ** be generated. If such a situation is detected, throw away the
+ ** generated, and emit better code.
+ ** Note: Lots of improvements would be possible here, but I will
+ ** concentrate on the most common case: memset with arguments 2 and 3
+ ** being constant numerical values. Some checks have shown that this
+ ** covers nearly 90% of all memset calls.
+ */
if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
ED_IsConstAbsInt (&Arg2.Expr) &&
((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) ||
}
/* memset returns the address, so the result is actually identical
- * to the first argument.
- */
+ ** to the first argument.
+ */
*Expr = Arg1.Expr;
} else if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
AddCodeLine ("bne %s", LocalLabelName (Label));
/* memset returns the address, so the result is actually identical
- * to the first argument.
- */
+ ** to the first argument.
+ */
*Expr = Arg1.Expr;
} else if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
(Arg2.Expr.IVal != 0 || IS_Get (&CodeSizeFactor) > 200)) {
/* Remove all of the generated code but the load of the first
- * argument.
- */
+ ** argument.
+ */
RemoveCode (&Arg1.Push);
/* We need a label */
}
/* Load the function result pointer into a/x (x is still valid). This
- * code will get removed by the optimizer if it is not used later.
- */
+ ** code will get removed by the optimizer if it is not used later.
+ */
AddCodeLine ("lda ptr1");
/* The function result is an rvalue in the primary register */
ParseArg (&Arg2, Arg2Type);
/* Since strcmp is a fastcall function, we must load the
- * arg into the primary if it is not already there. This parameter is
- * also ignored for the calculation of the parameter size, since it is
- * not passed via the stack.
- */
+ ** arg into the primary if it is not already there. This parameter is
+ ** also ignored for the calculation of the parameter size, since it is
+ ** not passed via the stack.
+ */
if (Arg2.Flags & CF_CONST) {
LoadExpr (CF_NONE, &Arg2.Expr);
}
g_call (CF_FIXARGC, Func_strcmp, ParamSize);
/* Get the element counts of the arguments. Then get the larger of the
- * two into ECount1. This removes FLEXIBLE and UNSPECIFIED automatically
- */
+ ** two into ECount1. This removes FLEXIBLE and UNSPECIFIED automatically
+ */
ECount1 = ArrayElementCount (&Arg1);
ECount2 = ArrayElementCount (&Arg2);
if (ECount2 > ECount1) {
}
/* If the second argument is the empty string literal, we can generate
- * more efficient code.
- */
+ ** more efficient code.
+ */
if (ED_IsLocLiteral (&Arg2.Expr) &&
IS_Get (&WritableStrings) == 0 &&
GetLiteralSize (Arg2.Expr.LVal) == 1 &&
GetLiteralStr (Arg2.Expr.LVal)[0] == '\0') {
/* Drop the generated code so we have the first argument in the
- * primary
- */
+ ** primary
+ */
RemoveCode (&Arg1.Push);
/* We don't need the literal any longer */
ReleaseLiteral (Arg2.Expr.LVal);
/* We do now have Arg1 in the primary. Load the first character from
- * this string and cast to int. This is the function result.
- */
+ ** this string and cast to int. This is the function result.
+ */
IsArray = IsTypeArray (Arg1.Type) && ED_IsRVal (&Arg1.Expr);
if (IsArray && ED_IsLocStack (&Arg1.Expr) &&
(Offs = ED_GetStackOffs (&Arg1.Expr, 0) < 256)) {
AddCodeLine ("lda %s", ED_GetLabelName (&Arg1.Expr, 0));
} else {
/* Drop part of the generated code so we have the first argument
- * in the primary
- */
+ ** in the primary
+ */
RemoveCode (&Arg1.Push);
/* Fetch the first char */
ConsumeComma ();
/* Argument #2. Since strcpy is a fastcall function, we must load the
- * arg into the primary if it is not already there. This parameter is
- * also ignored for the calculation of the parameter size, since it is
- * not passed via the stack.
- */
+ ** arg into the primary if it is not already there. This parameter is
+ ** also ignored for the calculation of the parameter size, since it is
+ ** not passed via the stack.
+ */
ParseArg (&Arg2, Arg2Type);
if (Arg2.Flags & CF_CONST) {
LoadExpr (CF_NONE, &Arg2.Expr);
ECount = ArrayElementCount (&Arg1);
/* We've generated the complete code for the function now and know the
- * types of all parameters. Check for situations where better code can
- * be generated. If such a situation is detected, throw away the
- * generated, and emit better code.
- */
+ ** types of all parameters. Check for situations where better code can
+ ** be generated. If such a situation is detected, throw away the
+ ** generated, and emit better code.
+ */
if (((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) ||
(ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) &&
((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) ||
ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) {
/* It is possible to just use one index register even if the stack
- * offset is not zero, by adjusting the offset to the constant
- * address accordingly. But we cannot do this if the data in
- * question is in the register space or at an absolute address less
- * than 256. Register space is zero page, which means that the
- * address calculation could overflow in the linker.
- */
+ ** offset is not zero, by adjusting the offset to the constant
+ ** address accordingly. But we cannot do this if the data in
+ ** question is in the register space or at an absolute address less
+ ** than 256. Register space is zero page, which means that the
+ ** address calculation could overflow in the linker.
+ */
int AllowOneIndex = !ED_IsLocRegister (&Arg1.Expr) &&
!(ED_IsLocAbs (&Arg1.Expr) && Arg1.Expr.IVal < 256);
StackPtr >= -255) {
/* It is possible to just use one index register even if the stack
- * offset is not zero, by adjusting the offset to the constant
- * address accordingly. But we cannot do this if the data in
- * question is in the register space or at an absolute address less
- * than 256. Register space is zero page, which means that the
- * address calculation could overflow in the linker.
- */
+ ** offset is not zero, by adjusting the offset to the constant
+ ** address accordingly. But we cannot do this if the data in
+ ** question is in the register space or at an absolute address less
+ ** than 256. Register space is zero page, which means that the
+ ** address calculation could overflow in the linker.
+ */
int AllowOneIndex = !ED_IsLocRegister (&Arg2.Expr) &&
!(ED_IsLocAbs (&Arg2.Expr) && Arg2.Expr.IVal < 256);
hie1 (&Arg);
/* Check if the argument is an array. If so, remember the element count.
- * Otherwise set the element count to undefined.
- */
+ ** Otherwise set the element count to undefined.
+ */
IsArray = IsTypeArray (Arg.Type);
if (IsArray) {
ECount = GetElementCount (Arg.Type);
}
/* Check if the elements of an array can be addressed by a byte sized
- * index. This is true if the size of the array is known and less than
- * 256.
- */
+ ** index. This is true if the size of the array is known and less than
+ ** 256.
+ */
IsByteIndex = (ECount != UNSPECIFIED && ECount < 256);
/* Do type conversion */
TypeConversion (&Arg, ArgType);
/* If the expression is a literal, and if string literals are read
- * only, we can calculate the length of the string and remove it
- * from the literal pool. Otherwise we have to calculate the length
- * at runtime.
- */
+ ** only, we can calculate the length of the string and remove it
+ ** from the literal pool. Otherwise we have to calculate the length
+ ** at runtime.
+ */
if (ED_IsLocLiteral (&Arg) && IS_Get (&WritableStrings) == 0) {
/* Constant string literal */
ReleaseLiteral (Arg.LVal);
/* We will inline strlen for arrays with constant addresses, if either the
- * inlining was forced on the command line, or the array is smaller than
- * 256, so the inlining is considered safe.
- */
+ ** inlining was forced on the command line, or the array is smaller than
+ ** 256, so the inlining is considered safe.
+ */
} else if (ED_IsLocConst (&Arg) && IsArray &&
(IS_Get (&InlineStdFuncs) || IsByteIndex)) {
Expr->Type = type_size_t;
/* We will inline strlen for arrays on the stack, if the array is
- * completely within the reach of a byte sized index register.
- */
+ ** completely within the reach of a byte sized index register.
+ */
} else if (ED_IsLocStack (&Arg) && IsArray && IsByteIndex &&
(Arg.IVal - StackPtr) + ECount < 256) {
Expr->Type = type_size_t;
/* strlen for a string that is pointed to by a register variable will only
- * get inlined if requested on the command line, since we cannot know how
- * big the buffer actually is, so inlining is not always safe.
- */
+ ** get inlined if requested on the command line, since we cannot know how
+ ** big the buffer actually is, so inlining is not always safe.
+ */
} else if (ED_IsLocRegister (&Arg) && ED_IsLVal (&Arg) && IsPtr &&
IS_Get (&InlineStdFuncs)) {
Expr->Type = type_size_t;
/* Last check: We will inline a generic strlen routine if inlining was
- * requested on the command line, and the code size factor is more than
- * 400 (code is 13 bytes vs. 3 for a jsr call).
- */
+ ** requested on the command line, and the code size factor is more than
+ ** 400 (code is 13 bytes vs. 3 for a jsr call).
+ */
} else if (IS_Get (&CodeSizeFactor) > 400 && IS_Get (&InlineStdFuncs)) {
/* Load the expression into the primary */
int FindStdFunc (const char* Name)
/* Determine if the given function is a known standard function that may be
- * called in a special way. If so, return the index, otherwise return -1.
- */
+** called in a special way. If so, return the index, otherwise return -1.
+*/
{
/* Look into the table for known names */
struct StdFuncDesc* D =
/* */
/* */
/* (C) 1998-2004 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
int FindStdFunc (const char* Name);
/* Determine if the given function is a known standard function that may be
- * called in a special way. If so, return the index, otherwise return -1.
- */
+** called in a special way. If so, return the index, otherwise return -1.
+*/
void HandleStdFunc (int Index, struct FuncDesc* F, ExprDesc* lval);
/* Generate code for a known standard function. */
static int CheckLabelWithoutStatement (void)
/* Called from Statement() after a label definition. Will check for a
- * following closing curly brace. This means that a label is not followed
- * by a statement which is required by the standard. Output an error if so.
- */
+** following closing curly brace. This means that a label is not followed
+** by a statement which is required by the standard. Output an error if so.
+*/
{
if (CurTok.Tok == TOK_RCURLY) {
Error ("Label at end of compound statement");
static void CheckTok (token_t Tok, const char* Msg, int* PendingToken)
/* Helper function for Statement. Will check for Tok and print Msg if not
- * found. If PendingToken is NULL, it will the skip the token, otherwise
- * it will store one to PendingToken.
- */
+** found. If PendingToken is NULL, it will the skip the token, otherwise
+** it will store one to PendingToken.
+*/
{
if (CurTok.Tok != Tok) {
Error ("%s", Msg);
static void CheckSemi (int* PendingToken)
/* Helper function for Statement. Will check for a semicolon and print an
- * error message if not found (plus some error recovery). If PendingToken is
- * NULL, it will the skip the token, otherwise it will store one to
- * PendingToken.
- * This function is a special version of CheckTok with the addition of the
- * error recovery.
- */
+** error message if not found (plus some error recovery). If PendingToken is
+** NULL, it will the skip the token, otherwise it will store one to
+** PendingToken.
+** This function is a special version of CheckTok with the addition of the
+** error recovery.
+*/
{
int HaveToken = (CurTok.Tok == TOK_SEMI);
if (!HaveToken) {
g_defcodelabel (Label1);
/* Since there's no else clause, we're not sure, if the a break
- * statement is really executed.
- */
+ ** statement is really executed.
+ */
return 0;
} else {
NextToken ();
/* If the if expression was always true, the code in the else branch
- * is never executed. Output a warning if this is the case.
- */
+ ** is never executed. Output a warning if this is the case.
+ */
if (TestResult == TESTEXPR_TRUE) {
Warning ("Unreachable code");
}
NextToken ();
/* Add the loop to the loop stack. In case of a while loop, the condition
- * label is used for continue statements.
- */
+ ** label is used for continue statements.
+ */
AddLoop (BreakLabel, CondLabel);
/* We will move the code that evaluates the while condition to the end of
- * the loop, so generate a jump here.
- */
+ ** the loop, so generate a jump here.
+ */
g_jump (CondLabel);
/* Remember the current position */
g_defcodelabel (BreakLabel);
/* Eat remaining tokens that were delayed because of line info
- * correctness
- */
+ ** correctness
+ */
SkipPending (PendingToken);
/* Remove the loop from the loop stack */
hie0 (&Expr);
/* If we return something in a void function, print an error and
- * ignore the value. Otherwise convert the value to the type of the
- * return.
- */
+ ** ignore the value. Otherwise convert the value to the type of the
+ ** return.
+ */
if (F_HasVoidReturn (CurrentFunc)) {
Error ("Returning a value in function with return type void");
} else {
NextToken ();
/* Add the loop to the loop stack. A continue jumps to the start of the
- * the increment condition.
- */
+ ** the increment condition.
+ */
AddLoop (BreakLabel, IncLabel);
/* Skip the opening paren */
Statement (&PendingToken);
/* If we had an increment expression, move the code to the bottom of
- * the loop. In this case we don't need to jump there at the end of
- * the loop body.
- */
+ ** the loop. In this case we don't need to jump there at the end of
+ ** the loop body.
+ */
if (HaveIncExpr) {
CodeMark Here;
GetCodePos (&Here);
static int CompoundStatement (void)
/* Compound statement. Allow any number of statements inside braces. The
- * function returns true if the last statement was a break or return.
- */
+** function returns true if the last statement was a break or return.
+*/
{
int GotBreak;
int Statement (int* PendingToken)
/* Statement parser. Returns 1 if the statement does a return/break, returns
- * 0 otherwise. If the PendingToken pointer is not NULL, the function will
- * not skip the terminating token of the statement (closing brace or
- * semicolon), but store true if there is a pending token, and false if there
- * is none. The token is always checked, so there is no need for the caller to
- * check this token, it must be skipped, however. If the argument pointer is
- * NULL, the function will skip the token.
- */
+** 0 otherwise. If the PendingToken pointer is not NULL, the function will
+** not skip the terminating token of the statement (closing brace or
+** semicolon), but store true if there is a pending token, and false if there
+** is none. The token is always checked, so there is no need for the caller to
+** check this token, it must be skipped, however. If the argument pointer is
+** NULL, the function will skip the token.
+*/
{
ExprDesc Expr;
int GotBreak;
}
/* Check for a label. A label is always part of a statement, it does not
- * replace one.
- */
+ ** replace one.
+ */
while (CurTok.Tok == TOK_IDENT && NextTok.Tok == TOK_COLON) {
/* Handle the label */
DoLabel ();
/* Actual statement */
ExprWithCheck (hie0, &Expr);
/* Load the result only if it is an lvalue and the type is
- * marked as volatile. Otherwise the load is useless.
- */
+ ** marked as volatile. Otherwise the load is useless.
+ */
if (ED_IsLVal (&Expr) && IsQualVolatile (Expr.Type)) {
LoadExpr (CF_NONE, &Expr);
}
/* If the statement didn't generate code, and is not of type
- * void, emit a warning.
- */
+ ** void, emit a warning.
+ */
GetCodePos (&End);
if (CodeRangeIsEmpty (&Start, &End) &&
!IsTypeVoid (Expr.Type) &&
int Statement (int* PendingToken);
/* Statement parser. Returns 1 if the statement does a return/break, returns
- * 0 otherwise. If the PendingToken pointer is not NULL, the function will
- * not skip the terminating token of the statement (closing brace or
- * semicolon), but store true if there is a pending token, and false if there
- * is none. The token is always checked, so there is no need for the caller to
- * check this token, it must be skipped, however. If the argument pointer is
- * NULL, the function will skip the token.
- */
+** 0 otherwise. If the PendingToken pointer is not NULL, the function will
+** not skip the terminating token of the statement (closing brace or
+** semicolon), but store true if there is a pending token, and false if there
+** is none. The token is always checked, so there is no need for the caller to
+** check this token, it must be skipped, however. If the argument pointer is
+** NULL, the function will skip the token.
+*/
NextToken ();
/* Read the switch expression and load it into the primary. It must have
- * integer type.
- */
+ ** integer type.
+ */
ConsumeLParen ();
Expression0 (&SwitchExpr);
if (!IsClassInt (SwitchExpr.Type)) {
ConsumeRParen ();
/* Add a jump to the switch code. This jump is usually unnecessary,
- * because the switch code will moved up just behind the switch
- * expression. However, in rare cases, there's a label at the end of
- * the switch expression. This label will not get moved, so the code
- * jumps around the switch code, and after moving the switch code,
- * things look really weird. If we add a jump here, we will never have
- * a label attached to the current code position, and the jump itself
- * will get removed by the optimizer if it is unnecessary.
- */
+ ** because the switch code will moved up just behind the switch
+ ** expression. However, in rare cases, there's a label at the end of
+ ** the switch expression. This label will not get moved, so the code
+ ** jumps around the switch code, and after moving the switch code,
+ ** things look really weird. If we add a jump here, we will never have
+ ** a label attached to the current code position, and the jump itself
+ ** will get removed by the optimizer if it is unnecessary.
+ */
SwitchCodeLabel = GetLocalLabel ();
g_jump (SwitchCodeLabel);
/* Remember the current code position. We will move the switch code
- * to this position later.
- */
+ ** to this position later.
+ */
GetCodePos (&CaseCodeStart);
/* Setup the control structure, save the old and activate the new one */
}
/* Parse the following statement, which will actually be a compound
- * statement because of the curly brace at the current input position
- */
+ ** statement because of the curly brace at the current input position
+ */
HaveBreak = Statement (&RCurlyBrace);
/* Check if we had any labels */
}
/* If the last statement did not have a break, we may have an open
- * label (maybe from an if or similar). Emitting code and then moving
- * this code to the top will also move the label to the top which is
- * wrong. So if the last statement did not have a break (which would
- * carry the label), add a jump to the exit. If it is useless, the
- * optimizer will remove it later.
- */
+ ** label (maybe from an if or similar). Emitting code and then moving
+ ** this code to the top will also move the label to the top which is
+ ** wrong. So if the last statement did not have a break (which would
+ ** carry the label), add a jump to the exit. If it is useless, the
+ ** optimizer will remove it later.
+ */
if (!HaveBreak) {
g_jump (ExitLabel);
}
FreeCaseNodeColl (SwitchData.Nodes);
/* If the case statement was (correctly) terminated by a closing curly
- * brace, skip it now.
- */
+ ** brace, skip it now.
+ */
if (RCurlyBrace) {
NextToken ();
}
/* Return true if this is a function that must be output */
{
/* Symbol must be a function which is defined and either extern or
- * static and referenced.
- */
+ ** static and referenced.
+ */
return IsTypeFunc (Sym->Type) &&
SymIsDef (Sym) &&
(Sym->Flags & (SC_REF | SC_EXTERN));
unsigned Label;
/* Register bank offset and offset of the saved copy on stack for
- * register variables.
- */
+ ** register variables.
+ */
struct {
int RegOffs;
int SaveOffs;
if (!SymIsTypeDef (Entry)) {
/* Check if the symbol is one with storage, and it if it was
- * defined but not used.
- */
+ ** defined but not used.
+ */
if (((Flags & SC_AUTO) || (Flags & SC_STATIC)) && (Flags & SC_EXTERN) == 0) {
if (SymIsDef (Entry) && !SymIsRef (Entry) &&
!SymHasAttr (Entry, atUnused)) {
SymTable* S;
/* Get a new symbol table and make it current. Note: Structs and enums
- * nested in struct scope are NOT local to the struct but visible in the
- * outside scope. So we will NOT create a new struct or enum table.
- */
+ ** nested in struct scope are NOT local to the struct but visible in the
+ ** outside scope. So we will NOT create a new struct or enum table.
+ */
S = NewSymTable (SYMTAB_SIZE_BLOCK);
S->PrevTab = SymTab;
SymTab = S;
CHECK (Struct != 0);
/* Now search in the struct symbol table. Beware: The table may not
- * exist.
- */
+ ** exist.
+ */
if (Struct->V.S.SymTab) {
Field = FindSymInTable (Struct->V.S.SymTab, Name, HashStr (Name));
}
EType = Entry->Type;
/* If we are handling arrays, the old entry or the new entry may be an
- * incomplete declaration. Accept this, and if the exsting entry is
- * incomplete, complete it.
- */
+ ** incomplete declaration. Accept this, and if the exsting entry is
+ ** incomplete, complete it.
+ */
if (IsTypeArray (T) && IsTypeArray (EType)) {
/* Get the array sizes */
}
/* In case of a function, use the new type descriptor, since it
- * contains pointers to the new symbol tables that are needed if
- * an actual function definition follows. Be sure not to use the
- * new descriptor if it contains a function declaration with an
- * empty parameter list.
- */
+ ** contains pointers to the new symbol tables that are needed if
+ ** an actual function definition follows. Be sure not to use the
+ ** new descriptor if it contains a function declaration with an
+ ** empty parameter list.
+ */
if (IsFunc) {
/* Get the function descriptor from the new type */
FuncDesc* F = GetFuncDesc (T);
/* Use this new function descriptor if it doesn't contain
- * an empty parameter list.
- */
+ ** an empty parameter list.
+ */
if ((F->Flags & FD_EMPTY) == 0) {
Entry->V.F.Func = F;
SetFuncDesc (EType, F);
Entry->Type = TypeDup (T);
/* If this is a function, set the function descriptor and clear
- * additional fields.
- */
+ ** additional fields.
+ */
if (IsFunc) {
Entry->V.F.Func = GetFuncDesc (Entry->Type);
Entry->V.F.Seg = 0;
/* Output info for locals if enabled */
if (DebugInfo) {
/* For cosmetic reasons in the output file, we will insert two tabs
- * on global level and just one on local level.
- */
+ ** on global level and just one on local level.
+ */
if (LexicalLevel == LEX_LEVEL_GLOBAL) {
Head = "\t.dbg\t\tsym";
} else {
unsigned Test (unsigned Label, int Invert)
/* Evaluate a boolean test expression and jump depending on the result of
- * the test and on Invert. The function returns one of the TESTEXPR_xx codes
- * defined above. If the jump is always true, a warning is output.
- */
+** the test and on Invert. The function returns one of the TESTEXPR_xx codes
+** defined above. If the jump is always true, a warning is output.
+*/
{
ExprDesc Expr;
unsigned Result;
unsigned TestInParens (unsigned Label, int Invert)
/* Evaluate a boolean test expression in parenthesis and jump depending on
- * the result of the test * and on Invert. The function returns one of the
- * TESTEXPR_xx codes defined above. If the jump is always true, a warning is
- * output.
- */
+** the result of the test * and on Invert. The function returns one of the
+** TESTEXPR_xx codes defined above. If the jump is always true, a warning is
+** output.
+*/
{
unsigned Result;
/* */
/* */
/* (C) 2004 Ullrich von Bassewitz */
-/* Römerstraße 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
unsigned Test (unsigned Label, int Invert);
/* Evaluate a boolean test expression and jump depending on the result of
- * the test and on Invert. The function returns one of the TESTEXPR_xx codes
- * defined above. If the jump is always true, a warning is output.
- */
+** the test and on Invert. The function returns one of the TESTEXPR_xx codes
+** defined above. If the jump is always true, a warning is output.
+*/
unsigned TestInParens (unsigned Label, int Invert);
/* Evaluate a boolean test expression in parenthesis and jump depending on
- * the result of the test * and on Invert. The function returns one of the
- * TESTEXPR_xx codes defined above. If the jump is always true, a warning is
- * output.
- */
+** the result of the test * and on Invert. The function returns one of the
+** TESTEXPR_xx codes defined above. If the jump is always true, a warning is
+** output.
+*/
/* Note: This is NOT some sort of code segment, it is used to store lines of
- * output that are textual (not real code) instead.
- */
+** output that are textual (not real code) instead.
+*/
/* Note: This is NOT some sort of code segment, it is used to store lines of
- * output that are textual (not real code) instead.
- */
+** output that are textual (not real code) instead.
+*/
static int ParamsHaveDefaultPromotions (const FuncDesc* F)
/* Check if any of the parameters of function F has a default promotion. In
- * this case, the function is not compatible with an empty parameter name list
- * declaration.
- */
+** this case, the function is not compatible with an empty parameter name list
+** declaration.
+*/
{
/* Get the symbol table */
const SymTable* Tab = F->SymTab;
while (Sym && (Sym->Flags & SC_PARAM)) {
/* If this is an integer type, check if the promoted type is equal
- * to the original type. If not, we have a default promotion.
- */
+ ** to the original type. If not, we have a default promotion.
+ */
if (IsClassInt (Sym->Type)) {
if (IntPromotion (Sym->Type) != Sym->Type) {
return 1;
static int EqualFuncParams (const FuncDesc* F1, const FuncDesc* F2)
/* Compare two function symbol tables regarding function parameters. Return 1
- * if they are equal and 0 otherwise.
- */
+** if they are equal and 0 otherwise.
+*/
{
/* Get the symbol tables */
const SymTable* Tab1 = F1->SymTab;
Type* Type2 = Sym2->Type;
/* If either of both functions is old style, apply the default
- * promotions to the parameter type.
- */
+ ** promotions to the parameter type.
+ */
if (F1->Flags & FD_OLDSTYLE) {
if (IsClassInt (Type1)) {
Type1 = IntPromotion (Type1);
}
/* Check both pointers against NULL or a non parameter to compare the
- * field count
- */
+ ** field count
+ */
return (Sym1 == 0 || (Sym1->Flags & SC_PARAM) == 0) &&
(Sym2 == 0 || (Sym2->Flags & SC_PARAM) == 0);
}
RightQual = GetQualifier (rhs);
/* If the left type is a pointer and the right is an array, both
- * are compatible.
- */
+ ** are compatible.
+ */
if (LeftType == T_TYPE_PTR && RightType == T_TYPE_ARRAY) {
RightType = T_TYPE_PTR;
}
}
/* On indirection level zero, a qualifier or sign difference is
- * accepted. The types are no longer equal, but compatible.
- */
+ ** accepted. The types are no longer equal, but compatible.
+ */
if (LeftSign != RightSign) {
if (ElementCount == 0) {
SetResult (Result, TC_SIGN_DIFF);
}
if (LeftQual != RightQual) {
/* On the first indirection level, different qualifiers mean
- * that the types are still compatible. On the second level,
- * this is a (maybe minor) error, so we create a special
- * return code, since a qualifier is dropped from a pointer.
- * Starting from the next level, the types are incompatible
- * if the qualifiers differ.
- */
+ ** that the types are still compatible. On the second level,
+ ** this is a (maybe minor) error, so we create a special
+ ** return code, since a qualifier is dropped from a pointer.
+ ** Starting from the next level, the types are incompatible
+ ** if the qualifiers differ.
+ */
/* printf ("Ind = %d %06X != %06X\n", Indirections, LeftQual, RightQual); */
switch (Indirections) {
case 1:
/* A non const value on the right is compatible to a
- * const one to the left, same for volatile.
- */
+ ** const one to the left, same for volatile.
+ */
if ((LeftQual & T_QUAL_CONST) < (RightQual & T_QUAL_CONST) ||
(LeftQual & T_QUAL_VOLATILE) < (RightQual & T_QUAL_VOLATILE)) {
SetResult (Result, TC_QUAL_DIFF);
F2 = GetFuncDesc (rhs);
/* If one of both functions has an empty parameter list (which
- * does also mean, it is not a function definition, because the
- * flag is reset in this case), it is considered equal to any
- * other definition, provided that the other has no default
- * promotions in the parameter list. If none of both parameter
- * lists is empty, we have to check the parameter lists and
- * other attributes.
- */
+ ** does also mean, it is not a function definition, because the
+ ** flag is reset in this case), it is considered equal to any
+ ** other definition, provided that the other has no default
+ ** promotions in the parameter list. If none of both parameter
+ ** lists is empty, we have to check the parameter lists and
+ ** other attributes.
+ */
if (F1->Flags & FD_EMPTY) {
if ((F2->Flags & FD_EMPTY) == 0) {
if (ParamsHaveDefaultPromotions (F2)) {
case T_TYPE_STRUCT:
case T_TYPE_UNION:
/* Compare the fields recursively. To do that, we fetch the
- * pointer to the struct definition from the type, and compare
- * the fields.
- */
+ ** pointer to the struct definition from the type, and compare
+ ** the fields.
+ */
Sym1 = GetSymEntry (lhs);
Sym2 = GetSymEntry (rhs);
Tab2 = Sym2->V.S.SymTab;
/* One or both structs may be forward definitions. In this case,
- * the symbol tables are both non existant. Assume that the
- * structs are equal in this case.
- */
+ ** the symbol tables are both non existant. Assume that the
+ ** structs are equal in this case.
+ */
if (Tab1 != 0 && Tab2 != 0) {
if (EqualSymTables (Tab1, Tab2) == 0) {
OldType = Expr->Type;
/* If we're converting to void, we're done. Note: This does also cover a
- * conversion void -> void.
- */
+ ** conversion void -> void.
+ */
if (IsTypeVoid (NewType)) {
ED_MakeRVal (Expr); /* Never an lvalue */
goto ExitPoint;
}
/* Get the sizes of the types. Since we've excluded void types, checking
- * for known sizes makes sense here.
- */
+ ** for known sizes makes sense here.
+ */
OldSize = CheckedSizeOf (OldType);
NewSize = CheckedSizeOf (NewType);
/* lvalue? */
if (ED_IsLVal (Expr)) {
- /* We have an lvalue. If the new size is smaller than the new one,
- * we don't need to do anything. The compiler will generate code
- * to load only the portion of the value that is actually needed.
- * This works only on a little endian architecture, but that's
- * what we support.
- * If both sizes are equal, do also leave the value alone.
- * If the new size is larger, we must convert the value.
- */
+ /* We have an lvalue. If the new size is smaller than the old one,
+ ** we don't need to do anything. The compiler will generate code
+ ** to load only the portion of the value that is actually needed.
+ ** This works only on a little endian architecture, but that's
+ ** what we support.
+ ** If both sizes are equal, do also leave the value alone.
+ ** If the new size is larger, we must convert the value.
+ */
if (NewSize > OldSize) {
/* Load the value into the primary */
LoadExpr (CF_NONE, Expr);
} else if (ED_IsLocAbs (Expr)) {
/* A cast of a constant numeric value to another type. Be sure
- * to handle sign extension correctly.
- */
+ ** to handle sign extension correctly.
+ */
/* Get the current and new size of the value */
unsigned OldBits = OldSize * 8;
unsigned NewBits = NewSize * 8;
/* Check if the new datatype will have a smaller range. If it
- * has a larger range, things are ok, since the value is
- * internally already represented by a long.
- */
+ ** has a larger range, things are OK, since the value is
+ ** internally already represented by a long.
+ */
if (NewBits <= OldBits) {
/* Cut the value to the new size */
} else {
/* The value is not a constant. If the sizes of the types are
- * not equal, add conversion code. Be sure to convert chars
- * correctly.
- */
+ ** not equal, add conversion code. Be sure to convert chars
+ ** correctly.
+ */
if (OldSize != NewSize) {
/* Load the value into the primary */
void TypeConversion (ExprDesc* Expr, Type* NewType)
/* Do an automatic conversion of the given expression to the new type. Output
- * warnings or errors where this automatic conversion is suspicious or
- * impossible.
- */
+** warnings or errors where this automatic conversion is suspicious or
+** impossible.
+*/
{
#if 0
/* Debugging */
/* First, do some type checking */
if (IsTypeVoid (NewType) || IsTypeVoid (Expr->Type)) {
/* If one of the sides are of type void, output a more apropriate
- * error message.
- */
+ ** error message.
+ */
Error ("Illegal type");
}
}
/* Pointer to pointer assignment is valid, if:
- * - both point to the same types, or
- * - the rhs pointer is a void pointer, or
- * - the lhs pointer is a void pointer.
- */
+ ** - both point to the same types, or
+ ** - the rhs pointer is a void pointer, or
+ ** - the lhs pointer is a void pointer.
+ */
if (!IsTypeVoid (Indirect (NewType)) && !IsTypeVoid (Indirect (Expr->Type))) {
/* Compare the types */
switch (TypeCmp (NewType, Expr->Type)) {
void TypeConversion (ExprDesc* Expr, Type* NewType);
/* Do an automatic conversion of the given expression to the new type. Output
- * warnings or errors where this automatic conversion is suspicious or
- * impossible.
- */
+** warnings or errors where this automatic conversion is suspicious or
+** impossible.
+*/
void TypeCast (ExprDesc* Expr);
/* Handle an explicit cast. */
/* */
/* */
/* (C) 1998-2004 Ullrich von Bassewitz */
-/* Römerstraße 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
int PowerOf2 (unsigned long Val)
/* Return the exponent if val is a power of two. Return -1 if val is not a
- * power of two.
- */
+** power of two.
+*/
{
int I;
unsigned long Mask = 0x0001;
/* */
/* */
/* (C) 1998-2004 Ullrich von Bassewitz */
-/* Römerstraße 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
int PowerOf2 (unsigned long Val);
/* Return the exponent if val is a power of two. Return -1 if val is not a
- * power of two.
- */
+** power of two.
+*/
/*
- * The following is a corrected doc from the BGI font editor toolkit:
- *
- * BGI Stroke File Format
- *
- * The structure of Borland .CHR (stroke) files is as follows:
- *
- * ; offset 0h is a Borland header:
- * ;
- * HeaderSize equ 080h
- * DataSize equ (size of font file)
- * descr equ "Triplex font"
- * fname equ "TRIP"
- * MajorVersion equ 1
- * MinorVersion equ 0
- *
- * db 'PK',8,8
- * db 'BGI ',descr,' V'
- * db MajorVersion+'0'
- * db (MinorVersion / 10)+'0',(MinorVersion mod 10)+'0'
- * db ' - 19 October 1987',0DH,0AH
- * db 'Copyright (c) 1987 Borland International', 0dh,0ah
- * db 0,1ah ; null & ctrl-Z = end
- *
- * dw HeaderSize ; size of header
- * db fname ; font name
- * dw DataSize ; font file size
- * db MajorVersion,MinorVersion ; version #'s
- * db 1,0 ; minimal version #'s
- *
- * db (HeaderSize - $) DUP (0) ; pad out to header size
- *
- * At offset 80h starts data for the file:
- *
- * ; 80h '+' flags stroke file type
- * ; 81h-82h number chars in font file (n)
- * ; 83h undefined
- * ; 84h ASCII value of first char in file
- * ; 85h-86h offset to stroke definitions (8+3n)
- * ; 87h scan flag (normally 0)
- * ; 88h distance from origin to top of capital
- * ; 89h distance from origin to baseline
- * ; 8Ah distance from origin to bottom descender
- * ; 8Bh-8Fh undefined
- * ; 90h offsets to individual character definitions
- * ; 90h+2n width table (one word per character)
- * ; 90h+3n start of character definitions
- * ;
- * The individual character definitions consist of a variable number of words
- * describing the operations required to render a character. Each word
- * consists of an (x,y) coordinate pair and a two-bit opcode, encoded as shown
- * here:
- *
- * Byte 1 7 6 5 4 3 2 1 0 bit #
- * op1 <seven bit signed X coord>
- *
- * Byte 2 7 6 5 4 3 2 1 0 bit #
- * op2 <seven bit signed Y coord>
- *
- *
- * Opcodes
- *
- * op1=0 op2=0 End of character definition.
- * op1=1 op2=0 Move the pointer to (x,y)
- * op1=1 op2=1 Draw from current pointer to (x,y)
- */
+** The following is a corrected doc from the BGI font editor toolkit:
+**
+** BGI Stroke File Format
+**
+** The structure of Borland .CHR (stroke) files is as follows:
+**
+** ; offset 0h is a Borland header:
+** ;
+** HeaderSize equ 080h
+** DataSize equ (size of font file)
+** descr equ "Triplex font"
+** fname equ "TRIP"
+** MajorVersion equ 1
+** MinorVersion equ 0
+**
+** db 'PK',8,8
+** db 'BGI ',descr,' V'
+** db MajorVersion+'0'
+** db (MinorVersion / 10)+'0',(MinorVersion mod 10)+'0'
+** db ' - 19 October 1987',0DH,0AH
+** db 'Copyright (c) 1987 Borland International', 0dh,0ah
+** db 0,1ah ; null & ctrl-Z = end
+**
+** dw HeaderSize ; size of header
+** db fname ; font name
+** dw DataSize ; font file size
+** db MajorVersion,MinorVersion ; version #'s
+** db 1,0 ; minimal version #'s
+**
+** db (HeaderSize - $) DUP (0) ; pad out to header size
+**
+** At offset 80h starts data for the file:
+**
+** ; 80h '+' flags stroke file type
+** ; 81h-82h number chars in font file (n)
+** ; 83h undefined
+** ; 84h ASCII value of first char in file
+** ; 85h-86h offset to stroke definitions (8+3n)
+** ; 87h scan flag (normally 0)
+** ; 88h distance from origin to top of capital
+** ; 89h distance from origin to baseline
+** ; 8Ah distance from origin to bottom descender
+** ; 8Bh-8Fh undefined
+** ; 90h offsets to individual character definitions
+** ; 90h+2n width table (one word per character)
+** ; 90h+3n start of character definitions
+** ;
+** The individual character definitions consist of a variable number of words
+** describing the operations required to render a character. Each word
+** consists of an (x,y) coordinate pair and a two-bit opcode, encoded as shown
+** here:
+**
+** Byte 1 7 6 5 4 3 2 1 0 bit #
+** op1 <seven bit signed X coord>
+**
+** Byte 2 7 6 5 4 3 2 1 0 bit #
+** op2 <seven bit signed Y coord>
+**
+**
+** Opcodes
+**
+** op1=0 op2=0 End of character definition.
+** op1=1 op2=0 Move the pointer to (x,y)
+** op1=1 op2=1 Draw from current pointer to (x,y)
+*/
/* The target file format is designed to be read by a cc65 compiled program
- * more easily. It should not be necessary to load the whole file into a
- * buffer to parse it, or seek within the file. Also using less memory if
- * possible would be fine. Therefore we use the following structure:
- *
- * Header portion:
- * .byte $54, $43, $48, $00 ; "TCH" version
- * .word <size of data portion>
- * Data portion:
- * .byte <top> ; Baseline to top
- * .byte <bottom> ; Baseline to bottom
- * .byte <height> ; Maximum char height
- * .byte <width>, ... ; $5F width bytes
- * .word <char definition offset>, ... ; $5F char def offsets
- * Character definitions:
- * .word <converted opcode>, ...
- * .byte $80
- *
- * The baseline of the character is assume to be at position zero. top and
- * bottom are both positive values. The former extends in positive, the other
- * in negative direction of the baseline. height contains the sum of top and
- * bottom and is stored here just for easier handling.
- *
- * The opcodes get converted for easier handling: END is marked by bit 7
- * set in the first byte. The second byte of this opcode is not needed.
- * Bit 7 of the second byte marks a MOVE (bit 7 = 0) or DRAW (bit 7 = 1).
- *
- * The number of characters is fixed to $20..$7E (space to tilde), so character
- * widths and offsets can be stored in fixed size preallocated tables. The
- * space for the character definitions is allocated on the heap, it's size
- * is stored in the header.
- *
- * Above structure allows a program to read the header portion of the file,
- * validate it, then read the remainder of the file into memory in one chunk.
- * The character definition offsets will then be converted into pointers by
- * adding the character definition base pointer to each.
- */
+** more easily. It should not be necessary to load the whole file into a
+** buffer to parse it, or seek within the file. Also using less memory if
+** possible would be fine. Therefore we use the following structure:
+**
+** Header portion:
+** .byte $54, $43, $48, $00 ; "TCH" version
+** .word <size of data portion>
+** Data portion:
+** .byte <top> ; Baseline to top
+** .byte <bottom> ; Baseline to bottom
+** .byte <height> ; Maximum char height
+** .byte <width>, ... ; $5F width bytes
+** .word <char definition offset>, ... ; $5F char def offsets
+** Character definitions:
+** .word <converted opcode>, ...
+** .byte $80
+**
+** The baseline of the character is assume to be at position zero. top and
+** bottom are both positive values. The former extends in positive, the other
+** in negative direction of the baseline. height contains the sum of top and
+** bottom and is stored here just for easier handling.
+**
+** The opcodes get converted for easier handling: END is marked by bit 7
+** set in the first byte. The second byte of this opcode is not needed.
+** Bit 7 of the second byte marks a MOVE (bit 7 = 0) or DRAW (bit 7 = 1).
+**
+** The number of characters is fixed to $20..$7E (space to tilde), so character
+** widths and offsets can be stored in fixed size preallocated tables. The
+** space for the character definitions is allocated on the heap, it's size
+** is stored in the header.
+**
+** Above structure allows a program to read the header portion of the file,
+** validate it, then read the remainder of the file into memory in one chunk.
+** The character definition offsets will then be converted into pointers by
+** adding the character definition base pointer to each.
+*/
static void ConvertChar (StrBuf* Data, const unsigned char* Buf, int Remaining)
/* Convert data for one character. Original data is in Buf, converted data
- * will be placed in Data.
- */
+** will be placed in Data.
+*/
{
/* Convert all drawing vectors for this character */
while (1) {
/* The header of a BGI vector font file */
static const unsigned char ChrHeader[] = {
/* According to the Borland docs, the following should work, but it
- * doesn't. Seems like there are fonts that work, but don't have the
- * "BGI" string in the header. So we use just the PK\b\b mark as
- * a header.
- *
- * 0x50, 0x4B, 0x08, 0x08, 0x42, 0x47, 0x49, 0x20 */
+ ** doesn't. Seems like there are fonts that work, but don't have the
+ ** "BGI" string in the header. So we use just the PK\b\b mark as
+ ** a header.
+ **
+ ** 0x50, 0x4B, 0x08, 0x08, 0x42, 0x47, 0x49, 0x20
+ */
0x50, 0x4B, 0x08, 0x08
};
Print (stderr, 1, "%.*s\n", (int) (MsgEnd - Buf - 4), Buf+4);
/* Get pointers to the width table, the offset table and the vector data
- * table. The first two corrected for 0x20 as first entry.
- */
+ ** table. The first two corrected for 0x20 as first entry.
+ */
OffsetBuf = Buf + 0x90 + ((0x20 - FirstChar) * 2);
WidthBuf = Buf + 0x90 + (CharCount * 2) + (0x20 - FirstChar);
VectorBuf = Buf + 0x90 + (CharCount * 3);
}
/* If the output file is NULL, use the name of the input file with ".tch"
- * appended.
- */
+ ** appended.
+ */
if (Output == 0) {
Output = MakeFilename (Input, ".tch");
}
/* Check out if we have a spawn() function on the system, or if we must use
- * our own.
- */
+** our own.
+*/
#if defined(_WIN32)
# define HAVE_SPAWN 1
#else
#endif
/* GCC strictly follows http://c-faq.com/ansi/constmismatch.html and issues an
- * 'incompatible pointer type' warning - that can't be suppressed via #pragma.
- * The spawnvp() prototype of MinGW (http://www.mingw.org/) differs from the
- * one of MinGW-w64 (http://mingw-w64.sourceforge.net/) regarding constness.
- * So there's no alternative to actually distinguish these environments :-(
- */
+** 'incompatible pointer type' warning - that can't be suppressed via #pragma.
+** The spawnvp() prototype of MinGW (http://www.mingw.org/) differs from the
+** one of MinGW-w64 (http://mingw-w64.sourceforge.net/) regarding constness.
+** So there's no alternative to actually distinguish these environments :-(
+*/
#define SPAWN_ARGV_CONST_CAST
#if defined(__MINGW32__)
# include <_mingw.h>
static const char* LinkerConfig = 0;
/* The name of the first input file. This will be used to construct the
- * executable file name if no explicit name is given.
- */
+** executable file name if no explicit name is given.
+*/
static const char* FirstInput = 0;
/* The names of the files for dependency generation */
++Cmd->ArgCount;
/* If the argument was terminated by a comma, skip it, otherwise
- * we're done.
- */
+ ** we're done.
+ */
if (*P == ',') {
/* Start over at next char */
Arg = ++P;
}
/* If the file name is not NULL (which is legal and is used to terminate
- * the file list), check if the file name does already exist in the file
- * list and print a warning if so. Regardless of the search result, add
- * the file.
- */
+ ** the file list), check if the file name does already exist in the file
+ ** list and print a warning if so. Regardless of the search result, add
+ ** the file.
+ */
if (File) {
unsigned I;
for (I = 0; I < Cmd->FileCount; ++I) {
unsigned I;
/* Since linking is always the final step, if we have an output file name
- * given, set it here. If we don't have an explicit output name given,
- * try to build one from the name of the first input file.
- */
+ ** given, set it here. If we don't have an explicit output name given,
+ ** try to build one from the name of the first input file.
+ */
if (OutputName) {
CmdSetOutput (&LD65, OutputName);
}
/* If we have a linker config file given, add it to the command line.
- * Otherwise pass the target to the linker if we have one.
- */
+ ** Otherwise pass the target to the linker if we have one.
+ */
if (LinkerConfig) {
if (Module) {
Error ("Cannot use -C and --module together");
static void AssembleFile (const char* File, unsigned ArgCount)
/* Common routine to assemble a file. Will be called by Assemble() and
- * AssembleIntermediate(). Adds options common for both routines and
- * assembles the file. Will remove excess arguments after assembly.
- */
+** AssembleIntermediate(). Adds options common for both routines and
+** assembles the file. Will remove excess arguments after assembly.
+*/
{
/* Set the target system */
CmdSetTarget (&CA65, Target);
/* Check if this is the last processing step */
if (DoLink) {
/* We're linking later. Add the output file of the assembly
- * the the file list of the linker. The name of the output
- * file is that of the input file with ".s" replaced by ".o".
- */
+ ** the the file list of the linker. The name of the output
+ ** file is that of the input file with ".s" replaced by ".o".
+ */
char* ObjName = MakeFilename (File, ".o");
CmdAddFile (&LD65, ObjName);
xfree (ObjName);
static void AssembleIntermediate (const char* SourceFile)
/* Assemble an intermediate file which was generated by a previous processing
- * step with SourceFile as input. The -dep options won't be added and
- * the intermediate assembler file is removed after assembly.
- */
+** step with SourceFile as input. The -dep options won't be added and
+** the intermediate assembler file is removed after assembly.
+*/
{
/* Generate the name of the assembler output file from the source file
- * name. It's the same name with the extension replaced by ".s"
- */
+ ** name. It's the same name with the extension replaced by ".s"
+ */
char* AsmName = MakeFilename (SourceFile, ".s");
/* Assemble the intermediate assembler file */
unsigned ArgCount = CA65.ArgCount;
/* We aren't assembling an intermediate file, but one requested by the
- * user. So add a few options here if they were given on the command
- * line.
- */
+ ** user. So add a few options here if they were given on the command
+ ** line.
+ */
if (DepName && *DepName) {
CmdAddArg2 (&CA65, "--create-dep", DepName);
}
/* Check if this is the final step */
if (DoAssemble) {
/* We will assemble this file later. If a dependency file is to be
- * generated, set the dependency target to be the final object file,
- * not the intermediate assembler file. But beware: There may be an
- * output name specified for the assembler.
- */
+ ** generated, set the dependency target to be the final object file,
+ ** not the intermediate assembler file. But beware: There may be an
+ ** output name specified for the assembler.
+ */
if (DepName || FullDepName) {
/* Was an output name for the assembler specified? */
if (!DoLink && OutputName) {
}
} else {
/* If we won't assemble, this is the final step. In this case, set
- * the output name if it was given.
- */
+ ** the output name if it was given.
+ */
if (OutputName) {
CmdSetOutput (&CC65, OutputName);
}
CmdDelArgs (&CC65, ArgCount);
/* If this is not the final step, assemble the generated file, then
- * remove it
- */
+ ** remove it
+ */
if (DoAssemble) {
/* Assemble the intermediate file and remove it */
AssembleIntermediate (File);
unsigned ArgCount = GRC.ArgCount;
/* Resource files need an geos-apple or geos-cbm target but this
- * is checked within grc65.
- */
+ ** is checked within grc65.
+ */
CmdSetTarget (&GRC, Target);
/* Add the file as argument for the resource compiler */
CmdDelArgs (&GRC, ArgCount);
/* If this is not the final step, assemble the generated file, then
- * remove it
- */
+ ** remove it
+ */
if (DoAssemble) {
/* Assemble the intermediate file and remove it */
AssembleIntermediate (File);
unsigned ArgCount = CO65.ArgCount;
/* If we won't assemble, this is the final step. In this case, set the
- * output name.
- */
+ ** output name.
+ */
if (!DoAssemble && OutputName) {
CmdSetOutput (&CO65, OutputName);
}
CmdDelArgs (&CO65, ArgCount);
/* If this is not the final step, assemble the generated file, then
- * remove it
- */
+ ** remove it
+ */
if (DoAssemble) {
/* Assemble the intermediate file and remove it */
AssembleIntermediate (File);
static const char* RelocExpr (const O65Data* D, unsigned char SegID,
unsigned long Val, const O65Reloc* R)
/* Generate the segment relative relocation expression. R is only used if the
- * expression contains am import, and may be NULL if this is an error (which
- * is then flagged).
- */
+** expression contains am import, and may be NULL if this is an error (which
+** is then flagged).
+*/
{
const O65Import* Import;
if (Model == O65_MODEL_CC65_MODULE) {
/* o65 files of type cc65-module are linked together with a definition
- * file for the zero page, but the zero page is not allocated in the
- * module itself, but the locations are mapped to the zp locations of
- * the main file.
- */
+ ** file for the zero page, but the zero page is not allocated in the
+ ** module itself, but the locations are mapped to the zp locations of
+ ** the main file.
+ */
fprintf (F, ".import\t__ZP_START__\t\t; Linker generated symbol\n");
fprintf (F, "%s = __ZP_START__\n", ZeropageLabel);
} else {
char* Author = 0;
/* For now, we do only accept o65 files generated by the ld65 linker which
- * have a specific format.
- */
+ ** have a specific format.
+ */
if (!Debug && D->Header.mode != O65_MODE_CC65) {
Error ("Cannot convert o65 files of this type");
}
PrintO65Stats (D);
/* Walk through the options and print them if verbose mode is enabled.
- * Check for a os=cc65 option and bail out if we didn't find one (for
- * now - later we switch to special handling).
- */
+ ** Check for a os=cc65 option and bail out if we didn't find one (for
+ ** now - later we switch to special handling).
+ */
for (I = 0; I < CollCount (&D->Options); ++I) {
/* Get the next option */
/* */
/* */
/* (C) 2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
O65Model FindModel (const char* ModelName)
/* Map a model name to its identifier. Return O65_MODEL_INVALID if the name
- * could not be found. Case is ignored when comparing names.
- */
+** could not be found. Case is ignored when comparing names.
+*/
{
O65Model M;
for (M = O65_MODEL_NONE; M < O65_MODEL_COUNT; ++M) {
/* */
/* */
/* (C) 2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
O65Model FindModel (const char* ModelName);
/* Map a model name to its identifier. Return O65_MODEL_INVALID if the name
- * could not be found. Case is ignored when comparing names.
- */
+** could not be found. Case is ignored when comparing names.
+*/
/* */
/* */
/* (C) 2002-2004 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
static unsigned long ReadO65Size (FILE* F, const O65Header* H)
/* Read a size variable (16 or 32 bit, depending on the mode word in the
- * header) from the o65 file.
- */
+** header) from the o65 file.
+*/
{
unsigned long Size = 0; /* Initialize to avoid warnings */
switch (H->mode & O65_SIZE_MASK) {
static void ReadO65Header (FILE* F, O65Header* H)
/* Read an o65 header from the given file. The function will call Error if
- * something is wrong.
- */
+** something is wrong.
+*/
{
static const char Magic[3] = {
O65_MAGIC_0, O65_MAGIC_1, O65_MAGIC_2 /* "o65" */
static O65Option* ReadO65Option (FILE* F)
/* Read the next O65 option from the given file. The option is stored into a
- * dynamically allocated O65Option struct which is returned. On end of options,
- * NULL is returned. On error, Error is called which terminates the program.
- */
+** dynamically allocated O65Option struct which is returned. On end of options,
+** NULL is returned. On error, Error is called which terminates the program.
+*/
{
O65Option* O;
static O65Data* ReadO65Data (FILE* F)
/* Read a complete o65 file into dynamically allocated memory and return the
- * created O65Data struct.
- */
+** created O65Data struct.
+*/
{
unsigned long Count;
O65Option* O;
O65Data* ReadO65File (const char* Name)
/* Read a complete o65 file into dynamically allocated memory and return the
- * created O65Data struct.
- */
+** created O65Data struct.
+*/
{
O65Data* D;
const char* GetO65OptionText (const O65Option* O)
/* Return the data of the given option as a readable text. The function returns
- * a pointer to a static buffer that is reused on the next call, so if in doubt,
- * make a copy (and no, the function is not thread safe).
- */
+** a pointer to a static buffer that is reused on the next call, so if in doubt,
+** make a copy (and no, the function is not thread safe).
+*/
{
static char Buf[256];
unsigned I, J;
/* */
/* */
/* (C) 2002-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* This files exports structures and constants to handle the o65 relocatable
- * file format as defined by Andre Fachat. See the original document under
- *
- * http://www.6502.org/users/andre/o65/fileformat.html
- *
- * for more information.
- */
+** file format as defined by Andre Fachat. See the original document under
+**
+** http://www.6502.org/users/andre/o65/fileformat.html
+**
+** for more information.
+*/
O65Data* ReadO65File (const char* Name);
/* Read a complete o65 file into dynamically allocated memory and return the
- * created O65Data struct.
- */
+** created O65Data struct.
+*/
const char* GetO65OSName (unsigned char OS);
/* Return the name of the operating system given by OS */
const char* GetO65OptionText (const O65Option* O);
/* Return the data of the given option as a readable text. The function returns
- * a pointer to a static buffer that is reused on the next call, so if in doubt,
- * make a copy (and no, the function is not thread safe).
- */
+** a pointer to a static buffer that is reused on the next call, so if in doubt,
+** make a copy (and no, the function is not thread safe).
+*/
void AbEnd (const char* Format, ...)
/* Print a message preceeded by the program name and terminate the program
- * with an error exit code.
- */
+** with an error exit code.
+*/
{
va_list ap;
void AbEnd (const char* Format, ...) attribute ((format (printf, 1, 2), noreturn));
/* Print a message preceeded by the program name and terminate the program
- * with an error exit code.
- */
+** with an error exit code.
+*/
unsigned char AddrSizeFromStr (const char* Str)
/* Return the address size for a given string. Returns ADDR_SIZE_INVALID if
- * the string cannot be mapped to an address size.
- */
+** the string cannot be mapped to an address size.
+*/
{
static const struct {
const char* Name;
unsigned char AddrSizeFromStr (const char* Str);
/* Return the address size for a given string. Returns ADDR_SIZE_INVALID if
- * the string cannot be mapped to an address size.
- */
+** the string cannot be mapped to an address size.
+*/
/* To factorize an alignment, we will use the following prime table. It lists
- * all primes up to 256, which means we're able to factorize alignments up to
- * 0x10000. This is checked in the code.
- */
+** all primes up to 256, which means we're able to factorize alignments up to
+** 0x10000. This is checked in the code.
+*/
static const unsigned char Primes[] = {
2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
unsigned long LeastCommonMultiple (unsigned long Left, unsigned long Right)
/* Calculate the least common multiple of two numbers and return
- * the result.
- */
+** the result.
+*/
{
unsigned I;
FactorizedNumber L, R;
Factorize (Right, &R);
/* Generate the result from the factors.
- * Some thoughts on range problems: Since the largest numbers we can
- * factorize are 2^16 (0x10000), the only numbers that could produce an
- * overflow when using 32 bits are exactly these. But the LCM for 2^16
- * and 2^16 is 2^16 so this will never happen and we're safe.
- */
+ ** Some thoughts on range problems: Since the largest numbers we can
+ ** factorize are 2^16 (0x10000), the only numbers that could produce an
+ ** overflow when using 32 bits are exactly these. But the LCM for 2^16
+ ** and 2^16 is 2^16 so this will never happen and we're safe.
+ */
Res = L.Remainder * R.Remainder;
for (I = 0; I < PRIME_COUNT; ++I) {
unsigned P = (L.Powers[I] > R.Powers[I])? L.Powers[I] : R.Powers[I];
/* Maximum possible alignment. Beware: To increase the possible alignment it
- * is not enough to bump this value. Check the code inside.
- */
+** is not enough to bump this value. Check the code inside.
+*/
#define MAX_ALIGNMENT 0x10000UL
/* The following value marks what is considered a "large alignment" and worth
- * a warning if not suppressed.
- */
+** a warning if not suppressed.
+*/
#define LARGE_ALIGNMENT 0x101UL
unsigned long LeastCommonMultiple (unsigned long Left, unsigned long Right);
/* Calculate the least common multiple of two numbers and return
- * the result.
- */
+** the result.
+*/
unsigned long AlignAddr (unsigned long Addr, unsigned long Alignment);
/* Align an address to the given alignment */
/* */
/* */
/* (C) 2000-2004 Ullrich von Bassewitz */
-/* Römerstraße 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
#define CD_TYPE_MAX 6 /* Maximum numeric type value */
/* ConDes priorities, zero is no valid priority and used to mark an empty
- * (missing) decl for this type throughout the code.
- */
+** (missing) decl for this type throughout the code.
+*/
#define CD_PRIO_NONE 0 /* No priority (no decl) */
#define CD_PRIO_MIN 1 /* Lowest priority */
#define CD_PRIO_DEF 7 /* Default priority */
#define CD_TYPE_INT 2 /* Interruptor */
/* When part of an export in an object file, type and priority are encoded in
- * one byte. In this case, the following macros access the fields:
- */
+** one byte. In this case, the following macros access the fields:
+*/
#define CD_GET_TYPE(v) (((v) >> 5) & 0x07)
#define CD_GET_PRIO(v) (((v) & 0x1F) + 1)
/* */
/* */
/* (C) 2000-2004 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* This module contains replacements for functions in ctype.h besides other
- * functions. There is a problem with using ctype.h directly:
- * The parameter must have a value of "unsigned char" or EOF.
- * So on platforms where a char is signed, this may give problems or at
- * least warnings. The wrapper functions below will have an "char" parameter
- * but handle it correctly. They will NOT work for EOF, but this is not a
- * problem, since EOF is always handled separately.
- */
+** functions. There is a problem with using ctype.h directly:
+** The parameter must have a value of "unsigned char" or EOF.
+** So on platforms where a char is signed, this may give problems or at
+** least warnings. The wrapper functions below will have an "char" parameter
+** but handle it correctly. They will NOT work for EOF, but this is not a
+** problem, since EOF is always handled separately.
+*/
/* */
/* */
/* (C) 2000-2004 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* This module contains replacements for functions in ctype.h besides other
- * functions. There is a problem with using ctype.h directly:
- * The parameter must have a value of "unsigned char" or EOF.
- * So on platforms where a char is signed, this may give problems or at
- * least warnings. The wrapper functions below will have an "char" parameter
- * but handle it correctly. They will NOT work for EOF, but this is not a
- * problem, since EOF is always handled separately.
- */
+** functions. There is a problem with using ctype.h directly:
+** The parameter must have a value of "unsigned char" or EOF.
+** So on platforms where a char is signed, this may give problems or at
+** least warnings. The wrapper functions below will have an "char" parameter
+** but handle it correctly. They will NOT work for EOF, but this is not a
+** problem, since EOF is always handled separately.
+*/
#define ABORT(s) CheckFailed (MsgProgramAborted, s, __FILE__, __LINE__)
/* Use this one instead of FAIL if there is no internal program error but an
- * error condition that is caused by the user or operating system (FAIL and
- * ABORT are essentially the same but the message differs).
- */
+** error condition that is caused by the user or operating system (FAIL and
+** ABORT are essentially the same but the message differs).
+*/
#define PRECONDITION(c) \
((void) ((c)? 0 : (CheckFailed (MsgPrecondition, #c, __FILE__, __LINE__), 0)))
static void ExpandFile (CmdLine* L, const char* Name)
/* Add the contents of a file to the command line. Each line is a separate
- * argument with leading and trailing whitespace removed.
- */
+** argument with leading and trailing whitespace removed.
+*/
{
char Buf [256];
const char* B = Buf;
/* Skip trailing whitespace (this will also kill the newline that is
- * appended by fgets().
- */
+ ** appended by fgets().
+ */
unsigned Len = strlen (Buf);
while (Len > 0 && IsSpace (Buf [Len-1])) {
--Len;
}
/* Close the file, ignore errors here since we had the file open for
- * reading only.
- */
+ ** reading only.
+ */
(void) fclose (F);
}
void InitCmdLine (int* aArgCount, char** aArgVec[], const char* aProgName)
/* Initialize command line parsing. aArgVec is the argument array terminated by
- * a NULL pointer (as usual), ArgCount is the number of valid arguments in the
- * array. Both arguments are remembered in static storage.
- */
+** a NULL pointer (as usual), ArgCount is the number of valid arguments in the
+** array. Both arguments are remembered in static storage.
+*/
{
CmdLine L;
int I;
NewCmdLine (&L);
/* Walk over the parameters and add them to the CmdLine struct. Add a
- * special handling for arguments preceeded by the '@' sign - these are
- * actually files containing arguments.
- */
+ ** special handling for arguments preceeded by the '@' sign - these are
+ ** actually files containing arguments.
+ */
for (I = 0; I < *aArgCount; ++I) {
/* Get the next argument */
const char* GetArg (unsigned* ArgNum, unsigned Len)
/* Get an argument for a short option. The argument may be appended to the
- * option itself or may be separate. Len is the length of the option string.
- */
+** option itself or may be separate. Len is the length of the option string.
+*/
{
const char* Arg = ArgVec[*ArgNum];
if (Arg[Len] != '\0') {
void InitCmdLine (int* aArgCount, char** aArgVec[], const char* aProgName);
/* Initialize command line parsing. aArgVec is the argument array terminated by
- * a NULL pointer (as usual), ArgCount is the number of valid arguments in the
- * array. Both arguments are remembered in static storage.
- */
+** a NULL pointer (as usual), ArgCount is the number of valid arguments in the
+** array. Both arguments are remembered in static storage.
+*/
void UnknownOption (const char* Opt) attribute ((noreturn));
/* Print an error about an unknown option and die. */
const char* GetArg (unsigned* ArgNum, unsigned Len);
/* Get an argument for a short option. The argument may be appended to the
- * option itself or may be separate. Len is the length of the option string.
- */
+** option itself or may be separate. Len is the length of the option string.
+*/
void LongOption (unsigned* ArgNum, const LongOpt* OptTab, unsigned OptCount);
/* Handle a long command line option */
void DoneCollection (Collection* C)
/* Free the data for a collection. This will not free the data contained in
- * the collection.
- */
+** the collection.
+*/
{
/* Free the pointer array */
xfree (C->Items);
void CollGrow (Collection* C, unsigned Size)
/* Grow the collection C so it is able to hold Size items without a resize
- * being necessary. This can be called for performance reasons if the number
- * of items to be placed in the collection is known in advance.
- */
+** being necessary. This can be called for performance reasons if the number
+** of items to be placed in the collection is known in advance.
+*/
{
void** NewItems;
#if !defined(HAVE_INLINE)
void* CollPop (Collection* C)
/* Remove the last segment from the stack and return it. Calls FAIL if the
- * collection is empty.
- */
+** collection is empty.
+*/
{
/* We must have at least one entry */
PRECONDITION (C->Count > 0);
int CollIndex (Collection* C, const void* Item)
/* Return the index of the given item in the collection. Return -1 if the
- * item was not found in the collection.
- */
+** item was not found in the collection.
+*/
{
/* Linear search */
unsigned I;
void CollDelete (Collection* C, unsigned Index)
/* Remove the item with the given index from the collection. This will not
- * free the item itself, just the pointer. All items with higher indices
- * will get moved to a lower position.
- */
+** free the item itself, just the pointer. All items with higher indices
+** will get moved to a lower position.
+*/
{
/* Check the index */
PRECONDITION (Index < C->Count);
void CollDeleteItem (Collection* C, const void* Item)
/* Delete the item pointer from the collection. The item must be in the
- * collection, otherwise FAIL will be called.
- */
+** collection, otherwise FAIL will be called.
+*/
{
/* Get the index of the entry */
int Index = CollIndex (C, Item);
#if !defined(HAVE_INLINE)
void CollReplace (Collection* C, void* Item, unsigned Index)
/* Replace the item at the given position. The old item will not be freed,
- * just the pointer will get replaced.
- */
+** just the pointer will get replaced.
+*/
{
/* Check the index */
PRECONDITION (Index < C->Count);
void CollReplaceExpand (Collection* C, void* Item, unsigned Index)
/* If Index is a valid index for the collection, replace the item at this
- * position by the one passed. If the collection is too small, expand it,
- * filling unused pointers with NULL, then add the new item at the given
- * position.
- */
+** position by the one passed. If the collection is too small, expand it,
+** filling unused pointers with NULL, then add the new item at the given
+** position.
+*/
{
if (Index < C->Count) {
/* Collection is already large enough */
void CollMove (Collection* C, unsigned OldIndex, unsigned NewIndex)
/* Move an item from one position in the collection to another. OldIndex
- * is the current position of the item, NewIndex is the new index after
- * the function has done it's work. Existing entries with indices NewIndex
- * and up are moved one position upwards.
- */
+** is the current position of the item, NewIndex is the new index after
+** the function has done it's work. Existing entries with indices NewIndex
+** and up are moved one position upwards.
+*/
{
/* Get the item and remove it from the collection */
void* Item = CollAt (C, OldIndex);
void CollMoveMultiple (Collection* C, unsigned Start, unsigned Count, unsigned Target)
/* Move a range of items from one position to another. Start is the index
- * of the first item to move, Count is the number of items and Target is
- * the index of the target item. The item with the index Start will later
- * have the index Target. All items with indices Target and above are moved
- * to higher indices.
- */
+** of the first item to move, Count is the number of items and Target is
+** the index of the target item. The item with the index Start will later
+** have the index Target. All items with indices Target and above are moved
+** to higher indices.
+*/
{
void** TmpItems;
unsigned Bytes;
memcpy (TmpItems, C->Items + Start, Bytes);
/* Check if the range has to be moved upwards or downwards. Move the
- * existing items to their final location, so that the space needed
- * for the items now in temporary storage is unoccupied.
- */
+ ** existing items to their final location, so that the space needed
+ ** for the items now in temporary storage is unoccupied.
+ */
if (Target < Start) {
/* Move downwards */
void CollTransfer (Collection* Dest, const Collection* Source)
/* Transfer all items from Source to Dest. Anything already in Dest is left
- * untouched. The items in Source are not changed and are therefore in both
- * Collections on return.
- */
+** untouched. The items in Source are not changed and are therefore in both
+** Collections on return.
+*/
{
/* Be sure there's enough room in Dest */
CollGrow (Dest, Dest->Count + Source->Count);
int (*Compare) (void*, const void*, const void*),
void* Data)
/* Sort the collection using the given compare function. The data pointer is
- * passed as *first* element to the compare function, it's not used by the
- * sort function itself. The other two pointer passed to the Compare function
- * are pointers to objects.
- */
+** passed as *first* element to the compare function, it's not used by the
+** sort function itself. The other two pointer passed to the Compare function
+** are pointers to objects.
+*/
{
if (C->Count > 1) {
QuickSort (C, 0, C->Count-1, Compare, Data);
void DoneCollection (Collection* C);
/* Free the data for a collection. This will not free the data contained in
- * the collection.
- */
+** the collection.
+*/
Collection* NewCollection (void);
/* Create and return a new collection */
void CollGrow (Collection* C, unsigned Size);
/* Grow the collection C so it is able to hold Size items without a resize
- * being necessary. This can be called for performance reasons if the number
- * of items to be placed in the collection is known in advance.
- */
+** being necessary. This can be called for performance reasons if the number
+** of items to be placed in the collection is known in advance.
+*/
#if defined(HAVE_INLINE)
INLINE unsigned CollCount (const Collection* C)
#if defined(HAVE_INLINE)
INLINE void* CollPop (Collection* C)
/* Remove the last segment from the stack and return it. Calls FAIL if the
- * collection is empty.
- */
+** collection is empty.
+*/
{
/* We must have at least one entry */
PRECONDITION (C->Count > 0);
#else
void* CollPop (Collection* C);
/* Remove the last segment from the stack and return it. Calls FAIL if the
- * collection is empty.
- */
+** collection is empty.
+*/
#endif
int CollIndex (Collection* C, const void* Item);
/* Return the index of the given item in the collection. Return -1 if the
- * item was not found in the collection.
- */
+** item was not found in the collection.
+*/
void CollDelete (Collection* C, unsigned Index);
/* Remove the item with the given index from the collection. This will not
- * free the item itself, just the pointer. All items with higher indices
- * will get moved to a lower position.
- */
+** free the item itself, just the pointer. All items with higher indices
+** will get moved to a lower position.
+*/
void CollDeleteItem (Collection* C, const void* Item);
/* Delete the item pointer from the collection. The item must be in the
- * collection, otherwise FAIL will be called.
- */
+** collection, otherwise FAIL will be called.
+*/
#if defined(HAVE_INLINE)
INLINE void CollDeleteAll (Collection* C)
/* Delete all items from the given collection. This will not free the items
- * itself, it will only remove the pointers.
- */
+** itself, it will only remove the pointers.
+*/
{
/* This one is easy... */
C->Count = 0;
#if defined(HAVE_INLINE)
INLINE void CollReplace (Collection* C, void* Item, unsigned Index)
/* Replace the item at the given position. The old item will not be freed,
- * just the pointer will get replaced.
- */
+** just the pointer will get replaced.
+*/
{
/* Check the index */
PRECONDITION (Index < C->Count);
#else
void CollReplace (Collection* C, void* Item, unsigned Index);
/* Replace the item at the given position. The old item will not be freed,
- * just the pointer will get replaced.
- */
+** just the pointer will get replaced.
+*/
#endif
void CollReplaceExpand (Collection* C, void* Item, unsigned Index);
/* If Index is a valid index for the collection, replace the item at this
- * position by the one passed. If the collection is too small, expand it,
- * filling unused pointers with NULL, then add the new item at the given
- * position.
- */
+** position by the one passed. If the collection is too small, expand it,
+** filling unused pointers with NULL, then add the new item at the given
+** position.
+*/
void CollMove (Collection* C, unsigned OldIndex, unsigned NewIndex);
/* Move an item from one position in the collection to another. OldIndex
- * is the current position of the item, NewIndex is the new index after
- * the function has done it's work. Existing entries with indices NewIndex
- * and up are moved one position upwards.
- */
+** is the current position of the item, NewIndex is the new index after
+** the function has done it's work. Existing entries with indices NewIndex
+** and up are moved one position upwards.
+*/
void CollMoveMultiple (Collection* C, unsigned Start, unsigned Count, unsigned Target);
/* Move a range of items from one position to another. Start is the index
- * of the first item to move, Count is the number of items and Target is
- * the index of the target item. The item with the index Start will later
- * have the index Target. All items with indices Target and above are moved
- * to higher indices.
- */
+** of the first item to move, Count is the number of items and Target is
+** the index of the target item. The item with the index Start will later
+** have the index Target. All items with indices Target and above are moved
+** to higher indices.
+*/
void CollTransfer (Collection* Dest, const Collection* Source);
/* Transfer all items from Source to Dest. Anything already in Dest is left
- * untouched. The items in Source are not changed and are therefore in both
- * Collections on return.
- */
+** untouched. The items in Source are not changed and are therefore in both
+** Collections on return.
+*/
void CollSort (Collection* C,
int (*Compare) (void*, const void*, const void*),
void* Data);
/* Sort the collection using the given compare function. The data pointer is
- * passed as *first* element to the compare function, it's not used by the
- * sort function itself. The other two pointer passed to the Compare function
- * are pointers to objects.
- */
+** passed as *first* element to the compare function, it's not used by the
+** sort function itself. The other two pointer passed to the Compare function
+** are pointers to objects.
+*/
cpu_t FindCPU (const char* Name)
/* Find a CPU by name and return the target id. CPU_UNKNOWN is returned if
- * the given name is no valid target.
- */
+** the given name is no valid target.
+*/
{
unsigned I;
cpu_t FindCPU (const char* Name);
/* Find a CPU by name and return the target id. CPU_UNKNOWN is returned if
- * the given name is no valid target.
- */
+** the given name is no valid target.
+*/
const FileId* GetFileId (const char* Name, const FileId* Table, unsigned Count)
/* Determine the id of the given file by looking at file extension of the name.
- * The table passed to the function must be sorted alphabetically. If the
- * extension is found, a pointer to the matching table entry is returned. If
- * no matching table entry was found, the function returns NULL.
- */
+** The table passed to the function must be sorted alphabetically. If the
+** extension is found, a pointer to the matching table entry is returned. If
+** no matching table entry was found, the function returns NULL.
+*/
{
/* Determine the file type by the extension */
const char* Ext = FindExt (Name);
/* An entry for a table that maps extensions to some sort of identifier. Such
- * a table - sorted alphabetically - is passed to GetFileId.
- */
+** a table - sorted alphabetically - is passed to GetFileId.
+*/
typedef struct FileId FileId;
struct FileId {
const char Ext[4];
const FileId* GetFileId (const char* Name, const FileId* Table, unsigned Count);
/* Determine the id of the given file by looking at file extension of the name.
- * The table passed to the function must be sorted alphabetically. If the
- * extension is found, a pointer to the matching table entry is returned. If
- * no matching table entry was found, the function returns NULL.
- */
+** The table passed to the function must be sorted alphabetically. If the
+** extension is found, a pointer to the matching table entry is returned. If
+** no matching table entry was found, the function returns NULL.
+*/
int CompareFilePos (const FilePos* P1, const FilePos* P2)
/* Compare two file positions. Return zero if both are equal, return a value
- * > 0 if P1 is greater and P2, and a value < 0 if P1 is less than P2. The
- * compare rates file index over line over column.
- */
+** > 0 if P1 is greater and P2, and a value < 0 if P1 is less than P2. The
+** compare rates file index over line over column.
+*/
{
if (P1->Name > P2->Name) {
return 1;
int CompareFilePos (const FilePos* P1, const FilePos* P2);
/* Compare two file positions. Return zero if both are equal, return a value
- * > 0 if P1 is greater and P2, and a value < 0 if P1 is less than P2. The
- * compare rates file index over line over column.
- */
+** > 0 if P1 is greater and P2, and a value < 0 if P1 is less than P2. The
+** compare rates file index over line over column.
+*/
/* This module works around bugs in the time conversion code supplied by
- * Microsoft. See here for a description of the problem:
- * http://www.codeproject.com/KB/datetime/dstbugs.aspx
- * Please let me note that I find it absolutely unacceptable to just declare
- * buggy behaviour like this "works as designed" as Microsoft does. The
- * problems did even make it into .NET, where the DateTime builtin data type
- * has exactly the same problems as described in the article above.
- */
+** Microsoft. See here for a description of the problem:
+** http://www.codeproject.com/KB/datetime/dstbugs.aspx
+** Please let me note that I find it absolutely unacceptable to just declare
+** buggy behaviour like this "works as designed" as Microsoft does. The
+** problems did even make it into .NET, where the DateTime builtin data type
+** has exactly the same problems as described in the article above.
+*/
static time_t FileTimeToUnixTime (const FILETIME* T)
/* Calculate a unix time_t value from a FILETIME. FILETIME contains a 64 bit
- * value with point zero at 1600-01-01 00:00:00 and counting 100ns intervals.
- * time_t is in seconds since 1970-01-01 00:00:00.
- */
+** value with point zero at 1600-01-01 00:00:00 and counting 100ns intervals.
+** time_t is in seconds since 1970-01-01 00:00:00.
+*/
{
/* Offset between 1600-01-01 and the Epoch in seconds. Watcom C has no
- * way to express a number > 32 bit (known to me) but is able to do
- * calculations with 64 bit integers, so we need to do it this way.
- */
+ ** way to express a number > 32 bit (known to me) but is able to do
+ ** calculations with 64 bit integers, so we need to do it this way.
+ */
static const ULARGE_INTEGER Offs = { { 0xB6109100UL, 0x00000020UL } };
ULARGE_INTEGER V;
V.LowPart = T->dwLowDateTime;
}
/* Open the file using backup semantics, so we won't change atime. Then
- * retrieve the correct times in UTC and replace the ones in Buf. Return
- * EACCES in case of errors to avoid the hassle of translating windows
- * error codes to standard ones.
- */
+ ** retrieve the correct times in UTC and replace the ones in Buf. Return
+ ** EACCES in case of errors to avoid the hassle of translating windows
+ ** error codes to standard ones.
+ */
H = CreateFile (Path,
GENERIC_READ,
FILE_SHARE_READ,
/* This module works around bugs in the time conversion code supplied by
- * Microsoft. See here for a description of the problem:
- * http://www.codeproject.com/KB/datetime/dstbugs.aspx
- * Please let me note that I find it absolutely unacceptable to just declare
- * buggy behaviour like this "works as designed" as Microsoft does. The
- * problems did even make it into .NET, where the DateTime builtin data type
- * has exactly the same problems as described in the article above.
- */
+** Microsoft. See here for a description of the problem:
+** http://www.codeproject.com/KB/datetime/dstbugs.aspx
+** Please let me note that I find it absolutely unacceptable to just declare
+** buggy behaviour like this "works as designed" as Microsoft does. The
+** problems did even make it into .NET, where the DateTime builtin data type
+** has exactly the same problems as described in the article above.
+*/
/* This module works around bugs in the time conversion code supplied by
- * Microsoft. The problem described here:
- * http://www.codeproject.com/KB/datetime/dstbugs.aspx
- * is also true when setting file times via utime(), so we need a
- * replacement
- */
+** Microsoft. The problem described here:
+** http://www.codeproject.com/KB/datetime/dstbugs.aspx
+** is also true when setting file times via utime(), so we need a
+** replacement
+*/
static FILETIME* UnixTimeToFileTime (time_t T, FILETIME* FT)
/* Calculate a FILETIME value from a time_t. FILETIME contains a 64 bit
- * value with point zero at 1600-01-01 00:00:00 and counting 100ns intervals.
- * time_t is in seconds since 1970-01-01 00:00:00.
- */
+** value with point zero at 1600-01-01 00:00:00 and counting 100ns intervals.
+** time_t is in seconds since 1970-01-01 00:00:00.
+*/
{
/* Offset between 1600-01-01 and the Epoch in seconds. Watcom C has no
- * way to express a number > 32 bit (known to me) but is able to do
- * calculations with 64 bit integers, so we need to do it this way.
- */
+ ** way to express a number > 32 bit (known to me) but is able to do
+ ** calculations with 64 bit integers, so we need to do it this way.
+ */
static const ULARGE_INTEGER Offs = { { 0xB6109100UL, 0x00000020UL } };
ULARGE_INTEGER V;
V.QuadPart = ((unsigned __int64) T + Offs.QuadPart) * 10000000U;
int SetFileTimes (const char* Path, time_t T)
/* Set the time of last modification and the time of last access of a file to
- * the given time T. This calls utime() for system where it works, and applies
- * workarounds for all others (which in fact means "WINDOWS").
- */
+** the given time T. This calls utime() for system where it works, and applies
+** workarounds for all others (which in fact means "WINDOWS").
+*/
{
HANDLE H;
FILETIME FileTime;
int SetFileTimes (const char* Path, time_t T)
/* Set the time of last modification and the time of last access of a file to
- * the given time T. This calls utime() for system where it works, and applies
- * workarounds for all others (which in fact means "WINDOWS").
- */
+** the given time T. This calls utime() for system where it works, and applies
+** workarounds for all others (which in fact means "WINDOWS").
+*/
{
struct utimbuf U;
/* This module works around bugs in the time conversion code supplied by
- * Microsoft. The problem described here:
- * http://www.codeproject.com/KB/datetime/dstbugs.aspx
- * is also true when setting file times via utime(), so we need a
- * replacement
- */
+** Microsoft. The problem described here:
+** http://www.codeproject.com/KB/datetime/dstbugs.aspx
+** is also true when setting file times via utime(), so we need a
+** replacement
+*/
int SetFileTimes (const char* Path, time_t T);
/* Set the time of last modification and the time of last access of a file to
- * the given time T. This calls utime() for system where it works, and applies
- * workarounds for all others (which in fact means "WINDOWS").
- */
+** the given time T. This calls utime() for system where it works, and applies
+** workarounds for all others (which in fact means "WINDOWS").
+*/
FILETYPE GetFileType (const char* Name)
/* Determine the type of the given file by looking at the name. If the file
- * type could not be determined, the function returns FILETYPE_UNKOWN.
- */
+** type could not be determined, the function returns FILETYPE_UNKOWN.
+*/
{
/* Search for a table entry */
const FileId* F = GetFileId (Name, TypeTable, FILETYPE_COUNT);
/* */
/* */
/* (C) 2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
FILETYPE GetFileType (const char* Name);
/* Determine the type of the given file by looking at the name. If the file
- * type could not be determined, the function returns FILETYPE_UNKOWN.
- */
+** type could not be determined, the function returns FILETYPE_UNKOWN.
+*/
/* */
/* */
/* (C) 2000-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
const char* FindName (const char* Path)
/* Return a pointer to the file name in Path. If there is no path leading to
- * the file, the function returns Path as name.
- */
+** the file, the function returns Path as name.
+*/
{
/* Get the length of the name */
int Len = strlen (Path);
char* MakeFilename (const char* Origin, const char* Ext)
/* Make a new file name from Origin and Ext. If Origin has an extension, it
- * is removed and Ext is appended. If Origin has no extension, Ext is simply
- * appended. The result is placed in a malloc'ed buffer and returned.
- * The function may be used to create "foo.o" from "foo.s".
- */
+** is removed and Ext is appended. If Origin has no extension, Ext is simply
+** appended. The result is placed in a malloc'ed buffer and returned.
+** The function may be used to create "foo.o" from "foo.s".
+*/
{
char* Out;
const char* P = FindExt (Origin);
/* */
/* */
/* (C) 2000-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
const char* FindName (const char* Path);
/* Return a pointer to the file name in Path. If there is no path leading to
- * the file, the function returns Path as name.
- */
+** the file, the function returns Path as name.
+*/
char* MakeFilename (const char* Origin, const char* Ext);
/* Make a new file name from Origin and Ext. If Origin has an extension, it
- * is removed and Ext is appended. If Origin has no extension, Ext is simply
- * appended. The result is placed in a malloc'ed buffer and returned.
- * The function may be used to create "foo.o" from "foo.s".
- */
+** is removed and Ext is appended. If Origin has no extension, Ext is simply
+** appended. The result is placed in a malloc'ed buffer and returned.
+** The function may be used to create "foo.o" from "foo.s".
+*/
/* The compiler must use the same floating point arithmetic as the target
- * platform, otherwise expressions will yield a different result when
- * evaluated in the compiler or on the target platform. Since writing a target
- * and source library is almost double the work, we will at least add the
- * hooks here, and define functions for a plug in library that may be added
- * at a later time. Currently we use the builtin data types of the compiler
- * that translates cc65.
- */
+** platform, otherwise expressions will yield a different result when
+** evaluated in the compiler or on the target platform. Since writing a target
+** and source library is almost double the work, we will at least add the
+** hooks here, and define functions for a plug in library that may be added
+** at a later time. Currently we use the builtin data types of the compiler
+** that translates cc65.
+*/
/* The compiler must use the same floating point arithmetic as the target
- * platform, otherwise expressions will yield a different result when
- * evaluated in the compiler or on the target platform. Since writing a target
- * and source library is almost double the work, we will at least add the
- * hooks here, and define functions for a plug in library that may be added
- * at a later time. Currently we use the builtin data types of the compiler
- * that translates cc65.
- *
- * BEWARE: This code will currently only work on little endian systems!
- *
- */
+** platform, otherwise expressions will yield a different result when
+** evaluated in the compiler or on the target platform. Since writing a target
+** and source library is almost double the work, we will at least add the
+** hooks here, and define functions for a plug in library that may be added
+** at a later time. Currently we use the builtin data types of the compiler
+** that translates cc65.
+**
+** BEWARE: This code will currently only work on little endian systems!
+*/
void GT_AddArray (StrBuf* Type, unsigned ArraySize)
/* Add an array with the given size to the type string in Type. This will
- * NOT add the element type!
- */
+** NOT add the element type!
+*/
{
unsigned SizeBytes;
unsigned GT_GetElementCount (StrBuf* Type)
/* Retrieve the element count of an array stored in Type at the current index
- * position. Note: Index must point to the array token itself, since the size
- * of the element count is encoded there. The index position will get moved
- * past the array.
- */
+** position. Note: Index must point to the array token itself, since the size
+** of the element count is encoded there. The index position will get moved
+** past the array.
+*/
{
/* Get the number of bytes for the element count */
unsigned SizeBytes = GT_GET_SIZE (SB_Get (Type));
const char* GT_AsString (const StrBuf* Type, StrBuf* String)
/* Convert the type into a readable representation. The target string buffer
- * will be zero terminated and a pointer to the contents are returned.
- */
+** will be zero terminated and a pointer to the contents are returned.
+*/
{
static const char HexTab[16] = "0123456789ABCDEF";
unsigned I;
/* Convert Type into readable hex. String will have twice then length
- * plus a terminator.
- */
+ ** plus a terminator.
+ */
SB_Realloc (String, 2 * SB_GetLen (Type) + 1);
SB_Clear (String);
/* This module implements a specification for a "generic data type". It is
- * called generic, because it doesn't mimic a high level language. Instead it
- * tries to desrcibe the type as representation on the machine.
- * The reasoning behing this type is to allow a debugger to represent the
- * data to the user, independent of the actual source.
- * C data types may be mapped to generic ones, but attributes like const or
- * volatile are (of course) lost.
- *
- * The data type is stored in a char array and can be terminate by a zero
- * (see definition of GT_END below). The later is not really necessary but
- * allows handling of types using the usual string functions. This is in fact
- * one of the advantages of the choosen implementation:
- * String buffers may be used to dynamically build types. Types may be stored
- * as strings in the string pool of an object file. And a string pool may be
- * used to remove duplicates and reference types using unique ids.
- */
+** called generic, because it doesn't mimic a high level language. Instead it
+** tries to desrcibe the type as representation on the machine.
+** The reasoning behing this type is to allow a debugger to represent the
+** data to the user, independent of the actual source.
+** C data types may be mapped to generic ones, but attributes like const or
+** volatile are (of course) lost.
+**
+** The data type is stored in a char array; and, can be terminated by a zero
+** (see definition of GT_END below). The latter is not really necessary; but,
+** allows handling of types using the usual string functions. This is in fact
+** one of the advantages of the chosen implementation:
+** String buffers may be used to dynamically build types. Types may be stored
+** as strings in the string pool of an object file. And a string pool may be
+** used to remove duplicates and reference types using unique ids.
+*/
void GT_AddArray (StrBuf* Type, unsigned ArraySize);
/* Add an array with the given size to the type string in Type. This will
- * NOT add the element type!
- */
+** NOT add the element type!
+*/
unsigned GT_GetElementCount (StrBuf* Type);
/* Retrieve the element count of an array stored in Type at the current index
- * position. Note: Index must point to the array token itself, since the size
- * of the element count is encoded there. The index position will get moved
- * past the array.
- */
+** position. Note: Index must point to the array token itself, since the size
+** of the element count is encoded there. The index position will get moved
+** past the array.
+*/
const char* GT_AsString (const StrBuf* Type, StrBuf* String);
/* Convert the type into a readable representation. The target string buffer
- * will be zero terminated and a pointer to the contents are returned.
- */
+** will be zero terminated and a pointer to the contents are returned.
+*/
unsigned HashInt (unsigned V)
/* Return a hash value for the given integer. The function uses Robert
- * Jenkins' 32 bit integer hash function taken from
- * http://www.concentric.net/~ttwang/tech/inthash.htm
- * For 16 bit integers, the function may be suboptimal.
- */
+** Jenkins' 32 bit integer hash function taken from
+** http://www.concentric.net/~ttwang/tech/inthash.htm
+** For 16 bit integers, the function may be suboptimal.
+*/
{
V = (V + 0x7ed55d16) + (V << 12);
V = (V ^ 0xc761c23c) ^ (V >> 19);
void DoneHashTable (HashTable* T)
/* Destroy the contents of a hash table. Note: This will not free the entries
- * in the table!
- */
+** in the table!
+*/
{
/* Just free the array with the table pointers */
xfree (T->Table);
HashNode* HT_FindHash (const HashTable* T, const void* Key, unsigned Hash)
/* Find the node with the given key. Differs from HT_Find in that the hash
- * for the key is precalculated and passed to the function.
- */
+** for the key is precalculated and passed to the function.
+*/
{
HashNode* N;
while (N) {
/* First compare the full hash, to avoid calling the compare function
- * if it is not really necessary.
- */
+ ** if it is not really necessary.
+ */
if (N->Hash == Hash &&
T->Func->Compare (Key, T->Func->GetKey (N)) == 0) {
/* Found */
HashNode** Q = &T->Table[Slot];
while (1) {
/* If the pointer is NULL, the node is not in the table which we will
- * consider a serious error.
- */
+ ** consider a serious error.
+ */
CHECK (*Q != 0);
if (*Q == N) {
/* Found - remove it */
void HT_Walk (HashTable* T, int (*F) (void* Entry, void* Data), void* Data)
/* Walk over all nodes of a hash table, optionally deleting entries from the
- * table. For each node, the user supplied function F is called, passing a
- * pointer to the entry, and the data pointer passed to HT_Walk by the caller.
- * If F returns true, the node is deleted from the hash table otherwise it's
- * left in place. While deleting the node, the node is not accessed, so it is
- * safe for F to free the memory associcated with the entry.
- */
+** table. For each node, the user supplied function F is called, passing a
+** pointer to the entry, and the data pointer passed to HT_Walk by the caller.
+** If F returns true, the node is deleted from the hash table otherwise it's
+** left in place. While deleting the node, the node is not accessed, so it is
+** safe for F to free the memory associcated with the entry.
+*/
{
unsigned I;
/* Fetch the next node in chain now, because F() may delete it */
HashNode* Next = (*Cur)->Next;
/* Call the user function. N is also the pointer to the entry. If
- * the function returns true, the entry is to be deleted.
- */
+ ** the function returns true, the entry is to be deleted.
+ */
if (F (*Cur, Data)) {
/* Delete the node from the chain */
*Cur = Next;
/* Hash table node. NOTE: This structure must be the first member of a struct
- * that is hashed by the module. Having it first allows to omit a pointer to
- * the entry itself, because the C standard guarantees that a pointer to a
- * struct can be converted to its first member.
- */
+** that is hashed by the module. Having it first allows to omit a pointer to
+** the entry itself, because the C standard guarantees that a pointer to a
+** struct can be converted to its first member.
+*/
typedef struct HashNode HashNode;
struct HashNode {
HashNode* Next; /* Next entry in hash list */
int (*Compare) (const void* Key1, const void* Key2);
/* Compare two keys. The function must return a value less than zero if
- * Key1 is smaller than Key2, zero if both are equal, and a value greater
- * than zero if Key1 is greater then Key2.
- */
+ ** Key1 is smaller than Key2, zero if both are equal, and a value greater
+ ** than zero if Key1 is greater then Key2.
+ */
};
/* Hash table */
void DoneHashTable (HashTable* T);
/* Destroy the contents of a hash table. Note: This will not free the entries
- * in the table!
- */
+** in the table!
+*/
#if defined(HAVE_INLINE)
INLINE HashTable* NewHashTable (unsigned Slots, const HashFunctions* Func)
HashNode* HT_FindHash (const HashTable* T, const void* Key, unsigned Hash);
/* Find the node with the given key. Differs from HT_Find in that the hash
- * for the key is precalculated and passed to the function.
- */
+** for the key is precalculated and passed to the function.
+*/
void* HT_Find (const HashTable* T, const void* Key);
/* Find the entry with the given key and return it */
void HT_Walk (HashTable* T, int (*F) (void* Entry, void* Data), void* Data);
/* Walk over all nodes of a hash table, optionally deleting entries from the
- * table. For each node, the user supplied function F is called, passing a
- * pointer to the entry, and the data pointer passed to HT_Walk by the caller.
- * If F returns true, the node is deleted from the hash table otherwise it's
- * left in place. While deleting the node, the node is not accessed, so it is
- * safe for F to free the memory associcated with the entry.
- */
+** table. For each node, the user supplied function F is called, passing a
+** pointer to the entry, and the data pointer passed to HT_Walk by the caller.
+** If F returns true, the node is deleted from the hash table otherwise it's
+** left in place. While deleting the node, the node is not accessed, so it is
+** safe for F to free the memory associcated with the entry.
+*/
/* This module contains definitions for high level language symbols passed
- * down from the C compiler. They're collected in the assembler and written to
- * the object file in binary form, then again read by the linker and finally
- * placed in the debug info file.
- */
+** down from the C compiler. They're collected in the assembler and written to
+** the object file in binary form, then again read by the linker and finally
+** placed in the debug info file.
+*/
/* */
/* */
/* (C) 2004 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* If we have stdint.h, include it, otherwise try some quesswork on types.
- * gcc and msvc don't define __STDC_VERSION__ without special flags, so check
- * for them explicitly. Undefined symbols are replaced by zero, so a check for
- * defined(__GNUC__) or defined(_MSC_VER) is not necessary.
- */
+** gcc and msvc don't define __STDC_VERSION__ without special flags, so check
+** for them explicitly. Undefined symbols are replaced by zero, so a check for
+** defined(__GNUC__) or defined(_MSC_VER) is not necessary.
+*/
#if (__STDC_VERSION__ >= 199901) || (__GNUC__ >= 3) || (_MSC_VER >= 1600)
#include <stdint.h>
#else
/* Assume long is the largest type available, and assume that pointers can be
- * safely converted into this type and back.
- */
+** safely converted into this type and back.
+*/
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long intmax_t;
static int RealChar (const unsigned char* Pattern)
/* Return the next character from Pattern. If the next character is the
- * escape character, skip it and return the following.
- */
+** escape character, skip it and return the following.
+*/
{
if (*Pattern == ESCAPE_CHAR) {
Pattern++;
} else {
/* Check a single char. Build a set of all possible characters in
- * CS, then check if the current char of Source is contained in
- * there.
- */
+ ** CS, then check if the current char of Source is contained in
+ ** there.
+ */
CS_CLEAR (CS); /* Clear the character set */
if (*Pattern == '?') {
int MatchPattern (const char* Source, const char* Pattern)
/* Match the string in Source against Pattern. Pattern may contain the
- * wildcards '*', '?', '[abcd]' '[ab-d]', '[!abcd]', '[!ab-d]'. The
- * function returns a value of zero if Source does not match Pattern,
- * otherwise a non zero value is returned. If Pattern contains an invalid
- * wildcard pattern (e.g. 'A[x'), the function returns zero.
- */
+** wildcards '*', '?', '[abcd]' '[ab-d]', '[!abcd]', '[!ab-d]'. The
+** function returns a value of zero if Source does not match Pattern,
+** otherwise a non zero value is returned. If Pattern contains an invalid
+** wildcard pattern (e.g. 'A[x'), the function returns zero.
+*/
{
/* Handle the trivial cases */
if (Pattern == 0 || *Pattern == '\0') {
int MatchPattern (const char* Source, const char* Pattern);
/* Match the string in Source against Pattern. Pattern may contain the
- * wildcards '*', '?', '[abcd]' '[ab-d]', '[!abcd]', '[!ab-d]'. The
- * function returns a value of zero if Source does not match Pattern,
- * otherwise a non zero value is returned. If Pattern contains an invalid
- * wildcard pattern (e.g. 'A[x'), the function returns zero.
- */
+** wildcards '*', '?', '[abcd]' '[ab-d]', '[!abcd]', '[!ab-d]'. The
+** function returns a value of zero if Source does not match Pattern,
+** otherwise a non zero value is returned. If Pattern contains an invalid
+** wildcard pattern (e.g. 'A[x'), the function returns zero.
+*/
/* */
/* */
/* (C) 2003 Ullrich von Bassewitz */
-/* Römerstraße 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
void SetMemoryModel (mmodel_t Model)
/* Set the memory model updating the MemoryModel variables and the address
- * sizes for the segments.
- */
+** sizes for the segments.
+*/
{
/* Remember the memory model */
MemoryModel = Model;
/* */
/* */
/* (C) 2003 Ullrich von Bassewitz */
-/* Römerstraße 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
void SetMemoryModel (mmodel_t Model);
/* Set the memory model updating the MemoryModel variables and the address
- * sizes for the segments.
- */
+** sizes for the segments.
+*/
void AddSearchPathFromEnv (SearchPaths* P, const char* EnvVar)
/* Add a search path from an environment variable to the end of an existing
- * list.
- */
+** list.
+*/
{
AddSearchPath (P, getenv (EnvVar));
}
void AddSubSearchPathFromEnv (SearchPaths* P, const char* EnvVar, const char* SubDir)
/* Add a search path from an environment variable, adding a subdirectory to
- * the environment variable value.
- */
+** the environment variable value.
+*/
{
StrBuf Dir = AUTO_STRBUF_INITIALIZER;
void AddSubSearchPathFromWinBin (SearchPaths* P, const char* SubDir)
{
/* Windows only:
- * Add a search path from the running binary, adding a subdirectory to
- * the parent directory of the directory containing the binary.
- */
+** Add a search path from the running binary, adding a subdirectory to
+** the parent directory of the directory containing the binary.
+*/
#if defined(_WIN32)
char Dir[_MAX_PATH];
int PushSearchPath (SearchPaths* P, const char* NewPath)
/* Add a new search path to the head of an existing search path list, provided
- * that it's not already there. If the path is already at the first position,
- * return zero, otherwise return a non zero value.
- */
+** that it's not already there. If the path is already at the first position,
+** return zero, otherwise return a non zero value.
+*/
{
/* Generate a clean copy of NewPath */
char* Path = CleanupPath (NewPath);
char* SearchFile (const SearchPaths* P, const char* File)
/* Search for a file in a list of directories. Return a pointer to a malloced
- * area that contains the complete path, if found, return 0 otherwise.
- */
+** area that contains the complete path, if found, return 0 otherwise.
+*/
{
char* Name = 0;
StrBuf PathName = AUTO_STRBUF_INITIALIZER;
void AddSearchPathFromEnv (SearchPaths* P, const char* EnvVar);
/* Add a search path from an environment variable to the end of an existing
- * list.
- */
+** list.
+*/
void AddSubSearchPathFromEnv (SearchPaths* P, const char* EnvVar, const char* SubDir);
/* Add a search path from an environment variable, adding a subdirectory to
- * the environment variable value.
- */
+** the environment variable value.
+*/
void AddSubSearchPathFromWinBin (SearchPaths* P, const char* SubDir);
/* Windows only:
- * Add a search path from the running binary, adding a subdirectory to
- * the parent directory of the directory containing the binary.
- */
+** Add a search path from the running binary, adding a subdirectory to
+** the parent directory of the directory containing the binary.
+*/
int PushSearchPath (SearchPaths* P, const char* NewPath);
/* Add a new search path to the head of an existing search path list, provided
- * that it's not already there. If the path is already at the first position,
- * return zero, otherwise return a non zero value.
- */
+** that it's not already there. If the path is already at the first position,
+** return zero, otherwise return a non zero value.
+*/
void PopSearchPath (SearchPaths* P);
/* Remove a search path from the head of an existing search path list */
char* SearchFile (const SearchPaths* P, const char* File);
/* Search for a file in a list of directories. Return a pointer to a malloced
- * area that contains the complete path, if found, return 0 otherwise.
- */
+** area that contains the complete path, if found, return 0 otherwise.
+*/
/* */
/* */
/* (C) 2003 Ullrich von Bassewitz */
-/* Römerstraße 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* According to the C standard, shifting a data type by the number of bits it
- * has causes undefined behaviour. So
- *
- * unsigned long l = 1;
- * unsigned u =32;
- * l <<= u;
- *
- * maybe illegal. The functions in this module behave safely in this respect,
- * and they use proper casting to distinguish signed from unsigned shifts.
- * They are not a general purpose replacement for the shift operator!
- */
+** has causes undefined behaviour. So
+**
+** unsigned long l = 1;
+** unsigned u =32;
+** l <<= u;
+**
+** may be illegal. The functions in this module behave safely in that respect,
+** and they use proper casting to distinguish signed from unsigned shifts.
+** They are not a general purpose replacement for the shift operator!
+*/
/* */
/* */
/* (C) 2003 Ullrich von Bassewitz */
-/* Römerstraße 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* According to the C standard, shifting a data type by the number of bits it
- * has causes undefined behaviour. So
- *
- * unsigned long l = 1;
- * unsigned u =32;
- * l <<= u;
- *
- * maybe illegal. The functions in this module behave safely in this respect,
- * and they use proper casting to distinguish signed from unsigned shifts.
- * They are not a general purpose replacement for the shift operator!
- */
+** has causes undefined behaviour. So
+**
+** unsigned long l = 1;
+** unsigned u =32;
+** l <<= u;
+**
+** may be illegal. The functions in this module behave safely in that respect,
+** and they use proper casting to distinguish signed from unsigned shifts.
+** They are not a general purpose replacement for the shift operator!
+*/
StrBuf* SB_InitFromString (StrBuf* B, const char* S)
/* Initialize a string buffer from a literal string. Beware: The buffer won't
- * store a copy but a pointer to the actual string.
- */
+** store a copy but a pointer to the actual string.
+*/
{
B->Allocated = 0;
B->Len = strlen (S);
void SB_Realloc (StrBuf* B, unsigned NewSize)
/* Reallocate the string buffer space, make sure at least NewSize bytes are
- * available.
- */
+** available.
+*/
{
/* Get the current size, use a minimum of 8 bytes */
unsigned NewAllocated = B->Allocated;
}
/* Reallocate the buffer. Beware: The allocated size may be zero while the
- * length is not. This means that we have a buffer that wasn't allocated
- * on the heap.
- */
+ ** length is not. This means that we have a buffer that wasn't allocated
+ ** on the heap.
+ */
if (B->Allocated) {
/* Just reallocate the block */
B->Buf = xrealloc (B->Buf, NewAllocated);
static void SB_CheapRealloc (StrBuf* B, unsigned NewSize)
/* Reallocate the string buffer space, make sure at least NewSize bytes are
- * available. This function won't copy the old buffer contents over to the new
- * buffer and may be used if the old contents are overwritten later.
- */
+** available. This function won't copy the old buffer contents over to the new
+** buffer and may be used if the old contents are overwritten later.
+*/
{
/* Get the current size, use a minimum of 8 bytes */
unsigned NewAllocated = B->Allocated;
void SB_Terminate (StrBuf* B)
/* Zero terminate the given string buffer. NOTE: The terminating zero is not
- * accounted for in B->Len, if you want that, you have to use AppendChar!
- */
+** accounted for in B->Len, if you want that, you have to use AppendChar!
+*/
{
unsigned NewLen = B->Len + 1;
if (NewLen > B->Allocated) {
#if !defined(HAVE_INLINE)
void SB_Cut (StrBuf* B, unsigned Len)
/* Cut the contents of B at the given length. If the current length of the
- * buffer is smaller than Len, nothing will happen.
- */
+** buffer is smaller than Len, nothing will happen.
+*/
{
if (Len < B->Len) {
B->Len = Len;
void SB_Slice (StrBuf* Target, const StrBuf* Source, unsigned Start, unsigned Len)
/* Copy a slice from Source into Target. The current contents of Target are
- * destroyed. If Start is greater than the length of Source, or if Len
- * characters aren't available, the result will be a buffer with less than Len
- * bytes.
- */
+** destroyed. If Start is greater than the length of Source, or if Len
+** characters aren't available, the result will be a buffer with less than Len
+** bytes.
+*/
{
/* Calculate the length of the resulting buffer */
if (Start >= Source->Len) {
void SB_Move (StrBuf* Target, StrBuf* Source)
/* Move the complete contents of Source to target. This will delete the old
- * contents of Target, and Source will be empty after the call.
- */
+** contents of Target, and Source will be empty after the call.
+*/
{
/* Free the target string */
if (Target->Allocated) {
void SB_VPrintf (StrBuf* S, const char* Format, va_list ap)
/* printf function with S as target. The function is safe, which means that
- * the current contents of S are discarded, and are allocated again with
- * a matching size for the output. The function will call FAIL when problems
- * are detected (anything that let xsnprintf return -1).
- */
+** the current contents of S are discarded, and are allocated again with
+** a matching size for the output. The function will call FAIL when problems
+** are detected (anything that let xsnprintf return -1).
+*/
{
va_list tmp;
int SizeNeeded;
/* Since we must determine the space needed anyway, we will try with
- * the currently allocated memory. If the call succeeds, we've saved
- * an allocation. If not, we have to reallocate and try again.
- */
+ ** the currently allocated memory. If the call succeeds, we've saved
+ ** an allocation. If not, we have to reallocate and try again.
+ */
va_copy (tmp, ap);
SizeNeeded = xvsnprintf (S->Buf, S->Allocated, Format, tmp);
va_end (tmp);
void SB_Printf (StrBuf* S, const char* Format, ...)
/* vprintf function with S as target. The function is safe, which means that
- * the current contents of S are discarded, and are allocated again with
- * a matching size for the output. The function will call FAIL when problems
- * are detected (anything that let xsnprintf return -1).
- */
+** the current contents of S are discarded, and are allocated again with
+** a matching size for the output. The function will call FAIL when problems
+** are detected (anything that let xsnprintf return -1).
+*/
{
va_list ap;
va_start (ap, Format);
StrBuf* SB_InitFromString (StrBuf* B, const char* S);
/* Initialize a string buffer from a literal string. Beware: The buffer won't
- * store a copy but a pointer to the actual string. A buffer initialized with
- * this routine may be "forgotten" without calling SB_Done, since no memory
- * has been allocated.
- */
+** store a copy but a pointer to the actual string. A buffer initialized with
+** this routine may be "forgotten" without calling SB_Done, since no memory
+** has been allocated.
+*/
void SB_Done (StrBuf* B);
/* Free the data of a string buffer (but not the struct itself) */
void SB_Realloc (StrBuf* B, unsigned NewSize);
/* Reallocate the string buffer space, make sure at least NewSize bytes are
- * available.
- */
+** available.
+*/
#if defined(HAVE_INLINE)
INLINE unsigned SB_GetLen (const StrBuf* B)
#if defined(HAVE_INLINE)
INLINE char SB_Get (StrBuf* B)
/* Return the next character from the string incrementing Index. Returns NUL
- * if the end of the string is reached.
- */
+** if the end of the string is reached.
+*/
{
return (B->Index < B->Len)? B->Buf[B->Index++] : '\0';
}
#if defined(HAVE_INLINE)
INLINE char SB_Peek (const StrBuf* B)
/* Look at the next character from the string without incrementing Index.
- * Returns NUL if the end of the string is reached.
- */
+** Returns NUL if the end of the string is reached.
+*/
{
return (B->Index < B->Len)? B->Buf[B->Index] : '\0';
}
#if defined(HAVE_INLINE)
INLINE char SB_LookAt (const StrBuf* B, unsigned Index)
/* Look at a specific character from the string. Returns NUL if the given
- * index is greater than the size of the string.
- */
+** index is greater than the size of the string.
+*/
{
return (Index < B->Len)? B->Buf[Index] : '\0';
}
#if defined(HAVE_INLINE)
INLINE char SB_LookAtLast (const StrBuf* B)
/* Look at the last character from the string. Returns NUL if the string buffer
- * is empty.
- */
+** is empty.
+*/
{
return (B->Len > 0)? B->Buf[B->Len-1] : '\0';
}
void SB_Terminate (StrBuf* B);
/* Zero terminate the given string buffer. NOTE: The terminating zero is not
- * accounted for in B->Len, if you want that, you have to use AppendChar!
- */
+** accounted for in B->Len, if you want that, you have to use AppendChar!
+*/
void SB_CopyBuf (StrBuf* Target, const char* Buf, unsigned Size);
/* Copy Buf to Target, discarding the old contents of Target */
#if defined(HAVE_INLINE)
INLINE void SB_Cut (StrBuf* B, unsigned Len)
/* Cut the contents of B at the given length. If the current length of the
- * buffer is smaller than Len, nothing will happen.
- */
+** buffer is smaller than Len, nothing will happen.
+*/
{
if (Len < B->Len) {
B->Len = Len;
#else
void SB_Cut (StrBuf* B, unsigned Len);
/* Cut the contents of B at the given length. If the current length of the
- * buffer is smaller than Len, nothing will happen.
- */
+** buffer is smaller than Len, nothing will happen.
+*/
#endif
void SB_Slice (StrBuf* Target, const StrBuf* Source, unsigned Start, unsigned Len);
/* Copy a slice from Source into Target. The current contents of Target are
- * destroyed. If Start is greater than the length of Source, or if Len
- * characters aren't available, the result will be a buffer with less than Len
- * bytes.
- */
+** destroyed. If Start is greater than the length of Source, or if Len
+** characters aren't available, the result will be a buffer with less than Len
+** bytes.
+*/
void SB_Move (StrBuf* Target, StrBuf* Source);
/* Move the complete contents of Source to target. This will delete the old
- * contents of Target, and Source will be empty after the call.
- */
+** contents of Target, and Source will be empty after the call.
+*/
void SB_ToLower (StrBuf* S);
/* Convert all characters in S to lower case */
void SB_VPrintf (StrBuf* S, const char* Format, va_list ap) attribute ((format (printf, 2, 0)));
/* printf function with S as target. The function is safe, which means that
- * the current contents of S are discarded, and are allocated again with
- * a matching size for the output. The function will call FAIL when problems
- * are detected (anything that let xsnprintf return -1).
- */
+** the current contents of S are discarded, and are allocated again with
+** a matching size for the output. The function will call FAIL when problems
+** are detected (anything that let xsnprintf return -1).
+*/
void SB_Printf (StrBuf* S, const char* Format, ...) attribute ((format (printf, 2, 3)));
/* vprintf function with S as target. The function is safe, which means that
- * the current contents of S are discarded, and are allocated again with
- * a matching size for the output. The function will call FAIL when problems
- * are detected (anything that let xsnprintf return -1).
- */
+** the current contents of S are discarded, and are allocated again with
+** a matching size for the output. The function will call FAIL when problems
+** are detected (anything that let xsnprintf return -1).
+*/
/* A string pool is used to store identifiers and other strings. Each string
- * stored in the pool has a unique id, which may be used to access the string
- * in the pool. Identical strings are stored only once in the pool and have
- * identical ids. This means that instead of comparing strings, just the
- * string pool ids must be compared.
- */
+** stored in the pool has a unique id, which may be used to access the string
+** in the pool. Identical strings are stored only once in the pool and have
+** identical ids. This means that instead of comparing strings, just the
+** string pool ids must be compared.
+*/
static int HT_Compare (const void* Key1, const void* Key2);
/* Compare two keys. The function must return a value less than zero if
- * Key1 is smaller than Key2, zero if both are equal, and a value greater
- * than zero if Key1 is greater then Key2.
- */
+** Key1 is smaller than Key2, zero if both are equal, and a value greater
+** than zero if Key1 is greater then Key2.
+*/
static int HT_Compare (const void* Key1, const void* Key2)
/* Compare two keys. The function must return a value less than zero if
- * Key1 is smaller than Key2, zero if both are equal, and a value greater
- * than zero if Key1 is greater then Key2.
- */
+** Key1 is smaller than Key2, zero if both are equal, and a value greater
+** than zero if Key1 is greater then Key2.
+*/
{
return SB_Compare (Key1, Key2);
}
unsigned SP_Add (StringPool* P, const StrBuf* S)
/* Add a string buffer to the buffer and return the index. If the string does
- * already exist in the pool, SP_AddBuf will just return the index of the
- * existing string.
- */
+** already exist in the pool, SP_AddBuf will just return the index of the
+** existing string.
+*/
{
/* Search for a matching entry in the hash table */
StringPoolEntry* E = HT_Find (&P->Tab, S);
unsigned SP_AddStr (StringPool* P, const char* S)
/* Add a string to the buffer and return the index. If the string does already
- * exist in the pool, SP_Add will just return the index of the existing string.
- */
+** exist in the pool, SP_Add will just return the index of the existing string.
+*/
{
unsigned Id;
/* First make a string buffer, then add it. This is some overhead, but the
- * routine will probably go.
- */
+ ** routine will probably go.
+ */
StrBuf Buf;
Id = SP_Add (P, SB_InitFromString (&Buf, S));
/* A string pool is used to store identifiers and other strings. Each string
- * stored in the pool has a unique id, which may be used to access the string
- * in the pool. Identical strings are only stored once in the pool and have
- * identical ids. This means that instead of comparing strings, just the
- * string pool ids must be compared.
- */
+** stored in the pool has a unique ID, which may be used to access the string
+** in the pool. Identical strings are only stored once in the pool and have
+** identical IDs. This means that instead of comparing strings, just the
+** string pool IDs must be compared.
+*/
unsigned SP_Add (StringPool* P, const StrBuf* S);
/* Add a string buffer to the buffer and return the index. If the string does
- * already exist in the pool, SP_AddBuf will just return the index of the
- * existing string.
- */
+** already exist in the pool, SP_AddBuf will just return the index of the
+** existing string.
+*/
unsigned SP_AddStr (StringPool* P, const char* S);
/* Add a string to the buffer and return the index. If the string does already
- * exist in the pool, SP_Add will just return the index of the existing string.
- */
+** exist in the pool, SP_Add will just return the index of the existing string.
+*/
unsigned SP_GetCount (const StringPool* P);
/* Return the number of strings in the pool */
/* */
/* */
/* (C) 2001-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
char* StrCopy (char* Dest, size_t DestSize, const char* Source)
/* Copy Source to Dest honouring the maximum size of the target buffer. In
- * constrast to strncpy, the resulting string will always be NUL terminated.
- * The function returns the pointer to the destintation buffer.
- */
+** constrast to strncpy, the resulting string will always be NUL terminated.
+** The function returns the pointer to the destintation buffer.
+*/
{
size_t Len = strlen (Source);
if (Len >= DestSize) {
/* */
/* */
/* (C) 2001-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
char* StrCopy (char* Dest, size_t DestSize, const char* Source);
/* Copy Source to Dest honouring the maximum size of the target buffer. In
- * constrast to strncpy, the resulting string will always be NUL terminated.
- * The function returns the pointer to the destintation buffer.
- */
+** constrast to strncpy, the resulting string will always be NUL terminated.
+** The function returns the pointer to the destintation buffer.
+*/
int StrCaseCmp (const char* S1, const char* S2);
/* Compare two strings ignoring case */
};
/* Table that maps target names to ids. Sorted alphabetically for bsearch.
- * Allows mupltiple entries for one target id (target name aliases).
- */
+** Allows mupltiple entries for one target id (target name aliases).
+*/
static const TargetEntry TargetMap[] = {
{ "apple2", TGT_APPLE2 },
{ "apple2enh", TGT_APPLE2ENH },
target_t FindTarget (const char* Name)
/* Find a target by name and return the target id. TGT_UNKNOWN is returned if
- * the given name is no valid target.
- */
+** the given name is no valid target.
+*/
{
/* Search for the name in the map */
const TargetEntry* T;
target_t FindTarget (const char* Name);
/* Find a target by name and return the target id. TGT_UNKNOWN is returned if
- * the given name is no valid target.
- */
+** the given name is no valid target.
+*/
const TargetProperties* GetTargetProperties (target_t Target);
/* Return the properties for a target */
int TgtTranslateChar (int C)
/* Translate one character from the source character set into the target
- * system character set.
- */
+** system character set.
+*/
{
/* Translate */
return Tab[C & 0xFF];
void TgtTranslateBuf (void* Buf, unsigned Len)
/* Translate a buffer of the given length from the source character set into
- * the target system character set.
- */
+** the target system character set.
+*/
{
/* Translate */
unsigned char* B = (unsigned char*)Buf;
void TgtTranslateStrBuf (StrBuf* Buf)
/* Translate a string buffer from the source character set into the target
- * system character set.
- */
+** system character set.
+*/
{
TgtTranslateBuf (SB_GetBuf (Buf), SB_GetLen (Buf));
}
int TgtTranslateChar (int C);
/* Translate one character from the source character set into the target
- * system character set.
- */
+** system character set.
+*/
void TgtTranslateBuf (void* Buf, unsigned Len);
/* Translate a buffer of the given length from the source character set into
- * the target system character set.
- */
+** the target system character set.
+*/
void TgtTranslateStrBuf (StrBuf* Buf);
/* Translate a string buffer from the source character set into the target
- * system character set.
- */
+** system character set.
+*/
void TgtTranslateSet (unsigned Index, unsigned char C);
/* Set the translation code for the given character */
/* */
/* */
/* (C) 2000-2004 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* The following is a very basic vsnprintf like function called xvsnprintf. It
- * features only the basic format specifiers (especially the floating point
- * stuff is missing), but may be extended if required. Reason for supplying
- * my own implementation is that vsnprintf is standard but not implemented by
- * older compilers, and some that implement it, don't adhere to the standard
- * (for example Microsoft with its _vsnprintf).
- */
+** features only the basic format specifiers (especially the floating point
+** stuff is missing), but may be extended if required. Reason for supplying
+** my own implementation is that vsnprintf is standard but not implemented by
+** older compilers, and some that implement it, don't adhere to the standard
+** (for example Microsoft with its _vsnprintf).
+*/
typedef struct {
size_t BufFill;
/* Argument string buffer and string buffer pointer. The string buffer
- * must be big enough to hold a converted integer of the largest type
- * including an optional sign and terminating zero.
- */
+ ** must be big enough to hold a converted integer of the largest type
+ ** including an optional sign and terminating zero.
+ */
char ArgBuf[256];
int ArgLen;
ToStr (P, Val);
/* The default precision for all integer conversions is one. This means
- * that the fPrec flag is always set and does not need to be checked
- * later on.
- */
+ ** that the fPrec flag is always set and does not need to be checked
+ ** later on.
+ */
if ((P->Flags & fPrec) == 0) {
P->Flags |= fPrec;
P->Prec = 1;
unsigned WidthPadding;
/* Get the string length limited to the precision. Beware: We cannot use
- * strlen here, because if a precision is given, the string may not be
- * zero terminated.
- */
+ ** strlen here, because if a precision is given, the string may not be
+ ** zero terminated.
+ */
int Len;
if ((P->Flags & fPrec) != 0) {
const char* S = memchr (Val, '\0', P->Prec);
int xvsnprintf (char* Buf, size_t Size, const char* Format, va_list ap)
/* A basic vsnprintf implementation. Does currently only support integer
- * formats.
- */
+** formats.
+*/
{
PrintfCtrl P;
int Done;
if (F == '*') {
P.Width = va_arg (P.ap, int);
/* A negative field width argument is taken as a - flag followed
- * by a positive field width.
- */
+ ** by a positive field width.
+ */
if (P.Width < 0) {
P.Flags |= fMinus;
P.Width = -P.Width;
if (F == '*') {
P.Prec = va_arg (P.ap, int);
/* A negative precision argument is taken as if the precision
- * were omitted.
- */
+ ** were omitted.
+ */
if (P.Prec < 0) {
P.Flags &= ~fPrec;
}
}
} else if (F == '-') {
/* A negative precision argument is taken as if the precision
- * were omitted.
- */
+ ** were omitted.
+ */
F = *Format++; /* Skip the minus */
while (IsDigit (F = *Format++)) ;
P.Flags &= ~fPrec;
/* Handle the length by using a precision */
if ((P.Flags & fPrec) != 0) {
/* Precision already specified, use length of string
- * if less.
- */
+ ** if less.
+ */
if ((unsigned) P.Prec > SB_GetLen (S)) {
P.Prec = SB_GetLen (S);
}
va_end (P.ap);
/* Terminate the output string and return the number of chars that had
- * been written if the buffer was large enough.
- * Beware: The terminating zero is not counted for the function result!
- */
+ ** been written if the buffer was large enough.
+ ** Beware: The terminating zero is not counted for the function result!
+ */
AddChar (&P, '\0');
return P.BufFill - 1;
}
int xsnprintf (char* Buf, size_t Size, const char* Format, ...)
/* A basic snprintf implementation. Does currently only support integer
- * formats.
- */
+** formats.
+*/
{
int Res;
va_list ap;
/* We need a way to output a StrBuf, but on the other side, we don't want to
- * switch off gcc's printf format string checking. So we cheat as follows:
- * %m (which is a gcc extension and doesn't take an argument) switches %p
- * between outputting a pointer and a string buf. This works just one time,
- * so each StrBuf needs in fact a %m%p spec. There's no way to apply a width
- * and precision to such a StrBuf, but *not* using %p would bring up a warning
- * about a wrong argument type each time. Maybe gcc will one day allow custom
- * format specifiers and we can change this ...
- */
+** switch off gcc's printf format string checking. So we cheat as follows:
+** %m (which is a gcc extension and doesn't take an argument) switches %p
+** between outputting a pointer and a string buf. This works just one time,
+** so each StrBuf needs in fact a %m%p spec. There's no way to apply a width
+** and precision to such a StrBuf, but *not* using %p would bring up a warning
+** about a wrong argument type each time. Maybe gcc will one day allow custom
+** format specifiers and we can change this ...
+*/
int xvsnprintf (char* Buf, size_t Size, const char* Format, va_list ap)
attribute ((format (printf, 3, 0)));
/* A basic vsnprintf implementation. Does currently only support integer
- * formats.
- */
+** formats.
+*/
int xsnprintf (char* Buf, size_t Size, const char* Format, ...)
attribute ((format (printf, 3, 4)));
/* A basic snprintf implementation. Does currently only support integer
- * formats.
- */
+** formats.
+*/
int xsprintf (char* Buf, size_t BufSize, const char* Format, ...)
attribute ((format (printf, 3, 4)));
}
/* Determine the base of the number. Allow $ and % as prefixes for
- * hex and binary numbers respectively.
- */
+ ** hex and binary numbers respectively.
+ */
if (*L == '$') {
Base = 16;
++L;
/* */
/* */
/* (C) 2000-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
}
/* Seek to the input offset and correct size to contain the remainder of
- * the file.
- */
+ ** the file.
+ */
if (fseek (F, InputOffs, SEEK_SET) != 0) {
Error ("Cannot seek on file `%s': %s", InFile, strerror (errno));
}
}
/* If the start address was not given, set it so that the code loads to
- * 0x10000 - Size. This is a reasonable default assuming that the file
- * is a ROM that contains the hardware vectors at $FFFA.
- */
+ ** 0x10000 - Size. This is a reasonable default assuming that the file
+ ** is a ROM that contains the hardware vectors at $FFFA.
+ */
if (StartAddr < 0) {
if (Size > 0x10000) {
StartAddr = 0;
unsigned RemainingBytes = GetRemainingBytes ();
/* Count how many bytes are available. This number is limited by the
- * number of remaining bytes, a label, a segment change, or the end of
- * the given Style attribute.
- */
+ ** number of remaining bytes, a label, a segment change, or the end of
+ ** the given Style attribute.
+ */
unsigned Count = 1;
while (Count < RemainingBytes) {
attr_t Attr;
unsigned Count = GetSpan (Style);
/* If the count is less than the member size, print a row of Count data
- * bytes. We assume here that there is no member with a size that is less
- * than BytesPerLine.
- */
+ ** bytes. We assume here that there is no member with a size that is less
+ ** than BytesPerLine.
+ */
if (Count < MemberSize) {
DataByteLine (Count);
PC += Count;
unsigned long Start = PC;
/* Loop while table bytes left and we don't need to create a label at the
- * current position.
- */
+ ** current position.
+ */
while (BytesLeft && GetStyleAttr (PC) == atAddrTab) {
unsigned Addr;
unsigned long Start = PC;
/* Loop while table bytes left and we don't need to create a label at the
- * current position.
- */
+ ** current position.
+ */
while (BytesLeft && GetStyleAttr (PC) == atRtsTab) {
unsigned Addr;
static const char* GetAbsOverride (unsigned Flags, unsigned Addr)
/* If the instruction requires an abs override modifier, return the necessary
- * string, otherwise return the empty string.
- */
+** string, otherwise return the empty string.
+*/
{
if ((Flags & flAbsOverride) != 0 && Addr < 0x100) {
return "a:";
((Flags & flUseLabel) != 0 && Addr >= CodeStart && Addr <= CodeEnd))) {
/* As a special case, handle ranges with tables or similar. Within
- * such a range with a granularity > 1, do only generate dependent
- * labels for all addresses but the first one. Be sure to generate
- * a label for the start of the range, however.
- */
+ ** such a range with a granularity > 1, do only generate dependent
+ ** labels for all addresses but the first one. Be sure to generate
+ ** a label for the start of the range, however.
+ */
attr_t Style = GetStyleAttr (Addr);
unsigned Granularity = GetGranularity (Style);
/* Search for the start of the range or the last non dependent
- * label in the range.
- */
+ ** label in the range.
+ */
unsigned Offs;
attr_t LabelAttr;
unsigned LabelAddr = Addr;
unsigned BranchAddr = (((int) PC+3) + BranchOffs) & 0xFFFF;
/* Generate labels in pass 1. The bit branch codes are special in that
- * they don't really match the remainder of the 6502 instruction set (they
- * are a Rockwell addon), so we must pass additional flags as direct
- * value to the second GenerateLabel call.
- */
+ ** they don't really match the remainder of the 6502 instruction set (they
+ ** are a Rockwell addon), so we must pass additional flags as direct
+ ** value to the second GenerateLabel call.
+ */
GenerateLabel (D->Flags, TestAddr);
GenerateLabel (flLabel, BranchAddr);
static const char* MakeLabelName (unsigned Addr)
/* Make the default label name from the given address and return it in a
- * static buffer.
- */
+** static buffer.
+*/
{
static char LabelBuf [32];
xsprintf (LabelBuf, sizeof (LabelBuf), "L%04X", Addr);
/* Must not have two symbols for one address */
if (ExistingAttr != atNoLabel) {
/* Allow redefinition if identical. Beware: Unnamed labels don't
- * have a name (you guessed that, didn't you?).
- */
+ ** have a name (you guessed that, didn't you?).
+ */
if (ExistingAttr == Attr &&
((Name == 0 && SymTab[Addr] == 0) || strcmp (SymTab[Addr], Name) == 0)) {
return;
void AddDepLabel (unsigned Addr, attr_t Attr, const char* BaseName, unsigned Offs)
/* Add a dependent label at the given address using "basename+Offs" as the new
- * name.
- */
+** name.
+*/
{
/* Allocate memory for the dependent label name */
unsigned NameLen = strlen (BaseName);
static void AddLabelRange (unsigned Addr, attr_t Attr,
const char* Name, unsigned Count)
/* Add a label for a range. The first entry gets the label "Name" while the
- * others get "Name+offs".
- */
+** others get "Name+offs".
+*/
{
/* Define the label */
AddLabel (Addr, Attr, Name);
void AddIntLabelRange (unsigned Addr, const char* Name, unsigned Count)
/* Add an internal label for a range. The first entry gets the label "Name"
- * while the others get "Name+offs".
- */
+** while the others get "Name+offs".
+*/
{
/* Define the label range */
AddLabelRange (Addr, atIntLabel, Name, Count);
void AddExtLabelRange (unsigned Addr, const char* Name, unsigned Count)
/* Add an external label for a range. The first entry gets the label "Name"
- * while the others get "Name+offs".
- */
+** while the others get "Name+offs".
+*/
{
/* Define the label range */
AddLabelRange (Addr, atExtLabel, Name, Count);
int MustDefLabel (unsigned Addr)
/* Return true if we must define a label for this address, that is, if there
- * is a label at this address, and it is an external or internal label.
- */
+** is a label at this address, and it is an external or internal label.
+*/
{
/* Get the label attribute */
attr_t A = GetLabelAttr (Addr);
attr_t A = GetLabelAttr (Addr);
/* Special case unnamed labels, because these don't have a named stored in
- * the symbol table to save space.
- */
+ ** the symbol table to save space.
+ */
if (A == atUnnamedLabel) {
return "";
} else {
const char* GetLabel (unsigned Addr, unsigned RefFrom)
/* Return the label name for an address, as it is used in a label reference.
- * RefFrom is the address the label is referenced from. This is needed in case
- * of unnamed labels, to determine the name.
- */
+** RefFrom is the address the label is referenced from. This is needed in case
+** of unnamed labels, to determine the name.
+*/
{
static const char* FwdLabels[] = {
":+", ":++", ":+++", ":++++", ":+++++", ":++++++", ":+++++++",
attr_t A = GetLabelAttr (Addr);
/* Special case unnamed labels, because these don't have a named stored in
- * the symbol table to save space.
- */
+ ** the symbol table to save space.
+ */
if (A == atUnnamedLabel) {
unsigned Count = 0;
/* Search forward or backward depending in which direction the label
- * is.
- */
+ ** is.
+ */
if (Addr <= RefFrom) {
/* Search backwards */
unsigned I = RefFrom;
void ForwardLabel (unsigned Offs)
/* If necessary, output a forward label, one that is within the next few
- * bytes and is therefore output as "label = * + x".
- */
+** bytes and is therefore output as "label = * + x".
+*/
{
/* Calculate the actual address */
unsigned long Addr = PC + Offs;
}
/* An unnamed label cannot be output as a forward declaration, so this is
- * an error.
- */
+ ** an error.
+ */
if (A == atUnnamedLabel) {
Error ("Cannot define unnamed label at address $%04lX", Addr);
}
/* */
/* */
/* (C) 2006 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
void AddDepLabel (unsigned Addr, attr_t Attr, const char* BaseName, unsigned Offs);
/* Add a dependent label at the given address using "base name+Offs" as the new
- * name.
- */
+** name.
+*/
void AddIntLabelRange (unsigned Addr, const char* Name, unsigned Count);
/* Add an internal label for a range. The first entry gets the label "Name"
- * while the others get "Name+offs".
- */
+** while the others get "Name+offs".
+*/
void AddExtLabelRange (unsigned Addr, const char* Name, unsigned Count);
/* Add an external label for a range. The first entry gets the label "Name"
- * while the others get "Name+offs".
- */
+** while the others get "Name+offs".
+*/
int HaveLabel (unsigned Addr);
/* Check if there is a label for the given address */
int MustDefLabel (unsigned Addr);
/* Return true if we must define a label for this address, that is, if there
- * is a label at this address, and it is an external or internal label.
- */
+** is a label at this address, and it is an external or internal label.
+*/
const char* GetLabelName (unsigned Addr);
/* Return the label name for an address */
const char* GetLabel (unsigned Addr, unsigned RefFrom);
/* Return the label name for an address, as it is used in a label reference.
- * RefFrom is the address the label is referenced from. This is needed in case
- * of unnamed labels, to determine the name.
- */
+** RefFrom is the address the label is referenced from. This is needed in case
+** of unnamed labels, to determine the name.
+*/
void ForwardLabel (unsigned Offs);
/* If necessary, output a forward label, one that is within the next few
- * bytes and is therefore output as "label = * + x".
- */
+** bytes and is therefore output as "label = * + x".
+*/
void DefOutOfRangeLabels (void);
/* Output any labels that are out of the loaded code range */
/* */
/* */
/* */
-/* (C) 1998-2011, Ullrich von Bassewitz */
-/* Roemerstrasse 52 */
-/* D-70794 Filderstadt */
-/* EMail: uz@cc65.org */
+/* (C) 1998-2011, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
static void RangeCheck (const char* Opt, unsigned long Val,
unsigned long Min, unsigned long Max)
/* Do a range check for the given option and abort if there's a range
- * error.
- */
+** error.
+*/
{
if (Val < Min || Val > Max) {
Error ("Argument for %s outside valid range (%ld-%ld)", Opt, Min, Max);
static unsigned long CvtNumber (const char* Arg, const char* Number)
/* Convert a number from a string. Allow '$' and '0x' prefixes for hex
- * numbers.
- */
+** numbers.
+*/
{
unsigned long Val;
int Converted;
attr_t Style = GetStyleAttr (PC);
/* If we have a label at this address, output the label and an attached
- * comment, provided that we aren't in a skip area.
- */
+ ** comment, provided that we aren't in a skip area.
+ */
if (Style != atSkip && MustDefLabel (PC)) {
const char* Comment = GetComment (PC);
if (Comment) {
}
/* Check...
- * - ...if we have enough bytes remaining for the code at this address.
- * - ...if the current instruction is valid for the given CPU.
- * - ...if there is no label somewhere between the instruction bytes.
- * If any of these conditions is false, switch to data mode.
- */
+ ** - ...if we have enough bytes remaining for the code at this address.
+ ** - ...if the current instruction is valid for the given CPU.
+ ** - ...if there is no label somewhere between the instruction bytes.
+ ** If any of these conditions is false, switch to data mode.
+ */
if (Style == atDefault) {
if (D->Size > RemainingBytes) {
Style = atIllegal;
case atCode:
/* Beware: If we don't have enough bytes left to disassemble the
- * following insn, fall through to byte mode.
- */
+ ** following insn, fall through to byte mode.
+ */
if (D->Size <= RemainingBytes) {
/* Output labels within the next insn */
unsigned I;
}
/* Check the formatting options for reasonable values. Note: We will not
- * really check that they make sense, just that they aren't complete
- * garbage.
- */
+ ** really check that they make sense, just that they aren't complete
+ ** garbage.
+ */
if (MCol >= ACol) {
AbEnd ("mnemonic-column value must be smaller than argument-column value");
}
}
/* Get the current time and convert it to string so it can be used in
- * the output page headers.
- */
+ ** the output page headers.
+ */
T = time (0);
strftime (Now, sizeof (Now), "%Y-%m-%d %H:%M:%S", localtime (&T));
/* Descriptions for all opcodes. Base table from opc6502.c with illegal
- * opcodes from http://www.oxyron.de/html/opcodes02.html
- */
+** opcodes from http://www.oxyron.de/html/opcodes02.html
+*/
const OpcDesc OpcTable_6502X[256] = {
{ "brk", 1, flNone, OH_Implicit }, /* $00 */
{ "ora", 2, flUseLabel, OH_DirectXIndirect }, /* $01 */
{
Output ("%s:", Name);
/* If the label is longer than the configured maximum, or if it runs into
- * the opcode column, start a new line.
- */
+ ** the opcode column, start a new line.
+ */
if (Col > LBreak+2 || Col > MCol) {
LineFeed ();
}
void DefForward (const char* Name, const char* Comment, unsigned Offs)
/* Define a label as "* + x", where x is the offset relative to the
- * current PC.
- */
+** current PC.
+*/
{
if (Pass == PassCount) {
/* Flush existing output if necessary */
void DefForward (const char* Name, const char* Comment, unsigned Offs);
/* Define a label as "* + x", where x is the offset relative to the
- * current PC.
- */
+** current PC.
+*/
void DefConst (const char* Name, const char* Comment, unsigned Addr);
/* Define an address constant */
};
/* Tables containing the segments. A segment is inserted using it's hash
- * value. Collision is done by single linked lists.
- */
+** value. Collision is done by single linked lists.
+*/
static Segment* StartTab[HASH_SIZE]; /* Table containing segment starts */
static Segment* EndTab[HASH_SIZE]; /* Table containing segment ends */
#define STRBUF_INITIALIZER { 0, 0, 0 }
/* An array of unsigneds/pointers that grows if needed. C guarantees that a
- * pointer to a union correctly converted points to each of its members.
- * So what we do here is using union entries that contain an unsigned
- * (used to store ids until they're resolved) and pointers to actual items
- * in storage.
- */
+** pointer to a union correctly converted points to each of its members.
+** So what we do here is using union entries that contain an unsigned
+** (used to store ids until they're resolved) and pointers to actual items
+** in storage.
+*/
typedef union CollEntry CollEntry;
union CollEntry {
void* Ptr;
#define COLLECTION_INITIALIZER { 0, 0, 0 }
/* Span info management. The following table has as many entries as there
- * are addresses active in spans. Each entry lists the spans for this address.
- */
+** are addresses active in spans. Each entry lists the spans for this address.
+*/
typedef struct SpanInfoListEntry SpanInfoListEntry;
struct SpanInfoListEntry {
cc65_addr Addr; /* Unique address */
} Token;
/* Data structure containing information from the debug info file. A pointer
- * to this structure is passed as handle to callers from the outside.
- */
+** to this structure is passed as handle to callers from the outside.
+*/
typedef struct DbgInfo DbgInfo;
struct DbgInfo {
/* First we have all items in collections sorted by id. The ids are
- * continous, so an access by id is almost as cheap as an array access.
- * The collections are also used when the objects are deleted, so they're
- * actually the ones that "own" the items.
- */
+ ** continous, so an access by id is almost as cheap as an array access.
+ ** The collections are also used when the objects are deleted, so they're
+ ** actually the ones that "own" the items.
+ */
Collection CSymInfoById; /* C symbol infos sorted by id */
Collection FileInfoById; /* File infos sorted by id */
Collection LibInfoById; /* Library infos sorted by id */
};
/* A structure used when parsing a type string into a set of cc65_typedata
- * structures.
- */
+** structures.
+*/
typedef struct TypeParseData TypeParseData;
struct TypeParseData {
TypeInfo* Info;
static void SB_Realloc (StrBuf* B, unsigned NewSize)
/* Reallocate the string buffer space, make sure at least NewSize bytes are
- * available.
- */
+** available.
+*/
{
/* Get the current size, use a minimum of 8 bytes */
unsigned NewAllocated = B->Allocated;
}
/* Reallocate the buffer. Beware: The allocated size may be zero while the
- * length is not. This means that we have a buffer that wasn't allocated
- * on the heap.
- */
+ ** length is not. This means that we have a buffer that wasn't allocated
+ ** on the heap.
+ */
if (B->Allocated) {
/* Just reallocate the block */
B->Buf = xrealloc (B->Buf, NewAllocated);
static void SB_CheapRealloc (StrBuf* B, unsigned NewSize)
/* Reallocate the string buffer space, make sure at least NewSize bytes are
- * available. This function won't copy the old buffer contents over to the new
- * buffer and may be used if the old contents are overwritten later.
- */
+** available. This function won't copy the old buffer contents over to the new
+** buffer and may be used if the old contents are overwritten later.
+*/
{
/* Get the current size, use a minimum of 8 bytes */
unsigned NewAllocated = B->Allocated;
static void SB_Terminate (StrBuf* B)
/* Zero terminate the given string buffer. NOTE: The terminating zero is not
- * accounted for in B->Len, if you want that, you have to use AppendChar!
- */
+** accounted for in B->Len, if you want that, you have to use AppendChar!
+*/
{
unsigned NewLen = B->Len + 1;
if (NewLen > B->Allocated) {
static char* SB_StrDup (const StrBuf* B)
/* Return the contents of B as a dynamically allocated string. The string
- * will always be NUL terminated.
- */
+** will always be NUL terminated.
+*/
{
/* Allocate memory */
char* S = xmalloc (B->Len + 1);
static void CollDone (Collection* C)
/* Free the data for a collection. This will not free the data contained in
- * the collection.
- */
+** the collection.
+*/
{
/* Free the pointer array */
xfree (C->Items);
/* Clear the fields, so the collection may be reused (or CollDone called)
- * again
- */
+ ** again
+ */
C->Count = 0;
C->Size = 0;
C->Items = 0;
static void CollMove (Collection* Source, Collection* Target)
/* Move all data from one collection to another. This function will first free
- * the data in the target collection, and - after the move - clear the data
- * from the source collection.
- */
+** the data in the target collection, and - after the move - clear the data
+** from the source collection.
+*/
{
/* Free the target collection data */
xfree (Target->Items);
static void CollGrow (Collection* C, unsigned Size)
/* Grow the collection C so it is able to hold Size items without a resize
- * being necessary. This can be called for performance reasons if the number
- * of items to be placed in the collection is known in advance.
- */
+** being necessary. This can be called for performance reasons if the number
+** of items to be placed in the collection is known in advance.
+*/
{
CollEntry* NewItems;
static void CollReplaceExpand (Collection* C, void* Item, unsigned Index)
/* If Index is a valid index for the collection, replace the item at this
- * position by the one passed. If the collection is too small, expand it,
- * filling unused pointers with NULL, then add the new item at the given
- * position.
- */
+** position by the one passed. If the collection is too small, expand it,
+** filling unused pointers with NULL, then add the new item at the given
+** position.
+*/
{
if (Index < C->Count) {
/* Collection is already large enough */
static unsigned GetId (const void* Data)
/* Return the id of one of the info structures. All structures have the Id
- * field as first member, and the C standard allows converting a union pointer
- * to the data type of the first member, so this is safe and portable.
- */
+** field as first member, and the C standard allows converting a union pointer
+** to the data type of the first member, so this is safe and portable.
+*/
{
if (Data) {
return *(const unsigned*)Data;
static void UnknownKeyword (InputData* D)
/* Print a warning about an unknown keyword in the file. Try to do smart
- * recovery, so if later versions of the debug information add additional
- * keywords, this code may be able to at least ignore them.
- */
+** recovery, so if later versions of the debug information add additional
+** keywords, this code may be able to at least ignore them.
+*/
{
/* Output a warning */
ParseError (D, CC65_WARNING, "Unknown keyword \"%s\" - skipping",
NextToken (D);
/* If an equal sign follows, ignore anything up to the next line end
- * or comma. If a comma or line end follows, we're already done. If
- * we have none of both, we ignore the remainder of the line.
- */
+ ** or comma. If a comma or line end follows, we're already done. If
+ ** we have none of both, we ignore the remainder of the line.
+ */
if (D->Tok == TOK_EQUAL) {
NextToken (D);
while (D->Tok != TOK_COMMA && D->Tok != TOK_EOL && D->Tok != TOK_EOF) {
static cc65_csyminfo* new_cc65_csyminfo (unsigned Count)
/* Allocate and return a cc65_csyminfo struct that is able to hold Count
- * entries. Initialize the count field of the returned struct.
- */
+** entries. Initialize the count field of the returned struct.
+*/
{
cc65_csyminfo* S = xmalloc (sizeof (*S) - sizeof (S->data[0]) +
Count * sizeof (S->data[0]));
static cc65_sourceinfo* new_cc65_sourceinfo (unsigned Count)
/* Allocate and return a cc65_sourceinfo struct that is able to hold Count
- * entries. Initialize the count field of the returned struct.
- */
+** entries. Initialize the count field of the returned struct.
+*/
{
cc65_sourceinfo* S = xmalloc (sizeof (*S) - sizeof (S->data[0]) +
Count * sizeof (S->data[0]));
/* Helper function to sort file infos in a collection by name */
{
/* Sort by file name. If names are equal, sort by timestamp,
- * then sort by size. Which means, identical files will go
- * together.
- */
+ ** then sort by size. Which means, identical files will go
+ ** together.
+ */
int Res = strcmp (((const FileInfo*) L)->Name,
((const FileInfo*) R)->Name);
if (Res != 0) {
static cc65_libraryinfo* new_cc65_libraryinfo (unsigned Count)
/* Allocate and return a cc65_libraryinfo struct that is able to hold Count
- * entries. Initialize the count field of the returned struct.
- */
+** entries. Initialize the count field of the returned struct.
+*/
{
cc65_libraryinfo* L = xmalloc (sizeof (*L) - sizeof (L->data[0]) +
Count * sizeof (L->data[0]));
static cc65_lineinfo* new_cc65_lineinfo (unsigned Count)
/* Allocate and return a cc65_lineinfo struct that is able to hold Count
- * entries. Initialize the count field of the returned struct.
- */
+** entries. Initialize the count field of the returned struct.
+*/
{
cc65_lineinfo* L = xmalloc (sizeof (*L) - sizeof (L->data[0]) +
Count * sizeof (L->data[0]));
static cc65_moduleinfo* new_cc65_moduleinfo (unsigned Count)
/* Allocate and return a cc65_moduleinfo struct that is able to hold Count
- * entries. Initialize the count field of the returned struct.
- */
+** entries. Initialize the count field of the returned struct.
+*/
{
cc65_moduleinfo* M = xmalloc (sizeof (*M) - sizeof (M->data[0]) +
Count * sizeof (M->data[0]));
static cc65_scopeinfo* new_cc65_scopeinfo (unsigned Count)
/* Allocate and return a cc65_scopeinfo struct that is able to hold Count
- * entries. Initialize the count field of the returned struct.
- */
+** entries. Initialize the count field of the returned struct.
+*/
{
cc65_scopeinfo* S = xmalloc (sizeof (*S) - sizeof (S->data[0]) +
Count * sizeof (S->data[0]));
static cc65_segmentinfo* new_cc65_segmentinfo (unsigned Count)
/* Allocate and return a cc65_segmentinfo struct that is able to hold Count
- * entries. Initialize the count field of the returned struct.
- */
+** entries. Initialize the count field of the returned struct.
+*/
{
cc65_segmentinfo* S = xmalloc (sizeof (*S) - sizeof (S->data[0]) +
Count * sizeof (S->data[0]));
static cc65_spaninfo* new_cc65_spaninfo (unsigned Count)
/* Allocate and return a cc65_spaninfo struct that is able to hold Count
- * entries. Initialize the count field of the returned struct.
- */
+** entries. Initialize the count field of the returned struct.
+*/
{
cc65_spaninfo* S = xmalloc (sizeof (*S) - sizeof (S->data[0]) +
Count * sizeof (S->data[0]));
static int CompareSpanInfoByAddr (const void* L, const void* R)
/* Helper function to sort span infos in a collection by address. Span infos
- * with smaller start address are considered smaller. If start addresses are
- * equal, line spans with smaller end address are considered smaller. This
- * means, that when CompareSpanInfoByAddr is used for sorting, a range with
- * identical start addresses will have smaller spans first, followed by
- * larger spans.
- */
+** with smaller start address are considered smaller. If start addresses are
+** equal, line spans with smaller end address are considered smaller. This
+** means, that when CompareSpanInfoByAddr is used for sorting, a range with
+** identical start addresses will have smaller spans first, followed by
+** larger spans.
+*/
{
/* Sort by start of span */
if (((const SpanInfo*) L)->Start > ((const SpanInfo*) R)->Start) {
static cc65_symbolinfo* new_cc65_symbolinfo (unsigned Count)
/* Allocate and return a cc65_symbolinfo struct that is able to hold Count
- * entries. Initialize the count field of the returned struct.
- */
+** entries. Initialize the count field of the returned struct.
+*/
{
cc65_symbolinfo* S = xmalloc (sizeof (*S) - sizeof (S->data[0]) +
Count * sizeof (S->data[0]));
D->symbol_size = S->Size;
/* If this is an import, it doesn't have a value or segment. Use the data
- * from the matching export instead.
- */
+ ** from the matching export instead.
+ */
if (S->Exp.Info) {
/* This is an import, because it has a matching export */
D->export_id = S->Exp.Info->Id;
/* Helper function to sort symbol infos in a collection by value */
{
/* Sort by symbol value. If both are equal, sort by symbol name so it
- * looks nice when such a list is returned.
- */
+ ** looks nice when such a list is returned.
+ */
if (((const SymInfo*) L)->Value > ((const SymInfo*) R)->Value) {
return 1;
} else if (((const SymInfo*) L)->Value < ((const SymInfo*) R)->Value) {
static cc65_typedata* TypeFromString (TypeParseData* P)
/* Parse a type string and return a set of typedata structures. Will be called
- * recursively. Will set P->Error and return NULL in case of problems.
- */
+** recursively. Will set P->Error and return NULL in case of problems.
+*/
{
cc65_typedata* Data;
unsigned char B;
static TypeInfo* ParseTypeString (InputData* D, StrBuf* Type)
/* Check if the string T contains a valid type string. Convert it from readable
- * to binary. Calculate how many cc65_typedata structures are necessary when it
- * is converted. Convert the string into a set of cc65_typedata structures and
- * return them.
- */
+** to binary. Calculate how many cc65_typedata structures are necessary when it
+** is converted. Convert the string into a set of cc65_typedata structures and
+** return them.
+*/
{
unsigned I;
unsigned Count;
Type->Len = (Length /= 2);
/* Get a pointer to the type data, then count the number of cc65_typedata
- * items needed.
- */
+ ** items needed.
+ */
A = SB_GetConstBuf (Type);
Count = 0;
I = 0;
static void CreateSpanInfoList (SpanInfoList* L, Collection* SpanInfos)
/* Create a SpanInfoList from a Collection with span infos. The collection
- * must be sorted by ascending start addresses.
- */
+** must be sorted by ascending start addresses.
+*/
{
unsigned I, J;
SpanInfo* S;
S = CollAt (SpanInfos, I);
/* Determine the start index of the next range. Line infos are sorted
- * by ascending start address, so the start address of the next entry
- * is always larger than the previous one - we don't need to check
- * that.
- */
+ ** by ascending start address, so the start address of the next entry
+ ** is always larger than the previous one - we don't need to check
+ ** that.
+ */
if (S->Start <= End) {
/* Range starts within out already known linear range */
StartIndex += (unsigned) (S->Start - Start);
for (I = 0, List = L->List; I < L->Count; ++I, ++List) {
/* For a count of 1, we store the pointer to the lineinfo for this
- * address in the Data pointer directly. For counts > 1, we allocate
- * an array of pointers and reset the counter, so we can use it as
- * an index later. This is dangerous programming since it disables
- * all possible checks!
- */
+ ** address in the Data pointer directly. For counts > 1, we allocate
+ ** an array of pointers and reset the counter, so we can use it as
+ ** an index later. This is dangerous programming since it disables
+ ** all possible checks!
+ */
if (List->Count > 1) {
List->Data = xmalloc (List->Count * sizeof (SpanInfo*));
List->Count = 0;
S = CollAt (SpanInfos, I);
/* Determine the start index of the next range. Line infos are sorted
- * by ascending start address, so the start address of the next entry
- * is always larger than the previous one - we don't need to check
- * that.
- */
+ ** by ascending start address, so the start address of the next entry
+ ** is always larger than the previous one - we don't need to check
+ ** that.
+ */
if (S->Start <= End) {
/* Range starts within out already known linear range */
StartIndex += (unsigned) (S->Start - Start);
static int Consume (InputData* D, Token Tok, const char* Name)
/* Check for a token and consume it. Return true if the token was comsumed,
- * return false otherwise.
- */
+** return false otherwise.
+*/
{
if (TokenFollows (D, Tok, Name)) {
NextToken (D);
/* Parse a CSYM line */
{
/* Most of the following variables are initialized with a value that is
- * overwritten later. This is just to avoid compiler warnings.
- */
+ ** overwritten later. This is just to avoid compiler warnings.
+ */
unsigned Id = 0;
StrBuf Name = STRBUF_INITIALIZER;
int Offs = 0;
}
/* Remember the token, skip it, check for equal, check for an integer
- * constant.
- */
+ ** constant.
+ */
Tok = D->Tok;
NextToken (D);
if (!ConsumeEqual (D)) {
/* Parse a MODULE line */
{
/* Most of the following variables are initialized with a value that is
- * overwritten later. This is just to avoid compiler warnings.
- */
+ ** overwritten later. This is just to avoid compiler warnings.
+ */
unsigned Id = CC65_INV_ID;
StrBuf Name = STRBUF_INITIALIZER;
unsigned FileId = CC65_INV_ID;
/* Parse a SCOPE line */
{
/* Most of the following variables are initialized with a value that is
- * overwritten later. This is just to avoid compiler warnings.
- */
+ ** overwritten later. This is just to avoid compiler warnings.
+ */
unsigned Id = CC65_INV_ID;
cc65_scope_type Type = CC65_SCOPE_MODULE;
cc65_size Size = 0;
/* Parse a SYM line */
{
/* Most of the following variables are initialized with a value that is
- * overwritten later. This is just to avoid compiler warnings.
- */
+ ** overwritten later. This is just to avoid compiler warnings.
+ */
Collection DefLineIds = COLLECTION_INITIALIZER;
unsigned ExportId = CC65_INV_ID;
unsigned FileId = CC65_INV_ID;
/* Parse a TYPE line */
{
/* Most of the following variables are initialized with a value that is
- * overwritten later. This is just to avoid compiler warnings.
- */
+ ** overwritten later. This is just to avoid compiler warnings.
+ */
unsigned Id = CC65_INV_ID;
StrBuf Value = STRBUF_INITIALIZER;
case TOK_IDENT:
/* Try to skip unknown keywords that may have been added by
- * a later version.
- */
+ ** a later version.
+ */
UnknownKeyword (D);
break;
static int FindCSymInfoByName (const Collection* CSymInfos, const char* Name,
unsigned* Index)
/* Find the C symbol info with a given file name. The function returns true if
- * the name was found. In this case, Index contains the index of the first item
- * that matches. If the item wasn't found, the function returns false and
- * Index contains the insert position for Name.
- */
+** the name was found. In this case, Index contains the index of the first item
+** that matches. If the item wasn't found, the function returns false and
+** Index contains the insert position for Name.
+*/
{
/* Do a binary search */
int Lo = 0;
} else {
Hi = Cur - 1;
/* Since we may have duplicates, repeat the search until we've
- * the first item that has a match.
- */
+ ** the first item that has a match.
+ */
if (Res == 0) {
Found = 1;
}
static int FindFileInfoByName (const Collection* FileInfos, const char* Name,
unsigned* Index)
/* Find the FileInfo for a given file name. The function returns true if the
- * name was found. In this case, Index contains the index of the first item
- * that matches. If the item wasn't found, the function returns false and
- * Index contains the insert position for Name.
- */
+** name was found. In this case, Index contains the index of the first item
+** that matches. If the item wasn't found, the function returns false and
+** Index contains the insert position for Name.
+*/
{
/* Do a binary search */
int Lo = 0;
} else {
Hi = Cur - 1;
/* Since we may have duplicates, repeat the search until we've
- * the first item that has a match.
- */
+ ** the first item that has a match.
+ */
if (Res == 0) {
Found = 1;
}
static SpanInfoListEntry* FindSpanInfoByAddr (const SpanInfoList* L, cc65_addr Addr)
/* Find the index of a SpanInfo for a given address. Returns 0 if no such
- * SpanInfo was found.
- */
+** SpanInfo was found.
+*/
{
/* Do a binary search */
int Lo = 0;
static LineInfo* FindLineInfoByLine (const Collection* LineInfos, cc65_line Line)
/* Find the LineInfo for a given line number. The function returns the line
- * info or NULL if none was found.
- */
+** info or NULL if none was found.
+*/
{
/* Do a binary search */
int Lo = 0;
static SegInfo* FindSegInfoByName (const Collection* SegInfos, const char* Name)
/* Find the SegInfo for a given segment name. The function returns the segment
- * info or NULL if none was found.
- */
+** info or NULL if none was found.
+*/
{
/* Do a binary search */
int Lo = 0;
static int FindScopeInfoByName (const Collection* ScopeInfos, const char* Name,
unsigned* Index)
/* Find the ScopeInfo for a given scope name. The function returns true if the
- * name was found. In this case, Index contains the index of the first item
- * that matches. If the item wasn't found, the function returns false and
- * Index contains the insert position for Name.
- */
+** name was found. In this case, Index contains the index of the first item
+** that matches. If the item wasn't found, the function returns false and
+** Index contains the insert position for Name.
+*/
{
/* Do a binary search */
int Lo = 0;
} else {
Hi = Cur - 1;
/* Since we may have duplicates, repeat the search until we've
- * the first item that has a match.
- */
+ ** the first item that has a match.
+ */
if (Res == 0) {
Found = 1;
}
static int FindSymInfoByName (const Collection* SymInfos, const char* Name,
unsigned* Index)
/* Find the SymInfo for a given file name. The function returns true if the
- * name was found. In this case, Index contains the index of the first item
- * that matches. If the item wasn't found, the function returns false and
- * Index contains the insert position for Name.
- */
+** name was found. In this case, Index contains the index of the first item
+** that matches. If the item wasn't found, the function returns false and
+** Index contains the insert position for Name.
+*/
{
/* Do a binary search */
int Lo = 0;
} else {
Hi = Cur - 1;
/* Since we may have duplicates, repeat the search until we've
- * the first item that has a match.
- */
+ ** the first item that has a match.
+ */
if (Res == 0) {
Found = 1;
}
static int FindSymInfoByValue (const Collection* SymInfos, long Value,
unsigned* Index)
/* Find the SymInfo for a given value. The function returns true if the
- * value was found. In this case, Index contains the index of the first item
- * that matches. If the item wasn't found, the function returns false and
- * Index contains the insert position for the given value.
- */
+** value was found. In this case, Index contains the index of the first item
+** that matches. If the item wasn't found, the function returns false and
+** Index contains the insert position for the given value.
+*/
{
/* Do a binary search */
int Lo = 0;
} else {
Hi = Cur - 1;
/* Since we may have duplicates, repeat the search until we've
- * the first item that has a match.
- */
+ ** the first item that has a match.
+ */
if (Value == CurItem->Value) {
Found = 1;
}
unsigned I;
/* Walk over all c symbols. Resolve the ids and add the c symbols to the
- * corresponding asm symbols.
- */
+ ** corresponding asm symbols.
+ */
for (I = 0; I < CollCount (&D->Info->CSymInfoById); ++I) {
/* Get this c symbol info */
S->Sym.Info = CollAt (&D->Info->SymInfoById, S->Sym.Id);
/* For normal (=static) symbols, add a backlink to the symbol but
- * check that there is not more than one.
- */
+ ** check that there is not more than one.
+ */
if (S->SC != CC65_CSYM_AUTO && S->SC != CC65_CSYM_REG) {
if (S->Sym.Info->CSym) {
ParseError (D,
CollAppend (S->Scope.Info->CSymInfoByName, S);
/* If the scope has an owner symbol, it's a .PROC scope. If this
- * symbol is identical to the one attached to the C symbol, this
- * is actuallay a C function and the scope is the matching scope.
- * Remember the C symbol in the scope in this case.
- * Beware: Scopes haven't been postprocessed, so we don't have a
- * pointer but just an id.
- */
+ ** symbol is identical to the one attached to the C symbol, this
+ ** is actuallay a C function and the scope is the matching scope.
+ ** Remember the C symbol in the scope in this case.
+ ** Beware: Scopes haven't been postprocessed, so we don't have a
+ ** pointer but just an id.
+ */
if (S->Sym.Info && S->Scope.Info->Label.Id == S->Sym.Info->Id) {
/* This scope is our function scope */
S->Scope.Info->CSymFunc = S;
Collection* FileInfos = &D->Info->FileInfoById;
/* Walk over the line infos and replace the id numbers of file and segment
- * with pointers to the actual structs. Add the line info to each file
- * where it is defined. Resolve the spans and add backpointers to the
- * spans.
- */
+ ** with pointers to the actual structs. Add the line info to each file
+ ** where it is defined. Resolve the spans and add backpointers to the
+ ** spans.
+ */
for (I = 0; I < CollCount (LineInfos); ++I) {
/* Get LineInfo struct */
LineInfo* L = CollAt (LineInfos, I);
/* Replace the file id by a pointer to the FileInfo. Add a back
- * pointer
- */
+ ** pointer
+ */
if (L->File.Id >= CollCount (FileInfos)) {
ParseError (D,
CC65_ERROR,
}
/* Walk over all files and sort the line infos for each file so we can
- * do a binary search later.
- */
+ ** do a binary search later.
+ */
for (I = 0; I < CollCount (FileInfos); ++I) {
/* Get a pointer to this file info */
unsigned I, J;
/* Walk over all scopes. Resolve the ids and add the scopes to the list
- * of scopes for a module.
- */
+ ** of scopes for a module.
+ */
for (I = 0; I < CollCount (&D->Info->ScopeInfoById); ++I) {
/* Get this scope info */
CollAppend (&S->Mod.Info->ScopeInfoByName, S);
/* If this is a main scope, add a pointer to the corresponding
- * module.
- */
+ ** module.
+ */
if (S->Parent.Id == CC65_INV_ID) {
/* No parent means main scope */
S->Mod.Info->MainScope = S;
}
/* If this is the scope that implements a C function, add the
- * function to the list of all functions in this module.
- */
+ ** function to the list of all functions in this module.
+ */
if (S->CSymFunc) {
CollAppend (&S->Mod.Info->CSymFuncByName, S->CSymFunc);
}
}
/* Walk over all modules. If a module doesn't have scopes, it wasn't
- * compiled with debug info which is ok. If it has debug info, it must
- * also have a main scope. If there are scopes, sort them by name. Do
- * also sort C functions in this module by name.
- */
+ ** compiled with debug info which is ok. If it has debug info, it must
+ ** also have a main scope. If there are scopes, sort them by name. Do
+ ** also sort C functions in this module by name.
+ */
for (I = 0; I < CollCount (&D->Info->ModInfoById); ++I) {
/* Get this module */
}
/* Append this span info to the temporary collection that is later
- * sorted by address.
- */
+ ** sorted by address.
+ */
CollAppend (&SpanInfoByAddr, S);
}
cc65_dbginfo cc65_read_dbginfo (const char* FileName, cc65_errorfunc ErrFunc)
/* Parse the debug info file with the given name. On success, the function
- * will return a pointer to an opaque cc65_dbginfo structure, that must be
- * passed to the other functions in this module to retrieve information.
- * errorfunc is called in case of warnings and errors. If the file cannot be
- * read successfully, NULL is returned.
- */
+** will return a pointer to an opaque cc65_dbginfo structure, that must be
+** passed to the other functions in this module to retrieve information.
+** errorfunc is called in case of warnings and errors. If the file cannot be
+** read successfully, NULL is returned.
+*/
{
/* Data structure used to control scanning and parsing */
InputData D = {
case TOK_IDENT:
/* Output a warning, then skip the line with the unknown
- * keyword that may have been added by a later version.
- */
+ ** keyword that may have been added by a later version.
+ */
ParseError (&D, CC65_WARNING,
"Unknown keyword \"%s\" - skipping",
SB_GetConstBuf (&D.SVal));
SB_Done (&D.SVal);
/* In case of errors, delete the debug info already allocated and
- * return NULL
- */
+ ** return NULL
+ */
if (D.Errors > 0) {
/* Free allocated stuff */
FreeDbgInfo (D.Info);
}
/* We do now have all the information from the input file. Do
- * postprocessing. Beware: Some of the following postprocessing
- * depends on the order of the calls.
- */
+ ** postprocessing. Beware: Some of the following postprocessing
+ ** depends on the order of the calls.
+ */
ProcessCSymInfo (&D);
ProcessFileInfo (&D);
ProcessLineInfo (&D);
const cc65_csyminfo* cc65_csym_byid (cc65_dbginfo Handle, unsigned Id)
/* Return information about a c symbol with a specific id. The function
- * returns NULL if the id is invalid (no such c symbol) and otherwise a
- * cc65_csyminfo structure with one entry that contains the requested
- * symbol information.
- */
+** returns NULL if the id is invalid (no such c symbol) and otherwise a
+** cc65_csyminfo structure with one entry that contains the requested
+** symbol information.
+*/
{
const DbgInfo* Info;
cc65_csyminfo* S;
const cc65_csyminfo* cc65_cfunc_bymodule (cc65_dbginfo Handle, unsigned ModId)
/* Return the list of C functions (not symbols!) for a specific module. If
- * the module id is invalid, the function will return NULL, otherwise a
- * (possibly empty) c symbol list.
- */
+** the module id is invalid, the function will return NULL, otherwise a
+** (possibly empty) c symbol list.
+*/
{
const DbgInfo* Info;
const ModInfo* M;
const cc65_csyminfo* cc65_cfunc_byname (cc65_dbginfo Handle, const char* Name)
/* Return a list of all C functions with the given name that have a
- * definition.
- */
+** definition.
+*/
{
const DbgInfo* Info;
unsigned Index;
const cc65_csyminfo* cc65_csym_byscope (cc65_dbginfo Handle, unsigned ScopeId)
/* Return all C symbols for a scope. The function will return NULL if the
- * given id is invalid.
- */
+** given id is invalid.
+*/
{
const DbgInfo* Info;
const ScopeInfo* S;
const cc65_libraryinfo* cc65_library_byid (cc65_dbginfo Handle, unsigned Id)
/* Return information about a library with a specific id. The function
- * returns NULL if the id is invalid (no such library) and otherwise a
- * cc65_libraryinfo structure with one entry that contains the requested
- * library information.
- */
+** returns NULL if the id is invalid (no such library) and otherwise a
+** cc65_libraryinfo structure with one entry that contains the requested
+** library information.
+*/
{
const DbgInfo* Info;
cc65_libraryinfo* D;
const cc65_lineinfo* cc65_line_byid (cc65_dbginfo Handle, unsigned Id)
/* Return information about a line with a specific id. The function
- * returns NULL if the id is invalid (no such line) and otherwise a
- * cc65_lineinfo structure with one entry that contains the requested
- * module information.
- */
+** returns NULL if the id is invalid (no such line) and otherwise a
+** cc65_lineinfo structure with one entry that contains the requested
+** module information.
+*/
{
const DbgInfo* Info;
cc65_lineinfo* D;
const cc65_lineinfo* cc65_line_bynumber (cc65_dbginfo Handle, unsigned FileId,
cc65_line Line)
/* Return line information for a source file/line number combination. The
- * function returns NULL if no line information was found.
- */
+** function returns NULL if no line information was found.
+*/
{
const DbgInfo* Info;
const FileInfo* F;
const cc65_lineinfo* cc65_line_bysource (cc65_dbginfo Handle, unsigned FileId)
/* Return line information for a source file. The function returns NULL if the
- * file id is invalid.
- */
+** file id is invalid.
+*/
{
const DbgInfo* Info;
const FileInfo* F;
const cc65_lineinfo* cc65_line_bysymdef (cc65_dbginfo Handle, unsigned SymId)
/* Return line information for the definition of a symbol. The function
- * returns NULL if the symbol id is invalid, otherwise a list of line infos.
- */
+** returns NULL if the symbol id is invalid, otherwise a list of line infos.
+*/
{
const DbgInfo* Info;
const SymInfo* S;
const cc65_lineinfo* cc65_line_bysymref (cc65_dbginfo Handle, unsigned SymId)
/* Return line information for all references of a symbol. The function
- * returns NULL if the symbol id is invalid, otherwise a list of line infos.
- */
+** returns NULL if the symbol id is invalid, otherwise a list of line infos.
+*/
{
const DbgInfo* Info;
const SymInfo* S;
const cc65_lineinfo* cc65_line_byspan (cc65_dbginfo Handle, unsigned SpanId)
/* Return line information for a a span. The function returns NULL if the
- * span id is invalid, otherwise a list of line infos.
- */
+** span id is invalid, otherwise a list of line infos.
+*/
{
const DbgInfo* Info;
const SpanInfo* S;
D = new_cc65_lineinfo (CollCount (S->LineInfoList));
/* Fill in the data. Since S->LineInfoList may be NULL, we will use the
- * count field of the returned data struct instead.
- */
+ ** count field of the returned data struct instead.
+ */
for (I = 0; I < D->count; ++I) {
/* Copy the data */
CopyLineInfo (D->data + I, CollAt (S->LineInfoList, I));
const cc65_moduleinfo* cc65_module_byid (cc65_dbginfo Handle, unsigned Id)
/* Return information about a module with a specific id. The function
- * returns NULL if the id is invalid (no such module) and otherwise a
- * cc65_moduleinfo structure with one entry that contains the requested
- * module information.
- */
+** returns NULL if the id is invalid (no such module) and otherwise a
+** cc65_moduleinfo structure with one entry that contains the requested
+** module information.
+*/
{
const DbgInfo* Info;
cc65_moduleinfo* D;
const cc65_spaninfo* cc65_span_byid (cc65_dbginfo Handle, unsigned Id)
/* Return information about a span with a specific id. The function
- * returns NULL if the id is invalid (no such span) and otherwise a
- * cc65_spaninfo structure with one entry that contains the requested
- * span information.
- */
+** returns NULL if the id is invalid (no such span) and otherwise a
+** cc65_spaninfo structure with one entry that contains the requested
+** span information.
+*/
{
const DbgInfo* Info;
cc65_spaninfo* D;
const cc65_spaninfo* cc65_span_byaddr (cc65_dbginfo Handle, unsigned long Addr)
/* Return span information for the given address. The function returns NULL
- * if no spans were found for this address.
- */
+** if no spans were found for this address.
+*/
{
const DbgInfo* Info;
SpanInfoListEntry* E;
const cc65_spaninfo* cc65_span_byline (cc65_dbginfo Handle, unsigned LineId)
/* Return span information for the given source line. The function returns NULL
- * if the line id is invalid, otherwise the spans for this line (possibly zero).
- */
+** if the line id is invalid, otherwise the spans for this line (possibly zero).
+*/
{
const DbgInfo* Info;
const LineInfo* L;
const cc65_spaninfo* cc65_span_byscope (cc65_dbginfo Handle, unsigned ScopeId)
/* Return span information for the given scope. The function returns NULL if
- * the scope id is invalid, otherwise the spans for this scope (possibly zero).
- */
+** the scope id is invalid, otherwise the spans for this scope (possibly zero).
+*/
{
const DbgInfo* Info;
const ScopeInfo* S;
const cc65_sourceinfo* cc65_source_byid (cc65_dbginfo Handle, unsigned Id)
/* Return information about a source file with a specific id. The function
- * returns NULL if the id is invalid (no such source file) and otherwise a
- * cc65_sourceinfo structure with one entry that contains the requested
- * source file information.
- */
+** returns NULL if the id is invalid (no such source file) and otherwise a
+** cc65_sourceinfo structure with one entry that contains the requested
+** source file information.
+*/
{
const DbgInfo* Info;
cc65_sourceinfo* D;
const cc65_sourceinfo* cc65_source_bymodule (cc65_dbginfo Handle, unsigned Id)
/* Return information about the source files used to build a module. The
- * function returns NULL if the module id is invalid (no such module) and
- * otherwise a cc65_sourceinfo structure with one entry per source file.
- */
+** function returns NULL if the module id is invalid (no such module) and
+** otherwise a cc65_sourceinfo structure with one entry per source file.
+*/
{
const DbgInfo* Info;
const ModInfo* M;
const cc65_scopeinfo* cc65_scope_byid (cc65_dbginfo Handle, unsigned Id)
/* Return the scope with a given id. The function returns NULL if no scope
- * with this id was found.
- */
+** with this id was found.
+*/
{
const DbgInfo* Info;
cc65_scopeinfo* D;
const cc65_scopeinfo* cc65_scope_bymodule (cc65_dbginfo Handle, unsigned ModId)
/* Return the list of scopes for one module. The function returns NULL if no
- * scope with the given id was found.
- */
+** scope with the given id was found.
+*/
{
const DbgInfo* Info;
const ModInfo* M;
const cc65_scopeinfo* cc65_scope_byname (cc65_dbginfo Handle, const char* Name)
/* Return the list of scopes with a given name. Returns NULL if no scope with
- * the given name was found, otherwise a non empty scope list.
- */
+** the given name was found, otherwise a non empty scope list.
+*/
{
const DbgInfo* Info;
unsigned Index;
const cc65_scopeinfo* cc65_scope_byspan (cc65_dbginfo Handle, unsigned SpanId)
/* Return scope information for a a span. The function returns NULL if the
- * span id is invalid, otherwise a list of line scopes.
- */
+** span id is invalid, otherwise a list of line scopes.
+*/
{
const DbgInfo* Info;
const SpanInfo* S;
D = new_cc65_scopeinfo (CollCount (S->ScopeInfoList));
/* Fill in the data. Since D->ScopeInfoList may be NULL, we will use the
- * count field of the returned data struct instead.
- */
+ ** count field of the returned data struct instead.
+ */
for (I = 0; I < D->count; ++I) {
/* Copy the data */
CopyScopeInfo (D->data + I, CollAt (S->ScopeInfoList, I));
const cc65_scopeinfo* cc65_childscopes_byid (cc65_dbginfo Handle, unsigned Id)
/* Return the direct child scopes of a scope with a given id. The function
- * returns NULL if no scope with this id was found, otherwise a list of the
- * direct childs.
- */
+** returns NULL if no scope with this id was found, otherwise a list of the
+** direct childs.
+*/
{
const DbgInfo* Info;
cc65_scopeinfo* D;
const cc65_segmentinfo* cc65_segment_byid (cc65_dbginfo Handle, unsigned Id)
/* Return information about a segment with a specific id. The function returns
- * NULL if the id is invalid (no such segment) and otherwise a segmentinfo
- * structure with one entry that contains the requested segment information.
- */
+** NULL if the id is invalid (no such segment) and otherwise a segmentinfo
+** structure with one entry that contains the requested segment information.
+*/
{
const DbgInfo* Info;
cc65_segmentinfo* D;
const cc65_segmentinfo* cc65_segment_byname (cc65_dbginfo Handle,
const char* Name)
/* Return information about a segment with a specific name. The function
- * returns NULL if no segment with this name exists and otherwise a
- * cc65_segmentinfo structure with one entry that contains the requested
- * information.
- */
+** returns NULL if no segment with this name exists and otherwise a
+** cc65_segmentinfo structure with one entry that contains the requested
+** information.
+*/
{
const DbgInfo* Info;
const SegInfo* S;
const cc65_symbolinfo* cc65_symbol_byid (cc65_dbginfo Handle, unsigned Id)
/* Return the symbol with a given id. The function returns NULL if no symbol
- * with this id was found.
- */
+** with this id was found.
+*/
{
const DbgInfo* Info;
cc65_symbolinfo* D;
const cc65_symbolinfo* cc65_symbol_byname (cc65_dbginfo Handle, const char* Name)
/* Return a list of symbols with a given name. The function returns NULL if
- * no symbol with this name was found.
- */
+** no symbol with this name was found.
+*/
{
const DbgInfo* Info;
cc65_symbolinfo* D;
}
/* Index contains the position. Count how many symbols with this name
- * we have. Skip the first one, since we have at least one.
- */
+ ** we have. Skip the first one, since we have at least one.
+ */
Count = 1;
while ((unsigned) Index + Count < CollCount (&Info->SymInfoByName)) {
const SymInfo* S = CollAt (&Info->SymInfoByName, (unsigned) Index + Count);
const cc65_symbolinfo* cc65_symbol_byscope (cc65_dbginfo Handle, unsigned ScopeId)
/* Return a list of symbols in the given scope. This includes cheap local
- * symbols, but not symbols in subscopes. The function returns NULL if the
- * scope id is invalid (no such scope) and otherwise a - possibly empty -
- * symbol list.
- */
+** symbols, but not symbols in subscopes. The function returns NULL if the
+** scope id is invalid (no such scope) and otherwise a - possibly empty -
+** symbol list.
+*/
{
const DbgInfo* Info;
cc65_symbolinfo* D;
const cc65_symbolinfo* cc65_symbol_inrange (cc65_dbginfo Handle, cc65_addr Start,
cc65_addr End)
/* Return a list of labels in the given range. End is inclusive. The function
- * return NULL if no symbols within the given range are found. Non label
- * symbols are ignored and not returned.
- */
+** return NULL if no symbols within the given range are found. Non label
+** symbols are ignored and not returned.
+*/
{
const DbgInfo* Info;
Collection SymInfoList = COLLECTION_INITIALIZER;
Info = Handle;
/* Search for the symbol. Because we're searching for a range, we cannot
- * make use of the function result.
- */
+ ** make use of the function result.
+ */
FindSymInfoByValue (&Info->SymInfoByVal, Start, &Index);
/* Start from the given index, check all symbols until the end address is
- * reached. Place all symbols into SymInfoList for later.
- */
+ ** reached. Place all symbols into SymInfoList for later.
+ */
for (I = Index; I < CollCount (&Info->SymInfoByVal); ++I) {
/* Get the item */
SymInfo* Item = CollAt (&Info->SymInfoByVal, I);
/* The collection is sorted by address, so if we get a value larger
- * than the end address, we're done.
- */
+ ** than the end address, we're done.
+ */
if (Item->Value > (long) End) {
break;
}
}
/* If we don't have any labels within the range, bail out. No memory has
- * been allocated for SymInfoList.
- */
+ ** been allocated for SymInfoList.
+ */
if (CollCount (&SymInfoList) == 0) {
return 0;
}
const cc65_typedata* cc65_type_byid (cc65_dbginfo Handle, unsigned Id)
/* Return the data for the type with the given id. The function returns NULL
- * if no type with this id was found.
- */
+** if no type with this id was found.
+*/
{
const DbgInfo* Info;
const TypeInfo* T;
/* Data types used for addresses, sizes and line numbers. Change to "unsigned
- * long" if you ever want to run the code on a 16-bit machine.
- */
+** long" if you ever want to run the code on a 16-bit machine.
+*/
typedef unsigned cc65_line; /* Used to store line numbers */
typedef unsigned cc65_addr; /* Used to store (65xx) addresses */
typedef unsigned cc65_size; /* Used to store (65xx) sizes */
typedef void (*cc65_errorfunc) (const cc65_parseerror*);
/* Pointer to an opaque data structure containing information from the debug
- * info file. Actually a handle to the data in the file.
- */
+** info file. Actually a handle to the data in the file.
+*/
typedef const void* cc65_dbginfo;
cc65_dbginfo cc65_read_dbginfo (const char* filename, cc65_errorfunc errorfunc);
/* Parse the debug info file with the given name. On success, the function
- * will return a pointer to an opaque cc65_dbginfo structure, that must be
- * passed to the other functions in this module to retrieve information.
- * errorfunc is called in case of warnings and errors. If the file cannot be
- * read successfully, NULL is returned.
- */
+** will return a pointer to an opaque cc65_dbginfo structure, that must be
+** passed to the other functions in this module to retrieve information.
+** errorfunc is called in case of warnings and errors. If the file cannot be
+** read successfully, NULL is returned.
+*/
void cc65_free_dbginfo (cc65_dbginfo Handle);
/* Free debug information read from a file */
const cc65_csyminfo* cc65_csym_byid (cc65_dbginfo handle, unsigned id);
/* Return information about a c symbol with a specific id. The function
- * returns NULL if the id is invalid (no such c symbol) and otherwise a
- * cc65_csyminfo structure with one entry that contains the requested
- * symbol information.
- */
+** returns NULL if the id is invalid (no such c symbol) and otherwise a
+** cc65_csyminfo structure with one entry that contains the requested
+** symbol information.
+*/
const cc65_csyminfo* cc65_cfunc_bymodule (cc65_dbginfo handle, unsigned module_id);
/* Return the list of C functions (not symbols!) for a specific module. If
- * the module id is invalid, the function will return NULL, otherwise a
- * (possibly empty) c symbol list.
- */
+** the module id is invalid, the function will return NULL, otherwise a
+** (possibly empty) c symbol list.
+*/
const cc65_csyminfo* cc65_cfunc_byname (cc65_dbginfo handle, const char* name);
/* Return a list of all C functions with the given name that have a
- * definition.
- */
+** definition.
+*/
const cc65_csyminfo* cc65_csym_byscope (cc65_dbginfo handle, unsigned scope_id);
/* Return all C symbols for a scope. The function will return NULL if the
- * given id is invalid.
- */
+** given id is invalid.
+*/
void cc65_free_csyminfo (cc65_dbginfo handle, const cc65_csyminfo* info);
/* Free a c symbol info record */
const cc65_libraryinfo* cc65_library_byid (cc65_dbginfo handle, unsigned id);
/* Return information about a library with a specific id. The function
- * returns NULL if the id is invalid (no such library) and otherwise a
- * cc65_libraryinfo structure with one entry that contains the requested
- * library information.
- */
+** returns NULL if the id is invalid (no such library) and otherwise a
+** cc65_libraryinfo structure with one entry that contains the requested
+** library information.
+*/
void cc65_free_libraryinfo (cc65_dbginfo handle, const cc65_libraryinfo* info);
/* Free a library info record */
const cc65_lineinfo* cc65_line_byid (cc65_dbginfo handle, unsigned id);
/* Return information about a line with a specific id. The function
- * returns NULL if the id is invalid (no such line) and otherwise a
- * cc65_lineinfo structure with one entry that contains the requested
- * module information.
- */
+** returns NULL if the id is invalid (no such line) and otherwise a
+** cc65_lineinfo structure with one entry that contains the requested
+** module information.
+*/
const cc65_lineinfo* cc65_line_bynumber (cc65_dbginfo handle,
unsigned source_id,
cc65_line line);
/* Return line information for a source file/line number combination. The
- * function returns NULL if no line information was found.
- */
+** function returns NULL if no line information was found.
+*/
const cc65_lineinfo* cc65_line_bysource (cc65_dbginfo Handle, unsigned source_id);
/* Return line information for a source file. The function returns NULL if the
- * file id is invalid.
- */
+** file id is invalid.
+*/
const cc65_lineinfo* cc65_line_bysymdef (cc65_dbginfo handle, unsigned symbol_id);
/* Return line information for the definition of a symbol. The function
- * returns NULL if the symbol id is invalid, otherwise a list of line infos.
- */
+** returns NULL if the symbol id is invalid, otherwise a list of line infos.
+*/
const cc65_lineinfo* cc65_line_bysymref (cc65_dbginfo handle, unsigned symbol_id);
/* Return line information for all references of a symbol. The function
- * returns NULL if the symbol id is invalid, otherwise a list of line infos.
- */
+** returns NULL if the symbol id is invalid, otherwise a list of line infos.
+*/
const cc65_lineinfo* cc65_line_byspan (cc65_dbginfo handle, unsigned span_id);
/* Return line information for a a span. The function returns NULL if the
- * span id is invalid, otherwise a list of line infos.
- */
+** span id is invalid, otherwise a list of line infos.
+*/
void cc65_free_lineinfo (cc65_dbginfo handle, const cc65_lineinfo* info);
/* Free line info returned by one of the other functions */
/* Module information
- * Notes:
- * - scope_id contains CC65_INV_ID if the module was compiled without
- * debug information.
- */
+** Notes:
+** - scope_id contains CC65_INV_ID if the module was compiled without
+** debug information.
+*/
typedef struct cc65_moduledata cc65_moduledata;
struct cc65_moduledata {
unsigned module_id; /* The internal module id */
const cc65_moduleinfo* cc65_module_byid (cc65_dbginfo handle, unsigned id);
/* Return information about a module with a specific id. The function
- * returns NULL if the id is invalid (no such module) and otherwise a
- * cc65_moduleinfo structure with one entry that contains the requested
- * module information.
- */
+** returns NULL if the id is invalid (no such module) and otherwise a
+** cc65_moduleinfo structure with one entry that contains the requested
+** module information.
+*/
void cc65_free_moduleinfo (cc65_dbginfo handle, const cc65_moduleinfo* info);
/* Free a module info record */
const cc65_spaninfo* cc65_span_byid (cc65_dbginfo handle, unsigned id);
/* Return information about a span with a specific id. The function
- * returns NULL if the id is invalid (no such span) and otherwise a
- * cc65_spaninfo structure with one entry that contains the requested
- * span information.
- */
+** returns NULL if the id is invalid (no such span) and otherwise a
+** cc65_spaninfo structure with one entry that contains the requested
+** span information.
+*/
const cc65_spaninfo* cc65_span_byaddr (cc65_dbginfo handle,
unsigned long addr);
/* Return span information for the given address. The function returns NULL
- * if no spans were found for this address.
- */
+** if no spans were found for this address.
+*/
const cc65_spaninfo* cc65_span_byline (cc65_dbginfo handle, unsigned line_id);
/* Return span information for the given source line. The function returns NULL
- * if the line id is invalid, otherwise the spans for this line (possibly zero).
- */
+** if the line id is invalid, otherwise the spans for this line (possibly zero).
+*/
const cc65_spaninfo* cc65_span_byscope (cc65_dbginfo handle, unsigned scope_id);
/* Return span information for the given scope. The function returns NULL if
- * the scope id is invalid, otherwise the spans for this scope (possibly zero).
- */
+** the scope id is invalid, otherwise the spans for this scope (possibly zero).
+*/
void cc65_free_spaninfo (cc65_dbginfo handle, const cc65_spaninfo* info);
/* Free a span info record */
const cc65_sourceinfo* cc65_source_byid (cc65_dbginfo handle, unsigned id);
/* Return information about a source file with a specific id. The function
- * returns NULL if the id is invalid (no such source file) and otherwise a
- * cc65_sourceinfo structure with one entry that contains the requested
- * source file information.
- */
+** returns NULL if the id is invalid (no such source file) and otherwise a
+** cc65_sourceinfo structure with one entry that contains the requested
+** source file information.
+*/
const cc65_sourceinfo* cc65_source_bymodule (cc65_dbginfo handle,
unsigned module_id);
/* Return information about the source files used to build a module. The
- * function returns NULL if the module id is invalid (no such module) and
- * otherwise a cc65_sourceinfo structure with one entry per source file.
- */
+** function returns NULL if the module id is invalid (no such module) and
+** otherwise a cc65_sourceinfo structure with one entry per source file.
+*/
void cc65_free_sourceinfo (cc65_dbginfo handle, const cc65_sourceinfo* info);
/* Free a source info record */
const cc65_scopeinfo* cc65_scope_byid (cc65_dbginfo handle, unsigned id);
/* Return the scope with a given id. The function returns NULL if no scope
- * with this id was found.
- */
+** with this id was found.
+*/
const cc65_scopeinfo* cc65_scope_bymodule (cc65_dbginfo handle, unsigned module_id);
/* Return the list of scopes for one module. The function returns NULL if no
- * scope with the given id was found.
- */
+** scope with the given id was found.
+*/
const cc65_scopeinfo* cc65_scope_byname (cc65_dbginfo handle, const char* name);
/* Return the list of scopes with a given name. Returns NULL if no scope with
- * the given name was found, otherwise a non empty scope list.
- */
+** the given name was found, otherwise a non empty scope list.
+*/
const cc65_scopeinfo* cc65_scope_byspan (cc65_dbginfo handle, unsigned span_id);
/* Return scope information for a a span. The function returns NULL if the
- * span id is invalid, otherwise a list of line scopes.
- */
+** span id is invalid, otherwise a list of line scopes.
+*/
const cc65_scopeinfo* cc65_childscopes_byid (cc65_dbginfo handle, unsigned id);
/* Return the direct child scopes of a scope with a given id. The function
- * returns NULL if no scope with this id was found, otherwise a list of the
- * direct childs.
- */
+** returns NULL if no scope with this id was found, otherwise a list of the
+** direct childs.
+*/
void cc65_free_scopeinfo (cc65_dbginfo Handle, const cc65_scopeinfo* Info);
/* Free a scope info record */
/* Segment information.
- * Notes:
- * - output_name may be NULL if the data wasn't written to the output file
- * (example: bss segment)
- * - output_offs is invalid if there is no output_name, and may not be of
- * much use in case of a relocatable output file
- */
+** Notes:
+** - output_name may be NULL if the data wasn't written to the output file
+** (example: bss segment)
+** - output_offs is invalid if there is no output_name, and may not be of
+** much use in case of a relocatable output file
+*/
typedef struct cc65_segmentdata cc65_segmentdata;
struct cc65_segmentdata {
unsigned segment_id; /* The internal segment id */
const cc65_segmentinfo* cc65_segment_byid (cc65_dbginfo handle, unsigned id);
/* Return information about a segment with a specific id. The function returns
- * NULL if the id is invalid (no such segment) and otherwise a cc65_segmentinfo
- * structure with one entry that contains the requested segment information.
- */
+** NULL if the id is invalid (no such segment) and otherwise a cc65_segmentinfo
+** structure with one entry that contains the requested segment information.
+*/
const cc65_segmentinfo* cc65_segment_byname (cc65_dbginfo handle,
const char* name);
/* Return information about a segment with a specific name. The function
- * returns NULL if no segment with this name exists and otherwise a
- * cc65_segmentinfo structure with one entry that contains the requested
- * information.
- */
+** returns NULL if no segment with this name exists and otherwise a
+** cc65_segmentinfo structure with one entry that contains the requested
+** information.
+*/
void cc65_free_segmentinfo (cc65_dbginfo handle, const cc65_segmentinfo* info);
/* Free a segment info record */
} cc65_symbol_type;
/* Notes:
- * - If the symbol is segment relative, the segment id gives segment
- * information, otherwise it contains CC65_INV_ID.
- * - If the type is CC65_SYM_IMPORT, export_id may contain the id of the
- * export. This is not the case if the module contaiing the export doesn't
- * have debug information.
- * - For an import, the fields symbol_value and segment_id are taken from
- * the export, if it is available, since imports have no value or segments
- * by itself.
- * - For an import symbol_size doesn't have a meaning.
- * - For normal symbols (not cheap locals) parent_id contains CC65_INV_ID,
- * for cheap locals it contains the symbol id of the parent symbol.
- */
+** - If the symbol is segment relative, the segment id gives segment
+** information, otherwise it contains CC65_INV_ID.
+** - If the type is CC65_SYM_IMPORT, export_id may contain the id of the
+** export. This is not the case if the module contaiing the export doesn't
+** have debug information.
+** - For an import, the fields symbol_value and segment_id are taken from
+** the export, if it is available, since imports have no value or segments
+** by itself.
+** - For an import symbol_size doesn't have a meaning.
+** - For normal symbols (not cheap locals) parent_id contains CC65_INV_ID,
+** for cheap locals it contains the symbol id of the parent symbol.
+*/
typedef struct cc65_symboldata cc65_symboldata;
struct cc65_symboldata {
unsigned symbol_id; /* Id of symbol */
const cc65_symbolinfo* cc65_symbol_byid (cc65_dbginfo handle, unsigned id);
/* Return the symbol with a given id. The function returns NULL if no symbol
- * with this id was found.
- */
+** with this id was found.
+*/
const cc65_symbolinfo* cc65_symbol_byname (cc65_dbginfo handle, const char* name);
/* Return a list of symbols with a given name. The function returns NULL if
- * no symbol with this name was found.
- */
+** no symbol with this name was found.
+*/
const cc65_symbolinfo* cc65_symbol_byscope (cc65_dbginfo handle,
unsigned scope_id);
/* Return a list of symbols in the given scope. This includes cheap local
- * symbols, but not symbols in subscopes. The function returns NULL if the
- * scope id is invalid (no such scope) and otherwise a - possibly empty -
- * symbol list.
- */
+** symbols, but not symbols in subscopes. The function returns NULL if the
+** scope id is invalid (no such scope) and otherwise a - possibly empty -
+** symbol list.
+*/
const cc65_symbolinfo* cc65_symbol_inrange (cc65_dbginfo handle,
cc65_addr start, cc65_addr end);
/* Return a list of labels in the given range. end is inclusive. The function
- * return NULL if no symbols within the given range are found. Non label
- * symbols are ignored and not returned.
- */
+** return NULL if no symbols within the given range are found. Non label
+** symbols are ignored and not returned.
+*/
void cc65_free_symbolinfo (cc65_dbginfo handle, const cc65_symbolinfo* info);
/* Free a symbol info record */
/* A type is a linked list of typedata structures. In case of arrays, the
- * structure will contain an element count and the element type. In case of
- * pointers, the structure will contain the type of the data, the pointer
- * points to (currently, there are only VOID pointers).
- * The next pointer points to the next entry in the list. It is NULL if the
- * end of the list is reached.
- */
+** structure will contain an element count and the element type. In case of
+** pointers, the structure will contain the type of the data, the pointer
+** points to (currently, there are only VOID pointers).
+** The next pointer points to the next entry in the list. It is NULL if the
+** end of the list is reached.
+*/
typedef struct cc65_typedata cc65_typedata;
struct cc65_typedata {
cc65_typedata* next; /* Pointer to next entry */
const cc65_typedata* cc65_type_byid (cc65_dbginfo handle, unsigned id);
/* Return the data for the type with the given id. The function returns NULL
- * if no type with this id was found.
- */
+** if no type with this id was found.
+*/
void cc65_free_typedata (cc65_dbginfo Handle, const cc65_typedata* data);
/* Free a symbol info record */
static void ExecCmd (Collection* Args, const CmdEntry* Tab, unsigned Count)
/* Search for the command in slot 0 of the given collection. If found, check
- * the argument count, then execute it. If there are problems, output a
- * diagnostic.
- */
+** the argument count, then execute it. If there are problems, output a
+** diagnostic.
+*/
{
/* Search for the command, check number of args, then execute it */
const char* Cmd = CollAt (Args, 0);
}
/* Check the number of arguments. Zero means that the function will check
- * itself. A negative count means that the function needs at least
- * abs(count) arguments. A positive count means that the function needs
- * exactly this number of arguments.
- * Note: The number includes the command itself.
- */
+ ** itself. A negative count means that the function needs at least
+ ** abs(count) arguments. A positive count means that the function needs
+ ** exactly this number of arguments.
+ ** Note: The number includes the command itself.
+ */
if (E->ArgCount > 0 && (int)CollCount (Args) != E->ArgCount) {
/* Argument number mismatch */
switch (E->ArgCount) {
static int GetId (const char* S, unsigned* Id, unsigned* IdType)
/* Parse a string for an id. If a valid id is found, it is placed in Id and
- * the function returns true. If an optional type is found, it is placed in
- * IdType, otherwise IdType is left unchanged. If no id is found, the
- * function returns false.
- */
+** the function returns true. If an optional type is found, it is placed in
+** IdType, otherwise IdType is left unchanged. If no id is found, the
+** function returns false.
+*/
{
char TypeBuf[20];
char C;
static int FileIsLoaded (void)
/* Return true if the file is open and has loaded without errors: If not,
- * print an error message and return false.
- */
+** print an error message and return false.
+*/
{
/* File open? */
if (Info == 0) {
static int Parse (char* CmdLine, Collection* Args)
/* Parse the command line and store the arguments in Args. Return true if ok,
- * false on error.
- */
+** false on error.
+*/
{
char* End;
unsigned long Offs attribute ((unused)),
void* Data)
/* Called from SegWrite for an expression. Evaluate the expression, check the
- * range and write the expression value to the file.
- */
+** range and write the expression value to the file.
+*/
{
/* There's a predefined function to handle constant expressions */
return SegWriteConstExpr (((BinDesc*)Data)->F, E, Signed, Size);
PrintNumVal ("FileOffs", (unsigned long) ftell (D->F));
/* Check if the alignment for the segment from the linker config is
- * a multiple for that of the segment.
- */
+ ** a multiple for that of the segment.
+ */
if ((S->RunAlignment % S->Seg->Alignment) != 0) {
/* Segment requires another alignment than configured
- * in the linker.
- */
+ ** in the linker.
+ */
Warning ("Segment `%s' is not aligned properly. Resulting "
"executable may not be functional.",
GetString (S->Name));
}
/* If this is the run memory area, we must apply run alignment. If
- * this is not the run memory area but the load memory area (which
- * means that both are different), we must apply load alignment.
- * Beware: DoWrite may be true even if this is the run memory area,
- * because it may be also the load memory area.
- */
+ ** this is not the run memory area but the load memory area (which
+ ** means that both are different), we must apply load alignment.
+ ** Beware: DoWrite may be true even if this is the run memory area,
+ ** because it may be also the load memory area.
+ */
if (S->Run == M) {
/* Handle ALIGN and OFFSET/START */
}
/* Now write the segment to disk if it is not a BSS type segment and
- * if the memory area is the load area.
- */
+ ** if the memory area is the load area.
+ */
if (DoWrite) {
unsigned long P = ftell (D->F);
SegWrite (D->Filename, D->F, S->Seg, BinWriteExpr, D);
/* Called if an unresolved symbol is encountered */
{
/* Unresolved symbols are an error in binary format. Bump the counter
- * and return zero telling the caller that the symbol is indeed
- * unresolved.
- */
+ ** and return zero telling the caller that the symbol is indeed
+ ** unresolved.
+ */
((BinDesc*) D)->Undef++;
return 0;
}
D->Filename = GetString (F->Name);
/* Check for unresolved symbols. The function BinUnresolved is called
- * if we get an unresolved symbol.
- */
+ ** if we get an unresolved symbol.
+ */
D->Undef = 0; /* Reset the counter */
CheckUnresolvedImports (BinUnresolved, D);
if (D->Undef > 0) {
long CfgCheckedConstExpr (long Min, long Max)
/* Read an expression, make sure it's an int and in range, then return its
- * value.
- */
+** value.
+*/
{
/* Get the value */
long Val = CfgConstExpr ();
long CfgCheckedConstExpr (long Min, long Max);
/* Read an expression, make sure it's an int and in range, then return its
- * value.
- */
+** value.
+*/
int Cmp;
/* Data is actually a pointer to a ConDesDesc from the table, E1 and
- * E2 are exports from the collection. Get the condes type and cast
- * the void pointers to object pointers.
- */
+ ** E2 are exports from the collection. Get the condes type and cast
+ ** the void pointers to object pointers.
+ */
ConDesDesc* CD = ((ConDesDesc*) Data);
int Type = CD - ConDes;
const Export* Exp1 = (const Export*) E1;
unsigned I;
/* Check if this table has a segment and table label defined. If not,
- * creation was not requested in the config file - ignore it.
- */
+ ** creation was not requested in the config file - ignore it.
+ */
if (CD->SegName == INVALID_STRING_ID || CD->Label == INVALID_STRING_ID) {
return;
}
/* Check if there is an import for the table label. If not, there is no
- * reference to the table and we would just waste memory creating the
- * table.
- */
+ ** reference to the table and we would just waste memory creating the
+ ** table.
+ */
if (!IsUnresolved (CD->Label)) {
return;
}
Sec = NewSection (Seg, 1, ADDR_SIZE_ABS);
/* Walk over the exports and create a fragment for each one. We will use
- * the exported expression without copying it, since it's cheap and there
- * is currently no place where it gets changed (hope this will not hunt
- * me later...).
- */
+ ** the exported expression without copying it, since it's cheap and there
+ ** is currently no place where it gets changed (hope this will not hunt
+ ** me later...).
+ */
Count = CollCount (&CD->ExpList);
for (I = 0; I < Count; ++I) {
}
/* Define the table start as an export, offset into section is zero
- * (the section only contains the table).
- */
+ ** (the section only contains the table).
+ */
CreateSectionExport (CD->Label, Sec, 0);
/* If we have a CountSym name given AND if it is referenced, define it
- * with the number of elements in the table.
- */
+ ** with the number of elements in the table.
+ */
if (CD->CountSym) {
CreateConstExport (CD->CountSym, Count);
}
const ConDesImport* ConDesGetImport (unsigned Type)
/* Get the forced import for the given ConDes type. Returns NULL if there is
- * no forced import for this type.
- */
+** no forced import for this type.
+*/
{
const ConDesImport* Import;
const ConDesImport* ConDesGetImport (unsigned Type);
/* Get the forced import for the given ConDes type. Returns NULL if there is
- * no forced import for this type.
- */
+** no forced import for this type.
+*/
void ConDesSetImport (unsigned Type, const ConDesImport* Import);
/* Set the forced import for the given ConDes type */
} CfgSymType;
/* Symbol structure. It is used for o65 imports and exports, but also for
- * symbols from the SYMBOLS sections (symbols defined in the config file or
- * forced imports).
- */
+** symbols from the SYMBOLS sections (symbols defined in the config file or
+** forced imports).
+*/
typedef struct CfgSymbol CfgSymbol;
struct CfgSymbol {
CfgSymType Type; /* Type of symbol */
static CfgSymbol* NewCfgSymbol (CfgSymType Type, unsigned Name)
/* Create a new CfgSymbol structure with the given type and name. The
- * current config file position is recorded in the returned struct. The
- * created struct is inserted into the CfgSymbols collection and returned.
- */
+** current config file position is recorded in the returned struct. The
+** created struct is inserted into the CfgSymbols collection and returned.
+*/
{
/* Allocate memory */
CfgSymbol* Sym = xmalloc (sizeof (CfgSymbol));
static void FlagAttr (unsigned* Flags, unsigned Mask, const char* Name)
/* Check if the item is already defined. Print an error if so. If not, set
- * the marker that we have a definition now.
- */
+** the marker that we have a definition now.
+*/
{
if (*Flags & Mask) {
CfgError (&CfgErrorPos, "%s is already defined", Name);
AttrCheck (M->Attr, MA_SIZE, "SIZE");
/* If we don't have a file name for output given, use the default
- * file name.
- */
+ ** file name.
+ */
if ((M->Attr & MA_FILE) == 0) {
FileInsert (GetFile (GetStringId (OutputName)), M);
OutputNameUsed = 1;
}
/* An attribute of ALIGN_LOAD doesn't make sense if there are no
- * separate run and load memory areas.
- */
+ ** separate run and load memory areas.
+ */
if ((S->Flags & SF_ALIGN_LOAD) != 0 && (S->Load == S->Run)) {
CfgWarning (&CfgErrorPos,
"ALIGN_LOAD attribute specified, but no separate "
}
/* If the segment is marked as BSS style, it may not have separate
- * load and run memory areas, because it's is never written to disk.
- */
+ ** load and run memory areas, because it's is never written to disk.
+ */
if ((S->Flags & SF_BSS) != 0 && (S->Load != S->Run)) {
CfgWarning (&CfgErrorPos,
"Segment with type `bss' has both LOAD and RUN "
/* Cannot use this attribute twice */
FlagAttr (&AttrFlags, atOS, "OS");
/* Get the operating system. It may be specified as name or
- * as a number in the range 1..255.
- */
+ ** as a number in the range 1..255.
+ */
if (CfgTok == CFGTOK_INTCON) {
CfgRangeCheck (O65OS_MIN, O65OS_MAX);
OS = (unsigned) CfgIVal;
AttrCheck (AttrFlags, atDefault, "DEFAULT");
/* If no start address was given on the command line, use the one given
- * here
- */
+ ** here
+ */
if (!HaveStartAddr) {
StartAddr = DefStartAddr;
}
O65FmtDesc = NewO65Desc ();
/* If we have a config name given, open the file, otherwise we will read
- * from a buffer.
- */
+ ** from a buffer.
+ */
CfgOpenInput ();
/* Parse the file */
SegDesc* S = CollAtUnchecked (&SegDescList, I);
/* Search for the actual segment in the input files. The function may
- * return NULL (no such segment), this is checked later.
- */
+ ** return NULL (no such segment), this is checked later.
+ */
S->Seg = SegFind (S->Name);
/* If the segment is marked as BSS style, and if the segment exists
- * in any of the object file, check that there's no initialized data
- * in the segment.
- */
+ ** in any of the object file, check that there's no initialized data
+ ** in the segment.
+ */
if ((S->Flags & SF_BSS) != 0 && S->Seg != 0 && !IsBSSType (S->Seg)) {
CfgWarning (GetSourcePos (S->LI),
"Segment `%s' with type `bss' contains initialized data",
}
/* If this segment does exist in any of the object files, insert the
- * segment into the load/run memory areas. Otherwise print a warning
- * and discard it, because the segment pointer in the descriptor is
- * invalid.
- */
+ ** segment into the load/run memory areas. Otherwise print a warning
+ ** and discard it, because the segment pointer in the descriptor is
+ ** invalid.
+ */
if (S->Seg != 0) {
/* Insert the segment into the memory area list */
}
/* Check if we have this symbol defined already. The entry
- * routine will check this also, but we get a more verbose
- * error message when checking it here.
- */
+ ** routine will check this also, but we get a more verbose
+ ** error message when checking it here.
+ */
if (O65GetExport (O65FmtDesc, Sym->Name) != 0) {
CfgError (
GetSourcePos (Sym->LI),
}
/* Check if we have this symbol defined already. The entry
- * routine will check this also, but we get a more verbose
- * error message when checking it here.
- */
+ ** routine will check this also, but we get a more verbose
+ ** error message when checking it here.
+ */
if (O65GetImport (O65FmtDesc, Sym->Name) != 0) {
CfgError (
GetSourcePos (Sym->LI),
unsigned CfgProcess (void)
/* Process the config file after reading in object files and libraries. This
- * includes postprocessing of the config file data but also assigning segments
- * and defining segment/memory area related symbols. The function will return
- * the number of memory area overflows (so zero means anything went ok).
- * In case of overflows, a short mapfile can be generated later, to ease the
- * task of rearranging segments for the user.
- */
+** includes postprocessing of the config file data but also assigning segments
+** and defining segment/memory area related symbols. The function will return
+** the number of memory area overflows (so zero means anything went ok).
+** In case of overflows, a short mapfile can be generated later, to ease the
+** task of rearranging segments for the user.
+*/
{
unsigned Overflows = 0;
unsigned I;
/* Postprocess symbols. We must do that first, since weak symbols are
- * defined here, which may be needed later.
- */
+ ** defined here, which may be needed later.
+ */
ProcessSymbols ();
/* Postprocess segments */
ProcessSegments ();
/* Walk through each of the memory sections. Add up the sizes and check
- * for an overflow of the section. Assign the start addresses of the
- * segments while doing this.
- */
+ ** for an overflow of the section. Assign the start addresses of the
+ ** segments while doing this.
+ */
for (I = 0; I < CollCount (&MemoryAreas); ++I) {
unsigned J;
M->Relocatable = RelocatableBinFmt (M->F->Format);
/* Resolve the start address expression, remember the start address
- * and mark the memory area as placed.
- */
+ ** and mark the memory area as placed.
+ */
if (!IsConstExpr (M->StartExpr)) {
CfgError (GetSourcePos (M->LI),
"Start address of memory area `%s' is not constant",
M->Flags |= MF_PLACED;
/* If requested, define the symbol for the start of the memory area.
- * Doing it here means that the expression for the size of the area
- * may reference this symbol.
- */
+ ** Doing it here means that the expression for the size of the area
+ ** may reference this symbol.
+ */
if (M->Flags & MF_DEFINE) {
Export* E;
StrBuf Buf = STATIC_STRBUF_INITIALIZER;
unsigned long StartAddr = Addr;
/* Some actions depend on wether this is the load or run memory
- * area.
- */
+ ** area.
+ */
if (S->Run == M) {
/* This is the run (and maybe load) memory area. Handle
- * alignment and explict start address and offset.
- */
+ ** alignment and explict start address and offset.
+ */
if (S->Flags & SF_ALIGN) {
/* Align the address */
unsigned long NewAddr = AlignAddr (Addr, S->RunAlignment);
/* If the first segment placed in the memory area needs
- * fill bytes for the alignment, emit a warning, since
- * this is somewhat suspicious.
- */
+ ** fill bytes for the alignment, emit a warning, since
+ ** this is somewhat suspicious.
+ */
if (M->FillLevel == 0 && NewAddr > Addr) {
CfgWarning (GetSourcePos (S->LI),
"First segment in memory area `%s' does "
}
/* Set the start address of this segment, set the readonly flag
- * in the segment and and remember if the segment is in a
- * relocatable file or not.
- */
+ ** in the segment and and remember if the segment is in a
+ ** relocatable file or not.
+ */
S->Seg->PC = Addr;
S->Seg->ReadOnly = (S->Flags & SF_RO) != 0;
/* Remember the run memory for this segment, which is also a
- * flag that the segment has been placed.
- */
+ ** flag that the segment has been placed.
+ */
S->Seg->MemArea = M;
} else if (S->Load == M) {
/* This is the load memory area, *and* run and load are
- * different (because of the "else" above). Handle alignment.
- */
+ ** different (because of the "else" above). Handle alignment.
+ */
if (S->Flags & SF_ALIGN_LOAD) {
/* Align the address */
Addr = AlignAddr (Addr, S->LoadAlignment);
}
/* If this is the load memory area and the segment doesn't have a
- * fill value defined, use the one from the memory area.
- */
+ ** fill value defined, use the one from the memory area.
+ */
if (S->Load == M && (S->Flags & SF_FILLVAL) == 0) {
S->Seg->FillVal = M->FillVal;
}
/* Increment the fill level of the memory area and check for an
- * overflow.
- */
+ ** overflow.
+ */
M->FillLevel = Addr + S->Seg->Size - M->Start;
if (M->FillLevel > M->Size && (M->Flags & MF_OVERFLOW) == 0) {
++Overflows;
}
/* If requested, define symbols for the start and size of the
- * segment.
- */
+ ** segment.
+ */
if (S->Flags & SF_DEFINE) {
if (S->Run == M && (S->Flags & SF_RUN_DEF) == 0) {
CreateRunDefines (S, Addr);
Addr += S->Seg->Size;
/* If this segment will go out to the file, or its place
- * in the file will be filled, then increase the file size.
- */
+ ** in the file will be filled, then increase the file size.
+ */
if (S->Load == M &&
((S->Flags & SF_BSS) == 0 || (M->Flags & MF_FILL) != 0)) {
M->F->Size += Addr - StartAddr;
}
/* If requested, define symbols for start, size and offset of the
- * memory area
- */
+ ** memory area
+ */
if (M->Flags & MF_DEFINE) {
Export* E;
StrBuf Buf = STATIC_STRBUF_INITIALIZER;
CollAppend (&E->DefLines, M->LI);
/* Define the file offset of the memory area. This isn't of much
- * use for relocatable output files.
- */
+ ** use for relocatable output files.
+ */
if (!M->Relocatable) {
SB_Printf (&Buf, "__%s_FILEOFFS__", GetString (M->Name));
E = CreateConstExport (GetStrBufId (&Buf), M->FileOffs);
}
/* If we didn't have an overflow and are requested to fill the memory
- * area, acount for that in the file size.
- */
+ ** area, acount for that in the file size.
+ */
if ((M->Flags & MF_OVERFLOW) == 0 && (M->Flags & MF_FILL) != 0) {
M->F->Size += (M->Size - M->FillLevel);
}
} else {
/* No output file. Walk through the list and mark all segments
- * loading into these memory areas in this file as dumped.
- */
+ ** loading into these memory areas in this file as dumped.
+ */
unsigned J;
for (J = 0; J < CollCount (&F->MemoryAreas); ++J) {
unsigned CfgProcess (void);
/* Process the config file after reading in object files and libraries. This
- * includes postprocessing of the config file data but also assigning segments
- * and defining segment/memory area related symbols. The function will return
- * the number of memory area overflows (so zero means anything went ok).
- * In case of overflows, a short mapfile can be generated later, to ease the
- * task of rearranging segments for the user.
- */
+** includes postprocessing of the config file data but also assigning segments
+** and defining segment/memory area related symbols. The function will return
+** the number of memory area overflows (so zero means anything went ok).
+** In case of overflows, a short mapfile can be generated later, to ease the
+** task of rearranging segments for the user.
+*/
void CfgWriteTarget (void);
/* Write the target file(s) */
static void AssignIds (void)
/* Assign the base ids for debug info output. Within each module, many of the
- * items are addressed by ids which are actually the indices of the items in
- * the collections. To make them unique, we must assign a unique base to each
- * range.
- */
+** items are addressed by ids which are actually the indices of the items in
+** the collections. To make them unique, we must assign a unique base to each
+** range.
+*/
{
/* Walk over all modules */
unsigned I;
fprintf (F, "version\tmajor=2,minor=0\n");
/* Output a line with the item numbers so the debug info module is able
- * to preallocate the required memory.
- */
+ ** to preallocate the required memory.
+ */
fprintf (
F,
"info\tcsym=%u,file=%u,lib=%u,line=%u,mod=%u,scope=%u,seg=%u,span=%u,sym=%u,type=%u\n",
};
/* We will collect all debug symbols in the following array and remove
- * duplicates before outputing them into a label file.
- */
+** duplicates before outputing them into a label file.
+*/
static DbgSym* DbgSymPool[256];
static DbgSym* GetDbgSym (DbgSym* D, long Val)
/* Check if we find the same debug symbol in the table. If we find it, return
- * a pointer to the other occurrence, if we didn't find it, return NULL.
- */
+** a pointer to the other occurrence, if we didn't find it, return NULL.
+*/
{
/* Create the hash. We hash over the symbol value */
unsigned Hash = ((Val >> 24) & 0xFF) ^
}
/* If its an exports, there's also the export id, but we don't remember
- * it but use it to let the export point back to us.
- */
+ ** it but use it to let the export point back to us.
+ */
if (SYM_IS_EXPORT (D->Type)) {
/* Get the export from the export id, then set the our id */
GetObjExport (O, ReadVar (F))->DbgSymId = Id;
}
/* For cheap local symbols, add the owner symbol, for others,
- * add the owner scope.
- */
+ ** add the owner scope.
+ */
if (SYM_IS_STD (S->Type)) {
fprintf (F, ",scope=%u", O->ScopeBaseId + S->OwnerId);
} else {
PrintLineInfo (F, &S->RefLines, ",ref=%u");
/* If this is an import, output the id of the matching export.
- * If this is not an import, output its value and - if we have
- * it - the segment.
- */
+ ** If this is not an import, output its value and - if we have
+ ** it - the segment.
+ */
if (SYM_IS_IMPORT (S->Type)) {
/* Get the import */
fputs (",type=imp", F);
/* If this is not a linker generated symbol, and the module
- * that contains the export has debug info, output the debug
- * symbol id for the export
- */
+ ** that contains the export has debug info, output the debug
+ ** symbol id for the export
+ */
if (Exp->Obj && OBJ_HAS_DBGINFO (Exp->Obj->Header.Flags)) {
fprintf (F, ",exp=%u", Exp->Obj->SymBaseId + Exp->DbgSymId);
}
fprintf (F, ",val=0x%lX", Val);
/* Check for a segmented expression and add the segment id to
- * the debug info if we have one.
- */
+ ** the debug info if we have one.
+ */
GetSegExprVal (S->Expr, &D);
if (!D.TooComplex && D.Seg != 0) {
fprintf (F, ",seg=%u", D.Seg->Id);
Val = GetDbgSymVal (D);
/* Lookup this symbol in the table. If it is found in the table, it was
- * already written to the file, so don't emit it twice. If it is not in
- * the table, insert and output it.
- */
+ ** already written to the file, so don't emit it twice. If it is not in
+ ** the table, insert and output it.
+ */
if (GetDbgSym (D, Val) == 0) {
/* Emit the VICE label line */
void FreeImport (Import* I)
/* Free an import. NOTE: This won't remove the import from the exports table,
- * so it may only be called for unused imports (imports from modules that
- * aren't referenced).
- */
+** so it may only be called for unused imports (imports from modules that
+** aren't referenced).
+*/
{
/* Safety */
PRECONDITION ((I->Flags & IMP_INLIST) == 0);
/* Check the address size */
if (I->AddrSize == ADDR_SIZE_DEFAULT || I->AddrSize > ADDR_SIZE_LONG) {
/* Beware: This function may be called in cases where the object file
- * is not read completely into memory. In this case, the file list is
- * invalid. Be sure not to access it in this case.
- */
+ ** is not read completely into memory. In this case, the file list is
+ ** invalid. Be sure not to access it in this case.
+ */
if (ObjHasFiles (I->Obj)) {
const LineInfo* LI = GetImportPos (I);
Error ("Invalid import size in for `%s', imported from %s(%u): 0x%02X",
/* Check the address size */
if (I->AddrSize == ADDR_SIZE_DEFAULT || I->AddrSize > ADDR_SIZE_LONG) {
/* We have no object file information and no line info for a new
- * import
- */
+ ** import
+ */
Error ("Invalid import size 0x%02X for symbol `%s'",
I->AddrSize,
GetString (I->Name));
}
/* Ok, E now points to a valid exports entry for the given import. Insert
- * the import into the imports list and update the counters.
- */
+ ** the import into the imports list and update the counters.
+ */
I->Exp = E;
I->Next = E->ImpList;
E->ImpList = I;
void FreeExport (Export* E)
/* Free an export. NOTE: This won't remove the export from the exports table,
- * so it may only be called for unused exports (exports from modules that
- * aren't referenced).
- */
+** so it may only be called for unused exports (exports from modules that
+** aren't referenced).
+*/
{
/* Safety */
PRECONDITION ((E->Flags & EXP_INLIST) == 0);
ReadData (F, ConDes, ConDesCount);
/* Re-order the data. In the file, each decl is encoded into a byte
- * which contains the type and the priority. In memory, we will use
- * an array of types which contain the priority.
- */
+ ** which contains the type and the priority. In memory, we will use
+ ** an array of types which contain the priority.
+ */
for (I = 0; I < ConDesCount; ++I) {
E->ConDes[CD_GET_TYPE (ConDes[I])] = CD_GET_PRIO (ConDes[I]);
}
ReadLineInfoList (F, O, &E->RefLines);
/* If this symbol is exported as a condes, and the condes type declares a
- * forced import, add this import to the object module.
- */
+ ** forced import, add this import to the object module.
+ */
for (I = 0; I < CD_TYPE_COUNT; ++I) {
const ConDesImport* CDI;
CollAppend (&O->Imports, Imp);
/* Add line info for the export that is actually the condes that
- * forces the import. Then, add line info for the config. file.
- * The export's info is added first because the import pretends
- * that it came from the object module instead of the config. file.
- */
+ ** forces the import. Then, add line info for the config. file.
+ ** The export's info is added first because the import pretends
+ ** that it came from the object module instead of the config. file.
+ */
for (J = 0; J < CollCount (&E->DefLines); ++J) {
CollAppend (&Imp->RefLines, DupLineInfo (CollAt (&E->DefLines, J)));
}
if (L->Expr == 0) {
/* This *is* an unresolved external. Use the actual export
- * in E instead of the dummy one in L.
- */
+ ** in E instead of the dummy one in L.
+ */
E->Next = L->Next;
E->ImpCount = L->ImpCount;
E->ImpList = L->ImpList;
ImpOpen -= E->ImpCount; /* Decrease open imports now */
xfree (L);
/* We must run through the import list and change the
- * export pointer now.
- */
+ ** export pointer now.
+ */
Imp = E->ImpList;
while (Imp) {
Imp->Exp = E;
Export* FindExport (unsigned Name)
/* Check for an identifier in the list. Return 0 if not found, otherwise
- * return a pointer to the export.
- */
+** return a pointer to the export.
+*/
{
/* Get a pointer to the list with the symbols hash value */
Export* L = HashTab[Name & HASHTAB_MASK];
const LineInfo* ImportLI = GetImportPos (I);
/* Generate strings that describe the location of the im- and
- * exports. This depends on the place from where they come:
- * Object file or linker config.
- */
+ ** exports. This depends on the place from where they come:
+ ** Object file or linker config.
+ */
if (E->Obj) {
/* The export comes from an object file */
SB_Printf (&ExportLoc, "%s, %s(%u)",
GetSourceLine (ImportLI));
} else if (ImportLI) {
/* The import is linker generated and we have line
- * information
- */
+ ** information
+ */
SB_Printf (&ImportLoc, "%s(%u)",
GetSourceName (ImportLI),
GetSourceLine (ImportLI));
} else {
/* The import is linker generated and we don't have line
- * information
- */
+ ** information
+ */
SB_Printf (&ImportLoc, "%s", GetObjFileName (I->Obj));
}
static void PrintUnresolved (ExpCheckFunc F, void* Data)
/* Print a list of unresolved symbols. On unresolved symbols, F is
- * called (see the comments on ExpCheckFunc in the data section).
- */
+** called (see the comments on ExpCheckFunc in the data section).
+*/
{
unsigned I;
void CheckExports (void)
/* Setup the list of all exports and check for export/import symbol type
- * mismatches.
- */
+** mismatches.
+*/
{
/* Create an export pool */
CreateExportPool ();
void CheckUnresolvedImports (ExpCheckFunc F, void* Data)
/* Check if there are any unresolved imports. On unresolved imports, F is
- * called (see the comments on ExpCheckFunc in the data section).
- */
+** called (see the comments on ExpCheckFunc in the data section).
+*/
{
/* Check for unresolved externals */
if (ImpOpen != 0) {
const Export* Exp = ExpPool [I];
/* Print the symbol only if there are imports, or if a verbose map
- * file is requested.
- */
+ ** file is requested.
+ */
if (VerboseMap || Exp->ImpCount > 0) {
/* Print the export */
while (Imp) {
/* Print the import. Beware: The import might be linker
- * generated, in which case there is no object file and
- * sometimes no line information.
- */
+ ** generated, in which case there is no object file and
+ ** sometimes no line information.
+ */
const LineInfo* LI = GetImportPos (Imp);
if (LI) {
fprintf (F,
/* Prototype of a function that is called if an undefined symbol is found. It
- * may check if the symbol is an external symbol (for binary formats that
- * support externals) and will return zero if the symbol could not be
- * resolved, or a value != zero if the symbol could be resolved. The
- * CheckExports routine will print out the missing symbol in the first case.
- */
+** may check if the symbol is an external symbol (for binary formats that
+** support externals) and will return zero if the symbol could not be
+** resolved, or a value != zero if the symbol could be resolved. The
+** CheckExports routine will print out the missing symbol in the first case.
+*/
typedef int (*ExpCheckFunc) (unsigned Name, void* Data);
void FreeImport (Import* I);
/* Free an import. NOTE: This won't remove the import from the exports table,
- * so it may only be called for unused imports (imports from modules that
- * aren't referenced).
- */
+** so it may only be called for unused imports (imports from modules that
+** aren't referenced).
+*/
Import* ReadImport (FILE* F, ObjData* Obj);
/* Read an import from a file and insert it into the table */
void FreeExport (Export* E);
/* Free an export. NOTE: This won't remove the export from the exports table,
- * so it may only be called for unused exports (exports from modules that
- * aren't referenced).
- */
+** so it may only be called for unused exports (exports from modules that
+** aren't referenced).
+*/
Export* ReadExport (FILE* F, ObjData* Obj);
/* Read an export from a file */
Export* FindExport (unsigned Name);
/* Check for an identifier in the list. Return 0 if not found, otherwise
- * return a pointer to the export.
- */
+** return a pointer to the export.
+*/
int IsUnresolved (unsigned Name);
/* Check if this symbol is an unresolved export */
void CheckExports (void);
/* Setup the list of all exports and check for export/import symbol type
- * mismatches.
- */
+** mismatches.
+*/
void CheckUnresolvedImports (ExpCheckFunc F, void* Data);
/* Check if there are any unresolved imports. On unresolved imports, F is
- * called (see the comments on ExpCheckFunc in the data section).
- */
+** called (see the comments on ExpCheckFunc in the data section).
+*/
void PrintExportMapByName (FILE* F);
/* Print an export map to the given file (sorted by symbol name) */
int IsConstExpr (ExprNode* Root)
/* Return true if the given expression is a constant expression, that is, one
- * with no references to external symbols.
- */
+** with no references to external symbols.
+*/
{
int Const;
Export* E;
/* Get the referenced export */
E = GetExprExport (Root);
/* If this export has a mark set, we've already encountered it.
- * This means that the export is used to define it's own value,
- * which in turn means, that we have a circular reference.
- */
+ ** This means that the export is used to define it's own value,
+ ** which in turn means, that we have a circular reference.
+ */
if (ExportHasMark (E)) {
CircularRefError (E);
Const = 0;
case EXPR_SECTION:
/* A section expression is const if the segment it is in is
- * not relocatable and already placed.
- */
+ ** not relocatable and already placed.
+ */
S = GetExprSection (Root);
M = S->Seg->MemArea;
return M != 0 && (M->Flags & MF_PLACED) != 0 && !M->Relocatable;
GetSegExprVal (Root->Left, &D);
/* The expression is const if the expression contains exactly
- * one segment that is assigned to a memory area which has a
- * bank attribute that is constant.
- */
+ ** one segment that is assigned to a memory area which has a
+ ** bank attribute that is constant.
+ */
return (D.TooComplex == 0 &&
D.Seg != 0 &&
D.Seg->MemArea != 0 &&
PRECONDITION (Expr->Op == EXPR_SYMBOL);
/* If we have an object file, get the import from it, otherwise
- * (internally generated expressions), get the import from the
- * import pointer.
- */
+ ** (internally generated expressions), get the import from the
+ ** import pointer.
+ */
if (Expr->Obj) {
/* Return the Import */
return GetObjImport (Expr->Obj, Expr->V.ImpNum);
PRECONDITION (Expr->Op == EXPR_SECTION);
/* If we have an object file, get the section from it, otherwise
- * (internally generated expressions), get the section from the
- * section pointer.
- */
+ ** (internally generated expressions), get the section from the
+ ** section pointer.
+ */
if (Expr->Obj) {
/* Return the export */
return CollAt (&Expr->Obj->Sections, Expr->V.SecNum);
/* Get the referenced export */
E = GetExprExport (Expr);
/* If this export has a mark set, we've already encountered it.
- * This means that the export is used to define it's own value,
- * which in turn means, that we have a circular reference.
- */
+ ** This means that the export is used to define it's own value,
+ ** which in turn means, that we have a circular reference.
+ */
if (ExportHasMark (E)) {
CircularRefError (E);
Val = 0;
static void GetSegExprValInternal (ExprNode* Expr, SegExprDesc* D, int Sign)
/* Check if the given expression consists of a segment reference and only
- * constant values, additions and subtractions. If anything else is found,
- * set D->TooComplex to true.
- * Internal, recursive routine.
- */
+** constant values, additions and subtractions. If anything else is found,
+** set D->TooComplex to true.
+** Internal, recursive routine.
+*/
{
Export* E;
/* Get the referenced export */
E = GetExprExport (Expr);
/* If this export has a mark set, we've already encountered it.
- * This means that the export is used to define it's own value,
- * which in turn means, that we have a circular reference.
- */
+ ** This means that the export is used to define it's own value,
+ ** which in turn means, that we have a circular reference.
+ */
if (ExportHasMark (E)) {
CircularRefError (E);
} else {
void GetSegExprVal (ExprNode* Expr, SegExprDesc* D)
/* Check if the given expression consists of a segment reference and only
- * constant values, additions and subtractions. If anything else is found,
- * set D->TooComplex to true. The function will initialize D.
- */
+** constant values, additions and subtractions. If anything else is found,
+** set D->TooComplex to true. The function will initialize D.
+*/
{
/* Initialize the given structure */
D->Val = 0;
int IsConstExpr (ExprNode* Root);
/* Return true if the given expression is a constant expression, that is, one
- * with no references to external symbols.
- */
+** with no references to external symbols.
+*/
Import* GetExprImport (ExprNode* Expr);
/* Get the import data structure for a symbol expression node */
void GetSegExprVal (ExprNode* Expr, SegExprDesc* D);
/* Check if the given expression consists of a segment reference and only
- * constant values, additions and subtractions. If anything else is found,
- * set D->TooComplex to true. The function will initialize D.
- */
+** constant values, additions and subtractions. If anything else is found,
+** set D->TooComplex to true. The function will initialize D.
+*/
ExprNode* LiteralExpr (long Val, ObjData* O);
/* Return an expression tree that encodes the given literal value */
static void FreeExtSym (ExtSym* E)
/* Free an external symbol structure. Will not unlink the entry, so internal
- * use only.
- */
+** use only.
+*/
{
xfree (E);
}
ExtSym* GetExtSym (const ExtSymTab* Tab, unsigned Name)
/* Return the entry for the external symbol with the given name. Return NULL
- * if there is no such symbol.
- */
+** if there is no such symbol.
+*/
{
/* Hash the name */
unsigned Hash = (Name & HASHTAB_MASK);
const ExtSym* ExtSymList (const ExtSymTab* Tab)
/* Return the start of the symbol list sorted by symbol number. Call
- * ExtSymNext for the next symbol.
- */
+** ExtSymNext for the next symbol.
+*/
{
return Tab->Root;
}
ExtSym* GetExtSym (const ExtSymTab* Tab, unsigned Name);
/* Return the entry for the external symbol with the given name. Return NULL
- * if there is no such symbol.
- */
+** if there is no such symbol.
+*/
unsigned ExtSymCount (const ExtSymTab* Tab);
/* Return the number of symbols in the table */
const ExtSym* ExtSymList (const ExtSymTab* Tab);
/* Return the start of the symbol list sorted by symbol number. Call
- * ExtSymNext for the next symbol.
- */
+** ExtSymNext for the next symbol.
+*/
unsigned ExtSymNum (const ExtSym* E);
/* Return the number of an external symbol */
static int FindFileInfo (unsigned Name, unsigned* Index)
/* Find the FileInfo for a given file name. The function returns true if the
- * name was found. In this case, Index contains the index of the first item
- * that matches. If the item wasn't found, the function returns false and
- * Index contains the insert position for FileName.
- */
+** name was found. In this case, Index contains the index of the first item
+** that matches. If the item wasn't found, the function returns false and
+** Index contains the insert position for FileName.
+*/
{
/* Do a binary search */
int Lo = 0;
} else {
Hi = Cur - 1;
/* Since we may have duplicates, repeat the search until we've
- * the first item that has a match.
- */
+ ** the first item that has a match.
+ */
if (CurItem->Name == Name) {
Found = 1;
}
if (FindFileInfo (Name, &Index)) {
/* We have at least one such entry. Try all of them and, if size and
- * modification time matches, return the first match. When the loop
- * is terminated without finding an entry, Index points one behind
- * the last entry with the name, which is the perfect insert position.
- */
+ ** modification time matches, return the first match. When the loop
+ ** is terminated without finding an entry, Index points one behind
+ ** the last entry with the name, which is the perfect insert position.
+ */
FI = CollAt (&FileInfos, Index);
while (1) {
CollAppend (&FI->Modules, O);
/* Insert the file info in our global list. Index points to the insert
- * position.
- */
+ ** position.
+ */
CollInsert (&FileInfos, FI, Index);
/* Return the new struct */
/* Write a variable sized value to the file in special encoding */
{
/* We will write the value to the file in 7 bit chunks. If the 8th bit
- * is clear, we're done, if it is set, another chunk follows. This will
- * allow us to encode smaller values with less bytes, at the expense of
- * needing 5 bytes if a 32 bit value is written to file.
- */
+ ** is clear, we're done, if it is set, another chunk follows. This will
+ ** allow us to encode smaller values with less bytes, at the expense of
+ ** needing 5 bytes if a 32 bit value is written to file.
+ */
do {
unsigned char C = (V & 0x7F);
V >>= 7;
/* Read a variable size value from the file */
{
/* The value was written to the file in 7 bit chunks LSB first. If there
- * are more bytes, bit 8 is set, otherwise it is clear.
- */
+ ** are more bytes, bit 8 is set, otherwise it is clear.
+ */
unsigned char C;
unsigned long V = 0;
unsigned Shift = 0;
unsigned ReadStr (FILE* F)
/* Read a string from the file, place it into the global string pool, and
- * return its string id.
- */
+** return its string id.
+*/
{
unsigned Id;
StrBuf Buf = STATIC_STRBUF_INITIALIZER;
/* */
/* */
/* (C) 1998-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
unsigned ReadStr (FILE* F);
/* Read a string from the file, place it into the global string pool, and
- * return its string id.
- */
+** return its string id.
+*/
FilePos* ReadFilePos (FILE* F, FilePos* Pos);
/* Read a file position from the file */
Fragment* F;
/* Calculate the size of the memory block. LitBuf is only needed if the
- * fragment contains literal data.
- */
+ ** fragment contains literal data.
+ */
unsigned FragSize = sizeof (Fragment) - 1;
if (Type == FRAG_LITERAL) {
FragSize += Size;
static void ReadBasicData (Library* L, ObjData* O)
/* Read basic data for an object file that is necessary to resolve external
- * references.
- */
+** references.
+*/
{
/* Seek to the start of the object file and read the header */
LibSeek (L, O->Start);
}
/* Walk over the index and read basic data for all object files in the
- * library.
- */
+ ** library.
+ */
for (I = 0; I < CollCount (&L->Modules); ++I) {
ReadBasicData (L, CollAtUnchecked (&L->Modules, I));
}
static void LibCheckExports (ObjData* O)
/* Check if the exports from this file can satisfy any import requests. If so,
- * insert the imports and exports from this file and mark the file as added.
- */
+** insert the imports and exports from this file and mark the file as added.
+*/
{
unsigned I;
unsigned Additions;
/* Walk repeatedly over all open libraries until there's nothing more
- * to add.
- */
+ ** to add.
+ */
do {
Additions = 0;
Library* L = CollAt (&OpenLibs, I);
/* Walk through all modules in this library and check for each
- * module if there are unresolved externals in existing modules
- * that may be resolved by adding the module.
- */
+ ** module if there are unresolved externals in existing modules
+ ** that may be resolved by adding the module.
+ */
for (J = 0; J < CollCount (&L->Modules); ++J) {
/* Get the next module */
} while (Additions > 0);
/* We do know now which modules must be added, so we can load the data
- * for these modues into memory. Since we're walking over all modules
- * anyway, we will also remove data for unneeded modules.
- */
+ ** for these modues into memory. Since we're walking over all modules
+ ** anyway, we will also remove data for unneeded modules.
+ */
for (I = 0; I < CollCount (&OpenLibs); ++I) {
/* Get the next library */
Library* L = CollAt (&OpenLibs, I);
/* Walk over all modules in this library and add the files list and
- * sections for all referenced modules.
- */
+ ** sections for all referenced modules.
+ */
J = 0;
while (J < CollCount (&L->Modules)) {
ObjReadAssertions (L->F, O->Start + O->Header.AssertOffs, O);
/* Seek to the start of the segment list and read the segments.
- * This must be late, since the data here may reference other
- * stuff.
- */
+ ** This must be late, since the data here may reference other
+ ** stuff.
+ */
ObjReadSections (L->F, O->Start + O->Header.SegOffs, O);
/* Read the scope table from the object file. Scopes reference
- * segments, so we must read them after the sections.
- */
+ ** segments, so we must read them after the sections.
+ */
ObjReadScopes (L->F, O->Start + O->Header.ScopeOffs, O);
/* Read the spans */
ObjReadSpans (L->F, O->Start + O->Header.SpanOffs, O);
/* All references to strings are now resolved, so we can delete
- * the module string pool.
- */
+ ** the module string pool.
+ */
FreeObjStrings (O);
/* Insert the object into the list of all used object files */
}
/* If we have referenced modules in this library, assign it an id
- * (which is the index in the library collection) and keep it.
- */
+ ** (which is the index in the library collection) and keep it.
+ */
if (CollCount (&L->Modules) > 0) {
CloseLibrary (L);
L->Id = CollCount (&LibraryList);
void LibAdd (FILE* F, const char* Name)
/* Add files from the library to the list if there are references that could
- * be satisfied.
- */
+** be satisfied.
+*/
{
/* Add the library to the list of open libraries */
LibOpen (F, Name);
/* If there is no library group open, just resolve all open symbols and
- * close the library. Otherwise we will do nothing because resolving will
- * be done when the group is closed.
- */
+ ** close the library. Otherwise we will do nothing because resolving will
+ ** be done when the group is closed.
+ */
if (!Grouping) {
LibResolve ();
}
void LibStartGroup (void)
/* Start a library group. Objects within a library group may reference each
- * other, and libraries are searched repeatedly until all references are
- * satisfied.
- */
+** other, and libraries are searched repeatedly until all references are
+** satisfied.
+*/
{
/* We cannot already have a group open */
if (Grouping) {
void LibEndGroup (void)
/* End a library group and resolve all open references. Objects within a
- * library group may reference each other, and libraries are searched
- * repeatedly until all references are satisfied.
- */
+** library group may reference each other, and libraries are searched
+** repeatedly until all references are satisfied.
+*/
{
/* We must have a library group open */
if (!Grouping) {
void LibAdd (FILE* F, const char* Name);
/* Add files from the library to the list if there are references that could
- * be satisfied.
- */
+** be satisfied.
+*/
void LibStartGroup (void);
/* Start a library group. Objects within a library group may reference each
- * other, and libraries are searched repeatedly until all references are
- * satisfied.
- */
+** other, and libraries are searched repeatedly until all references are
+** satisfied.
+*/
void LibEndGroup (void);
/* End a library group and resolve all open references. Objects within a
- * library group may reference each other, and libraries are searched
- * repeatedly until all references are satisfied.
- */
+** library group may reference each other, and libraries are searched
+** repeatedly until all references are satisfied.
+*/
void LibCheckGroup (void);
/* Check if there are open library groups */
void ReadLineInfoList (FILE* F, ObjData* O, Collection* LineInfos)
/* Read a list of line infos stored as a list of indices in the object file,
- * make real line infos from them and place them into the passed collection.
- */
+** make real line infos from them and place them into the passed collection.
+*/
{
/* Read the number of line info indices that follow */
unsigned LineInfoCount = ReadVar (F);
unsigned LineInfoIndex = ReadVar (F);
/* The line info index was written by the assembler and must
- * therefore be part of the line infos read from the object file.
- */
+ ** therefore be part of the line infos read from the object file.
+ */
if (LineInfoIndex >= CollCount (&O->LineInfos)) {
Internal ("Invalid line info index %u in module `%s' - max is %u",
LineInfoIndex,
const LineInfo* GetAsmLineInfo (const Collection* LineInfos)
/* Find a line info of type LI_TYPE_ASM and count zero in the given collection
- * and return it. Return NULL if no such line info was found.
- */
+** and return it. Return NULL if no such line info was found.
+*/
{
unsigned I;
/* Structure holding line information. The Pos.Name field is always the
- * global string id of the file name. If the line info was read from the
- * object file, the File pointer is valid, otherwise it is NULL.
- */
+** global string id of the file name. If the line info was read from the
+** object file, the File pointer is valid, otherwise it is NULL.
+*/
typedef struct LineInfo LineInfo;
struct LineInfo {
unsigned Id; /* Line info id */
void ReadLineInfoList (FILE* F, struct ObjData* O, Collection* LineInfos);
/* Read a list of line infos stored as a list of indices in the object file,
- * make real line infos from them and place them into the passed collection.
- */
+** make real line infos from them and place them into the passed collection.
+*/
const LineInfo* GetAsmLineInfo (const Collection* LineInfos);
/* Find a line info of type LI_TYPE_ASM and count zero in the given collection
- * and return it. Return NULL if no such line info was found.
- */
+** and return it. Return NULL if no such line info was found.
+*/
#if defined(HAVE_INLINE)
INLINE const FilePos* GetSourcePos (const LineInfo* LI)
static unsigned long CvtNumber (const char* Arg, const char* Number)
/* Convert a number from a string. Allow '$' and '0x' prefixes for hex
- * numbers.
- */
+** numbers.
+*/
{
unsigned long Val;
int Converted;
Magic = Read32 (F);
/* Check the magic for known file types. The handling is somewhat weird
- * since we may have given a file with a ".lib" extension, which was
- * searched and found in a directory for library files, but we now find
- * out (by looking at the magic) that it's indeed an object file. We just
- * ignore the problem and hope no one will notice...
- */
+ ** since we may have given a file with a ".lib" extension, which was
+ ** searched and found in a directory for library files, but we now find
+ ** out (by looking at the magic) that it's indeed an object file. We just
+ ** ignore the problem and hope no one will notice...
+ */
switch (Magic) {
case OBJ_MAGIC:
if (ColPos == 0) {
/* Use default address size (which for now is always absolute
- * addressing)
- */
+ ** addressing)
+ */
InsertImport (GenImport (GetStringId (Arg), ADDR_SIZE_ABS));
} else {
ConDesCreate ();
/* Process data from the config file. Assign start addresses for the
- * segments, define linker symbols. The function will return the number
- * of memory area overflows (zero on success).
- */
+ ** segments, define linker symbols. The function will return the number
+ ** of memory area overflows (zero on success).
+ */
MemoryAreaOverflows = CfgProcess ();
/* Check module assertions */
CheckExports ();
/* If we had a memory area overflow before, we cannot generate the output
- * file. However, we will generate a short map file if requested, since
- * this will help the user to rearrange segments and fix the overflow.
- */
+ ** file. However, we will generate a short map file if requested, since
+ ** this will help the user to rearrange segments and fix the overflow.
+ */
if (MemoryAreaOverflows) {
if (MapFileName) {
CreateMapFile (SHORT_MAPFILE);
void CreateMapFile (int ShortMap)
/* Create a map file. If ShortMap is true, only the segment lists are
- * generated, not the import/export lists.
- */
+** generated, not the import/export lists.
+*/
{
unsigned I;
for (J = 0; J < CollCount (&O->Sections); ++J) {
const Section* S = CollConstAt (&O->Sections, J);
/* Don't include zero sized sections if not explicitly
- * requested
- */
+ ** requested
+ */
if (VerboseMap || S->Size > 0) {
fprintf (F,
" %-17s Offs=%06lX Size=%06lX "
/* */
/* */
/* (C) 1998-2005 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
void CreateMapFile (int ShortMap);
/* Create a map file. If ShortMap is true, only the segment lists are
- * generated, not the import/export lists.
- */
+** generated, not the import/export lists.
+*/
void CreateLabelFile (void);
/* Create a label file */
#define MF_ALIGN_MASK 0x0003 /* Mask to extract alignment */
/* The four o65 segment types. Note: These values are identical to the values
- * needed for the segmentID in the o65 spec.
- */
+** needed for the segmentID in the o65 spec.
+*/
#define O65SEG_UNDEF 0x00
#define O65SEG_ABS 0x01
#define O65SEG_TEXT 0x02
/* Map our own segment types into something o65 compatible */
{
/* Check the segment type. Readonly segments are assign to the o65
- * text segment, writeable segments that contain data are assigned
- * to data, bss and zp segments are handled respectively.
- * Beware: Zeropage segments have the SF_BSS flag set, so be sure
- * to check SF_ZP first.
- */
+ ** text segment, writeable segments that contain data are assigned
+ ** to data, bss and zp segments are handled respectively.
+ ** Beware: Zeropage segments have the SF_BSS flag set, so be sure
+ ** to check SF_ZP first.
+ */
if (S->Flags & SF_RO) {
return O65SEG_TEXT;
} else if (S->Flags & SF_ZP) {
static void CvtMemoryToSegment (ExprDesc* ED)
/* Convert a memory area into a segment by searching the list of run segments
- * in this memory area and assigning the nearest one.
- */
+** in this memory area and assigning the nearest one.
+*/
{
/* Get the memory area from the expression */
MemoryArea* M = ED->MemRef;
static const SegDesc* FindSeg (SegDesc** const List, unsigned Count, const Segment* S)
/* Search for a segment in the given list of segment descriptors and return
- * the descriptor for a segment if we found it, and NULL if not.
- */
+** the descriptor for a segment if we found it, and NULL if not.
+*/
{
unsigned I;
static void O65ParseExpr (ExprNode* Expr, ExprDesc* D, int Sign)
/* Extract and evaluate all constant factors in an subtree that has only
- * additions and subtractions. If anything other than additions and
- * subtractions are found, D->TooComplex is set to true.
- */
+** additions and subtractions. If anything other than additions and
+** subtractions are found, D->TooComplex is set to true.
+*/
{
Export* E;
/* Get the referenced Export */
E = GetExprExport (Expr);
/* If this export has a mark set, we've already encountered it.
- * This means that the export is used to define it's own value,
- * which in turn means, that we have a circular reference.
- */
+ ** This means that the export is used to define it's own value,
+ ** which in turn means, that we have a circular reference.
+ */
if (ExportHasMark (E)) {
CircularRefError (E);
} else if (E->Expr == 0) {
/* Remember the memory area reference */
D->MemRef = Expr->V.Mem;
/* Add the start address of the memory area to the constant
- * value
- */
+ ** value
+ */
D->Val += (Sign * D->MemRef->Start);
}
break;
static unsigned O65WriteExpr (ExprNode* E, int Signed, unsigned Size,
unsigned long Offs, void* Data)
/* Called from SegWrite for an expression. Evaluate the expression, check the
- * range and write the expression value to the file, update the relocation
- * table.
- */
+** range and write the expression value to the file, update the relocation
+** table.
+*/
{
long Diff;
unsigned RefCount;
}
/* We have a relocatable expression that needs a relocation table entry.
- * Calculate the number of bytes between this entry and the last one, and
- * setup all necessary intermediate bytes in the relocation table.
- */
+ ** Calculate the number of bytes between this entry and the last one, and
+ ** setup all necessary intermediate bytes in the relocation table.
+ */
Offs += D->SegSize; /* Calulate full offset */
Diff = ((long) Offs) - D->LastOffs;
while (Diff > 0xFE) {
}
/* If we have a memory area reference, we need to convert it into a
- * segment reference. If we cannot do that, we cannot handle the
- * expression.
- */
+ ** segment reference. If we cannot do that, we cannot handle the
+ ** expression.
+ */
if (ED.MemRef) {
CvtMemoryToSegment (&ED);
if (ED.SegRef == 0) {
WriteVal (D->F, BinVal, Size);
/* Determine the actual type of relocation entry needed from the
- * information gathered about the expression.
- */
+ ** information gathered about the expression.
+ */
if (E->Op == EXPR_BYTE0) {
RelocType = O65RELOC_LOW;
} else if (E->Op == EXPR_BYTE1) {
Seg = O65FindSeg (D, ED.SegRef);
if (Seg == 0) {
/* For some reason, we didn't find this segment in the list of
- * segments written to the o65 file.
- */
+ ** segments written to the o65 file.
+ */
return SEG_EXPR_INVALID;
}
RelocType |= O65SegType (Seg);
static void O65WriteBssSeg (O65Desc* D)
/* "Write" the bss segments to the o65 output file. This will only update
- * the relevant header fields.
- */
+** the relevant header fields.
+*/
{
/* Initialize variables */
D->CurReloc = 0;
static void O65WriteZPSeg (O65Desc* D)
/* "Write" the zeropage segments to the o65 output file. This will only update
- * the relevant header fields.
- */
+** the relevant header fields.
+*/
{
/* Initialize variables */
D->CurReloc = 0;
const char* Name = GetString (NameIdx);
/* Get the export for this symbol. We've checked before that this
- * export does really exist, so if it is unresolved, or if we don't
- * find it, there is an error in the linker code.
- */
+ ** export does really exist, so if it is unresolved, or if we don't
+ ** find it, there is an error in the linker code.
+ */
Export* E = FindExport (NameIdx);
if (E == 0 || IsUnresolvedExport (E)) {
Internal ("Unresolved export `%s' found in O65WriteExports", Name);
O65ParseExpr (Expr, InitExprDesc (&ED, D), 1);
/* We cannot handle expressions with imported symbols, or expressions
- * with more than one segment reference here
- */
+ ** with more than one segment reference here
+ */
if (ED.ExtRef != 0 || (ED.SegRef != 0 && ED.SecRef != 0)) {
ED.TooComplex = 1;
}
Seg = O65FindSeg (D, ED.SegRef);
if (Seg == 0) {
/* For some reason, we didn't find this segment in the list of
- * segments written to the o65 file.
- */
+ ** segments written to the o65 file.
+ */
Error ("Segment for symbol `%s' is undefined", Name);
}
SegmentID = O65SegType (Seg);
/* Set an exported identifier */
{
/* Get the export for this symbol and check if it does exist and is
- * a resolved symbol.
- */
+ ** a resolved symbol.
+ */
Export* E = FindExport (Ident);
if (E == 0 || IsUnresolvedExport (E)) {
Error ("Unresolved export: `%s'", GetString (Ident));
/* Update mode word, currently only the "simple" bit */
{
/* If we have byte wise relocation and an alignment of 1, and text
- * and data are adjacent, we can set the "simple addressing" bit
- * in the header.
- */
+ ** and data are adjacent, we can set the "simple addressing" bit
+ ** in the header.
+ */
if ((D->Header.Mode & MF_RELOC_MASK) == MF_RELOC_BYTE &&
(D->Header.Mode & MF_ALIGN_MASK) == MF_ALIGN_1 &&
D->Header.TextBase + D->Header.TextSize == D->Header.DataBase &&
D->Filename = GetString (F->Name);
/* Check for unresolved symbols. The function O65Unresolved is called
- * if we get an unresolved symbol.
- */
+ ** if we get an unresolved symbol.
+ */
D->Undef = 0; /* Reset the counter */
CheckUnresolvedImports (O65Unresolved, D);
if (D->Undef > 0) {
Print (stdout, 1, "Opened `%s'...\n", D->Filename);
/* Define some more options: A timestamp, the linker version and the
- * filename
- */
+ ** filename
+ */
T = time (0);
strcpy (OptBuf, ctime (&T));
OptLen = strlen (OptBuf);
void FreeObjData (ObjData* O)
/* Free an ObjData object. NOTE: This function works only for unused object
- * data, that is, ObjData objects that aren't used because they aren't
- * referenced.
- */
+** data, that is, ObjData objects that aren't used because they aren't
+** referenced.
+*/
{
unsigned I;
void FreeObjStrings (ObjData* O)
/* Free the module string data. Used once the object file is loaded completely
- * when all strings are converted to global strings.
- */
+** when all strings are converted to global strings.
+*/
{
xfree (O->Strings);
O->Strings = 0;
void InsertObjGlobals (ObjData* O)
/* Insert imports and exports from the object file into the global import and
- * export lists.
- */
+** export lists.
+*/
{
unsigned I;
const char* GetObjFileName (const ObjData* O)
/* Get the name of the object file. Return "[linker generated]" if the object
- * file is NULL.
- */
+** file is NULL.
+*/
{
return O? GetString (O->Name) : "[linker generated]";
}
void FreeObjData (ObjData* O);
/* Free an ObjData object. NOTE: This function works only for unused object
- * data, that is, ObjData objects that aren't used because they aren't
- * referenced.
- */
+** data, that is, ObjData objects that aren't used because they aren't
+** referenced.
+*/
void FreeObjStrings (ObjData* O);
/* Free the module string data. Used once the object file is loaded completely
- * when all strings are converted to global strings.
- */
+** when all strings are converted to global strings.
+*/
void InsertObjData (ObjData* O);
/* Insert the ObjData object into the collection of used ObjData objects. */
void InsertObjGlobals (ObjData* O);
/* Insert imports and exports from the object file into the global import and
- * export lists.
- */
+** export lists.
+*/
unsigned MakeGlobalStringId (const ObjData* O, unsigned Index);
/* Convert a local string id into a global one and return it. */
const char* GetObjFileName (const ObjData* O);
/* Get the name of the object file. Return "[linker generated]" if the object
- * file is NULL.
- */
+** file is NULL.
+*/
#if defined(HAVE_INLINE)
INLINE int ObjHasFiles (const ObjData* O)
ObjReadAssertions (Obj, O->Header.AssertOffs, O);
/* Read the segment list from the object file. This must be late, since
- * the expressions stored in the code may reference segments or imported
- * symbols.
- */
+ ** the expressions stored in the code may reference segments or imported
+ ** symbols.
+ */
ObjReadSections (Obj, O->Header.SegOffs, O);
/* Read the scope table from the object file. Scopes reference segments, so
- * we must read them after the sections.
- */
+ ** we must read them after the sections.
+ */
ObjReadScopes (Obj, O->Header.ScopeOffs, O);
/* Read the spans from the object file */
InsertObjData (O);
/* All references to strings are now resolved, so we can delete the module
- * string pool.
- */
+ ** string pool.
+ */
FreeObjStrings (O);
}
extern unsigned long CfgIVal;
/* Error location. PLEASE NOTE: I'm abusing the FilePos structure to some
- * degree. It is used mostly to hold a file position, where the Name member
- * is an index into the source file table of an object file. As used in config
- * file processing, the Name member is a string pool index instead. This is
- * distinguished by the object file pointer being NULL or not in the structs
- * where this is relevant.
- */
+** degree. It is used mostly to hold a file position, where the Name member
+** is an index into the source file table of an object file. As used in config
+** file processing, the Name member is a string pool index instead. This is
+** distinguished by the object file pointer being NULL or not in the structs
+** where this is relevant.
+*/
extern FilePos CfgErrorPos;
Segment* GetSegment (unsigned Name, unsigned char AddrSize, const char* ObjName)
/* Search for a segment and return an existing one. If the segment does not
- * exist, create a new one and return that. ObjName is only used for the error
- * message and may be NULL if the segment is linker generated.
- */
+** exist, create a new one and return that. ObjName is only used for the error
+** message and may be NULL if the segment is linker generated.
+*/
{
/* Try to locate the segment in the table */
Segment* S = SegFind (Name);
/* If we don't have that segment already, allocate it using the type of
- * the first section.
- */
+ ** the first section.
+ */
if (S == 0) {
/* Create a new segment */
S = NewSegment (Name, AddrSize);
int IsBSSType (Segment* S)
/* Check if the given segment is a BSS style segment, that is, it does not
- * contain non-zero data.
- */
+** contain non-zero data.
+*/
{
/* Loop over all sections */
unsigned I;
unsigned SegWriteConstExpr (FILE* F, ExprNode* E, int Signed, unsigned Size)
/* Write a supposedly constant expression to the target file. Do a range
- * check and return one of the SEG_EXPR_xxx codes.
- */
+** check and return one of the SEG_EXPR_xxx codes.
+*/
{
static const unsigned long U_Hi[4] = {
0x000000FFUL, 0x0000FFFFUL, 0x00FFFFFFUL, 0xFFFFFFFFUL
void SegWrite (const char* TgtName, FILE* Tgt, Segment* S, SegWriteFunc F, void* Data)
/* Write the data from the given segment to a file. For expressions, F is
- * called (see description of SegWriteFunc above).
- */
+** called (see description of SegWriteFunc above).
+*/
{
unsigned I;
int Sign;
Print (stdout, 2, " Section from \"%s\"\n", GetObjFileName (Sec->Obj));
/* If we have fill bytes, write them now. Beware: If this is the
- * first section, the fill value is not considered part of the segment
- * and therefore taken from the memory area.
- */
+ ** first section, the fill value is not considered part of the segment
+ ** and therefore taken from the memory area.
+ */
FillVal = (I == 0)? S->MemArea->FillVal : S->FillVal;
Print (stdout, 2, " Filling 0x%lx bytes with 0x%02x\n",
Sec->Fill, FillVal);
void CheckSegments (void)
/* Walk through the segment list and check if there are segments that were
- * not written to the output file. Output an error if this is the case.
- */
+** not written to the output file. Output an error if this is the case.
+*/
{
unsigned I;
for (I = 0; I < CollCount (&SegmentList); ++I) {
/* Prototype for a function that is used to write expressions to the target
- * file (used in SegWrite). It returns one of the following values:
- */
+** file (used in SegWrite). It returns one of the following values:
+*/
#define SEG_EXPR_OK 0U /* Ok */
#define SEG_EXPR_RANGE_ERROR 1U /* Range error */
#define SEG_EXPR_TOO_COMPLEX 2U /* Expression too complex */
Segment* GetSegment (unsigned Name, unsigned char AddrSize, const char* ObjName);
/* Search for a segment and return an existing one. If the segment does not
- * exist, create a new one and return that. ObjName is only used for the error
- * message and may be NULL if the segment is linker generated.
- */
+** exist, create a new one and return that. ObjName is only used for the error
+** message and may be NULL if the segment is linker generated.
+*/
Section* NewSection (Segment* Seg, unsigned long Alignment, unsigned char AddrSize);
/* Create a new section for the given segment */
int IsBSSType (Segment* S);
/* Check if the given segment is a BSS style segment, that is, it does not
- * contain non-zero data.
- */
+** contain non-zero data.
+*/
void SegDump (void);
/* Dump the segments and it's contents */
unsigned SegWriteConstExpr (FILE* F, ExprNode* E, int Signed, unsigned Size);
/* Write a supposedly constant expression to the target file. Do a range
- * check and return one of the SEG_EXPR_xxx codes.
- */
+** check and return one of the SEG_EXPR_xxx codes.
+*/
void SegWrite (const char* TgtName, FILE* Tgt, Segment* S, SegWriteFunc F, void* Data);
/* Write the data from the given segment to a file. For expressions, F is
- * called (see description of SegWriteFunc above).
- */
+** called (see description of SegWriteFunc above).
+*/
unsigned SegmentCount (void);
/* Return the total number of segments */
void CheckSegments (void);
/* Walk through the segment list and check if there are segments that were
- * not written to the output file. Output an error if this is the case.
- */
+** not written to the output file. Output an error if this is the case.
+*/
unsigned* ReadSpanList (FILE* F)
/* Read a list of span ids from a file. The list is returned as an array of
- * unsigneds, the first being the number of spans (never zero) followed by
- * the span ids. If the number of spans is zero, NULL is returned.
- */
+** unsigneds, the first being the number of spans (never zero) followed by
+** the span ids. If the number of spans is zero, NULL is returned.
+*/
{
unsigned* Spans;
void PrintDbgSpanList (FILE* F, const ObjData* O, const unsigned* List)
/* Output a string ",span=x[+y...]" for the given list. If the list is empty
- * or NULL, output nothing. This is a helper function for other modules to
- * print a list of spans read by ReadSpanList to the debug info file.
- */
+** or NULL, output nothing. This is a helper function for other modules to
+** print a list of spans read by ReadSpanList to the debug info file.
+*/
{
if (List && *List) {
unsigned I;
unsigned* ReadSpanList (FILE* F);
/* Read a list of span ids from a file. The list is returned as an array of
- * unsigneds, the first being the number of spans (never zero) followed by
- * the span ids. If the number of spans is zero, NULL is returned.
- */
+** unsigneds, the first being the number of spans (never zero) followed by
+** the span ids. If the number of spans is zero, NULL is returned.
+*/
unsigned* DupSpanList (const unsigned* S);
/* Duplicate a span list */
void PrintDbgSpanList (FILE* F, const struct ObjData* O, const unsigned* List);
/* Output a string ",span=x[+y...]" for the given list. If the list is empty
- * or NULL, output nothing. This is a helper function for other modules to
- * print a list of spans read by ReadSpanList to the debug info file.
- */
+** or NULL, output nothing. This is a helper function for other modules to
+** print a list of spans read by ReadSpanList to the debug info file.
+*/
void PrintDbgSpans (FILE* F);
/* Output the spans to a debug info file */
StrPool = NewStringPool (1103);
/* We insert a first string here, which will have id zero. This means
- * that we can treat index zero later as invalid.
- */
+ ** that we can treat index zero later as invalid.
+ */
SP_AddStr (StrPool, "<invalid message #0>");
}
static void DestroyStrPool (Collection* C)
/* Free all strings in the given pool plus the item pointers. Note: The
- * collection may not be reused later.
- */
+** collection may not be reused later.
+*/
{
unsigned I;
for (I = 0; I < CollCount (C); ++I) {
static const char* GetString (const Collection* C, unsigned Index)
/* Get a string from a collection. In fact, this function calls CollConstAt,
- * but will print a somewhat more readable error message if the index is out
- * of bounds.
- */
+** but will print a somewhat more readable error message if the index is out
+** of bounds.
+*/
{
if (Index >= CollCount (C)) {
Error ("Invalid string index (%u) - file corrupt!", Index);
default:
/* Unknown argument type. This means that we cannot determine
- * the option length, so we cannot proceed.
- */
+ ** the option length, so we cannot proceed.
+ */
Error ("Unknown option type: 0x%02X", Type);
break;
}
/* Read a variable size value from the file */
{
/* The value was written to the file in 7 bit chunks LSB first. If there
- * are more bytes, bit 8 is set, otherwise it is clear.
- */
+ ** are more bytes, bit 8 is set, otherwise it is clear.
+ */
unsigned char C;
unsigned long V = 0;
unsigned Shift = 0;
#define GET_SF() ((Regs.SR & SF) != 0)
/* Set the flags. The parameter is a boolean flag that says if the flag should be
- * set or reset.
- */
+** set or reset.
+*/
#define SET_CF(f) do { if (f) { Regs.SR |= CF; } else { Regs.SR &= ~CF; } } while (0)
#define SET_ZF(f) do { if (f) { Regs.SR |= ZF; } else { Regs.SR &= ~ZF; } } while (0)
#define SET_IF(f) do { if (f) { Regs.SR |= IF; } else { Regs.SR &= ~IF; } } while (0)
#define SET_SF(f) do { if (f) { Regs.SR |= SF; } else { Regs.SR &= ~SF; } } while (0)
/* Special test and set macros. The meaning of the parameter depends on the
- * actual flag that should be set or reset.
- */
+** actual flag that should be set or reset.
+*/
#define TEST_ZF(v) SET_ZF (((v) & 0xFF) == 0)
#define TEST_SF(v) SET_SF (((v) & 0x80) != 0)
#define TEST_CF(v) SET_CF (((v) & 0xFF00) != 0)
unsigned ExecuteInsn (void);
/* Execute one CPU instruction. Return the number of clock cycles for the
- * executed instruction.
- */
+** executed instruction.
+*/
unsigned long GetCycles (void);
/* Return the total number of clock cycles executed */
unsigned MemReadZPWord (unsigned char Addr)
/* Read a word from the zero page. This function differs from ReadMemW in that
- * the read will always be in the zero page, even in case of an address
- * overflow.
- */
+** the read will always be in the zero page, even in case of an address
+** overflow.
+*/
{
unsigned W = MemReadByte (Addr++);
return (W | (MemReadByte (Addr) << 8));
unsigned MemReadZPWord (unsigned char Addr);
/* Read a word from the zero page. This function differs from ReadMemW in that
- * the read will always be in the zero page, even in case of an address
- * overflow.
- */
+** the read will always be in the zero page, even in case of an address
+** overflow.
+*/
void MemInit (void);
/* Initialize the memory subsystem */
int FindAttr (const Collection* C, const char* Name, unsigned* Index)
/* Search for an attribute with the given name in the collection. If it is
- * found, the function returns true and Index contains the index of the
- * entry. If Name isn't found, the function returns false and Index
- * will contain the insert position.
- */
+** found, the function returns true and Index contains the index of the
+** entry. If Name isn't found, the function returns false and Index
+** will contain the insert position.
+*/
{
/* Do a binary search */
int Lo = 0;
const Attr* GetAttr (const Collection* C, const char* Name)
/* Search for an attribute with the given name and return it. The function
- * returns NULL if the attribute wasn't found.
- */
+** returns NULL if the attribute wasn't found.
+*/
{
/* Search for the attribute and return it */
unsigned Index;
const Attr* NeedAttr (const Collection* C, const char* Name, const char* Op)
/* Search for an attribute with the given name and return it. If the attribute
- * is not found, the function terminates with an error using Op as additional
- * context in the error message.
- */
+** is not found, the function terminates with an error using Op as additional
+** context in the error message.
+*/
{
/* Search for the attribute and return it */
unsigned Index;
const char* GetAttrVal (const Collection* C, const char* Name)
/* Search for an attribute with the given name and return its value. The
- * function returns NULL if the attribute wasn't found.
- */
+** function returns NULL if the attribute wasn't found.
+*/
{
const Attr* A = GetAttr (C, Name);
return (A == 0)? 0 : A->Value;
const char* NeedAttrVal (const Collection* C, const char* Name, const char* Op)
/* Search for an attribute with the given name and return its value. If the
- * attribute wasn't not found, the function terminates with an error using
- * Op as additional context in the error message.
- */
+** attribute wasn't not found, the function terminates with an error using
+** Op as additional context in the error message.
+*/
{
const Attr* A = NeedAttr (C, Name, Op);
return (A == 0)? 0 : A->Value;
Attr* A = NewAttr (Name, Value);
/* Search for the attribute. If it is there, we have a duplicate, otherwise
- * we have the insert position.
- */
+ ** we have the insert position.
+ */
unsigned Index;
if (FindAttr (C, Name, &Index)) {
Error ("Duplicate command line attribute `%s'", Name);
void SplitAddAttr (Collection* C, const char* Combined, const char* Name)
/* Split a combined name/value pair and add it as an attribute to C. Some
- * attributes may not need a name. If the name is missing, use Name. If
- * Name is NULL, terminate with an error.
- */
+** attributes may not need a name. If the name is missing, use Name. If
+** Name is NULL, terminate with an error.
+*/
{
/* Name and value are separated by an equal sign */
const char* Pos = strchr (Combined, '=');
Collection* ParseAttrList (const char* List, const char** NameList, unsigned NameCount)
/* Parse a list containing name/value pairs into a sorted collection. Some
- * attributes may not need a name, so NameList contains these names. If there
- * were no errors, the function returns a alphabetically sorted collection
- * containing Attr entries.
- */
+** attributes may not need a name, so NameList contains these names. If there
+** were no errors, the function returns a alphabetically sorted collection
+** containing Attr entries.
+*/
{
const char* Name;
int FindAttr (const Collection* C, const char* Name, unsigned* Index);
/* Search for an attribute with the given name in the collection. If it is
- * found, the function returns true and Index contains the index of the
- * entry. If Name isn't found, the function returns false and Index
- * will contain the insert position.
- */
+** found, the function returns true and Index contains the index of the
+** entry. If Name isn't found, the function returns false and Index
+** will contain the insert position.
+*/
const Attr* GetAttr (const Collection* C, const char* Name);
/* Search for an attribute with the given name and return it. The function
- * returns NULL if the attribute wasn't found.
- */
+** returns NULL if the attribute wasn't found.
+*/
const Attr* NeedAttr (const Collection* C, const char* Name, const char* Op);
/* Search for an attribute with the given name and return it. If the attribute
- * is not found, the function terminates with an error using Op as additional
- * context in the error message.
- */
+** is not found, the function terminates with an error using Op as additional
+** context in the error message.
+*/
const char* GetAttrVal (const Collection* C, const char* Name);
/* Search for an attribute with the given name and return its value. The
- * function returns NULL if the attribute wasn't found.
- */
+** function returns NULL if the attribute wasn't found.
+*/
const char* NeedAttrVal (const Collection* C, const char* Name, const char* Op);
/* Search for an attribute with the given name and return its value. If the
- * attribute wasn't not found, the function terminates with an error using
- * Op as additional context in the error message.
- */
+** attribute wasn't not found, the function terminates with an error using
+** Op as additional context in the error message.
+*/
void AddAttr (Collection* C, const char* Name, const char* Value);
/* Add an attribute to an alphabetically sorted attribute collection */
void SplitAddAttr (Collection* C, const char* Combined, const char* Name);
/* Split a combined name/value pair and add it as an attribute to C. Some
- * attributes may not need a name. If the name is missing, use Name. If
- * Name is NULL, terminate with an error.
- */
+** attributes may not need a name. If the name is missing, use Name. If
+** Name is NULL, terminate with an error.
+*/
Collection* ParseAttrList (const char* List, const char** NameList, unsigned NameCount);
/* Parse a list containing name/value pairs into a sorted collection. Some
- * attributes may not need a name, so NameList contains these names. If there
- * were no errors, the function returns a alphabetically sorted collection
- * containing Attr entries.
- */
+** attributes may not need a name, so NameList contains these names. If there
+** were no errors, the function returns a alphabetically sorted collection
+** containing Attr entries.
+*/
void FreeAttrList (Collection* C);
/* Free a list of attributes */
}
/* Write to the file. We will use fwrite here instead of the fileio
- * module, since it's just one call, so the latter doesn't have any
- * advantages, and we can output a more readable error message in case of
- * problems.
- */
+ ** module, since it's just one call, so the latter doesn't have any
+ ** advantages, and we can output a more readable error message in case of
+ ** problems.
+ */
Size = SB_GetLen (Data);
if (fwrite (SB_GetConstBuf (Data), 1, Size, F) != Size) {
Error ("Error writing to output file `%s': %s", Name, strerror (errno));
Bitmap* SliceBitmap (const Bitmap* O, unsigned OrigX, unsigned OrigY,
unsigned Width, unsigned Height)
/* Create a slice of the given bitmap. The slice starts at position X/Y of
- * the original and has the given width and height. Location 0/0 is at the
- * upper left corner.
- */
+** the original and has the given width and height. Location 0/0 is at the
+** upper left corner.
+*/
{
Bitmap* B;
unsigned Y;
Color GetPixelColor (const Bitmap* B, unsigned X, unsigned Y)
/* Get the color for a given pixel. For indexed bitmaps, the palette entry
- * is returned.
- */
+** is returned.
+*/
{
/* Get the pixel at the given coordinates */
Pixel P = GetPixel (B, X, Y);
/* If the bitmap has a palette, return the color from the palette. For
- * simplicity, we will only check the palette, not the type.
- */
+ ** simplicity, we will only check the palette, not the type.
+ */
if (B->Pal) {
if (P.Index >= B->Pal->Count) {
/* Palette index is invalid */
Pixel GetPixel (const Bitmap* B, unsigned X, unsigned Y)
/* Return a pixel from the bitmap. The returned value may either be a color
- * or a palette index, depending on the type of the bitmap.
- */
+** or a palette index, depending on the type of the bitmap.
+*/
{
/* Check the coordinates */
PRECONDITION (X < B->Width && Y < B->Height);
struct Bitmap {
/* Name of the bitmap. This is used for error messages and should be
- * something that allows the user to identify which bitmap the message
- * refers to. For bitmaps loaded from a file, using the file name is
- * a good idea.
- */
+ ** something that allows the user to identify which bitmap the message
+ ** refers to. For bitmaps loaded from a file, using the file name is
+ ** a good idea.
+ */
StrBuf Name;
/* Size of the bitmap */
unsigned X, unsigned Y,
unsigned Width, unsigned Height);
/* Create a slice of the given bitmap. The slice starts at position X/Y of
- * the original and has the given width and height. Location 0/0 is at the
- * upper left corner.
- */
+** the original and has the given width and height. Location 0/0 is at the
+** upper left corner.
+*/
Color GetPixelColor (const Bitmap* B, unsigned X, unsigned Y);
/* Get the color for a given pixel. For indexed bitmaps, the palette entry
- * is returned.
- */
+** is returned.
+*/
Pixel GetPixel (const Bitmap* B, unsigned X, unsigned Y);
/* Return a pixel from the bitmap. The returned value may either be a color
- * or a palette index, depending on the type of the bitmap.
- */
+** or a palette index, depending on the type of the bitmap.
+*/
#if defined(HAVE_INLINE)
INLINE int BitmapIsIndexed (const Bitmap* B)
#if defined(HAVE_INLINE)
INLINE unsigned GetBitmapColors (const Bitmap* B)
/* Get the number of colors in an image. The function will return the number
- * of palette entries for indexed bitmaps and 2^24 for non indexed bitmaps.
- */
+** of palette entries for indexed bitmaps and 2^24 for non indexed bitmaps.
+*/
{
return B->Pal? B->Pal->Count : (1U << 24);
}
/* Write a readable header */
fprintf (F,
"/*\n"
- " * This file was generated by %s %s from\n"
- " * %.*s (%ux%u, %u colors%s)\n"
- " */\n"
+ "** This file was generated by %s %s from\n"
+ "** %.*s (%ux%u, %u colors%s)\n"
+ "*/\n"
"\n",
ProgName,
GetVersionAsString (),
BitmapIsIndexed (B)? ", indexed" : "");
/* If an identifier was given, output #defines for width, height, the
- * number of colors and declare a variable for the data.
- */
+ ** number of colors and declare a variable for the data.
+ */
if (Ident) {
fprintf (F,
"#define %s_COLORS %u\n"
StrBuf* ConvertTo (const Bitmap* B, const Collection* A)
/* Convert the bitmap B into some sort of other binary format. The output is
- * stored in a string buffer (which is actually a dynamic char array) and
- * returned. The actual output format is taken from the "format" attribute
- * in the attribute collection A.
- */
+** stored in a string buffer (which is actually a dynamic char array) and
+** returned. The actual output format is taken from the "format" attribute
+** in the attribute collection A.
+*/
{
const ConverterMapEntry* E;
StrBuf* ConvertTo (const Bitmap* B, const Collection* A);
/* Convert the bitmap B into some sort of other binary format. The output is
- * stored in a string buffer (which is actually a dynamic char array) and
- * returned. The actual output format is taken from the "format" attribute
- * in the attribute collection A.
- */
+** stored in a string buffer (which is actually a dynamic char array) and
+** returned. The actual output format is taken from the "format" attribute
+** in the attribute collection A.
+*/
void ListConversionTargets (FILE* F);
/* Output a list of conversion targets */
static void StoreByte (struct RLE* RLE)
/* Store a unique byte or a run of repeated bytes. If count is zero, the
- * function will flush the internal buffers, so that all data is in RLE->D.
- */
+** function will flush the internal buffers, so that all data is in RLE->D.
+*/
{
if (RLE->Count == 1 || RLE->Count == 2) {
/* A run of two identical bytes is treated as two unique bytes, since
- * this will usually merge with the following run.
- */
+ ** this will usually merge with the following run.
+ */
SB_AppendChar (&RLE->UniqueData, RLE->LastVal);
if (RLE->Count == 2) {
SB_AppendChar (&RLE->UniqueData, RLE->LastVal);
} else {
/* Run of repeated bytes. First flush the temp buffer for unique
- * bytes.
- */
+ ** bytes.
+ */
const char* Buf = SB_GetConstBuf (&RLE->UniqueData);
unsigned Count = SB_GetLen (&RLE->UniqueData);
while (Count) {
StrBuf* GenGeosBitmap (const Bitmap* B, const Collection* A attribute ((unused)))
/* Generate binary output in GEOS compacted bitmap format for the bitmap B.
- * The output is stored in a string buffer (which is actually a dynamic char
- * array) and returned.
- */
+** The output is stored in a string buffer (which is actually a dynamic char
+** array) and returned.
+*/
{
unsigned LineWidth;
unsigned char* Buf;
SB_Realloc (D, 64);
/* Compact the image. We're currently using only REPEAT and UNIQUE opcodes.
- * BIGCOUNT is rather difficult to apply.
- */
+ ** BIGCOUNT is rather difficult to apply.
+ */
RLE.Buf = Buf;
RLE.Remaining = LineWidth * GetBitmapHeight (B) - 1;
RLE.LastVal = *RLE.Buf++;
StrBuf* GenGeosBitmap (const Bitmap* B, const Collection* A);
/* Generate binary output in GEOS compacted bitmap format for the bitmap B.
- * The output is stored in a string buffer (which is actually a dynamic char
- * array) and returned.
- */
+** The output is stored in a string buffer (which is actually a dynamic char
+** array) and returned.
+*/
StrBuf* GenGeosIcon (const Bitmap* B, const Collection* A attribute ((unused)))
/* Generate binary output in GEOS icon format for the bitmap B. The output
- * is stored in a string buffer (which is actually a dynamic char array) and
- * returned.
- */
+** is stored in a string buffer (which is actually a dynamic char array) and
+** returned.
+*/
{
StrBuf* D;
unsigned X, Y;
StrBuf* GenGeosIcon (const Bitmap* B, const Collection* A);
/* Generate binary output in GEOS icon format for the bitmap B. The output
- * is stored in a string buffer (which is actually a dynamic char array) and
- * returned.
- */
+** is stored in a string buffer (which is actually a dynamic char array) and
+** returned.
+*/
Bitmap* ReadInputFile (const Collection* A)
/* Read a bitmap from a file and return it. Format, file name etc. must be
- * given as attributes in A. If no format is given, the function tries to
- * autodetect it by using the extension of the file name.
- */
+** given as attributes in A. If no format is given, the function tries to
+** autodetect it by using the extension of the file name.
+*/
{
const FileId* F;
Bitmap* ReadInputFile (const Collection* A);
/* Read a bitmap from a file and return it. Format, file name etc. must be
- * given as attributes in A. If no format is given, the function tries to
- * autodetect it by using the extension of the file name.
- */
+** given as attributes in A. If no format is given, the function tries to
+** autodetect it by using the extension of the file name.
+*/
StrBuf* GenKoala (const Bitmap* B, const Collection* A attribute ((unused)))
/* Generate binary output in koala format for the bitmap B. The output is
- * stored in a string buffer (which is actually a dynamic char array) and
- * returned.
- */
+** stored in a string buffer (which is actually a dynamic char array) and
+** returned.
+*/
{
StrBuf* D;
unsigned char Screen[160][200];
StrBuf* GenKoala (const Bitmap* B, const Collection* A);
/* Generate binary output in koala format for the bitmap B. The output is
- * stored in a string buffer (which is actually a dynamic char array) and
- * returned.
- */
+** stored in a string buffer (which is actually a dynamic char array) and
+** returned.
+*/
static void encodeSprite(StrBuf *D, enum Mode M, char ColorBits, char ColorMask, char LineBuffer[512],
int len, int LastOpaquePixel) {
/*
- * The data starts with a byte count. It tells the number of bytes on this
- * line + 1.
- * Special case is a count of 1. It will change to next quadrant.
- * Other special case is 0. It will end the sprite.
- *
- * Ordinary data packet. These are bits in a stream.
- * 1=literal 0=packed
- * 4 bit count (+1)
- * for literal you put "count" values
- * for packed you repeat the value "count" times
- * Never use packed mode for one pixel
- * If the last bit on a line is 1 you need to add a byte of zeroes
- * A sequence 00000 ends a scan line
- *
- * All data is high nybble first
- */
+** The data starts with a byte count. It tells the number of bytes on this
+** line + 1.
+** Special case is a count of 1. It will change to next quadrant.
+** Other special case is 0. It will end the sprite.
+**
+** Ordinary data packet. These are bits in a stream.
+** 1=literal 0=packed
+** 4 bit count (+1)
+** for literal you put "count" values
+** for packed you repeat the value "count" times
+** Never use packed mode for one pixel
+** If the last bit on a line is 1 you need to add a byte of zeroes
+** A sequence 00000 ends a scan line
+**
+** All data is high nybble first
+*/
unsigned char V = 0;
signed i;
signed count;
StrBuf* GenLynxSprite (const Bitmap* B, const Collection* A)
/* Generate binary output in Lynx sprite format for the bitmap B. The output
- * is stored in a string buffer (which is actually a dynamic char array) and
- * returned.
- *
- * The Lynx will draw 4 quadrants:
- * - Down right
- * - Up right
- * - Up left
- * - Down left
- *
- * The sprite will end with a byte 0.
- */
+** is stored in a string buffer (which is actually a dynamic char array) and
+** returned.
+**
+** The Lynx will draw 4 quadrants:
+** - Down right
+** - Up right
+** - Up left
+** - Down left
+**
+** The sprite will end with a byte 0.
+*/
{
enum Mode M;
StrBuf* D;
StrBuf* GenLynxSprite (const Bitmap* B, const Collection* A);
/* Generate binary output in packed Lynx sprite format for the bitmap B. The output
- * is stored in a string buffer (which is actually a dynamic char array) and
- * returned.
- */
+** is stored in a string buffer (which is actually a dynamic char array) and
+** returned.
+*/
static void SetWorkBitmap (Bitmap* N)
/* Delete an old working bitmap and set a new one. The new one may be NULL
- * to clear it.
- */
+** to clear it.
+*/
{
/* If we have a distinct work bitmap, delete it */
if (C != 0 && C != B) {
static void SetOutputData (StrBuf* N)
/* Delete the old output data and replace it by the given one. The new one
- * may be NULL to clear it.
- */
+** may be NULL to clear it.
+*/
{
/* Delete the old output data */
if (D != 0) {
void WriteOutputFile (const StrBuf* Data, const Collection* A, const Bitmap* B)
/* Write the contents of Data to a file. Format, file name etc. must be given
- * as attributes in A. If no format is given, the function tries to autodetect
- * it by using the extension of the file name. The bitmap passed to the
- * function is the bitmap used as source of the conversion. It may be used to
- * determine the bitmap properties for documentation purposes.
- */
+** as attributes in A. If no format is given, the function tries to autodetect
+** it by using the extension of the file name. The bitmap passed to the
+** function is the bitmap used as source of the conversion. It may be used to
+** determine the bitmap properties for documentation purposes.
+*/
{
const FileId* F;
void WriteOutputFile (const StrBuf* Data, const Collection* A, const Bitmap* B);
/* Write the contents of Data to a file. Format, file name etc. must be given
- * as attributes in A. If no format is given, the function tries to autodetect
- * it by using the extension of the file name. The bitmap passed to the
- * function is the bitmap used as source of the conversion. It may be used to
- * determine the bitmap properties for documentation purposes.
- */
+** as attributes in A. If no format is given, the function tries to autodetect
+** it by using the extension of the file name. The bitmap passed to the
+** function is the bitmap used as source of the conversion. It may be used to
+** determine the bitmap properties for documentation purposes.
+*/
P->Compressed, Name);
}
/* We support:
- * - one plane with either 1 or 8 bits per pixel
- * - three planes with 8 bits per pixel
- * - four planes with 8 bits per pixel (does this exist?)
- */
+ ** - one plane with either 1 or 8 bits per pixel
+ ** - three planes with 8 bits per pixel
+ ** - four planes with 8 bits per pixel (does this exist?)
+ */
if (!((P->BPP == 1 && P->Planes == 1) ||
(P->BPP == 8 && (P->Planes == 1 || P->Planes == 3 || P->Planes == 4)))) {
/* We could support others, but currently we don't */
}
/* One plane means we have a palette which is either part of the header
- * or follows.
- */
+ ** or follows.
+ */
if (P->PalInfo == 0) {
/* Create the monochrome palette */
StrBuf* GenRaw (const Bitmap* B, const Collection* A attribute ((unused)))
/* Generate binary output in raw format. The output is stored in a string
- * buffer (which is actually a dynamic char array) and returned.
- */
+** buffer (which is actually a dynamic char array) and returned.
+*/
{
StrBuf* D;
unsigned X, Y;
StrBuf* GenRaw (const Bitmap* B, const Collection* A);
/* Generate binary output in raw format. The output is stored in a string
- * buffer (which is actually a dynamic char array) and returned.
- */
+** buffer (which is actually a dynamic char array) and returned.
+*/
StrBuf* GenVic2Sprite (const Bitmap* B, const Collection* A)
/* Generate binary output in VICII sprite format for the bitmap B. The output
- * is stored in a string buffer (which is actually a dynamic char array) and
- * returned.
- */
+** is stored in a string buffer (which is actually a dynamic char array) and
+** returned.
+*/
{
enum Mode M;
StrBuf* D;
StrBuf* GenVic2Sprite (const Bitmap* B, const Collection* A);
/* Generate binary output in VICII sprite format for the bitmap B. The output
- * is stored in a string buffer (which is actually a dynamic char array) and
- * returned.
- */
+** is stored in a string buffer (which is actually a dynamic char array) and
+** returned.
+*/
/*
- * testprogram printing the default device
- *
- * 26-Nov-2009, Christian Groessler
- */
+** testprogram printing the default device
+**
+** 26-Nov-2009, Christian Groessler
+*/
#include <stdio.h>
#include <conio.h>
/*
- * show some memory stuff
- *
- * 04-Aug-2004, Christian Groessler
- */
+** show some memory stuff
+**
+** 04-Aug-2004, Christian Groessler
+*/
#include <stdio.h>
#include <stdlib.h>
/*
- * testprogram for get_ostype() and get_tv() functions
- *
- * 09-Jul-2004, chris@groessler.org
- */
+** testprogram for get_ostype() and get_tv() functions
+**
+** 09-Jul-2004, chris@groessler.org
+*/
#include <stdio.h>
#include <atari.h>
/*
- * testprogram for _sys() function on Atari
- *
- * 17-Sep-2013, chris@groessler.org
- *
- * uses PUTCHR IOCB function to display a string
- */
+** testprogram for _sys() function on Atari
+**
+** 17-Sep-2013, chris@groessler.org
+**
+** uses PUTCHR IOCB function to display a string
+*/
#include <atari.h>
#include <6502.h>
/*
- * simple clock test
- *
- * 06-Nov-2001, Christian Groessler
- */
+** simple clock test
+**
+** 06-Nov-2001, Christian Groessler
+*/
#include <stdio.h>
#include <conio.h>
/*
- * test program for the cprintf() function
- * (for the \r and \n special operators)
- * CPG
- *
- * The output generated by this program should look
- * like this:
- *
- * ---- top of screen --------
- * 12345
- * 67890
- *
- *
- * 67890
- *
- * hit return to exit....
+** test program for the cprintf() function
+** (for the \r and \n special operators)
+** CPG
+**
+** The output generated by this program should look
+** like this:
+**
+** ---- top of screen --------
+** 12345
+** 67890
+**
+**
+** 67890
+**
+** hit return to exit....
.
.
.
- * ---- bottom of screen -----
- */
+** ---- bottom of screen -----
+*/
#include <stdio.h>
#include <conio.h>
/*
- * test for conio cursor() function
- * CPG 2002
- *
- * the cursor should be in the same state as mentioned in the printfs
- */
+** test for conio cursor() function
+** CPG 2002
+**
+** the cursor should be in the same state as mentioned in the printfs
+*/
#include <conio.h>
/*
- * test program for the debugger
- *
- * press 'd' to enter the debugger
- *
- */
+** test program for the debugger
+**
+** press 'd' to enter the debugger
+**
+*/
#include <stdio.h>
#include <conio.h>
cputs ("\r\nTesting em_copyfrom/em_copyto");
/* We're filling now 384 bytes per run to test the copy routines with
- * other sizes.
- */
+ ** other sizes.
+ */
PageCount = (PageCount * 2) / 3;
/* Setup the copy structure */
/*
- * simple file i/o test
- *
- * 12-Jun-2000, Christian Groessler
- *
- * please compile with
- * cl65 -tsystem ft.c getsp.s -o ft.com
- *
- * The program asks for a filename (if it hasn't
- * got one from argv). I then opens the file,
- * reads the the first 16 bytes and displays them
- * (as hex values).
- * The values of sp (cc65 runtime stack pointer)
- * are displayed at some places. The displayed
- * value should always be the same.
- */
+** simple file I/O test
+**
+** 12-Jun-2000, Christian Groessler
+**
+** please compile with
+** cl65 -tsystem ft.c getsp.s -o ft.com
+**
+** The program asks for a filename (if it hasn't
+** got one from argv). I then opens the file,
+** reads the the first 16 bytes and displays them
+** (as hex values).
+** The values of sp (cc65 runtime stack pointer)
+** are displayed at some places. The displayed
+** value should always be the same.
+*/
#include <stdio.h>
#include <string.h>
/*
- * This is part of a changed public domain getopt implementation that
- * had the following text on top:
- *
- * I got this off net.sources from Henry Spencer.
- * It is a public domain getopt(3) like in System V.
- * I have made the following modifications:
- *
- * A test main program was added, ifdeffed by GETOPT.
- * This main program is a public domain implementation
- * of the getopt(1) program like in System V. The getopt
- * program can be used to standardize shell option handling.
- * e.g. cc -DGETOPT getopt.c -o getopt
- */
+** This is part of a changed public domain getopt implementation that
+** had the following text on top:
+**
+** I got this off net.sources from Henry Spencer.
+** It is a public domain getopt(3) like in System V.
+** I have made the following modifications:
+**
+** A test main program was added, ifdeffed by GETOPT.
+** This main program is a public domain implementation
+** of the getopt(1) program like in System V. The getopt
+** program can be used to standardize shell option handling.
+** e.g. cc -DGETOPT getopt.c -o getopt
+*/
#include <stdio.h>
#include <stdlib.h>
unsigned char* P = malloc (Size);
/* Set the string to a defined value. We use the size, since this will
- * also allow us to retrieve it later.
- */
+ ** also allow us to retrieve it later.
+ */
if (P) {
memset (P, Size, Size);
} else {
\r
\r
/* Number of elements in the progress bar. Use a power of 2, to avoid the\r
- * multiplication (which is about to be tested).\r
- */\r
+** multiplication (which is about to be tested).\r
+*/\r
#define BAR_ELEMENTS 32U\r
\r
#if defined(__CBM__)\r
{"qwerty 095 2", "qwerty %i%i", 2, INT, {0} , INT, {95}},
{"qwerty 0e5 2", "qwerty %i%i", 1, INT, {0} , INT, {0}},
- /* (String pointers are cast as (int),
- * in order to avoid cc65 warnings.) */
+ /* [String pointers are cast as (int),
+ ** in order to avoid cc65 warnings.]
+ */
/* Test that character specifiers can handle end-of-file. */
{"qwerty" , "qwerty %s%s" , EOF, CHAR, {(int)""}, CHAR, {(int)""}},
/*
- * seek test program
- */
+** seek test program
+*/
#include <stdio.h>
#include <string.h>
/* Struct used to test the 'n' conversion specifier. It is machine dependent /
- * not portable.
- */
+** not portable.
+*/
typedef union WriteCount WriteCount;
union WriteCount {
signed char C;
static void OneTest (int Line, const char* RString, int RCount, const char* Format, ...)
/* Test one conversion. Line is the line number (to make the life of the
- * tester easier), RString the expected result and RCount the expected return
- * count. The other parameters are used for formatting.
- */
+** tester easier), RString the expected result and RCount the expected return
+** count. The other parameters are used for formatting.
+*/
{
int Count;
char Buf[128];
static void WriteTest (int Line, const char* Format, WriteCount* W, long Count)
/* Test one write conversion. Line is the line number (to make the life of the
- * tester easier), Format is the format specification. W is a WriteCount
- * variable and Count is the expected result.
- */
+** tester easier), Format is the format specification. W is a WriteCount
+** variable and Count is the expected result.
+*/
{
/* Clear the counter in full length */
W->L = 0x5A5A5A5AL;
OneTest (__LINE__, "EF98", 4, "%+X", -4200U);
/* ' ': If the first character of a signed conversion is not a sign, or if
- * a signed conversion results in no characters, a space is prefixed
- * to the result.
- */
+ ** a signed conversion results in no characters, a space is prefixed
+ ** to the result.
+ */
OneTest (__LINE__, "u", 1, "% c", 'u');
OneTest (__LINE__, " 4200", 5, "% d", 4200);
OneTest (__LINE__, "-4200", 5, "% d", -4200);
OneTest (__LINE__, "EF98 ", 15, "%-15X", -4200U);
/* A negative field width specified via an argument is treated as if the
- * '-' flag and a positive field width were given.
- *
- * Beware: These tests will crash the old printf routine!
- */
+ ** '-' flag and a positive field width were given.
+ **
+ ** Beware: These tests will crash the old printf routine!
+ */
#ifndef NOCRASH
OneTest (__LINE__, "u ", 15, "%*c", -15, 'u');
OneTest (__LINE__, "4200 ", 15, "%*d", -15, 4200);
OneTest (__LINE__, " 000000EF98", 15, "%15.10X", -4200U);
/* For d, i, o, u, x and X conversions, if a precision is specified, the
- * '0' flag is ignored.
- */
+ ** '0' flag is ignored.
+ */
OneTest (__LINE__, " 0000004200", 15, "%015.10d", 4200);
OneTest (__LINE__, " -0000004200", 15, "%015.10d", -4200);
OneTest (__LINE__, " 0000004200", 15, "%015.10i", 4200);
/* strqtok-test.c
- *
- * 2014-04-21, Paul Foerster
- * 2014-05-20, Greg King
- *
- * This program tests that strqtok() correctly will parse strings
- * with quotation marks in them. It should show this list of tokens
- * from the test strings:
- *
- * >This<
- * > is only <
- * >a<
- * >short<
- * >quoting<
- * >test , honoring blanks, commas<
- * >and<
- * >(4)<
- * >empty<
- * ><
- * ><
- * ><
- * ><
- * >strings, EOT <
- *
- * It shouldn't show
- *
- * >Bogus token<
- *
- */
+**
+** 2014-04-21, Paul Foerster
+** 2014-05-20, Greg King
+**
+** This program tests that strqtok() correctly will parse strings
+** with quotation marks in them. It should show this list of tokens
+** from the test strings:
+**
+** >This<
+** > is only <
+** >a<
+** >short<
+** >quoting<
+** >test , honoring blanks, commas<
+** >and<
+** >(4)<
+** >empty<
+** ><
+** ><
+** ><
+** ><
+** >strings, EOT <
+**
+** It shouldn't show
+**
+** >Bogus token<
+**
+*/
#include <string.h>
#include <stdio.h>
void main (void)
{
/* b[] and s[] are declared as automatic, not static, variables
- * because strqtok() will change them.
- * They must be defined together; and, b[] must be defined first
- * (because they're copied onto the top-down stack).
- */
+ ** because strqtok() will change them.
+ ** They must be defined together; and, b[] must be defined first
+ ** (because they're copied onto the top-down stack).
+ */
char b[] = "Bogus token ";
char s[] = " This , \" is only \"a short "
"quoting\"test , honoring blanks"
static void IncStr (char* Buf)
/* Increment a number represented as a string by one. The string MUST not
- * start with a '9', we cannot handle overflow in this case.
- */
+** start with a '9', we cannot handle overflow in this case.
+*/
{
int Len = strlen (Buf);
static void IncStr (char* Buf)
/* Increment a number represented as a string by one. The string MUST not
- * start with a '9', we cannot handle overflow in this case.
- */
+** start with a '9', we cannot handle overflow in this case.
+*/
{
int Len = strlen (Buf);
/*
- * Simple ("tiny") shell to test filename and directory functions.
- * Copyright (c) 2013, Christian Groessler, chris@groessler.org
- */
+** Simple ("tiny") shell to test filename and directory functions.
+** Copyright (c) 2013, Christian Groessler, chris@groessler.org
+*/
#define VERSION_ASC "0.90"
/*
- * Compresses data to the DEFLATE format.
- * The compressed data is ready to use with inflatemem().
- * Compile using e.g.
- * gcc -O2 -o deflater deflater.c -lz
- *
- * Author: Piotr Fusik <fox@scene.pl>
- */
+** Compresses data to the DEFLATE format.
+** The compressed data is ready to use with inflatemem().
+** Compile using e.g.
+** gcc -O2 -o deflater deflater.c -lz
+**
+** Author: Piotr Fusik <fox@scene.pl>
+*/
#include <stdio.h>
#include <stdlib.h>
#include <zlib.h>