Examen de Fundamentos de Sistemas Operativos Problema: Compilator en Rc Cree un script llamado compilator.rc que reciba el nombre de un directorio, y para todos los ficheros fuente en C contenidos en dicho directorio o en cualquier subdirectorio, compile dichos fuentes; y deje en un fichero llamado errores (en el directorio donde está el fuente) las líneas causantes de errores de compilación (el texto de las líneas y no el número de línea). Problema: Compilator lite en C Implemente el programa anterior en C, de tal forma que las compilaciones ejecuten en paralelo. En este caso, el fichero errores debe contener los mensajes de error de compilación y no el texto de las líneas que han causado los errores. NOTA: Puede ignorarse todo lo relacionado con la concurrencia. Si no sabes lo que es ‘‘la concurrencia’’, puedes ignorar esta nota. -2- Solución ___________ _compilator.rc #!/bin/rc rfork e if(! ~ $#* 1){ echo ’usage: compilator.rc dir’ >[1=2] exit usage } cd $1 || exit ’cd’ dirs=‘{du | awk ’{print $2}’ | sort -u} for(d in $dirs){ cd $d for(f in ‘{ls *.c >[2] /dev/null}){ lines=‘{8c -FVw $f | sed -n ’s/^’^$f^’:([0-9]+)[ ].*/\1/p’} for(l in $lines) sed -n $l^’p’ $f >> errors } cd $1 } exit ’’ compilator.c ____________ #include <u.h> #include <libc.h> static void usage(void) { fprint(2, "usage: %s dir\n", argv0); exits("usage"); } static int fderrors(void) { int fd; if(access("errors", AEXIST) == 0) fd = open("errors", OWRITE); else fd = create("errors", OWRITE, 0660); if(fd < 0) return -1; seek(fd, 0, 2); return fd; } -3- static void compile(char *dir, char *file) { int fd; switch(fork()){ case -1: sysfatal("exec failed: %r"); case 0: if(chdir(dir) < 0) sysfatal("can’t change wd to %s:%r", dir); fd = fderrors(); if(fd < 0) sysfatal("can’t open/create the errors file: %r"); dup(fd, 1); close(fd); execl("/bin/8c", "8c", "-FVw", file, nil); sysfatal("exec failed: %r"); } } static int issource(Dir *d) { char *p; if(d->mode & DMDIR) return 0; p = strrchr(d->name, ’.’); if(p == nil) return 0; if(strcmp(".c", p) != 0) return 0; return 1; } static int compilator(char *path) { int fd, err, i; Dir *d; long nd; char *npath; -4- err = 0; fd = open(path, OREAD); if(fd < 0) return -1; nd = dirreadall(fd, &d); close(fd); for(i = 0; i < nd; i++){ if(d[i].mode & DMDIR){ npath = smprint("%s/%s", path, d[i].name); err -= compilator(npath); free(npath); } if(issource(&d[i])) compile(path, d[i].name); } free(d); return err; } void main(int argc, char *argv[]) { int err; Waitmsg *m; ARGBEGIN{ default: usage(); }ARGEND if(argc != 1) usage(); err = compilator(argv[0]); while((m = wait()) != nil){ if(m->msg[0] != ’\0’) err--; free(m); } if(err) exits("some errors"); exits(nil); }