Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- @ECHO off
- setlocal ENABLEDELAYEDEXPANSION ENABLEEXTENSIONS
- rem Глобальные переменные
- rem Набор выводимых символов. Символы, вывод которых вызывал ошибки исполнения cmd заменены символом "."
- set char=".#$...'()*+,-./0123456789.....?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]._`abcdefghijklmnopqrstuvwxyz{.}~_"
- rem Размер maxmem можно поставить 30000 ячеек памяти, но тогда инициализация идет очень долго.
- set maxmem=100
- echo Brainfuck Interpreter
- echo.
- IF "%1" NEQ "" GOTO :init
- echo Usage: %~nx0 file.bf
- goto :eof
- :init
- rem Инициализируем память.
- call :array create mem %maxmem% 0
- set mp=0
- set sp=0
- set cp=0
- rem читаем программу в память
- set work_file=%1
- set bf_prog=
- FOR /F "eol=c delims=*" %%I IN (%work_file%) DO SET bf_prog=!bf_prog!%%I
- rem узнаем длину программы
- Echo.%bf_prog%>"%TEMP%\%~n0.tmp"
- For %%i In ("%TEMP%\%~n0.tmp") Do Set /A bf_len=%%~zi-2
- rem Выводим тест, что программа работает, а не зависла.
- echo Executing programm
- echo %bf_prog%
- echo.
- rem рабочий цикл
- :work
- set cop=!bf_prog:~%cp%,1!
- if "%cop%" == "+" (
- call :array get mem %mp% tmp
- set /a tmp += 1
- if "!tmp!" == "256" set tmp=0
- call :array set mem %mp% !tmp!
- ) else if "%cop%" == "-" (
- call :array get mem %mp% tmp
- set /a tmp -= 1
- if !tmp! LSS 0 set tmp=255
- call :array set mem %mp% !tmp!
- ) else if "%cop%" == ")" (
- set /a mp +=1
- if !mp! == %maxmem% set mp=0
- ) else if "%cop%" == "(" (
- set /a mp -=1
- if !mp! == -1 set /a mp=%maxmem% - 1
- ) else if "%cop%" == "," (
- call :comma
- ) else if "%cop%" == "." (
- call :array get mem %mp% tmp
- call :Echochr !tmp!
- ) else if "%cop%" == "[" (
- call :array get mem %mp% tmp
- if "!tmp!" == "0" (
- call :skip1
- )
- ) else if "%cop%" == "]" (
- call :array get mem %mp% tmp
- if "!tmp!" NEQ "0" (
- call :skip2
- )
- )
- set /a cp += 1
- if %cp% == %bf_len% goto :exit
- goto :work
- :skip1
- :w11
- set /a cp += 1
- if %cp% == %bf_len% (
- call :err_print "] not found"
- goto :exit
- )
- set cop=!bf_prog:~%cp%,1!
- if "%cop%" == "[" (set /a sp +=1)
- if "%cop%" == "]" if %sp% NEQ 0 (set /a sp -=1) else (goto :w12)
- goto :w11
- :w12
- exit /b 0
- :skip2
- :w21
- set /a cp -= 1
- if "%cp%" LSS "0" (
- call :err_print "[ not found"
- goto :exit
- )
- set cop=!bf_prog:~%cp%,1!
- if "%cop%" == "]" (set /a sp +=1)
- if "%cop%" == "[" if %sp% NEQ 0 (set /a sp -=1) else (goto :w22)
- goto :w21
- :w22
- exit /b 0
- :comma
- rem Не реализованно
- exit /b 0
- rem ==========================================================================
- rem Процедура echochr
- rem Эмуляция функции chr()
- rem ==========================================================================
- :echochr
- if %1==10 echo.
- if %1==13 echo.
- if %1==32 <nul set /p strTemp="_"
- if %1 GTR 32 (
- set /a code=%1 - 32
- for /f %%t in ('cmd /c "echo %%char:~!code!,1%%"') do <nul set /p strTemp="%%t"
- )
- exit /b 0
- rem ==========================================================================
- rem Процедура debug
- rem Печать состояния переменных и памяти
- rem ==========================================================================
- :debug
- call :array get mem %mp% tmp
- echo cp=%cp%, mp=%mp%, cop=%cop%, mem[mp]=%tmp%
- rem pause
- exit /b 0
- rem ==========================================================================
- rem ==========================================================================
- rem Процедура EchoWithoutCrLf
- rem %1 : текст для вывода.
- rem ==========================================================================
- :EchoWithoutCrLf
- <nul set /p strTemp="%~1"
- exit /b 0
- rem ==========================================================================
- rem ==========================================================================
- rem Процедура err_print
- rem Печать кода ошибки. Создание дампов работы.
- rem ==========================================================================
- :err_print
- echo Error on %cp% position.
- echo %1
- echo.
- echo cp: %cp% >register.dmp
- echo mp: %mp% >>register.dmp
- echo sp: %sp% >>register.dmp
- call :array save mem memory.dmp
- exit /b 0
- rem ==========================================================================
- rem ===== Arrays =====
- rem Важно помнить, что после каждого вызова функции удаляются все переменные, начинающиеся на __
- :array
- rem Сохранение аргументов в локальных переменных
- rem чтобы можно было обращать отложенным методом !__1!
- rem ~ - убрать кавычки
- set __1=%~1
- set __2=%~2
- set __3=%~3
- set __4=%~4
- set __5=%~5
- set __6=%~6
- rem == create ==
- rem Создание массива
- rem call :array create имя_массива [размер=0] [начальные значения=0]
- if /I "!__1!"=="create" (
- rem Имя массива
- if "!__2!"=="" (
- echo Не указано имя массива
- goto :eof
- )
- set _name=array_!__2!
- rem Размер
- set /a _count=0
- if not "!__3!"=="" (
- set /a _count = !__3!
- )
- rem Начальные значения
- set _defval=0
- if not "!__4!"=="" (
- set _defval=!__4!
- )
- rem Удаление массива, если существует c таким же именем
- rem Можно было не удалять все переменные, а только оставшиеся после перезаписи, но может быть как-нибудь потом
- call :array_del_ifdef !__2!
- set /a __maxindex=!_count!-1
- for /l %%i in (0,1,!__maxindex!) do set !_name!_%%i=!_defval!
- set /a !_name!_count = !_count!
- set _name=
- set _count=
- set _defval=
- rem == get ==
- rem Получение элемента массива (сохранение в переменную)
- rem call :array get имя_массива [index=0] [имя_целевой_переменной=_l]
- rem Если индекс отрицательный, то он считается с конца (-1 - последний, -2 - предпоследний и т.д.)
- ) else if /I "!__1!"=="get" (
- rem Имя массива
- if "!__2!"=="" (
- echo Не указано имя массива
- goto :eof
- )
- set __name=array_!__2!
- rem Проверка существования массива
- call :array_notdefined !__2! __errors
- rem Если есть ошибки, то выходим
- if not !__errors!==0 goto :eof
- rem Индекс элемента
- set /a __i = 0
- if not "!__3!"=="" (
- set /a __i = !__3!
- )
- rem Если индекс отрицательный, то считаем с конца
- if !__i! LSS 0 (
- rem Получаем размер
- call :set __count !__name!_count
- set /a __i=!__count!+!__i!
- )
- rem Имя переменной, содержащей значение элемента
- set __target=!__name!_!__i!
- rem Проверка существования элемента
- if not defined !__target! (
- echo В массиве !__2! нет элемента с индексом !__i!
- goto :eof
- )
- rem Записываем значение элемента во временную переменную
- call :set __value !__target!
- set __var=_l
- if not "!__4!"=="" (
- set __var=!__4!
- )
- rem Записываем в целевую
- call :set !__var! __value
- rem == list ==
- rem Вывод значений списком. Может быть полезно при перенаправлении вывода
- rem call :array list имя_массива
- rem Пример: call :array list myArr > array.txt - сохраняет текущий массив в файт array.txt
- rem Для сохранения в кодировке cp1251 используйте save
- ) else if /I "!__1!"=="list" (
- rem Имя массива
- if "!__2!"=="" (
- echo Не указано имя массива
- goto :eof
- )
- rem Проверка существования массива
- call :array_notdefined !__2! __errors
- rem Если есть ошибки, то выходим
- if not !__errors!==0 goto :eof
- set __name=array_!__2!
- rem Получаем размер
- call :set __count !__name!_count
- set /a __maxindex=!__count!-1
- rem Вывод значений
- for /l %%i in (0,1,!__maxindex!) do (
- call :set __value !__name!_%%i
- echo !__value!
- )
- rem == save ==
- rem Сохраняет массив в указанный файл в кодировке cp1251
- rem call :array save имя_массива имя_файла
- ) else if /i "!__1!"=="save" (
- rem Имя файла
- if "!__3!"=="" (
- echo Не указано имя файла
- goto :eof
- )
- rem Парсим вывод команды chcp, ищим номер кодовой страницы и запаминаем
- for /f "usebackq tokens=2 delims=:" %%i in (`chcp`) do set /a _pageset=%%i
- rem Меняем кодовую страницу на 1251
- chcp 1251>nul
- rem Перенаправляем вывод list в файл
- call :array list !__2! > !__3!
- rem Возвращаем кодовую страницу
- chcp !_pageset!>nul
- set _pageset=
- rem == set ==
- rem Присвоение значения элементу
- rem call :array set имя_массива индекс значение
- ) else if /I "!__1!"=="set" (
- if "!__4!"=="" (
- echo Не указано значение. Значение не может быть пустым
- goto :eof
- )
- rem Сохраняем параметры, для того, чтобы после вызова get они не потерялись
- set _name=array_!__2!
- set /a _i=!__3!
- set _value=!__4!
- rem Получение значения обеспечивает нам проверку параметров
- rem Важно. После операции все локальные переменные (__*) очищаются
- call :array get !__2! !__3! _localresult
- rem Если результат get существует, то удаляем элемент
- rem Сообщения об ошибках в противном случае покажет сам get
- if defined _localresult (
- set !_name!_!_i!=!_value!
- )
- set _localresult=
- set _name=
- set _i=
- set _value=
- )
- call :clear_local
- goto :eof
- rem Копирует значение одной переменной в другую
- rem Плюс в том, что имя переменной, значение которой извлекается, может быть составным
- rem call :set имя_целевой_переменной имя_переменной_содержищее_значение
- :set
- set %~1=!%~2!
- goto :eof
- rem Удаление локальных переменных (начинаются с __)
- :clear_local
- rem Устанавливаю переменную __, чтобы set __ не возвращал "Переменная среды __ не определена"
- set __=0
- for /F "usebackq delims==" %%i in (`set __`) do set %%i=
- goto :eof
- :array_del_ifdef
- call :array_notdefined %1 __array_del_ifdef_result H
- if !__array_del_ifdef_result!==0 call :array delete %1
- goto :eof
- rem Проверка существования массива
- :array_notdefined
- rem Устанавливаем имя целевой переменной
- set __var=_l
- rem Тихая проверка - не выводить сообщение
- set __hide=0
- if not "%2"=="" (
- set __var=%2
- )
- if /i "%3"=="h" (
- set __hide=1
- )
- if not defined !__var! set /a !__var!=0
- rem Проверка существования переменной, содержащей размер
- if not defined array_%~1_count (
- if not !__hide!==1 echo Массив %~1 не определен
- set /a !__var!+=1
- )
- goto :eof
- :exit
- rem сохраняем дамп памяти
- call :array save mem memory.dmp
- echo.
- pause
- ENDLOCAL
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement