Self-print code for documentation ?

Status
Not open for further replies.

Jp3141

Well-known member
I suspect this is not possible, but is there a way (in the Arduino environment) to have a program print its own source code for documentation purposes ? I'd like to be able to do this as part of the standard compile process, not as an extra step.

I have many programs on various Teensy's and it's hard to keep track of which Teensy has which version of code. If the program could print (most of ?) its own source code upon startup, I could save myself some confusion.

While there are some examples of programs that print their own code (quine), these are not arbitrary programs, and my requirement is not that it print exactly, but something that I can use to recover source if needed.
 
If you use a source code control system like cvs, you might be able to have the source code control system put out an identifying symbol. For example, I've been using cvs for years, and if I put '$Header$' in the source, cvs will put in a string with the filename, revision, etc. into the source. Of course this means you will have to check in the files to bump the revision number.

You might use it as follows:

Code:
static const char header[] = "$Header$ compiled on " __DATE__ " " __TIME__;

void setup (void)
{
  Serial.begin (9600);

  // wait up to 3 seconds for the Serial device to become available
  while (!Serial && (millis () <= 3000))
    ;
  Serial.println (header);
  // ..
}
 
I think you are right … not possible.

I have this in most of my sketches to at least point to the source file when a Teensy is plugged in:
Code:
 while (!Serial && millis() < 5000 );
 Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);
 
While there are some examples of programs that print their own code (quine), these are not arbitrary programs, and my requirement is not that it print exactly, but something that I can use to recover source if needed.

Several people have requested this over the years. I'm considering adding it. This is a situation many people encounter, there they're using a different machine or the project was made years ago with a laptop that's long since gone, but the code needs to be updated or modified in some way.

How to handle a couple points are still unclear to me.

1: Should this be on or off by default? Either way, how to make it apparent... in a world where countless details are all vying finite attention span and people don't tend to read stuff that seems like minor details? Especially if it's on by default, how can we warn people who wish to make a commercial product?

2: How to handle libraries?

On how to make it actually work, I do have a pretty good idea on that one. We'd almost certainly add a script to one of the hooks in Arduino's build process. The script would make a ZIP archive, and we'd convert it to a .o file that gets linked into the final executable image. Inside the USB stack, I'd probably add an extra interface with a control transfer (no extra endpoints) that reads out the data. There's also need to be a libusb-based utility on the PC side to send the control transfers and save the ZIP file to a temp folder, then extract it. Whether the GUI would be stand-alone or integrate in the Java code is a good question, but either way should be do-able. It's just a matter of needing more hours in the day to do it....
 
I do that too, but with many computers of different vintages and locations, it's not unique enough for me.

I'd like something like (I know this won't work) where the #include basically loads the contents of FILE as a string. One reason it won't work is FILE will contain quotes and other special characters that shouldn't be interpreted by the compiler.

Code:
Serial.puts(
#include __FILE__
)

@Paul -- For my use case, I was envisioning that the result (basically a v. long string) would be printed on the serial port by the program -- at startup or some other condition. I guess there could be problems with this reducing the space available for program code also, but my programs are relatively small and that's not a concern for me.
 
Edit - re read your post I think you are after the second half here, and a self developed script may actually get close to what your want. Would generally be an uncommonly asked for feature since you are potentially wasting a lot of flash and in a commercial environment making cloning a product trivial.

_____________________________

@Jp3141 - Are you trying to make the microcontroller spit back the compiled HEX file, or the original text that was compiled to make the hex file? If the former then it would be relatively straight forward just having code that when triggered streamed the flash contents out but that hex file would not be very useful for minor edits and I think would be missing some configuration information. If you want your readable code spat out then you would need to compress and package it into the flash in some way as text alongside or after your actual running code. Saving the text of your code is more straightforward to use but means you waste a lot of flash that does not do anything useful for the project itself.

If you want to roll your own you can probably write a processing or similar script that eats your arduino .INO file and package it into a suitable array of bytes that you then paste into a tab at the back of your code along with a process to spit those out on demand. It may even be possible to semiautomate the process by having the script create an include file that is referenced from your .ino file so only user action is to fire the script before hitting compile. If going this route you may want to think about included libraries. You probably cannot also include all of them as text without running out of space, but a recovered .iso file may not work against the libraries current at time of recovery. To be really robust you would probably need to include your current Arduino build environment at completion of the project on USB storage media somewhere inside the thing.
 
Last edited:
I'm back on this again. I created a simple script that I run manually to generate a #include file. The script is:

Code:
awk 'BEGIN{print "Serial.println( F( \\"}{gsub("\"","\\\"");print "\"" $0 "\\n\""}END{print "));"}' *.ino > printme.h

which generates a file containing the program as a long F() string that printed -- it starts like this:

Code:
Serial.println( F( \
"int led = 13;\n"
.
.
.

and in the .ino file, I include a line:

Code:
#include "printme.h"

which prints that string. It probably has bugs and could be improved, but it works for what I want.
 
Status
Not open for further replies.
Back
Top