[alt.sources] Small introspective program

leo@s514.ipmce.su (Leonid A. Broukhis) (03/11/91)

	This is an introspective program in C.

char*a="char*a=%c%s%c;main(){printf(a,34,a,34);}";main(){printf(a,34,a,34);}

	Do you know a shorter program?

-- 
Leonid A. Broukhis | 89-1-95 Liberty St. | "BROUKHIS" is Hebrew for
7+095 494.6241 (h) | Moscow 123481 USSR  |       "BENEDICTAE"
7+095 132.9475 (o) | (leo@s514.ipmce.su) | {Licet omnia qualibet dicas}

olsen@casbah.acns.nwu.edu (Jeff Olsen) (03/11/91)

In article <AB2MbsdCB6@s514.ipmce.su> leo@s514.ipmce.su writes:
>	This is an introspective program in C.
>char*a="char*a=%c%s%c;main(){printf(a,34,a,34);}";main(){printf(a,34,a,34);}
>	Do you know a shorter program?

sure...

*a="*a=%c%s%c;main(){printf(a,34,a,34);}";main(){printf(a,34,a,34);}

I tried it with MSC 6.0 and whatever the default cc is on a encore
multimax.  GCC doesn't appear to like it, though.

Jeff Olsen
olsen@eecs.nwu.edu

andy@research.canon.oz.au (Andy Newman) (03/12/91)

The smaller the better! In many interpreted BASIC's of years ago you could do:

	1 LIST

Which when RUN would produce:

	1 LIST

(Using a single digit line number to make it as small as possible).


-- 
Andrew Newman, Software Engineer.            | Net:   andy@research.canon.oz.au
Canon Information Systems Research Australia | Phone: +61 2 805 2914
P.O. Box 313 North Ryde, NSW, Australia 2113 | Fax:   +61 2 805 2929

scotth@corp.sgi.com (Scott Henry) (03/12/91)

andy> The smaller the better! In many interpreted BASIC's of years ago you
andy> could do:

andy> 	1 LIST

andy> Which when RUN would produce:

andy> 	1 LIST

andy> (Using a single digit line number to make it as small as possible).

And in any sh|csh|tcsh on unix, this one is about as short as you can get:

        cat $0

--
 Scott Henry <scotth@sgi.com> / Traveller on Dragon Wings
 Information Services,       / Help! My disclaimer is missing!
 Silicon Graphics, Inc      / Politicians no baka!

jonth@ifi.uio.no (Jon Thingvold) (03/13/91)

What about this one (BSD UNIX):

#!/bin/cat

Or better in SIMULA an empty file is a valid program that
(of course) produces no output.

Jon.
--

dm@think.com (Dave Mankins) (03/13/91)

This is not quite the same thing, but it is a hack I have found very useful
when spinning small test programs.  

You start the program (e.g., ``foo.c'') with:

#ifdef notdef

  cc $0 -g -o `basename $0 .c` -Ineeded-includes -lneeded-libraries 

  exit;

#endif notdef

#include <stdio.h>
...

(all bound to an emacs function, insert-self-compile, of course)

Then invoke it with: 

	sh foo.c

This is much less labor-intensive than editing a Makefile (and re-editing it,
if the source file should move to another directory).

Even in semi-formally maintained code, I have found this most useful in files
that make up components of libraries, in this form:

#ifdef notdef

  cc $0 -DTEST -g -o `basename $0 .c` -Ineeded-includes -lneeded-libraries 

  exit;

#endif notdef

	/* library module source ... */

#ifdef TEST

main() {
	.... code to test the call library functions with test inputs and 
	     check the results ....
}

#endif /* TEST */

This allows your library modules to be self-testing, a great time-saver in the
later phases of development.
--
david mankins (dm@think.com)

clear@cavebbs.gen.nz (Charlie Lear) (03/13/91)

In article <1991Mar12.050929.2870@research.canon.oz.au> andy@research.canon.oz.au (Andy Newman) writes:
>The smaller the better! In many interpreted BASIC's of years ago you could do:
>	1 LIST
>Which when RUN would produce:
>	1 LIST
>(Using a single digit line number to make it as small as possible).

Sorry, your entry is disqualified through being too large. REAL BASICs used
to be able to tokenise, and the winner is:
	1 L.
which when run would produce
 	1 L.

Lets see you do THAT in C!

-- 
--------------------------------------------------------------------------
Charlie "The Bear" Lear | clear@cavebbs.gen.nz | Kawasaki Z750GT  DoD#0221
The Cave MegaBBS  +64 4 642260  V32 | PO Box 2009, Wellington, New Zealand
--------------------------------------------------------------------------

steele@en.ecn.purdue.edu@en.ecn.purdue.edu (Richard A. Steele) (03/13/91)

