int main(void) { macro_list_print(); macro_set("A", "a"); macro_set("B", "bb"); macro_set("C", "ccc"); macro_list_print(); macro_set("B", "dddd"); macro_list_print(); macro_set("A", "eeeee"); macro_list_print(); printf("%s = '%s' (%d)\n", "A", macro_body("A"), macro_length("A")); printf("%s = '%s' (%d)\n", "B", macro_body("B"), macro_length("B")); printf("%s = '%s' (%d)\n", "C", macro_body("C"), macro_length("C")); printf("%s = '%s' (%d)\n", "D", macro_body("D"), macro_length("D")); char in[4096] = "test.${A}.${B}.${C}.${D}."; char out[4096]; printf("len %d\n", macro_expand_length(in)); macro_expand(in, out); printf("%zd %s\n", strlen(in), in); printf("%zd %s\n", strlen(out), out); printf("len %d\n", macro_expand_length(in)); macro_set("A", "${B}"); macro_list_print(); printf("len %d\n", macro_expand_length(in)); macro_expand(in, out); printf("%zd %s\n", strlen(in), in); printf("%zd %s\n", strlen(out), out); printf("len %d\n", macro_expand_length(in)); macro_set("A", "body"); macro_set("B", "body body"); macro_set("C", "body body body"); macro_set("D", "enough already!"); macro_list_print(); printf("len %d\n", macro_expand_length(in)); macro_expand(in, out); printf("%zd %s\n", strlen(in), in); printf("%zd %s\n", strlen(out), out); printf("len %d\n", macro_expand_length(in)); return 0; }
static void cli_command_switch(char *args) { char *token; int value; cli_strip_spaces(&args); token = args; if(cli_strip_decimal_number(&args)) { uart_printf("1 Incorrect format, switch [n] [\"text\"]\n"); return; } value = atoi(token); if(value < 0 || value >= MACRO_MAX) { uart_printf("2 Incorrect format, switch [n] [\"text\"]\n"); return; } ++args; cli_strip_spaces(&args); token = args; if(cli_strip_quotes(&args)) { uart_printf("3 Incorrect format, switch [n] [\"text\"]\n"); return; } macro_set(value, ++token); }
static void read_lines(char *filename, FILE *fp) { verify(filename != NULL, "null arg filename"); verify(filename[0] != '\0', "empty arg filename"); verify(fp != NULL, "null arg fp"); if (verbose > 0) { fprintf(stderr, "%s: read_lines(%s)\n", prog, filename); } char original[MAXLINE+2]; // from fgets() char expanded[MAXLINE+2]; // after macro expansion char buffer[MAXLINE+2]; // working copy, safe to modify char whsp[] = " \t\n\v\f\r"; // whitespace characters int line_number = 0; int recipe_line_number = 0; while (fgets(original, MAXLINE, fp) != NULL) { // it is possible that the input line was too long, so terminate the string cleanly original[MAXLINE] = '\n'; original[MAXLINE+1] = '\0'; line_number++; if (verbose > 0) printf("%s: %s: line %d: %s", prog, filename, line_number, original); // assume original[] is constructed properly // assume expanded[] is large enough macro_expand(original, expanded); if (verbose > 0) printf("%s: %s: line %d: %s", prog, filename, line_number, expanded); strcpy(buffer, expanded); // copy, safe to modify char *buf = buffer; while (*buf == ' ') buf++; // skip past leading spaces (not tabs!) char *p_hash = strchr(buf, '#'); // a comment starts with # if (p_hash != NULL) { *p_hash = '\0'; } // remove the comment int n = 0; // remove trailing whitespace while (buf[n] != '\0') { int n1 = strspn(&buf[n], whsp); // buf[n .. n+n1-1] is whitespace int n2 = strcspn(&buf[n + n1], whsp); // buf[n+n1 .. n+n1+n2-1] is not if (n2 == 0) { buf[n] = '\0'; break; } // remove trailing whitespace n += n1 + n2; } if (buf[0] == '\0') // nothing left? { continue; } char *p_colon = strchr(buf, ':'); // : indicates a target-prerequisite line char *p_equal = strchr(buf, '='); // = indicates a macro definition if (buffer[0] == '\t') { recipe_line_number++; if (verbose > 0) printf(" >>> recipe line %d\n", recipe_line_number); // (save this for a later project) } else if (p_colon != NULL) { recipe_line_number = 0; if (verbose > 0) printf(" >>> target-prerequisite\n"); // (save this for a later project) } else if (p_equal != NULL) { if (verbose > 0) printf(" >>> macro definition\n"); // name = body // *p_equal is '=' char *name_start = buf; while (*name_start == ' ' || *name_start == '\t') // skip past spaces and tabs { name_start++; } char *name_end = p_equal-1; while (*name_end == ' ' || *name_end == '\t') { name_end--; } name_end++; *name_end = '\0'; char *body_start = p_equal+1; while (*body_start == ' ' || *body_start == '\t') { body_start++; } char *body_end = body_start; while (*body_end != '\0') // end of string { body_end++; } while (*body_end == ' ' || *body_end == '\t') { body_end--; } body_end++; *body_end = '\0'; if (verbose > 1) macro_list_print(); macro_set(name_start, body_start); if (verbose > 1) macro_list_print(); } else if (strncmp("include", buf, 7) == 0) { if (verbose > 0) printf(" >>> include\n"); char *name_start = buf + 7; // skip past "include" while (*name_start == ' ' || *name_start == '\t') // skip past spaces and tabs { name_start++; } if (*name_start == '\0') { // following GNU Make, this is not an error if (verbose > 0) fprintf(stderr, "%s: %s: line %d: include but no filename\n", prog, filename, line_number); continue; } else if (*name_start == '\'' || *name_start == '"') // quoted filename { // find matching quote, remove it char *q = name_start + 1; // skip past ' or " while (*q != *name_start && *q != '\0') q++; // find end of string or line if (*q == '\0') { fprintf(stderr, "%s: %s: line %d: file name error: >>>%s<<<\n", prog, filename, line_number, name_start); continue; } name_start++; // skip past opening quote *q = '\0'; // remove closing quote } read_file(name_start, 0); } else { if (verbose > 0) printf(" >>> something else\n"); fprintf(stderr, "%s: %s: line %d: not recognized: %s", prog, filename, line_number, original); } } if (ferror(fp)) // error when reading the file { fprintf(stderr, "%s: %s: read error: %s\n", prog, filename, strerror(errno)); } return; }
static void read_lines(char *filename, FILE *fp) { verify(filename != NULL, "null arg filename"); verify(filename[0] != '\0', "empty arg filename"); verify(fp != NULL, "null arg fp"); fprintf(stderr, "%s: read_lines(%s)\n", prog, filename); char original[MAXLINE+2]; // from fgets() char expanded[MAXLINE+2]; // after macro expansion char buffer[MAXLINE+2]; // working copy, safe to modify char whsp[] = " \t\n\v\f\r"; // whitespace characters int line_number = 0; int recipe_line_number = 0; while (fgets(original, MAXLINE, fp) != NULL) { // it is possible that the input line was too long, so terminate the string cleanly original[MAXLINE] = '\n'; original[MAXLINE+1] = '\0'; line_number++; //printf("%s: %s: line %d: %s", prog, filename, line_number, original); // assume original[] is constructed properly // assume expanded[] is large enough macro_expand(original, expanded); printf("%s: %s: line %d: %s", prog, filename, line_number, expanded); strcpy(buffer, expanded); // copy, safe to modify char *buf = buffer; while (*buf == ' ') buf++; // skip past leading spaces (not tabs!) char *p_hash = strchr(buf, '#'); // a comment starts with # if (p_hash != NULL) { *p_hash = '\0'; } // remove the comment int n = 0; // remove trailing whitespace while (buf[n] != '\0'){ int n1 = strspn(&buf[n], whsp); // buf[n .. n+n1-1] is whitespace int n2 = strcspn(&buf[n + n1], whsp); // buf[n+n1 .. n+n1+n2-1] is not if (n2 == 0) { buf[n] = '\0'; break; } // remove trailing whitespace n += n1 + n2; } if (buf[0] == '\0') { // nothing left? continue; } char *p_colon = strchr(buf, ':'); // : indicates a target-prerequisite line char *p_equal = strchr(buf, '='); // = indicates a macro definition // ---------------------------Recipes--------------------------------------------------------- if (buffer[0] == '\t') { recipe_line_number++; //printf(" >>> recipe line %d\n", recipe_line_number); // the target that is before the recipe struct target *myTarget = tg_list.head; if ( myTarget != NULL) { myTarget->rp_list.head = NULL; myTarget->rp_list.tail = NULL; // (save this for a later project) char *recipe = Malloc(128*sizeof(char *)); int i = 1; for(; buffer[i] != '\0'; i++) { recipe[i-1] = buffer[i]; } recipe[i] = '\0'; list_recipes_append(&(myTarget->rp_list), recipe); } } // --------------------------------Targets-------------------------------------------------------- else if (p_colon != NULL) { recipe_line_number = 0; // printf(" >>> target-prerequisite\n"); // (save this for a later project) char *target = Malloc(128 * sizeof(char *)); int i = 0; //printf("%s\n",buffer); // store target to the list while(buffer[i] != ':' && buffer[i] != ' ') { target[i] = buffer[i]; i++; } target[i] = '\0'; list_targets_append(&tg_list, target); struct target *myTarget = target_lookup(tg_list, target); // --------------------------------Sources------------------------------------------------------ //struct list_sources sc_list = *(myTarget->sc_list); myTarget->sc_list.head = NULL; myTarget->sc_list.tail = NULL; // store source to the list // skip all the spaces and ':', and go to the first source while(buffer[i] == ' ' || buffer[i] == ':' ) { i++; } // store sources to the list while(buffer[i] != '\0') { // not terminate until the end of line if( isalpha(buffer[i]) ) { char* source = Malloc(128*sizeof(char)); assert(source != NULL); int j=0; while( isalpha(buffer[i]) ) { source[j] = buffer[i]; // printf("source: %s\n", source); j++; i++; } list_sources_append(&(myTarget->sc_list), source); } else { // skip one whitespace i++; } } } // --------------------------------Macros----------------------------------------------------- else if (p_equal != NULL){ // printf(" >>> macro definition\n"); // name = body // *p_equal is '=' char *name_start = buf; while (*name_start == ' ' || *name_start == '\t') // skip past spaces and tabs { name_start++; } char *name_end = p_equal-1; while (*name_end == ' ' || *name_end == '\t') { name_end--; } name_end++; *name_end = '\0'; char *body_start = p_equal+1; while (*body_start == ' ' || *body_start == '\t') { body_start++; } char *body_end = body_start; while (*body_end != '\0') // end of string { body_end++; } while (*body_end == ' ' || *body_end == '\t') { body_end--; } body_end++; *body_end = '\0'; macro_list_print(); macro_set(name_start, body_start); macro_list_print(); } else if (strncmp("include", buf, 7) == 0) { // printf(" >>> include\n"); char *name_start = buf + 7; // skip past "include" while (*name_start == ' ' || *name_start == '\t') { // skip past spaces and tabs name_start++; } if (*name_start == '\0') { // following GNU Make, this is not an error // fprintf(stderr, "%s: %s: line %d: include but no filename\n", prog, filename, line_number); continue; } else if (*name_start == '\'' || *name_start == '"'){ // quoted filename // find matching quote, remove it char *q = name_start + 1; // skip past ' or " while (*q != *name_start && *q != '\0') { q++; // find end of string or line } if (*q == '\0') { fprintf(stderr, "%s: %s: line %d: file name error: >>>%s<<<\n", prog, filename, line_number, name_start); continue; } name_start++; // skip past opening quote *q = '\0'; // remove closing quote } read_file(name_start, 0); } else { printf(" >>> something else\n"); fprintf(stderr, "%s: %s: line %d: not recognized: %s", prog, filename, line_number, original); } } if (ferror(fp)) { // error when reading the file fprintf(stderr, "%s: %s: read error: %s\n", prog, filename, strerror(errno)); } return; }
static void read_lines(char *filename, FILE *fp) { // if (verbose > 0) // { fprintf(stderr, "%s: read_lines(%s)\n", prog, filename); } char original[MAXLINE+2]; // from fgets() char expanded[MAXLINE+2]; // after macro expansion char buffer[MAXLINE+2]; // working copy, safe to modify char whsp[] = " \t\n\v\f\r"; // whitespace characters int line_number = 0; int recipe_line_number = 0; bool have_target = false; // recipes must follow targets while (fgets(original, MAXLINE, fp) != NULL) { // it is possible that the input line was too long, so terminate the string cleanly original[MAXLINE] = '\n'; original[MAXLINE+1] = '\0'; line_number++; if (verbose > 0) printf("%s: %s: line %d: %s\n", "prog", filename, line_number, original); // assume original[] is constructed properly // assume expanded[] is large enough macro_expand(original, expanded); if (verbose > 0) printf("%s: %s: line %d: %s\n", "prog", filename, line_number, expanded); strcpy(buffer, expanded); // copy, safe to modify char *buf = buffer; while (*buf == ' ') buf++; // skip past leading spaces (not tabs!) char *p_hash = strchr(buf, '#'); // a comment starts with # if (p_hash != NULL) { *p_hash = '\0'; } // remove the comment int n = 0; // remove trailing whitespace while (buf[n] != '\0') { int n1 = strspn(&buf[n], whsp); // buf[n .. n+n1-1] is whitespace int n2 = strcspn(&buf[n + n1], whsp); // buf[n+n1 .. n+n1+n2-1] is not if (n2 == 0) { buf[n] = '\0'; break; } // remove trailing whitespace n += n1 + n2; } if (buf[0] == '\0') // nothing left? { continue; } char *p_colon = strchr(buf, ':'); // : indicates a target-prerequisite line char *p_equal = strchr(buf, '='); // = indicates a macro definition if (buffer[0] == '\t') { recipe_line_number++; if (verbose > 0) printf(" diagnosis: recipe line %d\n", recipe_line_number); if (have_target == false) { fprintf(stderr, "%s: %s: line %d: recipe but no target\n", prog, filename, line_number); continue; } int count = 0; while(*(buffer+1+count) != '\0') { count++; } char *recipe_temp = malloc((count+1)*sizeof(char)); set_chars(recipe_temp, buffer+1); struct target* temp_update_target = find_target(first_related_target); for(int i = 0; i < target_length; i++) { temp_update_target->target_recipes = add_recipe(temp_update_target->target_recipes, recipe_temp); if(target_length > 1) temp_update_target = temp_update_target->next; } } else if (p_colon != NULL) { first_related_target = NULL; target_length = 0; recipe_line_number = 0; if (verbose > 0) printf(" diagnosis: target-prerequisite\n"); have_target = true; char *source_start = p_colon+1; while(*source_start == ' ') { source_start++; } char *source_end = source_start; struct source *source_head = malloc(sizeof(struct source)); if(source_head == NULL) { printf("Malloc failed to allocate space for a source_head in the main program\n"); return; } if(*source_end == '\n' || *source_end == '\0' || *source_end == '\r') { source_head = add_source(source_head, ""); } while(*source_end != '\n' && *source_end != '\0' && *source_end != '\r') { if(*source_end == ' ' || *source_end == '\0') { *source_end = '\0'; int count = 0; while(*(source_start+count) != '\0') { count++; } char *source_temp = malloc((count+1)*sizeof(char)); set_chars(source_temp, source_start); source_head = add_source(source_head, source_temp); source_start = source_end+1; } if(*(source_end+1) == '\0') { int count = 0; while(*(source_start+count) != '\0') { count++; } char *source_temp = malloc((count+1)*sizeof(char)); set_chars(source_temp, source_start); source_head = add_source(source_head, source_temp); } source_end++; } char *tar_start = buf; while(*tar_start == ' ') { tar_start++; } char *tar_end = tar_start; while(*tar_end != ':' && *tar_end != '\0') { if(*tar_end == ' ' || *tar_end == '\t') { *tar_end = '\0'; if(default_goal == NULL) { int count = 0; while(*(tar_start+count) != '\0') { count++; } default_goal = malloc((count+1)*sizeof(char)); set_chars(default_goal, tar_start); } struct recipe* super_temp = malloc(sizeof(struct recipe)); super_temp->line = "replaceme"; char* temp = malloc(30 * sizeof(char)); set_chars(temp, tar_start); add_target(temp, source_head, super_temp); if(first_related_target == NULL) { int count = 0; while(*(tar_start+count) != '\0') { count++; } first_related_target = malloc((count+1)*sizeof(char)); if (first_related_target == NULL) { printf("malloc failed\n"); } for(int i = 0; i < count+2; i++) { *(first_related_target+i) = *(tar_start+i); } } target_length++; tar_start = (tar_end+1); } if(*(tar_end+1) == ':' ) { if(*(tar_end) != ' ') { int count = 0; while(*(tar_start+count) != ':') { count++; } *(tar_end+1) = '\0'; char *tar_temp = malloc((count+1)*sizeof(char)); set_chars(tar_temp, tar_start); struct recipe* super_temp = malloc(sizeof(struct recipe)); super_temp->line = "replaceme"; add_target(tar_temp, source_head, super_temp); if(first_related_target == NULL) { int count = 0; while(*(tar_start+count) != '\0') { count++; } first_related_target = malloc((count+1)*sizeof(char)); if (first_related_target == NULL) { printf("malloc failed\n"); } set_chars(first_related_target, tar_start); } } } tar_end++; } } else if (p_equal != NULL) { first_related_target = NULL; target_length = 0; if (verbose > 0) printf(" diagnosis: macro definition\n"); have_target = false; // name = body // *p_equal is '=' char *name_start = buf; while (*name_start == ' ' || *name_start == '\t') // skip past spaces and tabs { name_start++; } char *name_end = p_equal-1; while (*name_end == ' ' || *name_end == '\t') { name_end--; } name_end++; *name_end = '\0'; char *body_start = p_equal+1; while (*body_start == ' ' || *body_start == '\t') { body_start++; } char *body_end = body_start; while (*body_end != '\0') // end of string { body_end++; } while (*body_end == ' ' || *body_end == '\t') { body_end--; } body_end++; *body_end = '\0'; if (verbose > 1) macro_list_print(); macro_set(name_start, body_start); if (verbose > 1) macro_list_print(); } else if (strncmp("include", buf, 7) == 0) { first_related_target = NULL; target_length = 0; if (verbose > 0) printf(" diagnosis: include\n"); have_target = false; char *name_start = buf + 7; // skip past "include" while (*name_start == ' ' || *name_start == '\t') // skip past spaces and tabs { name_start++; } if (*name_start == '\0') { // following GNU Make, this is not an error if (verbose > 0) fprintf(stderr, "%s: %s: line %d: include but no filename\n", prog, filename, line_number); continue; } else if (*name_start == '\'' || *name_start == '"') // quoted filename { // find matching quote, remove it char *q = name_start + 1; // skip past ' or " while (*q != *name_start && *q != '\0') q++; // find end of string or line if (*q == '\0') { fprintf(stderr, "%s: %s: line %d: file name error [%s]\n", prog, filename, line_number, name_start); continue; } name_start++; // skip past opening quote *q = '\0'; // remove closing quote } pr8_read(name_start); } else { if (verbose > 0) printf(" diagnosis: something else\n"); have_target = false; // fprintf(stderr, "%s: %s: line %d: not recognized: %s", prog, filename, line_number, original); } } // if (ferror(fp)) // error when reading the file // { fprintf(stderr, "%s: %s: read error: %s\n", prog, filename, strerror(errno)); } return; }