Просмотр сообщений

В этом разделе можно просмотреть все сообщения, сделанные этим пользователем.


Сообщения - X512

Страницы: 1 2 [3]
31
Общий раздел / Re: Component Pascal vs Oberon-07
« : Январь 14, 2013, 07:27:00 am »
Во-вторых у того же msp430 есть 20ти битная адресация памяти. Память остается плоской. Мегабайт ннада? :-)
Тогда это в принципе уже можно считать 32-х битной архитектурой. Указатели там сколько бит занимают?
...кстати посмотрел я этот msp430. Набор инструкций довольно простой, думаю несложно будет компилятор написать. Только у меня этого микроконтроллера к сожалению нет, а эмулятор неинтересно.
Это будет гарантированно работать везде и всегда. А вот что выбрать в КП? :-)
INTEGER разумеется :)
Хотя возможно действительно стоит объявить тип, аналогичный size_t(как я писал ранее про Host.Int) в Си. Тогда его можно будет использовать в качестве индекса массива для гарантии полного покрытия на 64-х битных архитектурах.

Большенство программ пользуется автотулзами например, которые проверяют при configure параметры платформы, наличие нужных библиотек, свойств ОС и так далее. Если configure отработало нормально, значит с очень большой вероятностью, все будет ОК.
Не говорите мне про этот ужас. Я с ним под Haiku намучился. Если под Haiku есть проблемы, то представляю какие серьёзные будут проблемы с микроконтроллерами.

А теперь я прошу доказать тезис, что любой Обероновский (в том числе любого Оберона) код будет гарантированно работать и работать везде одинаково.
А чего тут доказывать; спецификация оберонов чётко описывает все детали, критичные для исполнения. В отличии от Си там нет "undefined behavior". Другое дело, что не каждый компилятор соответствует спецификации. Например компилятор BlackBox'а содержит несколько критичных для безопасности багов и некорректно реализует логику оператора WITH.

Никто не мешает. Просто жалко памяти :-) КПД 50, а тои 25% это как-то маловато будет.
А какая разница объявить целое как INTEGER или LONGINT если всё равно логика программы работает только в диапазоне INTEGER'а. Из-за выравнивания КПД в любом случае будет низким.

Ни то ни другое не является вменяемой заменой. Просмотреть экспорт - там не будет комментариев и некоторых милых нюансов, которые в рукописной спеке всегда видны. То есть это тупо машинная выдача.
Скопируйте эту выдачу в документацию и напишите какие хотите комментарии.

С тем же успехом я могу просматривать експорты dll и на основе этого пытаться писать приложение.
Не можете. Там нет информации о типах, именах аргументов процедур и т. д.

А документация на модуль (писаная человеком) во-первых не всегда есть
Header с комментариями - это уже по сути документация. Некоторые программы типа Doxygen'а даже умеют по ним HTML документацию с навигацией составлять.

, во-вторых устаревает, в-третьих она НИКАК не согласована с реальной реализацией. Очередной источник ошибок. Спасибо, я как-нибудь с хедерами (а лучше - с Адскими спеками на пакет)
Извините, но если вы не можете согласовать документацию с кодом, то у вас плохая организация разработки. Оберон тут не виноват. Я конечно понимаю, что у каждого свой подход к разработке, но...

Рукотворный костыль. Тем более что он работет только в ББ, а мы про язык говорим.
Если вам угодно, можете настроить выделение жирным шрифтом идентификаторов со "*" в каком-нибудь Notepad++ или как ваш любимый редактор/IDE называется.

Ну, поэтому и появилась например scala и kotlin. Особенно прекрасен последний (ибо скала все же тяжеловата для восприятия).
Т. е. синтаксис оберона всё же лучше Java?

Они там по сути пулы делают. С рукопашным убиением пулов.
Они же не так делаются...

