Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Reid G.C.Thinking in PostScript.1990.pdf
Скачиваний:
17
Добавлен:
23.08.2013
Размер:
846.44 Кб
Скачать

Although the run operator can perform precisely this task, the technique of looping through a file is still useful in many situations.

Example 13.5: Executing Data Found in a File

/datafile (/usr/local/lib/sample.ps) (r) file def /buffer 1024 string def

{ %loop

datafile buffer readline { %ifelse

cvx exec % execute the line of data just read }{ %else

datafile closefile exit

}ifelse

}bind loop

This simplistic program won’t work with all data files, since it attempts to execute exactly one line of the program at a time. If any delimiters such as parentheses or braces are opened on one line but not closed until a subsequent line, the code will not execute correctly.

TURNING INSTRUCTIONS INTO DATA

A good example of turning program instructions into data is the task of listing (or printing out) a PostScript program so you can look at it on paper. You may have already run into this situation if you have worked much with the PostScript language. The previous example program that works as a simple line printer emulator actually does convert PostScript program code into data for typesetting if you should happen to feed it a file that contains PostScript. Example 13.6 shows this same emulator with slightly different data at the end. You might have to look closely to see that last ten lines of the program are not executed, but are printed on the page.

Figure 13.1 shows what the top of the output page would look like when the program in Example 13.6 is executed.

Chapter 13: PROGRAM DATA AND INSTRUCTIONS

161

Example 13.6: Instructions as Data (to be Line Printed)

% even more line printer emulation /left 36 def % margins /bottom 36 def

/top 792 48 sub def /buffer 1024 string def

/setup

% - setup -

{ %def

 

/Courier 12 selectfont left top moveto

} bind def

/emulate % - emulate - { %def

{ %loop

currentfile buffer readline { %ifelse

(X) search { %ifelse

gsave show grestore pop showpage setup

} if

gsave show grestore 0 -14 rmoveto

currentpoint exch pop bottom le { %if showpage setup

} if }{ %else

showpage exit

} ifelse

}loop

}bind def

%everything after the following “setup emulate” line will be printed on

%paper instead of executed:

setup emulate %!

/datafile (/usr/local/lib/sample.ps) (r) file def /buffer 1024 string def

{ %loop

datafile buffer readline { %ifelse

cvx exec % execute the line from the file }{ %else

datafile closefile exit

}ifelse

}bind loop

162

Chapter 13: PROGRAM DATA AND INSTRUCTIONS

Figure 13.1: Output of Example 13.6

output page

%!

/datafile (/usr/local/lib/sample.ps) (r) file def /buffer 1024 string def

{ %loop

datafile buffer readline { %ifelse

cvx exec % execute the line from the file }{ %else

datafile closefile exit

}ifelse

}bind loop

DATA CONVERSIONS

Quite a few PostScript operators convert one data type to another. Once you know that they exist, they are easy enough to use. There are also some fancy ways to accomplish data conversion in the next few sections. But first, some examples of common data conversions using the appropriate PostScript operators (see Example 13.7).

Example 13.7: Converting Strings to Numbers

(12456) cvi

% 12456

(2898.87) cvi

% 2899

(117.5) cvr

% 117.5

(120) cvr

% 120.0

(5837.9) cvx exec

% 5837.9

(612.0) token pop exch pop

% 612.0

(612.0 792.0 moveto) token pop

 

exch token pop exch pop

% 612.0 792.0

Example 13.8 shows the conversion of decimal numbers to an octal or hexadecimal representation (the result is a string, since octal numbers do not exist in the interpreter except as notation).

Chapter 13: PROGRAM DATA AND INSTRUCTIONS

163

Example 13.8: Converting Decimal Numbers to Octal or Hex

/scratch (0000) def

 

32 8 scratch cvrs

% (40)

193 16 scratch cvrs

% (C1)

(y) 0 get 16 scratch cvrs

% (79)

The program segments shown in Example 13.9 show how to convert back and forth between name and string data types, which are very similar in content. Remember that the slash (/) character often seen in programs is not really part of the name, but just the syntax used to express a literal name to the interpreter.

Example 13.9: Converting between Names and Strings

/scratch 128 string def

 

/Palatino-Roman scratch cvs

% (Palatino-Roman)

(Palatino-Roman) cvn

% /Palatino-Roman

Example 13.10 shows one way to convert an array to a procedure. Since arrays are built in real time, you have to be careful not to accidentally execute something that you intend to be placed on the operand stack.

Example 13.10: Converting Arrays to Procedures

% careful about executable names:

[

0 0 /moveto cvx

/Optima 24.0 /selectfont cvx (Optima sample) /show cvx

] cvx

The cvs operator converts arbitrary data types to strings, which can be useful for printing out data. However, the cvs operator cannot convert composite objects like dictionaries or arrays to a string representation. An example of this simple kind of conversion is given in Example 13.11, with a workaround for composite objects. A better approach would be to use the type operator to explicitly determine the type of the object, then take some appropriate action to convert it to a string. Exercise 3 at the end of this chapter explores this concept more fully.

164

Chapter 13: PROGRAM DATA AND INSTRUCTIONS