Drop Down MenusCSS Drop Down MenuPure CSS Dropdown Menu

вторник, 22 декабря 2015 г.

Разработка языков программирования и компиляторов в СССР

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


http://habrahabr.ru/company/ua-hosting/blog/273665/

Программирующая Программа — первый компилятор


Основоположником информатики в СССР, в частности раздела автоматизации программирования, является Алексей Андреевич Ляпунов, первым предложивший рассматривать программу как последовательность чередующихся этапов, на которых выполняется некая обработка данных. Этап Ляпунов предложил назвать оператором, а схемой счета — совокупность операторов и логических условий. Схема и совокупность спецификаций каждого оператора — это программа. Взгляд на программу в таком ключе стал революционным и сразу лег в основу первых трансляторов (компиляторов) или программирующих программ, как их тогда называли.


М. Р. Шура-Бура, А. А. Ляпунов, С. С. Камынин

Первым в мире транслятором языка высокого уровня является ПП (Программирующая Программа), он же ПП-1, успешно испытанный в 1954 году. Транслятор ПП-2 (1955 год, 4 в мире транслятор) уже был оптимизирующим и содержал собственный загрузчик и отладчик, библиотеку стандартных процедур.

Первыми программами, принадлежащими системному программному обеспечению, были трансляторы — ассемблеры и автокоды на Западе, программирующие программы (ПП) у нас.

Сотрудники отдела программирования исследовали реализуемость операторных схем и определили основные типы операторов, соответствующие решаемым задачам: Ai — арифметические операторы, Pi — логические операторы, управляющие счетом, Fi — операторы переадресации, позволяющие переходить к следующему значению индекса.

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

Типы операторов соответствовали подавляющему большинству решаемых тогда задач, а именно — вычислительным задачам. Выделялись арифметические операторы Аi, ведущие вычисление по формулам, логические операторы Рi, осуществляющие управление счетом, операторы переадресации Fi, позволяющие переходить к следующему значению индекса (и обратные им операторы восстановления), все же неарифметические вычисления объединялись в так называемые нестандартные операторы Hi, для которых спецификацией был их машинный код. Специального подъязыка описания данных, зачатки которого появились в более поздних ФОРТРАНе и Алголе, не существовало.

Программирующая программа ПП-1 являлась одним из первых в мировой практике трансляторов и, по-видимому, имела самый высокий уровень входного языка.

Программирующая программа ПП-2, была создана под руководством М. Р.Шура-Буры в 1955 году для машины Стрела-1, основывалась на ПП-1 как прототипе. В ПП-2 были усовершенствованы алгоритмы трансляции и было уделено заметное внимание оптимизации программ — экономии выражений, оптимальному сочетанию переадресации и восстановления (иначе говоря, наилучшей реализации вычисления индексных выражений), оптимальному отведению памяти для так называемых рабочих ячеек. Это был, по-видимому, первый оптимизирующий транслятор.


Стрела-1. Принцип взаимодействия узлов ЭВМ

ПП для БЭСМ развивала входной язык программирующих программ. Она объединяла схему и спецификацию операторов в одном тексте, был введен первый структурный оператор — оператор цикла (соответствующий современным циклам с параметром).

ПП-2 послужила идейной основой двух проектов — ПП для Стрелы 4 и ПП для Стрелы 7. Первая из них представляла собой зачаток настоящей системы программирования: помимо собственно транслятора она содержала систему сборки модулей и некоторые средства отладки. Транслятор получал такие фрагменты объектной программы, которые потом назовут модулями, а система сборки создавала программу из оттранслированных модулей и библиотечных программ.

В ПП для Стрелы 3 был реализован ряд идей — табличный подход к синтаксическому анализу, оптимальное (по числу рабочих переменных) программирование арифметических выражений. Был изобретен метод хеширования, который применялся к экономии арифметических выражений.

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

В конце пятидесятых прошлого столетия развивался и подход к автоматизации программирования с помощью библиотек стандартных программ. Были разработаны — стандартная составляющая программа — ССП ( осуществляла статическую загрузку и связывание стандартных программ из достаточно обширной библиотеки), интерпретирующая система (ИС), ИС-2 уже реализовывала некоторые функции будущих операционных систем, осуществляя динамическое связывание, подкачку и смену используемых подпрограмм, причем все это делалось с небольшими накладными расходами и весьма скромными запросами на память. Высокая эффективность ИС-2 и хорошо продуманный интерфейс с основной программой сделали ее (как и положено операционной системе) неотъемлемой частью комплекта поставки ЭВМ.

