diff --git a/simplecpreprocessor.py b/simplecpreprocessor.py
index d6d025b..53da5fb 100644
--- a/simplecpreprocessor.py
+++ b/simplecpreprocessor.py
@@ -104,6 +104,7 @@ IFDEF = "ifdef"
 IFNDEF = "ifndef"
 ELSE = "else"
 SKIP_FILE = object()
+TOKEN = re.compile(r"\b\w+\b")
 
 
 class Preprocessor(object):
@@ -228,27 +229,22 @@ class Preprocessor(object):
             self.process_define(define, old_line_num)
 
     def process_source_line(self, line, line_num):
-        matches = set()
-        line = self._recursive_transform(line, matches)
+        line = self._recursive_transform(line, set())
         return line + self.line_ending
 
-    def _recursive_transform(self, line, matches):
-        original_line = line
-        new_matches = set()
+    def _recursive_transform(self, line, seen):
 
         def transform_word(match):
             word = match.group(0)
-            if word in matches:
+            if word in seen:
                 return word
             else:
-                new_matches.add(word)
-                return self.defines.get(word, word)
-        line = re.sub(r"\b\w+\b", transform_word, line)
-        matches.update(new_matches)
-        if original_line == line:
-            return line
-        else:
-            return self._recursive_transform(line, matches)
+                local_seen = {word}
+                local_seen.update(seen)
+                word = self.defines.get(word, word)
+                return self._recursive_transform(word, local_seen)
+
+        return TOKEN.sub(transform_word, line)
 
     def skip_file(self, name):
         item = self.include_once.get(name)

Macro expansion produces produces wrong results
See for details https://github.com/nanonyme/simplecpreprocessor/commit/c3a1d4617fa0977bbc0f6bd0098b2d74219489bf
diff --git a/test_simplecpreprocessor.py b/test_simplecpreprocessor.py
index 71ae36d..8a4f33b 100644
--- a/test_simplecpreprocessor.py
+++ b/test_simplecpreprocessor.py
@@ -97,6 +97,14 @@ class TestSimpleCPreprocessor(ProfilerMixin, unittest.TestCase):
         expected_list = ["(4 + (2 * x))\n", "(2 * (4 + y))\n"]
         self.run_case(f_obj, expected_list)
 
+    def test_define_indirect_self_reference_multiple(self):
+        f_obj = FakeFile("header.h", ["#define I 1\n",
+                                      "#define J I + 2\n",
+                                      "#define K I + J\n",
+                                      "I\n", "J\n", "K\n"])
+        expected_list = ["1\n", "1 + 2\n", "1 + 1 + 2\n"]
+        self.run_case(f_obj, expected_list)
+
     def test_partial_match(self):
         f_obj = FakeFile("header.h", [
             "#define FOO\n",

pip install -e .
parse_log_pytest
requirements.txt
pytest
apt-get update apt-get install -y gcc
3.6
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs==22.2.0
bleach==4.1.0
certifi==2021.5.30
cffi==1.15.1
charset-normalizer==2.0.12
colorama==0.4.5
cryptography==40.0.2
docutils==0.18.1
flake8==5.0.4
idna==3.10
importlib-metadata==4.2.0
importlib-resources==5.4.0
iniconfig==1.1.1
jeepney==0.7.1
keyring==23.4.1
mccabe==0.7.0
packaging==21.3
pkginfo==1.10.0
pluggy==1.0.0
py==1.11.0
pycodestyle==2.9.1
pycparser==2.21
pyflakes==2.5.0
Pygments==2.14.0
pyparsing==3.1.4
pytest==7.0.1
readme-renderer==34.0
requests==2.27.1
requests-toolbelt==1.0.0
rfc3986==1.5.0
SecretStorage==3.3.3
setuptools-scm==6.4.2
-e git+https://github.com/nanonyme/simplecpreprocessor.git@766d87b952e0ad6f573ce396aff41cc13521e79e#egg=simplecpreprocessor
six==1.17.0
tomli==1.2.3
tqdm==4.64.1
twine==3.8.0
typing_extensions==4.1.1
urllib3==1.26.20
webencodings==0.5.1
zipp==3.6.0

name: simplecpreprocessor
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=21.2.2=py36h06a4308_0
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - attrs==22.2.0
      - bleach==4.1.0
      - cffi==1.15.1
      - charset-normalizer==2.0.12
      - colorama==0.4.5
      - cryptography==40.0.2
      - docutils==0.18.1
      - flake8==5.0.4
      - idna==3.10
      - importlib-metadata==4.2.0
      - importlib-resources==5.4.0
      - iniconfig==1.1.1
      - jeepney==0.7.1
      - keyring==23.4.1
      - mccabe==0.7.0
      - packaging==21.3
      - pkginfo==1.10.0
      - pluggy==1.0.0
      - py==1.11.0
      - pycodestyle==2.9.1
      - pycparser==2.21
      - pyflakes==2.5.0
      - pygments==2.14.0
      - pyparsing==3.1.4
      - pytest==7.0.1
      - readme-renderer==34.0
      - requests==2.27.1
      - requests-toolbelt==1.0.0
      - rfc3986==1.5.0
      - secretstorage==3.3.3
      - setuptools-scm==6.4.2
      - six==1.17.0
      - tomli==1.2.3
      - tqdm==4.64.1
      - twine==3.8.0
      - typing-extensions==4.1.1
      - urllib3==1.26.20
      - webencodings==0.5.1
      - zipp==3.6.0
prefix: /opt/conda/envs/simplecpreprocessor

test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_define_indirect_self_reference_multiple
test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_blank_define test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_complex_ignore test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_define test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_define_indirect_self_reference test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_define_inside_ifndef test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_define_parens test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_define_simple_self_referential test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_define_undefine test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_define_with_comment test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_expand_size_t test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_extra_endif_causes_error test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_fulfilled_ifdef_define_allowed test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_fullfile_guard_ifdef_noskip test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_fullfile_guard_ifdef_skip test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_fullfile_guard_ifndef_noskip test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_fullfile_guard_ifndef_skip test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_handler_existing_file test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_handler_missing_file test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_ifdef_else_defined test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_ifdef_else_undefined test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_ifdef_file_guard test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_ifdef_left_open_causes_error test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_ifdef_unfulfilled_define_ignored test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_ifdef_with_comment test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_ifndef_else_defined test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_ifndef_else_undefined test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_ifndef_fulfilled_define_allowed test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_ifndef_left_open_causes_error test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_ifndef_unfulfilled_define_ignored test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_ignore_include_path test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_include_local_file_with_subdirectory test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_include_missing_local_file test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_include_with_path_list test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_include_with_path_list_with_subdirectory test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_lines_normalize_custom test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_lines_normalized test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_multiline_define test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_no_fullfile_guard_ifdef test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_no_fullfile_guard_ifndef test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_partial_match test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_platform_constants test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_pragma_once test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_repeated_macro test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_space_macro_indentation test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_tab_macro_indentation test_simplecpreprocessor.py::TestSimpleCPreprocessor::test_unexpected_macro_gives_parse_error
simplecpreprocessor.py
simplecpreprocessor.py