Правка чужого кода
Всегда приятно, когда удаётся сделать мир чуточку лучше.
Для одного проекта мне понадобился просмотрщик памяти в DOS. В идеале хотелось бы иметь редактор памяти, чтобы в нём был поиск по ключевым словам, перемещение к заданному адресу. Но для старта мне было бы достаточно хотя бы возможность просмотра всего мегабайта доступной «нижней» памяти.
Старожилы знают, что в комплекте с различными версиями ДОС шли дополнительные утилиты, и среди них была «замечательная» утилита debug
, которая убога чуть более, чем полностью. Ещё во времена моей молодости эта утилита вызывала у меня самые противоречивые чувства, то сейчас и подавно. Пользоваться ей без успокоительных очень сложно, с другой стороны, хорошо? что она есть. Но мне возможностей и удобства этой утилиты не хватало, поэтому пришлось искать другой подходящий инструмент. После длительного гугления наткнулся на исходники утилиты RAM View.
К сожалению, исполняемого файла найти не удалось, только исходные коды под Borland C++ 3.1
, и как впоследствии оказалось, сама программа содержала ошибки.
Всё это вылилось в интересный квест по поиску старого компилятора, исправления ошибок в программе 25-ти летней давности и создания запроса на слияние.
❯ Компиляция
Поскольку утилита поставляется только в исходных кодах, то её необходимо собрать. Как я не пытался, найти исполняемого файла мне не удалось. Поэтому придётся пройти этот тернистый путь, благо хотя бы компиляторы все в доступе.
Для того чтобы собрать и проверить эту утилиту, мне понадобится программа DOSBOX. До того как запускать коробку с ДОС, создаю папку DOS
в корне диска C, либо ~/DOS
в любимом Linux.
Перехожу в эту папку и клонирую туда этот проект:
git clone https://github.com/aurelitec/ramview.git
Сборка старых программ — это определённый квест, доступный не каждому: старые компиляторы, у которых есть свои особенности работы с ними, описанные в книгах, сданных в макулатуру. Поскольку ранее с компилятором Borland C++
дел не имел, пришлось идти в ретрочатик t.me/retrocomps и просить помощи.
Согласно описанию в гите, мне нужен Borland C++ 3.1
, который я скачал отсюда. Выбрал портабельную последнюю версию, чтобы не заниматься установкой, и распаковываю её в папку C:\DOS\BC\
.
После чего запускаю DOSBOX и монтирую локальную папку C:\DOS
, как диск C:\
:
Если просто открыть проект в компиляторе BC и попробовать собрать, то вылезет ошибка, что библиотеки не найдены, и тут начинается главная магия. Идея в том, что надо понять в какую папку был установлен компилятор у автора, чтобы пути к библиотекам в его проекте совпали с реальным их расположением, но как это сделать? Всё достаточно просто, возможно вариант не самый элегантный, но рабочий.
Первое — это нужно получить Makefile из самого проекта, делается это командой PRJ2MAK
(не забываем указать пути к исполняемому файлу):
PRJ2MAK RAMVIEW.PRJ
После этого у нас появится Makefile RAMVIEW.MAK
, в котором уже можно посмотреть пути, где должен обитать компилятор.
Теперь осталось перенести компилятор в папку BORLANDC
и должно произойти чудо.
Переименование папки
Запускаю компилятор, собираю и да, полный успех!
Казалось бы, вот оно счастье! Программа собралась, и можно пользоваться.
После всех неочевидных манипуляций запускаю программу и вижу такую картину:
Куча мусорных символов, которые разделяют шестнадцатеричные данные, и количество символов справа меньше 16 (вылезают за пределы экрана). Связанно это с тем, что отображаемый символ не один, а три, вот он и «выдавливает» текст за пределы строки.
Ну что ж, пришла пора исправлять чужие ошибки в старой программе.
❯ Исправление ошибок в чужом коде
Проблема достаточно банальная, автор программы писал во времена DOS, в кодировке IBM CP866, а потом исходники видимо кочевали по разным дискам, вот и потерялись различные спецсимволы, которые затем были некорректно декодированы при заливке на github.
В этом можно убедиться, если открыть Notepad++ и посмотреть исходники, то достаточно быстро можно найти подобные места:
Некорректное отображение символов
Если в настройках сменить кодировку на CP866 (в моём случае это кириллица), то места станут намного более очевидными. А главное, они сразу будут узнаваемы с теми символами, что на скриншоте.
Проблемные места в кодировке CP866
Всё достаточно банально, нужно просто подобрать в ASCII-кодах подходящие символы и вставить их в нужные места. Первые две «сломанные» строки — это явно вертикальный символ, а нижний — это красивая деталь разделитель рамки.
Таблица ASCII — кириллица
Результатом стал выбор символа 0xB3 для вертикальной черты, и 0xBA для детали рамки.
cputs(" Version 0.1 \xb3 Copyright (c) 1997 Aurelitec");
…
cputs("\xb3 F10 = Exit");
…
strcat(buffer, " \xba");
Очень удобно редактировать код в Notepad++, а затем собирать в DOSBOX, новейшие технологии стучатся в наши двери (сарказм). После перекомпиляции получаем программу, которая выглядит и работает, так как надо:
Область памяти с ROM BIOS
Вот, теперь всё на своих местах. Есть разделители, четыре блока по четыре байта, итого 16 символов. Справа ровно 16 символов для текста, и ничего не теряется. Программа работает именно так, как нужно.
В целом можно добавить и другой функционал, например, поиск в памяти, который есть у того же debug, но мне пока лень.
Поскольку автор предоставляет нам как лицензионную, так и просто человеческую возможность вносить изменения в свою программу:
Contributing
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
Этой возможностью мы и воспользуемся.
❯ Оформление изменений в чужой проект
Это самая главная задача, из-за которой и была написана эта статья. Мне бы хотелось, чтобы читатели не боялись создавать запросы на слияния в чужие репозитории и исправляли чужие ошибки или писали дополнения. Плюс это весьма полезный опыт для новичков.
Если попробовать закоммитить полученные изменения в репозиторий, из которого мы склонировали, то ничего не выйдет. Для этого в github есть другой механизм, по-русски называемый запросом на слияние. В gitlab он называется merge request, в github именуется pull request. Так как мне довелось достаточно долго поработать с github и gitlab, то я больше люблю за удобство gitlab, он сделан людьми для людей. Но человек ко всему привыкает и даже к таким ужасным вещам, как неочевидный интерфейс github.
Первое, что потребуется сделать — это создать ответвление от родительского проекта (fork). Для этого нужно клацнуть по соответствующей кнопке в родительском репозитории.
Кнопка — создание форка репозитория
Клонирование репозитория к себе, в моём случае форк уже создан
После чего, у вас в профиле, появится такой же репозиторий с тем же именем и содержанием.
После этого необходимо в вашем локальном репозитории, который на вашем компьютере, переключить origin с адреса родительского репозитория, на ваш удалённый. Для этого нужно скопировать путь до вашего репозитория.
В локальном репозитории выполняем:
git remote set-url origin https://github.com/dlinyj/ramview.git
Далее можно добавить все изменённые файлы, сделать коммит и затолкать изменения в наш форкнутый репозиторий.
git add
git commit -m "Fixed minor bugs with the display of symbols"
git push
И тут начинается самое интересное. Вообще, как я понимаю, можно сделать и локально запрос на слияние, но мне удобнее через web-интерфейс.
В веб-интерфейсе вашего удалённого репозитория нужно зайти «Pull requests» и там нажать кнопку «New pull request».
Там будет предложено выбрать удалённый репозиторий, в который нам нужно произвести слияние, по умолчанию там будет уже стоять родительский, и описание вашего запроса на слияние. В результате всех манипуляций в родительском репозитории появится запрос на слияние следующего вида:
Как выглядит запрос на слияние
К сожалению для меня, и к счастью для вас, владелец репозитория проигнорировал мой запрос, и вы можете его посмотреть по следующей ссылке.
На этом ваши приключения не заканчиваются, а только начинаются. Это самая интересная, может кому-то неприятная, часть заливки кода в чужеродный репозиторий.
После того как вы создали запрос на слияние, может быть несколько вариантов развития событий: игнорирование (как в этом случае), автор может отклонить ваш запрос, добавить его в основную ветку, или самый распространённый случай, написать вам замечания, которые вы должны будете исправлять.
Самое неприятное и распространённое — это исправление замечаний от владельца репозитория. Вы вносите эти изменения точно так же локально, но когда вы делаете коммит, то не создаёте новый, а добавляете изменения в старый коммит, так чтобы его hash не менялся.
Делается это следующей командой:
git commit --amend
Но git push у вас сделать не получится, потому что это вы будете вносить исправления в уже существующие коммиты на удалённом сервере. Поэтому надо его запихать туда принудительно, без предварительных ласк и грубой силой, используя опцию --force
. Крайне не рекомендуется её использовать, но других вариантов я не знаю.
git push --force
Это обновит содержимое вашего репозитория, а также исправит содержание запроса на слияние у владельца.
У такого подхода есть недостаток, что стираются замечания, которые владелец вам оставил (это особенность github, у нормального gitlab таких проблем нет), так что рекомендую сохранять все замечания до финального коммита.
❯ Выводы
Реальное применение исправленной программы
Достаточно часто встречаю от начинающих программистов вопрос: как мне набраться опыта в программировании? И всем им даю один и тот же ответ: идите на гитхаб и принимайте участие в каком-либо проекте. Правка чужого кода — это лучший способ научиться программировать. Поэтому настоятельно рекомендую не стесняться и делать такие правки, в худшем случае отклонят ваш запрос на слияние. В любом случае вы получите полезный опыт.
В моём случае это представляло скорее спортивный интерес, плюс мне нужна была рабочая версия программы, а сделать запрос на слияние для меня дело пяти минут.
Для тех, кому нужен исполняемый файл, вы можете его скачать у меня с диска.
❯ Полезные ссылки:
- Оригинальный репозиторий.
- Моя исправления копия.
- Оформленный запрос на слияние.
- Готовая собранная программа.
P.S. Попробуем правила 6 рукопожатий, быть может, кто-то из вас знает владельца репозитория и попросит его посмотреть мой запрос на слияние?