`
Читать книги » Книги » Компьютеры и Интернет » Программное обеспечение » Брайан Керниган - UNIX — универсальная среда программирования

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

1 ... 90 91 92 93 94 ... 103 ВПЕРЕД
Перейти на страницу:

 char *p, *malloc();

 p = malloc(n);

 if (p == 0)

  execerror("out of memory", (char*)0);

 return p;

}

3.6 hoc5

3.6.1 code.c

#include "hoc.h"

#include "y.tab.h"

#define NSTACK 256

static Datum stack[NSTACK];

static Datum *stackp;

#define NPROG 2000

Inst prog[NPROG];

static Inst *pc;

Inst *progp;

initcode() {

 progp = prog;

 stackp = stack;

}

push(d)

 Datum d;

{

 if (stackp >= &stack[NSTACK])

  execerror("stack too deep", (char*)0);

 *stackp++ = d;

}

Datum pop() {

 if (stackp == stack)

  execerror("stack underflow", (char*)0);

 return *--stackp;

}

constpush() {

 Datum d;

 d.val = ((Symbol*)*pc++)->u.val;

 push(d);

}

varpush() {

 Datum d;

 d.sym = (Symbol*)(*pc++);

 push(d);

}

whilecode() {

 Datum d;

 Inst *savepc = pc; /* loop body */

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

 d = pop();

 while (d.val) {

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

  execute(savepc+2);

  d = pop();

 }

 pc = *((Inst**)(savepc+1)); /* next statement */

}

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)));

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

}

bltin() {

 Datum d;

 d = pop();

 d.val = (*(double(*)())(*pc++))(d.val);

 push(d);

}

eval() /* Evaluate variable on stack */ {

 Datum d;

 d = pop();

 if (d.sym->type != VAR && d.sym->type != UNDEF)

  execerror("attempt to evaluate non-variable", d.sym->name);

 if (d.sym->type == UNDEF)

  execerror("undefined variable", d.sym->name);

 d.val = d.sym->u.val;

  push(d);

}

add() {

 Datum d1, d2;

 d2 = pop();

 d1 = pop();

 d1.val += d2.val;

 push(d1);

}

sub() {

 Datum d1, d2;

 d2 = pop();

 d1 = pop();

 d1.val -= d2.val;

 push(d1);

}

mul() {

 Datum d1, d2;

 d2 = pop();

 d1 = pop();

 d1.val *= d2.val;

 push(d1);

}

div() {

 Datum d1, d2;

 d2 = pop();

 if (d2.val == 0.0)

  execerror("division by zero", (char*)0);

 d1 = pop();

 d1.val /= d2.val;

 push(d1);

}

negate() {

 Datum d;

 d = pop();

 d.val = -d.val;

 push(d);

}

gt() {

 Datum d1, d2;

 d2 = pop();

 d1 = pop();

 d1.val = (double)(d1.val > d2.val);

 push(d1);

}

lt() {

 Datum d1, d2;

 d2 = pop();

 d1 = pop();

 d1.val = (double)(d1.val < d2.val);

 push(d1);

}

ge() {

 Datum d1, d2;

 d2 = pop();

 d1 = pop();

 d1.val = (double)(d1.val >= d2.val);

 push(d1);

}

le() {

 Datum d1, d2;

 d2 = pop();

 d1 = pop();

 d1.val = (double)(d1.val <= d2.val);

 push(d1);

}

eq() {

 Datum d1, d2;

 d2 = pop();

 d1 = pop();

 d1.val = (double)(d1.val == d2.val);

 push(d1);

}

ne() {

 Datum d1, d2;

 d2 = pop();

 d1 = pop();

 d1.val = (double)(d1.val != d2.val);

 push(d1);

}

and() {

 Datum d1, d2;

 d2 = pop();

 d1 = pop();

 d1.val = (double)(d1.val != 0.0 && d2.val != 0.0);

 push(d1);

}

or() {

 Datum d1, d2;

 d2 = pop();

 d1 = pop();

 d1.val = (double)(d1.val != 0.0 || d2.val != 0.0);

 push(d1);

}

not() {

 Datum d;

 d = pop();

 d.val = (double)(d.val == 0.0);

 push(d);

}

power() {

 Datum d1, d2;

 extern double Pow();

 d2 = pop();

 d1 = pop();

 d1.val = Pow(d1.val, d2.val);

 push(d1);

}

assign() {

 Datum d1, d2;

 d1 = pop();

 d2 = pop();

 if (d1.sym->type != VAR && d1.sym->type != UNDEF)

  execerror("assignment to non-variable", d1.sym->name);

 d1.sym->u.val = d2.val;

 d1.sym->type = VAR;

 push(d2);

}

print() {

 Datum d;

 d = pop();

 printf("t%.8gn", d.val);

}

prexpr() /* print numeric value */

{

 Datum d;

 d = pop();

 printf("%.8gn", d.val);

}

Inst *code(f) /* install one instruction or operand */

 Inst f;

{

 Inst *oprogp = progp;

 if (progp >= &prog[NPROG])

  execerror("expression too complicated", (char*)0);

 *progp++ = f;

 return oprogp;

}

execute(p)

 Inst *p;

{

 for (pc = p; *pc != STOP; ) (*(*pc++))();

}

3.6.2 fib

{

 a=0

 b=1

 while(b<1000) {

  c=b

  b=a+b

  a=c

  print(c)

 }

}

3.6.3 fib2

{

 n=0

 a=0

 b=1

 while(b<10000000){

  n=n+1

  c=b

  b=a+b

  a=c

  print(b)

 }

 print(n)

}

3.6.4 hoc.h

typedef struct Symbol { /* symbol table entry */

 char *name;

 short type; /* VAR, BLTIN, UNDEF */

 union {

  double val; /* if VAR */

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

 } u;

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

} Symbol;

Symbol *install(), *lookup();

typedef union Datum { /* interpreter stack type */

 double val;

 Symbol *sym;

} Datum;

extern Datum pop();

typedef int (*Inst)(); /* machine instruction */

#define STOP (Inst)0

extern Inst prog[], *progp, *code();

extern eval(), add(), sub(), mul(), div(), negate(), power();

extern assign(), bltin(), varpush(), constpush(), print();

extern prexpr();

extern gt(), lt(), eq(), ge(), le(), ne(), and(), or(), not();

extern ifcode(), whilecode();

3.6.5 hoc.y

%{

#include "hoc.h"

#define code2(c1,c2) code(c1); code(c2)

#define code3(c1,c2,c3) code(c1); code(c2); code(c3)

%}

%union {

 Symbol *sym; /* symbol table pointer */

 Inst *inst; /* machine instruction */

}

%token <sym> NUMBER PRINT VAR BLTIN UNDEF WHILE IF ELSE

%type <inst> stmt asgn expr stmtlist cond while if end

%right '='

%left OR

%left AND

%left GT GE LT LE EQ NE

%left '+' '-'

%left '*' '/'

%left UNARYMINUS NOT

%right

%%

list: /* nothing */

 | list 'n'

 | list asgn 'n' { code2(pop, STOP); return 1; }

 | list stmt 'n' { code(STOP); return 1; }

 | list expr 'n' { code2(print, STOP); return 1; }

 | list error 'n' { yyerrok; }

 ;

asgn: VAR '=' expr { $$=$3; code3(varpush,(Inst)$1.assign); }

 ;

stmt: expr { code(pop); }

 | PRINT expr { code(prexpr); $$ = $2; }

 | while cond stmt end {

  ($1)[1] = (Inst)$3; /* body of loop */

  ($1)[2] = (Inst)$4;

 } /* end, if cond fails */

 | if cond stmt end { /* else-less if */

  ($1)[1] = (Inst)$3; /* thenpart */

  ($1)[2] = (Inst)$4;

 } /* end, if cond fails */

 | if cond stmt end ELSE stmt end { /* if with else */

  ($1)[1] = (Inst)$3; /* thenpart */

  ($1)[2] = (Inst)$6; /* elsepart */

  ($1)[3] = (Inst)$7;

 } /* end, if cond fails */

 | '{' stmtlist '}' { $$ = $2; }

 ;

cond: '(' expr ')' { code(STOP); $$ = $2; }

 ;

while: WHILE { $$ = code3(whilecode, STOP, STOP); }

 ;

if: IF { $$=code(ifcode); code3(STOP, STOP, STOP); }

 ;

end: /* nothing */ { code(STOP); $$ = progp; }

 ;

stmtlist: /* nothing */ { $$ = progp; }

 | stmtlist 'n'

 | stmtlist stmt

 ;

expr: NUMBER { $$ = code2(constpush, (Inst)$1); }

1 ... 90 91 92 93 94 ... 103 ВПЕРЕД
Перейти на страницу:

Откройте для себя мир чтения на siteknig.com - месте, где каждая книга оживает прямо в браузере. Здесь вас уже ждёт произведение Брайан Керниган - UNIX — универсальная среда программирования, относящееся к жанру Программное обеспечение. Никаких регистраций, никаких преград - только вы и история, доступная в полном формате. Наш литературный портал создан для тех, кто любит комфорт: хотите читать с телефона - пожалуйста; предпочитаете ноутбук - идеально! Все книги открываются моментально и представлены полностью, без сокращений и скрытых страниц. Каталог жанров поможет вам быстро найти что-то по настроению: увлекательный роман, динамичное фэнтези, глубокую классику или лёгкое чтение перед сном. Мы ежедневно расширяем библиотеку, добавляя новые произведения, чтобы вам всегда было что открыть "на потом". Сегодня на siteknig.com доступно более 200000 книг - и каждая готова стать вашей новой любимой. Просто выбирайте, открывайте и наслаждайтесь чтением там, где вам удобно.

Комментарии (0)