From 7ea8d717c5931d4824bfbb4df7d1d3aa63547dcc Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Wed, 22 Oct 2025 01:00:38 +0000 Subject: [PATCH 1/2] Add FILE: line extraction logic to parse embedded C/C++ blocks from program.st - Extract FILE: lines from program.st similar to DBG: line extraction - Write extracted files to ./core directory with proper path handling - Support subdirectories (e.g., FILE:test/abc.txt -> ./core/test/abc.txt) - Remove FILE: and DBG: lines from program.st before MatIEC compilation - No fallback .blank files needed for FILE: content Co-Authored-By: Thiago Alves --- webserver/openplc.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/webserver/openplc.py b/webserver/openplc.py index 2cf416e..3c11cfe 100644 --- a/webserver/openplc.py +++ b/webserver/openplc.py @@ -5,6 +5,7 @@ import errno import time from threading import Thread, Lock from queue import Queue, Empty +import os import os.path intervals = ( @@ -123,10 +124,18 @@ class runtime: combined_lines = combined_lines.split('\n') program_lines = [] c_debug_lines = [] + file_lines = {} for line in combined_lines: if line.startswith('(*DBG:') and line.endswith('*)'): c_debug_lines.append(line[6:-2]) + elif line.startswith('(*FILE:') and line.endswith('*)'): + file_content = line[7:-2].strip() + if ' ' in file_content: + file_path, file_line = file_content.split(' ', 1) + if file_path not in file_lines: + file_lines[file_path] = [] + file_lines[file_path].append(file_line) else: program_lines.append(line) @@ -148,6 +157,12 @@ class runtime: with open('./core/debug.cpp', "w") as f: f.write(c_debug) + for file_path, lines in file_lines.items(): + full_path = os.path.join('./core', file_path) + os.makedirs(os.path.dirname(full_path), exist_ok=True) + with open(full_path, "w") as f: + f.write('\n'.join(lines)) + # Start compilation try: a = subprocess.Popen(['./scripts/compile_program.sh', str(st_file)], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) @@ -164,6 +179,12 @@ class runtime: with open('./core/debug.cpp', "w") as f: f.write(c_debug) + for file_path, lines in file_lines.items(): + full_path = os.path.join('./core', file_path) + os.makedirs(os.path.dirname(full_path), exist_ok=True) + with open(full_path, "w") as f: + f.write('\n'.join(lines)) + #Write program and debug files with open('./st_files/' + st_file, "w") as f: f.write(program) From ec3a29f28cf9d0d8d5b22c72b92528918b9e356d Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Wed, 22 Oct 2025 09:58:45 -0400 Subject: [PATCH 2/2] Fix compilation issues --- webserver/core/lib/iec_std_FB.h | 1 + webserver/openplc.py | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/webserver/core/lib/iec_std_FB.h b/webserver/core/lib/iec_std_FB.h index dfb01b7..fd25e05 100755 --- a/webserver/core/lib/iec_std_FB.h +++ b/webserver/core/lib/iec_std_FB.h @@ -1886,6 +1886,7 @@ __end: #include "communication.h" +#include "../c_blocks.h" #if defined(SEQUENT) #include "sm_cards.h" #endif diff --git a/webserver/openplc.py b/webserver/openplc.py index 3c11cfe..e00e0f8 100644 --- a/webserver/openplc.py +++ b/webserver/openplc.py @@ -129,6 +129,12 @@ class runtime: for line in combined_lines: if line.startswith('(*DBG:') and line.endswith('*)'): c_debug_lines.append(line[6:-2]) + elif line.startswith('(*FILE:c_blocks_code.cpp') and 'extern "C" void' in line: + # This is a hack to backport runtime v4 C/C++ functionality to v3. The v3 runtime needs to + # exclude all extern "C" declarations from the c_blocks_code.cpp file. I know this is not + # pretty, but v3 architecture is not pretty, so we are doing this here so that v4 code + # can remain pretty. + pass elif line.startswith('(*FILE:') and line.endswith('*)'): file_content = line[7:-2].strip() if ' ' in file_content: