| 14601 | } |
| 14602 | |
| 14603 | char *gmt_first_modifier (struct GMT_CTRL *GMT, char *string, const char *sep) { |
| 14604 | /* Return pointer to the first modifier +<char>, with three conditions: |
| 14605 | * 1. <char> must be one of the letters in sep, |
| 14606 | * 2. We must not be inside quoted text, i.e., "my +shit title", |
| 14607 | * 3. The + must not be escaped, i.e., +t"My \+shit text" |
| 14608 | * |
| 14609 | * If the modifier is not found we returns NULL. This is not an error |
| 14610 | * but means we did not find anything. |
| 14611 | */ |
| 14612 | size_t len, k = 0; |
| 14613 | bool inside_quote = false, done = false; |
| 14614 | if (sep == NULL) { |
| 14615 | GMT_Report (GMT->parent, GMT_MSG_ERROR, "gmt_first_modifier: No separation codes given\n"); |
| 14616 | return NULL; |
| 14617 | } |
| 14618 | |
| 14619 | if (string == NULL) return NULL; |
| 14620 | len = strlen (string); |
| 14621 | inside_quote = (string[0] == '\"' || string[0] == '\''); |
| 14622 | while (!done) { |
| 14623 | while (k < len && (inside_quote || string[k] != '+' || (k > 0 && string[k-1] == '\\'))) { |
| 14624 | k++; |
| 14625 | if (string[k] == '\"' || string[k] == '\'') inside_quote = !inside_quote; |
| 14626 | } |
| 14627 | k++; /* Advance to character after the + */ |
| 14628 | if (k >= len) return NULL; |
| 14629 | if (strchr (sep, string[k])) |
| 14630 | done = true; |
| 14631 | else { |
| 14632 | if (isalpha (string[k])) GMT_Report (GMT->parent, GMT_MSG_WARNING, "Modifier +%c detected but not a valid modifier! - ignored\n", string[k]); |
| 14633 | return NULL; |
| 14634 | } |
| 14635 | } |
| 14636 | return (k > 0 && k < len) ? &string[k-1] : NULL; |
| 14637 | } |
| 14638 | |
| 14639 | char *gmtlib_last_valid_file_modifier (struct GMTAPI_CTRL *API, char* filename, const char *mods) { |
| 14640 | /* A filename make have sequences that could look like a GMT modifier but is actually just part |
no test coverage detected