it-history
February 6

Xerox Alto, BCPL и спиритизм  

Или как я собрал и вызвал великий дух компьютерных предков. Без Кастаньеды и пейота, только водка и компилятор чай и гугл.

Не обращайте внимание на Ди Каприо за рулем советского ЗИЛа посреди cибирcкой деревни, главное - то что в центре. Этот релиз Xerox Alto был сделан примерно за месяц до моего рождения.

Что такое легенда

Не хочу снова цитировать википедию или (прости Господи) Хабр — вы и так должны знать историю про Xerox, PARС и Alto если учились по крайней мере в школе.

Серьезно, про лабораторию Xerox PARC и ее вклад в развитие компьютеров рассказывали даже мне на уроках информатики. И та школа была очень далеко от Москвы .

Ладно, сделаю скидку на убогость современного образования:

Xerox Altoкомпьютер, разработанный в исследовательском центре Xerox PARC в 1973 году. Это первый в мире компьютер, использовавший метафору «рабочего стола» и графический пользовательский интерфейс.

Вот небольшое но современное видео одной такой рабочей станции после восстановления:

Тумбочка снизу - не просто тумбочка, а монитор тут пока еще просто монитор и отвечает только за картинку. 1973 год однако.

Несмотря на то что Xerox Alto никогда не продавалась как коммерческий продукт а такие рабочие станции использовались только внутри самой Xerox и еще нескольких исследовательских центров — небольшое количество таких машин все же дожили до наших дней, были восстановлены и ныне поддерживаются в работоспособном состоянии руками фанатов.

Например один такой энтузиаст из солнечной Калифорнии занимается восстановлением до полной работоспособности одной из сохранившихся машин.

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

Вот так выглядит жесткий диск:

Как вам размерчик?

Исходный код

Собирая материалы для этой статьи, с удивлением обнаружил невероятное:

был выложен и ныне доступен публично исходный код большинства проектов лаборатории PARC

И там очень много интересного:

This archive is a collection of source code and digital text documents, image files, and other files from Xerox Palo Alto Research Center (PARC). This came from the same IFS backup file repositories that the earlier 2013 release of the Xerox Alto source code archive came from, and is a superset of that archive, containing files related to projects from the 1980s, up to 1994, that were not included there. Information pertaining only to Alto systems was covered on the previous Alto archive walkthrough and will be omitted here.

Особенно шокировал раздел Databases, File Systems, and Client/Server Applications, как вам например такое:

Hickory — 1986 reminder and calendar system based on the Cypress database in Cedar

Зато теперь понятно откуда растут уши Lotus Notes и куда более позднего Microsoft Outlook, получается что ключевой корпоративный софт был придуман очень и очень давно.

По этой ссылке доступен один интересный PDF-документ, сохраненный специально для унижения тупых потомков:

Реляционная база данных, с транзакциями для хранения электронной почты. В 1972 году.

Читаешь такое и воешь от зависти, вспоминая свое голожопое детство и сраный крякнутый Паскаль с видеоиграми — оказывается люди делом занимались еще за 30 лет до того ширпотреба, с которого я когда-то начинал свой путь в ИТ.

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

Эмуляторы

Я нашел целых три действующих эмулятора Xerox Alto, позволяющих без особых проблем запускать столь древний софт на обычном x86 компьютере.

ContrAltoJS

Реализация эмулятора на Javascript, работает в браузере:

This is a pure JavaScript implementation of the ContrAlto Xerox Alto emulator. The end goal is a usable, performant Xerox Alto emulator running in your web browser.

Исходники находятся вот тут.

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

ContrAlto на современном компьютере в музее. На мониторе кстати Smalltalk - далекий предок современной Java.

ContrAlto

Современный эмулятор на C#, созданный сотрудником Living Computers Museium, собираемый и запускаемый без особых проблем как на Windows так и на Linux:

Living Computers’ Engineer Josh Dersch spent more than a year creating this emulator of the Xerox Alto, a pioneering computer workstation developed at the Palo Alto Research Center (PARC) in 1973. The Alto introduced several experimental concepts, including the graphical user interface, object-oriented programming, and Ethernet networking.

Исходники находятся вот тут, доступна также бинарная сборка.

