Брайан Керниган - UNIX — универсальная среда программирования

Тут можно читать онлайн Брайан Керниган - UNIX — универсальная среда программирования - бесплатно ознакомительный отрывок. Жанр: comp-osnet, издательство Финансы и статистика, год 1992. Здесь Вы можете читать ознакомительный отрывок из книги онлайн без регистрации и SMS на сайте лучшей интернет библиотеки ЛибКинг или прочесть краткое содержание (суть), предисловие и аннотацию. Так же сможете купить и скачать торрент в электронном формате fb2, найти и слушать аудиокнигу на русском языке или узнать сколько частей в серии и всего страниц в публикации. Читателям доступно смотреть обложку, картинки, описание и отзывы (комментарии) о произведении.
  • Название:
    UNIX — универсальная среда программирования
  • Автор:
  • Жанр:
  • Издательство:
    Финансы и статистика
  • Год:
    1992
  • Город:
    Москва
  • ISBN:
    5-289-00253-4
  • Рейтинг:
    5/5. Голосов: 81
  • Избранное:
    Добавить в избранное
  • Отзывы:
  • Ваша оценка:
    • 100
    • 1
    • 2
    • 3
    • 4
    • 5

Брайан Керниган - UNIX — универсальная среда программирования краткое содержание

UNIX — универсальная среда программирования - описание и краткое содержание, автор Брайан Керниган, читайте бесплатно онлайн на сайте электронной библиотеки LibKing.Ru

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

Для программистов-пользователей операционной системы UNIX.

UNIX — универсальная среда программирования - читать онлайн бесплатно ознакомительный отрывок

UNIX — универсальная среда программирования - читать книгу онлайн бесплатно (ознакомительный отрывок), автор Брайан Керниган
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

defnonly(s) /* warn if illegal definition */

char *s;

{

if (!indef)

execerror(s, "used outside definition");

}

Переменная indefопределена в hoc.yи принимает значения в действиях для опред .

К лексическому анализатору добавлены средства проверки аргументов: символ $, за которым следует чисто для строки в кавычках. Последовательности в строках, начинающиеся с обратной дробной черты, например \n, обрабатываются функцией backslash:

yylex() /* hoc6 */

...

if (c == '$') { /* argument? */

int n = 0;

while (isdigit(c=getc(fin)))

n = 10 * n + c — '0';

ungetc(с, fin);

if (n == 0)

execerror("strange $...", (char*)0);

yylval.narg = n;

return ARG;

}

if (c == '"') { /* quoted string */

char sbuf [100], *p, *emalloc();

for (p = sbuf; (c=getc(fin)) != '"'; p++) {

if (с == '\n' || c == EOF)

execerror("missing quote", "");

if (p >= sbuf + sizeof (sbuf) - 1) {

*p = '\0';

execerror("string too long", sbuf);

}

*p = backslash(c);

}

*p = 0;

yylval.sym = (Symbol*)emalloc(strlen(sbuf)+1);

strcpy(yylval.sym, sbuf);

return STRING;

}

...

backslash(c) /* get next char with \'s interpreted */

int c;

{

char *index(); /* 'strchr()' in some systems */

static char transtab[] = "b\bf\fn\nr\rt\t";

if (c != '\\')

return c;

c = getc(fin);

if (islower(c) && index(transtab, c))

return index(transtab, с)[1];

return c;

}

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

Остальные изменения сосредоточены главным образом в файле code.c, хотя несколько имен функций добавляется к файлу hoc.h. Машина остается той же, но с дополнительным стеком для хранения последовательности вложенных вызовов функций и процедур (проще ввести второй стек, чем загружать больший объем информации в существующий). Начало файла code.cвыглядит так:

$ cat code.c

#include "hoc.h"

#include "y.tab.h"

#include

#define NSTACK 256

static Datum stack[NSTACK]; /* the stack */

static Datum *stackp; /* next free spot on stack */

#define NPROG 2000

Inst prog[NPROG]; /* the machine */

Inst *progp; /* next free spot for code generation */