java-приложения грузятся во-первых не полторы минуты
Лично видел. Простая графическая Java-программа в Windows грузилась очень долго. Вообще Java в Windows выглядит и работает как-то криво и инородно.

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

Обероны вообще и КП в частности, в наше время не являются безопасными языками. Безопасный это haskell например. А лучше - Agda.
Component Pascal сам по себе формально является чисто безопасным ЯП. Модуль SYSTEM - это BlackBox-специфичное расширение языка, не имеющее к Component Pascal'ю никакого отношения. Также как говорилось выше компилятор BlackBox содержит критические уязвимости, позволяющие написать эксплоит и обойти защиту.

...и в С++, если нужно безопасно, то можно сделать безопасней чем в Обероне.
В С++ не может формально считаться безопасным, т. к. там допустима арифметика указателей и небезопасное управление памятью.

Насколько я помню, в КП нет модуля Meta. Так что и проблемы нет :-)
Вообще в сообщении о языке написано:
Цитировать
Appendix D: Mandatory Requirements for Environment
...
3) Modules and at least their exported procedures (commands) and exported types must be retrievable dynamically. If necessary, this may cause modules to be loaded. The programming interface used to load modules or to access the mentioned meta information is not defined by the language, but the language compiler needs to preserve this information when generating code.
Except for fully linked applications where no modules will ever be added at run-time, a linking loader for modules is required. Embedded systems are important examples of applications that can be fully linked.
Хотя в конце сказано, что для слинкованных модулей (как раз случай для микроконтроллеров) допускается исключить эту информацию. Так что ООП и RTTI Component Pascal'я можно смело использовать в микроконтроллерах.

Ну, ладно, не удачный пример. Пусть будет АВЛ-дерево. Или красно-черное.

Да что там, можно и по алгоритмам пройтись. Например сортировки. Обогнать стандартную шаблонную с++-сортировку очень сложно. То есть реализовав одну из стандартных сортировок (из книжки Вирта например) его не обогнать.
Вы часто в своём коде этим пользуетесь напрямую? В BlackBox вообще сложнее Shell-sort(сортировка ключей строковых ресурсов) да бинарного поиска(поиск имён символов при импорте) я алгоритма не нашёл. При этом BlackBox работает весьма шустро.

32
Общий раздел / Re: Машинный код x86
« : Январь 14, 2013, 05:42:32 am »
1. В Интеле 3 режима: 16-битный, 32-битный, 64-битный.
Мне нужен 32-х битный режим.

2. Коды - это не самое сложное. В какой оси хотите работать? От этого зависит структура объектного-исполняемого файла.
У меня проблема именно с кодами. Формат у меня будет свой, похожий на формат BlackBox'а. С этим проблем нет. Я уже писал свой загрузчик модулей PE и ocf(Oberon Code File, формат скомпилированных модулей BlackBox-а), ничего сложного там нет. Работать предполагается в Windows и Haiku.

3. Гораздо проще перевести в программу на ассемблере и запустить уже стандартный механизм формирования исполняемого модуля.
Мне нужно генерировать машинный код напрямую. Руководств и примеров написания компиляторов в ассемблер в сети видел много, а вот с машинными кодами не густо. Нашёл только TCC.

33
Общий раздел / Машинный код x86
« : Январь 14, 2013, 04:38:00 am »
У меня давно уже есть идея написать компилятор обероноподобного языка. Как писать лексер и парсер в принципе понятно, но где брать информацию о машинном коде x86 не совсем. Где можно найти информацию о генерации кода для x86? Документации Intel - слишком сложно, я на ассемблере почти не писал. Пока у меня есть своя стековая виртуальная машина и ассемблер для неё; программы выглядят как-то так
PROCEDURE^ Sort (8)

PROCEDURE Main
VAR a, len, i (* все переменные только INTEGER *)
CODE
STK a ->
5345235 -436  235 235 4 -53254 235 23 34 -325 342 523 35523 (* массив для сортировки *)
STK a& - 4 DIV len ->
a& PRINT len& PRINT -10000 PRINT
a& len& Sort!
0 i ->
:l i& len& < e?
a& i& 4 * + ^ PRINT
i& 1 + i ->
l@
:e
END Main