Собирается из исходников без особых проблем как в Windows так и в линуксе. Бинарная сборка запускается и на FreeBSD тоже (с Mono), но официально это не заявлено.

Да, тут внезапно есть поддержка сети:

ContrAlto is an application for modern PCs that simulates the original Xerox Alto, from the graphical display to the Ethernet interface. It allows you to experience part of the world Xerox PARC created 40 years ago.

Но имейте ввиду что сеть там своя, времен еще до TCP/IP стека, поэтому для работы нужно что-то такое:

This project is an interface / gateway from the Xerox Alto's 3 Mb/s Ethernet to the outside world. The software runs on a BeagleBone Black single-board Linux computer and uses a simple interface board (shield) to interface with the Alto's Ethernet. This system makes use of the IFS file server software from Living Computers Museum+Labs.

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

Salto

Этот эмулятор в работе вы видите на стартовой картинке в статье. Наверное самый «хардкорный» вариант — на чистом Си, актуальные исходники проекта находятся вот тут:

SALTO — Xerox Alto I/II Simulator. Not a project of mine, just to keep this code from getting lost

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

Забираем:

git clone https://github.com/brainsqueezer/salto_simulator.git

Сборка проекта сделана на чистом Makefile, без всяких autotools поэтому на FreeBSD запускаем gmake и получаем кучу вот таких ошибок:

Проблема заключается в измененном поведении новых версий компилятора GCC:

Yes there was a change in behaviour.
In C you are supposed to only define a global variable in one translation unit, other translation unit that want to access the variable should declare it as "extern".
In your code, a.h is included in both a.c and main.c so the variable is defined twice. To fix this you should change the "int test" in a.h to "extern int test", then add "int test" to a.c to define the variable exactly once.

К счастью это очень легко исправить, добавив ключ -fcommon в переменную CFLAGS:

CFLAGS	+= -Wall -MD -fcommon

Ключ fcommon возвращает поведение «как у дидов»:

Older versions of gcc would allow multiple tenative definitions (but not multiple non-tentative definitions) of a global variable in different compilation units by default. gcc-10 does not. You can restore the old behavior with the command line option «-fcommon» but this is discouraged.

и позволяет завершить сборку без ошибок:

Готовые бинарники будут в каталоге bin:

Запускается эмулятор вот так:

bin/salto disks/games.dsk.Z

А вот так выглядит запущенный эмулятор:

Нужен большой экран да

Теперь немного отвлечемся от эмуляции, перейдя к не менее интересной теме древних языков разработки, благо в Xerox Alto их было несколько.

Обатите внимание на раскладку на клавиатуре - она внезапно совпадает с современной!

BCPL

Начнем с вот этого:

BCPL (Basic Combined Programming Language) — язык программирования, разработанный Мартином Ричардсом в 1966 году в Кембриджском университете.

Вот так выглядел код на BCPL в 1972м (часть из исходников самого компилятора):

if SourceName!0 eq 0 do Error("No source file name")
if SourceDevice!0 eq 0 do Movestring(SourceName, SourceDevice)
if BinName!0 eq 0 do Error("No binary file name")

test SWTTOfile % (SWOutput & not SWTTOtype)
   ifso
      [
      if OutputName!0 eq 0 then Error("No output file name")
      OutputStream = OpenOutput(OutputName)
      ]
   ifnot [ OutputStream = TTOstream; OutputName!0 = 0 ]

test SWTTOfile
   ifso ErrorStream = OutputStream
   ifnot ErrorStream = TTOstream
...

На мой взгляд куда читабельней современного Javascript, не находите?

Фанатами BCPL был портирован на x86 архитектуру раз и два, один из этих портов я покажу в работе дальше:

This is an x86 (IA-32) port of the "classic" old BCPL compiler
(around 1980) from the Tripos Research Group at Cambridge University.

Этот язык — важная веха развития программирования, сильно повлиявший на появившейся позже знаменитый Си:

BCPL was a popular systems programming language during the 1960s
and 1970s, and is of great historical importance: about the time
of the birth of UNIX, BCPL directly inspired the computer language
B and thus had a very big influence on the development of C.

