Quantcast
Channel: Stupid Compiler
Viewing all articles
Browse latest Browse all 10

A Quine in PDF

$
0
0

A quine is a self-reproducing program. One whose output is the source of the program itself. The wikipedia link above goes into more depth.

I’m full of mucus and my head is floating, so instead of working on stuff that matters I spent a few hours working out a quine in PDF. Since I wasted so much time making it, I’ve decided to waste some more trying to explain it. I think to understand this, you’ll need to either already be familiar with the PDF format or you will need to grab the specification and follow along with me.

I’ll go object by object and try to explain how it works at each object.

  • Object 1 – Catalog dictionary
  • Object 2 – Pages dictionary
  • Object 3 – Page dictionary
    • Contains references to XObjects defined in objects 9 and 10
    • Font is defined in object 4
    • Content stream for this page is defined in object 5
    • The page is extra long (/MediaBox [0 0 612 1600]) to fit the whole quine in a single page
  • Object 4 – Font dictionary
  • Object 5 – Content stream for page defined by object 3
    • Draws the entire page — this is “main”
    • Overall flow:
      • \X4 Do – Call XObject to draw the raw file up to the start of object 9.
      • \X3 Do – Call XObject to draw the commands that draw the raw file up to the start of object 9.
      • Draw the bits in between the prologue of object 9′s content stream and the start of object 10.
      • \X3 Do – Call XObject to draw the commands that draw the raw file up to the start of object 9.
      • Draw the prologue of the file. This includes the end of object 10 and the xref table.
  • Object 6 – A NOP XObject stream
  • Object 7 – An XObject stream that draws the first half of the drawing commands to draw a line
    • To avoid putting the left parenthesis (0×28) in a normal string where it would have to be escaped, a hex string (<28>) is used.
  • Object 8 – An XObject stream that draws the second half of the drawing commands to draw a line
    • Again, to avoid putting the right parenthesis (0×29) in a normal string where it would have to be escaped, a hex string (<29>) is used.
  • Object 9 and 10 – XObject streams that print the first part of the PDF file and the drawing commands that print the first part of the PDF file
    • The streams for these two objects are intentionally identical. Their dictionaries define different object for the X1 and X2 objects used in the streams. To print the raw pdf lines, a NOP XObject (object 6) is used for both. To print the drawing commands used to print the raw pdf, the prefix and suffix are defined by objects 7 and 8.

That still seems horribly unclear. Hrm. The main idea is to use the Form XObject object as a macro to easily draw the pdf “escaped” or “unescaped” (to draw the commands to draw a string or just the string). The extra wrench is that the XObjects do not inherit any values from the calling stream. This means we can’t call the same XObject twice to draw the escaped and unescaped versions. Instead, we create two versions with identical streams but different Resource dictionaries (defining escaped or unescaped).

Well, I think that’s the best my medicated ass is going to do. Please leave comments with the bits that are unclear.

EDIT: For quines in many languages, check out The Quine Page.



Viewing all articles
Browse latest Browse all 10

Trending Articles