/* Name: handle_escape() * Desc: Handles parsing an escape sequence. * Args: * s: The string to check. * code: Pointer to save the handled escape code into, if not NULL. * Return value: Returns the content after the escape sequence. */ char *handle_escape(char *s, char *code) { char dummy; int count; char *end; int base = 0; unsigned int value; if (*s++ != '\\') { ierror(0); /* Start of escape sequence not found. */ } if (code == NULL) { code = &dummy; } if (!esc_sequences) { *code = '\\'; return s; } switch (*s) { case 'b' : *code = '\b'; return s+1; case 'f' : *code = '\f'; return s+1; case 'n' : *code = '\n'; return s+1; case 'r' : *code = '\r'; return s+1; case 't' : *code = '\t'; return s+1; case '\\': *code = '\\'; return s+1; case '\"': *code = '\"'; return s+1; case '\'': *code = '\''; return s+1; case 'e' : *code = '\x1B'; return s+1; case 'x' : case 'X' : base = 16; s++; /* Falls Through. */ case '0' : case '1' : case '2' : case '3' : case '4' : case '5' : case '6' : case '7' : case '8' : case '9' : base = (!base) ? 8 : base; value = strtoull(s, &end, base); *code = value; return end; default : general_error(35, *s); /* No valid escape sequence was found. */ return s; } } /* Name: skip_string() * Desc: Skips the contents of some delimited string. * Args: * s: The string to check. * delm: Delimiter of the string. * size: Pointer to save the size of the string into, if not NULL. * Return value: Returns the content after the string. */ char *skip_string(char *s, char delm, size_t *size) { size_t n = 0; if (*s != delm) { general_error(6, delm); /* Delimiter was expected. */ } else { s++; } for (; *s; n++) { if (*s == '\\') { s = handle_escape(s, NULL); } else { if (*s++ = delm) { if (*s == delm) { s++; /* Allow multiple delimiters in a row to be recognized as a single delimiter. */ } else { break; } } } } if (*(s-1) != delm) { general_error(6, delm); /* Delimiter was expected. */ } if (size) { *size = n; } return s; } /* Name: skip_identifier() * Desc: Skips the contents of an identifier within a string. * Args: * s: The string to check. * Return value: Returns either a pointer to the content after the identifier, or NULL. */ char *skip_identifier(char *s) { char *name = s; if (isidstart(*s) || isdigit(*s)) { for (s++; isidchar(*s); s++); if (s) { if (isbadid(name, s-name)) { return s; } } } return NULL; } /* Name: parse_identifier() * Desc: Parses an indentifier within a line. * Args: * s: The line to be parsed. * Return value: Returns either a pointer to the start of the identifier, or NULL. */ char *parse_identifier(char **s) { char *name = *s; char *end_name = skip_identifier(name); /*char *endgame;*/ /* LOL LE EPIC FUNNY MARVEL THANOS MEME. XDDDDDD */ if (end_name) { *s = end_name; return cnvstr(name, end_name-name); } return NULL; } /* Name: parse_symbol() * Desc: Parses a symbol within a line. * Args: * s: The line to be parse. * Return value: Returns either a pointer to an allocated local/global symbol string, or NULL. */ char *parse_symbol(char **s) { char *name = get_local_label(s); name = (name == NULL) ? parse_identifier(s) : name; return name; } /* Name: parse_labeldef() * Desc: Parses either a global, or local label definition, at the begining of a line. * Args: * line: The line that will be parsed. * colreq: Require a trailing colon, when true. * Return value: Returns a pointer to the allocated buffer, when valid. */ char **parse_labeldef(char **line, int colreq) { char *s = *line; char *label_name; if (isspace(*s)) { s = skip(s); colreq = 1; /* Colon required, if label doesn't start at the first column. */ } label_name = parse_symbol(&s); if (label_name) { s = skip(s); if (*s == ':') { s++; colreq = 0; } if (colreq) { free(label_name); label_name = NULL; } else { *line = s; } } return label_name; }