In article <1991Mar13.032422.9438@cavebbs.gen.nz> clear@cavebbs.gen.nz (Charlie Lear) writes:
>In article <1991Mar12.050929.2870@research.canon.oz.au> andy@research.canon.oz.au (Andy Newman) writes:
>>The smaller the better! In many interpreted BASIC's of years ago you could do:
>>	1 LIST
>>Which when RUN would produce:
>>	1 LIST
>>(Using a single digit line number to make it as small as possible).
>
>Sorry, your entry is disqualified through being too large. REAL BASICs used
>to be able to tokenise, and the winner is:
>	1 L.
>which when run would produce
> 	1 L.
>
>Lets see you do THAT in C!
>

You sure?  If the BASIC is tokenized, then L. will be expanded to LIST
in the source code listing, so that you'd get
	1 LIST
when run.  I have to admit, my only experience with tokenized basics is
the old 8-bit Ataris; do other basics leave the abbreviation?

Rich

-- 
-------------------------------------------------------------------------------
Richard Steele          |  INTERNET : steele@ecn.purdue.edu
Electrical Engineering  |  BITNET   : steele%ecn.purdue.edu@purccvm
Purdue University       |  UUCP     : {purdue, pur-ee}!ecn.purdue.edu!steele

henry@zoo.toronto.edu (Henry Spencer) (03/14/91)

In article <1991Mar13.001423.5194@Think.COM> dm@think.com (Dave Mankins) writes:
>You start the program (e.g., ``foo.c'') with:
>
>#ifdef notdef
>  cc $0 -g -o `basename $0 .c` -Ineeded-includes -lneeded-libraries 
>  exit;
>#endif notdef

It is no longer legal to put arbitrary trash after "#endif", so that
identifier has to go.  "#endif /* notdef */" is better.

Note also that you need to be careful about what you put inside #ifdef,
because it is *not* completely ignored.  The above example should be okay,
but in general the contents have to be either legal C tokens or things
that could not be mistaken for C tokens.  Notably, an unmatched ' or " is
not kosher.
-- 
"But this *is* the simplified version   | Henry Spencer @ U of Toronto Zoology
for the general public."     -S. Harris |  henry@zoo.toronto.edu  utzoo!henry

zap@savage.UUCP (Zap Savage) (03/14/91)

In <1991Mar13.151756.2885@en.ecn.purdue.edu>, steele@en.ecn.purdue.edu@en.ecn.purdue.edu (Richard A. Steele) writes:
> In article <1991Mar13.032422.9438@cavebbs.gen.nz> clear@cavebbs.gen.nz (Charlie Lear) writes:
> >                                                           REAL BASICs used
> >to be able to tokenise, and the winner is:
> >	1 L.
> >which when run would produce
> > 	1 L.
> You sure?  If the BASIC is tokenized, then L. will be expanded to LIST
> in the source code listing, so that you'd get
> 	1 LIST
> when run.  I have to admit, my only experience with tokenized basics is
> the old 8-bit Ataris; do other basics leave the abbreviation?

Nah, old TRS-80s with Level-1 Basic stored exactly what you typed and L. was
indeed the short form of LIST as P. was short for PRINT.  1 L. would indeed
work.

Zap
---
Zap Savage, Savage Research, Inc.
"We are the energy of Shakespeare's verse/we are what mathematics wants to be/
 The Life Force in the Universe/That longs to See!/That would Become/and give
 a voice to matter that was dumb."	"To Sail Beyond The Sun"
					R. Bradbury&J.V.Post

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (03/14/91)

The subject line is seriously misleading.  None of the examples that
has been posted has anything to do with INTROSPECTION (one might call
3-Lisp introspective, perhaps even Scheme, with its built in function
call-with-current-continuation).  They are SELF-REPRODUCING programs,
which is something rather different.  A program would be introspective
if it could take a step back from itself and watch its own workings.
(One might even call a UNIX program that has called monitor() or profil()
an introspective program.)  Self-reproducing programs are old hat.
-- 
The purpose of advertising is to destroy the freedom of the market.

magnus%thep.lu.se@Urd.lth.se (Magnus Olsson) (03/14/91)

In article <1991Mar13.151756.2885@en.ecn.purdue.edu> steele@en.ecn.purdue.edu@en.ecn.purdue.edu (Richard A. Steele) writes:
>In article <1991Mar13.032422.9438@cavebbs.gen.nz> clear@cavebbs.gen.nz (Charlie Lear) writes:
>>Sorry, your entry is disqualified through being too large. REAL BASICs used
>>to be able to tokenise, and the winner is:
>>	1 L.
>>which when run would produce
>> 	1 L.

>You sure?  If the BASIC is tokenized, then L. will be expanded to LIST
>in the source code listing, so that you'd get
>	1 LIST
>when run.  I have to admit, my only experience with tokenized basics is
>the old 8-bit Ataris; do other basics leave the abbreviation?

