#define _POSIX_C_SOURCE 200809L #define BUFFER_SIZE 1024 #define STRING_BUFFER_SIZE 32 #include #include #include #include // Helps to match a string (excludes blanks and special characters) static int is_char(char c) { return c != '\0' && !isblank(c) && c != ':' && c != '=' && c != '#'; } // Returns the next word from buf until buf_len, // and the numbers of read characters in *read_chars // WARNING allocates the result on the heap static char *readWord(char *buf, size_t buf_len, size_t *read_chars) { size_t i = 0; size_t str_buf_size = STRING_BUFFER_SIZE; char *str_buf = malloc(sizeof(char) * str_buf_size); while (i < buf_len && is_char(buf[i])) { // Reallocate more space if necessary if (i >= str_buf_size - 1) { str_buf_size += STRING_BUFFER_SIZE; str_buf = realloc(str_buf, str_buf_size); if (str_buf == NULL) errx(2, "Could not realloc"); } str_buf[i] = buf[i]; i++; } str_buf[i] = '\0'; *read_chars = i; return str_buf; } int skip_blanks(char *buf, size_t buf_len) { size_t i = 0; while (i < buf_len && isblank(buf[i])) i++; return i; } int main(int argc, char **argv) { if (argc < 2) errx(2, "Not enough arguments"); if (argc > 2) errx(2, "Not enough arguments"); // Open file FILE *stream = fopen(argv[1], "r"); if (stream == 0) errx(2, "Could not open file"); // Allocate buffer size_t buf_size = BUFFER_SIZE; char *buf = malloc(sizeof(char) * buf_size); if (buf == NULL) errx(2, "Could not allocate more memory"); // Read ssize_t nread; while ((nread = getline(&buf, &buf_size, stream)) != -1) { size_t u_nread = nread; size_t i = 0; // Skip blanks i += skip_blanks(buf + i, nread - i); // Read target name size_t skipped_chars = 0; char *rule_name = readWord(buf + i, nread - i, &skipped_chars); if (skipped_chars != 0) printf("%s:", rule_name); i += skipped_chars; // Skip until ':' i += skip_blanks(buf + i, nread - i); if (buf[i] != ':') errx(2, "Unexpected character '%c' after rule declaration '%s'", buf[i], rule_name); i++; // Read deps while (i < u_nread) { // Skip blanks i += skip_blanks(buf + i, nread - i); // Read word size_t skipped_chars = 0; char *dep_name = readWord(buf + i, nread - i, &skipped_chars); if (skipped_chars != 0) printf(" %s", dep_name); free(dep_name); i += skipped_chars; if (!is_char(buf[i]) && !isblank(buf[i]) && buf[i] != '\0') errx(2, "Unexpected character '%c'", buf[i]); } i++; free(rule_name); } free(buf); fclose(stream); return 0; }