(*
Спецификация ассемблерного кода ниже
PROCEDURE Sort(VAR a: ARRAY OF INTEGER);
VAR i, j: INTEGER; x, t: INTEGER;
BEGIN
i := 0; j := LEN(a)-1;
x := a[(LEN(a)-1) DIV 2];
REPEAT
WHILE a[i] < x DO INC(i) END;
WHILE x < a[j] DO DEC(j) END;
IF i <= j THEN
t := a[i]; a[i] := a[j]; a[j] := t;
INC(i); DEC(j)
END
UNTIL i > j;
IF 0 < j THEN Sort(SPLIT(a, 0, j+1)) END;
IF i < LEN(a)-1 THEN Sort(SPLIT(a, i, LEN(a))) END
END Sort.
*)

PROCEDURE Sort(len, a)
VAR i, j, x, t
CODE
0 i -> len& 1 - j ->
len& 1 - 2 DIV 4 * a& + ^ x ->
:l1 a& i& 4 * + ^ x& < l2?
i& 1 + i ->
l1@
:l2 x& a& j& 4 * + ^ < l3?
j& 1 - j ->
l2@
:l3 i& j& <= l4?
a& i& 4 * + ^ t ->
a& j& 4 * + ^ a& i& 4 * + =>
t& a& j& 4 * + =>
i& 1 + i ->
j& 1 - j ->
:l4 i& j& > l1?
0 j& < l5?
a& j& 1 + Sort!
:l5 i& len& 1 - < l6?
i& 4 * a& + len& i& - Sort!
:l6
END Sort
SPLIT(array: ANYARR; beg, end: INTEGER): ANYARR - это встроенная функция моего языка для выделения подмассива.

34
Общий раздел / Re: Component Pascal vs Oberon-07
« : Январь 14, 2013, 04:27:02 am »
Кстати, а какая разница с точки зрения языка, какая там модель памяти у машинки внизу? Вроде бы в сообщении о языке ничего об этом не говорится.
Проблема в том, что адресуемой 16-ю битами памятью не достаточно для сложных приложений (ОС, GUI). Поэтому для реализации Component Pascal для 16bit x86 потребуется специальный runtime, который будет подгружать и отгружать неиспользуемые сегменты, код; управлять дескрипторами и т.д. (см. описание работы Windows 1.0 - 2.0). Многие указатели будут на самом деле дескрипторами. Без всего этого BlackBox'у просто не хватит памяти.

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

Не для всякой переменной, а создавая свои типы. Переменных одного типа, как понимаешь, может быть множество.
Что мне выбрать для счётчика массива?

У Си, равно как и у С++,  давно уже другой подход. И он лучше чем в КП, и тем более чем в Oberon-07/11.
Всё равно большинство программ этим не пользуются. При портировании код придётся тщательно тестировать и править при необходимости. Обероновский же код будет гарантированно работать везде и везде одинаково.

Затрудняюсь ответить (то есть прямо сейчас по полочкам не разложу). Но в принципе, могу сказать какие проблемы бывают на АРМе с 16тью битами - выравнивание. Данные должны быть выровнены, и доступ к 16ти битной переменной идет медленней чем к 32битной. Соответственно на 64битах относительно 32бит может быть то же самое.
Кто мешает выравнивать 4-х байтные целые до 8-ми байт? Спецификация языка не требует, чтобы размер записей был равен сумме содержимого.
Кстати у компиляторов Microsoft'а для AMD64 стандартный размер int равен 4-ём байтам.

Нет. То есть модулей конечно же нет в явном виде. Но попробуй, пожалуйста, получить вот в данной программе из другой единицы компиляции к переменной foo:
// Foo.c
static int foo = 42;