Не смотря на все свои достоинства, программирующие программы широкого практического использования не имели:
даже при их наличии почти во всем множестве архитектур, существовавшем в стране, доля программирования непосредственно в машинном языке была преобладающей. Переход к современному стилю программирования на языках программирования высокого уровня был осуществлен благодаря созданию первых алголовских трансляторов. Произошло так, что первая тройка отечественных алголовских трансляторов, созданная для наиболее массовой тогда ЭВМ М-20, различалась по своим потребительским возможностям так, что своей совокупностью они удовлетворяли практически все категории пользователей.

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

Алгол




А. А. Берс, А. Ф. Рар «Становление Новосибирской школы программирования. Мозаика воспоминаний»:
Что на меня в Алголе 68 произвело наибольшее впечатление? Во-первых, это был первый язык, в котором был очень богатый список средств описания типов, и можно очень четко и формально описать структуры с вариантами и скомбинировать с массивами и т.д., и т.п., и все что по этому поводу проделывалось. Во-вторых, там был прекрасный механизм приведений, который позволял достаточно глубоко пользоваться описанными типами для того, чтоб перебрасывать по ним значения. И конечно, сама двухэтажная грамматика. И тут уже у меня возникло желание воспользоваться этим для того, чтобы делать хороший русский перевод.

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

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

Да, еще одна замечательная вещь, которая там была — это выдача значения почти любой конструкцией, что позволяло широко пользоваться суперпозицией при построении выражений. Важно осознать тот факт, что значение, которое выражение выдает — однократно неповторимо и уникально и что оно может использоваться только двумя разными способами. Либо ты его подхватишь суперпозицией, либо должен спрятать как состояние объекта. В первом случае этому значению не надо давать обозначение, тогда его использование как бы от тебя скрыто. Потому что само это значение увидеть нельзя, и оно ничем не названо. С другой стороны, если ты его ничем не подхватишь, то оно исчезнет.

Сейчас в объектных языках всё очень хорошо: вы должны с помощью этого значения привести объект в определенное состояние. Приведя, вы можете из этого состояния вычитывать это значение столько раз, сколько вам надо, и получите, что оно обозначало. То есть вот эта композитная программа очень красиво позволяла писать синтаксические выражения, очень связного характера. И поскольку языки программирования всегда тащили за собой английский жаргон, причем не язык, а именно жаргон… Тут еще одна вещь была, на мой взгляд, существенной — это работа над созданием русских национальных вариантов Алгола 68. Ершов и я, мы стремились к тому, чтобы все можно написать и без латинских букв, чтобы программы можно было бы практически читать вслух, — вещь недоступная для предыдущих языков. А синтаксис вообще удалось перевести как математический стих — все правила сохранили, и мнемонический смысл, и точную форму.

И, в общем, язык получился довольно стройный. Но сложности ему добавляло, на мой взгляд, стандартное вступление. Это был еще более свернуто написанный программный текст с дополнительными надстройками макросного характера.

Единственный отечественный язык программирования, получивший общемировую известность, это язык Рефал. Однако распространённость этого языка мала. Первая версия Рефала была создана в 1966 году Валентином Турчиным в качестве метаязыка для описания семантики других языков. Впоследствии, в результате появления достаточно эффективных реализаций на ЭВМ, он стал находить практическое использование в качестве языка программирования. В настоящее время основными диалектами языка являются Рефал-2 (1970-е), Рефал-5 (1985) и Рефал+ (1990), отличающиеся друг от друга деталями синтаксиса и набором дополнительных средств, расширяющих первоначальный вариант. 

Язык программирования Рефал


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


Рефал — язык бестиповый. В его основе лежит понятие объектного выражения как универсального типа данных. Все аргументы и результаты всех функций являются объектными выражениями.

Объектное выражение определяется таким образом, что операция конкатенации делается неявной, скрытой. Точнее сказать, что конкатенация на уровне значений выражается конкатенацией на уровне имен. Это свойство вытекает из основной цели Рефала как метаязыка для описания различных языковых объектов. Оно придает особую выразительную силу и остальным средствам языка, таким как образцы и результатные выражения.

Образцы — мощное изобразительное средство. Они в сжатой и наглядной форме обеспечивают как запись условий на вид аргумента, так и разбиение аргумента на составные части. Язык образцов Рефала лишен каких-либо «упрощающих» ограничений, свойственных другим языкам, что делает его очень простым для освоения и использования.

