diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9b9ed23..dc8fdf1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,10 +4,20 @@ on: [push, pull_request] jobs: build: - runs-on: ubuntu-latest + strategy: + matrix: + os: [ubuntu, windows, macos] + runs-on: "${{ matrix.os }}-latest" steps: - - uses: actions/checkout@v2 + - name: Checkout + uses: actions/checkout@v4.0.0 + with: + submodules: true + + - uses: lukka/get-cmake@latest + - uses: lukka/run-vcpkg@v10 + - name: Build - run: make - - name: Test - run: make check + uses: lukka/run-cmake@v10 + with: + workflowPreset: "${{ matrix.os }}-ci" diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..a0a57f3 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "vcpkg"] + path = vcpkg + url = https://github.com/microsoft/vcpkg.git diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 76f31ae..0000000 --- a/.travis.yml +++ /dev/null @@ -1,37 +0,0 @@ -language: cpp - -before_install: - - sudo add-apt-repository ppa:fkrull/deadsnakes -y - - sudo apt-get update -qq - - pip install --user cpp-coveralls - -install: - - sudo apt-get install -y --allow-unauthenticated -qq zlib1g-dev python3.5 - - sudo apt-get install -y -qq binutils-mingw-w64-i686 - - sudo apt-get install -y -qq gcc-mingw-w64-i686 - - sudo apt-get install -y -qq g++-mingw-w64-i686 - -script: - - make NO_APPSIGN=1 - - make PYTHON=python3.5 check - - make clean - - sudo apt-get install -y -qq libssl-dev libgmp-dev - - make - - echo MinGW Build - - make clean - - make CROSS_COMPILE=i686-w64-mingw32- NO_APPSIGN=1 - - make clean - - make - - make PYTHON=python3.5 check - - make PYTHON=python3.5 coverage - -after_success: - - coveralls --gcov-options '\-lp' - -notifications: - irc: - channels: - - "irc.choopa.net#spasm-ng" - on_success: change - on_failure: always - skip_join: true diff --git a/CIncludeDirectoryCollection.h b/CIncludeDirectoryCollection.h deleted file mode 100644 index 588af93..0000000 --- a/CIncludeDirectoryCollection.h +++ /dev/null @@ -1,72 +0,0 @@ -#pragma once -#ifdef SPASM_NG_ENABLE_COM -struct _CopyVariantFromAdaptBstr { - static HRESULT copy(VARIANT* p1, const CAdapt* p2) { - p1->vt = VT_BSTR; - p1->bstrVal = p2->m_T.Copy(); - return (p1->bstrVal ? S_OK : E_OUTOFMEMORY); - } - - static void init(VARIANT* p) { VariantInit(p); } - static void destroy(VARIANT* p) { VariantClear(p); } -}; - -typedef CComEnumOnSTL > > - CComEnumVariantOnVectorOfAdaptBstr; - -struct _CopyBstrFromAdaptBstr { - static HRESULT copy(BSTR* p1, const CAdapt* p2) { - *p1 = SysAllocString(p2->m_T); - return (p1 ? S_OK : E_OUTOFMEMORY); - } - - static void init(BSTR* p) { } - static void destroy(BSTR* p) { SysFreeString(*p); } -}; - -typedef ICollectionOnSTLImpl, - std::vector< CAdapt >, - BSTR, - _CopyBstrFromAdaptBstr, - CComEnumVariantOnVectorOfAdaptBstr> - IIncludeDirectoryCollectionImpl; - - -class ATL_NO_VTABLE CIncludeDirectoryCollection : - public CComObjectRootEx, - public IIncludeDirectoryCollectionImpl -{ -public: - BEGIN_COM_MAP(CIncludeDirectoryCollection) - COM_INTERFACE_ENTRY(IIncludeDirectoryCollection) - COM_INTERFACE_ENTRY(IDispatch) - END_COM_MAP() - - STDMETHOD(Add)(BSTR bstrDirectory) - { - m_coll.push_back(CAdapt< CComBSTR >(bstrDirectory)); - return S_OK; - } - - STDMETHOD(Remove)(BSTR bstrDirectory) - { - for (auto it = m_coll.begin(); it != m_coll.end(); it++) - { - if (wcscmp((*it).m_T, bstrDirectory) == 0) - { - m_coll.erase(it); - return S_OK; - } - } - return S_FALSE; - } - - STDMETHOD(Clear)() - { - m_coll.clear(); - return S_OK; - } -}; -#endif \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..706b505 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,98 @@ +cmake_minimum_required(VERSION 3.7) +project(spasm-ng + HOMEPAGE_URL https://github.com/alberthdev/spasm-ng +) + +set( + CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake" + CACHE STRING "vcpkg toolchain file" +) + +add_compile_options(-Wall) +if(WIN32) + add_compile_definitions(_CRT_SECURE_NO_WARNINGS) + # Disable warnings on spectre mitigation fence insertion points + add_compile_options(/wd5045) +endif() + +add_executable( + spasm + main.cpp opcodes.cpp pass_one.cpp pass_two.cpp utils.cpp + export.cpp preop.cpp directive.cpp console.cpp expand_buf.cpp + hash.cpp list.cpp parser.cpp storage.cpp errors.cpp bitmap.cpp + modp_ascii.cpp opcodes_ez80.cpp md5.c +) +if(WIN32 OR MINGW OR MSYS) +target_sources(spasm PRIVATE spasm.exe.manifest) +endif() + +set_property(TARGET spasm PROPERTY CXX_STANDARD 17) + +set(ENABLE_APP_SIGNING ON CACHE BOOL "Enable support for signing applications") +if (ENABLE_APP_SIGNING) + find_package(PkgConfig REQUIRED) + pkg_check_modules(gmp REQUIRED IMPORTED_TARGET gmp) + target_link_libraries(spasm PkgConfig::gmp) +else() + add_compile_definitions(NO_APPSIGN) +endif() + +set(ENABLE_DEBUG_PRINT OFF CACHE BOOL "Enable additional debug messages") +if (ENABLE_DEBUG_PRINT) + add_compile_definitions(DEBUG_PRINT) +endif() + +add_compile_definitions( + USE_REUSABLES + USE_BUILTIN_FCREATE +) +if (WIN32) + add_compile_definitions(UNICODE _UNICODE) +endif() + +# Version generation +find_package(Git) +if (Git_FOUND) + execute_process( + COMMAND "${GIT_EXECUTABLE}" describe --always --dirty + WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" + RESULT_VARIABLE res + OUTPUT_VARIABLE GIT_TREE_DESC + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE + ) +else() + set(GIT_TREE_DESC "unknown") +endif() +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/version.h.in" "${CMAKE_CURRENT_BINARY_DIR}/version.h") +target_include_directories(spasm + PRIVATE "${CMAKE_CURRENT_BINARY_DIR}" +) +# Trick from https://cmake.org/pipermail/cmake/2018-October/068389.html +# to force a reconfigure on git change so the version string is always up to date +set_property(GLOBAL APPEND + PROPERTY CMAKE_CONFIGURE_DEPENDS + "${CMAKE_SOURCE_DIR}/.git/index" +) + +# Tests +include(CTest) +add_subdirectory(${PROJECT_SOURCE_DIR}/tests) + +# Install target +include(GNUInstallDirs) +install(TARGETS spasm) +install(FILES README.md LICENSE + DESTINATION ${CMAKE_INSTALL_DOCDIR}/spasm +) +file(GLOB include_files "inc/*.inc") +install(FILES ${include_files} + DESTINATION ${CMAKE_INSTALL_DATADIR}/spasm/inc +) + +# Distribution packaging +set(CPACK_PACKAGE_VERSION "${GIT_TREE_DESC}") +set(CPACK_PACKAGE_DESCRIPTION "SPASM-ng is a z80 assembler with extra features to support development for TI calculators.") +set(CPACK_PACKAGE_CONTACT "alberthdev@users.noreply.github.com") +set(CPACK_DEBIAN_PACKAGE_DEPENDS "zlib1g, libssl1.0.0, libgmp10") +include(CPack) diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 0000000..7ad5925 --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,74 @@ +{ + "version": 6, + "configurePresets": [ + { + "name": "default", + "binaryDir": "${sourceDir}/build/default/" + }, + { + "name": "vcpkg", + "binaryDir": "${sourceDir}/build/vcpkg/", + "toolchainFile": "${sourceDir}/vcpkg/scripts/buildsystems/vcpkg.cmake" + } + ], + "buildPresets": [ + { + "name": "default", + "configurePreset": "default" + }, + { + "name": "vcpkg", + "configurePreset": "vcpkg" + } + ], + "testPresets": [ + { + "name": "default", + "configurePreset": "default", + "configuration": "Debug", + "output": { + "outputOnFailure": true + } + }, + { + "name": "vcpkg", + "configurePreset": "vcpkg", + "inherits": "default" + } + ], + "workflowPresets": [ + { + "name": "ubuntu-ci", + "steps": [ + { "type": "configure", + "name": "default" }, + { "type": "build", + "name": "default" }, + { "type": "test", + "name": "default" } + ] + }, + { + "name": "windows-ci", + "steps": [ + { "type": "configure", + "name": "vcpkg" }, + { "type": "build", + "name": "vcpkg" }, + { "type": "test", + "name": "vcpkg" } + ] + }, + { + "name": "macos-ci", + "steps": [ + { "type": "configure", + "name": "default" }, + { "type": "build", + "name": "default" }, + { "type": "test", + "name": "default" } + ] + } + ] +} diff --git a/CTextStream.cpp b/CTextStream.cpp deleted file mode 100644 index 6ddddaf..0000000 --- a/CTextStream.cpp +++ /dev/null @@ -1,118 +0,0 @@ -#include "stdafx.h" - -#include "CTextStream.h" - -#define MAX_PIPE_SIZE (1024 * 1024) - -#ifdef SPASM_NG_ENABLE_COM -HRESULT CTextStream::FinalConstruct() -{ - HANDLE hRead, hWrite; - BOOL fResult = CreatePipe(&hRead, &hWrite, NULL, MAX_PIPE_SIZE); - if (fResult) - { - //DWORD dwMode = PIPE_READMODE_BYTE | PIPE_NOWAIT; - //fResult = SetNamedPipeHandleState(hRead, &dwMode, NULL, NULL); - fResult = SetStdHandle(STD_OUTPUT_HANDLE, hWrite); - m_hRead = hRead; - - stdout->_file = _open_osfhandle((long) hWrite, _O_TEXT); - - } - return S_OK; -} - - -STDMETHODIMP CTextStream::get_AtEndOfLine(VARIANT_BOOL *bEOL) -{ - return E_NOTIMPL; -} - -STDMETHODIMP CTextStream::get_AtEndOfStream(VARIANT_BOOL *bEOS) -{ - fflush(stdout); - - DWORD dwAvail; - BOOL fResult = PeekNamedPipe(m_hRead, NULL, 0, NULL, &dwAvail, NULL); - *bEOS = (dwAvail == 0) ? VARIANT_TRUE : VARIANT_FALSE; - return S_OK; -} - -STDMETHODIMP CTextStream::Read(LONG cch, LPBSTR lpbstrResult) -{ - fflush(stdout); - DWORD dwRead; - CComHeapPtr szText; - int cbText = min(MAX_PIPE_SIZE, cch) * sizeof(TCHAR); - szText.Allocate(cbText); - BOOL fResult = ReadFile(m_hRead, szText, cbText, &dwRead, NULL); - if (fResult) - { - szText[dwRead / sizeof(TCHAR)] = _T('\0'); - *lpbstrResult = SysAllocString(_bstr_t(szText)); - return S_OK; - } - return E_FAIL; -} - -STDMETHODIMP CTextStream::ReadLine(LPBSTR lpbstrLine) -{ - fflush(stdout); - - _bstr_t result; - - TCHAR ch[2] = {_T('\0')}; - DWORD dwRead; - BOOL fResult; - do - { - fResult = ReadFile(m_hRead, ch, sizeof(TCHAR), &dwRead, NULL); - if (fResult && dwRead == sizeof(TCHAR) && ch[0] != _T('\r') && ch[0] != _T('\n')) - { - result += ch; - } - } - while (ch[0] != _T('\n') && fResult && dwRead > 0); - - *lpbstrLine = SysAllocString(result); - return S_OK; -} - -STDMETHODIMP CTextStream::ReadAll(LPBSTR lpbstrResult) -{ - return Read(LONG_MAX, lpbstrResult); -} - -STDMETHODIMP CTextStream::Write(BSTR bstrText) -{ - return E_NOTIMPL; -} - -STDMETHODIMP CTextStream::WriteLine(BSTR bstrLine) -{ - return E_NOTIMPL; -} - -STDMETHODIMP CTextStream::WriteBlankLines(LONG nLines) -{ - return E_NOTIMPL; -} - -STDMETHODIMP CTextStream::Skip(LONG cch) -{ - BSTR bstrLine = NULL; - HRESULT hr = Read(cch, &bstrLine); - return hr; -} - -STDMETHODIMP CTextStream::SkipLine() -{ - BSTR bstrLine = NULL; - HRESULT hr = ReadLine(&bstrLine); - return hr; -} -STDMETHODIMP CTextStream::Close() -{ - return S_FALSE; -} -#endif \ No newline at end of file diff --git a/CTextStream.h b/CTextStream.h deleted file mode 100644 index ac94224..0000000 --- a/CTextStream.h +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -#ifdef SPASM_NG_ENABLE_COM -class ATL_NO_VTABLE CTextStream : - public CComObjectRootEx, - public IDispatchImpl -{ -public: - BEGIN_COM_MAP(CTextStream) - COM_INTERFACE_ENTRY(ITextStream) - COM_INTERFACE_ENTRY(IDispatch) - END_COM_MAP() - - HRESULT FinalConstruct(); - - STDMETHOD(get_Line)(LONG *plLine) - { - return E_NOTIMPL; - } - STDMETHOD(get_Column)(LONG *plColumn) - { - return E_NOTIMPL; - } - - STDMETHOD(get_AtEndOfLine)(VARIANT_BOOL *bEOL); - STDMETHOD(get_AtEndOfStream)(VARIANT_BOOL *bEOS); - - STDMETHOD(Read)(LONG cch, LPBSTR lpbstrResult); - STDMETHOD(ReadLine)(LPBSTR lpbstrLine); - STDMETHOD(ReadAll)(LPBSTR lpbstrResult); - - STDMETHOD(Write)(BSTR bstrText); - STDMETHOD(WriteLine)(BSTR bstrLine); - STDMETHOD(WriteBlankLines)(LONG nLines); - - STDMETHOD(Skip)(LONG cch); - STDMETHOD(SkipLine)(); - STDMETHOD(Close)(); - -private: - HANDLE m_hRead; -}; -#endif \ No newline at end of file diff --git a/CZ80AssemblerTest.cpp b/CZ80AssemblerTest.cpp deleted file mode 100644 index 0d0a849..0000000 --- a/CZ80AssemblerTest.cpp +++ /dev/null @@ -1,288 +0,0 @@ -#include "stdafx.h" - -#include "spasm.h" -#include "storage.h" -#include "errors.h" -#include "parser.h" -#include "CTextStream.h" -#include "CIncludeDirectoryCollection.h" -#include "hash.h" - -#include "Module.h" - -#ifdef SPASM_NG_ENABLE_COM -class ATL_NO_VTABLE CZ80Assembler : - public CComObjectRootEx, - public CComCoClass, - public IDispatchImpl -{ -public: - DECLARE_REGISTRY_RESOURCEID(IDR_Z80ASSEMBLER) - //DECLARE_CLASSFACTORY_SINGLETON(CZ80Assembler) - - BEGIN_COM_MAP(CZ80Assembler) - COM_INTERFACE_ENTRY(IZ80Assembler) - COM_INTERFACE_ENTRY(IDispatch) - END_COM_MAP() - - HRESULT FinalConstruct() - { - HRESULT hr = m_dict.CreateInstance(__uuidof(Dictionary)); - - CComObject *pObj = NULL; - CComObject::CreateInstance(&pObj); - pObj->AddRef(); - m_pStdOut = pObj; - pObj->Release(); - - CComObject *pDirObj = NULL; - CComObject::CreateInstance(&pDirObj); - pDirObj->AddRef(); - m_pDirectories = pDirObj; - pDirObj->Release(); - - m_fFirstAssembly = TRUE; - m_dwOptions = 0; - - AtlComModuleRevokeClassObjects(&_AtlComModule); - return hr; - } - - void FinalRelease() - { - if (!m_fFirstAssembly) - { - free_storage(); - } - } - - STDMETHOD(get_Defines)(IDictionary **ppDictionary) - { - return m_dict->QueryInterface(ppDictionary); - } - - static void label_enum_callback(void *rawlabel, void *arg) - { - IDictionary *pDict = (IDictionary *) arg; - label_t *label = (label_t *) rawlabel; - - CComVariant name(label->name); - CComVariant value((unsigned int) label->value, VT_UI4); - - pDict->Add(&name, &value); - } - - STDMETHOD(get_Labels)(IDictionary **ppLabels) - { - IDictionaryPtr labels(__uuidof(Dictionary)); - if (label_table != NULL) - { - hash_enum(label_table, label_enum_callback, labels.GetInterfacePtr()); - } - return labels->QueryInterface(ppLabels); - } - - STDMETHOD(get_StdOut)(ITextStream **ppStream) - { - return m_pStdOut->QueryInterface(ppStream); - } - - STDMETHOD(get_InputFile)(LPBSTR lpbstrInputFile) - { - *lpbstrInputFile = SysAllocString(m_bstrInputFile); - return S_OK; - } - - STDMETHOD(put_InputFile)(BSTR bstrInputFile) - { - m_bstrInputFile = bstrInputFile; - return S_OK; - } - - STDMETHODIMP put_OutputFile(BSTR bstrOutputFile) - { - m_bstrOutputFile = bstrOutputFile; - return S_OK; - } - - STDMETHODIMP get_OutputFile(LPBSTR lpbstrOutputFile) - { - *lpbstrOutputFile = SysAllocString(m_bstrOutputFile); - return S_OK; - } - - STDMETHODIMP put_CurrentDirectory(BSTR bstrDirectory) - { - SetCurrentDirectory(_bstr_t(bstrDirectory)); - return S_OK; - } - - STDMETHODIMP get_CurrentDirectory(LPBSTR lpbstrDirectory) - { - TCHAR szBuffer[MAX_PATH]; - GetCurrentDirectory(ARRAYSIZE(szBuffer), szBuffer); - *lpbstrDirectory = SysAllocString(_bstr_t(szBuffer)); - return S_OK; - } - - STDMETHOD(get_Options)(LPDWORD lpdwOptions) - { - *lpdwOptions = m_dwOptions; - return S_OK; - } - - STDMETHOD(put_Options)(DWORD dwOptions) - { - m_dwOptions = dwOptions; - return S_OK; - } - - STDMETHOD(get_CaseSensitive)(VARIANT_BOOL *lpCaseSensitive) - { - *lpCaseSensitive = get_case_sensitive() ? VARIANT_TRUE : VARIANT_FALSE; - return S_OK; - } - - STDMETHOD(put_CaseSensitive)(VARIANT_BOOL caseSensitive) - { - set_case_sensitive(caseSensitive == VARIANT_TRUE ? TRUE : FALSE); - return S_OK; - } - - STDMETHOD(get_IncludeDirectories)(IIncludeDirectoryCollection **ppDirectories) - { - return m_pDirectories->QueryInterface(ppDirectories); - } - - STDMETHOD(Assemble)(VARIANT varInput, IStream **ppOutput) - { - HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, output_buf_size); - output_contents = (unsigned char *) GlobalLock(hGlobal); - - mode = m_dwOptions; - - if (V_VT(&varInput) == VT_BSTR) - { - mode |= MODE_NORMAL | MODE_COMMANDLINE; - mode &= ~MODE_LIST; - - if (m_fFirstAssembly) - { - init_storage(); - } - - CW2CT szInput(V_BSTR(&varInput)); - input_contents = strdup(szInput); - - curr_input_file = strdup("COM Interface"); - } - else - { - mode &= ~MODE_COMMANDLINE; - mode |= MODE_NORMAL; - - curr_input_file = strdup(m_bstrInputFile); - output_filename = strdup(m_bstrOutputFile); - - if (!m_fFirstAssembly) - { - free_storage(); - } - - init_storage(); - } - - // Set up the include directories - CComPtr pEnumUnk; - HRESULT hr = m_pDirectories->get__NewEnum(&pEnumUnk); - - CComQIPtr pEnum = pEnumUnk; - - CComVariant varItem; - ULONG ulFetched; - - while (pEnum->Next(1, &varItem, &ulFetched) == S_OK) - { - include_dirs = list_prepend(include_dirs, (char *) strdup(_bstr_t(V_BSTR(&varItem)))); - } - - AddDefines(); - - int error = run_assembly(); - - list_free(include_dirs, true, NULL); - include_dirs = NULL; - - ClearSPASMErrorSessions(); - - GlobalUnlock(hGlobal); - - CComPtr pStream; - hr = CreateStreamOnHGlobal(hGlobal, TRUE, &pStream); - ULARGE_INTEGER ul; - ul.QuadPart = out_ptr - output_contents; - pStream->SetSize(ul); - - m_fFirstAssembly = FALSE; - if (output_filename != NULL) - { - free(output_filename); - output_filename = NULL; - } - if (curr_input_file) - { - free(curr_input_file); - curr_input_file = NULL; - } - - if (mode & MODE_COMMANDLINE) - { - free(input_contents); - input_contents = NULL; - } - return pStream->QueryInterface(ppOutput); - } - - STDMETHOD(Parse)(BSTR bstrInput, LPBSTR lpbstrOutput) - { - return E_NOTIMPL; - } - -private: - void AddDefines() - { - - CComPtr pEnumUnk; - HRESULT hr = m_dict->_NewEnum(&pEnumUnk); - - CComQIPtr pEnum = pEnumUnk; - - CComVariant varItem; - ULONG ulFetched; - - while (pEnum->Next(1, &varItem, &ulFetched) == S_OK) - { - _bstr_t key = V_BSTR(&varItem); - - _variant_t varValue; - m_dict->get_Item(&varItem, &varValue); - - _bstr_t val = varValue; - - bool redefined; - define_t *define = add_define(strdup(key), &redefined); - set_define(define, val, -1, redefined); - } - } - - BOOL m_fFirstAssembly; - DWORD m_dwOptions; - IDictionaryPtr m_dict; - CComPtr m_pStdOut; - CComPtr m_pDirectories; - _bstr_t m_bstrInputFile; - _bstr_t m_bstrOutputFile; -}; - -OBJECT_ENTRY_AUTO(__uuidof(Z80Assembler), CZ80Assembler) -#endif \ No newline at end of file diff --git a/Makefile b/Makefile deleted file mode 100644 index 2add701..0000000 --- a/Makefile +++ /dev/null @@ -1,101 +0,0 @@ -ISWIN = $(or $(findstring Windows,$(OS)),$(findstring mingw,$(CROSS_COMPILE))) -CC = $(CROSS_COMPILE)g++ -LD = $(CROSS_COMPILE)ld -STRIP = $(CROSS_COMPILE)strip -CXXFLAGS+= -Wall -DUSE_REUSABLES $(if $(ISWIN),,-DUNIXVER) -DUSE_BUILTIN_FCREATE -LDFLAGS+= -lm - -DESTDIR ?= /usr/local - -ifdef FORCE_NO_GIT - FORCE_NO_GIT = 1 -endif -export FORCE_NO_GIT - -VERSION=$$(./version.sh | head -n 1) -VERSION_DPKG=$$(./version.sh dpkg) -GITREV=$$(./version.sh | grep "Git") - -ifdef NO_APPSIGN - CXXFLAGS += -DNO_APPSIGN -else - LDFLAGS += -lgmp -lcrypto -endif - -export CXXFLAGS -export LDFLAGS - -# Suffix Rules -.SUFFIXES: .cpp - -.cpp.o: - $(CC) $(CXXFLAGS) -c $< - -.cpp: - $(CC) $(CXXFLAGS) $< -o $@ - -SRC = main.cpp opcodes.cpp pass_one.cpp pass_two.cpp utils.cpp export.cpp preop.cpp directive.cpp console.cpp \ -expand_buf.cpp hash.cpp list.cpp parser.cpp storage.cpp errors.cpp bitmap.cpp modp_ascii.cpp opcodes_ez80.cpp -OBJ = $(addsuffix .o, $(basename $(SRC))) -OBJ_FILES = $(addsuffix .o, $(basename $(notdir $(SRC)))) -EXE = $(if $(ISWIN),spasm.exe,spasm) - -$(EXE): $(OBJ) Makefile - $(CC) -o $@ $(OBJ_FILES) $(LDFLAGS) - $(STRIP) $@ - -debug: CXXFLAGS+= -g -debug: STRIP= : -debug: $(EXE) - -debugp: CXXFLAGS+= -g -DDEBUG_PRINT -debugp: STRIP= : -debugp: $(EXE) - -prep-special-build: - $(MAKE) clean - touch prep-special-build - -opt: CXXFLAGS+= -O3 -opt: prep-special-build $(OBJ) - touch opt - -static: LDFLAGS+= -static -static: $(EXE) - touch static - -opt-static: opt static - -tar: opt-static - tar czvf spasm-ng_$(VERSION)_binary.tar.gz $(EXE) README.md LICENSE inc/ - -# This is a fake Debian package builder - it uses checkinstall -# to make this work. -debian: opt $(EXE) - echo "SPASM-ng is a z80 assembler with extra features to support development for TI calculators." > description-pak - checkinstall --requires "zlib1g, libssl1.0.0, libgmp10" \ - --pkgname="spasm-ng" --pkgversion="$(VERSION_DPKG)" --pkgrelease="1" \ - --maintainer="alberthdev@users.noreply.github.com" \ - --backup=no --deldoc=yes --deldesc=yes --delspec=yes \ - --install=no --default $(CHECKINSTALL_OPTS) - rm -f description-pak - -install: - cp $(EXE) $(DESTDIR)/bin/$(EXE) - -check: $(EXE) - $(PYTHON) tests/test-runner.py ./$(EXE) - -coverage: CXXFLAGS+=-g -O0 --coverage -coverage: LDFLAGS+=-g -O0 --coverage -coverage: clean check - -clean: - rm -f $(OBJ) $(EXE) description-pak spasm-ng*.deb spasm-ng*.tar.gz - rm -f opt static prep-special-build - rm -f *.gcno *.gcda *.gcov - -version: - @./version.sh set - @echo "The current spasm-ng version is: $(VERSION)" - @test -n "$(GITREV)" && echo "$(GITREV)" || exit 0 diff --git a/Module.h b/Module.h deleted file mode 100644 index 2219b24..0000000 --- a/Module.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#ifdef _WINDOWS -#ifndef _TEST -#include "SPASM_h.h" - -#ifdef SPASM_NG_ENABLE_COM -class CSPASMModule : public ATL::CAtlExeModuleT -{ -public: - DECLARE_LIBID(LIBID_SPASM) -}; - -extern CSPASMModule _AtlModule; -#endif - -#endif -#endif diff --git a/SPASM.idl b/SPASM.idl deleted file mode 100644 index 9be7e97..0000000 --- a/SPASM.idl +++ /dev/null @@ -1,146 +0,0 @@ -import "oaidl.idl"; -import "ocidl.idl"; - -/* -[ - object, - uuid(9E52A44E-9B78-4662-B423-9A70A9D76140), - dual, - nonextensible, - pointer_default(unique) -] -interface IStringCollection : IDispatch -{ - [propget] - HRESULT Count([out, retval] LONG *Count); - - [id(DISPID_VALUE), propget] - HRESULT Item([in] LONG Index, [out, retval] BSTR **Item); - - [id(DISPID_NEWENUM), propget, hidden] - HRESULT _NewEnum([out, retval] IUnknown** ppEnum); - - [helpstring("Add a new string")] - HRESULT Add([in] BSTR Name, [out, retval] BSTR **Value); - - [helpstring("Remove a string")] - HRESULT Remove([in] BSTR Name); - - [helpstring("Clears the collection")] - HRESULT Clear(); -} -*/ - - -[ - object, - uuid(CC851E27-B58F-40DC-AB58-63AFE27BC4D7), - odl, - dual, - oleautomation, - nonextensible, - pointer_default(unique) -] -interface IIncludeDirectoryCollection : IDispatch -{ - [propget] - HRESULT Count([out, retval] LONG *Count); - - [propget, id(DISPID_VALUE)] - HRESULT Item([in] LONG Index, [out, retval] BSTR *Item); - - [propget, restricted, hidden, id(DISPID_NEWENUM)] - HRESULT _NewEnum([out, retval] IUnknown** ppEnum); - - [helpstring("Add a new string")] - HRESULT Add([in] BSTR Name); - - [helpstring("Remove a string")] - HRESULT Remove([in] BSTR Name); - - [helpstring("Clears the collection")] - HRESULT Clear(); -} - -enum ASSEMBLYOPTIONS { - NORMAL = 1, - CODE_COUNTER = 2, - SYMTABLE = 4, - STATS = 8, - LIST = 16, - COMMANDLINE = 32, -} ; - -[ - uuid(16387CF3-1B28-46C0-ABA9-5DEC7A8FA7AA), - version(1.2), - helpstring("SPASM Z80 Assembler 1.2 Type Library"), -] -library SPASM -{ - importlib("stdole2.tlb"); - importlib("scrrun.dll"); - - [ - object, - uuid(4B8E17F3-2326-453D-AF80-E5CC0CA52373), - dual, - nonextensible, - pointer_default(unique) - ] - interface IZ80Assembler : IDispatch - { - [propget, helpstring("Preprocessor definitions")] - HRESULT Defines([out, retval] Scripting.IDictionary **Defines); - - [propget, helpstring("Current labels for the assembly environment")] - HRESULT Labels([out, retval] Scripting.IDictionary **Labels); - - [propget, helpstring("Output text")] - HRESULT StdOut([out, retval] Scripting.ITextStream **OutputStream); - - [propget, helpstring("Input file")] - HRESULT InputFile([out, retval] BSTR *InputFile); - - [propput, helpstring("Input file")] - HRESULT InputFile([in] BSTR InputFile); - - [propget, helpstring("Output file")] - HRESULT OutputFile([out, retval] BSTR *OutputFile); - - [propput, helpstring("Output file")] - HRESULT OutputFile([in] BSTR OutputFile); - - [propget, helpstring("Assembly options")] - HRESULT Options([out, retval] DWORD *Options); - - [propput, helpstring("Assembly options")] - HRESULT Options([in] DWORD Options); - - [propget, helpstring("Case sensitivity")] - HRESULT CaseSensitive([out, retval] VARIANT_BOOL *IsCaseSensitive); - - [propput, helpstring("Case sensitivity")] - HRESULT CaseSensitive([in] VARIANT_BOOL IsCaseSensitive); - - [propget, helpstring("Current directory")] - HRESULT CurrentDirectory([out, retval] BSTR *CurrentDirectory); - - [propput, helpstring("Current directory")] - HRESULT CurrentDirectory([in] BSTR CurrentDirectory); - - [propget, helpstring("Collection of additional include directories")] - HRESULT IncludeDirectories([out, retval] IIncludeDirectoryCollection **IncludeDirectories); - - [helpstring("Assemble a buffer or filename and return the output stream")] - HRESULT Assemble([in, optional] VARIANT Input, [out, retval] IStream **Output); - } - - [ - uuid(BDD26FAE-A388-4860-9D4E-669809BC8EC2) - ] - coclass Z80Assembler - { - [default] interface IZ80Assembler; - }; -}; diff --git a/SPASM.rc b/SPASM.rc deleted file mode 100644 index 25b66cd..0000000 Binary files a/SPASM.rc and /dev/null differ diff --git a/SPASM.rgs b/SPASM.rgs deleted file mode 100644 index 8219d93..0000000 --- a/SPASM.rgs +++ /dev/null @@ -1,3 +0,0 @@ -HKCR -{ -} diff --git a/SPASM.sln b/SPASM.sln deleted file mode 100644 index 3874c56..0000000 --- a/SPASM.sln +++ /dev/null @@ -1,40 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual C++ Express 2010 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{339D2AC9-17A8-4F03-BCB0-6148573892BC}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SPASM", "SPASM.vcxproj", "{106FF797-6997-43F1-88E3-7D6C0D8A6F3F}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {85D2CCCD-B12D-4A80-BB4E-9233E078D9EA}.Debug|Win32.ActiveCfg = Debug|Win32 - {85D2CCCD-B12D-4A80-BB4E-9233E078D9EA}.Debug|x64.ActiveCfg = Debug|x64 - {85D2CCCD-B12D-4A80-BB4E-9233E078D9EA}.Release|Win32.ActiveCfg = Release|Win32 - {85D2CCCD-B12D-4A80-BB4E-9233E078D9EA}.Release|x64.ActiveCfg = Release|x64 - {106FF797-6997-43F1-88E3-7D6C0D8A6F3F}.Debug|Win32.ActiveCfg = Debug|Win32 - {106FF797-6997-43F1-88E3-7D6C0D8A6F3F}.Debug|Win32.Build.0 = Debug|Win32 - {106FF797-6997-43F1-88E3-7D6C0D8A6F3F}.Debug|x64.ActiveCfg = Debug|x64 - {106FF797-6997-43F1-88E3-7D6C0D8A6F3F}.Debug|x64.Build.0 = Debug|x64 - {106FF797-6997-43F1-88E3-7D6C0D8A6F3F}.Release|Win32.ActiveCfg = Release|Win32 - {106FF797-6997-43F1-88E3-7D6C0D8A6F3F}.Release|Win32.Build.0 = Release|Win32 - {106FF797-6997-43F1-88E3-7D6C0D8A6F3F}.Release|x64.ActiveCfg = Release|x64 - {106FF797-6997-43F1-88E3-7D6C0D8A6F3F}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(TeamFoundationVersionControl) = preSolution - SccNumberOfProjects = 3 - SccEnterpriseProvider = {4CA58AB2-18FA-4F8D-95D4-32DDF27D184C} - SccTeamFoundationServer = https://tfs.codeplex.com/tfs/tfs07 - SccLocalPath0 = . - SccProjectUniqueName1 = SPASM.vcxproj - SccLocalPath1 = . - EndGlobalSection -EndGlobal diff --git a/SPASM.vcxproj b/SPASM.vcxproj deleted file mode 100644 index 6aa11fc..0000000 --- a/SPASM.vcxproj +++ /dev/null @@ -1,342 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {106FF797-6997-43F1-88E3-7D6C0D8A6F3F} - SAK - SAK - SAK - SAK - AtlProj - SPASM - - - - Application - true - Static - MultiByte - v100 - - - Application - true - Dynamic - MultiByte - v110 - - - Application - false - Static - MultiByte - true - v100 - - - Application - false - Static - MultiByte - true - v110 - - - - - - - - - - - - - - - - - - - true - true - false - $(ProjectDir)\lib;C:\Program Files %28x86%29\Visual Leak Detector\lib\Win32;$(LibraryPath) - C:\Program Files %28x86%29\Visual Leak Detector\include;$(IncludePath) - - - true - true - false - $(ProjectDir)\lib\x64;C:\Program Files %28x86%29\Visual Leak Detector\lib\Win64;$(LibraryPath) - C:\Program Files %28x86%29\Visual Leak Detector\include;$(IncludePath) - - - true - false - false - $(ProjectDir)\lib;$(LibraryPath) - - - true - false - false - $(ProjectDir)\lib\x64;$(LibraryPath) - - - - Use - Level3 - Disabled - WIN32;_WINDOWS;USE_REUSABLES;USE_BUILTIN_FCREATE;_CRT_SECURE_NO_WARNINGS;STRSAFE_NO_DEPRECATE;_DEBUG;%(PreprocessorDefinitions) - - - true - - - - - Win32 - - - - - 0x0409 - $(IntDir);%(AdditionalIncludeDirectories) - _DEBUG;%(PreprocessorDefinitions) - - - Console - true - comsuppw.lib;mpir.lib;%(AdditionalDependencies) - - - Performing registration - "$(TargetPath)" /RegServer - - - mpir.lib - - - - - Level3 - Disabled - WIN32;_WINDOWS;USE_REUSABLES;USE_BUILTIN_FCREATE;_CRT_SECURE_NO_WARNINGS;STRSAFE_NO_DEPRECATE;_DEBUG;_WIN64;%(PreprocessorDefinitions) - - - true - Use - - - - - X64 - - - 0x0409 - $(IntDir);%(AdditionalIncludeDirectories) - _DEBUG;%(PreprocessorDefinitions) - - - Console - true - comsuppw.lib;mpir.lib;%(AdditionalDependencies) - - - Performing registration - "$(TargetPath)" /RegServer - - - - - Use - Level3 - Full - WIN32;_WINDOWS;USE_REUSABLES;USE_BUILTIN_FCREATE;_CRT_SECURE_NO_WARNINGS;STRSAFE_NO_DEPRECATE;NDEBUG;%(PreprocessorDefinitions) - - - true - AnySuitable - Speed - true - true - MultiThreaded - - - false - Win32 - NDEBUG;%(PreprocessorDefinitions) - true - - - true - - - 0x0409 - $(IntDir);%(AdditionalIncludeDirectories) - NDEBUG;%(PreprocessorDefinitions) - - - Console - true - true - true - mpir.lib;%(AdditionalDependencies) - UseLinkTimeCodeGeneration - true - - - Performing registration - "$(TargetPath)" /RegServer - - - - - Use - Level3 - MaxSpeed - _WIN64;_WINDOWS;USE_REUSABLES;USE_BUILTIN_FCREATE;_CRT_SECURE_NO_WARNINGS;STRSAFE_NO_DEPRECATE;NDEBUG;%(PreprocessorDefinitions) - - - true - AnySuitable - true - Speed - MultiThreaded - true - - - false - NDEBUG;%(PreprocessorDefinitions) - - - X64 - true - - - 0x0409 - $(IntDir);%(AdditionalIncludeDirectories) - NDEBUG;%(PreprocessorDefinitions) - - - Console - true - true - true - mpir.lib;%(AdditionalDependencies) - true - - - Performing registration - "$(TargetPath)" /RegServer - - - - - - - - - - true - - - - - - - - - - - - - - - - false - false - - - NotUsing - false - false - - - - - - - Create - Create - Create - Create - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - X64 - - - - - - \ No newline at end of file diff --git a/SPASM.vcxproj.filters b/SPASM.vcxproj.filters deleted file mode 100644 index 2e093ac..0000000 --- a/SPASM.vcxproj.filters +++ /dev/null @@ -1,206 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - {00f5d352-e0a0-4e66-b18e-6a5438b1485c} - False - - - {e4a84b9a-4629-4f9b-817e-776daf4c2553} - - - {d97024e2-4364-4c9c-89e3-b6270d2abe69} - False - - - - - Source Files - - - Generated Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Generated Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Source Files - - - Header Files - - - - - Resource Files - - - Resource Files - - - Source Files - - - Source Files - - - Test Files - - - Test Files - - - Generated Files - - - - - Resource Files - - - - - IDL Files - - - \ No newline at end of file diff --git a/SPASM.vcxproj.vspscc b/SPASM.vcxproj.vspscc deleted file mode 100644 index 631be8a..0000000 --- a/SPASM.vcxproj.vspscc +++ /dev/null @@ -1,15 +0,0 @@ -"" -{ -"FILE_VERSION" = "9237" -"ENLISTMENT_CHOICE" = "NEVER" -"PROJECT_FILE_RELATIVE_PATH" = "" -"NUMBER_OF_EXCLUDED_FILES" = "5" -"EXCLUDED_FILE0" = "test.lst" -"EXCLUDED_FILE1" = "SPASM_i.c" -"EXCLUDED_FILE2" = "test.z80" -"EXCLUDED_FILE3" = "SPASM_i.h" -"EXCLUDED_FILE4" = "commands.inc" -"ORIGINAL_PROJECT_FILE_PATH" = "" -"NUMBER_OF_NESTED_PROJECTS" = "0" -"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER" -} diff --git a/SPASM.vssscc b/SPASM.vssscc deleted file mode 100644 index 794f014..0000000 --- a/SPASM.vssscc +++ /dev/null @@ -1,10 +0,0 @@ -"" -{ -"FILE_VERSION" = "9237" -"ENLISTMENT_CHOICE" = "NEVER" -"PROJECT_FILE_RELATIVE_PATH" = "" -"NUMBER_OF_EXCLUDED_FILES" = "0" -"ORIGINAL_PROJECT_FILE_PATH" = "" -"NUMBER_OF_NESTED_PROJECTS" = "0" -"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROJECT" -} diff --git a/Test.vbs b/Test.vbs deleted file mode 100644 index 3a11994..0000000 --- a/Test.vbs +++ /dev/null @@ -1,6 +0,0 @@ -Set asm = CreateObject("Wabbit.SPASM") - -asm.Defines.Add "test", 34 - -asm.Assemble " .echo ""hello "",test" -WScript.Echo asm.StdOut.ReadAll diff --git a/Z80Assembler.cpp b/Z80Assembler.cpp deleted file mode 100644 index 6c70e60..0000000 --- a/Z80Assembler.cpp +++ /dev/null @@ -1,209 +0,0 @@ -// Z80Assembler.cpp : Implementation of CZ80Assembler - -#include "stdafx.h" -#include "Z80Assembler.h" -#include "Z80Label.h" - -#include "spasm.h" -#include "utils.h" -#include "storage.h" -#include "list.h" -#include "hash.h" - -extern hash_t *label_table; - -LONG CZ80Assembler::m_lIndex; - -HRESULT CZ80Assembler::FinalConstruct() -{ - curr_input_file = strdup("COM Interface"); - output_filename = strdup("COM Interface"); - - init_storage(); - m_pStmOutput = NULL; - return S_OK; -} - -void CZ80Assembler::FinalRelease() -{ - free_storage(); - - if (curr_input_file) { - free(curr_input_file); - } - curr_input_file = NULL; - if (output_filename) { - free(output_filename); - } - output_filename = NULL; -} - -STDMETHODIMP CZ80Assembler::get_Output(IStream **ppOutput) -{ - if (ppOutput == NULL) - { - return E_INVALIDARG; - } - - if (m_pStmOutput == NULL) - { - return E_NOT_VALID_STATE; - } - return m_pStmOutput->QueryInterface(IID_PPV_ARGS(ppOutput)); -} - -STDMETHODIMP CZ80Assembler::put_InputFile(BSTR bstrInputFile) -{ - m_bstrInputFile = bstrInputFile; - return S_OK; -} - -STDMETHODIMP CZ80Assembler::get_InputFile(LPBSTR lpbstrInputFile) -{ - *lpbstrInputFile = SysAllocString(m_bstrInputFile); - return S_OK; -} - -STDMETHODIMP CZ80Assembler::put_OutputFile(BSTR bstrOutputFile) -{ - m_bstrOutputFile = bstrOutputFile; - return S_OK; -} - -STDMETHODIMP CZ80Assembler::get_OutputFile(LPBSTR lpbstrOutputFile) -{ - *lpbstrOutputFile = SysAllocString(m_bstrOutputFile); - return S_OK; -} - - -STDMETHODIMP CZ80Assembler::ClearDefines() -{ - list_free(default_defines, true, NULL); - default_defines = NULL; - return S_OK; -} - -STDMETHODIMP CZ80Assembler::AddDefine(BSTR bstrName, VARIANT varValue) -{ - if (V_VT(&varValue) == VT_EMPTY || V_VT(&varValue) == VT_ERROR) - { - V_VT(&varValue) = VT_UI4; - V_UI4(&varValue) = 1; - } - - VARIANT varDefine; - VariantInit(&varDefine); - V_VT(&varDefine) = VT_BSTR; - V_BSTR(&varDefine) = SysAllocString(L""); - HRESULT hr = VariantChangeType(&varDefine, &varValue, 0, VT_BSTR); - if (FAILED(hr)) - { - return hr; - } - - CW2A szName(bstrName); - - bool fRedefined = false; - define_t *define = add_define(strdup(szName), &fRedefined); - - if (define != NULL) - { - CW2A szContents(V_BSTR(&varDefine)); - define->contents = strdup(szContents); - return S_OK; - } - else - { - return E_FAIL; - } -} - -STDMETHODIMP CZ80Assembler::ClearIncludeDirectories() -{ - list_free(include_dirs, true, NULL); - include_dirs = NULL; - return S_OK; -} - -STDMETHODIMP CZ80Assembler::AddIncludeDirectory(BSTR bstrDirectory) -{ - CW2CT szInput(bstrDirectory); - include_dirs = list_append(include_dirs, strdup(szInput)); - return S_OK; -} - -STDMETHODIMP CZ80Assembler::Assemble(VARIANT varInput, int *lpInt) -{ - HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, output_buf_size); - output_contents = (unsigned char *) GlobalLock(hGlobal); - - if (V_VT(&varInput) == VT_BSTR) - { - mode = MODE_NORMAL | MODE_COMMANDLINE; - - CW2CT szInput(V_BSTR(&varInput)); - input_contents = strdup(szInput); - } - else - { - mode = MODE_NORMAL; - - if (curr_input_file) { - free(curr_input_file); - } - curr_input_file = strdup(m_bstrInputFile); - if (output_filename) { - free(output_filename); - } - output_filename = strdup(m_bstrOutputFile); - } - - *lpInt = run_assembly(); - - GlobalUnlock(hGlobal); - - if (m_pStmOutput != NULL) - { - m_pStmOutput->Release(); - } - - LPSTREAM pStream = NULL; - HRESULT hr = CreateStreamOnHGlobal(hGlobal, TRUE, &pStream); - ULARGE_INTEGER ul; - ul.QuadPart = out_ptr - output_contents; - pStream->SetSize(ul); - - m_pStmOutput = pStream; - - return S_OK; -} - -void CZ80Assembler::get_label_callback(label_t *label, CComSafeArray *lpsa) -{ - CComObject *pLabelObj = NULL; - CComObject::CreateInstance(&pLabelObj); - pLabelObj->AddRef(); - pLabelObj->Initialize(label); - - IZ80Label *pLabel; - pLabelObj->QueryInterface(&pLabel); - - pLabelObj->Release(); - - lpsa->SetAt(m_lIndex++, pLabel, FALSE); -} - -STDMETHODIMP CZ80Assembler::get_Labels(LPSAFEARRAY *ppsa) -{ - CComSafeArray sa((ULONG) label_table->used); - - m_lIndex = sa.GetLowerBound(0); - hash_enum(label_table, (HASH_ENUM_CALLBACK) get_label_callback, &sa); - - LPSAFEARRAY lpsa; - sa.CopyTo(&lpsa); - - *ppsa = lpsa; - return S_OK; -} diff --git a/Z80Assembler.h b/Z80Assembler.h deleted file mode 100644 index a275f76..0000000 --- a/Z80Assembler.h +++ /dev/null @@ -1,69 +0,0 @@ -// Z80Assembler.h : Declaration of the CZ80Assembler - -#pragma once -#include "resource.h" // main symbols -#include "list.h" -#include "storage.h" - -#include "SPASM_i.h" - -typedef struct -{ - char name[64]; - char value[64]; -} -default_define_pair_t; - -// CZ80Assembler - -class ATL_NO_VTABLE CZ80Assembler : - public CComObjectRootEx, - public CComCoClass, - public IDispatchImpl -{ -public: - DECLARE_REGISTRY_RESOURCEID(IDR_Z80ASSEMBLER) - - BEGIN_COM_MAP(CZ80Assembler) - COM_INTERFACE_ENTRY(IZ80Assembler) - COM_INTERFACE_ENTRY(IDispatch) - END_COM_MAP() - - DECLARE_PROTECT_FINAL_CONSTRUCT() - - HRESULT FinalConstruct(); - void FinalRelease(); - -public: - STDMETHOD(get_Output)(IStream **ppStream); - - STDMETHOD(get_InputFile)(LPBSTR lpbstrInput); - STDMETHOD(put_InputFile)(BSTR bstrInput); - - STDMETHOD(get_OutputFile)(LPBSTR lpbstrOutput); - STDMETHOD(put_OutputFile)(BSTR bstrOutput); - - STDMETHOD(ClearDefines)(); - STDMETHOD(AddDefine)(BSTR bstrName, VARIANT varValue); - - STDMETHOD(ClearIncludeDirectories)(); - STDMETHOD(AddIncludeDirectory)(BSTR bstrDirectory); - - STDMETHOD(Assemble)(VARIANT varInput, int *lpReturn); - - STDMETHOD(get_Labels)(LPSAFEARRAY *lpsa); - - -private: - static LONG m_lIndex; - static void get_label_callback(label_t *label, CComSafeArray *lpsa); - - LPSTREAM m_pStmOutput; - - _bstr_t m_bstrInputFile; - _bstr_t m_bstrOutputFile; - - list_t *default_defines; -}; - -OBJECT_ENTRY_AUTO(__uuidof(Z80Assembler), CZ80Assembler) diff --git a/Z80Assembler.rgs b/Z80Assembler.rgs deleted file mode 100644 index ce49bf3..0000000 --- a/Z80Assembler.rgs +++ /dev/null @@ -1,26 +0,0 @@ -HKCR -{ - ForceRemove Wabbit.SPASM.1 = s 'Z80Assembler Class' - { - CLSID = s '{BDD26FAE-A388-4860-9D4E-669809BC8EC2}' - } - ForceRemove Wabbit.SPASM = s 'Z80Assembler Class' - { - CurVer = s 'Wabbit.SPASM.1' - } - NoRemove CLSID - { - ForceRemove {BDD26FAE-A388-4860-9D4E-669809BC8EC2} = s 'Z80Assembler Class' - { - ProgID = s 'Wabbit.SPASM.1' - VersionIndependentProgID = s 'Wabbit.SPASM' - ForceRemove Programmable - LocalServer32 = s '%MODULE%' - { - val ServerExecutable = s '%MODULE_RAW%' - } - TypeLib = s '{16387CF3-1B28-46C0-ABA9-5DEC7A8FA7AA}' - Version = s '1.2' - } - } -} diff --git a/Z80Label.cpp b/Z80Label.cpp deleted file mode 100644 index e7bf080..0000000 --- a/Z80Label.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "stdafx.h" - -#include "Z80Label.h" - -STDMETHODIMP CZ80Label::get_Name(BSTR *lpbstr) -{ - _bstr_t str(m_label->name); - *lpbstr = SysAllocString(str); - return S_OK; -} - -STDMETHODIMP CZ80Label::get_Value(DWORD *lpdwValue) -{ - *lpdwValue = m_label->value; - return S_OK; -} \ No newline at end of file diff --git a/Z80Label.h b/Z80Label.h deleted file mode 100644 index 3f0dac4..0000000 --- a/Z80Label.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include "SPASM_i.h" -#include "storage.h" - -class ATL_NO_VTABLE CZ80Label : - public CComObjectRootEx, - public IDispatchImpl -{ -public: - - DECLARE_REGISTRY_RESOURCEID(IDR_Z80ASSEMBLER) - - BEGIN_COM_MAP(CZ80Label) - COM_INTERFACE_ENTRY(IZ80Label) - COM_INTERFACE_ENTRY(IDispatch) - END_COM_MAP() - -public: - STDMETHOD(get_Name)(BSTR *lpbstrName); - STDMETHOD(get_Value)(DWORD *lpdwValue); - - void Initialize(const label_t *label) - { - m_label = label; - } -private: - const label_t *m_label; -}; - diff --git a/bitmap.cpp b/bitmap.cpp index 0e2639a..0537250 100644 --- a/bitmap.cpp +++ b/bitmap.cpp @@ -1,4 +1,6 @@ -#include "stdafx.h" +#include +#include +#include #include "spasm.h" #include "errors.h" @@ -7,14 +9,14 @@ #include "pass_one.h" #include "parser.h" -#ifndef WIN32 #include -typedef int32_t LONG; + +typedef uint32_t LONG; typedef uint16_t UINT; typedef uint8_t BYTE; typedef uint16_t WORD; -// Defined in stdafx.h -//typedef uint32_t DWORD; +typedef uint32_t DWORD; + #define LOBYTE(w) ((BYTE)(w)) #define HIBYTE(w) ((BYTE)(((WORD)(w)>>8)&0xFF)) #define BI_RGB 0 @@ -23,36 +25,37 @@ typedef struct tagRECT { LONG top, left, right, bottom; } RECT; +#pragma pack(push, 1) typedef struct tagRGBQUAD { BYTE rgbBlue; BYTE rgbGreen; BYTE rgbRed; BYTE rgbReserved; -} __attribute__((packed)) RGBQUAD,*LPRGBQUAD; +} RGBQUAD,*LPRGBQUAD; typedef struct tagBITMAPFILEHEADER { WORD bfType; - DWORD bfSize; + LONG bfSize; WORD bfReserved1; WORD bfReserved2; - DWORD bfOffBits; -} __attribute__((packed)) BITMAPFILEHEADER,*LPBITMAPFILEHEADER,*PBITMAPFILEHEADER; + LONG bfOffBits; +} BITMAPFILEHEADER,*LPBITMAPFILEHEADER,*PBITMAPFILEHEADER; typedef struct tagBITMAPINFOHEADER{ - DWORD biSize; + LONG biSize; LONG biWidth; LONG biHeight; WORD biPlanes; WORD biBitCount; - DWORD biCompression; - DWORD biSizeImage; + LONG biCompression; + LONG biSizeImage; LONG biXPelsPerMeter; LONG biYPelsPerMeter; - DWORD biClrUsed; - DWORD biClrImportant; -} __attribute__((packed)) BITMAPINFOHEADER,*LPBITMAPINFOHEADER,*PBITMAPINFOHEADER; -#endif + LONG biClrUsed; + LONG biClrImportant; +} BITMAPINFOHEADER,*LPBITMAPINFOHEADER,*PBITMAPINFOHEADER; +#pragma pack(pop) #ifdef __BIG_ENDIAN__ #define _ZL(Z) ((LONG) _DW(Z)) @@ -163,7 +166,7 @@ static void handle_bitmap_internal(FILE *file, const RECT *r, const BITMAPFILEHE // Bytes, padded to the nearest 32-bit const LONG biScanWidth = ((_ZL(bi->biWidth) * _W(bi->biBitCount)) + 31) / 32 * 4; - const DWORD biImageSize = (_DW(bf->bfSize) - _DW(bf->bfOffBits)); + const LONG biImageSize = (_DW(bf->bfSize) - _DW(bf->bfOffBits)); // if (biImageSize % biScanWidth != 0) { // printf("Scan width calculation incorrect! (image size: %ld, scan: %ld)\n", biImageSize, biScanWidth); // return; @@ -178,8 +181,8 @@ static void handle_bitmap_internal(FILE *file, const RECT *r, const BITMAPFILEHE fread ((BYTE *) pBits, biScanWidth * (r->bottom - r->top), 1, file); // Create the mask buffer - const DWORD biOutputRowSize = ((max(r->right - r->left, min_w) + 7) / 8) * 8; - const DWORD biByteSize = (r->bottom - r->top) * biOutputRowSize; + const LONG biOutputRowSize = ((max(r->right - r->left, min_w) + 7) / 8) * 8; + const LONG biByteSize = (r->bottom - r->top) * biOutputRowSize; #define OUTPUT_ACCESS(zr, zc) pOutput[((zr) * biOutputRowSize) + (zc)] //BYTE (*pOutput)[biOutputRowSize] = malloc(biByteSize); @@ -192,7 +195,7 @@ static void handle_bitmap_internal(FILE *file, const RECT *r, const BITMAPFILEHE memset (pMask, 1, biByteSize); RGBQUAD rgbMask = {0, 255, 0, 0}; - DWORD value = parse_f ("__BM_MSK_RGB"); + uint32_t value = parse_f ("__BM_MSK_RGB"); rgbMask.rgbRed = (value >> 16) & 0xFF; rgbMask.rgbGreen = (value >> 8) & 0xFF; diff --git a/console.cpp b/console.cpp index ec780e1..afb19a3 100644 --- a/console.cpp +++ b/console.cpp @@ -1,10 +1,14 @@ -#include "stdafx.h" +#include + +#ifdef WIN32 +#include +#endif #include "console.h" #include "spasm.h" //saved console attributes, to be restored on exit -WORD user_attributes; +uint16_t user_attributes; void restore_console_attributes_at_exit () { if (!use_colors) return; @@ -15,7 +19,7 @@ void restore_console_attributes_at_exit () { #endif } -void restore_console_attributes (WORD orig_attributes) { +void restore_console_attributes (uint16_t orig_attributes) { if (!use_colors) return; #ifdef WIN32 SetConsoleTextAttribute (GetStdHandle (STD_OUTPUT_HANDLE), orig_attributes); @@ -24,7 +28,7 @@ void restore_console_attributes (WORD orig_attributes) { #endif } -WORD save_console_attributes () { +uint16_t save_console_attributes () { #ifdef WIN32 CONSOLE_SCREEN_BUFFER_INFO csbiScreenBufferInfo; GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &csbiScreenBufferInfo); @@ -34,7 +38,7 @@ WORD save_console_attributes () { #endif } -BOOL set_console_attributes (unsigned short attr) { +bool set_console_attributes (uint16_t attr) { if (!use_colors) return true; #ifdef WIN32 return SetConsoleTextAttribute (GetStdHandle (STD_OUTPUT_HANDLE), (WORD)attr); diff --git a/console.h b/console.h index e877298..5e92d6f 100644 --- a/console.h +++ b/console.h @@ -4,6 +4,7 @@ #include "spasm.h" #ifdef WIN32 +#include # define COLOR_RED FOREGROUND_RED | FOREGROUND_INTENSITY # define COLOR_YELLOW FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY # define COLOR_WHITE FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY @@ -17,10 +18,10 @@ # define COLOR_GREEN 32 #endif -WORD save_console_attributes (); +uint16_t save_console_attributes (); void restore_console_attributes_at_exit (); -void restore_console_attributes (WORD orig_attributes); -BOOL set_console_attributes (unsigned short); +void restore_console_attributes (uint16_t orig_attributes); +bool set_console_attributes (uint16_t); #endif diff --git a/directive.cpp b/directive.cpp index 8584e1c..910e2f6 100644 --- a/directive.cpp +++ b/directive.cpp @@ -1,4 +1,7 @@ -#include "stdafx.h" +#include +#include +#include +#include #include "spasm.h" #include "directive.h" @@ -507,15 +510,6 @@ void show_define (define_t *define) { } putchar ('\n'); restore_console_attributes(console_attrib); - -#ifdef WIN32 - if (define->contents != NULL) - { - OutputDebugString(define->contents); - OutputDebugString("\n"); - } -#endif - } @@ -586,7 +580,7 @@ char *parse_emit_string (const char *ptr, ES_TYPE type, void *echo_target) { case ES_FCREATE: { char buffer[256]; - sprintf_s(buffer, "%d", value); + sprintf(buffer, "%d", value); eb_append((expand_buf_t *) echo_target, buffer, -1); break; } @@ -702,7 +696,7 @@ char *parse_emit_string (const char *ptr, ES_TYPE type, void *echo_target) { if (IsSPASMErrorSessionFatal(inner_session)) { EndSPASMErrorSession(inner_session); - AddSPASMErrorSessionAnnotation(session, _T("Error during evaluation of macro '%s'"), define->name); + AddSPASMErrorSessionAnnotation(session, "Error during evaluation of macro '%s'", define->name); ReplaySPASMErrorSession(session); } diff --git a/dll.cpp b/dll.cpp deleted file mode 100644 index 4490e50..0000000 --- a/dll.cpp +++ /dev/null @@ -1,211 +0,0 @@ -#include "stdafx.h" - -#ifdef _WINDLL -#include "spasm.h" -#include "utils.h" -#include "storage.h" -#include "list.h" - -list_t *default_defines; -typedef struct { - char name[64]; - char value[64]; -} default_define_pair_t; - -#ifdef LOG -#include -FILE *logfile; -#endif -extern "C" -{ - __declspec (dllexport) BOOL __stdcall DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) - { - switch (ul_reason_for_call) - { - case DLL_PROCESS_ATTACH: - #ifdef LOG - logfile = fopen("logfile.txt", "a"); - fprintf(logfile, "Log opened\n"); - fflush(logfile); - #endif - /* - AllocConsole(); - SetConsoleTitle("SPASM"); - // The following is a really disgusting hack to make stdin and stdout attach - // to the newly created console using the MSVC++ libraries. I hope other - // operating systems don't need this kind of kludge.. :) - stdout->_file = _open_osfhandle((long)GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT); - stdin->_file = _open_osfhandle((long)GetStdHandle(STD_INPUT_HANDLE), _O_TEXT); - */ - output_contents = (unsigned char *) malloc (output_buf_size); - setvbuf(stdout, output_text, _IOFBF, 65536); - break; - case DLL_THREAD_ATTACH: - break; - case DLL_THREAD_DETACH: - break; - case DLL_PROCESS_DETACH: - #ifdef LOG - fprintf(logfile, "Log closed\n"); - fflush(logfile); - fclose(logfile); - #endif - //stdout->_file = -1; - //stdin->_file = -1; - //FreeConsole(); - free(output_contents); -#ifdef _DEBUG - _CrtDumpMemoryLeaks(); -#endif - break; - } - - - return TRUE; - } - - __declspec (dllexport) int __stdcall - SetInputFile(const char *lpFilename) { - curr_input_file = strdup(lpFilename); - #ifdef LOG - fprintf(logfile, "SetInputFile: %s\n", curr_input_file); - fflush(logfile); - #endif - return EXIT_NORMAL; - } - - __declspec (dllexport) int __stdcall - SetOutputFile(const char *lpFilename) { - output_filename = strdup(lpFilename); - #ifdef LOG - fprintf(logfile, "SetInputFile: %s\n", output_filename); - fflush(logfile); - #endif - return EXIT_NORMAL; - } - - __declspec (dllexport) int __stdcall - ClearDefines() { - list_free(default_defines, true, NULL); - default_defines = NULL; - #ifdef LOG - fprintf(logfile, "ClearDefines"); - fflush(logfile); - #endif - return 0; - } - - __declspec (dllexport) int __stdcall - AddDefine(const char *lpName, const char *lpValue) { - default_define_pair_t *ddp = (default_define_pair_t*)malloc (sizeof(*ddp)); - strncpy(ddp->name, lpName, sizeof(ddp->name)); - if (lpValue == NULL) { - strcpy(ddp->value, "1"); - } else { - strncpy(ddp->value, lpValue, sizeof(ddp->value)); - } - default_defines = list_append(default_defines, ddp); - #ifdef LOG - fprintf(logfile, "AddDefine: %s %d\n", ddp->name, ddp->value); - fflush(logfile); - #endif - return 0; - } - - __declspec (dllexport) int __stdcall - ClearIncludes() { - list_free(include_dirs, true, NULL); - include_dirs = NULL; - #ifdef LOG - fprintf(logfile, "ClearIncludes\n"); - fflush(logfile); - #endif - return 0; - } - - __declspec (dllexport) int __stdcall - AddInclude(const char *lpDirectory) { - include_dirs = list_append(include_dirs, strdup (lpDirectory)); - #ifdef LOG - fprintf(logfile, "AddInclude: %s\n", lpDirectory); - fflush(logfile); - #endif - return 0; - } - - __declspec (dllexport) int __stdcall - RunAssembly() { - list_t *list = default_defines; - int result; - - mode = MODE_NORMAL; - init_storage(); - - while (list) { - char *name = ((default_define_pair_t *) list->data)->name; - char *value = ((default_define_pair_t *) list->data)->value; - add_define (strdup (name), NULL)->contents = strdup (value); - list = list->next; - } - - printf("Input file: %s\n", curr_input_file); - printf("Output file: %s\n", output_filename); - - list = include_dirs; - while (list) { - printf("Include dir: %s\n", (char *) list->data); - list = list->next; - } - - if (curr_input_file == NULL || output_filename == NULL) { - #ifdef LOG - fprintf(logfile, "Unable to assemble file\n"); - fflush(logfile); - #endif - return EXIT_FATAL_ERROR; - } - - result = run_assembly(); - fflush(stdout); - #ifdef LOG - fprintf(logfile, "File assembled with return value: %d\n", result); - fflush(logfile); - #endif - free_storage(); - return result; - } - - __declspec (dllexport) - char* __stdcall GetStdOut() - { - return output_text; - } - - __declspec (dllexport) - int __stdcall RunAssemblyWithArguments(char *szCommand, BYTE *lpResult, int cbResult) { - - output_filename = NULL; - mode = MODE_NORMAL | MODE_COMMANDLINE; - input_contents = (char *) malloc (strlen(szCommand) + 1 + 2); - - strcpy(input_contents, " "); - strcat(input_contents, szCommand); - strcat(input_contents, "\n"); - - curr_input_file = NULL; - int result = run_assembly(); - - if (lpResult != NULL) { - memcpy(lpResult, output_contents, min(out_ptr - output_contents, cbResult)); - } - return min(out_ptr - output_contents, cbResult); - } - - __declspec (dllexport) int __stdcall - ShowMessage() { - MessageBox(NULL, "Hello", "Hello", MB_OK); - return 0; - } -} - -#endif \ No newline at end of file diff --git a/dlldata.c b/dlldata.c deleted file mode 100644 index bf8c051..0000000 --- a/dlldata.c +++ /dev/null @@ -1,38 +0,0 @@ -/********************************************************* - DllData file -- generated by MIDL compiler - - DO NOT ALTER THIS FILE - - This file is regenerated by MIDL on every IDL file compile. - - To completely reconstruct this file, delete it and rerun MIDL - on all the IDL files in this DLL, specifying this file for the - /dlldata command line option - -*********************************************************/ - -#define PROXY_DELEGATION - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -EXTERN_PROXY_FILE( SPASM ) - - -PROXYFILE_LIST_START -/* Start of list */ - REFERENCE_PROXY_FILE( SPASM ), -/* End of list */ -PROXYFILE_LIST_END - - -DLLDATA_ROUTINES( aProxyFileList, GET_DLL_CLSID ) - -#ifdef __cplusplus -} /*extern "C" */ -#endif - -/* end of generated dlldata file */ diff --git a/errors.cpp b/errors.cpp index a67300a..413e57b 100644 --- a/errors.cpp +++ b/errors.cpp @@ -1,4 +1,8 @@ -#include "stdafx.h" +#include +#include +#include +#include +#include #define _ERRORS_CPP #include "errors.h" @@ -9,15 +13,15 @@ typedef struct tagERRORINSTANCE { - LPSTR lpszFileName; + char *lpszFileName; int line_num; //-1 for no line - DWORD dwErrorCode; + uint32_t dwErrorCode; int nSession; bool fSuppressErrors; bool fIsWarning; int nPrintSession; - LPTSTR lpszErrorText; - LPTSTR lpszAnnotation; + char *lpszErrorText; + char *lpszAnnotation; } ERRORINSTANCE, *LPERRORINSTANCE; typedef struct _errorlist { @@ -38,7 +42,7 @@ static void PrintSPASMError(const LPERRORINSTANCE lpError) assert(lpError != NULL); if ((lpError->dwErrorCode != SPASM_ERR_SUCCESS) || (lpError->lpszErrorText != NULL)) { - WORD orig_attributes = save_console_attributes(); + uint16_t orig_attributes = save_console_attributes(); set_console_attributes(lpError->fIsWarning ? COLOR_YELLOW : COLOR_RED); if (lpError->lpszAnnotation != NULL) { @@ -46,10 +50,6 @@ static void PrintSPASMError(const LPERRORINSTANCE lpError) } printf("%s\n", lpError->lpszErrorText); -#ifdef WINVER - OutputDebugString(lpError->lpszErrorText); - OutputDebugString(_T("\n")); -#endif restore_console_attributes(orig_attributes); } } @@ -107,7 +107,7 @@ int GetSPASMErrorSessionErrorCount(int nSession) return nCount; } -bool IsSPASMErrorFatal(DWORD dwError) +bool IsSPASMErrorFatal(int32_t dwError) { return !(dwError == SPASM_ERR_LOCAL_LABEL_FORWARD_REF || dwError == SPASM_ERR_LABEL_NOT_FOUND || @@ -122,7 +122,7 @@ bool IsSPASMErrorSessionFatal(int nSession) while ((pList != NULL) && ((LPERRORINSTANCE) pList->data)->nSession == nSession) { LPERRORINSTANCE lpError = (LPERRORINSTANCE) pList->data; - DWORD dwError = lpError->dwErrorCode; + uint32_t dwError = lpError->dwErrorCode; if (IsSPASMErrorFatal(dwError)) { fIsFatal = true; @@ -178,7 +178,7 @@ void ReplayFatalSPASMErrorSession(int nSession) ReplaySPASMErrorSession(nSession, true); } -bool IsErrorInSPASMErrorSession(int nSession, DWORD dwErrorCode) +bool IsErrorInSPASMErrorSession(int nSession, uint32_t dwErrorCode) { list_t *pList = (list_t *) g_ErrorList; while ((pList != NULL) && ((LPERRORINSTANCE) pList->data)->nSession == nSession) @@ -193,16 +193,16 @@ bool IsErrorInSPASMErrorSession(int nSession, DWORD dwErrorCode) return false; } -void AddSPASMErrorSessionAnnotation(int nSession, LPCTSTR lpszFormat, ...) +void AddSPASMErrorSessionAnnotation(int nSession, const char *lpszFormat, ...) { va_list valist; va_start(valist, lpszFormat); - TCHAR szBuffer[256]; - TCHAR szDescription[128] = _T("An error occurred"); + char szBuffer[256] = {}; + char szDescription[128] = "An error occurred"; - StringCchVPrintf(szDescription, ARRAYSIZE(szDescription), lpszFormat, valist); - StringCchPrintf(szBuffer, ARRAYSIZE(szBuffer), _T("%s:%d: %s"), + vsnprintf(szDescription, std::size(szDescription) - 1, lpszFormat, valist); + snprintf(szBuffer, std::size(szBuffer) - 1, "%s:%d: %s", curr_input_file, line_num, szDescription); va_end(valist); @@ -217,7 +217,7 @@ void AddSPASMErrorSessionAnnotation(int nSession, LPCTSTR lpszFormat, ...) { free(lpErr->lpszAnnotation); } - lpErr->lpszAnnotation = _tcsdup(szBuffer); + lpErr->lpszAnnotation = strdup(szBuffer); } pList = pList->next; } @@ -295,7 +295,7 @@ void FreeSPASMErrorSessions(void) } #ifdef _TEST -DWORD GetLastSPASMError() +uint32_t GetLastSPASMError() { list_t *pList = (list_t *) g_ErrorList; while (pList != NULL) @@ -327,7 +327,7 @@ int GetLastSPASMErrorLine() #endif -static void SetLastSPASMProblem(DWORD dwErrorCode, bool fIsWarning, va_list valist) +static void SetLastSPASMProblem(int32_t dwErrorCode, bool fIsWarning, va_list valist) { if (dwErrorCode == SPASM_ERR_SUCCESS) { @@ -337,47 +337,47 @@ static void SetLastSPASMProblem(DWORD dwErrorCode, bool fIsWarning, va_list vali LPERRORINSTANCE lpErr = AllocErrorInstance(); lpErr->dwErrorCode = dwErrorCode; lpErr->line_num = line_num; - lpErr->lpszFileName = _strdup(curr_input_file); + lpErr->lpszFileName = strdup(curr_input_file); //lpErr->fSuppressErrors = suppress_errors; lpErr->fIsWarning = fIsWarning; - TCHAR szBuffer[256]; - TCHAR szDescription[128] = _T("An error occurred"); + char szBuffer[256]; + char szDescription[128] = "An error occurred"; - for (int i = 0; i < ARRAYSIZE(g_ErrorCodes); i++) + for (int i = 0; i < std::size(g_ErrorCodes); i++) { if (g_ErrorCodes[i].dwCode == lpErr->dwErrorCode) { - StringCchVPrintf(szDescription, ARRAYSIZE(szDescription), + vsnprintf(szDescription, std::size(szDescription) - 1, g_ErrorCodes[i].lpszDescription, valist); break; } } - LPCTSTR lpszProblemType = (fIsWarning) ? _T("warning") : _T("error"); - LPCTSTR lpszProblemCode = (fIsWarning) ? _T("SW") : _T("SE"); + const char *lpszProblemType = (fIsWarning) ? "warning" : "error"; + const char *lpszProblemCode = (fIsWarning) ? "SW" : "SE"; if (lpErr->line_num != -1) { - StringCchPrintf(szBuffer, ARRAYSIZE(szBuffer), _T("%s:%d: %s %s%03X: %s"), + snprintf(szBuffer, std::size(szBuffer) - 1, "%s:%d: %s %s%03X: %s", lpErr->lpszFileName, lpErr->line_num, lpszProblemType, lpszProblemCode, lpErr->dwErrorCode, szDescription); } else { - StringCchPrintf(szBuffer, ARRAYSIZE(szBuffer), _T("%s: %s %s%03X: %s"), + snprintf(szBuffer, std::size(szBuffer) - 1, "%s: %s %s%03X: %s", lpErr->lpszFileName, lpszProblemType, lpszProblemCode, lpErr->dwErrorCode, szDescription); } - lpErr->lpszErrorText = _strdup(szBuffer); + lpErr->lpszErrorText = strdup(szBuffer); - g_ErrorList = (errorlist_t *) list_prepend((list_t *) g_ErrorList, (LPVOID) lpErr); + g_ErrorList = (errorlist_t *) list_prepend((list_t *) g_ErrorList, lpErr); //if (suppress_errors == false) //{ //PrintSPASMError(lpErr); //} } -void SetLastSPASMWarning(DWORD dwErrorCode, ...) +void SetLastSPASMWarning(int32_t dwErrorCode, ...) { va_list valist; va_start(valist, dwErrorCode); @@ -387,7 +387,7 @@ void SetLastSPASMWarning(DWORD dwErrorCode, ...) va_end(valist); } -void SetLastSPASMError(DWORD dwErrorCode, ...) +void SetLastSPASMError(int32_t dwErrorCode, ...) { va_list valist; va_start(valist, dwErrorCode); diff --git a/errors.h b/errors.h index 6f8843d..84fba8b 100644 --- a/errors.h +++ b/errors.h @@ -1,9 +1,11 @@ #pragma once +#include + typedef struct tagSPASMERROR { - DWORD dwCode; - LPCTSTR lpszDescription; + uint32_t dwCode; + const char *lpszDescription; } SPASMERROR, *LPSPASMERROR; @@ -80,76 +82,76 @@ SPASMERROR g_ErrorCodes[] #ifdef _ERRORS_CPP = { - {SPASM_ERR_FILE_NOT_FOUND, _T("Could not find the file '%s'")}, - {SPASM_ERR_NO_ACCESS, _T("Could not access the file '%s'")}, - - {SPASM_ERR_LOCAL_LABEL_SYNTAX, _T("Error in local label's syntax (had leading +/- but no _)")}, - {SPASM_ERR_LOCAL_LABEL_FORWARD_REF, _T("Reference to local label which doesn't exist")}, - {SPASM_ERR_ARG_USED_WITHOUT_VALUE, _T("Argument '%s' used without value")}, - {SPASM_ERR_OPERATOR_EXPECTED, _T("Expecting an operator, found '%c' instead")}, - {SPASM_ERR_VALUE_EXPECTED, _T("Expecting a value, expression ended early")}, - {SPASM_ERR_LABEL_NOT_FOUND, _T("Could not find label or macro '%s'")}, - {SPASM_ERR_BAD_VALUE_PREFIX, _T("Unrecognized value prefix '%c'")}, - {SPASM_ERR_INVALID_ADDRESS, _T("The value '%s' is not a valid Z80 address")}, - {SPASM_ERR_SIZE_MUST_BE_POSITIVE, _T("The value '%s' is a size and must be positive")}, - {SPASM_ERR_FILENAME_EXPECTED, _T("Expecting a filename, none was provided")}, - {SPASM_ERR_INVALID_OPERANDS, _T("The opcode %s was given invalid operands")}, - {SPASM_ERR_INVALID_RST_OPERANDS, _T("The opcode rst was given invalid operands")}, - {SPASM_ERR_UNKNOWN_PREOP, _T("Unknown preprocessor command '#%s'")}, - {SPASM_ERR_UNKNOWN_DIRECTIVE, _T("Unknown assembler directive '.%s'")}, - {SPASM_ERR_UNKNOWN_OPCODE, _T("Unknown opcode '%s'")}, - {SPASM_ERR_EQUATE_MISSING_LABEL, _T("Equate is missing corresponding label")}, - {SPASM_ERR_EXCEEDED_RECURSION_LIMIT,_T("Recursion depth limit exceeded")}, - {SPASM_ERR_EXPRESSION_EXPECTED, _T("Expecting an expression, statement ended early")}, - {SPASM_ERR_SYNTAX, _T("Unknown syntax")}, - {SPASM_ERR_JUMP_EXCEEDED, _T("Relative jump distance exceeded (distance %d)")}, - {SPASM_ERR_INDEX_OFFSET_EXCEEDED, _T("Index register offset exceeded (offset %d)")}, - {SPASM_ERR_NAME_EXPECTED, _T("Expecting a name, expression ended early")}, - {SPASM_ERR_NO_PREVIOUS_DEFINE, _T("No previous define to continue")}, - {SPASM_ERR_ELIF_WITHOUT_IF, _T("Use of #ELIF outside of an #IF expression")}, - {SPASM_ERR_INVALID_OPTION, _T("The option %s does not exist")}, - {SPASM_ERR_INVALID_ADDINSTR, _T("Required information for .ADDINSTR is missing or invalid")}, - {SPASM_ERR_INVALID_RST_OPERANDS, _T("Invalid operands for the RST command")}, - {SPASM_ERR_DEFINE_HAS_NO_VALUE, _T("The define '%s' has been used, but doesn't have a value")}, - {SPASM_ERR_RECURSION_DEPTH, _T("Expression is too deep (only %d levels allowed)")}, - {SPASM_ERR_LABEL_CONFLICT, _T("Conflicting definition of '%s' at %s:%d")}, - {SPASM_ERR_INVALID_INDEX_OFFSET, _T("Index offset is expected to begin with '+' or '-' or be missing")}, - - {SPASM_ERR_INVALID_DECIMAL_DIGIT, _T("Invalid digit '%c' in the decimal number '%s'")}, - {SPASM_ERR_INVALID_HEX_DIGIT, _T("Invalid digit '%c' in the hexadecimal number '%s'")}, - {SPASM_ERR_INVALID_BINARY_DIGIT, _T("Invalid digit '%c' in the binary number '%s'")}, - {SPASM_ERR_DIVIDE_BY_ZERO, _T("Division by zero in evaluation of expression '%s'")}, - {SPASM_ERR_INTEGER_OVERFLOW, _T("Magnitude of literal value '%s' is too large")}, - {SPASM_ERR_DIVIDE_IMIN1, _T("Division of INT_MIN by -1 in expression '%s' is unrepresentable")}, - - {SPASM_ERR_FCREATE_NOFILE, _T("No buffer was selected for the fcreate call")}, - {SPASM_ERR_UNMATCHED_IF, _T("Unbalanced #IF/#ENDIF")}, - {SPASM_ERR_STRAY_PREOP, _T("Stray #%s")}, - - {SPASM_ERR_SIGNER_MISSING_LENGTH, _T("Length field missing")}, - {SPASM_ERR_SIGNER_PRGM_TYPE, _T("Program type field missing or incorrect")}, - {SPASM_ERR_SIGNER_MISSING_PAGES, _T("Page count field missing")}, - {SPASM_ERR_SIGNER_MISSING_NAME, _T("Name field missing")}, - {SPASM_ERR_SIGNER_ROOM_FOR_SIG, _T("Not enough room for signature on last page")}, - - {SPASM_ERR_CUSTOM, _T("%s")}, - - {SPASM_WARN_TRUNCATING_8, _T("Value too large for 8-bits, truncation required")}, - {SPASM_WARN_TRUNCATING_16, _T("Value too large for 16-bits, truncation required")}, - {SPASM_WARN_SMALL_LAST_PAGE, _T("Only %d bytes are used on the last APP page")}, - {SPASM_WARN_UNKNOWN_EXTENSION, _T("Unrecognized file extension, assuming binary")}, - {SPASM_WARN_MACRO_TOO_MANY_ARGS, _T("Macro '%s' was given too many arguments, ignoring extras")}, - {SPASM_WARN_LABEL_OVER_DEFINE, _T("Label %s was used instead define %s")}, - - {SPASM_WARN_SIGNER_FILE_SIZE_24KB, _T("The output file is larger than 24KB")}, - {SPASM_WARN_SIGNER_FILE_SIZE_64KB, _T("The output file is larger than 64KB")}, + {SPASM_ERR_FILE_NOT_FOUND, "Could not find the file '%s'"}, + {SPASM_ERR_NO_ACCESS, "Could not access the file '%s'"}, + + {SPASM_ERR_LOCAL_LABEL_SYNTAX, "Error in local label's syntax (had leading +/- but no _)"}, + {SPASM_ERR_LOCAL_LABEL_FORWARD_REF, "Reference to local label which doesn't exist"}, + {SPASM_ERR_ARG_USED_WITHOUT_VALUE, "Argument '%s' used without value"}, + {SPASM_ERR_OPERATOR_EXPECTED, "Expecting an operator, found '%c' instead"}, + {SPASM_ERR_VALUE_EXPECTED, "Expecting a value, expression ended early"}, + {SPASM_ERR_LABEL_NOT_FOUND, "Could not find label or macro '%s'"}, + {SPASM_ERR_BAD_VALUE_PREFIX, "Unrecognized value prefix '%c'"}, + {SPASM_ERR_INVALID_ADDRESS, "The value '%s' is not a valid Z80 address"}, + {SPASM_ERR_SIZE_MUST_BE_POSITIVE, "The value '%s' is a size and must be positive"}, + {SPASM_ERR_FILENAME_EXPECTED, "Expecting a filename, none was provided"}, + {SPASM_ERR_INVALID_OPERANDS, "The opcode %s was given invalid operands"}, + {SPASM_ERR_INVALID_RST_OPERANDS, "The opcode rst was given invalid operands"}, + {SPASM_ERR_UNKNOWN_PREOP, "Unknown preprocessor command '#%s'"}, + {SPASM_ERR_UNKNOWN_DIRECTIVE, "Unknown assembler directive '.%s'"}, + {SPASM_ERR_UNKNOWN_OPCODE, "Unknown opcode '%s'"}, + {SPASM_ERR_EQUATE_MISSING_LABEL, "Equate is missing corresponding label"}, + {SPASM_ERR_EXCEEDED_RECURSION_LIMIT,"Recursion depth limit exceeded"}, + {SPASM_ERR_EXPRESSION_EXPECTED, "Expecting an expression, statement ended early"}, + {SPASM_ERR_SYNTAX, "Unknown syntax"}, + {SPASM_ERR_JUMP_EXCEEDED, "Relative jump distance exceeded (distance %d)"}, + {SPASM_ERR_INDEX_OFFSET_EXCEEDED, "Index register offset exceeded (offset %d)"}, + {SPASM_ERR_NAME_EXPECTED, "Expecting a name, expression ended early"}, + {SPASM_ERR_NO_PREVIOUS_DEFINE, "No previous define to continue"}, + {SPASM_ERR_ELIF_WITHOUT_IF, "Use of #ELIF outside of an #IF expression"}, + {SPASM_ERR_INVALID_OPTION, "The option %s does not exist"}, + {SPASM_ERR_INVALID_ADDINSTR, "Required information for .ADDINSTR is missing or invalid"}, + {SPASM_ERR_INVALID_RST_OPERANDS, "Invalid operands for the RST command"}, + {SPASM_ERR_DEFINE_HAS_NO_VALUE, "The define '%s' has been used, but doesn't have a value"}, + {SPASM_ERR_RECURSION_DEPTH, "Expression is too deep (only %d levels allowed)"}, + {SPASM_ERR_LABEL_CONFLICT, "Conflicting definition of '%s' at %s:%d"}, + {SPASM_ERR_INVALID_INDEX_OFFSET, "Index offset is expected to begin with '+' or '-' or be missing"}, + + {SPASM_ERR_INVALID_DECIMAL_DIGIT, "Invalid digit '%c' in the decimal number '%s'"}, + {SPASM_ERR_INVALID_HEX_DIGIT, "Invalid digit '%c' in the hexadecimal number '%s'"}, + {SPASM_ERR_INVALID_BINARY_DIGIT, "Invalid digit '%c' in the binary number '%s'"}, + {SPASM_ERR_DIVIDE_BY_ZERO, "Division by zero in evaluation of expression '%s'"}, + {SPASM_ERR_INTEGER_OVERFLOW, "Magnitude of literal value '%s' is too large"}, + {SPASM_ERR_DIVIDE_IMIN1, "Division of INT_MIN by -1 in expression '%s' is unrepresentable"}, + + {SPASM_ERR_FCREATE_NOFILE, "No buffer was selected for the fcreate call"}, + {SPASM_ERR_UNMATCHED_IF, "Unbalanced #IF/#ENDIF"}, + {SPASM_ERR_STRAY_PREOP, "Stray #%s"}, + + {SPASM_ERR_SIGNER_MISSING_LENGTH, "Length field missing"}, + {SPASM_ERR_SIGNER_PRGM_TYPE, "Program type field missing or incorrect"}, + {SPASM_ERR_SIGNER_MISSING_PAGES, "Page count field missing"}, + {SPASM_ERR_SIGNER_MISSING_NAME, "Name field missing"}, + {SPASM_ERR_SIGNER_ROOM_FOR_SIG, "Not enough room for signature on last page"}, + + {SPASM_ERR_CUSTOM, "%s"}, + + {SPASM_WARN_TRUNCATING_8, "Value too large for 8-bits, truncation required"}, + {SPASM_WARN_TRUNCATING_16, "Value too large for 16-bits, truncation required"}, + {SPASM_WARN_SMALL_LAST_PAGE, "Only %d bytes are used on the last APP page"}, + {SPASM_WARN_UNKNOWN_EXTENSION, "Unrecognized file extension, assuming binary"}, + {SPASM_WARN_MACRO_TOO_MANY_ARGS, "Macro '%s' was given too many arguments, ignoring extras"}, + {SPASM_WARN_LABEL_OVER_DEFINE, "Label %s was used instead define %s"}, + + {SPASM_WARN_SIGNER_FILE_SIZE_24KB, "The output file is larger than 24KB"}, + {SPASM_WARN_SIGNER_FILE_SIZE_64KB, "The output file is larger than 64KB"}, } #endif ; -void SetLastSPASMError(DWORD dwErrorCode, ...); -void SetLastSPASMWarning(DWORD dwErrorCode, ...); -//DWORD GetLastSPASMError(); +void SetLastSPASMError(int32_t dwErrorCode, ...); +void SetLastSPASMWarning(int32_t dwErrorCode, ...); +//int32_t GetLastSPASMError(); int StartSPASMErrorSession(void); int GetSPASMErrorSessionErrorCount(int nSession); bool IsSPASMErrorSessionFatal(int nSession); @@ -158,10 +160,10 @@ void ReplayFatalSPASMErrorSession(int nSession); void EndSPASMErrorSession(int errors); void ClearSPASMErrorSessions(); int CleanupSPASMErrorSession(int nSession); -void AddSPASMErrorSessionAnnotation(int nSession, LPCTSTR lpszFormat, ...); -bool IsErrorInSPASMErrorSession(int nSession, DWORD dwErrorCode); +void AddSPASMErrorSessionAnnotation(int nSession, const char *lpszFormat, ...); +bool IsErrorInSPASMErrorSession(int nSession, uint32_t dwErrorCode); void FreeSPASMErrorSessions(void); #ifdef _TEST -DWORD GetLastSPASMError(); +uint32_t GetLastSPASMError(); int GetLastSPASMErrorLine(); #endif diff --git a/expand_buf.cpp b/expand_buf.cpp index c8e1836..61fde15 100644 --- a/expand_buf.cpp +++ b/expand_buf.cpp @@ -1,4 +1,5 @@ -#include "stdafx.h" +#include +#include #include "spasm.h" diff --git a/export.cpp b/export.cpp index a4c0d63..5873179 100644 --- a/export.cpp +++ b/export.cpp @@ -2,9 +2,15 @@ by Spencer Putt and James Montelongo */ /* Modified for use in SPASM by Don Straney */ - -#include "stdafx.h" - +#include +#include +#include +#include +#include +#include +#include + +#include "md5.h" #include "spasm.h" #include "utils.h" #include "errors.h" @@ -98,12 +104,21 @@ int findfield_flex( unsigned char prefix_byte, const unsigned char* buffer, int int siggen (const unsigned char* hashbuf, unsigned char* sigbuf, int* outf); void intelhex (FILE * outfile , const unsigned char* buffer, int size, unsigned int address = 0x4000); void alphanumeric (char* namestring, bool allow_lower); -void makerom (const unsigned char *output_contents, DWORD output_len, FILE *outfile); -void makehex (const unsigned char *output_contents, DWORD output_len, FILE *outfile); -void makeapp (const unsigned char *output_contents, DWORD output_len, FILE *outfile, const char *prgmname); +void makerom (const unsigned char *output_contents, uint32_t output_len, FILE *outfile); +void makehex (const unsigned char *output_contents, uint32_t output_len, FILE *outfile); +void makeapp (const unsigned char *output_contents, uint32_t output_len, FILE *outfile, const char *prgmname); void makeprgm (const unsigned char *output_contents, int size, FILE *outfile, const char *prgmname, calc_type calc); void make83 (const unsigned char *output_contents, int size, FILE *outfile, const char *prgmname); +static bool compareCaseInsensitive(const char *s1, const char *s2) { + while (*s1 != 0 && *s2 != 0) { + if (std::tolower(*s1++) != std::tolower(*s2++)) { + return false; + } + } + + return *s1 == 0 && *s2 == 0; +} void write_file (const unsigned char *output_contents, int output_len, const char *output_filename) { FILE *outfile; @@ -112,7 +127,7 @@ void write_file (const unsigned char *output_contents, int output_len, const cha free(curr_input_file); - curr_input_file = strdup(_T("exporter")); + curr_input_file = strdup("exporter"); line_num = -1; @@ -122,14 +137,14 @@ void write_file (const unsigned char *output_contents, int output_len, const cha const char *ext = output_filename + i + 1; int type; - for (type = 0; type < ARRAYSIZE(extensions); type++) { - if (!_stricmp (ext, extensions[type])) + for (type = 0; type < std::size(extensions); type++) { + if (compareCaseInsensitive(ext, extensions[type])) break; } - if (type == ARRAYSIZE(extensions)) { + if (type == std::size(extensions)) { SetLastSPASMWarning(SPASM_WARN_UNKNOWN_EXTENSION); - type = ARRAYSIZE(extensions) - 1; + type = std::size(extensions) - 1; } calc = (calc_type)type; @@ -175,16 +190,16 @@ void write_file (const unsigned char *output_contents, int output_len, const cha case TYPE_85S: case TYPE_86P: case TYPE_86S: - makeprgm (output_contents, (DWORD) output_len, outfile, prgmname, calc); + makeprgm (output_contents, (int32_t) output_len, outfile, prgmname, calc); break; case TYPE_8XK: - makeapp (output_contents, (DWORD) output_len, outfile, prgmname); + makeapp (output_contents, (int32_t) output_len, outfile, prgmname); break; case TYPE_ROM: - makerom(output_contents, (DWORD) output_len, outfile); + makerom(output_contents, (int32_t) output_len, outfile); break; case TYPE_HEX: - makehex(output_contents, (DWORD) output_len, outfile); + makehex(output_contents, (int32_t) output_len, outfile); break; //bin default: @@ -198,7 +213,7 @@ void write_file (const unsigned char *output_contents, int output_len, const cha curr_input_file = NULL; } -void makerom (const unsigned char *output_contents, DWORD size, FILE *outfile) { +void makerom (const unsigned char *output_contents, uint32_t size, FILE *outfile) { unsigned int i; const int final_size = 512*1024; for(i = 0; i < size; i++) @@ -207,11 +222,11 @@ void makerom (const unsigned char *output_contents, DWORD size, FILE *outfile) { fputc(0xFF, outfile); } -void makehex (const unsigned char *output_contents, DWORD size, FILE *outfile) { +void makehex (const unsigned char *output_contents, uint32_t size, FILE *outfile) { intelhex(outfile, output_contents, size); } -void makeapp (const unsigned char *output_contents, DWORD size, FILE *outfile, const char* prgmname) { +void makeapp (const unsigned char *output_contents, uint32_t size, FILE *outfile, const char* prgmname) { unsigned char *buffer; int i,pnt,siglength,tempnum,f,pages,field_sz; unsigned int total_size; @@ -278,19 +293,11 @@ void makeapp (const unsigned char *output_contents, DWORD size, FILE *outfile, c #ifndef NO_APPSIGN /* Calculate MD5 */ -#ifdef WIN32 - unsigned char hashbuf[64]; - HCRYPTPROV hCryptProv; - HCRYPTHASH hCryptHash; - DWORD sizebuf = ARRAYSIZE(hashbuf); - CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET); - CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hCryptHash); - CryptHashData(hCryptHash, buffer, size, 0); - CryptGetHashParam(hCryptHash, HP_HASHVAL, hashbuf, &sizebuf, 0); -#else unsigned char hashbuf[16]; - MD5 (buffer, size, hashbuf); //This uses ssl but any good md5 should work fine. -#endif + MD5_CTX ctx; + MD5_Init(&ctx); + MD5_Update(&ctx, buffer, size); + MD5_Final(hashbuf, &ctx); /* Generate the signature to the buffer */ siglength = siggen(hashbuf, buffer+size+3, &f ); @@ -329,18 +336,6 @@ void makeapp (const unsigned char *output_contents, DWORD size, FILE *outfile, c /* Convert to 8xk */ intelhex(outfile, buffer, total_size); -#ifndef NO_APPSIGN -#ifdef WIN32 - if (hCryptHash) { - CryptDestroyHash(hCryptHash); - hCryptHash = NULL; - } - if (hCryptProv) { - CryptReleaseContext(hCryptProv,0); - hCryptProv = NULL; - } -#endif -#endif free(buffer); // if (pages==1) printf("%s (%d page",filename,pages); // else printf("%s (%d pages",filename,pages); diff --git a/hash.cpp b/hash.cpp index 495243e..aded5c3 100644 --- a/hash.cpp +++ b/hash.cpp @@ -1,4 +1,4 @@ -#include "stdafx.h" + #include "spasm.h" #include "hash.h" diff --git a/hash.h b/hash.h index 808bcd7..b93aa2a 100644 --- a/hash.h +++ b/hash.h @@ -1,7 +1,8 @@ #ifndef HASH_H_ #define HASH_H_ -#include +#include +#include #include #include "list.h" @@ -10,7 +11,6 @@ typedef struct { } store_t; struct comparator - : public std::binary_function { bool operator()(const char * _Left, const char *_Right) const { diff --git a/lib/mpir.lib b/lib/mpir.lib deleted file mode 100644 index 89b7eba..0000000 Binary files a/lib/mpir.lib and /dev/null differ diff --git a/lib/mpir.pdb b/lib/mpir.pdb deleted file mode 100644 index b765e5c..0000000 Binary files a/lib/mpir.pdb and /dev/null differ diff --git a/lib/x64/mpir.lib b/lib/x64/mpir.lib deleted file mode 100644 index f177455..0000000 Binary files a/lib/x64/mpir.lib and /dev/null differ diff --git a/lib/x64/mpir.pdb b/lib/x64/mpir.pdb deleted file mode 100644 index a6d87e3..0000000 Binary files a/lib/x64/mpir.pdb and /dev/null differ diff --git a/list.cpp b/list.cpp index cadf1df..df4efc7 100644 --- a/list.cpp +++ b/list.cpp @@ -1,4 +1,4 @@ -#include "stdafx.h" +#include #include "spasm.h" diff --git a/main.cpp b/main.cpp index 39c3962..1dafb7d 100644 --- a/main.cpp +++ b/main.cpp @@ -1,5 +1,16 @@ -#include "stdafx.h" +#include +#include +#include +#include +#include +#ifdef WIN32 +#include +#else +#include +#endif + +// This defines assorted globals in spasm.h rather than just declaring them. #define __MAIN_C #include "pass_one.h" @@ -10,7 +21,6 @@ #include "utils.h" #include "console.h" #include "errors.h" -#include "Module.h" #define LISTING_BUF_SIZE 65536 //initial size of buffer for output listing @@ -36,13 +46,7 @@ CSPASMModule _AtlModule; int run_assembly() { -#ifdef _WIN32 - struct _timeb time_start, time_end; - _ftime(&time_start); -#else - struct timeb time_start, time_end; - ftime(&time_start); -#endif + auto time_start = std::chrono::steady_clock::now(); exit_code = EXIT_NORMAL; /*extern int generic_map[256]; @@ -200,21 +204,9 @@ int run_assembly() get_num_labels (), get_num_defines (), stats_codesize, stats_datasize, stats_codesize + stats_datasize); } -#ifdef _WIN32 - _ftime(&time_end); -#else - ftime(&time_end); -#endif - int s_diff = (int) (time_end.time - time_start.time); - int ms_diff = time_end.millitm - time_start.millitm; - if (ms_diff < 0) { - ms_diff += 1000; - s_diff -= 1; - } else if (ms_diff > 1000) { - ms_diff -= 1000; - s_diff += 1; - } - printf("Assembly time: %0.3f seconds\n", (float) s_diff + ((float) ms_diff / 1000.0f)); + auto elapsed = std::chrono::steady_clock::now() - time_start; + float seconds = std::chrono::duration_cast(elapsed).count() / 1000; + printf("Assembly time: %0.3f seconds\n", seconds); return exit_code; } void print_help_message(void){ diff --git a/md5.c b/md5.c new file mode 100644 index 0000000..bc91564 --- /dev/null +++ b/md5.c @@ -0,0 +1,291 @@ +/* + * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. + * MD5 Message-Digest Algorithm (RFC 1321). + * + * Homepage: + * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 + * + * Author: + * Alexander Peslyak, better known as Solar Designer + * + * This software was written by Alexander Peslyak in 2001. No copyright is + * claimed, and the software is hereby placed in the public domain. + * In case this attempt to disclaim copyright and place the software in the + * public domain is deemed null and void, then the software is + * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the + * general public under the following terms: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + * + * (This is a heavily cut-down "BSD license".) + * + * This differs from Colin Plumb's older public domain implementation in that + * no exactly 32-bit integer data type is required (any 32-bit or wider + * unsigned integer data type will do), there's no compile-time endianness + * configuration, and the function prototypes match OpenSSL's. No code from + * Colin Plumb's implementation has been reused; this comment merely compares + * the properties of the two independent implementations. + * + * The primary goals of this implementation are portability and ease of use. + * It is meant to be fast, but not as fast as possible. Some known + * optimizations are not included to reduce source code size and avoid + * compile-time configuration. + */ + +#ifndef HAVE_OPENSSL + +#include + +#include "md5.h" + +/* + * The basic MD5 functions. + * + * F and G are optimized compared to their RFC 1321 definitions for + * architectures that lack an AND-NOT instruction, just like in Colin Plumb's + * implementation. + */ +#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) +#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y)))) +#define H(x, y, z) (((x) ^ (y)) ^ (z)) +#define H2(x, y, z) ((x) ^ ((y) ^ (z))) +#define I(x, y, z) ((y) ^ ((x) | ~(z))) + +/* + * The MD5 transformation for all four rounds. + */ +#define STEP(f, a, b, c, d, x, t, s) \ + (a) += f((b), (c), (d)) + (x) + (t); \ + (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \ + (a) += (b); + +/* + * SET reads 4 input bytes in little-endian byte order and stores them in a + * properly aligned word in host byte order. + * + * The check for little-endian architectures that tolerate unaligned memory + * accesses is just an optimization. Nothing will break if it fails to detect + * a suitable architecture. + * + * Unfortunately, this optimization may be a C strict aliasing rules violation + * if the caller's data buffer has effective type that cannot be aliased by + * MD5_u32plus. In practice, this problem may occur if these MD5 routines are + * inlined into a calling function, or with future and dangerously advanced + * link-time optimizations. For the time being, keeping these MD5 routines in + * their own translation unit avoids the problem. + */ +#if defined(__i386__) || defined(__x86_64__) || defined(__vax__) +#define SET(n) \ + (*(MD5_u32plus *)&ptr[(n) * 4]) +#define GET(n) \ + SET(n) +#else +#define SET(n) \ + (ctx->block[(n)] = \ + (MD5_u32plus)ptr[(n) * 4] | \ + ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \ + ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \ + ((MD5_u32plus)ptr[(n) * 4 + 3] << 24)) +#define GET(n) \ + (ctx->block[(n)]) +#endif + +/* + * This processes one or more 64-byte data blocks, but does NOT update the bit + * counters. There are no alignment requirements. + */ +static const void *body(MD5_CTX *ctx, const void *data, unsigned long size) +{ + const unsigned char *ptr; + MD5_u32plus a, b, c, d; + MD5_u32plus saved_a, saved_b, saved_c, saved_d; + + ptr = (const unsigned char *)data; + + a = ctx->a; + b = ctx->b; + c = ctx->c; + d = ctx->d; + + do { + saved_a = a; + saved_b = b; + saved_c = c; + saved_d = d; + +/* Round 1 */ + STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7) + STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12) + STEP(F, c, d, a, b, SET(2), 0x242070db, 17) + STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22) + STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7) + STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12) + STEP(F, c, d, a, b, SET(6), 0xa8304613, 17) + STEP(F, b, c, d, a, SET(7), 0xfd469501, 22) + STEP(F, a, b, c, d, SET(8), 0x698098d8, 7) + STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12) + STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17) + STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22) + STEP(F, a, b, c, d, SET(12), 0x6b901122, 7) + STEP(F, d, a, b, c, SET(13), 0xfd987193, 12) + STEP(F, c, d, a, b, SET(14), 0xa679438e, 17) + STEP(F, b, c, d, a, SET(15), 0x49b40821, 22) + +/* Round 2 */ + STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5) + STEP(G, d, a, b, c, GET(6), 0xc040b340, 9) + STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14) + STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20) + STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5) + STEP(G, d, a, b, c, GET(10), 0x02441453, 9) + STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14) + STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20) + STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5) + STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9) + STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14) + STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20) + STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5) + STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9) + STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14) + STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20) + +/* Round 3 */ + STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4) + STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11) + STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16) + STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23) + STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4) + STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11) + STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16) + STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23) + STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4) + STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11) + STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16) + STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23) + STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4) + STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11) + STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16) + STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23) + +/* Round 4 */ + STEP(I, a, b, c, d, GET(0), 0xf4292244, 6) + STEP(I, d, a, b, c, GET(7), 0x432aff97, 10) + STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15) + STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21) + STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6) + STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10) + STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15) + STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21) + STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6) + STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10) + STEP(I, c, d, a, b, GET(6), 0xa3014314, 15) + STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21) + STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6) + STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10) + STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15) + STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21) + + a += saved_a; + b += saved_b; + c += saved_c; + d += saved_d; + + ptr += 64; + } while (size -= 64); + + ctx->a = a; + ctx->b = b; + ctx->c = c; + ctx->d = d; + + return ptr; +} + +void MD5_Init(MD5_CTX *ctx) +{ + ctx->a = 0x67452301; + ctx->b = 0xefcdab89; + ctx->c = 0x98badcfe; + ctx->d = 0x10325476; + + ctx->lo = 0; + ctx->hi = 0; +} + +void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size) +{ + MD5_u32plus saved_lo; + unsigned long used, available; + + saved_lo = ctx->lo; + if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) + ctx->hi++; + ctx->hi += size >> 29; + + used = saved_lo & 0x3f; + + if (used) { + available = 64 - used; + + if (size < available) { + memcpy(&ctx->buffer[used], data, size); + return; + } + + memcpy(&ctx->buffer[used], data, available); + data = (const unsigned char *)data + available; + size -= available; + body(ctx, ctx->buffer, 64); + } + + if (size >= 64) { + data = body(ctx, data, size & ~(unsigned long)0x3f); + size &= 0x3f; + } + + memcpy(ctx->buffer, data, size); +} + +#define OUT(dst, src) \ + (dst)[0] = (unsigned char)(src); \ + (dst)[1] = (unsigned char)((src) >> 8); \ + (dst)[2] = (unsigned char)((src) >> 16); \ + (dst)[3] = (unsigned char)((src) >> 24); + +void MD5_Final(unsigned char *result, MD5_CTX *ctx) +{ + unsigned long used, available; + + used = ctx->lo & 0x3f; + + ctx->buffer[used++] = 0x80; + + available = 64 - used; + + if (available < 8) { + memset(&ctx->buffer[used], 0, available); + body(ctx, ctx->buffer, 64); + used = 0; + available = 64; + } + + memset(&ctx->buffer[used], 0, available - 8); + + ctx->lo <<= 3; + OUT(&ctx->buffer[56], ctx->lo) + OUT(&ctx->buffer[60], ctx->hi) + + body(ctx, ctx->buffer, 64); + + OUT(&result[0], ctx->a) + OUT(&result[4], ctx->b) + OUT(&result[8], ctx->c) + OUT(&result[12], ctx->d) + + memset(ctx, 0, sizeof(*ctx)); +} + +#endif diff --git a/md5.h b/md5.h new file mode 100644 index 0000000..3414563 --- /dev/null +++ b/md5.h @@ -0,0 +1,53 @@ +/* + * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. + * MD5 Message-Digest Algorithm (RFC 1321). + * + * Homepage: + * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 + * + * Author: + * Alexander Peslyak, better known as Solar Designer + * + * This software was written by Alexander Peslyak in 2001. No copyright is + * claimed, and the software is hereby placed in the public domain. + * In case this attempt to disclaim copyright and place the software in the + * public domain is deemed null and void, then the software is + * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the + * general public under the following terms: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + * + * See md5.c for more information. + */ + +#ifndef _MD5_H +#define _MD5_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Any 32-bit or wider unsigned integer data type will do */ +typedef uint32_t MD5_u32plus; + +typedef struct { + MD5_u32plus lo, hi; + MD5_u32plus a, b, c, d; + unsigned char buffer[64]; + MD5_u32plus block[16]; +} MD5_CTX; + +extern void MD5_Init(MD5_CTX *ctx); +extern void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size); +extern void MD5_Final(unsigned char *result, MD5_CTX *ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/modp_ascii.cpp b/modp_ascii.cpp index c9c3881..5dfc106 100644 --- a/modp_ascii.cpp +++ b/modp_ascii.cpp @@ -1,5 +1,6 @@ /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */ /* vi: set expandtab shiftwidth=4 tabstop=4: */ +#include /** * \file modp_ascii.c @@ -41,7 +42,7 @@ * http://www.opensource.org/licenses/bsd-license.php * */ -#include "stdafx.h" + #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) typedef unsigned char uint8_t; typedef unsigned int uint32_t; diff --git a/opcodes.cpp b/opcodes.cpp index 4fc4c55..7c3bc4a 100644 --- a/opcodes.cpp +++ b/opcodes.cpp @@ -1,4 +1,4 @@ -#include "stdafx.h" +#include #include "opcodes.h" diff --git a/opcodes_ez80.cpp b/opcodes_ez80.cpp index ac17aa6..04e58dc 100644 --- a/opcodes_ez80.cpp +++ b/opcodes_ez80.cpp @@ -1,4 +1,4 @@ -#include "stdafx.h" +#include #include "opcodes.h" diff --git a/parser.cpp b/parser.cpp index ea53f75..42ffdf6 100644 --- a/parser.cpp +++ b/parser.cpp @@ -1,4 +1,7 @@ -#include "stdafx.h" +#include +#include +#include +#include #define __PARSER_C @@ -408,7 +411,7 @@ static const char *parse_single_num (const char *expr, int *value) { if (GetSPASMErrorSessionErrorCount(session) > 0) { - AddSPASMErrorSessionAnnotation(session, _T("Error during evaluation of macro '%s'"), define->name); + AddSPASMErrorSessionAnnotation(session, "Error during evaluation of macro '%s'", define->name); ReplaySPASMErrorSession(session); fHasError = true; } @@ -603,7 +606,7 @@ static const char *parse_num_full (const char *expr, int *value, int depth) { } last_op = M_NONE; - for (int i = 0; i < ARRAYSIZE(MathDefs); i++) + for (int i = 0; i < std::size(MathDefs); i++) { if (strncmp(expr, MathDefs[i].szDef, strlen(MathDefs[i].szDef)) == 0) { @@ -657,7 +660,7 @@ static const char *parse_num_full (const char *expr, int *value, int depth) { static bool conv_generic(const char *str, const char *end, int *output_num, int base, int error_code) { char *ep; - long long value = _strtoi64(str, &ep, base); + long long value = strtoll(str, &ep, base); if (ep < end) { char *number = strndup(str, end - str); diff --git a/pass_one.cpp b/pass_one.cpp index 3dc4340..99cebc9 100644 --- a/pass_one.cpp +++ b/pass_one.cpp @@ -1,775 +1,776 @@ -#include "stdafx.h" - -#include "spasm.h" -#include "utils.h" -#include "storage.h" -#include "parser.h" -#include "pass_two.h" -#include "opcodes.h" -#include "directive.h" -#include "preop.h" -#include "list.h" -#include "errors.h" - -#ifdef USE_BUILTIN_FCREATE -#include "expand_buf.h" -#include "directive.h" -#include "pass_one.h" -#define MAX_BUFFERS 10 -static expand_buf_t* fcreate_bufs[MAX_BUFFERS]; -#endif - -char *run_first_pass_line (char *ptr); -char *run_first_pass_line_sec (char *ptr); -char *handle_opcode_or_macro (char *ptr); -int parse_suffix (char **opcode_end); -char *match_opcode_args (char *ptr, char **arg_ptrs, char **arg_end_ptrs, opcode *curr_opcode, instr **curr_instr); -int write_instruction_data (instr *curr_instr, char **arg_ptrs, char **arg_end_ptrs, int suffix); - -bool adl_mode; -int listing_width; -const char *last_banner = NULL; -const char *built_in_fcreate = "Built-in fcreate"; - -/* - * Writes val to the output - */ - -int write_out (int val) { - - //write hex data if listing mode is on - if (mode & MODE_LIST && listing_on) { - char text[4]; - - if (pass_one && listing_width >= 4) { - listing_width = 0; - listing_offset = eb_insert (listing_buf, listing_offset, NEWLINE " ", -1); - } else if (!pass_one) { - /* If it's on the second pass, a word might - span two lines, so check if we need to skip - to the beginning of the next line */ - char buf_char = eb_get_char (listing_buf, listing_offset); - if (buf_char == '\n' || buf_char == '\r') { - while (isspace ((unsigned char) eb_get_char (listing_buf, listing_offset))) - listing_offset++; - } - } - - sprintf (text, "%02X ", val & 0xFF); - if (pass_one) - listing_offset = eb_insert (listing_buf, listing_offset, text, 3); - else { - eb_overwrite (listing_buf, listing_offset, text, 3); - listing_offset += 3; - } - listing_width++; - } - - //if (mode & MODE_NORMAL) - *(out_ptr++) = val; - - return val; -} - - -/* - * Writes listing for a single line, not - * including hex data (handled by write_out) - * or line number / program counter (handled - * in run_first_pass) - */ - -void do_listing_for_line (char *ptr) { - char *curr_line, text[32]; - - //make sure empty bytes are filled - while (listing_width < 4) { - listing_offset = eb_insert (listing_buf, listing_offset, "- ", 3); - listing_width++; - } - - //and finally, write the contents of the line - //TODO: clean up? - curr_line = skip_to_next_line (line_start); - while (curr_line < ptr) { - listing_offset = eb_insert (listing_buf, listing_offset, line_start, curr_line - line_start); - line_start = curr_line; - curr_line = skip_to_next_line (curr_line); - - old_line_num++; - sprintf (text, "%5d %02X:%04X ", old_line_num, (program_counter >> 16), program_counter & 0xFFFF); - listing_offset = eb_insert (listing_buf, listing_offset, text, strlen (text)); - } - listing_offset = eb_insert (listing_buf, listing_offset, line_start, ptr - line_start); - //make sure there's a newline char at the end - if (*(ptr - 1) != '\n') { - listing_offset = eb_insert (listing_buf, listing_offset, NEWLINE, -1); - } -} - - -/* - * Goes through the first - * pass on an mmapped file - */ - -void run_first_pass (char *ptr) { - line_num = 1; - pass_one = true; - if (mode & MODE_EZ80) { - adl_mode = true; - } - - while (!error_occurred && *ptr != '\0') { - - if (mode & MODE_LIST) { - //init some listing stuff - listing_width = 0; - line_start = ptr; - old_line_num = line_num; - listing_for_line_done = false; - - if (listing_on) { - char text[32]; - - //add the line number and program counter at the beginning of the line - sprintf (text, "%5d %02X:%04X ", line_num, (program_counter >> 16), program_counter & 0xFFFF); - listing_offset = eb_insert (listing_buf, listing_offset, text, strlen (text)); - } - } - - ptr = run_first_pass_line (ptr); - if (ptr != NULL) { - //evaluate the line - ptr = skip_to_next_line (ptr); - - //do listing stuff for this line - if (mode & MODE_LIST && listing_on && !listing_for_line_done) - do_listing_for_line (ptr); - - line_num++; - } else { - // Nothing more to read, return - break; - } - } -} - - -/* - * Parses a single line, - * returns a pointer to the - * end of the line - */ - -char *run_first_pass_line (char *ptr) { - do { - if (*ptr == '\\') - ptr++; - - //char *code_end = skip_to_line_end(ptr); - //printf("line %d: %s\n", line_num, strndup(ptr, code_end - ptr)); - //parse what's on the line - ptr = run_first_pass_line_sec (ptr); - if (ptr == NULL) - return NULL; - ptr = skip_whitespace (ptr); - - //when that's done, skip any whitespace and see if more is stuck on the end with a backslash - - // if so, keep looping until this line's done - } while (!error_occurred && *ptr == '\\'); - - return ptr; -} - - -/* - * Parses a single command/section - * on a line, returns a pointer to - * the end of the usable part - */ - -char *run_first_pass_line_sec (char *ptr) { - - if (is_end_of_code_line (ptr)) { - //if the line's blank or a comment, don't do anything with it - return ptr; - } else if (isalpha ((unsigned char) *ptr) || *ptr == '_') { - //if the first char on the line is a number, letter, or underscore, it must be a label - char *name, *label_end; - - //find the end of the label - label_end = skip_to_name_end (ptr); - if (*label_end == '(') - return handle_opcode_or_macro (ptr); - - name = strndup (ptr, label_end - ptr); - - ptr = label_end; - - if (*ptr == ':') ptr++; - -#ifdef USE_REUSABLES - if (strcmp (name, "_") == 0) { - add_reusable(); - free(name); -#else - if (0) { -#endif - } else { - //if there's a ':', either the line ends or there's an instruction after it - last_label = add_label (name, program_counter); - } - - return run_first_pass_line_sec (ptr); - } else if (isspace ((unsigned char) *ptr)) { - //if it starts with whitespace, skip that - ptr = skip_whitespace (ptr); - - if (isalpha (*ptr) || *ptr == '_') - //otherwise, it might be an instruction or macro - return handle_opcode_or_macro (ptr); - - return run_first_pass_line_sec (ptr); - } else if (*ptr == '.') { - //handle it if it's a directive - return handle_directive (++ptr); - } else if (*ptr == '#') { - //or pre-op - return handle_preop (++ptr); - } else if (*ptr == '=') { - //handle 'x = 1234' type lines - int value; - char value_str[256]; - - ptr++; - read_expr (&ptr, value_str, ""); - - if (parse_num (value_str, &value) == true) - { - if (last_label == NULL) { - SetLastSPASMError(SPASM_ERR_EQUATE_MISSING_LABEL); - } else { - last_label->value = value; - } - } - return ptr; - - } else { - SetLastSPASMError(SPASM_ERR_SYNTAX); - return ptr; - } -} - - -static define_t *search_defines_helper(const char *name_start, size_t len) -{ - char *name = strndup(name_start, len); - define_t *result = search_defines(name); - free(name); - return result; -} - -/* - * Handles an opcode or macro, - * returns the new location in - * the file - */ - -char *handle_opcode_or_macro (char *ptr) { - char *name_end; - char *name_start = ptr; - opcode *curr_opcode; - - //first get the name - name_end = skip_to_name_end (ptr); - ptr = name_end; - - //parse the suffix if possible - char *opcode_end = name_end; - int suffix = -1; - if (mode & MODE_EZ80) - suffix = parse_suffix(&opcode_end); - - //try to match it against opcodes first - curr_opcode = all_opcodes; - while (curr_opcode && curr_opcode->name) { - if (!strncasecmp (name_start, curr_opcode->name, max(strlen(curr_opcode->name), opcode_end - name_start))) - break; - curr_opcode = curr_opcode->next; - } - - //if it was found, then find the right instruction - if (curr_opcode && curr_opcode->name) { - char *arg_ptrs[3], *arg_end_ptrs[3]; - instr *curr_instr = NULL; - - //go to the start of the arguments - ptr = skip_whitespace (ptr); - - //try to match them to one of the opcode's sets of arguments - ptr = match_opcode_args (ptr, arg_ptrs, arg_end_ptrs, curr_opcode, &curr_instr); - if (curr_instr != NULL) - { - //if that worked, write data + args - int size = write_instruction_data (curr_instr, arg_ptrs, arg_end_ptrs, suffix); - - //increment program counter and stats - program_counter += size; - stats_codesize += size; - stats_mintime += curr_instr->min_exectime; - stats_maxtime += curr_instr->max_exectime; - if (MODE_EZ80) { - //increment stats further based on suffix and mode - int penalty = (suffix >= 0 ? 1 : 0); - if ((suffix < 0 && adl_mode) || suffix > 0) - penalty += curr_instr->adl_exectime_penalty; - stats_mintime += penalty; - stats_maxtime += penalty; - } - } - - } else { - //if this name doesn't match an opcode, it must be a macro (#macro OR #define) - define_t *define; -#ifdef USE_BUILTIN_FCREATE - if (!strncasecmp (name_start, "buf", name_end - name_start) && *ptr == '(') { - char buf[256]; - int value; - ptr++; - read_expr(&ptr, buf, _T(")")); - if (parse_num(buf, &value)) { - cur_buf = value; - } else { - SetLastSPASMError(SPASM_ERR_INVALID_OPERANDS); - } - ptr++; - } else if (!strncasecmp (name_start, "clr", name_end - name_start) && *ptr == '(') { - expand_buf_t *eb_fcreate = fcreate_bufs[cur_buf]; - if (eb_fcreate != NULL) { - eb_free(eb_fcreate); - } - eb_fcreate = eb_init(128); - fcreate_bufs[cur_buf] = eb_fcreate; - ptr += 2; - } else if (!strncasecmp (name_start, "wr", name_end - name_start) && *ptr == '(') { - expand_buf_t *eb_fcreate = fcreate_bufs[cur_buf]; - if (eb_fcreate == NULL) { - eb_fcreate = eb_init(128); - fcreate_bufs[cur_buf] = eb_fcreate; - } - - ptr = parse_emit_string(++ptr, ES_FCREATE, eb_fcreate); - ptr++; - eb_append(eb_fcreate, NEWLINE, strlen(NEWLINE)); - } else if (!strncasecmp (name_start, "run", name_end - name_start) && *ptr == '(') { - expand_buf_t *eb_fcreate = fcreate_bufs[cur_buf]; - if (eb_fcreate == NULL) - { - SetLastSPASMError(SPASM_ERR_FCREATE_NOFILE); - } - else - { - char *fcreate_string = eb_extract(eb_fcreate); - - //make sure the listing for this line is finished up BEFORE - // the new file is parsed and writes its listing stuff all over - if (mode & MODE_LIST && listing_on && !listing_for_line_done) - do_listing_for_line (skip_to_next_line (line_start)); - - if (mode & MODE_LIST && listing_on && last_banner != built_in_fcreate) { - char include_banner[128] = "Listing for built-in fcreate" NEWLINE; - listing_offset = eb_insert (listing_buf, listing_offset, include_banner, strlen (include_banner)); - last_banner = built_in_fcreate; - } - - // Thanks for this Don - int old_line_num = line_num; - char *old_input_file = curr_input_file; - int old_in_macro = in_macro; - char *old_line_start = line_start; - int old_old_line_num = old_line_num; - curr_input_file = (char *) built_in_fcreate; - - int session = StartSPASMErrorSession(); - - run_first_pass(fcreate_string); - - curr_input_file = old_input_file; - line_num = old_line_num; - in_macro = old_in_macro; - line_start = old_line_start; - old_line_num = old_old_line_num; - - if (mode & MODE_LIST && listing_on && !listing_for_line_done) - listing_for_line_done = true; - - if (mode & MODE_LIST && listing_on && last_banner != curr_input_file) { - char include_banner[MAX_PATH + 64]; - snprintf(include_banner, sizeof (include_banner), "Listing for file \"%s\"" NEWLINE, curr_input_file); - listing_offset = eb_insert (listing_buf, listing_offset, include_banner, strlen (include_banner)); - last_banner = curr_input_file; - } - - free(fcreate_string); - eb_free(fcreate_bufs[cur_buf]); - fcreate_bufs[cur_buf] = NULL; - - if (GetSPASMErrorSessionErrorCount(session) > 0) - { - AddSPASMErrorSessionAnnotation(session, "Error during invocation of fcreate"); - ReplaySPASMErrorSession(session); - } - EndSPASMErrorSession(session); - } - ptr += 2; - } else -#endif - - if ((define = search_defines_helper(name_start, name_end - name_start))) - { - list_t *args = NULL; - char *args_end; - - //if there are arguments, parse them - int session = StartSPASMErrorSession(); - args_end = parse_args(ptr, define, &args); - - ptr = args_end; - - if (!IsSPASMErrorSessionFatal(session)) - { - in_macro++; - - //printf("args: %s\n", ((define_t *) args->data)->name); - - //see if any code is left on the line - if (!is_end_of_code_line (skip_whitespace (ptr))) { - char *line_end = skip_to_line_end (ptr); - if (define->contents == NULL) - { - SetLastSPASMError(SPASM_ERR_ARG_USED_WITHOUT_VALUE, define->name); - } - else - { - char *full_line = (char *)malloc(strlen(define->contents) + line_end - ptr + 1); - - strcpy(full_line, define->contents); - strncat(full_line, ptr, line_end - ptr); - - run_first_pass_line(full_line); - free(full_line); - } - } else { - if (define->contents == NULL) - { - SetLastSPASMError(SPASM_ERR_ARG_USED_WITHOUT_VALUE, define->name); - } - else - { - //parse each line in the macro (prefix with space) - //Buckeye: this malloc size is extra so that we can simply replace - //@params and not worry about reallocating - char *full_macro = (char *) malloc(strlen(define->contents) + 2); - char *curr_line = full_macro; - - full_macro[0] = ' '; - strcpy(&full_macro[1], define->contents); - - //char *replace_args_ptr = full_macro; - //replace_args_ptr = replace_literal_args(replace_args_ptr, define, &args); - - const char *old_filename = curr_input_file; - int old_line_num = line_num; - curr_input_file = define->input_file; - line_num = define->line_num; - - while (curr_line != NULL && *curr_line && !error_occurred) - { - char *next_line = run_first_pass_line(curr_line); - curr_line = skip_to_next_line(next_line); - line_num++; - } - - if ((mode & MODE_LIST) && listing_on && last_banner != old_filename) { - if (mode & MODE_LIST && listing_on && !listing_for_line_done) - do_listing_for_line (skip_to_next_line (line_start) ); - - listing_for_line_done = true; - - char include_banner[MAX_PATH + 64]; - snprintf(include_banner, sizeof (include_banner), "Listing for file \"%s\"" NEWLINE, old_filename); - listing_offset = eb_insert (listing_buf, listing_offset, include_banner, strlen (include_banner)); - last_banner = old_filename; - } - - curr_input_file = (char *) old_filename; - line_num = old_line_num; - - free(full_macro); - } - } - in_macro--; - } - - //clear the argument values - remove_arg_set(args); - - AddSPASMErrorSessionAnnotation(session, "Error during invocation of macro '%s'", define->name); - ReplayFatalSPASMErrorSession(session); - EndSPASMErrorSession(session); - - } else { - char *name = strndup(name_start, name_end - name_start); - SetLastSPASMError(SPASM_ERR_UNKNOWN_OPCODE, name); - free (name); - } - } - - return ptr; -} - -/* - * Attempts to parse a suffix at the end of an - * eZ80 opcode. Returns -1 if no suffix found, - * or a bitmask corresponding to the proper - * suffix. If a suffix is found, the opcode_end - * argument is set to the end of the main opcode. - */ - -int parse_suffix(char **opcode_end) { - char *suffix_ptr = *opcode_end; - char last1 = tolower(*--suffix_ptr); - if (last1 == 's' || last1 == 'l') { - char last2 = tolower(*--suffix_ptr); - if (last2 == '.') { - *opcode_end = suffix_ptr; - return (last1 == 'l' ? SUFFIX_L : 0) | (adl_mode ? SUFFIX_IL : 0); - } - if (last2 == 'i') { - last2 = tolower(*--suffix_ptr); - if (last2 == '.') { - *opcode_end = suffix_ptr; - return (adl_mode ? SUFFIX_L : 0) | (last1 == 'l' ? SUFFIX_IL : 0); - } - if (*--suffix_ptr == '.' && (last2 == 's' || last2 == 'l')) { - *opcode_end = suffix_ptr; - return (last2 == 'l' ? SUFFIX_L : 0) | (last1 == 'l' ? SUFFIX_IL : 0); - } - } - } - return -1; -} - - -/* - * Tries to match instruction - * arguments at ptr to one of - * the sets of arguments for - * curr_opcode, sets arg_ptrs - * and arg_end_ptrs to start - * and end of text of arguments, - * sets curr_instr if a match - * is found, returns new position - * in file - */ - -char *match_opcode_args (char *ptr, char **arg_ptrs, char **arg_end_ptrs, opcode *curr_opcode, instr **curr_instr) { - char *curr_arg_file = NULL; - int instr_num; - - for (instr_num = 0; instr_num < curr_opcode->num_instrs; instr_num++) { - //test each possible set of arguments for this opcode - const char *curr_arg; - int curr_arg_num = 0; - - curr_arg_file = ptr; - curr_arg = curr_opcode->instrs[instr_num].args; - - //check each character in the current argument - while (*curr_arg && !(is_end_of_code_line (curr_arg_file) || *curr_arg_file == '\\')) { - if (is_arg (*curr_arg)) { - char trash_buf[256]; - - //if this part of the argument is a number, then make sure it exists, - //save its position in the file, and skip to the next argument - if (is_end_of_code_line (curr_arg_file) || *curr_arg_file == '\\') - break; - - // if a name starts with, but is longer than, "ix" or "iy", don't match index offset - if (*curr_arg == '@' && is_name_char(*curr_arg_file)) - break; - - arg_ptrs[curr_arg_num] = curr_arg_file; - BOOL test = read_expr (&curr_arg_file, trash_buf, ","); - if (*(curr_arg_file - 1) == ',') - curr_arg_file--; - arg_end_ptrs[curr_arg_num] = curr_arg_file; - curr_arg_num++; - - } else { - //if this part of the argument isn't a number, and they don't match, then break - if (tolower (*curr_arg_file) != tolower (*curr_arg)) - break; - - curr_arg_file++; - } - // only skip whitespace if not in the middle of a register - if (!isalpha(*(curr_arg_file - 1)) || !isalpha(*curr_arg_file)) - curr_arg_file = skip_whitespace (curr_arg_file); - curr_arg++; - } - - //special case, allow empty string at the end to match ix/iy offset - if (*curr_arg == '@') { - arg_ptrs[curr_arg_num] = curr_arg_file; - arg_end_ptrs[curr_arg_num] = curr_arg_file; - curr_arg_num++; - curr_arg++; - } - - //see if all the arguments matched - if (!(*curr_arg) && (is_end_of_code_line (curr_arg_file) || *curr_arg_file == '\\')) - break; - } - - if (instr_num >= curr_opcode->num_instrs) { - // If the next mnemonic is the same, skip to the next group - if (curr_opcode->next != NULL && !strcasecmp (curr_opcode->name, curr_opcode->next->name)) - return match_opcode_args (ptr, arg_ptrs, arg_end_ptrs, curr_opcode->next, curr_instr); - - //if it doesn't match any instructions for this opcode, show an error and skip to line end - SetLastSPASMError(SPASM_ERR_INVALID_OPERANDS, curr_opcode->name); - - } else - *curr_instr = &(curr_opcode->instrs[instr_num]); - - curr_opcode->use_count++; - return curr_arg_file; -} - - -/* - * Writes the instruction data and arguments - * for curr_instr, with argument text start - * and end points in arg_ptrs and arg_end_ptrs - * - * Suffix is relevant for eZ80 instructions - * and may change the instruction's size, - * so the final size is returned. - */ - -int write_instruction_data (instr *curr_instr, char **arg_ptrs, char **arg_end_ptrs, int suffix) { - char *bit_arg_text = NULL; - bool has_bit_arg = false; - int i, curr_arg_num = 0; - int size = curr_instr->size; - - if (suffix >= 0) { - write_out (0x40 + suffix * 9); - size++; - } - else if (mode & MODE_EZ80) { - suffix = adl_mode ? (SUFFIX_L | SUFFIX_IL) : 0; - } - - //write the actual instruction data first - if (mode & MODE_NORMAL || mode & MODE_LIST) { - int i; - for (i = curr_instr->instr_size - 1; i >= 0; i--) - write_out (curr_instr->instr_data[i]); - } - - //then the arguments, if there are any - for (i = 0; curr_instr->args[i]; i++) { - //use the argument positions that were saved when we matched the arg strings - if (is_arg (curr_instr->args[i])) { - //first get the text of each argument - char *arg_text = strndup (arg_ptrs[curr_arg_num], - arg_end_ptrs[curr_arg_num] - arg_ptrs[curr_arg_num]); - char *fake_arg_text; - - // Check for extra parentheses (confusingly looks like indirection) - if (arg_text[0] == '(') { - int level = 1; - char *p = &arg_text[1]; - char *last = &arg_text[strlen(arg_text) - 1]; - - // Clip off ending space - while (isspace((unsigned char) *last) && last > p) - last--; - - // Search the inner chars - while (p < last && level > 0) { - if (*p == '(') level++; - else if (*p == ')') level--; - p++; - } - if (p == last) - show_warning ("Suggest remove extra parentheses around argument"); - } - curr_arg_num++; - - switch (curr_instr->args[i]) { - case '*': //16-bit number - if (suffix >= 0 && suffix & SUFFIX_IL) { - size++; - add_pass_two_expr (arg_text, ARG_NUM_24, size, 0); - } - else { - add_pass_two_expr (arg_text, ARG_NUM_16, size, 0); - } - free (arg_text); - break; - case '&': //8-bit number - add_pass_two_expr (arg_text, ARG_NUM_8, size, 0); - free (arg_text); - break; - case '%': //8-bit address offset - add_pass_two_expr (arg_text, ARG_ADDR_OFFSET, size, 0); - free (arg_text); - break; - case '@': //8-bit IX/IY offset - if (arg_text[0] != '\0' && arg_text[0] != '+' && arg_text[0] != '-') - SetLastSPASMError(SPASM_ERR_INVALID_INDEX_OFFSET); - else { - // prefix the arg with "0" so that the first "+" or "-" is - // correctly parsed as an operator, and not part of a local - // label, also handles an empty arg - fake_arg_text = (char *)malloc (1 + strlen(arg_text) + 1); - fake_arg_text[0] = '0'; - strcpy (fake_arg_text + 1, arg_text); - add_pass_two_expr (fake_arg_text, ARG_IX_IY_OFFSET, size, 0); - free (fake_arg_text); - } - free (arg_text); - break; - case '^': //bit number - has_bit_arg = true; - bit_arg_text = arg_text; - break; - case '#': - add_pass_two_expr (arg_text, ARG_RST, size, 0); - free(arg_text); - break; - } - } - } - - //if there's extra data at the end of the instruction, write that too - if (curr_instr->has_end_data && (mode & MODE_NORMAL || mode & MODE_LIST)) { - if (has_bit_arg) - add_pass_two_expr (bit_arg_text, ARG_BIT_NUM, size, curr_instr->end_data); - else - write_out (curr_instr->end_data); - } - - if (bit_arg_text) - free (bit_arg_text); - - return size; -} - - - - +#include +#include +#include +#include + +#include "spasm.h" +#include "utils.h" +#include "storage.h" +#include "parser.h" +#include "pass_two.h" +#include "opcodes.h" +#include "directive.h" +#include "preop.h" +#include "list.h" +#include "errors.h" + +#ifdef USE_BUILTIN_FCREATE +#include "expand_buf.h" +#include "directive.h" +#include "pass_one.h" +#define MAX_BUFFERS 10 +static expand_buf_t* fcreate_bufs[MAX_BUFFERS]; +#endif + +char *run_first_pass_line (char *ptr); +char *run_first_pass_line_sec (char *ptr); +char *handle_opcode_or_macro (char *ptr); +int parse_suffix (char **opcode_end); +char *match_opcode_args (char *ptr, char **arg_ptrs, char **arg_end_ptrs, opcode *curr_opcode, instr **curr_instr); +int write_instruction_data (instr *curr_instr, char **arg_ptrs, char **arg_end_ptrs, int suffix); + +bool adl_mode; +int listing_width; +const char *last_banner = NULL; +const char *built_in_fcreate = "Built-in fcreate"; + +/* + * Writes val to the output + */ + +int write_out (int val) { + + //write hex data if listing mode is on + if (mode & MODE_LIST && listing_on) { + char text[4]; + + if (pass_one && listing_width >= 4) { + listing_width = 0; + listing_offset = eb_insert (listing_buf, listing_offset, NEWLINE " ", -1); + } else if (!pass_one) { + /* If it's on the second pass, a word might + span two lines, so check if we need to skip + to the beginning of the next line */ + char buf_char = eb_get_char (listing_buf, listing_offset); + if (buf_char == '\n' || buf_char == '\r') { + while (isspace ((unsigned char) eb_get_char (listing_buf, listing_offset))) + listing_offset++; + } + } + + sprintf (text, "%02X ", val & 0xFF); + if (pass_one) + listing_offset = eb_insert (listing_buf, listing_offset, text, 3); + else { + eb_overwrite (listing_buf, listing_offset, text, 3); + listing_offset += 3; + } + listing_width++; + } + + //if (mode & MODE_NORMAL) + *(out_ptr++) = val; + + return val; +} + + +/* + * Writes listing for a single line, not + * including hex data (handled by write_out) + * or line number / program counter (handled + * in run_first_pass) + */ + +void do_listing_for_line (char *ptr) { + char *curr_line, text[32]; + + //make sure empty bytes are filled + while (listing_width < 4) { + listing_offset = eb_insert (listing_buf, listing_offset, "- ", 3); + listing_width++; + } + + //and finally, write the contents of the line + //TODO: clean up? + curr_line = skip_to_next_line (line_start); + while (curr_line < ptr) { + listing_offset = eb_insert (listing_buf, listing_offset, line_start, curr_line - line_start); + line_start = curr_line; + curr_line = skip_to_next_line (curr_line); + + old_line_num++; + sprintf (text, "%5d %02X:%04X ", old_line_num, (program_counter >> 16), program_counter & 0xFFFF); + listing_offset = eb_insert (listing_buf, listing_offset, text, strlen (text)); + } + listing_offset = eb_insert (listing_buf, listing_offset, line_start, ptr - line_start); + //make sure there's a newline char at the end + if (*(ptr - 1) != '\n') { + listing_offset = eb_insert (listing_buf, listing_offset, NEWLINE, -1); + } +} + + +/* + * Goes through the first + * pass on an mmapped file + */ + +void run_first_pass (char *ptr) { + line_num = 1; + pass_one = true; + if (mode & MODE_EZ80) { + adl_mode = true; + } + + while (!error_occurred && *ptr != '\0') { + + if (mode & MODE_LIST) { + //init some listing stuff + listing_width = 0; + line_start = ptr; + old_line_num = line_num; + listing_for_line_done = false; + + if (listing_on) { + char text[32]; + + //add the line number and program counter at the beginning of the line + sprintf (text, "%5d %02X:%04X ", line_num, (program_counter >> 16), program_counter & 0xFFFF); + listing_offset = eb_insert (listing_buf, listing_offset, text, strlen (text)); + } + } + + ptr = run_first_pass_line (ptr); + if (ptr != NULL) { + //evaluate the line + ptr = skip_to_next_line (ptr); + + //do listing stuff for this line + if (mode & MODE_LIST && listing_on && !listing_for_line_done) + do_listing_for_line (ptr); + + line_num++; + } else { + // Nothing more to read, return + break; + } + } +} + + +/* + * Parses a single line, + * returns a pointer to the + * end of the line + */ + +char *run_first_pass_line (char *ptr) { + do { + if (*ptr == '\\') + ptr++; + + //char *code_end = skip_to_line_end(ptr); + //printf("line %d: %s\n", line_num, strndup(ptr, code_end - ptr)); + //parse what's on the line + ptr = run_first_pass_line_sec (ptr); + if (ptr == NULL) + return NULL; + ptr = skip_whitespace (ptr); + + //when that's done, skip any whitespace and see if more is stuck on the end with a backslash - + // if so, keep looping until this line's done + } while (!error_occurred && *ptr == '\\'); + + return ptr; +} + + +/* + * Parses a single command/section + * on a line, returns a pointer to + * the end of the usable part + */ + +char *run_first_pass_line_sec (char *ptr) { + + if (is_end_of_code_line (ptr)) { + //if the line's blank or a comment, don't do anything with it + return ptr; + } else if (isalpha ((unsigned char) *ptr) || *ptr == '_') { + //if the first char on the line is a number, letter, or underscore, it must be a label + char *name, *label_end; + + //find the end of the label + label_end = skip_to_name_end (ptr); + if (*label_end == '(') + return handle_opcode_or_macro (ptr); + + name = strndup (ptr, label_end - ptr); + + ptr = label_end; + + if (*ptr == ':') ptr++; + +#ifdef USE_REUSABLES + if (strcmp (name, "_") == 0) { + add_reusable(); + free(name); +#else + if (0) { +#endif + } else { + //if there's a ':', either the line ends or there's an instruction after it + last_label = add_label (name, program_counter); + } + + return run_first_pass_line_sec (ptr); + } else if (isspace ((unsigned char) *ptr)) { + //if it starts with whitespace, skip that + ptr = skip_whitespace (ptr); + + if (isalpha (*ptr) || *ptr == '_') + //otherwise, it might be an instruction or macro + return handle_opcode_or_macro (ptr); + + return run_first_pass_line_sec (ptr); + } else if (*ptr == '.') { + //handle it if it's a directive + return handle_directive (++ptr); + } else if (*ptr == '#') { + //or pre-op + return handle_preop (++ptr); + } else if (*ptr == '=') { + //handle 'x = 1234' type lines + int value; + char value_str[256]; + + ptr++; + read_expr (&ptr, value_str, ""); + + if (parse_num (value_str, &value) == true) + { + if (last_label == NULL) { + SetLastSPASMError(SPASM_ERR_EQUATE_MISSING_LABEL); + } else { + last_label->value = value; + } + } + return ptr; + + } else { + SetLastSPASMError(SPASM_ERR_SYNTAX); + return ptr; + } +} + + +static define_t *search_defines_helper(const char *name_start, size_t len) +{ + char *name = strndup(name_start, len); + define_t *result = search_defines(name); + free(name); + return result; +} + +/* + * Handles an opcode or macro, + * returns the new location in + * the file + */ + +char *handle_opcode_or_macro (char *ptr) { + char *name_end; + char *name_start = ptr; + opcode *curr_opcode; + + //first get the name + name_end = skip_to_name_end (ptr); + ptr = name_end; + + //parse the suffix if possible + char *opcode_end = name_end; + int suffix = -1; + if (mode & MODE_EZ80) + suffix = parse_suffix(&opcode_end); + + //try to match it against opcodes first + curr_opcode = all_opcodes; + while (curr_opcode && curr_opcode->name) { + if (!strncasecmp (name_start, curr_opcode->name, max(strlen(curr_opcode->name), opcode_end - name_start))) + break; + curr_opcode = curr_opcode->next; + } + + //if it was found, then find the right instruction + if (curr_opcode && curr_opcode->name) { + char *arg_ptrs[3], *arg_end_ptrs[3]; + instr *curr_instr = NULL; + + //go to the start of the arguments + ptr = skip_whitespace (ptr); + + //try to match them to one of the opcode's sets of arguments + ptr = match_opcode_args (ptr, arg_ptrs, arg_end_ptrs, curr_opcode, &curr_instr); + if (curr_instr != NULL) + { + //if that worked, write data + args + int size = write_instruction_data (curr_instr, arg_ptrs, arg_end_ptrs, suffix); + + //increment program counter and stats + program_counter += size; + stats_codesize += size; + stats_mintime += curr_instr->min_exectime; + stats_maxtime += curr_instr->max_exectime; + if (MODE_EZ80) { + //increment stats further based on suffix and mode + int penalty = (suffix >= 0 ? 1 : 0); + if ((suffix < 0 && adl_mode) || suffix > 0) + penalty += curr_instr->adl_exectime_penalty; + stats_mintime += penalty; + stats_maxtime += penalty; + } + } + + } else { + //if this name doesn't match an opcode, it must be a macro (#macro OR #define) + define_t *define; +#ifdef USE_BUILTIN_FCREATE + if (!strncasecmp (name_start, "buf", name_end - name_start) && *ptr == '(') { + char buf[256]; + int value; + ptr++; + read_expr(&ptr, buf, ")"); + if (parse_num(buf, &value)) { + cur_buf = value; + } else { + char *const name = strndup(name_start, name_end - name_start); + SetLastSPASMError(SPASM_ERR_INVALID_OPERANDS, name); + free(name); + } + ptr++; + } else if (!strncasecmp (name_start, "clr", name_end - name_start) && *ptr == '(') { + expand_buf_t *eb_fcreate = fcreate_bufs[cur_buf]; + if (eb_fcreate != NULL) { + eb_free(eb_fcreate); + } + eb_fcreate = eb_init(128); + fcreate_bufs[cur_buf] = eb_fcreate; + ptr += 2; + } else if (!strncasecmp (name_start, "wr", name_end - name_start) && *ptr == '(') { + expand_buf_t *eb_fcreate = fcreate_bufs[cur_buf]; + if (eb_fcreate == NULL) { + eb_fcreate = eb_init(128); + fcreate_bufs[cur_buf] = eb_fcreate; + } + + ptr = parse_emit_string(++ptr, ES_FCREATE, eb_fcreate); + ptr++; + eb_append(eb_fcreate, NEWLINE, strlen(NEWLINE)); + } else if (!strncasecmp (name_start, "run", name_end - name_start) && *ptr == '(') { + expand_buf_t *eb_fcreate = fcreate_bufs[cur_buf]; + if (eb_fcreate == NULL) + { + SetLastSPASMError(SPASM_ERR_FCREATE_NOFILE); + } + else + { + char *fcreate_string = eb_extract(eb_fcreate); + + //make sure the listing for this line is finished up BEFORE + // the new file is parsed and writes its listing stuff all over + if (mode & MODE_LIST && listing_on && !listing_for_line_done) + do_listing_for_line (skip_to_next_line (line_start)); + + if (mode & MODE_LIST && listing_on && last_banner != built_in_fcreate) { + char include_banner[128] = "Listing for built-in fcreate" NEWLINE; + listing_offset = eb_insert (listing_buf, listing_offset, include_banner, strlen (include_banner)); + last_banner = built_in_fcreate; + } + + // Thanks for this Don + int old_line_num = line_num; + char *old_input_file = curr_input_file; + int old_in_macro = in_macro; + char *old_line_start = line_start; + int old_old_line_num = old_line_num; + curr_input_file = (char *) built_in_fcreate; + + int session = StartSPASMErrorSession(); + + run_first_pass(fcreate_string); + + curr_input_file = old_input_file; + line_num = old_line_num; + in_macro = old_in_macro; + line_start = old_line_start; + old_line_num = old_old_line_num; + + if (mode & MODE_LIST && listing_on && !listing_for_line_done) + listing_for_line_done = true; + + if (mode & MODE_LIST && listing_on && last_banner != curr_input_file) { + char include_banner[MAX_PATH + 64]; + snprintf(include_banner, sizeof (include_banner), "Listing for file \"%s\"" NEWLINE, curr_input_file); + listing_offset = eb_insert (listing_buf, listing_offset, include_banner, strlen (include_banner)); + last_banner = curr_input_file; + } + + free(fcreate_string); + eb_free(fcreate_bufs[cur_buf]); + fcreate_bufs[cur_buf] = NULL; + + if (GetSPASMErrorSessionErrorCount(session) > 0) + { + AddSPASMErrorSessionAnnotation(session, "Error during invocation of fcreate"); + ReplaySPASMErrorSession(session); + } + EndSPASMErrorSession(session); + } + ptr += 2; + } else +#endif + + if ((define = search_defines_helper(name_start, name_end - name_start))) + { + list_t *args = NULL; + char *args_end; + + //if there are arguments, parse them + int session = StartSPASMErrorSession(); + args_end = parse_args(ptr, define, &args); + + ptr = args_end; + + if (!IsSPASMErrorSessionFatal(session)) + { + in_macro++; + + //printf("args: %s\n", ((define_t *) args->data)->name); + + //see if any code is left on the line + if (!is_end_of_code_line (skip_whitespace (ptr))) { + char *line_end = skip_to_line_end (ptr); + if (define->contents == NULL) + { + SetLastSPASMError(SPASM_ERR_ARG_USED_WITHOUT_VALUE, define->name); + } + else + { + char *full_line = (char *)malloc(strlen(define->contents) + line_end - ptr + 1); + + strcpy(full_line, define->contents); + strncat(full_line, ptr, line_end - ptr); + + run_first_pass_line(full_line); + free(full_line); + } + } else { + if (define->contents == NULL) + { + SetLastSPASMError(SPASM_ERR_ARG_USED_WITHOUT_VALUE, define->name); + } + else + { + //parse each line in the macro (prefix with space) + //Buckeye: this malloc size is extra so that we can simply replace + //@params and not worry about reallocating + char *full_macro = (char *) malloc(strlen(define->contents) + 2); + char *curr_line = full_macro; + + full_macro[0] = ' '; + strcpy(&full_macro[1], define->contents); + + //char *replace_args_ptr = full_macro; + //replace_args_ptr = replace_literal_args(replace_args_ptr, define, &args); + + const char *old_filename = curr_input_file; + int old_line_num = line_num; + curr_input_file = define->input_file; + line_num = define->line_num; + + while (curr_line != NULL && *curr_line && !error_occurred) + { + char *next_line = run_first_pass_line(curr_line); + curr_line = skip_to_next_line(next_line); + line_num++; + } + + if ((mode & MODE_LIST) && listing_on && last_banner != old_filename) { + if (mode & MODE_LIST && listing_on && !listing_for_line_done) + do_listing_for_line (skip_to_next_line (line_start) ); + + listing_for_line_done = true; + + char include_banner[MAX_PATH + 64]; + snprintf(include_banner, sizeof (include_banner), "Listing for file \"%s\"" NEWLINE, old_filename); + listing_offset = eb_insert (listing_buf, listing_offset, include_banner, strlen (include_banner)); + last_banner = old_filename; + } + + curr_input_file = (char *) old_filename; + line_num = old_line_num; + + free(full_macro); + } + } + in_macro--; + } + + //clear the argument values + remove_arg_set(args); + + AddSPASMErrorSessionAnnotation(session, "Error during invocation of macro '%s'", define->name); + ReplayFatalSPASMErrorSession(session); + EndSPASMErrorSession(session); + + } else { + char *name = strndup(name_start, name_end - name_start); + SetLastSPASMError(SPASM_ERR_UNKNOWN_OPCODE, name); + free (name); + } + } + + return ptr; +} + +/* + * Attempts to parse a suffix at the end of an + * eZ80 opcode. Returns -1 if no suffix found, + * or a bitmask corresponding to the proper + * suffix. If a suffix is found, the opcode_end + * argument is set to the end of the main opcode. + */ + +int parse_suffix(char **opcode_end) { + char *suffix_ptr = *opcode_end; + char last1 = tolower(*--suffix_ptr); + if (last1 == 's' || last1 == 'l') { + char last2 = tolower(*--suffix_ptr); + if (last2 == '.') { + *opcode_end = suffix_ptr; + return (last1 == 'l' ? SUFFIX_L : 0) | (adl_mode ? SUFFIX_IL : 0); + } + if (last2 == 'i') { + last2 = tolower(*--suffix_ptr); + if (last2 == '.') { + *opcode_end = suffix_ptr; + return (adl_mode ? SUFFIX_L : 0) | (last1 == 'l' ? SUFFIX_IL : 0); + } + if (*--suffix_ptr == '.' && (last2 == 's' || last2 == 'l')) { + *opcode_end = suffix_ptr; + return (last2 == 'l' ? SUFFIX_L : 0) | (last1 == 'l' ? SUFFIX_IL : 0); + } + } + } + return -1; +} + + +/* + * Tries to match instruction + * arguments at ptr to one of + * the sets of arguments for + * curr_opcode, sets arg_ptrs + * and arg_end_ptrs to start + * and end of text of arguments, + * sets curr_instr if a match + * is found, returns new position + * in file + */ + +char *match_opcode_args (char *ptr, char **arg_ptrs, char **arg_end_ptrs, opcode *curr_opcode, instr **curr_instr) { + char *curr_arg_file = NULL; + int instr_num; + + for (instr_num = 0; instr_num < curr_opcode->num_instrs; instr_num++) { + //test each possible set of arguments for this opcode + const char *curr_arg; + int curr_arg_num = 0; + + curr_arg_file = ptr; + curr_arg = curr_opcode->instrs[instr_num].args; + + //check each character in the current argument + while (*curr_arg && !(is_end_of_code_line (curr_arg_file) || *curr_arg_file == '\\')) { + if (is_arg (*curr_arg)) { + char trash_buf[256]; + + //if this part of the argument is a number, then make sure it exists, + //save its position in the file, and skip to the next argument + if (is_end_of_code_line (curr_arg_file) || *curr_arg_file == '\\') + break; + + // if a name starts with, but is longer than, "ix" or "iy", don't match index offset + if (*curr_arg == '@' && is_name_char(*curr_arg_file)) + break; + + arg_ptrs[curr_arg_num] = curr_arg_file; + bool test = read_expr (&curr_arg_file, trash_buf, ","); + if (*(curr_arg_file - 1) == ',') + curr_arg_file--; + arg_end_ptrs[curr_arg_num] = curr_arg_file; + curr_arg_num++; + + } else { + //if this part of the argument isn't a number, and they don't match, then break + if (tolower (*curr_arg_file) != tolower (*curr_arg)) + break; + + curr_arg_file++; + } + // only skip whitespace if not in the middle of a register + if (!isalpha(*(curr_arg_file - 1)) || !isalpha(*curr_arg_file)) + curr_arg_file = skip_whitespace (curr_arg_file); + curr_arg++; + } + + //special case, allow empty string at the end to match ix/iy offset + if (*curr_arg == '@') { + arg_ptrs[curr_arg_num] = curr_arg_file; + arg_end_ptrs[curr_arg_num] = curr_arg_file; + curr_arg_num++; + curr_arg++; + } + + //see if all the arguments matched + if (!(*curr_arg) && (is_end_of_code_line (curr_arg_file) || *curr_arg_file == '\\')) + break; + } + + if (instr_num >= curr_opcode->num_instrs) { + // If the next mnemonic is the same, skip to the next group + if (curr_opcode->next != NULL && !strcasecmp (curr_opcode->name, curr_opcode->next->name)) + return match_opcode_args (ptr, arg_ptrs, arg_end_ptrs, curr_opcode->next, curr_instr); + + //if it doesn't match any instructions for this opcode, show an error and skip to line end + SetLastSPASMError(SPASM_ERR_INVALID_OPERANDS, curr_opcode->name); + + } else + *curr_instr = &(curr_opcode->instrs[instr_num]); + + curr_opcode->use_count++; + return curr_arg_file; +} + + +/* + * Writes the instruction data and arguments + * for curr_instr, with argument text start + * and end points in arg_ptrs and arg_end_ptrs + * + * Suffix is relevant for eZ80 instructions + * and may change the instruction's size, + * so the final size is returned. + */ + +int write_instruction_data (instr *curr_instr, char **arg_ptrs, char **arg_end_ptrs, int suffix) { + char *bit_arg_text = NULL; + bool has_bit_arg = false; + int i, curr_arg_num = 0; + int size = curr_instr->size; + + if (suffix >= 0) { + write_out (0x40 + suffix * 9); + size++; + } + else if (mode & MODE_EZ80) { + suffix = adl_mode ? (SUFFIX_L | SUFFIX_IL) : 0; + } + + //write the actual instruction data first + if (mode & MODE_NORMAL || mode & MODE_LIST) { + int i; + for (i = curr_instr->instr_size - 1; i >= 0; i--) + write_out (curr_instr->instr_data[i]); + } + + //then the arguments, if there are any + for (i = 0; curr_instr->args[i]; i++) { + //use the argument positions that were saved when we matched the arg strings + if (is_arg (curr_instr->args[i])) { + //first get the text of each argument + char *arg_text = strndup (arg_ptrs[curr_arg_num], + arg_end_ptrs[curr_arg_num] - arg_ptrs[curr_arg_num]); + char *fake_arg_text; + + // Check for extra parentheses (confusingly looks like indirection) + if (arg_text[0] == '(') { + int level = 1; + char *p = &arg_text[1]; + char *last = &arg_text[strlen(arg_text) - 1]; + + // Clip off ending space + while (isspace((unsigned char) *last) && last > p) + last--; + + // Search the inner chars + while (p < last && level > 0) { + if (*p == '(') level++; + else if (*p == ')') level--; + p++; + } + if (p == last) + show_warning ("Suggest remove extra parentheses around argument"); + } + curr_arg_num++; + + switch (curr_instr->args[i]) { + case '*': //16-bit number + if (suffix >= 0 && suffix & SUFFIX_IL) { + size++; + add_pass_two_expr (arg_text, ARG_NUM_24, size, 0); + } + else { + add_pass_two_expr (arg_text, ARG_NUM_16, size, 0); + } + free (arg_text); + break; + case '&': //8-bit number + add_pass_two_expr (arg_text, ARG_NUM_8, size, 0); + free (arg_text); + break; + case '%': //8-bit address offset + add_pass_two_expr (arg_text, ARG_ADDR_OFFSET, size, 0); + free (arg_text); + break; + case '@': //8-bit IX/IY offset + if (arg_text[0] != '\0' && arg_text[0] != '+' && arg_text[0] != '-') + SetLastSPASMError(SPASM_ERR_INVALID_INDEX_OFFSET); + else { + // prefix the arg with "0" so that the first "+" or "-" is + // correctly parsed as an operator, and not part of a local + // label, also handles an empty arg + fake_arg_text = (char *)malloc (1 + strlen(arg_text) + 1); + fake_arg_text[0] = '0'; + strcpy (fake_arg_text + 1, arg_text); + add_pass_two_expr (fake_arg_text, ARG_IX_IY_OFFSET, size, 0); + free (fake_arg_text); + } + free (arg_text); + break; + case '^': //bit number + has_bit_arg = true; + bit_arg_text = arg_text; + break; + case '#': + add_pass_two_expr (arg_text, ARG_RST, size, 0); + free(arg_text); + break; + } + } + } + + //if there's extra data at the end of the instruction, write that too + if (curr_instr->has_end_data && (mode & MODE_NORMAL || mode & MODE_LIST)) { + if (has_bit_arg) + add_pass_two_expr (bit_arg_text, ARG_BIT_NUM, size, curr_instr->end_data); + else + write_out (curr_instr->end_data); + } + + if (bit_arg_text) + free (bit_arg_text); + + return size; +} diff --git a/pass_two.cpp b/pass_two.cpp index 7b94102..0f47209 100644 --- a/pass_two.cpp +++ b/pass_two.cpp @@ -1,4 +1,6 @@ -#include "stdafx.h" +#include +#include +#include #include "spasm.h" #include "pass_one.h" diff --git a/preop.cpp b/preop.cpp index 8c33b0d..5b51ebc 100644 --- a/preop.cpp +++ b/preop.cpp @@ -1,4 +1,14 @@ -#include "stdafx.h" +#include +#include +#include +#include +#include +#include + +#ifdef WIN32 +#else +#include +#endif #include "preop.h" #include "spasm.h" @@ -158,7 +168,7 @@ char *handle_preop (char *ptr) { } else { - SetLastSPASMError(SPASM_ERR_STRAY_PREOP, _T("ENDIF")); + SetLastSPASMError(SPASM_ERR_STRAY_PREOP, "ENDIF"); } break; } @@ -396,43 +406,21 @@ char *handle_preop_define (const char *ptr) { * return NULL if there's no matching path */ -char *full_path (const char *filename) { - list_t *dir; - char *full_path; -#ifdef WIN32 - if (is_abs_path(filename) && (GetFileAttributes(filename) != 0xFFFFFFFF)) -#else - if (is_abs_path(filename) && (access (filename, R_OK) == 0)) -#endif - return strdup (filename); - - dir = include_dirs; - full_path = NULL; - do if (dir) { - expand_buf_t *eb = eb_init (-1); - - eb_append (eb, (char *) dir->data, -1); - eb_append (eb, "/", 1); - eb_append (eb, filename, -1); - free (full_path); - full_path = eb_extract (eb); - fix_filename (full_path); - eb_free (eb); - dir = dir->next; -#ifdef WIN32 - } while (GetFileAttributes(full_path) == 0xFFFFFFFF && dir); -#else - } while (access (full_path, R_OK) && dir); -#endif +char *full_path (const char *filename_bytes) { + std::error_code fs_err; + const std::filesystem::path filename(filename_bytes); -#ifdef WIN32 - if (GetFileAttributes(full_path) != 0xFFFFFFFF) -#else - if (access (full_path, R_OK) == 0) -#endif - return full_path; + if (filename.is_absolute() && std::filesystem::exists(filename, fs_err)) + return strdup(filename.string().c_str()); - free (full_path); + for (const list_t *dir = include_dirs; dir != nullptr; dir = dir->next) { + auto path = std::filesystem::path((const char *)dir->data) / filename; + + if (std::filesystem::exists(path, fs_err)) { + return strdup(filename.string().c_str()); + } + } + return NULL; } @@ -657,11 +645,11 @@ char *do_if (char *ptr, int condition) else { char *result = skip_until (ptr, &line_num, 3, "#else", "#elif", "#endif"); - if (line_has_word(result, _T("#else"), 5)) + if (line_has_word(result, "#else", 5)) { result = next_code_line(result) - 1; } - else if (line_has_word(result, _T("#elif"), 5)) + else if (line_has_word(result, "#elif", 5)) { result = handle_preop_if(skip_whitespace(result) + 5); } diff --git a/resource.h b/resource.h deleted file mode 100644 index f0aca8b..0000000 Binary files a/resource.h and /dev/null differ diff --git a/spasm.exe.manifest b/spasm.exe.manifest new file mode 100644 index 0000000..91a25df --- /dev/null +++ b/spasm.exe.manifest @@ -0,0 +1,10 @@ + + + + + UTF-8 + + + \ No newline at end of file diff --git a/spasm.h b/spasm.h index bc8c769..f1bfd30 100644 --- a/spasm.h +++ b/spasm.h @@ -32,15 +32,11 @@ typedef enum { } EXIT_STATUS; #ifdef _WINDOWS -#include #define NEWLINE "\r\n" #define PATH_SEPARATOR '\\' #define WRONG_PATH_SEPARATOR '/' #define strcasecmp _stricmp #define strncasecmp _strnicmp -#define snprintf sprintf_s -#define strdup _strdup - #else #define NEWLINE "\n" #define PATH_SEPARATOR '/' @@ -58,11 +54,16 @@ typedef int BOOL; //#define OUTPUT_BUF_SIZE 8000000 const static unsigned int output_buf_size = 8000000; //size of output buffer for assembled code -//make sure that MAX_PATH is max path length on *nix and Windows -#if !defined(MAX_PATH) || defined(UNIX_VER) - #include - #define MAX_PATH PATH_MAX +// TODO: all users of MAX_PATH should instead not do that, and the Windows +// application manifest declare that it's longPathAware +#ifndef MAX_PATH +#ifdef _MSC_VER +#define MAX_PATH 260 +#else +#include +#define MAX_PATH PATH_MAX #endif +#endif /* MAX_PATH */ GLOBAL unsigned int mode; GLOBAL list_t *include_dirs, *input_files; diff --git a/stdafx.cpp b/stdafx.cpp deleted file mode 100644 index 459a29a..0000000 --- a/stdafx.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// stdafx.cpp : source file that includes just the standard includes -// SPASMNew.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" diff --git a/stdafx.h b/stdafx.h deleted file mode 100644 index be013b4..0000000 --- a/stdafx.h +++ /dev/null @@ -1,164 +0,0 @@ -#pragma once - -#ifndef _STDAFX_H -#define _STDAFX_H - -#if defined(_WINDOWS) -#ifndef STRICT -#define STRICT -#endif - -#include "targetver.h" - -/* Workaround for error in Visual Studio 2015 (and newer): - * error LNK2019: unresolved external symbol ___iob_func referenced in function ___gmp_default_allocate - */ -#if _MSC_VER >= 1900 -#include -extern "C" { FILE __iob_func[3] = { *stdin,*stdout,*stderr }; } -#endif - -#ifdef SPASM_NG_ENABLE_COM -//#define _ATL_APARTMENT_THREADED -#define _ATL_FREE_THREADED - -#define _ATL_NO_AUTOMATIC_NAMESPACE - -#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit - -#define _ATL_STATIC_REGISTRY -#define ATL_NO_ASSERT_ON_DESTROY_NONEXISTENT_WINDOW -#endif - -#include "resource.h" - -#ifdef SPASM_NG_ENABLE_COM -#include -#include -#include -#include -#include - -using namespace ATL; - -// We don't have to really worry about this (non-ATL), but -// we'll include it in this #ifdef anyways. -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -//#include - -#import rename("FreeSpace", "FreeSpace2") no_namespace, raw_interfaces_only - -#include "SPASM_h.h" - -#include "gmp.h" - -// Silly workarounds for WinSDK conflicts with VS2010 Express -// (a seriously buggy release of VS...) -#ifdef SPASM_NG_ENABLE_COM -// Are we using VS2010? -#if (_MSC_VER == 1600) - -// The Chromium devs did it best, so I'll let them take over here... - -/* Copyright 2013 The Chromium Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license. - * Workaround for: - * http://connect.microsoft.com/VisualStudio/feedback/details/621653/ - * http://crbug.com/225822 - * Note that we can't actually include here because there's other - * code in third_party that has partial versions of stdint types that conflict. - */ -#include -#undef INT8_MIN -#undef INT16_MIN -#undef INT32_MIN -#undef INT64_MIN -#undef INT8_MAX -#undef UINT8_MAX -#undef INT16_MAX -#undef UINT16_MAX -#undef INT32_MAX -#undef UINT32_MAX -#undef INT64_MAX -#undef UINT64_MAX - -#endif // VS2010 check -#endif // SPASM_NG_ENABLE_COM - -#else -#include -#include -#include -#include -#include -#include -#include -#include -#ifndef NO_APPSIGN -#include -#include -#endif /* NO_APPSIGN */ -#include -#include -#include -#include - -#define __inout - -#ifdef UNIXVER -typedef unsigned int DWORD; -#else -#include -#endif -typedef const char *LPCTSTR; -typedef char *LPSTR, *LPTSTR; -typedef char TCHAR; -typedef void *LPVOID; - -#define _T(z) z - -#define _stricmp strcasecmp -#define _tcsdup strdup -#define _strdup strdup -#define sprintf_s sprintf -#define _strtoi64 strtoll - -#define StringCchPrintf(dest, size, fmt, ...) snprintf(dest, size, fmt, __VA_ARGS__) -#define StringCchVPrintf(dest, size, fmt, args) vsnprintf(dest, size, fmt, args) - -#ifdef UNIXVER -#define ARRAYSIZE(z) (sizeof(z)/sizeof((z)[0])) -#endif - -#endif -#endif diff --git a/storage.cpp b/storage.cpp index ece6b5f..ed53948 100644 --- a/storage.cpp +++ b/storage.cpp @@ -1,4 +1,6 @@ -#include "stdafx.h" +#include +#include +#include #include "spasm.h" #include "storage.h" @@ -132,14 +134,6 @@ void write_defines_callback(void *data, void *data_list) { void dump_defines_callback(void *data, void *reserved) { define_t *define = (define_t *)data; -#ifdef WIN32 - OutputDebugString(define->name); - OutputDebugString("---------\n"); - OutputDebugString(define->contents); - OutputDebugString("\n---------\n\n"); -#else - -#endif } void dump_defines() { diff --git a/targetver.h b/targetver.h deleted file mode 100644 index 90e767b..0000000 --- a/targetver.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -// Including SDKDDKVer.h defines the highest available Windows platform. - -// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and -// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. - -#include diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..0d3afbd --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,28 @@ +include(CTest) + +# A fixture that compiles the assembler so the test runner can run it +add_test( + NAME test_build_assembler + COMMAND "${CMAKE_COMMAND}" + --build "${CMAKE_BINARY_DIR}" + --config "$" + --target spasm +) +set_tests_properties(test_build_assembler PROPERTIES FIXTURES_SETUP f_build_assembler) + +# Find every .asm file and run it under the test runner +file(GLOB_RECURSE asm_files "*.asm") +foreach(asm_file ${asm_files}) + cmake_path( + RELATIVE_PATH asm_file + BASE_DIRECTORY "${CMAKE_SOURCE_DIR}" + OUTPUT_VARIABLE asm_file_relpath + ) + add_test( + NAME autotest_${asm_file_relpath} + COMMAND python ${CMAKE_SOURCE_DIR}/tests/test-runner.py $ ${asm_file} + ) + SET_TESTS_PROPERTIES(autotest_${asm_file_relpath} + PROPERTIES + FIXTURES_REQUIRED f_build_assembler) +endforeach() diff --git a/tests/bugs/issue-71-paren-eof.asm b/tests/bugs/issue-71-paren-eof.asm new file mode 100644 index 0000000..888c34f --- /dev/null +++ b/tests/bugs/issue-71-paren-eof.asm @@ -0,0 +1,3 @@ +; CHECK-NFERR: 104 +; CHECK-NFERR: 110 +b( diff --git a/tests/test-runner.py b/tests/test-runner.py index 462aa31..2e8d162 100755 --- a/tests/test-runner.py +++ b/tests/test-runner.py @@ -197,13 +197,17 @@ def run_assembler(assembler: str, infile: str, opts: str) -> Tuple[int, ByteStri proc = subprocess.Popen( [assembler] + shlex.split(opts) + [infile, outfile_name], stdin=DEVNULL, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, universal_newlines=True) + stderr=subprocess.STDOUT) pout, perr = proc.communicate() + try: + output = pout.decode('utf-8') + except UnicodeDecodeError as e: + raise ValueError('assembler output cannot be decoded as text: %s', pout) from e outfile = os.fdopen(outfile_fd, "rb") binary = outfile.read() outfile.close() - return (proc.returncode, binary, pout.split('\n')) + return (proc.returncode, binary, output.split('\n')) def filter_whitespace(s: str) -> str: diff --git a/utils.cpp b/utils.cpp index 60c5e22..86d4932 100644 --- a/utils.cpp +++ b/utils.cpp @@ -1,7 +1,8 @@ -#include "stdafx.h" - -//max depth of #defines -#define RECURSION_LIMIT 20 +#include +#include +#include +#include +#include #include "storage.h" #include "parser.h" @@ -12,6 +13,9 @@ #include "spasm.h" #include "errors.h" +//max depth of #defines +#define RECURSION_LIMIT 20 + static void destroy_char_value (label_t *label) { if (label->name) @@ -474,7 +478,7 @@ bool read_expr_impl(const char ** const ptr, char word[256], const char *delims) char *extract_arg_string(const char ** const ptr, arg_context_t *context) { - bool fReadResult = read_expr((char **) ptr, context->arg, _T(",")); + bool fReadResult = read_expr((char **) ptr, context->arg, ","); if (fReadResult == true) { if (**ptr == ',') @@ -904,7 +908,7 @@ void show_error_prefix(const char *zcif, const int zln) { //this is temporary till everything is rolled into errors.cpp WORD attr = save_console_attributes(); #ifdef _WIN32 - //TCHAR szPrefix[256]; + //char szPrefix[256]; //sprintf(szPrefix, "%s:%d: error: ", zcif, zln); //OutputDebugString(szPrefix); #endif @@ -935,10 +939,6 @@ void show_fatal_error(const char *text, ...) { if (exit_code < EXIT_FATAL_ERROR) exit_code = EXIT_FATAL_ERROR; show_error_prefix(curr_input_file, line_num); -#ifdef WIN32 - OutputDebugString(text); - OutputDebugString(TEXT("\n")); -#endif set_console_attributes (COLOR_RED); va_start(args, text); @@ -964,10 +964,6 @@ void show_warning(const char *text, ...) { if (exit_code < EXIT_WARNINGS) exit_code = EXIT_WARNINGS; show_warning_prefix(curr_input_file, line_num); -#ifdef WIN32 - OutputDebugString(text); - OutputDebugString(TEXT("\n")); -#endif set_console_attributes (COLOR_YELLOW); va_start(args, text); diff --git a/utils.h b/utils.h index 2d25844..11f6317 100644 --- a/utils.h +++ b/utils.h @@ -25,7 +25,7 @@ bool is_arg (char test); char *next_code_line (char *); char *next_expr (const char *ptr, const char *delims); #define read_expr(ptr, word, delims) (read_expr_impl((const char ** const) ptr, word, delims)) -bool read_expr_impl(__inout const char ** const ptr, char word[256], const char *delims); +bool read_expr_impl(const char ** const ptr, char word[256], const char *delims); char *extract_arg_string(const char ** const ptr, arg_context_t *context); char *parse_args (const char *ptr, define_t *define, list_t **arg_local_labels); char *replace_literal_args (const char *ptr, define_t *define, list_t **curr_arg_set); diff --git a/vcpkg b/vcpkg new file mode 160000 index 0000000..e8c2a04 --- /dev/null +++ b/vcpkg @@ -0,0 +1 @@ +Subproject commit e8c2a04eb7ca058b6e2f0e6e33c67fdbffeee846 diff --git a/vcpkg.json b/vcpkg.json new file mode 100644 index 0000000..0f98d30 --- /dev/null +++ b/vcpkg.json @@ -0,0 +1,6 @@ +{ + "dependencies" : [ + "gmp", + "pkgconf" + ] +} \ No newline at end of file diff --git a/version.h b/version.h deleted file mode 100644 index 713bf29..0000000 --- a/version.h +++ /dev/null @@ -1 +0,0 @@ -#define SPASM_NG_VERSION "v0.5-beta.3" diff --git a/version.h.in b/version.h.in new file mode 100644 index 0000000..3fa30d4 --- /dev/null +++ b/version.h.in @@ -0,0 +1 @@ +#define SPASM_NG_VERSION "@GIT_TREE_DESC@" diff --git a/version.sh b/version.sh deleted file mode 100755 index 67e975d..0000000 --- a/version.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/bash -getversion() { - if [ -f version_base.h ];then - VERSION=`cat version_base.h | head -n 1 | cut -f3 -d' ' | tr -d '"'` - else - VERSION="v0.1-alpha.1" - fi - if [ -d ".git" ]; then - test -z "$FORCE_NO_GIT" && which git 2>&1 >/dev/null - if [ "$?" = "0" ];then - git describe --exact-match --tags HEAD 2>/dev/null >/dev/null - if [ "$?" = "0" ];then - echo "$VERSION" - else - echo "$VERSION.git"`date "+%Y%m%d"` - fi - else - echo "$VERSION" - fi - else - echo "$VERSION" - fi -} - -if [ "$1" = "set" ];then - echo '#define SPASM_NG_VERSION "'`getversion`'"' > version.h - which git 2>&1 >/dev/null && git describe --exact-match --tags HEAD 2>/dev/null - if [ ! "$?" = "0" ];then - echo '#define SPASM_NG_GITREV "'`git rev-parse --short HEAD`'"' >> version.h - fi -elif [ "$1" = "dpkg" ];then - getversion | sed -r 's/^.{1}//' | sed 's/[-]/~/' | sed 's/[.]git/+git/' | sed -e ':begin;s/[.]//2;t begin' -else - getversion - which git 2>&1 >/dev/null && git describe --exact-match --tags HEAD 2>/dev/null >/dev/null - if [ ! "$?" = "0" ];then - test -z "$FORCE_NO_GIT" && echo "Git revision: "`git rev-parse --short HEAD` - fi -fi diff --git a/version_base.h b/version_base.h deleted file mode 100644 index 713bf29..0000000 --- a/version_base.h +++ /dev/null @@ -1 +0,0 @@ -#define SPASM_NG_VERSION "v0.5-beta.3"