Замечу, что это даже не С++, а просто Си.
Если бы не static, то можно было бы через extern... Но всё же такая система модулей однозначно хуже обероновской.
Потому, что становится невозможным specification driven development. Что бывает очень полезно. Особенно в больших проектах. Да и библиотеки которые написаны в таком стиле читать/разбираться намного приятней.

Побыстрому что-то накидать конечно удобней в стиле без спецификации отдельно.

Впрочем, этим грешат многие (чуть ли не все) новоделы. Та же java например, с#, go, D и так далее. Свет в окошке только Ада да Haskell.
Во-первых в BlackBox можно просматривать экспорт любого модуля, а во-вторых для specification driven development есть документация на модуль. В её начале есть definition модуля, потом общее описание и описание экспортированных символов. По-хорошему нужно писать документацию для каждого модуля; в ряде случаев выгоднее писать сначала документацию, потом реализацию. Из BlackBox'а легко смотреть описание на символ, достаточно его выделить и нажать Alt I, D.

Но в java,c# и Go это все частично компенсируется IDE, а вот в КП и D - нет. Увы-с. С таким работать не приятно.
И какие конкретно функции там есть?

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

Да, к тому же, длинное слово вроде public в С++ не требуется писать перед КАЖДОЙ сущность в структуре/классе. Таким образом, если у нас есть группа экспортируемых сущностей числом больше шести, то по лаконичности С++ начинает выигрывать. А по наглядности он выигрывает сразу.
Я про Java'у думал. Там public static final в порядке вещей (мог что-то напутать).

Оно бы нагружало сборщик мусора, если бы реализация была бы наивной. Но она не такова, и в ряде случаев "объекты" будут на стеке. А сборщик мусора c поколениями в КП настолько не нужен, что народ аж переходит на ручное управление памятью :-) Как раз вот свеженькая темка в тему:  http://forum.oberoncore.ru/viewtopic.php?f=23&p=77104

Которое повышает вероятность утечек, ведь это не С++ и умный указатель тут не сделаешь.
Чего-то не понял, что они там делают.
Относительно оптимизаций: они работают не стабильно, иногда они не возможны, у каждой JVM свои. Оптимизации во время исполнения снижают скорость исполнения кода, в результате чего программы на Java'е полторы минуты грузятся.

Да, текущая система размещения записей не через NEW() не идеальна, но похоже это лучшее, что есть в безопасных ЯП.

Наврятли. На микроконтроллерах обычно тормозит например умножение и работа с плавающей точкой. А RTTI там противопоказан не из соображений производительности обычно, а из соображений экономии ОЗУ. На минуточку - у тебя 8 КБ на ВСЁ. Вообще все! Причем 8 Кб ОЗУ - это достаточно жирный микроконтроллер.

Я гонял приложение на c++11 (с лямбдами и прочим) на микроконтроллере с 512 байтами ОЗУ.
Дескрипторы типов не такие уж и большие, к тому же их можно урезать в конкретной реализации (например до 4-х уровней наследования). Естественно не генерировать никаких дескрипторов, если тип не расширяемый или известен во время компиляции. Если не нужен модуль Meta (доступ к символам во время выполнения), то можно не сохранять имена символов и типы полей записей.

А что-то хитрее тоже не сложно организовать? Скажем B-tree?
Здесь как раз обероновский подход оправдан. B tree - это специфическая дисковая структура данных для ускорения доступа к большому объёму данных по ключу. Её реализация будет только в каком-то одном внутреннем модуле БД и она будет оптимизирована под структуру этой БД. К тому же формат БД публичен и требуется работать с определённым форматом.