Язык определения функций Рефала, основанный на понятиях образца и результатного выражения чрезвычайно прост и компактен. Его минимальная версия получила название Базисный Рефал. Диалект Базисного рефала под названием Рефал-2 был реализован на многих типах отечественных ЭВМ и долгое время играл роль де-факто стандарта языка Рефал.

Язык Рефал-5 содержит Базисный Рефал в качестве подмножества. Расширения языка Рефал-5 качественно меняют стиль программирования.

В настоящее время существует две реализации языка Рефал-5: одна выполнена Д. Турчиным, другая — Н. Кондратьевым и Арк. Климовым. Обе имеют практически один и тот же входной язык, но отличаются рядом особенностей реализации. Вторая известна также под названием Рефал-6, однако следует помнить, что это название не языка, а его реализации.

Был также разработан язык Рефал Плюс, в отличии от Рефал-5 доведенный до концептуальной полноты (расширение рефала средствами обработки неуспехов). 

1997 год. Рефал прочно занимает свою нишу, не опасаясь никаких конкурентов. Например, он успешно используется физиками Обнинска, многими математическими центрами в России. Одно из основных применений Рефал – разработка трансляторов с языков программирования, когда сам Рефал используется как метаязык. В ИПМ на нем был очень быстро написан высокоэффективный транслятор Cern Fortran.

Рефал не обошли вниманием и военные. Современная боевая техника нередко требует модификации средств разработки, делая их адекватными растущим возможностям электроники, и Рефал поддерживает создание быстро совершенствующихся узкоспециализированных языков программирования. Одна из интересных областей, в которой применяется Рефал, – искусственный интеллект (ИИ). В ИИ Рефал используется и в качестве конечного средства разработчика, и как инструмент для создания языков представления знаний, ориентированных на конкретные области применения в ИИ. Одним из фундаментальных направлений, позволяющих эффективно использовать мощь Рефал, является анализ естественных языков. С помощью Рефал созданы лингвистические процессоры, экспертные системы.

Язык программирования Алмо


Язык системного программирования (машинно-ориентированный язык), задумывался как язык-посредник при трансляции с различных языков. Для каждой аппаратной платформы достаточно было написать транслятор Алмо — и появлялась возможность работать с множеством языков программирования, которые имели трансляцию в Алмо. Были созданы реализации языка для основных отечественных машин того времени (М-20, БЭСМ-6, Минск 2, Урал 11) и трансляторы с Алгола-60 и ФОРТРАНа в Алмо, причем все трансляторы также были написаны на Алмо и “раскручены” на всех этих машинах. Язык Алмо имел в своей основе некоторую абстрактную машину, отражавшую особенность существовавшего тогда класса машин, и в этом отношении Алмо-подход предвосхищал появившиеся позже Р-код, М-код и прочие подобные подходы. Машинная ориентированность явно прослеживалась в языке — регистровые объекты, постфиксная запись выражений, оперирование с битами машинных слов и т.д.

Система программирования Сигма


Г. Г. Степанов:
… название языка — Сигма — неожиданно очень удачно стало соответствовать сути разработанного языка, которую можно описать как «Символьный Генератор и Макроассемблер».
Всего в истории языка Сигма было три его реализации: на М-20, на БЭСМ-б и на самом языке Сигма. Первая, конечно самая памятная, т.к. это была мол первая работа в области системного программирования (да и вообще первая работа). Вторая была выполнена на лучшей, по моему мнению, отечественной машине БЭСМ-6. Третья опиралась на вторую, была раскручена сама через себя и могла генерировать программы как для БЭСМ-6, так и для СМ-4 и ЕС ЭВМ.



Сигма — СИмвольный Генератор и МАкроассемблер — обладал двумя важными и в то время новыми особенностями. Синтаксически ограничиваемый макросами, ондопускал генеральную линию создания программ — подстановку описанных макросов. Язык содержал средства формального описания конкретной архитектуры: была разработана система параметров, в терминах которой фиксировалось представление языка для конкретной ЭВМ. Таким образом, общая Сигма-программа вместе с описанием архитектуры ЭВМ транслировалась на данную ЭВМ. Параметрами архитектуры были длина слова, представление значений типов в машинном слове и т.п., так и правила заполнения шаблонов машинных команд.

