diff --git a/1991/dds/.gitignore b/1991/dds/.gitignore index d7985d043..2118681f1 100644 --- a/1991/dds/.gitignore +++ b/1991/dds/.gitignore @@ -1 +1,5 @@ dds +dds.alt +a +a.c +a.out diff --git a/1991/dds/Makefile b/1991/dds/Makefile index c6c26c061..a4bed896d 100644 --- a/1991/dds/Makefile +++ b/1991/dds/Makefile @@ -114,8 +114,8 @@ OBJ= ${PROG}.o DATA= TARGET= ${PROG} # -ALT_OBJ= -ALT_TARGET= +ALT_OBJ= ${PROG}.alt.o +ALT_TARGET= ${PROG}.alt ################# diff --git a/1991/dds/README.md b/1991/dds/README.md index d68f03fb5..c4143d72f 100644 --- a/1991/dds/README.md +++ b/1991/dds/README.md @@ -11,41 +11,73 @@ make all -### To run +## To run: ./dds basic_program - ./a + ./a.out [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed some segfaults in this entry as well as making it so `a` (was `a.out`, see below) can be generated -(as in the program did not work, at least with clang). The first segfault which -was always triggered was due to the code `*q>' '&&(*q)--;`. This seems odd at -first glance but it's pointing to `s` which was read-only memory as a `char *s`. -It's now a `char s[]`. The second and third segfaults were caused if a file was -not specified (or it the one specified did not exist or couldn't be opened for -some reason) and if the output file could not be opened for writing. The -allowing the generated code to compile with clang is something of a hack -unfortunately. The code `return system(q-6);` ended up doing `return system("cc -a.c");` but depending on the compiler this would trigger errors due to no -function prototype specified and also a case where main() had a `return;` -without any return value. Because the string `s` is complicated and because Cody -did not want to inadvertently mess something up he changed that code to -`system("make a");` and then added the right rule to the Makefile. Thus you now -need both `make` and `cc`. If you use gcc you may change the system() call to -what was given in this description to get a more authentic feel. If you do this -you must then run `./a.out` not `./a`! Thank you Cody for your assistance! +(as in the program did not work, at least with clang). The alternative code, +described below, is what is needed for clang. Reading it might be instructive +even if you have gcc. +The first segfault which was always triggered was due to the code `*q>' +'&&(*q)--;`. This seems odd at first glance but it's pointing to `s` which was +read-only memory as a `char *s`. It's now a `char s[]`. The second and third +segfaults were caused if a file was not specified (or it the one specified did +not exist or couldn't be opened for some reason) and if the output file could +not be opened for writing. -## Judges' comments +Thank you Cody for your assistance! -Make and run as follows: +## Try: + +With gcc, make and run as follows: make dds For example, the author suggests trying: ./dds LANDER.BAS - ./a + ./a.out + +### Alternative code: + +The alternative code, provided by Cody, allows this entry to work successfully +even with clang. He notes that unfortunately it's something of a hack or maybe +even a kludge. This however seems important because it works well and allows for +not messing with the `s` string which is quite complicated. For all Cody knows +even changing the length could break functionality and indeed the length would +have to be longer for this to work with clang. + +How does it work? The code, which you will see in `dds.c`, `return system(q-6);` +equates to `return system("cc a.c");` but clang by default, at least in macOS, +has default -Werror and there were some warnings. This means that the +compilation failed with clang. In particular it would fail (at least with +`LANDER.BAS`) due to a return from `main()` without a return value and the use +of functions not yet declared. + +Now as noted since the string `s` is complicated and because Cody did not want +to inadvertently mess something up he changed that code to `system("make a");` +and then added the right rule to the Makefile. Thus for the alternative version +you now need both `make` and `cc`. If you use gcc you may change the system() +call to what was given in this description to get a more authentic feel. If you +do this you must then run `./a.out` not `./a`! Thus to use the alternative +version: + +```sh +make clobber alt +./dds.alt LANDER.BAS +./a +``` + +Thank you Cody for your assistance! + + +## Judges' comments: + +## Try: Notice that a file a.c has been generated. Can you tell how a.c was produced? How does a.c relate to LANDER.BAS? diff --git a/1991/dds/dds.alt.c b/1991/dds/dds.alt.c new file mode 100644 index 000000000..6956c2d9d --- /dev/null +++ b/1991/dds/dds.alt.c @@ -0,0 +1,17 @@ +#include +#define Q r=R[*p++-'0'];while( +#define B ;break;case +char s[]="Qjou!s\\311^-g\\311^-n\\311^-c\\::^-q-ma%mO1JBHm%BQ-aP1J[O1HB%[QaP2QaP4HC%T\ +Qs\\q,,^>m,2aP4HC%SD12N1\nJNQm>s\\..q^aHC%NHb%GN1!D32P3%RN1UP1D12JPQUaP1H\ +R%PN4\nQaP2Q,2aP4Hb%OD12D12N2!N3\nJVP3Q,,n\ +\\(aP3Q(^*m>g\\(aP3Q(^::::aHC%VP3Q>bupj)hfut)c**aHb%JD12JON1!Qjg)a%LN1UP1D12JIQUa\ +P1HL%IQ*m>aN2!N2\nP2QP2Q>aN2\nP2Hbdd!b/d";int k;char R[4][99] +;main(c,v)char**v;{char*p,*r,*q;for(q=s;*q;q++)*q>' '&&(*q)--;{FILE*i=fopen(v +[1],"r"),*o=fopen(q-3,"w");if(!i||!o)return 1;for(p=s;;p++)switch(*p++){B'M': +Q(k=fgetc(i))!=EOF&&k!=*p)*r++=k;if(k==EOF){fputs("}}\n",o);fclose(o);return +system("make a");}*r=0 B'P':while(*p!='`')fputc(*p++,o)B'O':Q*r)fputc(*r++,o); +p--B'C':k=0;Q k<*p-'0')(*r++=fgetc(i),k++);*r=0 B'I':k= *p;if(**R==k)goto G +B'G':k= *p;G:p=s;while(*p!='$'||p[1]!= k)p++;p++B'N':R[*p-'0'][0]++;}}} diff --git a/1991/dds/dds.c b/1991/dds/dds.c index 6956c2d9d..888ff412b 100644 --- a/1991/dds/dds.c +++ b/1991/dds/dds.c @@ -12,6 +12,6 @@ P1HL%IQ*m>aN2!N2\nP2QP2Q>aN2\nP2Hbdd!b/d";int k;char R[4][99 ;main(c,v)char**v;{char*p,*r,*q;for(q=s;*q;q++)*q>' '&&(*q)--;{FILE*i=fopen(v [1],"r"),*o=fopen(q-3,"w");if(!i||!o)return 1;for(p=s;;p++)switch(*p++){B'M': Q(k=fgetc(i))!=EOF&&k!=*p)*r++=k;if(k==EOF){fputs("}}\n",o);fclose(o);return -system("make a");}*r=0 B'P':while(*p!='`')fputc(*p++,o)B'O':Q*r)fputc(*r++,o); +system(q-6);}*r=0 B'P':while(*p!='`')fputc(*p++,o)B'O':Q*r)fputc(*r++,o); p--B'C':k=0;Q k<*p-'0')(*r++=fgetc(i),k++);*r=0 B'I':k= *p;if(**R==k)goto G B'G':k= *p;G:p=s;while(*p!='$'||p[1]!= k)p++;p++B'N':R[*p-'0'][0]++;}}}