Inst *pc; /* program counter during execution */

Inst *progbase = prog; /* start of current subprogram */

int returning; /* 1 if return stmt seen */

typedef struct Frame { /* proc/func call stack frame */

Symbol *sp; /* symbol table entry */

Inst *retpc; /* where to resume after return */

Datum *argn; /* n-th argument on stack */

int nargs; /* number of arguments */

} Frame;

#define NFRAME 100 Frame frame[NFRAME];

Frame *fp; /* frame pointer */

initcode() {

progp = progbase;

stackp = stack;

fp = frame;

returning = 0;

}

...

$

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

$ cat hoc.h

typedef struct Symbol { /* symbol table entry */

char *name;

short type;

union {

double val; /* VAR */

double (*ptr)(); /* BLTIN */

int (*defn)(); /* FUNCTION, PROCEDURE */

char *str; /* STRING */

} u;

struct Symbol *next; /* to link to another */

} Symbol;

$

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

define(sp) /* put func/proc in symbol table */

Symbol *sp;

{

sp->u.defn = (Inst)progbase; /* start of code */

progbase = progp; /* next code starts here */

}

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

call() /* call a function */

{

Symbol *sp = (Symbol*)pc[0]; /* symbol table entry */

/* for function */

if (fp++ >= &frame[NFRAME-1])

execerror(sp->name, "call nested too deeply");

fp->sp = sp;

fp->nargs = (int)pc[1];

fp->retpc = pc + 2;

fp->argn = stackp - 1; /* last argument */

execute(sp->u.defn);

returning = 0;

}

Создаваемая структура показана на рис. 8.2.

Рис 82 Структуры данных для вызова процедуры В конце концов произойдет - фото 7

Рис. 8.2 : Структуры данных для вызова процедуры

В конце концов произойдет возврат из вызываемой программы при выполнении procretили funcret:

funcret() /* return from a function */

{

Datum d;

if (fp->sp->type == PROCEDURE)

execerror(fp->sp->name, "(proc) returns value");

d = pop(); /* preserve function return value */

ret();

push(d);

}

procret() /* return from a procedure */

{

if (fp->sp->type == FUNCTION)

execerror(fp->sp->name(func) returns no value");

ret();

}

Функция retудаляет аргументы из стека, сохраняет указатель на образ стека fpи устанавливает счетчик команд:

ret() /* common return from func or proc */

{

int i;

for (i = 0; i < fp->nargs; i++)

pop(); /* pop arguments */

pc = (Inst*)fp->retpc;

--fp;

returning = 1;

}

Некоторые программы интерпретатора нуждаются в небольших поправках для учета ситуаций, когда происходит возврат во вложенных операторах. Решение не элегантно, но верно и состоит во введении признака с именем returning, который принимает значение 1 при обнаружении оператора return. Выполнение, организуемое функциями ifcode, whilecode, execute, завершается раньше, если установлен признак returning; в функции callон обнуляется.

ifcode() {

Datum d;

Inst *savepc = pc; /* then part */

execute(savepc+3); /* condition */

d = pop();

if (d.val)

execute(*((Inst**)(savepc)));

else if (*((Inst**)(savepc+1))) /* else part? */

execute(*((Inst**)(savepc+1)));

if (!returning)

pc = *((Inst**)(savepc+2)); /* next stmt */

}

whilecode() {

Datum d;

Inst *savepc = pc;

execute(savepc+2); /* condition */

d = pop();

while (d.val) {

execute(*((Inst**)(savepc))); /* body */

if (returning)

break;

execute(savepc+2); /* condition */

d = pop();

}

if (!returning)

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать


Брайан Керниган читать все книги автора по порядку

Брайан Керниган - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки LibKing.




UNIX — универсальная среда программирования отзывы


Отзывы читателей о книге UNIX — универсальная среда программирования, автор: Брайан Керниган. Читайте комментарии и мнения людей о произведении.


Понравилась книга? Поделитесь впечатлениями - оставьте Ваш отзыв или расскажите друзьям

Напишите свой комментарий
x