From 56b31286d1e6ab7ee7e7dda5695b3bb8efe2eaee Mon Sep 17 00:00:00 2001 From: Cody Boone Ferguson <53008573+xexyl@users.noreply.github.com> Date: Mon, 27 Mar 2023 12:27:08 -0700 Subject: [PATCH] Fix 1991/dds This was a fun one! There were up to three segfaults fixed and with clang the generated file could not be compiled. The latter part was fixed with (unfortunately) something of a hack. I explain below and in the README.md how to change that part to use just cc if you have gcc (macOS gcc is actually 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 I did not want to inadvertently mess something up I 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! --- 1991/dds/Makefile | 6 +++++- 1991/dds/README.md | 26 +++++++++++++++++++++++--- 1991/dds/dds.c | 12 ++++++------ 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/1991/dds/Makefile b/1991/dds/Makefile index d4f62d94d..c6c26c061 100644 --- a/1991/dds/Makefile +++ b/1991/dds/Makefile @@ -62,7 +62,7 @@ CDEFINE= # Include files that are needed to compile # -CINCLUDE= +CINCLUDE= -include stdio.h # Optimization # @@ -80,6 +80,7 @@ LIBS= # CC= cc +CSILENCE= -Wno-implicit-function-declaration # Compiler add-ons or replacements for clang only # ifeq ($(CC),clang) @@ -131,6 +132,9 @@ all: data ${TARGET} ${PROG}: ${PROG}.c ${CC} ${CFLAGS} $< -o $@ ${LIBS} +a: a.c + ${CC} ${CFLAGS} -Wno-return-type $< -o $@ ${LIBS} + # alternative executable # alt: data ${ALT_TARGET} diff --git a/1991/dds/README.md b/1991/dds/README.md index b24b50942..d68f03fb5 100644 --- a/1991/dds/README.md +++ b/1991/dds/README.md @@ -14,7 +14,27 @@ ### To run ./dds basic_program - ./a.out + ./a + +[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! + ## Judges' comments @@ -24,8 +44,8 @@ Make and run as follows: For example, the author suggests trying: - dds LANDER.BAS - a.out + ./dds LANDER.BAS + ./a 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.c b/1991/dds/dds.c index 1868a83e0..6956c2d9d 100644 --- a/1991/dds/dds.c +++ b/1991/dds/dds.c @@ -1,7 +1,7 @@ #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%[Q' '&&(*q)--;{FILE*i=fopen(v -[1],"r"),*o=fopen(q-3,"w");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(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]++;}}} +[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]++;}}}