Правка чужого кода

Всегда приятно, когда удаётся сделать мир чуточку лучше.

bt6hl_gpfe-ku2mxthxzdv_fsmc.png


Для одного проекта мне понадобился просмотрщик памяти в 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:\:

ngevek4aqkrpweblipu5tsccce8.png

Если просто открыть проект в компиляторе BC и попробовать собрать, то вылезет ошибка, что библиотеки не найдены, и тут начинается главная магия. Идея в том, что надо понять в какую папку был установлен компилятор у автора, чтобы пути к библиотекам в его проекте совпали с реальным их расположением, но как это сделать? Всё достаточно просто, возможно вариант не самый элегантный, но рабочий.

Первое — это нужно получить Makefile из самого проекта, делается это командой PRJ2MAK (не забываем указать пути к исполняемому файлу):

PRJ2MAK RAMVIEW.PRJ


ntii8ufq6bxlsv8p8fepbjanjuk.png

После этого у нас появится Makefile RAMVIEW.MAK, в котором уже можно посмотреть пути, где должен обитать компилятор.

npreskifqil9fzkocczqzrctpts.png

Теперь осталось перенести компилятор в папку BORLANDC и должно произойти чудо.

qpg91ktgwtsyommacofuvxzeyrg.png
Переименование папки

Запускаю компилятор, собираю и да, полный успех!

mcxwj1t9cmxki2yecwqfhn5kfng.png

Казалось бы, вот оно счастье! Программа собралась, и можно пользоваться.

После всех неочевидных манипуляций запускаю программу и вижу такую картину:

ndpr2rlqmqbpbgzbcersz_q5dr8.png

Куча мусорных символов, которые разделяют шестнадцатеричные данные, и количество символов справа меньше 16 (вылезают за пределы экрана). Связанно это с тем, что отображаемый символ не один, а три, вот он и «выдавливает» текст за пределы строки.

Ну что ж, пришла пора исправлять чужие ошибки в старой программе.

Исправление ошибок в чужом коде


Проблема достаточно банальная, автор программы писал во времена DOS, в кодировке IBM CP866, а потом исходники видимо кочевали по разным дискам, вот и потерялись различные спецсимволы, которые затем были некорректно декодированы при заливке на github.

В этом можно убедиться, если открыть Notepad++ и посмотреть исходники, то достаточно быстро можно найти подобные места:

fy-ksd063uvsyjk3yzgum-ajspa.png

8k2i6kgolmailws1vtp7h7amxoc.png
Некорректное отображение символов

Если в настройках сменить кодировку на CP866 (в моём случае это кириллица), то места станут намного более очевидными. А главное, они сразу будут узнаваемы с теми символами, что на скриншоте.

kosihloftfkswraumzaab9pdbbm.png

x8hcadxmv8kfr_m4b65isguvl70.png
Проблемные места в кодировке CP866

Всё достаточно банально, нужно просто подобрать в ASCII-кодах подходящие символы и вставить их в нужные места. Первые две «сломанные» строки — это явно вертикальный символ, а нижний — это красивая деталь разделитель рамки.

twzcrzmivevmz353yxj_v-og-9e.jpeg
Таблица ASCII — кириллица

Результатом стал выбор символа 0xB3 для вертикальной черты, и 0xBA для детали рамки.

cputs(" Version 0.1 \xb3 Copyright (c) 1997 Aurelitec");
…
cputs("\xb3 F10 = Exit");
…
strcat(buffer, " \xba");


Очень удобно редактировать код в Notepad++, а затем собирать в DOSBOX, новейшие технологии стучатся в наши двери (сарказм). После перекомпиляции получаем программу, которая выглядит и работает, так как надо:

uoupp5eg31vqdo6tldkj4gntkze.png
Область памяти с 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). Для этого нужно клацнуть по соответствующей кнопке в родительском репозитории.

lz0yldh29gfro7yrc0xpfasesuq.png
Кнопка — создание форка репозитория

7z1rqmllvojsnidmtn8bmvvush0.png
Клонирование репозитория к себе, в моём случае форк уже создан

После чего, у вас в профиле, появится такой же репозиторий с тем же именем и содержанием.
После этого необходимо в вашем локальном репозитории, который на вашем компьютере, переключить origin с адреса родительского репозитория, на ваш удалённый. Для этого нужно скопировать путь до вашего репозитория.

u-8jrbwes_-8q266ejtdwusmbpk.png

В локальном репозитории выполняем:

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».

ej73grivwo7zftteldcyos9zhvm.png

Там будет предложено выбрать удалённый репозиторий, в который нам нужно произвести слияние, по умолчанию там будет уже стоять родительский, и описание вашего запроса на слияние. В результате всех манипуляций в родительском репозитории появится запрос на слияние следующего вида:

ilk9iqikzre1ckrzjosmwqsmbay.png
Как выглядит запрос на слияние

К сожалению для меня, и к счастью для вас, владелец репозитория проигнорировал мой запрос, и вы можете его посмотреть по следующей ссылке.

На этом ваши приключения не заканчиваются, а только начинаются. Это самая интересная, может кому-то неприятная, часть заливки кода в чужеродный репозиторий.

После того как вы создали запрос на слияние, может быть несколько вариантов развития событий: игнорирование (как в этом случае), автор может отклонить ваш запрос, добавить его в основную ветку, или самый распространённый случай, написать вам замечания, которые вы должны будете исправлять.

Самое неприятное и распространённое — это исправление замечаний от владельца репозитория. Вы вносите эти изменения точно так же локально, но когда вы делаете коммит, то не создаёте новый, а добавляете изменения в старый коммит, так чтобы его hash не менялся.

Делается это следующей командой:

git commit --amend


Но git push у вас сделать не получится, потому что это вы будете вносить исправления в уже существующие коммиты на удалённом сервере. Поэтому надо его запихать туда принудительно, без предварительных ласк и грубой силой, используя опцию --force. Крайне не рекомендуется её использовать, но других вариантов я не знаю.

git push --force


Это обновит содержимое вашего репозитория, а также исправит содержание запроса на слияние у владельца.

У такого подхода есть недостаток, что стираются замечания, которые владелец вам оставил (это особенность github, у нормального gitlab таких проблем нет), так что рекомендую сохранять все замечания до финального коммита.

Выводы


sjcevsb0sjo8akpw2qlbr5nfrya.jpeg
Реальное применение исправленной программы

Достаточно часто встречаю от начинающих программистов вопрос: как мне набраться опыта в программировании? И всем им даю один и тот же ответ: идите на гитхаб и принимайте участие в каком-либо проекте. Правка чужого кода — это лучший способ научиться программировать. Поэтому настоятельно рекомендую не стесняться и делать такие правки, в худшем случае отклонят ваш запрос на слияние. В любом случае вы получите полезный опыт.

В моём случае это представляло скорее спортивный интерес, плюс мне нужна была рабочая версия программы, а сделать запрос на слияние для меня дело пяти минут.

Для тех, кому нужен исполняемый файл, вы можете его скачать у меня с диска.

Полезные ссылки:


  1. Оригинальный репозиторий.
  2. Моя исправления копия.
  3. Оформленный запрос на слияние.
  4. Готовая собранная программа.


P.S. Попробуем правила 6 рукопожатий, быть может, кто-то из вас знает владельца репозитория и попросит его посмотреть мой запрос на слияние?

p-u9l27ynelxi92bcmdxhu76ma8.png

© Habrahabr.ru