Поэтому тестовый пример кода на нем мы и напишем.

Среда разработки Cedar

Mesa

Нет это не та Mesa, по которой вы бегали с монтировкой гоняя инопланетных крабов в голожопом детстве, это такой язык программирования:

The Mesa programming language was designed by Charles M. Geschke, Butler Lampson, Jim Mitchell, James H. Morris, Jr., and Edwin H. Satterthwaite, with contributions from Alan Kay, Charles Simonyi, and John Wick. Mesa evolved from the Modular Programming Language (MPL), which was part of the Modular Programming System (MPS) project carried out jointly by PARC and the SRI International Augmentation Research Center (ARC). One of the goals of MPS was to facilitate migrating ARC's oNLine System (NLS) from the PDP-10 to smaller computers. MPL was designed by Butler Lampson and James G. Mitchell with contributions from others at SRI and PARC.

Помимо языка, была разработана очень интересная среда разработки Cedar:

Cedar/Mesa was not just a language and a set of libraries but a full integrated development environment (IDE) with its own mouse-driven graphical user interface (GUI), that, although taking some cues from Smalltalk's interface, also differed from it in many ways

Интересна она своим подходом к интерфейсу как к печатному документу:

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

К сожалению Mesa/Cedar так и не получили какого-либо развития, хотя и заметно повлияли на вектор развития ПО в целом.

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

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

-- File:  Answer.Mesa  - edited by
-- Karlton, December 2, 1980  1:28 PM

Answer: DEFINITIONS =
  BEGIN
  
  Block: TYPE = RECORD [
    buffer: LONG POINTER TO PACKED ARRAY [0..0) OF CHARACTER,
    length: CARDINAL];
  -- This is used exclusively with the putBlock procedure passed to the MakeHeader
  -- procedure described below.  The client is expected to make up the header
  -- of the new message from the Blocks given back to the client by successive
  -- calls on the putBlock procedure.  There will only be a single CR terminating
  -- the last Buffer.  If the client wishes to add more lines to the constructed
  -- header, this may be done.
  
  MakeHeader: PROCEDURE [
    getChar: PROCEDURE [CARDINAL] RETURNS [CHARACTER], getLength: CARDINAL,
    putBlock: PROCEDURE [Block],
    getPages: PROCEDURE [CARDINAL] RETURNS [LONG POINTER],
    freePages: PROCEDURE [LONG POINTER],
    userName, userRegistry: STRING,
    arpaGatewayHostNames: DESCRIPTOR FOR ARRAY OF STRING,
    cForCopies: BOOLEAN ← FALSE]
    RETURNS [answerError: BOOLEAN];
  -- Causes an answering header for a message that the client currently has.
  -- 'getChar' procedure is used to get characters from the old message header.
  -- The argument to 'getChar' is which character from the old header is needed.
  -- The same character may be asked for more than once.  'getLength' is the length
  -- of the old message being parsed; 'getChar' will always be called with the
  -- argument in the range [0..getLength).  'putBlock' is called by MakeHeader
  -- successively with pieces of the new header under construction.  'getPages'
  -- and 'freePages' are called by MakeHeader as it needs temporary storage while
  -- constructing the new header.  If MakeHeader is not unwound, all storage will
  -- be released before it returns.  If being used in the Alto/Mesa world, the high
  -- order word of the pointers must be zero.  'userName' and 'userRegistry' may not
  -- be NIL, and are used to eliminate some "redundant" information from the constructed
  -- header.  'arpaGatewayHostNames' should be an array of strings representing the
  -- local host, e.g. ["PARC-MAXC"L, "PARC"L, "MAXC"L].  'cForCopies causes the
  -- constructed header to have "c:  <recipient list>" instead of "cc: <recipient list>".
  -- If the parse of the old message failed, then MakeHeader returns TRUE.
    
  END.  -- Answer --

Как видите комментирование через '--' в современном SQL имеет ооочень глубокие корни.

Запущенная графическая среда разработки, 1972 год и классы с обьектами.

Alto Smalltalk-72

Далекий предок современной Java, когда-то непосредственно создавался на станциях Xerox Alto:

The first hardware-environments which ran the Smalltalk VMs were Xerox Alto computers

