J
jacob navia
Common widsom says that python, ruby or similar are good for scripting,
but C is not the right tool for it.
Here is a small "benchmark" that shows that C can be used as a
scripting language in the same way as, for instance, ruby.
Setup
-----
The task to be solved is as follows:
In the current directory you have a bunch of .c files.
For each file in that directory you should start the C
compiler, compile the file, and if the compile works,
link it and then run it. You should gather some statistics
about how many runs were done, and how many compilation
errors or run time errors were discovered, printing them
at the end.
Here is a solution using the "ruby" language:
--------------------------------------------------------------
#/usr/bin/ruby -w
class Array
alias :append ush
end
def run_and_collect(file_list)
comp_counter = 0
run_counter = 0
count_all_compilations = 0
failed_compilations = 0
count_all_runs = 0
failed_runs = 0
failed_run_progs = []
successfull_runs = []
failed_compilation_runs = []
file_list.each {|file|
ret_val = system("../lcc -O -DNO_LABEL_VALUES -c -nw -g2
#{file} -o a.obj && gcc a.obj lcclibc_asm.s -o a -lm")
count_all_compilations += 1
if (ret_val == false)
puts("failed compilation: #{file}")
failed_compilations += 1
failed_compilation_runs.append(file)
else
ret_val = true
ret_val = system("./a")
run_counter+= 1
if (ret_val == false)
puts("failed run: #{file}");
failed_runs += 1
failed_run_progs.append(file + " ")
successfull_runs.append(file)
end
end
}
puts("Compilations: #{count_all_compilations}, failed:
#{failed_compilations}\n
Runs: #{run_counter}, failed: #{failed_runs}\n
#{failed_run_progs} \n")
end
run_and_collect(ARGV)
---------------------------------------------------------------------
Now the C solution:
--------------------------------------------------------------------
#define MAXTESTS 1000
#include <stdio.h>
#include <string.h>
void ShowFailures(char *tab[],int);
int main(int argc,char *argv[])
{
FILE *f;
char buf[512],cmd[1024], tmpbuf[512];
int r, tests=0,CompilationFailures=0, LinkFailures=0, RunFailures=0;
char *CFailures[MAXTESTS],*LFailures[MAXTESTS],
*RFailures[MAXTESTS];
f = popen("ls *.c","r");
while (fgets(buf,sizeof(buf),f)) {
char *p = strchr(buf,'\n');
if (p) *p=0;
tests++;
sprintf(cmd,"../lcc -g2 -nw %s",buf);
p = strchr(buf,'.');
if (p) *p=0;
r = system(cmd);
if (r) {
printf("Compilation of %s.c failed\n",buf);
CFailures[CompilationFailures++] = strdup(buf);
} else {
sprintf(cmd,"gcc %s.o lcclibc_asm.s -lm");
r = system(cmd);
if (r) {
printf("Link of %s.o failed\n",buf);
LFailures[LinkFailures++] = strdup(buf);
} else {
r = system("./a.out");
if (r) {
printf("Execution of %s failed\n",buf);
RFailures[RunFailures++] = strdup(buf);
}
}
}
}
pclose(f);
printf("\n********************************\n%d"
"tests\n********************************\n",tests);
if (CompilationFailures) {
printf("Compilation Failures: (%d)\n",CompilationFailures);
ShowFailures(CFailures,CompilationFailures);
}
if (LinkFailures) {
printf("Link failures: (%d)\n",LinkFailures);
ShowFailures(LFailures,LinkFailures);
}
if (RunFailures) {
printf("Run failures (%d)\n",RunFailures);
ShowFailures(RFailures,RunFailures);
}
}
void ShowFailures(char *tab[],int n)
{
for (int i=0; i<n; i++) { printf("%s ",tab); } printf("\n");
}
----------------------------------------------------------------------------
Both programs use identical algorithms:
(1) The list of *.c files will be established. Ruby uses a list, C uses
a pipe connected to another process that sends a line at a time.
(2) For each file the compiler is called, then the linker and the
resulting program. Statistics are gathered.
(3) A printout at the end of the run lists the failures.
The length in source code of both programs is very similar.
The running time of both programs is identical.
I wrote the C program, and a friend wrote the ruby program. It was
for testing the Unix version of lcc-win, i.e. both programs are
used in a "production" setting.
I think that both languages are perfectly equivalent in this example.
The next example I will post is web programming.
Thanks for your attention.
but C is not the right tool for it.
Here is a small "benchmark" that shows that C can be used as a
scripting language in the same way as, for instance, ruby.
Setup
-----
The task to be solved is as follows:
In the current directory you have a bunch of .c files.
For each file in that directory you should start the C
compiler, compile the file, and if the compile works,
link it and then run it. You should gather some statistics
about how many runs were done, and how many compilation
errors or run time errors were discovered, printing them
at the end.
Here is a solution using the "ruby" language:
--------------------------------------------------------------
#/usr/bin/ruby -w
class Array
alias :append ush
end
def run_and_collect(file_list)
comp_counter = 0
run_counter = 0
count_all_compilations = 0
failed_compilations = 0
count_all_runs = 0
failed_runs = 0
failed_run_progs = []
successfull_runs = []
failed_compilation_runs = []
file_list.each {|file|
ret_val = system("../lcc -O -DNO_LABEL_VALUES -c -nw -g2
#{file} -o a.obj && gcc a.obj lcclibc_asm.s -o a -lm")
count_all_compilations += 1
if (ret_val == false)
puts("failed compilation: #{file}")
failed_compilations += 1
failed_compilation_runs.append(file)
else
ret_val = true
ret_val = system("./a")
run_counter+= 1
if (ret_val == false)
puts("failed run: #{file}");
failed_runs += 1
failed_run_progs.append(file + " ")
successfull_runs.append(file)
end
end
}
puts("Compilations: #{count_all_compilations}, failed:
#{failed_compilations}\n
Runs: #{run_counter}, failed: #{failed_runs}\n
#{failed_run_progs} \n")
end
run_and_collect(ARGV)
---------------------------------------------------------------------
Now the C solution:
--------------------------------------------------------------------
#define MAXTESTS 1000
#include <stdio.h>
#include <string.h>
void ShowFailures(char *tab[],int);
int main(int argc,char *argv[])
{
FILE *f;
char buf[512],cmd[1024], tmpbuf[512];
int r, tests=0,CompilationFailures=0, LinkFailures=0, RunFailures=0;
char *CFailures[MAXTESTS],*LFailures[MAXTESTS],
*RFailures[MAXTESTS];
f = popen("ls *.c","r");
while (fgets(buf,sizeof(buf),f)) {
char *p = strchr(buf,'\n');
if (p) *p=0;
tests++;
sprintf(cmd,"../lcc -g2 -nw %s",buf);
p = strchr(buf,'.');
if (p) *p=0;
r = system(cmd);
if (r) {
printf("Compilation of %s.c failed\n",buf);
CFailures[CompilationFailures++] = strdup(buf);
} else {
sprintf(cmd,"gcc %s.o lcclibc_asm.s -lm");
r = system(cmd);
if (r) {
printf("Link of %s.o failed\n",buf);
LFailures[LinkFailures++] = strdup(buf);
} else {
r = system("./a.out");
if (r) {
printf("Execution of %s failed\n",buf);
RFailures[RunFailures++] = strdup(buf);
}
}
}
}
pclose(f);
printf("\n********************************\n%d"
"tests\n********************************\n",tests);
if (CompilationFailures) {
printf("Compilation Failures: (%d)\n",CompilationFailures);
ShowFailures(CFailures,CompilationFailures);
}
if (LinkFailures) {
printf("Link failures: (%d)\n",LinkFailures);
ShowFailures(LFailures,LinkFailures);
}
if (RunFailures) {
printf("Run failures (%d)\n",RunFailures);
ShowFailures(RFailures,RunFailures);
}
}
void ShowFailures(char *tab[],int n)
{
for (int i=0; i<n; i++) { printf("%s ",tab); } printf("\n");
}
----------------------------------------------------------------------------
Both programs use identical algorithms:
(1) The list of *.c files will be established. Ruby uses a list, C uses
a pipe connected to another process that sends a line at a time.
(2) For each file the compiler is called, then the linker and the
resulting program. Statistics are gathered.
(3) A printout at the end of the run lists the failures.
The length in source code of both programs is very similar.
The running time of both programs is identical.
I wrote the C program, and a friend wrote the ruby program. It was
for testing the Unix version of lcc-win, i.e. both programs are
used in a "production" setting.
I think that both languages are perfectly equivalent in this example.
The next example I will post is web programming.
Thanks for your attention.