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

Example 7.12: Nested Conditionals

myfont /Optima eq { %ifelse ptsize 12 eq { %ifelse }{ %else

ptsize 100 gt { %ifelse }{ % else

} ifelse

} ifelse

 

}{ % else

 

} ifelse

 

The second important thing to keep straight in a complicated nested

 

conditional statement is the contents of the operand stack. This is

 

particularly important if you use dup or keep data on the operand stack

 

that must survive into the middle of the conditional somewhere.

 

Otherwise, nested conditionals are fairly straightforward to use.

 

 

TIP

If you use ifelse rather than if, make sure you supply both procedures, and

 

that you think carefully about what is on the operand stack for each of

 

them.

 

 

COMPOUND CONDITIONALS

Compound conditionals are found wherever there is a single condition but many possible else clauses. In other languages, this might be handled by a case statement, but—as you’ve already learned—there is no case operator in the PostScript language.

First, let’s look at an example of a compound conditional implemented in the most straightforward manner, as a series of else clauses. Remember that PostScript is not a compiled language. Therefore, you should try to put the most likely conditions first, since they will be tested in order. Since there is no way to choose from a parallel set of procedure bodies, the only way to implement a compound conditional with ifelse is to nest the conditionals, adding a new test for each else clause. This can get very tricky to maintain, since it may nest very deep to supply all of the required clauses (see Example 7.13).

88

Chapter 7: BUILDING CONDITIONAL STATEMENTS

You can imagine how complicated that would get if you had twenty or thirty different commands to look for. Example 7.14 uses a very slightly different structure for the same conditional that makes it a little flatter and easier to maintain.

Example 7.13: Compound Conditional with ifelse

%read a token from the input stream and look for a command

%like “PRINT”, “QUIT”, or “HELP”.

currentfile 256 string readline token { %ifelse % a token is a command

dup /PRINT eq { %ifelse do_print

}{ %else

dup /QUIT eq { %ifelse do_quit

}{ %else

dup /HELP eq { %ifelse do_help

}{ %else do_unknown

} ifelse

} ifelse

} ifelse }{ %else

(no more commands.) = stop

} ifelse

Example 7.14: Compound Conditional with loop

currentfile 256 string readline token { %ifelse % a token is a command

{ %dummy loop, always exited

dup /PRINT eq { do_print exit } if dup /QUIT eq { do_quit exit } if dup /HELP eq { do_help exit } if do_unknown

exit

} loop }{ %else

(no more commands.) = stop

} ifelse

Chapter 7: BUILDING CONDITIONAL STATEMENTS

89

Example 7.15 presents one more way to set up a compound conditional, one that uses the power and flexibility of the PostScript language, particularly the name lookup and dictionary mechanisms. In this implementation, the multiple cases are stored as procedures in a dictionary (the current dictionary, for simplicity in this example), and the command string is looked up in the current dictionary and executed. Note that this requires only a single conditional (for the unknown case).

Example 7.15: Compound Conditional Using Name Lookup

/commands 4 dict def commands begin /PRINT { do_print } def /QUIT { do_quit } def /HELP { do_help } def

currentfile 256 string readline token { %ifelse % a token is a command

dup where { %ifelse exch get exec

}{ %else do_unknown

} ifelse }{ %else

(no more commands.) = stop end % commands dictionary

} ifelse

As you can see, there are several approaches to setting up a compound conditional. The language is very flexible, but it is a bit of trouble to do without a case statement.

CONCLUDING THOUGHTS

The most important thing to remember about conditionals and the ifelse operator is that the whole construction is interpreted each time it is encountered. The condition (true or false) is computed each time, the two procedure bodies are loaded onto the operand stack, and the ifelse operator pushes one or the other of them onto the operand stack. There’s nothing really magical about the way it works, and the procedure bodies it uses are interchangeable with all other procedures in the PostScript language.

90

Chapter 7: BUILDING CONDITIONAL STATEMENTS

The next chapter presents a look at looping constructs. Loops share many properties with conditionals, since they require procedure bodies as arguments. Some of the concepts learned in this chapter will also apply in the next chapter.

EXERCISES

1.Design a case operator for the PostScript language, and design a procedure that will implement it. Think about the design trade-offs between ease of use (once your case operator exists) versus ease of implementation for you. Supply some simple documentation (comments in your program are good enough) explaining how to use your new case operator.

2.The following procedure emulates the setcmykcolor language extension by using setrgbcolor and doing a simple conversion. Design a conditional statement with the where operator that will define this procedure only if the setcmykcolor operator does not already exist.

/setcmykcolor { %def 1 sub 4 1 roll

3 { %repeat

3 index add neg dup 0 lt {pop 0} if 3 1 roll

}repeat setrgbcolor pop

}bind def

3.The “standard” procedure used with the image operator uses the readhexstring operator to get a line of data from the input file. The trouble is, it ignores the boolean returned by readhexstring, which is not really a good idea. Please rewrite this procedure body to check for the end-of-file condition reported by the readhexstring operator. (The second line of hex data is incomplete in this example, causing an error in the execution of the program as it stands. Fill out the line of data to see what the program is supposed to do.)

/picstr 16 string def

100 100 translate 100 900 scale 16 2 8 [ 16 0 0 16 0 0 ]

{ currentfile picstr readhexstring pop } image 00FF00FF00FF00FF00FF00FF00FF00FF 00FF00FF00FF00FF

Chapter 7: BUILDING CONDITIONAL STATEMENTS

91

92

Chapter 7: BUILDING CONDITIONAL STATEMENTS