Но Smalltalk как язык точно достоин отдельного поста и более глубокого раскрытия темы, тем более что язык развивается и используется по сей день, не так давно отметив 50-летний юбилей.

Вот тут находится веб-симулятор Alto Smalltalk-72, тут статья с примером работы с ним, откуда я и взял этот пример:

@ go 50 turn 90 go 50 turn 90 go 50 turn 90 go 50\

А вот еще один пример исходного кода, но в виде картинки:

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

Как видите это практически Emacs, только из 1972 года :)

Когда-нибудь я эту штуку тоже разберу, но не сегодня.

А пока вот вам свежее видео с демонстрацией Smalltalk на восстановленном Xerox Alto:

Interlisp

Само собой разумеется что в Xerox Alto был LISP (куда же без лиспа):

Interlisp is a software development environment, originating from Xerox PARC in the 1970s and 1980s. supporting software research in AI, computational linguistics, graphical user interfaces, hypertext, and other research areas. Software development in Interlisp-D is a different experience than is common, even today. The features of structure editing, source code management, code analysis and cross-referencing combined to support rapid incremental development. The 1992 ACM Software System Award was awarded to the Interlisp system for pioneering work in programming environments.

1982 год, демонстрация InterLisp в работе. Взято отсюда.

Для самых отбитых «археологов» вот тут выложены исходники Interlisp 1974 года. Но это еще не все, далеко не все.

Все же знают что лисперы — «особенные ребята»?

Поцелованные Богом в голову и потерявшие разум в обмен на умение программиовать скобочками

В общем эти особенные ребята воссоздали ту самую среду разработки, в том числе для работы через веб. Выглядит как-то так:

Несмотря на всю черно-белость, эта среда разработки очень даже рабочая:

Medley is a rich development environment but it's missing a test framework. Or so I thought. To fill the supposed gap I wrote Femtounit, a tiny — hence femto — unit test framework for Interlisp.

Вот так, взять и написать фреймворк для юниттестов под систему из 1972 года!

«Hello world» на системе из 1972го

Вы же не думали что я собирал и запускал эмулятор просто так?

Сейчас по шагам продемнострирую процесс написания кода, сборки и запуска приложения на Xerox Alto.

Поехали.

Запускаем эмулятор с вот этим образом диска, на котором есть необходимые инструменты для разработки:

bin/salto disks/tdisk4.dsk.Z

Запускаем текстовый редактор Bravo:

bravo

и видим вот такое:

Да, это самый первый WYSIWYG редактор на свете.

Нажимаем клавишу i (INSERT) и вводим вот такой код:

// Hello world demo
get "streams.d"
external
[
Ws
]

let Main() be
[
Ws("Hello World!*N")
]

Как это выглядит в эмуляторе:

После ввода нажимаем ESC , затем клавишу p и вводим имя файла:

hello.bcpl

Затем опять нажимаем ESC (НЕ Enter!) и запустится процесс сохранения, визуально медленный.

После сохранения на диск будет сообщение:

Нажимаем клавишу q и затем Enter для выхода из этого замечательного редактора.

Теперь запускаем компилятор BCPL:

bcpl hello.bcpl

Вот так выглядит результат компиляции в эмуляторе:

Запускаем линковщик (да да это все еще 1972 год!):

bldr/d/l/v hello

Обратите внимание на передачу параметров линковщику:

bldr это само приложение, а /d/l/v — параметры, которые идут подряд сразу после имени приложения и без пробелов.

Вот так выглядит результат работы линковщика:

Наконец запускаем само приложение:

hello

Результат:

Поздравляю — вы только что увидели кусочек истории ИТ практически вживую.

BCPL на современной ОС

Внезапно обнаружилось аж три разных порта компилятора этого языка на x86 и современные ОС, один из которых (последний) я собрал и смог использовать компиляции тестовой программы.

Так что если вам недостаточно пейота кодирования на BCPL в эмуляторе Xerox Alto — можете перейти на следующий уровень, начав программировать на BCPL в обычной повседневной ОС FreeBSD.

Психиатру только о таком опыте не рассказывайте — не так поймут.

Хотя на самом деле это еще не предел и есть на свете кое-что покруче:

BCPL++ is a modern programming language inspired by BCPL

c синтаксисом для троллинга как JS-разработчиков так и плюсолюбов-сишников:

section Main
require Std

let main(argc :: Int32, argv :: &&Char) be {
    writes("Hello, World");
    return 0;
}

От такого синтаксиса сразу всем поплохеет.

BCPL++ это уже современная разработка, проект написан на Rust и собирается с помощью Cargo, поэтому не так интересен.

Но разумеется его я тоже собрал и запустил.

Хотя никаких особых проблем со сборкой не было, а мелкие особенности сборки Rust проектов под FreeBSD я уже описывал вот тут.

Поэтому ниже будет про компилятор классического BCPL:

This is an x86 (i386) port of the "classic" old BCPL compiler (around 1980) from the Tripos Research Group at Cambridge University. This is a distribution suitable for compiling and running a range of older BCPL programs on 64-bit and 32-bit Linux and FreeBSD systems

Описание на сайте автора, взято с этой страницы, раздел «obcpl — Classic BCPL Compiler». Прямая ссылка для скачивания: obcpl-0.9.8.tar.xz.

Скачиваем и распаковываем:

tar xvzf ~/Downloads/obcpl-0.9.8.tar.xz

Сборка осуществляется скриптом makall в корневом каталоге, для сборки на FreeBSD необходимо указать на использование компилятора GCC вместо Clang через переменную окружения CC:

export CC=gcc
./makeall

После чего сборка завершится успешно:

Но к сожалению собранный компилятор окажется нерабочим:

Проблема заключается в параметре -m elf_i386, которым задается формат генерируемого ELF-бинарника:

st: su.o st.o blib.o global.o rt.o sys.o
	ld -m elf_i386 -o st su.o st.o blib.o global.o rt.o sys.o

На современной 64-битной FreeBSD это не работает даже с загруженным модулем ядра, отвечающим за поддержку запуска 32-битных приложений, поэтому ключ неоходимо удалить — произойдет подстановка типа ELF по-умолчанию, разумеется поддерживаемого.

Этот же ключ присутствует в shell-скрипте src/obcpl, прикидывающимся компилятором:

if test $cflag -eq 4; then
    ld -m elf_i386 -o $oname $ohead $olist $otail
fi

Это место в самом конце скрипта, которое запускает линковщик, исправленная строка должна выглядеть вот так:

ld -o $oname $ohead $olist $otail

После правок запускаем сначала очистку:

./makeall clean

затем повторную сборку:

./makeall

После успешной сборки компилятора, можно попробовать собрать и запустить тесты:

./src/obcpl ./util/cmpltest.b
./cmpltest

Успешный результат выглядит вот так:

Тестовая программа

Для начала адаптируем «Hello world» из 1973 года, вот так выглядит оригинал:

// Hello world demo
get "streams.d"
external
[
Ws
]

let Main() be
[
Ws("Hello hacker!*N")
]

А вот так — адаптация для компиляции на x86:

// Hello world on BCPL, 2024
GET "LIBHDR"

LET Start() be [
	WRITEF("Hello hacker!*N")
]

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

Сборка:

/src/obcpl ./hello.b

Запуск:

Если немного поискать, то можно обнаружить больше рабочих примеров, например вот так выглядит вычисление факториала:

GET "LIBHDR"

LET START() = VALOF $(
	FOR I = 1 TO 5 DO
		WRITEF("%N! = %I4*N", I, FACT(I))
	RESULTIS 0
$)

AND FACT(N) = N = 0 -> 1, N * FACT(N - 1)

Сборка и запуск:

Эпилог

Проект Xerox Alto это в чистом виде история всей компьютерной индустрии. Важная ступень развития, определившая все дальнейшее развитие компьютеров.

Разумеется столь невероятные по своей мощи исследовательские рабочие станции, созданные и использовавшиеся еще до моего рождения, никогда не появлялись на территории СССР/РФ, даже в самих США про этот проект было мало информации в те годы.

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

А лазая по выложенному архиву исходного кода Xerox Alto, можно воочию убедиться насколько на самом деле стары принципы работы компьютеров и разработки ПО.

Невероятный опыт, рекомендую.