I'm afraid Charlie used the word `tokenize' in a non-canonical way...
Tokenization means that tokens (identifiers, keywords etc) are saved
just as numbers, not as text. The interpreter would recognize `L.' as
a valid abbreviation of LIST, and store the corresponding number.
The LIST command would then look up this number and write out the 
corresponding word, i.e. `LIST'. Applesoft Basic did this, I believe -
`?' was accepted as an abbreviation for `PRINT', but the LIST command
printed it as `PRINT'.

Anyway, there *are* Basics that don't tokenize, but accept abbreviated
statements - like the one on the Acorn Atom (a 6502-based British machine).
A typical line from an Atom program would look something like
100F.I=1TOA.X;P.ZZX';GOS.200;N.
which would correspond to
100 FOR I=1 TO ABS(X) : PRINT ZZ(X) : GOSUB 200 : NEXT I
in Micrososft Basic.

Unfortunately, Atom Basic didn't allow LIST inside a program, so 
Charlie's program wouldn't run on an Atom...

Magnus Olsson                   | \e+      /_
Dept. of Theoretical Physics    |  \  Z   / q
University of Lund, Sweden      |   >----<           
Internet: magnus@thep.lu.se     |  /      \===== g
Bitnet: THEPMO@SELDC52          | /e-      \q

jay@hermix.UUCP (Jay Skeer) (03/16/91)

This one is self-recognizing.  I am sure someone can do it shorter.

(Btw, what about lisp's shortest self-repro programs "T", "0", "1", "2", ...)

j'
-------------------
#include <stdio.h>
#define N 18
#define F 8
#define L 80
#define Y Z[k++]
#define P sprintf
char*I="\"%s\",",*B="%s",
M[N*3][L],Z[L],D[N][L]={
"#include <stdio.h>",
"#define N 18",
"#define F 8",
"#define L 80",
"#define Y Z[k++]",
"#define P sprintf",
"char*I=\"\\\"%s\\\",\",*B=\"%s\",",
"M[N*3][L],Z[L],D[N][L]={",
"\"\"},v='\\\\',q='\\\"';",
"main(){int c,i=0,j=0,k,l;",
"for(;i<F;P(M[j++],B,D[i++]));",
"for(i=0;i<N-1;i++,P(M[j++],I,Z))",
"for(k=0,l=0;Z[k]=0,c=D[i][l++];Y=c)",
"((c^v)*(c^q))||(Y=v);",
"for(i=F;i<N;P(M[j++],B,D[i++]));",
"for(i=0;gets(Z);)strcmp(M[i++],Z)&&exit(puts(\"no\"),1);",
"exit(puts(\"yes\"),0);}",
""},v='\\',q='\"';
main(){int c,i=0,j=0,k,l;
for(;i<F;P(M[j++],B,D[i++]));
for(i=0;i<N-1;i++,P(M[j++],I,Z))
for(k=0,l=0;Z[k]=0,c=D[i][l++];Y=c)
((c^v)*(c^q))||(Y=v);
for(i=F;i<N;P(M[j++],B,D[i++]));
for(i=0;gets(Z);)strcmp(M[i++],Z)&&exit(puts("no"),1);
exit(puts("yes"),0);}

jay@hermix.UUCP (Jay Skeer) (03/16/91)

>I said:
>This one is self-recognizing.  I am sure someone can do it shorter.
>

Well, matter of fact, *I* can.  Paste the folowing lines together into
one line.  No spaces.

j'

-- start cutting and pasting on the next line --
*a="*a=%c%s%c,b[256],c[256],q=34;main(){sprintf(b,a,q,a,q,q,q,q,q);get
s(c);puts(strcmp(b,c)?%cno%c:%cyes%c);}",b[256],c[256],q=34;main(){spr
intf(b,a,q,a,q,q,q,q,q);gets(c);puts(strcmp(b,c)?"no":"yes");}

rdc@nebulus.ampr.org (Dalton Clark) (03/17/91)

magnus%thep.lu.se@Urd.lth.se (Magnus Olsson) writes:

>In article <1991Mar13.151756.2885@en.ecn.purdue.edu> steele@en.ecn.purdue.edu@en.ecn.purdue.edu (Richard A. Steele) writes:
>>In article <1991Mar13.032422.9438@cavebbs.gen.nz> clear@cavebbs.gen.nz (Charlie Lear) writes:
>>>Sorry, your entry is disqualified through being too large. REAL BASICs used
>>>to be able to tokenise, and the winner is:
>>>	1 L.
>>>which when run would produce
>>> 	1 L.

>>You sure?  If the BASIC is tokenized, then L. will be expanded to LIST
>>in the source code listing, so that you'd get
>>	1 LIST
>>when run.  I have to admit, my only experience with tokenized basics is
 
Isn't there a BASIC that uses "!" as a REM.
 
Thus the "shortest" basic program would be "1!"; this is 1/3 to 1/2 as short as 
your suggested "1 L." (I would have ommited the space before submitting).

I believe it is an old Tandy basic that does this and it did not expand the "!"
to rem but left it as is; it did add a space though .....

goer@quads.uchicago.edu (Richard L. Goerwitz) (03/18/91)

>Isn't there a BASIC that uses "!" as a REM.
>Thus the "shortest" basic program would be "1!"; this is 1/3 to 1/2 as short
>as your suggested "1 L." (I would have ommited the space before submitting).
>I believe it is an old Tandy basic that does this and it did not expand the "!"
>to rem but left it as is; it did add a space though .....

I don't see any source code here.  Please note the followup-to line
above.  Please, please, please - !

-Richard

diamond@jit345.swstokyo.dec.com (Norman Diamond) (03/18/91)

In article <1991Mar17.190756.29382@midway.uchicago.edu> goer@quads.uchicago.edu (Richard L. Goerwitz) writes:
>>Isn't there a BASIC that uses "!" as a REM.
>>Thus the "shortest" basic program would be "1!"; this is 1/3 to 1/2 as short
>>as your suggested "1 L." (I would have ommited the space before submitting).
>>I believe it is an old Tandy basic that does this and it did not expand the "!"
>>to rem but left it as is; it did add a space though .....
>
>I don't see any source code here.  Please note the followup-to line
>above.  Please, please, please - !

His source, though incorrect, is:
1!

Therefore I have changed the follow-up back to alt.sources.

Meanwhile, the reason his source is incorrect is that when you RUN it,
it does not output a copy of itself.

I still prefer the correct program which is even two characters shorter
than that.  (The source code is here, though it is difficult to see.)
--
Norman Diamond       diamond@tkov50.enet.dec.com
If this were the company's opinion, I wouldn't be allowed to post it.

lee@sq.sq.com (Liam R. E. Quin) (03/21/91)

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) writes:
>[About the hack for including a command to compile itself in a C program.]
> Many years ago Tom Duff wrote a nifty little program called "com"; [...]

I still use a shell-script called "use" for troff files, and sometimes for
complex shell scripts.

It understands a number of comment conventions, and looks for
	<any-sort-of-comment> use <command>
A % sign is turned into the filename.

For example,
	.\" Use pic % | troff -

Options other than -n are passed along....and appear immediately before the
first option in the Use line, so
	use -Timpr file
in the above file would be turned into
	pic file | troff -Timpr -

The Use comment must be in the 1st 5 lines.

Personally I prefer make, but that's another story...


Here it is.  Edit the "sed" line to change "^G" into a control G before
extracting.

Lee


sed 's/ControlG/^Gg' << 'boy' > use
:
if [ x"$1" = x"-n" ]
then	NOACTION=yes; shift
fi

while [ $# -gt 0 ]
do
    case "$1" in
    -*)
	TSOPTS="$TSOPTS '$1'"
	shift
	;;
    *)
	break
	;;
    esac
done

FILE=${1-:"You must give a filename"}

CMD=`sed -n '/^[ 	]*[#%*;][#%!*;]*\([ 	]*[uU]se \)/s//.\\\\" \1/
	    /^\.[ 	]*\\\\"[ 	]*[uU]se /p
	    5q' "${FILE}"`