Универсальный машинно-ориентированный язык программирования Эпсилон


Элементарный Преобразователь СИмвоЛьнОй иНформации — считался исключительно простым языком. Переменные в нем не имели типа и не описывались, идентификатор переменной просто обозначал содержимое ячейки, отведенной для этой переменной. Константы в языке могли быть либо натуральными числами, либо восьмеричными числами, либо — наборами двоичных цифр. Выражения были только двуместные; арифметические выражения обращались со значениями операндов, как с представлениями натуральных чисел; были еще поразрядные операции, операции сдвига и операция извлечения адреса данного объекта (позволяющая программисту управлять до некоторой степени распределением памяти). Объектами языка были так называемые списки (упакованные массивы) и слова (умещающиеся в одном машинном слове последовательности элементов разной длины). Программист мог задать двоичную кодировку для символа или множество двоичных кодировок для класса символов. Существовали переходы на метку условные и безусловные а также процедуры, замкнутые и открытые. 

Законным оператором языка была машинная команда представленная в восьмеричном виде. Именно в таком виде должны были осуществляться операции ввода-вывода. Используемые программой таблицы хранились как помеченные последовательности машинных команд; совместив в памяти такую последовательность с некоторым описанным списком, программист мог использовать для выбора элемента таблицы механизм выборки элемента списка.

А. Ф. Рар:
Заявленной целью разработчиков языка было предоставить удобный рабочий инструмент системным программистам…
Мы стремились достичь разумного компромисса между такими требованиями, как простота и удобство языковых средств, простота трансляции и возможность получения эффективной программы…
Отладка эта состояла в классической раскрутке ( bootstrapping ): Эпсилон-текст транслятора я пропускал через написанный вручную Эпсилон-транслятор, а получившийся новый транслятор проверял на нормальных Эпсилон-программах. Раскрутка эта дала заодно ответ на… вопрос: «[насколько] программы, полученные путем Эпсилон-трансляции, проигрывают по сравнению с программами, написанными вручную?» Оказалось… всего в 1,35 раза.


Система программирования Бета


Проект Бета был основан на предположении о конвергенции основных алгоритмических языков, как и методов трансляции и оптимизации. Первоначально основными входными языками считались Алгол 68 и ПЛ/1. Язык Паскаль появился на свет одновременно с началом работ над проектом Бета и вскоре был включен в список его входных языков как основной входной язык «пробной реализации» БЕТА-системы.

Центральным звеном проекта Бета был Внутренний язык, который должен был стать единым языком-посредником в БЕТА-системе «наибольшим общим делителем» входных языков и «наименьшим общим кратным» выходных машин. Кроме этой своей роли промежуточного языка, позволяющего уменьшить число путей в схеме m -языковой n -машинной трансляции с m * n до m + n, внутренний язык должен был также явиться средой оптимизирующих преобразований, т.е. он еще должен был быть достаточно богат, чтобы на нем было возможно представить результаты оптимизации; например, экономию совпадающих подвыражений в операторе a [ i, j, k ] := b [ i, j, k ] + c [ i, j, k ].

Одновременно предполагалось опробовать слишком много новшеств: многоязычие на входе, многомашинность на выходе; новые языки (например при начале работ существовали только неполные экспериментальные трансляторы с Алгола 68) и новые методы оптимизации для новых прикладных областей — и всё это в рамках научно-исследовательского института, полупроизводственная работа силами сотрудников, ориентированны на получение научных результатов.

Автокод МВК Эльбрус — Эль-76




Из книги В.М. Пентковского об автокоде «Эльбрус».
В советское время не стеснялись программировать на русском


Изначально этот язык был назван — автокод Эльбрус, затем был переименован в Эль-76. Несмотря на то, что Эль-76 является языком достаточно высокого уровня, есть основание называть его «автокодом». Эльбрус просто не имел языка более низкого уровня, т.е. «ассемблера». Т.е. язык минимального уровня Эльбрус — это Эль-76, остальные языки уже строились над ним. Это — замечательная иллюстрация высокого научного и инженерного уровня отечественных ИТ в то время. 
Эль-76 — язык программирования, использующий русскую лексику. Разработан в середине 70-х годов в СССР. Эль-76 предназначен для многомашинных вычислительных комплексов типа «Эльбрус». Объединяет в себе особенности машинного языка, непосредственно управляющего работой устройств ЭВМ, и изобразительные средства языка высокого уровня (во многом аналогично Алголу-68). Эль-76 поддерживает методику структурного программирования, т.е. композиции программы из процедур, линейных последовательностей операторов, циклов, альтернативных сочленений с выбором альтернативы по условию или по номеру альтернативы и параллельно выполняемых ветвей. Язык имеет специальные средства описания поведения программы в особых случаях — т.н. ситуации и структурные переходы. Основной особенностью Эль-76 является возможность хранения в памяти ЭВМ информации о типе переменной величины вместе с ее значением и ее изменения в ходе выполнения программы.

