bfcat - encode a file as a brainf*** program

Brainfuck, 55 51 bytes

,[>+++[>+++++++<-]>[<++>>+++<-]<+<[>.<-]>+++.>>-.,]

Try it online!

Example output for hi (without the linefeeds):

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++.>++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>

Explanation

This moves across the tape while writing the program. The surrounding ,[...,] is a standard input loop. For each character, we use four cells:

[... x a b c ...]

where x is the cell we write the input to.

>+++[>+++++++<-]

This part uses cell a to write a 21 into cell b via a standard multiplication of 3 and 7.

>[<++>>+++<-]

Now we use that 21 to write 42 into a and 63 into c by multiplying by 2 and 3 respectively. Then <+< moves back to cell x while turning the 42 into a 43 (the code point of +). Recap:

[... x 43 21 63 ...]

Now the main output loop:

[>.<-]

That is, while decrementing x we print one + each time.

>+++.

After we're done we reuse the + cell, by adding 3 to give ..

>>-.

Finally, we move to the 63, decrement it to 62 (>) and output that as well. The next iteration will use this cell as x.


Brainfuck, 39 33 32 31 bytes

-[-[>]<--<--],[[>.<+]>+.--.+<,]

The algorithm that places 45 on the tape is taken from Esolang's Brainfuck constants.

This answer assumes that the output program's interpreter has wrapping, bounded cells; and that , zeroes the current cell (implying that the output program is run without input). Try it online!

For a (longer) solution that works unconditionally, see my other answer.

Test run

For input Code Golf, the following output is generated.

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------.,-------------------------------------------------------------------------------------------------------------------------------------------------.,------------------------------------------------------------------------------------------------------------------------------------------------------------.,-----------------------------------------------------------------------------------------------------------------------------------------------------------.,--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------.,-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------.,-------------------------------------------------------------------------------------------------------------------------------------------------.,----------------------------------------------------------------------------------------------------------------------------------------------------.,----------------------------------------------------------------------------------------------------------------------------------------------------------.,

Try it online!

How it works

We begin by putting the integer 45 (character code of -) into a cell of the tape. The following code achieves this.

-      Decrement cell 0, setting it to 255.
[      While the cell under the head in non-zero:
  [>]    Advance to the next zero cell.
  <--    Decrement the cell to its left.
  <--    Decrement the next cell to the left.
]

Before we enter the loop, the tape looks like this.

         v
000 000 255

These three cells – -2, -1, and 0 – are the only ones we'll use in this program.

In the first each iteration of the loop, the rightmost cell is, then that cell and middle cell are decremented twice, leaving the following state.

     v
000 254 252

In the next 126 iterations, the initial - decrements the middle cell, [>]< jumps to the rightmost cell, and --<-- decrements the middle and the right cell. As a result, 3 is subtracted from the middle cell (modulo 256) and 2 is subtracted from the rightmost cell.

Since 254 ÷ 3 (mod 256) = (254 + 256) ÷ 3 = 510 ÷ 3 = 170 and 252 ÷ 3 = 84, the rightmost cell is zeroed out before the middle one, leaving the following state.

     v
000 132 000

Similarly to the first iteration of the loop, the next iteration now subtracts 3 from the middle cell and 2 from the leftmost cell, placing the head on the leftmost cell.

 v
254 129 000

Subsequent iterations, as in the 126 iteration before them, subtract 3 from the leftmost cell and 2 from the rightmost cell.

Since 254 ÷ 3 (mod 256) = 170 and 129 ÷ 2 (mod 256) is undefined, this is done 170 times, leaving the following state.

 v
000 045 000

The cell under the head is zero; the loop ends.

Now we're ready to generate output.

,      Read a character from STDIN and put it the leftmost cell.
[        While the leftmost cell is non-zero:
  [        While the leftmost cell is non-zero:
    >.     Print the content of the middle cell ('-').
    <-     Increment the leftmost cell.
  ]      If the leftmost cell held n, the above will print 256 - n minus signs
         which, when executed, will put n in cell 0 of the output program.
  >      Increment the middle cell, setting it to 46 ('.').
  .      Print its content ('.').
  --     Decrement the middle cell twice, setting it to 44 (',').
  .      Print its content (',').
         When executed, since the output program receives no input, the above
         will zero cell 0 of the output program.
  +      Increment the second cell, setting it back to 45 ('-').
  <,     Go back to the leftmost cell and read another character from STDIN.
]      Once EOF is reached, this will put 0 in the leftmost cell, ending the loop.

Jelly, 8 bytes

O”+ẋp“.>

Try it online!

Sample run

For input hi, this program prints

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++.+++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++>++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++>

(without the linefeeds) which, in turn, prints hi.

How it works

O”+ẋp“.>  Main link. Argument: s (string)

O         Ordinal; convert each character in s into its code point.
 ”+       Yield the character '+'.
   ẋ      Repeat '+' k times, for each k in the code points.
     “.>  Yield the string ".>".
    p     Take the Cartesian product of both results.