35
Общий раздел / Re: Component Pascal vs Oberon-07
« : Январь 14, 2013, 01:53:36 am »
Гм. Проблема наверно больше в модели программирования, в тех умолчаниях которые люди используют в своих программах.
То есть по умолчанию для ВСЕХ целочисленных переменных скорее всего будет использован всегда INTEGER, просто потому что это наиболее естественно. Скажем в Aде это будет не так, там принято под каждый тип переменных создавать свой диапазонной целочисленный тип.
Большинство современных программ в здравом уме сейчас на 16-битных процессорах запускать не будет. К тому же размеры целых типов - не единственная проблема. На таких процессорах кардинально другая система управления памятью с сегментами и дескрипторами.

Указывать диапазоны это конечно выглядит правильно, но довольно неприятно для всякой переменной указывать размер. Пусть лучше будет 4 байта, всё равно новый врятли будут запускать на 8-и и 16-ти битной машине. К тому же вероятно для таких машин могут потребоваться и другие изменения.

Подход Си в неопределённости размеров целых чисел неудачен, т. к. может нарушить логику работы программы на разных процессорах.

Таким образом КП-программа оказывается эффективной только на 32битной машине. Работа с 32битами не эффективна на машинах с меньшей битностью, и на ряде машин с бОльшей битностью.
В чём проблема с 4-х байтными целыми на AMD64?
Это есть и в java и в С++. Подозреваю, что в C# тоже есть.
В них можно получать полный доступ ко всем переменным внутри модуля (безо всяких friend и прочих костылей)? В них можно объявить класс, который может создать только модуль, который его объявил (безо всяких костылей типа объявления пустого класса и его расширения неэкспортированным классом). В С++ модульности вообще нет. Экспортируется всё. Инкапсуляция только на уровне классов.
Также в Component Pascal'е очень удобно, то, что не надо писать никаких definition'ов и header'ов. Компилятор это делает автоматически. Некоторые почему-то видят в этом недостаток, не знаю почему. Удобен метод экспортирования символов - просто ставишь "*" и всё. и никаких длинных слов вроде "public".
Ещё Java не умеет работать с неуказательныим классами, там они все только POINTER TO RECORD. Это повышает нагрузку на сборщик мусора и снижает эффективность работы. Для Component Pascal'я сборщик мусора с поколениями не нужен, поэтому память работает быстрее.

Но опять же, нужно очень сильно постараться, чтобы именно проверка типов в message bus'e стала бутылочным горлышком. Пожалуй такое возможно только на синтетических тестах.
Для микроконтроллеров вполне себе может стать. Высокая эффективность проверки типа позволяет использовать RTTI даже на микроконтроллерах.

А скажи пожалуйста, чем микроконтроллер на MSP430 с ОЗУ в 18 Кб менее полноценен, чем ARM (ARM7TDMI) с 8 Кб ОЗУ?
Если и там и там можно динамически загрузить модуль в ОЗУ и исполнить его оттуда, то ничем. Для меня загрузка модулей - один из основных критериев "полноценности" процессора.

Теперь про преимущества Oberon-07/11, то есть не в плане микроконтроллеров, а в принципе. Говорить буду за себя: дело в том, что текущая сфера где работает КП (в основном Windows) мне не слишком интересна, и я не вижу там особых прорывных перспектив. Мне интересны новые области, где Оберонов пока нет вообще, кроме того, там нет или почти нет и конкурентов на дОлжном уровне. С Обероном-07/11 туда взобраться намного проще, просто за счет того, что он легче в реализации. После того, как и если туда заберется Оберон-07, можно потихоньку туда же подтянуть и КП например.
Какие преимущества у Oberon-07/11 перед C/C++ кроме идеологии и простоты построения компилятора? Си же вроде для любого микроконтроллера есть...

