diff --git a/build.sh b/build.sh index 69ec447..fc56f25 100755 --- a/build.sh +++ b/build.sh @@ -31,7 +31,7 @@ CMAKEVCS="https://gitlab.kitware.com/cmake/cmake.git" # LLVM Settings LLVMDIR="${SRCDIR}/llvm" -LLVMTAG="llvmorg-22.1.0" +LLVMTAG="llvmorg-22.1.2" LLVMVCS="https://github.com/llvm/llvm-project.git" # Mtools Settings @@ -408,7 +408,7 @@ xtchain_build() echo ">>> Building XTchain tools ..." mkdir -p ${BINDIR}/bin mkdir -p ${BINDIR}/lib/xtchain - for EXEC in bin2c diskimg exetool xtcspecc; do + for EXEC in bin2c diskimg exetool xtadkgen xtcspecc; do if [ ! -e ${BINDIR}/bin/${EXEC} ]; then ${CCOMPILER} ${WRKDIR}/tools/${EXEC}.c -o ${BINDIR}/bin/${EXEC} fi diff --git a/tools/xtadkgen.c b/tools/xtadkgen.c new file mode 100644 index 0000000..8a49632 --- /dev/null +++ b/tools/xtadkgen.c @@ -0,0 +1,166 @@ +/** + * PROJECT: XTchain + * LICENSE: See COPYING.md in the top level directory + * FILE: tools/xtadkgen.c + * DESCRIPTION: XT Assembly Development Kit generator + * DEVELOPERS: Aiken Harris + */ + +#include "xtchain.h" + + +#define MAX_LINE_LEN 1024 +#define MAGIC_MARKER "==> " + +/* Prints usage */ +void PrintUsage(const char* ProgramName) +{ + /* Output usage instructions to stderr */ + fprintf(stderr, "Usage: %s [input2.S ...] -o \n", ProgramName); +} + +/* Processes single .S file */ +void ProcessSourceFile(FILE* InFile, FILE* OutFile) +{ + char LineBuffer[MAX_LINE_LEN]; + char SymbolName[256]; + char ValueString[256]; + char *ValuePointer; + char *Marker; + + /* Iterate through the input stream until the end of the file */ + while(fgets(LineBuffer, sizeof(LineBuffer), InFile)) + { + Marker = strstr(LineBuffer, MAGIC_MARKER); + + /* Search for the predefined translation marker */ + if(Marker) + { + /* Extract the symbol identifier and its associated value */ + if(sscanf(Marker, "==> %255s %255s", SymbolName, ValueString) == 2) + { + /* Initialize pointer for character-level cleanup */ + ValuePointer = ValueString; + + /* Strip architecture-specific immediate prefixes such as '$' (AT&T) or '#' (ARM) */ + while(*ValuePointer == '$' || *ValuePointer == '#') + { + /* Advance pointer to the first alpha-numeric character */ + ValuePointer++; + } + + /* Generate the corresponding C-preprocessor macro definition */ + fprintf(OutFile, "#define %s %s\n", SymbolName, ValuePointer); + } + } + } +} + +/* Main function */ +int main(int Argc, char* Argv[]) +{ + FILE* InFile; + FILE* OutFile = stdout; + const char* OutputName = NULL; + int FirstInputIndex = -1; + int InputCount = 0; + + /* Validate that a minimum set of command-line arguments is present */ + if(Argc < 2) + { + /* Display usage information and terminate on insufficient arguments */ + PrintUsage(Argv[0]); + return 1; + } + + /* Parse command-line arguments */ + for(int Index = 1; Index < Argc; Index++) + { + /* Identify the output file switch */ + if((strcmp(Argv[Index], "-o") == 0 || strcmp(Argv[Index], "-O") == 0) && Index + 1 < Argc) + { + /* Assign the designated output path and skip the next argument */ + OutputName = Argv[++Index]; + } + else + { + /* Track the first occurrence of an input file for the processing loop */ + if(FirstInputIndex == -1) + { + /* Store the argument index for the subsequent file operations */ + FirstInputIndex = Index; + } + + /* Increment the total count of input files */ + InputCount++; + } + } + + /* Ensure at least one input source is available for processing */ + if(InputCount == 0 || (OutputName == NULL && FirstInputIndex == -1)) + { + /* Print usage and exit */ + PrintUsage(Argv[0]); + return 1; + } + + /* Initialize the output stream either to a file or default to stdout */ + if(OutputName) + { + /* Attempt to open the specified output header for write access */ + OutFile = fopen(OutputName, "w"); + if(!OutFile) + { + /* Emit fatal error if the destination file cannot be accessed */ + fprintf(stderr, "%s: Failed to open output file '%s'\n", Argv[0], OutputName); + return 1; + } + } + + /* Write the auto-generation warning and inclusion guard */ + fprintf(OutFile, "// FILE GENERATED AUTOMATICALLY BY '%s'. DO NOT EDIT!\n\n", Argv[0]); + fprintf(OutFile, "#ifndef __XTADK_H_\n"); + fprintf(OutFile, "#define __XTADK_H_\n\n"); + + /* Loop through the arguments again to process each input file */ + for(int Index = 1; Index < Argc; Index++) + { + /* Skip the output switch and its associated parameter */ + if(strcmp(Argv[Index], "-o") == 0 || strcmp(Argv[Index], "-O") == 0) + { + /* Advance the loop counter and continue */ + Index++; + continue; + } + + /* Open the current assembly source file */ + InFile = fopen(Argv[Index], "r"); + if(!InFile) + { + /* Report error for the missing file and proceed to the next input file */ + fprintf(stderr, "%s: Failed to open file '%s', skipping.\n", Argv[0], Argv[Index]); + continue; + } + + /* Add source file data to the generated header */ + fprintf(OutFile, "/* Source: %s */\n", Argv[Index]); + ProcessSourceFile(InFile, OutFile); + fprintf(OutFile, "\n"); + + /* Close the input file handle */ + fclose(InFile); + } + + /* Close the inclusion guard in the output */ + fprintf(OutFile, "#endif /* __XTADK_H_ */\n"); + + /* Check if a file handle was utilized */ + if(OutFile != stdout) + { + /* Commit buffered data and close the output file */ + fclose(OutFile); + } + + /* Return success */ + return 0; +}