Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Creating a Quine in QB64PE
#1
A "quine" is a program that when you run it, generates a listing of itself, such that if you took its output and copied into QB64, it would produce the same thing, itself.

Well, I tried writing one, yeah I could get the program to list itself, but generating the data to allow that program to display itself, and have it look exactly the same is the problem.  Because you have to act one step back, meaning if you have a string, you have to enclose it in quotation marks, which means you have to show the quote mark, Chr$(34). It's still a pain.

So I decided to see other ways this could be done. And one said to write a program to list itself as contents from an array. That made it trivial.

What I did was write the program to list itself. But now it needs the data. So to get that, I wrote another program. This one reads a file and converts it into DATA statements containing the byte values as data statements. I copied them, added an extra 0 at the end as an end-of-file sentinel, and sure enough, it works perfectly.

First, here is the program, which I call dataconvert.bas, that translates a file into data statements:
Code: (Select All)

$Console:Only
'$Include:'Common_Dialog_Prefix.bi'
ReDim As _Unsigned _Byte Prg(1), L
Dim As Long I, J, K, Size


' Invoke Open Read File dialog
Filter$ = "Basic Programs (*.bas,bi.bm)|*.bas,*.bi,*.bm|All files (*.*)|*.*"
Flags& = OFN_FILEMUSTEXIST + OFN_NOCHANGEDIR + OFN_READONLY '    add flag constants here
F$ = GetOpenFileName$("Select name of Basic/QB64/qb64pe source code file", ".\", Filter$, 1, Flags&, Hwnd&)

If F$ = "" Then
    Print "Operation cancelled."
    End
End If

Open F$ For Binary Access Read As #1
I = LOF(1)
ReDim Prg(1 To I)
Get #1, , Prg()
Close #1

For J = 1 To I
    If L = 0 Then Print "Data ";
    Print LTrim$(Str$(Prg(J)));
    If J < I Then
        L = L + 1
        If L = 20 Then
            Print
            L = 0
        Else
            Print ",";
        End If
    Else
        Print
    End If
Next

End

'$Include:'Common_Dialog_Suffix.bi'

The files Common_Dialog_Prefix.bi and  Common_Dialog_Suffix.bi are included in the attached archive, and simply enable the use of the Open File dialog on Windows.

Now, here is the program to list itself:

Code: (Select All)

$Console:Only
Option _Explicit
Dim As _Unsigned _Byte Prg(1 To 100000), L
Dim As Long I, J, K

Do
    I = I + 1
    Read Prg(I)
    If Prg(I) = 0 Then Exit Do
Loop


For J = 1 To I
    Print Chr$(Prg(J));
Next

For J = 1 To I
    If L = 0 Then Print "Data ";
    Print LTrim$(Str$(Prg(J)));
    If J < I Then
        L = L + 1
        If L = 20 Then
            Print
            L = 0
        Else
            Print ",";
        End If
    Else
        Print
    End If
Next

End

For brevity, the data statements are stripped out here, but are included in the copy below. If you want to try this, be sure you include a 0 as the last data item.

Writing a quine was a fun intellectual enterprise, and I'll probably do a different one soon. Doing this one gave me ideas on how to fix the other one. I hope you find looking at/exploring this one as much fun as I had writing it!


Paul


Attached Files
.zip   Quine2.zip (Size: 4.33 KB / Downloads: 25)
While 1
   Fix Bugs
   report all bugs fixed
   receive bug report
end while
Reply
#2
Save as "untitled.bas"

Code: (Select All)
Open "untitled.bas" For Input As #1
While Not EOF(1)
    Line Input #1, junk$
    Print junk$
Wend
Reply
#3
If you're using the newest versions of QB64PE, there's also the simple $EMBED command.  Simply embed your source in the EXE and have a routine to print that to screen/file as needed/wanted.
Reply
#4
(04-29-2024, 04:10 PM)SMcNeill Wrote: Save as "untitled.bas"

Code: (Select All)
Open "untitled.bas" For Input As #1
While Not EOF(1)
    Line Input #1, junk$
    Print junk$
Wend
That's cheating! Technically, the quine itself is supposed to be able to display itself without accessing an external file.
While 1
   Fix Bugs
   report all bugs fixed
   receive bug report
end while
Reply




Users browsing this thread: 1 Guest(s)