Да, но для реальной юзабельности КП жутко не хватает способа создавать нормальные контейнеры. То есть там шаблонов, дженериков, модулей с параметрами-типами или чего-то еще подобного. Скажем в Go этого тоже нет и это ЖУТКО не удобно. И у них в TODO стоит решить эту проблему. У всех остальных современных языков со статической типизацией эта проблема решена (так или иначе).
Смотрю я код BlackBox'а и думаю: видимо это идеология оберона такая писать контейнеры каждый раз свои для каждого объекта. Принципе это не сложно организовывать связные списки и т.п.. К тому же это позволяет адаптировать контейнеры под применение объектов и повысить эффективность. При использовании шаблонов можно запросто написать крайне неэффективный код, не зная особенностей реализации (например один раз открывал большой RTF в Haiku и так и не дождался пока он откроется; оказывается там строковой буфер очищался удалением каждого символа с начала; у себя локально исправил проблему).

37
Общий раздел / Component Pascal vs Oberon-07
« : Январь 14, 2013, 12:25:13 am »

38
Нет. У КП гвоздями прибиты типы к jvm. Как оно будет жить на 64битной машине? А на 16ти битной?
А в чём проблема? В документации чётко определено что BYTE, SHORTINT, INTEGER и LONGINT - это знаковые целые числа с размером 1, 2, 4 и 8 байт соответственно. Следовательно основной целый тип INTEGER будет 4-байтным на любой машине. Насколько мне известно даже 16 битный x86 его поддерживает. Не поддерживаемые типы придётся эмулировать, тут ничего не поделаешь. Без это логика программы может просто сломаться от переполнения.
Если использование 4-ёх байтного INTEGER'а неэффективно, то можно сделать специальный модуль HostCpu и объявить в нём HostCpu.Int наиболее эффективный для данной платформы.

Так это недостаток (существенный) С++, что там за обозримое время силами 1-2 человек, которые занимаются еще чем-то другим, основным, нельзя нарисовать компилятор. И это одно из основный преимуществ Оберона перед С++.

... Но ООП в КП точно не мощнее того что есть в java, и тем более С++.
Спорное утверждение. ООП Component Pascal'я обладает уникальными преимуществами перед ООП других ЯП. Например возможность определять как можно расширять запись и связанные с ней процедуры (так называются методы в оберонах). Засчёт отсутствия множественного наследования в Runtime'е BlackBox'а реализована быстрая и эффективная проверка типов, позволяющая писать шины сообщений и расширяемый код.

ООП это основное преимущество Component Pascal'я перед остальными оберонами.
Не факт. У Зоннона и Active-Oberon'a ООП тоже интересное.
Где можно взять компилятор под Windows без эмуляции ОС? Желательно без .NET . Дизайн их ОС ужасный, немедленно вызывает рвотный рефлекс. И название "Bluebottle" соответствующее. Управление тоже очень неудобное.

Микроконтроллеров много всяких бывает. А полноценных процессора сейчас только три: i386, AMD64 и ARM. Остальные(SPARC, Power PC и т. д.) либо померли, либо имеют специфическое применение.
Грань между микроконтроллером и чем-то "полноценным" очень тонка.
Как раз грань очень чёткая: микроконтроллер - это обычно 8-ми или 16-ти разрядный процессор с интегрированными ОЗУ и ПЗУ небольших объёмов. Код и данные обычно адресуются независимо. Примеры: PIC, AVR.

ARM'ы - это уже полноценные процессоры и на них уже можно использовать все возможности Component Pascal в том числе сборку мусора (она будет быстрой на небольшом объёме памяти).

Брать язык который только для микроконтроллеров или только для "полноценных" не вижу смысла. C++11 отлично подходит и для того и для другого. Oberon-07/11 более-менее подходит и для того и другого.
Никто не заставляет использовать все возможности Component Pascal'я при программировании софта для микроконтроллеров. Понятно, что там не будет сборщика мусора и основными целыми типами будут BYTE и SHORTINT. C++11 также можно использовать при программировании софта для микроконтроллеров в очень небольшом (1%) подмножестве. STL использовать нельзя.

Впрочем, мы отклонились от темы.
Новую тему создать?

