void pragma_handle(const char *pragma, where *loc) { if(!strncmp(pragma, "STDC", 4)){ handle_pragma_stdc(str_spc_skip(pragma + 4), loc); }else if(!strncmp(pragma, "ucc", 3)){ handle_pragma_ucc(str_spc_skip(pragma + 3), loc); }else{ /* * #pragma GCC visibility <arg> * #pragma align <arg> * #pragma pack <arg> * #pragma section <arg> * #pragma unused <arg> * #pragma weak <arg> * #pragma attribute <arg> */ cc1_warn_at(loc, unknown_pragma, "unknown pragma '%s'", pragma); } }
void str_trim(char *str) { char *s = str_spc_skip(str); memmove(str, s, strlen(s) + 1); for(s = str; *s; s++); while(s > str && isspace(*s)) s--; *s = '\0'; }
static char *filter_macros(char *line) { /* check for non-standard space-then-# */ char *hash = line; if(*hash == '#' || *(hash = str_spc_skip(hash)) == '#'){ if(*line != '#') CPP_WARN(WTRADITIONAL, "'#' for directive isn't in the first column"); parse_directive(hash + 1); free(line); return NULL; }else{ if(parse_should_noop()) *line = '\0'; else line = eval_expand_macros(line); return line; } }
static char *strip_comment(char *line) { const int is_directive = *str_spc_skip(line) == '#'; char *s; if(strip_in_block == IN_BLOCK_BEGIN) strip_in_block = IN_BLOCK_FULL; else if(strip_in_block == IN_BLOCK_END) strip_in_block = NOT_IN_BLOCK; for(s = line; *s; s++){ if(strip_in_block == IN_BLOCK_FULL || strip_in_block == IN_BLOCK_BEGIN){ const int clear_comments = (strip_comments == STRIP_ALL); if(*s == '*' && s[1] == '/'){ strip_in_block = IN_BLOCK_END; if(clear_comments) *s++ = ' '; } if(clear_comments) *s = ' '; }else if(*s == '"' || *s == '\''){ /* read until the end of the string */ char *end = str_quotefin2(s + 1, *s); if(!end){ CPP_WARN(WQUOTE, "no terminating quote to string"); /* skip to eol */ s = strchr(s, '\0') - 1; }else{ s = end; } }else if(*s == '/'){ if(cpp_std >= STD_C99 && s[1] == '/'){ switch(strip_comments){ case STRIP_EXCEPT_DIRECTIVE: if(is_directive) goto strip_1line; /* fall */ case STRIP_NONE: { /* convert to a block comment */ const unsigned pos_slash = s - line; const unsigned len = strlen(line); line = urealloc1(line, len + 2 + 1); s = line + pos_slash; s[1] = '*'; strcpy(line + len, "*/"); break; } strip_1line: case STRIP_ALL: /* ignore //.* */ *s = '\0'; break; } break; }else if(s[1] == '*'){ strip_in_block = IN_BLOCK_BEGIN; switch(strip_comments){ case STRIP_EXCEPT_DIRECTIVE: if(!is_directive) break; /* fall */ case STRIP_ALL: /* wait for terminator elsewhere (i'll be back) */ *s = s[1] = ' '; s++; case STRIP_NONE: break; } } } } return line; }
static char *splice_lines(int *peof) { static int n_nls; char *line; char *last_backslash; int splice = 0; if(n_nls){ n_nls--; return ustrdup(""); } line = read_line(); if(!line){ *peof = 1; return NULL; } if(option_trigraphs) line = expand_trigraphs(line); last_backslash = strrchr(line, '\\'); if(last_backslash){ char *i; /* is this the end of the line? */ i = str_spc_skip(last_backslash + 1); if(*i == '\0'){ splice = 1; if(i > last_backslash + 1){ CPP_WARN(WBACKSLASH_SPACE_NEWLINE, "backslash and newline separated by space"); } } } if(splice){ char *next = splice_lines(peof); /* remove in any case */ *last_backslash = '\0'; if(next){ const size_t this_len = last_backslash - line; const size_t next_len = strlen(next); n_nls++; line = urealloc1(line, this_len + next_len + 1); strcpy(line + this_len, next); free(next); }else{ /* backslash-newline at eof * else we may return non-null on eof, * so we need an eof-check in read_line() */ CPP_WARN(WFINALESCAPE, "backslash-escape at eof"); *peof = 1; } } return line; }