Рапира




Язык программирования Рапира — один из двух входных языков учебной системы программирования, входящей в состав интегрированной программной среды «Школьница». Рапира представляет собой концентрическое семейство языков с последовательно расширяемым набором возможностей. Каждый концентр можно рассматривать как замкнутый язык-оболочку.

Если интересно (и если есть время):
Приводится полное описание синтаксиса языка и краткие сведения о семантике его основных конструкций. По документу 3533847.00042-01 35 01 из архива академика А.П.Ершова: Описание языка


Язык Ада




Четырнадцатая линия парижского метрополитена. Поезд, в котором нет кабины машиниста. Движение поездов на этой линии полностью управляется Ада-программой. ТАНТК им. Г. М. Бериева — самолетов-амфибия с бортовым программным обеспечением на базе языка Ада.

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



Язык этот назвали в честь Августы Ады Лавлейс – женщины, которая считается первым программистом на Земле.

Адские мифы
Довольно часто с Адой связывают набор устойчивых заблуждений, препятствующих как распространению языка, так и осознанному выбору Ады в качестве языка реализации проекта.

Ада – мертвый язык, на нем сейчас никто не программирует. В действительности, Ада уверенно занимает нишу больших встроенных систем с повышенными требованиями к надежности. По сравнению с «коробочными» продуктами для Windows, такие системы не так заметны, поскольку либо существуют в одном экземпляре (какой смысл тиражировать программу, управляющую движением поездов метро), или распространяются как часть системы, в которую они встроены (бортовое программное обеспечение).

Ада – язык, предназначенный исключительно для военных применений.Ада действительно была разработана при участии Министерства обороны США, однако отсутствуют какие-либо технические, административные или иные причины, препятствующие использованию Ады для разработки гражданских систем. Количество «гражданских» проектов, основанных на этом языке, сегодня сопоставимо с количеством «военных» проектов.

Ада – слишком большой и сложный язык, для того чтобы использовать его в небольшом проекте. Объем и сложность всех современных индустриальных языков практически одинаковы, и чтобы убедиться в этом, достаточно просто сравнить объем их описаний. Этот миф восходит к началу 80-х годов, когда Аду сопоставляли с Паскалем, Фортраном 77 или Бейсиком.



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

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

Существующие Ада-технологии неэффективны; и трансляторы, и порождаемый ими код, отличаются низкой производительностью. Этот миф также восходит к первой половине 80-х годов, когда появились первые реализации Ады, фактически всего лишь доказывавшие «теорему существования Ада-транслятора, соответствующего стандарту». Достаточно провести ряд несложных экспериментов, запрограммировав некоторую модельную задачку на Аде, Паскале и Си/Си++, и сравнив (при сопоставимых параметрах компиляторов) затем скорость компиляции, объем порождаемого кода и скорость его выполнения, чтобы убедиться, что какой-либо специфической неэффективности, свойственной Аде, просто не существует. Можно также отметить, что система программирования GNAT при объеме исходных текстов более 40 Мбайт, на 90% реализована на Аде, и построение ее из исходных текстов (в его ходе она трижды сама себя компилирует) на современном ПК занимает не более получаса.

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

История создания языков программирования в нашей стране не исчерпывается перечисленным.Много интересных разработок на сегодняшний день можно считать «мёртвыми». Эти языки уходили вместе с техникой, в которой они «жили».
Вот перечень трансляторов сделанных в СССР (видимо неполный):
  • Ada
  • Algol-60
  • Algol-68
  • C
  • CLU
  • Forth
  • Fortran (для Эльбрусов сделали 2 компилятора)
  • Lisp
  • Modula-2
  • Pascal
  • PL/I
  • SETL
  • Simula-67
  • Snobol-4

Комментариев нет:

Отправить комментарий

Related Posts Plugin for WordPress, Blogger...
Related Posts Plugin for WordPress, Blogger...