39
Ну, КП как минимум абсолютно не портабельный
В каком плане не портабельный? Плохо запускается не разных ОС или сложно написать новый backend?
, да и существенно более сложный (и для реализации и для изучения).
Никто же не заставляет вам его реализовывать. Вы же не пишете для себя компилятор C++ например, не так ли?

Относительно простоты для обучения: я здесь не вижу каких-либо проблем. Базовые конструкции те же, что и в предыдущих оберонах, а ООП для обучения использовать никто не заставляет. Впрочем ООП в Component Pascal очень мощный и простой по сравнению с другими ЯП(С++, Java). ООП это основное преимущество Component Pascal'я перед остальными оберонами.
С другой стороны, я не вижу у Оберона-07/11 преимуществ для микроконтроллеров перед другими языками.
Здесь как раз простота реализации компилятора - очень важное преимущество. Микроконтроллеров много всяких бывает. А полноценных процессора сейчас только три: i386, AMD64 и ARM. Остальные(SPARC, Power PC и т. д.) либо померли, либо имеют специфическое применение.

40
Oberon-07 выглядит ощутимо хуже предыдущих оберонов. Зачем его использовать для не микроконтроллерного софта мне не понятно. По мне так самый лучший оберон это Component Pascal, хотя недостатков в нём тоже хватает. Например недостаточно проработаны записи, размещаемые не через NEW().

41
Только наткнулся случайно на odcread
Как-то сложно. Много классов, которые ничего ни делают. В BlackBox есть упрощённый читатель текстовых odc файлов в модуле Dialog. Он используется при чтении ресурсов. Исходный код довольно короткий:
PROCEDURE ReadStringFile (subsys: Files.Name; f: Files.File; VAR tab: StringTab);
VAR i, j, h, n, s, x, len, next, down, end: INTEGER; in, in1: Files.Reader;
ch: CHAR; b: BYTE; p, q: StringPtr;

PROCEDURE ReadInt (OUT x: INTEGER);
VAR b: BYTE;
BEGIN
in.ReadByte(b); x := b MOD 256;
in.ReadByte(b); x := x + (b MOD 256) * 100H;
in.ReadByte(b); x := x + (b MOD 256) * 10000H;
in.ReadByte(b); x := x + b * 1000000H
END ReadInt;

PROCEDURE ReadHead (OUT next, down, end: INTEGER);
VAR b, t: BYTE; n: INTEGER;
BEGIN
in.ReadByte(b);
REPEAT
in.ReadByte(t);
IF t = -14 THEN ReadInt(n)
ELSE
REPEAT in.ReadByte(b) UNTIL b = 0
END
UNTIL t # -15;
ReadInt(n);
ReadInt(next); next := next + in.Pos();
ReadInt(down); down := down + in.Pos();
ReadInt(end); end := end + in.Pos()
END ReadHead;

