BS(1) BS(1)
НАЗВАНИЕ
bs - компилятор/интерпретатор программ умеренных разме-
ров
СИНТАКСИС
bs [файл [аргумент ...]]
ОПИСАНИЕ
Язык bs - отдаленный потомок Бейсика и Снобола-4 с не-
которыми дополнениями из языка C. Язык bs создан для
тех задач программирования, в которых время разработки
так же важно, как и полученная в результате скорость
выполнения. Формальности об явления данных и манипуля-
ции с файлами и процессами минимизированы. Построчная
отладка, операторы trace и dump, а также подробные со-
общения об ошибках выполнения упрощают тестирование
программ. Более того, можно отлаживать незавершенные
программы; внутренние функции могут тестироваться до
того, как написаны внешние функции, и наоборот.
Если в командной строке указан аргумент файл, ввод на-
чинается из него и продолжается с терминала. По умолча-
нию, операторы, прочитанные из файла, компилируются для
последующего выполнения. Операторы, введенные с терми-
нала, обычно выполняются немедленно (см. ниже операторы
compile и execute). Если последняя операция - не прис-
ваивание, результат оператора-выражения печатается.
Программы на языке bs состоят из строк. Символом про-
должения является \ в конце строки. Язык допускает
строки следующего вида:
оператор
метка оператор
Метка - это имя (см. ниже), за которым следует двоето-
чие. Метки и переменные могут иметь одни и те же имена.
Оператор языка bs - это выражение или ключевое слово,
за которым следует 0 или более выражений. Некоторые
ключевые слова (clear, compile, !, execute, include,
ibase, obase и run) всегда выполняются, как только они
откомпилированы.
Синтаксис операторов
выражение
Целью выполнения выражения являются его побочные
эффекты (значение, присваивание или вызов функ-
ции). Детали приводятся ниже, после описания типов
операторов.
break
Выйти из самого внутреннего for/while цикла.
clear
Выполняется немедленно. Очистить таблицу имен и
удалить скомпилированные операторы.
compile [выражение]
Выполняется немедленно. Откомпилировать последую-
щие операторы (не принимая во внимание установлен-
ный режим немедленного выполнения). Необязательное
выражение вычисляется и используется в качестве
имени файла для последующего ввода. В последнем
случае выполняется clear.
continue
Перейти к следующей итерации текущего for/while
цикла.
dump [имя]
Напечатать имена и текущие значения всех нелокаль-
ных переменных. Если указана опция имя, сообщается
только о данной переменной. После ошибки или пре-
рывания выводится номер последнего оператора и
(возможно) трассировка пользовательских функций.
exit [выражение]
Вернуться на системный уровень. Выражение возвра-
щается в качестве кода завершения.
execute
Изменить режим выполнения на немедленный (прерыва-
ние дает аналогичный эффект). Эта команда не вызы-
вает выполнения запомненных операторов (см. ниже
команду run).
for имя = выражение выражение оператор
for имя = выражение выражение
...
next
for выражение, выражение, выражение оператор
for выражение, выражение, выражение
...
next
Циклически выполнять оператор (первая форма) или
группу операторов (вторая форма) под управлением
переменной с указанным именем. Переменная принима-
ет значение первого выражения, затем она увеличи-
вается на единицу в каждом цикле, пока не превзой-
дет значения второго выражения. Третьей и четвер-
той формам требуются три выражения, разделенные
запятыми. Первое из них - инициализация, второе
условие (если истинно, то продолжать), и третье
действие при переходе к следующей итерации (обычно
приращение).
fun f([a, ...]) [v, ...]
...
nuf
Определить имя, аргументы и локальные переменные
написанной пользователем функции. Допускается до
10 аргументов и локальных переменных. Эти имена не
могут быть массивами, а также не могут быть связа-
ны по вводу и выводу. Определения функций не могут
быть вложенными.
freturn
Сигнализировать о неудачном завершении пользова-
тельской функции. См. ниже операцию опроса (?).
Если опрос отсутствует, freturn возвращает 0. Ког-
да опрос активен, freturn возвращается к соот-
ветствующему выражению (возможно, выполняя возвра-
ты из вложенных функций).
goto имя
Передать управление на хранящийся в памяти опера-
тор с соответствующей меткой.
ibase N
Установить основание системы счисления при вводе
чисел равным N. Поддерживаются только следующие
значения N: 8, 10 (по умолчанию) и 16. Шестнадца-
теричные значения 10-15 вводятся как a-f. Первой
должна стоять цифра (то есть f0a следует вводить
как 0f0a). Ibase (и, ниже, obase) выполняются не-
медленно.
if выражение оператор
if выражение
...
[else
...]
fi
Выполнить оператор (первая форма) или группу опе-
раторов (вторая форма), если результат вычисления
выражения ненулевой. Цепочки символов 0 и "" (пус-
тая) считаются нулевыми. Во второй форме допуска-
ется дополнительная группа операторов, которая
должна выполняться, когда не выполняется первая
группа. Единственный оператор, допустимый в той же
строке, что и else, - это if; только другие fi мо-
гут быть в той же строке, что и fi. Поддерживается
сокращение else и if в elif. Чтобы закрыть после-
довательность if ... elif ... [ else ... ], требу-
ется только одно fi.
include выражение
Выражение должно определять имя файла. Файл должен
содержать bs-операторы. Такие операторы становятся
частью компилируемой программы. Операторы include
не могут быть вложенными.
obase N
Установить основание системы счисления при выводе
чисел равным N (см. выше ibase).
onintr метка
onintr
Программная обработка прерываний. В первой форме
после прерывания управление передается на указан-
ную метку, в точности так, как если бы в момент
прерывания был выполнен оператор goto. После нача-
ла обработки прерывания установленная реакция от-
меняется. Во второй форме прерывание вызывает за-
вершение выполнения.
return [выражение]
Вычислить выражение и возвратить его значение в
качестве результата вызова функции. Если выражение
не указано, возвращается 0.
run Перезапустить генератор случайных чисел. Передать
управление на первый скомпилированный оператор.
Если оператор run содержится в файле, он должен
быть последним оператором.
stop Прекратить выполнение скомпилированных операторов.
Bs возвращается в режим немедленного выполнения.
trace [выражение]
Управление трассировкой функций. Если выражение не
указано (или имеет нулевое значение), трассировка
выключается; в противном случае печатается прото-
кол вызовов пользовательских функций и возвратов
из них. Каждый возврат уменьшает на единицу значе-
ние выражения, указанного в операторе trace.
while выражение оператор
while выражение
...
next
Оператор while аналогичен for за исключением того,
что указывается условие продолжения цикла.
! команда shell'а
Выполнить команду shell'а.
# ...
Этот оператор игнорируется. Он используется для
включения в программу комментариев.
Синтаксис выражений
имя Имя используется для того, чтобы указать перемен-
ную. Имена состоят из буквы (прописной или строч-
ной), за которой могут следовать буквы и цифры.
Только первые шесть символов в имени являются зна-
чащими. За исключением имен, об явленных в опера-
торах fun, все имена являются глобальными. Значе-
ниями имен могут быть числа (вещественные двойной
точности) и цепочки символов; кроме того, имена
могут быть связаны по вводу/выводу (см. ниже
встроенную функцию open).
имя ([выражение [, выражение] ...])
К функциям можно обращаться по имени, за которым
следуют аргументы в скобках, разделенные запятыми.
За исключением встроенных функций (описанных ни-
же), имя должно быть определено при помощи опера-
тора fun. Аргументы функций передаются по значе-
нию.
имя [выражение [, выражение] ...]
Такой синтаксис используется для обращения к мас-
сивам или таблицам (см. ниже описание встроенных
функций для работы с таблицами). Для массивов каж-
дое выражение урезается до целого и используется
как спецификатор для имени. Результирующее обраще-
ние синтаксически эквивалентно имени (то есть мо-
жет употребляться в тех же местах, что и имя); за-
писи a[1,2] и a[1][2] обозначают одно и то же.
Значения урезанных выражений должны быть в преде-
лах от 0 до 32767.
число
Число используется для представления константного
значения. Число записывается в стиле Фортрана и
содержит цифры, десятичную точку (не обязательно)
и, возможно, масштабный множитель, состоящий из
символа e, за которым может следовать характерис-
тика со знаком.
цепочка_символов
Цепочки_символов ограничиваются знаками ". Знак \
позволяет вставлять в цепочку следующие символы:
кавычка (\"), перевод строки (\n), возврат каретки
(\r), пробел (\b) и табуляция (\t). В остальных
случаях символ \ обозначает сам себя.
(выражение)
Скобки используются для того, чтобы изменить поря-
док вычислений.
(выражение, выражение [, выражение ...]) [выражение]
Последнее выражение используется как индекс, чтобы
выбрать один элемент из взятого в круглые скобки
списка выражений, разделенных запятыми. Элементы
списка нумеруются слева, начиная с нуля. Выраже-
ние:
(False, True)[a == b]
имеет значение True, если a равно b.
? выражение
Операция опроса проверяет "успех" вычисления выра-
жения, а не его значение. Ее целесообразно исполь-
зовать для проверки выхода на конец файла (см. ни-
же ПРИМЕРЫ), результата вычисления встроенной
функции и для проверки возврата из определенных
пользователем функций (см. freturn). "Реакция на
прерывание", устанавливаемая данной операцией
(например, конец файла), приводит к немедленному
переходу к самому последнему опросу с возможным
пропуском операторов присваивания или переходом
через уровни вложенности функций.
- выражение
Результатом является значение выражения с обратным
знаком.
++ имя
Увеличивает на единицу значение переменной (или
элемента массива). Результатом является новое зна-
чение.
-- имя
Уменьшает на единицу значение переменной. Резуль-
татом является новое значение.
! выражение
Логическое отрицание значения выражения. Будьте
осторожны, такое выражение может быть воспринято
как запрос на выполнение команды shell'а.
выражение операция выражение
Обращения к общеупотребимым функциям двух аргумен-
тов обозначаются двумя аргументами, которые разде-
ляются операцией, указывающей функцию. За исключе-
нием присваивания, конкатенации и операций сравне-
ния, перед тем, как выполняется операция, оба опе-
ранда преобразуются к целому типу.
Бинарные операции (упорядочены по возрастанию приорите-
та):
= Операция присваивания. Левый операнд должен быть
именем или элементом массива. Результатом является
правый операнд. Последовательные присваивания вы-
полняются справа налево; все другие операции -
слева направо.
_ (подчеркивание). Операция конкатенации.
& | Результатом & (логическое и) является 0, если ка-
кой-нибудь из ее аргументов - 0; результат равен
1, если оба аргумента ненулевые; результатом |
(логическое или) является 0, если оба аргумента
равны нулю; результат равен 1, если какой-нибудь
из аргументов ненулевой. Обе операции трактуют
пустую цепочку символов как 0.
< <= > >= == !=
Операции сравнения (меньше, меньше или равно,
больше, больше или равно, равно, не равно) возвра-
щают 1, если их аргументы находятся в указанном
отношении. В противном случае они возвращают 0.
Допустимы выражения, подобные a>b>c (что эквива-
лентно a>b & b>c). Если оба аргумента являются це-
почками символов, проверяется лексикографическая
упорядоченность.
+ - Сложение и вычитание.
* / %
Умножение, деление и остаток.
^ Возведение в степень.
Встроенные функции
Работа с аргументами
arg(i)
Значение i-го фактического аргумента текущего
уровня вызова функции. На нулевом уровне arg
возвращает i-ый аргумент командной строки (arg (0)
возвращает bs).
narg( )
Возвращает число переданных аргументов. На нулевом
уровне возвращается число аргументов командной
строки.
Математические функции
abs(x)
Абсолютная величина x.
atan(x)
Арктангенс x. Значение между - П/2 и П/2.
ceil(x)
Минимальное целое, не меньшее x.
cos(x)
Косинус x (Углы задаются в радианах).
exp(x)
Экспонента x.
floor(x)
Наибольшее целое число, не превосходящее x.
log(x)
Натуральный логарифм x.
rand( )
Равномерно распределенное между 0 и 1 случайное
число.
sin(x)
Синус x.
sqrt(x)
Квадратный корень из x.
Операции с цепочками символов
size(s)
Размер (длина в байтах) цепочки s.
format(f, a)
Возвращает отформатированное значение a. Предпола-
гается, что f - это спецификация формата в смысле
printf(3S). Рекомендуется использовать только сле-
дующие типы спецификаторов формата: %...f, %...e и
%...s.
index(x, y)
Номер первого символа в x, совпадающего с каким
либо символом из y. Если такого нет, возвращается
0.
trans(s, f, t)
Сопоставляет символы источника s с символами f, и
заменяет их на символы, стоящие в той же позиции
цепочки t. Символы источника, которые не встреча-
ются в f, копируются в результат. Если f длиннее,
чем t, символы источника, которые сопоставляются с
избыточной частью f, не помещаются в результат.
substr(s, начало, ширина)
Подцепочка s с заданными началом и шириной.
match(цепочка_символов, шаблон)
mstring(n)
Шаблон имеет синтаксис, аналогичный регулярным вы-
ражениям команды ed(1). Символы ., [, ] (внутрен-
ние скобки), ^, * и $ являются специальными. Функ-
ция mstring возвращает n-ую (1 n< 10) подцепочку
обрабатываемой цепочки_символов, которая успешно
сопоставлена с фрагментом шаблона, заключенного
между парами символов \( и \), из последнего обра-
щения к match. Шаблоны сопоставляются с началом
цепочки_символов (как если бы все они начинались
символом ^). Функция match возвращает число успеш-
но сопоставленных символов. Пример:
match("a123ab123", ".*\([a-z]\)") == 6
mstring(1) == "b"
Работа с файлами
open(имя, файл, тип)
close(имя)
Аргумент имя должен быть именем переменной в смыс-
ле bs (переданным как цепочка символов). При обра-
щении к функции open в качестве аргумента файл
можно задавать:
1. 0, 1, или 2, что означает стандартный ввод,
стандартный вывод и стандартный протокол соот-
ветственно.
2. Цепочку символов, представляющую имя файла.
3. Цепочку символов с ! в начале, представляющую
команду, которая должна быть выполнена (пос-
редством sh -c).
Аргумент тип должен быть одним из следующих: r
(читать), w (писать), W (писать без перевода стро-
ки), a (добавлять). После того как выполнена функ-
ция close, имя становится обычной переменной. На-
чальные связывания таковы:
open("get", 0, "r")
open("put", 1, "w")
open("puterr", 2, "w")
Примеры приведены ниже.
access(s, m)
Выполняет вызов access(2).
ftype(s)
Возвращает односимвольный индикатор типа файла: f
для обычного файла, p для именованного канала, d
для каталога, b для блочного устройства, c для
символьного устройства.
Таблицы
table(имя, размер)
Таблица в bs - это одномерный массив с ассоциатив-
ным доступом. "Индексами" (их называют также клю-
чами) являются цепочки символов (числа преобразу-
ются в цепочки). Аргумент имя должен быть именем
переменной в смысле bs (переданным как цепочка
символов). Аргумент размер устанавливает минималь-
ное число элементов, которое должно быть размеще-
но. Bs печатает сообщение об ошибке и завершает
работу, когда таблица переполняется.
item(имя, номер)
key( )
Функция item осуществляет доступ к элементам таб-
лицы по их номерам (обычно множество значений клю-
чей не допускает систематического перебора). После
того, как функция item возвратит значение элемента
таблицы, результатом функции key будет "индекс"
(ключ) этого элемента. Аргумент имя нельзя брать в
кавычки. Так как точные размеры таблицы не опреде-
лены, надо использовать операцию опроса, чтобы об-
наружить конец таблицы, например:
table("t", 100)
...
# Если значением переменной word является слово,
# следующее выражение добавляет единицу
# к счетчику этого слова:
++t[word]
...
# Напечатать пары ключ/значение:
for i = 0, ?(s = item(t, i)), ++i if key() \
put = key()_":"_s
iskey(имя, слово)
Проверяет, есть ли ключ слово в таблице имя; возв-
ращает 1, если есть, и 0, если нет.
Прочие функции
eval(цепочка_символов)
Вычисляет свой аргумент как выражение в смысле bs.
Эта функция удобна для преобразования числовых
строк во внутреннюю числовую форму. Eval также мо-
жет использоваться как грубый метод косвенной ад-
ресации. Например, после выполнения операторов
name = "xyz"
eval("++"_name)
значение переменной xyz увеличится на 1. Кроме то-
го, функция eval с предшествующей операцией опроса
позволяет управлять обработкой ошибочных ситуаций.
Результатом выполнения оператора
?eval("open(\"X\", \"XXX\", \"r\")")
будет 0, если файла с именем "XXX" нет (вместо
аварийного завершения программы пользователя).
Следующий фрагмент выполняет переход на метку L
(если она существует):
label="L"
if !(?eval("goto "_label)) puterr = "no label"
plot(запрос, аргументы)
Формирует вывод для устройств, которые поддержива-
ются программой tplot(1G). Допустимы следующие
запросы:
plot(0, терминал)
Определяет, что дальнейший вывод программы plot
должен направляться программе tplot(1G) с аргу-
ментом -Tтерминал.
plot(4)
"Очищает" плоттер.
plot(2, метка)
Ставит метку на текущую точку.
plot(3, x1, y1, x2, y2)
Рисует отрезок между (x1,y1) и (x2,y2).
plot(4, x, y, r)
Рисует круг с центром (x,y) и радиусом r.
plot(5, x1, y1, x2, y2, x3, y3)
Рисует дугу с центром (x1,y1) и концами (x2,y2)
и (x3,y3).
plot(6)
Не реализован.
plot(7, x, y)
Делает точку (x,y) текущей.
plot(8, x, y)
Рисует отрезок из текущей точки в (x,y).
plot(9, x, y)
Рисует точку в (x,y).
plot(10, режим)
Устанавливает заданный режим проведения линий.
plot(11, x1, y1, x2, y2)
Устанавливает левый нижний угол области рисова-
ния в (x1,y1), а правый верхний - в (x2,y2).
plot(12, x1, y1, x2, y2)
Определяет, что соответствующие x (y) координа-
ты должны умножаться на x1 (y1) и затем склады-
ваться с x2 (y2) перед тем, как они изобража-
ются. Первоначальный масштаб - plot(12, 1.0,
1.0, 0.0, 0.0).
Некоторые запросы применимы не ко всем плоттерам.
Все запросы, кроме 0 и 12, реализованы на основе
передачи символов программе tplot(1G). Чтобы полу-
чить дополнительную информацию, см. plot(4).
last( )
В режиме немедленного выполнения возвращает пос-
леднее вычисленное значение.
ПРИМЕРЫ
1. Использование bs в качестве калькулятора:
$ bs
# Расстояние (в дюймах), которое свет
# проходит за наносекунду.
186000 * 5280 * 12 / 1e9
11.78496
# Сложный процент (из 6% за 5 лет
# с 1000 долларов).
int = .06 / 4
bal = 1000
for i = 1 5*4 bal = bal + bal*int
bal - 1000
346.855007
exit
2. Общий вид типичных bs-программ:
# Инициализация:
var1 = 1
open("read", "infile", "r")
...
# Вычисление:
while ?(str = read)
...
next
# Завершение
close("read")
...
# Последний выполняемый оператор (exit или stop):
exit
# Последняя входная строка
run
3. Примеры ввода/вывода:
# Копировать "oldfile" в "newfile".
open("read", "oldfile", "r")
open("write", "newfile", "w")
...
while ?(write = read) ...
...
# закрыть "read" и "write":
close("read")
close("write")
# Канал между командами.
open("ls", "!ls *", "r")
open("pr", "!pr -2 -h 'List'", "w")
while ?(pr = ls) ...
...
# Закрыть файлы:
close("ls")
close("pr")
СМ. ТАКЖЕ
ed(1), sh(1), tplot(1G).
access(2), printf(3S), stdio(3S), plot(4) в Справочнике
программиста.
Более полное описание математических функций см. в раз-
деле 3M Справочника программиста (для возведения в сте-
пень используется функция pow, описанная в exp(3M); па-
кет ввода/вывода используется стандартный.
СЮРПРИЗЫ
"Индексами" неинициализированных элементов таблицы яв-
ляются цепочки из двух символов с восьмеричными кодами
43 и 300, поэтому приведенный пример печати пар ключ/з-
начение будет работать неверно.
В цепочке символов нельзя употребить знак #, поскольку
он служит началом комментария.
|