if [ x"$CMD" = x"" ]
then
	echo "No Use comment in the file... do it yourself"
	exit 1
fi

pipeline=`echo "$CMD" | sed -e '
	s/^\.[ 	]*\\\\"[ 	]*[uU]se[ 	]*//
	sControlG%'"ControlG${FILE}"'ControlGg
	sControlG -ControlG'"${TSOPTS}"'&ControlG
	' `

echo $pipeline

if [ x"$NOACTION" = x"yes" ]
then	echo "[no action taken]"
else	eval $pipeline
fi
use
echo extracted use.
exit 0

-- 
Liam R. E. Quin,  lee@sq.com, SoftQuad Inc., Toronto, +1 (416) 963-8337
    `A wrong that cannot be repaired must be transcended'
						Ursula K. Le Guin, in _Tehanu_

ishpanta@bluemoon.uucp (John Huenefeld) (03/22/91)

> Isn't there a BASIC that uses "!" as a REM.
>  
> Thus the "shortest" basic program would be "1!"; this is 1/3 to 1/2 as short 
> your suggested "1 L." (I would have ommited the space before submitting).
> 
> I believe it is an old Tandy basic that does this and it did not expand the "
> to rem but left it as is; it did add a space though .....


I also believe that the Basic on the IBM system 3x machines (34,36,38) 
also uses the ! as REM.  Also when listed it would be listed as 1 ! (even 
when you just typed 1!).

John Huenefeld