BEGIN
tab := NIL;
IF f # NIL THEN (* read text file *)
in := f.NewReader(NIL); in1 :=  f.NewReader(NIL);
IF (in # NIL) & (in1 # NIL) THEN
in.SetPos(8); ReadHead(next, down, end); (* document view *)
in.SetPos(down); ReadHead(next, down, end); (* document model *)
in.SetPos(down); ReadHead(next, down, end); (* text view *)
in.SetPos(down); ReadHead(next, down, end); (* text model *)
in.ReadByte(b); in.ReadByte(b); in.ReadByte(b); (* versions *)
in.ReadByte(b); in.ReadByte(b); in.ReadByte(b);
ReadInt(x); in1.SetPos(in.Pos() + x); (* text offset *)
next := down;
NEW(tab); tab.name := subsys$;
NEW(tab.data, f.Length());
n := 0; i := 0; s := 0; in.ReadByte(b);
WHILE b # -1 DO
IF next = in.Pos() THEN ReadHead(next, down, end); in.SetPos(end) END; (* skip attributes *)
ReadInt(len);
IF len > 0 THEN (* shortchar run *)
WHILE len > 0 DO
in1.ReadByte(b); ch := CHR(b MOD 256);
IF ch >= " " THEN
IF s = 0 THEN j := i; s := 1 END; (* start of left part *)
tab.data[j] := ch; INC(j)
ELSIF (s = 1) & (ch = TAB) THEN
tab.data[j] := 0X; INC(j);
s := 2 (* start of right part *)
ELSIF (s = 2) & (ch = CR) THEN
tab.data[j] := 0X; INC(j);
INC(n); i := j; s := 0 (* end of line *)
ELSE
s := 0 (* reset *)
END;
DEC(len)
END
ELSIF len < 0 THEN (* longchar run *)
WHILE len < 0 DO
in1.ReadByte(b); x := b MOD 256; in1.ReadByte(b); ch := CHR(x + 256 * (b + 128));
IF s = 0 THEN j := i; s := 1 END; (* start of left part *)
tab.data[j] := ch; INC(j);
INC(len, 2)
END
ELSE (* view *)
ReadInt(x); ReadInt(x); in1.ReadByte(b); (* ignore *)
END;
IF next = in.Pos() THEN ReadHead(next, down, end); in.SetPos(end) END; (* skip view data *)
in.ReadByte(b);
END;
IF n > 0 THEN
NEW(tab.key, n); NEW(tab.str, n); i := 0; j := 0;
WHILE j < n DO
tab.key[j] := SYSTEM.VAL(StringPtr, SYSTEM.ADR(tab.data[i]));
WHILE tab.data[i] >= " " DO INC(i) END;
INC(i);
tab.str[j] := SYSTEM.VAL(StringPtr, SYSTEM.ADR(tab.data[i]));
WHILE tab.data[i] >= " " DO INC(i) END;
INC(i); INC(j)
END;
(* sort keys (shellsort) *)
h := 1; REPEAT h := h*3 + 1 UNTIL h > n;
REPEAT h := h DIV 3; i := h;
WHILE i < n DO p := tab.key[i]; q := tab.str[i]; j := i;
WHILE (j >= h) & (tab.key[j-h]^ > p^) DO
tab.key[j] := tab.key[j-h]; tab.str[j] := tab.str[j-h]; j := j-h
END;
tab.key[j] := p; tab.str[j] := q; INC(i)
END
UNTIL h = 1
END
END
END
END ReadStringFile;
Помимо чтения odc там ешё чтение и сортировка строковых ресурсов.

42
Если можно, перекодируйте в utf-8, а то просмоторщик вопросы вместо комментариев показывает.

43
На Си можно избежать дублирования кода пользуясь тем фактом, что оператор присваивания возвращает значение:
i = 0;
while ((i < колВоСундуков) && (
   !(заяц = ЗАЯЦ(сундуки[i]))
|| !(утка = УТКА(заяц)))
|| !(яйцо = ЯЙЦО(утка))
|| !(игла = ИГЛА(яйцо))
)) ++i;
PS: прошлый раз не заметил, что там ещё и игла есть...

44
Это же банальный линейный поиск:
i := 0;
WHILE (i < LEN(сундуки)) & ((ЗАЯЦ(сундуки[i]) = NIL) OR (УТКА(ЗАЯЦ(сундуки[i])) = NIL) OR (ЯЙЦО(УТКА(ЗАЯЦ(сундуки[i]))) = NIL)) DO INC(i) END
Короткое решение безо всяких break'ов.

45
Что качается самого компилятора, то планируется сделать его общедоступным и открыть исходники, но это будет не раньше осени и только после удаления ряда зависимостей. в паблик пойдёт только компилятор с рантаймом и несколько пакетов, всё остальное, включая среду разработки раскрывать мы не имеем права, а то нас закроют )))
Уже ноябрь, скоро зима... Планируется выпустить Сириус в открытый доступ? Интересный проект.

Страницы: 1 2 [3]