Text* Parser::parse_text(){ if(it==end){ return NULL; } SaneString::iterator start=it; char c,q; if(maybe_char(QUOTE1)){ q=QUOTE1; } else if(maybe_char(QUOTE2)){ q=QUOTE2; } else if(maybe_char(QUOTE3)){ q=QUOTE3; } //Try unquoted else{ do{ c=parse_escape(*it,UNQUOTED_EOF); }while(!( //Ordered by expected frequency isspace(c) or c==OPEN_TAG or c==CLOSE_TAG or c==NAMED_ATTR or c==QUOTE1 or c==QUOTE2 or c==OPEN_SECTION or c==CLOSE_SECTION or c==QUOTE3 ) and ++it!=end); if(it==start){ return NULL; } return new Text(text.substr(start-text.begin(),it-start)); } //Must be quoted do{ c=parse_escape(*it,QUOTED_EOF); }while(c!=q and ++it!=end); if(!maybe_char(q)){ throw ParseError(QUOTED_EOF,line,col); } return new Text( ((SaneString)text.substr(start-text.begin(),it-start)).escape(q) ); }
/** текст выводимый на консоль **/ int parse_print(char *text,char **endptr,Tag *toptag) { char *s,*p; Tag *tag; TRACE(""); tag=NULL; if (text[0]!='#'||text[1]!='?'||text[2]!='>') return 1; s=text; if (toptag) tag=mark(PRINT,text,text,toptag); mark_len(NULL,3,s,&s,tag); // открывающая группа #?> while(*s) { p=s; mark_cspn(CHARS,"<$[\\",s,&s,tag); // фрагмент до кавычки ' или esc if (s[0]=='\\') parse_escape(s,&s,tag); // esc if (s[0]=='$') parse_variable(s,&s,tag);// подстановка переменных if (s[0]=='[') parse_command(s,&s,tag); // полстановка команд if (s[0]=='<') { if (s[1]=='?' && s[2]=='#') { mark_len(NULL,3,s,&s,tag); // закрывающая группа <?# break; } else { mark_len(NULL,1,s,&s,tag); } } if (p==s) break; } if (endptr) (*endptr)=s; return 0; }
/** строка с подстановками */ int parse_subst(char *text,char **endptr,Tag *toptag) { char *p; char *s; Tag *tag; tag=NULL; if (text[0]!='\"') return 1; s=text; if (toptag) tag=mark(STRING,text,s,toptag); mark_len(NULL,1,s,&s,tag); // открывающая кавычка while(*s) { p=s; s+=strcspn(s,"\\$[{\""); if (p!=s) mark(CHARS,p,s,tag); switch (*s) { case '\\' : parse_escape(s,&s,tag);break; case '$' : parse_variable(s,&s,tag);break; case '[' : parse_command(s,&s,tag);break; } if (s[0]=='\"') { mark_len(NULL,1,s,&s,tag); // закрывающая кавычка break; } if (p==s) break; } if (endptr) (*endptr)=s; return 0; }
struct token *get_string_constant(SCTX_ struct token *token, struct expression *expr) { struct string *string = token->string; struct token *next = token->next, *done = NULL; int stringtype = token_type(token); int is_wide = stringtype == TOKEN_WIDE_STRING; static char buffer[MAX_STRING]; int len = 0; int bits; while (!done) { switch (token_type(next)) { case TOKEN_WIDE_STRING: is_wide = 1; case TOKEN_STRING: next = next->next; break; default: done = next; } } bits = is_wide ? 32 : sctxp bits_in_char; while (token != done) { unsigned v; const char *p = token->string->data; const char *end = p + token->string->length - 1; while (p < end) { p = parse_escape(sctx_ p, &v, end, bits, token->pos); if (len < MAX_STRING) buffer[len] = v; len++; } token = token->next; } if (len > MAX_STRING) { warning(sctx_ token->pos, "trying to concatenate %d-character string (%d bytes max)", len, MAX_STRING); len = MAX_STRING; } if (len >= string->length) /* can't cannibalize */ string = __alloc_string(sctx_ len+1); string->length = len+1; string->used = string->length; memcpy(string->data, buffer, len); string->data[len] = '\0'; expr->string = string; expr->wide = is_wide; return token; }
/* If the text starting at P going up to (but not including) END starts with a character constant, set *TOK to point to that character constant, and return 1. Otherwise, return zero. Signal an error if it contains a malformed or incomplete character constant. */ static int get_character_constant (struct macro_buffer *tok, char *p, char *end) { /* ISO/IEC 9899:1999 (E) Section 6.4.4.4 paragraph 1 But of course, what really matters is that we handle it the same way GDB's C/C++ lexer does. So we call parse_escape in utils.c to handle escape sequences. */ if ((p + 1 <= end && *p == '\'') || (p + 2 <= end && p[0] == 'L' && p[1] == '\'')) { char *tok_start = p; char *body_start; if (*p == '\'') p++; else if (*p == 'L') p += 2; else gdb_assert (0); body_start = p; for (;;) { if (p >= end) error ("Unmatched single quote."); else if (*p == '\'') { if (p == body_start) error ("A character constant must contain at least one " "character."); p++; break; } else if (*p == '\\') { p++; parse_escape (&p); } else p++; } set_token (tok, tok_start, p); return 1; } else return 0; }
/* If the text starting at P going up to (but not including) END starts with a string literal, set *TOK to point to that string literal, and return 1. Otherwise, return zero. Signal an error if it contains a malformed or incomplete string literal. */ static int get_string_literal (struct macro_buffer *tok, char *p, char *end) { if ((p + 1 <= end && *p == '\"') || (p + 2 <= end && p[0] == 'L' && p[1] == '\"')) { char *tok_start = p; if (*p == '\"') p++; else if (*p == 'L') p += 2; else gdb_assert (0); for (;;) { if (p >= end) error ("Unterminated string in expression."); else if (*p == '\"') { p++; break; } else if (*p == '\n') error ("Newline characters may not appear in string " "constants."); else if (*p == '\\') { p++; parse_escape (&p); } else p++; } set_token (tok, tok_start, p); return 1; } else return 0; }
Text* Parser::parse_doc_text(){ if(it==end){ return NULL; } SaneString::iterator start=it; char c; do{ c=parse_escape(*it,NULL); }while(c!=OPEN_TAG and ++it!=end); if(start==it){ return NULL; } return new Text(text.substr(start-text.begin(),it-start)); }
void iterator::parse_string( void ) { if ( _c != '\"' ) return; skip_utf(); while( _c != '\"' ) { if ( _c == '\\' ) parse_escape(); next_utf(); if ( ! _utf ) return; } skip_utf(); _type = TOK_STRING; }
void iterator::parse_char( void ) { if ( _c != '\'' ) return; skip_utf(); while( _c != '\'' ) { if ( _c == '\\' ) parse_escape(); next_utf(); if ( ! _utf ) return; } skip_utf(); _type = TOK_CHARACTER; }
Text* Parser::parse_section_text(){ if(it==end){ return NULL; } SaneString::iterator start=it; char c; do{ c=parse_escape(*it,SECTION_EOF); }while(!(c==OPEN_TAG or c==CLOSE_SECTION) and ++it!=end); if(start==it){ return NULL; } return new Text(text.substr(start-text.begin(),it-start)); }
static int parse_fstab_line(char *line, struct fs_info **ret_fs) { char *dev, *device, *mntpnt, *type, *opts, *freq, *passno, *cp; struct fs_info *fs; *ret_fs = 0; strip_line(line); if ((cp = strchr(line, '#'))) *cp = 0; /* Ignore everything after the comment char */ cp = line; device = parse_word(&cp); mntpnt = parse_word(&cp); type = parse_word(&cp); opts = parse_word(&cp); freq = parse_word(&cp); passno = parse_word(&cp); if (!device) return 0; /* Allow blank lines */ if (!mntpnt || !type) return -1; parse_escape(device); parse_escape(mntpnt); parse_escape(type); parse_escape(opts); parse_escape(freq); parse_escape(passno); dev = blkid_get_devname(cache, device, NULL); if (dev) device = dev; if (strchr(type, ',')) type = 0; fs = create_fs_device(device, mntpnt, type ? type : "auto", opts, freq ? atoi(freq) : -1, passno ? atoi(passno) : -1); if (dev) free(dev); if (!fs) return -1; *ret_fs = fs; return 0; }
static int parse_fstab_line(char *line, struct fs_info *fs) { char *dev, *device, *mntpnt, *type, *opts, *freq, *passno, *cp; if ((cp = strchr(line, '#'))) *cp = 0; /* Ignore everything after the comment char */ cp = line; device = parse_word(&cp); mntpnt = parse_word(&cp); type = parse_word(&cp); opts = parse_word(&cp); freq = parse_word(&cp); passno = parse_word(&cp); if (!device) return -1; /* Allow blank lines */ if (!mntpnt || !type) return -1; parse_escape(device); parse_escape(mntpnt); parse_escape(type); parse_escape(opts); parse_escape(freq); parse_escape(passno); dev = blkid_get_devname(cache, device, NULL); if (dev) device = dev; if (strchr(type, ',')) type = 0; fs->device = string_copy(device); fs->mountpt = string_copy(mntpnt); fs->type = string_copy(type); fs->opts = string_copy(opts ? opts : ""); fs->freq = freq ? atoi(freq) : -1; fs->passno = passno ? atoi(passno) : -1; fs->flags = 0; fs->next = NULL; if (dev) free(dev); return 0; }
/** строка без подстановок */ int parse_string(char *text,char **endptr,Tag *toptag) { char *s,*p; Tag *tag; TRACE(""); tag=NULL; if (text[0]!='\'') return 1; s=text; if (toptag) tag=mark(STRING,text,text,toptag); mark_len(NULL,1,s,&s,tag); // открывающая кавычка while(*s) { p=s; mark_cspn(CHARS,"\'\\",s,&s,tag); // фрагмент до кавычки ' или esc if (s[0]=='\\') parse_escape(s,&s,tag); // esc if (s[0]=='\'') { mark_len(NULL,1,s,&s,tag); // закрывающая кавычка break; } if (p==s) break; } if (endptr) (*endptr)=s; return 0; }
void get_char_constant(SCTX_ struct token *token, unsigned long long *val) { const char *p = token->embedded, *end; unsigned v; int type = token_type(token); switch (type) { case TOKEN_CHAR: case TOKEN_WIDE_CHAR: p = token->string->data; end = p + token->string->length; break; case TOKEN_CHAR_EMBEDDED_0 ... TOKEN_CHAR_EMBEDDED_3: end = p + type - TOKEN_CHAR; break; default: end = p + type - TOKEN_WIDE_CHAR; } p = parse_escape(sctx_ p, &v, end, type < TOKEN_WIDE_CHAR ? sctxp bits_in_char : 32, token->pos); if (p != end) warning(sctx_ token->pos, "multi-character character constant"); *val = v; }
Regexp * make_regexp(char *s, size_t len, int ignorecase, int dfa) { Regexp *rp; const char *rerr; char *src = s; char *temp; char *end = s + len; register char *dest; register int c, c2; /* Handle escaped characters first. */ /* * Build a copy of the string (in dest) with the * escaped characters translated, and generate the regex * from that. */ emalloc(dest, char *, len + 2, "make_regexp"); temp = dest; while (src < end) { if (*src == '\\') { c = *++src; switch (c) { case 'a': case 'b': case 'f': case 'n': case 'r': case 't': case 'v': case 'x': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': c2 = parse_escape(&src); if (c2 < 0) cant_happen(); /* * Unix awk treats octal (and hex?) chars * literally in re's, so escape regexp * metacharacters. */ if (do_traditional && ! do_posix && (ISDIGIT(c) || c == 'x') && strchr("()|*+?.^$\\[]", c2) != NULL) *dest++ = '\\'; *dest++ = (char) c2; break; case '8': case '9': /* a\9b not valid */ *dest++ = c; src++; break; case 'y': /* normally \b */ /* gnu regex op */ if (! do_traditional) { *dest++ = '\\'; *dest++ = 'b'; src++; break; } /* else, fall through */ default: *dest++ = '\\'; *dest++ = (char) c; src++; break; } /* switch */ } else *dest++ = *src++; /* not '\\' */ } /* for */ *dest = '\0' ; /* Only necessary if we print dest ? */ emalloc(rp, Regexp *, sizeof(*rp), "make_regexp"); memset((char *) rp, 0, sizeof(*rp)); rp->pat.allocated = 0; /* regex will allocate the buffer */ emalloc(rp->pat.fastmap, char *, 256, "make_regexp"); if (ignorecase) rp->pat.translate = casetable; else rp->pat.translate = NULL; len = dest - temp; if ((rerr = re_compile_pattern(temp, len, &(rp->pat))) != NULL) fatal("%s: /%s/", gettext(rerr), temp); /* gack. this must be done *after* re_compile_pattern */ rp->pat.newline_anchor = FALSE; /* don't get \n in middle of string */ if (dfa && ! ignorecase) { dfacomp(temp, len, &(rp->dfareg), TRUE); rp->dfa = TRUE; } else rp->dfa = FALSE; free(temp); return rp; }
/* rebuild it with those removed or expanded, respectively */ void vms_arg_fixup( int *pargc, char ***pargv ) { char *f_in, *f_out, *f_err, *out_mode, *rms_opt1, *rms_opt2; char **argv = *pargv; int i, argc = *pargc; int err_to_out_redirect = 0, out_to_err_redirect = 0; #ifndef NO_CHECK_SHELL if (shell$is_shell()) return; /* don't do anything if we're running DECshell */ #endif #ifndef NO_DCL_CMD for (i = 1; i < argc ; i++) /* check for dash or other non-VMS args */ if (strchr("->\\|", *argv[i])) break; /* found => (i < argc) */ if (i >= argc && (v_argc = vms_gawk()) > 0) { /* vms_gawk => dcl_parse */ /* if we successfully parsed the command, replace original argv[] */ argc = v_argc, argv = v_argv; v_argz = v_argc = 0, v_argv = NULL; } #endif v_add_arg(v_argc = 0, basename(argv[0])); /* store arg #0 (image name) */ f_in = f_out = f_err = NULL; /* stdio setup (no filenames yet) */ out_mode = "w"; /* default access for stdout */ rms_opt1 = rms_opt2 = "ctx=stm"; /* ("context = stream") == no-opt */ for (i = 1; i < argc; i++) { char *p, *fn; int is_arg; is_arg = 0; /* current arg does not begin with dash */ p = argv[i]; /* current arg */ switch (*p) { case '<': /* stdin */ /*[should try to determine whether this is really a directory spec using <>; for now, force user to quote them with '\<']*/ if ( f_in ) { fatal("multiple specification of '<' for stdin"); } else if (*++p == '<') { /* '<<' is not supported */ fatal("'<<' not available for stdin"); } else { p = skipblanks(p); fn = (*p ? p : argv[++i]); /* use next arg if necessary */ if (i >= argc || *fn == '-') fatal("invalid i/o redirection, null filespec after '<'"); else f_in = fn; /* save filename for stdin */ } break; case '>': { /* stdout or stderr */ /*[vms-specific kludge '>$' added to force stdout to be created as record-oriented text file instead of in stream-lf format]*/ int is_out = 1; /* assume stdout */ if (*++p == '>') /* '>>' => append */ out_mode = "a", p++; else if (*p == '&') /* '>&' => stderr */ is_out = 0, p++; else if (*p == '$') /* '>$' => kludge for record format */ rms_opt1 = "rfm=var", rms_opt2 = "rat=cr", p++; else /* '>' => create */ ; /* use default values initialized prior to loop */ p = skipblanks(p); fn = (*p ? p : argv[++i]); /* use next arg if necessary */ if (i >= argc || *fn == '-') { fatal("invalid i/o redirection, null filespec after '>'"); } else if (is_out) { if (out_to_err_redirect) fatal("conflicting specifications for stdout"); else if (f_out) fatal("multiple specification of '>' for stdout"); else f_out = fn; /* save filename for stdout */ } else { if (err_to_out_redirect) fatal("conflicting specifications for stderr"); else if (f_err) fatal("multiple specification of '>&' for stderr"); else f_err = fn; /* save filename for stderr */ } } break; case '2': /* check for ``2>&1'' special case'' */ if (strcmp(p, "2>&1") != 0) goto ordinary_arg; else if (f_err || out_to_err_redirect) fatal("conflicting specifications for stderr"); else { err_to_out_redirect = 1; f_err = "SYS$OUTPUT:"; } break; case '1': /* check for ``1>&2'' special case'' */ if (strcmp(p, "1>&2") != 0) goto ordinary_arg; else if (f_out || err_to_out_redirect) fatal("conflicting specifications for stdout"); else { out_to_err_redirect = 1; f_out = "SYS$ERROR:"; } break; case '|': /* pipe */ /* command pipelines are not supported */ fatal("command pipes not available ('|' encountered)"); break; case '&': /* background */ /*[we could probably spawn or fork ourself--maybe someday]*/ if (*(p+1) == '\0' && i == argc - 1) { fatal("background tasks not available ('&' encountered)"); break; } else /* fall through */ ; /*NOBREAK*/ case '-': /* argument */ is_arg = 1; /*(=> skip wildcard check)*/ default: /* other (filespec assumed) */ ordinary_arg: /* process escape sequences or expand wildcards */ v_add_arg(++v_argc, p); /* include this arg */ p = strchr(p, '\\'); /* look for backslash */ if (p != NULL) { /* does it have escape sequence(s)? */ #if 0 /* disable escape parsing; it's now done elsewhere within gawk */ register int c; char *q = v_argv[v_argc] + (p - argv[i]); do { c = *p++; if (c == '\\') c = parse_escape(&p); *q++ = (c >= 0 ? (char)c : '\\'); } while (*p != '\0'); *q = '\0'; #endif /*0*/ } else if (!is_arg && strchr(v_argv[v_argc], '=') == NULL) { vms_expand_wildcards(v_argv[v_argc]); } break; } /* end switch */ } /* loop */ /* * Now process any/all I/O options encountered above. */ /* must do stderr first, or vaxcrtl init might not see it */ /*[ catch 22: we'll also redirect errors encountered doing <in or >out ]*/ if (f_err) { /* define logical name but don't open file */ int len = strlen(f_err); if (strncasecmp(f_err, "SYS$OUTPUT", len) == 0 && (f_err[len] == ':' || f_err[len] == '\0')) err_to_out_redirect = 1; else (void) vms_define("SYS$ERROR", f_err); } /* do stdin before stdout, so we bomb we won't create empty output file */ if (f_in) { /* [re]open file and define logical name */ stdin = freopen(f_in, "r", stdin, "mbf=2"); if (stdin != NULL) (void) vms_define("SYS$INPUT", f_in); else fatal("<%s (%s)", f_in, strerror(errno)); } if (f_out) { /* disallow file sharing to reduce overhead */ stdout = freopen(f_out, out_mode, stdout, rms_opt1, rms_opt2, "shr=nil", "mbf=2"); /*VAXCRTL*/ if (stdout != NULL) { #ifdef crtl_bug /* eof sometimes doesn't get set properly for stm_lf file */ # define BIGBUF 8*BUFSIZ /* maximum record size: 4096 instead of 512 */ setvbuf(stdout, malloc(BIGBUF), _IOFBF, BIGBUF); #endif (void) vms_define("SYS$OUTPUT", f_out); } else fatal(">%s%s (%s)", (*out_mode == 'a' ? ">" : ""), f_out, strerror(errno)); } if (err_to_out_redirect) { /* special case for ``2>&1'' construct */ (void) fclose(stderr); (void) dup2(1, 2); /* make file 2 (stderr) share file 1 (stdout) */ stderr = stdout; (void) vms_define("SYS$ERROR", "SYS$OUTPUT:"); } else if (out_to_err_redirect) { /* ``1>&2'' */ (void) fclose(stdout); (void) dup2(2, 1); /* make file 1 (stdout) share file 2 (stderr) */ stdout = stderr; (void) vms_define("SYS$OUTPUT", "SYS$ERROR:"); } #ifndef NO_DCL_CMD /* if we replaced argv[] with our own, we can release it now */ if (argv != *pargv) free((void *)argv), argv = NULL; #endif *pargc = ++v_argc; /* increment to account for argv[0] */ *pargv = v_argv; return; }
Regexp * make_regexp(const char *s, size_t len, int ignorecase, int dfa) { Regexp *rp; const char *rerr; const char *src = s; char *temp; const char *end = s + len; register char *dest; register int c, c2; static short first = TRUE; static short no_dfa = FALSE; int has_anchor = FALSE; /* The number of bytes in the current multibyte character. It is 0, when the current character is a singlebyte character. */ size_t is_multibyte = 0; #ifdef MBS_SUPPORT mbstate_t mbs; if (gawk_mb_cur_max > 1) memset(&mbs, 0, sizeof(mbstate_t)); /* Initialize. */ #endif if (first) { first = FALSE; no_dfa = (getenv("GAWK_NO_DFA") != NULL); /* for debugging and testing */ } /* Handle escaped characters first. */ /* * Build a copy of the string (in dest) with the * escaped characters translated, and generate the regex * from that. */ emalloc(dest, char *, len + 2, "make_regexp"); temp = dest; while (src < end) { #ifdef MBS_SUPPORT if (gawk_mb_cur_max > 1 && ! is_multibyte) { /* The previous byte is a singlebyte character, or last byte of a multibyte character. We check the next character. */ is_multibyte = mbrlen(src, end - src, &mbs); if ((is_multibyte == 1) || (is_multibyte == (size_t) -1) || (is_multibyte == (size_t) -2 || (is_multibyte == 0))) { /* We treat it as a singlebyte character. */ is_multibyte = 0; } } #endif /* We skip multibyte character, since it must not be a special character. */ if ((gawk_mb_cur_max == 1 || ! is_multibyte) && (*src == '\\')) { c = *++src; switch (c) { case 'a': case 'b': case 'f': case 'n': case 'r': case 't': case 'v': case 'x': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': c2 = parse_escape(&src); if (c2 < 0) cant_happen(); /* * Unix awk treats octal (and hex?) chars * literally in re's, so escape regexp * metacharacters. */ if (do_traditional && ! do_posix && (ISDIGIT(c) || c == 'x') && strchr("()|*+?.^$\\[]", c2) != NULL) *dest++ = '\\'; *dest++ = (char) c2; break; case '8': case '9': /* a\9b not valid */ *dest++ = c; src++; break; case 'y': /* normally \b */ /* gnu regex op */ if (! do_traditional) { *dest++ = '\\'; *dest++ = 'b'; src++; break; } /* else, fall through */ default: *dest++ = '\\'; *dest++ = (char) c; src++; break; } /* switch */ } else { c = *src; if (c == '^' || c == '$') has_anchor = TRUE; *dest++ = *src++; /* not '\\' */ } if (gawk_mb_cur_max > 1 && is_multibyte) is_multibyte--; } /* while */ *dest = '\0' ; /* Only necessary if we print dest ? */ emalloc(rp, Regexp *, sizeof(*rp), "make_regexp"); memset((char *) rp, 0, sizeof(*rp)); rp->pat.allocated = 0; /* regex will allocate the buffer */ emalloc(rp->pat.fastmap, char *, 256, "make_regexp"); /* * Lo these many years ago, had I known what a P.I.T.A. IGNORECASE * was going to turn out to be, I wouldn't have bothered with it. * * In the case where we have a multibyte character set, we have no * choice but to use RE_ICASE, since the casetable is for single-byte * character sets only. * * On the other hand, if we do have a single-byte character set, * using the casetable should give a performance improvement, since * it's computed only once, not each time a regex is compiled. We * also think it's probably better for portability. See the * discussion by the definition of casetable[] in eval.c. */ if (ignorecase) { if (gawk_mb_cur_max > 1) { syn |= RE_ICASE; rp->pat.translate = NULL; } else { syn &= ~RE_ICASE; rp->pat.translate = (char *) casetable; } } else { rp->pat.translate = NULL; syn &= ~RE_ICASE; } dfasyntax(syn | (ignorecase ? RE_ICASE : 0), ignorecase ? TRUE : FALSE, '\n'); re_set_syntax(syn); len = dest - temp; if ((rerr = re_compile_pattern(temp, len, &(rp->pat))) != NULL) fatal("%s: /%s/", rerr, temp); /* rerr already gettextized inside regex routines */ /* gack. this must be done *after* re_compile_pattern */ rp->pat.newline_anchor = FALSE; /* don't get \n in middle of string */ if (dfa && ! no_dfa) { dfacomp(temp, len, &(rp->dfareg), TRUE); rp->dfa = TRUE; } else rp->dfa = FALSE; rp->has_anchor = has_anchor; free(temp); return rp; }
static void mi_parse_argv (char *args, struct mi_parse *parse) { char *chp = args; int argc = 0; char **argv = xmalloc ((argc + 1) * sizeof (char *)); argv[argc] = NULL; while (1) { char *arg; /* skip leading white space */ while (isspace (*chp)) chp++; /* Three possibilities: EOF, quoted string, or other text. */ switch (*chp) { case '\0': parse->argv = argv; parse->argc = argc; return; case '"': { /* A quoted string. */ int len; char *start = chp + 1; /* Determine the buffer size. */ chp = start; len = 0; while (*chp != '\0' && *chp != '"') { if (*chp == '\\') { chp++; if (parse_escape (&chp) <= 0) { /* Do not allow split lines or "\000" */ freeargv (argv); return; } } else chp++; len++; } /* Insist on a closing quote. */ if (*chp != '"') { freeargv (argv); return; } /* Insist on trailing white space. */ if (chp[1] != '\0' && !isspace (chp[1])) { freeargv (argv); return; } /* create the buffer. */ arg = xmalloc ((len + 1) * sizeof (char)); /* And copy the characters in. */ chp = start; len = 0; while (*chp != '\0' && *chp != '"') { if (*chp == '\\') { chp++; arg[len] = parse_escape (&chp); } else arg[len] = *chp++; len++; } arg[len] = '\0'; chp++; /* that closing quote. */ break; } default: { /* An unquoted string. Accumulate all non blank characters into a buffer. */ int len; char *start = chp; while (*chp != '\0' && !isspace (*chp)) { chp++; } len = chp - start; arg = xmalloc ((len + 1) * sizeof (char)); strncpy (arg, start, len); arg[len] = '\0'; break; } } /* Append arg to argv. */ argv = xrealloc (argv, (argc + 2) * sizeof (char *)); argv[argc++] = arg; argv[argc] = NULL; } }
void do_set_command (const char *arg, int from_tty, struct cmd_list_element *c) { /* A flag to indicate the option is changed or not. */ int option_changed = 0; gdb_assert (c->type == set_cmd); switch (c->var_type) { case var_string: { char *newobj; const char *p; char *q; int ch; if (arg == NULL) arg = ""; newobj = (char *) xmalloc (strlen (arg) + 2); p = arg; q = newobj; while ((ch = *p++) != '\000') { if (ch == '\\') { /* \ at end of argument is used after spaces so they won't be lost. */ /* This is obsolete now that we no longer strip trailing whitespace and actually, the backslash didn't get here in my test, readline or something did something funky with a backslash right before a newline. */ if (*p == 0) break; ch = parse_escape (get_current_arch (), &p); if (ch == 0) break; /* C loses */ else if (ch > 0) *q++ = ch; } else *q++ = ch; } #if 0 if (*(p - 1) != '\\') *q++ = ' '; #endif *q++ = '\0'; newobj = (char *) xrealloc (newobj, q - newobj); if (*(char **) c->var == NULL || strcmp (*(char **) c->var, newobj) != 0) { xfree (*(char **) c->var); *(char **) c->var = newobj; option_changed = 1; } else xfree (newobj); } break; case var_string_noescape: if (arg == NULL) arg = ""; if (*(char **) c->var == NULL || strcmp (*(char **) c->var, arg) != 0) { xfree (*(char **) c->var); *(char **) c->var = xstrdup (arg); option_changed = 1; } break; case var_filename: if (arg == NULL) error_no_arg (_("filename to set it to.")); /* FALLTHROUGH */ case var_optional_filename: { char *val = NULL; if (arg != NULL) { /* Clear trailing whitespace of filename. */ const char *ptr = arg + strlen (arg) - 1; char *copy; while (ptr >= arg && (*ptr == ' ' || *ptr == '\t')) ptr--; copy = xstrndup (arg, ptr + 1 - arg); val = tilde_expand (copy); xfree (copy); } else val = xstrdup (""); if (*(char **) c->var == NULL || strcmp (*(char **) c->var, val) != 0) { xfree (*(char **) c->var); *(char **) c->var = val; option_changed = 1; } else xfree (val); } break; case var_boolean: { int val = parse_cli_boolean_value (arg); if (val < 0) error (_("\"on\" or \"off\" expected.")); if (val != *(int *) c->var) { *(int *) c->var = val; option_changed = 1; } } break; case var_auto_boolean: { enum auto_boolean val = parse_auto_binary_operation (arg); if (*(enum auto_boolean *) c->var != val) { *(enum auto_boolean *) c->var = val; option_changed = 1; } } break; case var_uinteger: case var_zuinteger: { LONGEST val; if (arg == NULL) { if (c->var_type == var_uinteger) error_no_arg (_("integer to set it to, or \"unlimited\".")); else error_no_arg (_("integer to set it to.")); } if (c->var_type == var_uinteger && is_unlimited_literal (arg)) val = 0; else val = parse_and_eval_long (arg); if (c->var_type == var_uinteger && val == 0) val = UINT_MAX; else if (val < 0 /* For var_uinteger, don't let the user set the value to UINT_MAX directly, as that exposes an implementation detail to the user interface. */ || (c->var_type == var_uinteger && val >= UINT_MAX) || (c->var_type == var_zuinteger && val > UINT_MAX)) error (_("integer %s out of range"), plongest (val)); if (*(unsigned int *) c->var != val) { *(unsigned int *) c->var = val; option_changed = 1; } } break; case var_integer: case var_zinteger: { LONGEST val; if (arg == NULL) { if (c->var_type == var_integer) error_no_arg (_("integer to set it to, or \"unlimited\".")); else error_no_arg (_("integer to set it to.")); } if (c->var_type == var_integer && is_unlimited_literal (arg)) val = 0; else val = parse_and_eval_long (arg); if (val == 0 && c->var_type == var_integer) val = INT_MAX; else if (val < INT_MIN /* For var_integer, don't let the user set the value to INT_MAX directly, as that exposes an implementation detail to the user interface. */ || (c->var_type == var_integer && val >= INT_MAX) || (c->var_type == var_zinteger && val > INT_MAX)) error (_("integer %s out of range"), plongest (val)); if (*(int *) c->var != val) { *(int *) c->var = val; option_changed = 1; } break; } case var_enum: { int i; int len; int nmatches; const char *match = NULL; char *p; /* If no argument was supplied, print an informative error message. */ if (arg == NULL) { char *msg; int msg_len = 0; for (i = 0; c->enums[i]; i++) msg_len += strlen (c->enums[i]) + 2; msg = xmalloc (msg_len); *msg = '\0'; make_cleanup (xfree, msg); for (i = 0; c->enums[i]; i++) { if (i != 0) strcat (msg, ", "); strcat (msg, c->enums[i]); } error (_("Requires an argument. Valid arguments are %s."), msg); } p = strchr (arg, ' '); if (p) len = p - arg; else len = strlen (arg); nmatches = 0; for (i = 0; c->enums[i]; i++) if (strncmp (arg, c->enums[i], len) == 0) { if (c->enums[i][len] == '\0') { match = c->enums[i]; nmatches = 1; break; /* Exact match. */ } else { match = c->enums[i]; nmatches++; } } if (nmatches <= 0) error (_("Undefined item: \"%s\"."), arg); if (nmatches > 1) error (_("Ambiguous item \"%s\"."), arg); if (*(const char **) c->var != match) { *(const char **) c->var = match; option_changed = 1; } } break; case var_zuinteger_unlimited: { LONGEST val; if (arg == NULL) error_no_arg (_("integer to set it to, or \"unlimited\".")); if (is_unlimited_literal (arg)) val = -1; else val = parse_and_eval_long (arg); if (val > INT_MAX) error (_("integer %s out of range"), plongest (val)); else if (val < -1) error (_("only -1 is allowed to set as unlimited")); if (*(int *) c->var != val) { *(int *) c->var = val; option_changed = 1; } } break; default: error (_("gdb internal error: bad var_type in do_setshow_command")); } c->func (c, NULL, from_tty); if (notify_command_param_changed_p (option_changed, c)) { char *name, *cp; struct cmd_list_element **cmds; struct cmd_list_element *p; int i; int length = 0; /* Compute the whole multi-word command options. If user types command 'set foo bar baz on', c->name is 'baz', and GDB can't pass "bar" to command option change notification, because it is confusing. We can trace back through field 'prefix' to compute the whole options, and pass "foo bar baz" to notification. */ for (i = 0, p = c; p != NULL; i++) { length += strlen (p->name); length++; p = p->prefix; } cp = name = (char *) xmalloc (length); cmds = XNEWVEC (struct cmd_list_element *, i); /* Track back through filed 'prefix' and cache them in CMDS. */ for (i = 0, p = c; p != NULL; i++) { cmds[i] = p; p = p->prefix; } /* Don't trigger any observer notification if prefixlist is not setlist. */ i--; if (cmds[i]->prefixlist != &setlist) { xfree (cmds); xfree (name); return; } /* Traverse them in the reversed order, and copy their names into NAME. */ for (i--; i >= 0; i--) { memcpy (cp, cmds[i]->name, strlen (cmds[i]->name)); cp += strlen (cmds[i]->name); if (i != 0) { cp[0] = ' '; cp++; } } cp[0] = 0; xfree (cmds); switch (c->var_type) { case var_string: case var_string_noescape: case var_filename: case var_optional_filename: case var_enum: observer_notify_command_param_changed (name, *(char **) c->var); break; case var_boolean: { char *opt = *(int *) c->var ? "on" : "off"; observer_notify_command_param_changed (name, opt); } break; case var_auto_boolean: { const char *s = auto_boolean_enums[*(enum auto_boolean *) c->var]; observer_notify_command_param_changed (name, s); } break; case var_uinteger: case var_zuinteger: { char s[64]; xsnprintf (s, sizeof s, "%u", *(unsigned int *) c->var); observer_notify_command_param_changed (name, s); } break; case var_integer: case var_zinteger: case var_zuinteger_unlimited: { char s[64]; xsnprintf (s, sizeof s, "%d", *(int *) c->var); observer_notify_command_param_changed (name, s); } break; } xfree (name); } }
/* Parse a C escape sequence. STRING_PTR points to a variable * containing a pointer to the string to parse. That pointer * is updated past the characters we use. The value of the * escape sequence is returned. * * A negative value means the sequence \ newline was seen, * which is supposed to be equivalent to nothing at all. * * If \ is followed by a null character, we return a negative * value and leave the string pointer pointing at the null character. * * If \ is followed by 000, we return 0 and leave the string pointer * after the zeros. A value of 0 does not mean end of string. */ int parse_escape(char **string_ptr) { register int c = *(*string_ptr)++; switch (c) { case 'a': return '\a'; case 'b': return '\b'; case 'e': return 033; case 'f': return '\f'; case 'n': return '\n'; case 'r': return '\r'; case 't': return '\t'; case 'v': return '\v'; case '\n': return -2; case 0: (*string_ptr)--; return 0; case '^': c = *(*string_ptr)++; if (c == '\\') { c = parse_escape(string_ptr); } if (c == '?') { return 0177; } return ((c & 0200) | (c & 037)); case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': { register int i = (c - '0'); register int count = 0; while (++count < 3) { if ((c = *(*string_ptr)++) >= '0' && c <= '7') { i *= 8; i += (c - '0'); } else { (*string_ptr)--; break; } } return i; } default: return c; } }
void do_setshow_command(char *arg, int from_tty, struct cmd_list_element *c) { if (c->type == set_cmd) { switch (c->var_type) { case var_string: { char *newstr; char *p; char *q; int ch; if (arg == NULL) arg = ""; newstr = (char *)xmalloc(strlen(arg) + 2); p = arg; q = newstr; while ((ch = *p++) != '\000') { if (ch == '\\') { /* \ at end of argument is used after spaces so they won't be lost. */ /* This is obsolete now that we no longer strip trailing whitespace and actually, the backslash didn't get here in my test, readline or something did something funky with a backslash right before a newline. */ if (*p == 0) break; ch = parse_escape(&p); if (ch == 0) break; /* C loses */ else if (ch > 0) *q++ = ch; } else *q++ = ch; } #if 0 if (*(p - 1) != '\\') *q++ = ' '; #endif /* 0 */ *q++ = '\0'; newstr = (char *)xrealloc(newstr, (q - newstr)); if (*(char **)c->var != NULL) xfree(*(char **)c->var); *(char **)c->var = newstr; } break; case var_string_noescape: if (arg == NULL) arg = ""; if (*(char **)c->var != NULL) xfree(*(char **)c->var); *(char **)c->var = savestring(arg, strlen(arg)); break; case var_optional_filename: if (arg == NULL) arg = ""; if (*(char **)c->var != NULL) xfree(*(char **)c->var); *(char **)c->var = savestring(arg, strlen(arg)); break; case var_filename: if (arg == NULL) error_no_arg(_("filename to set it to.")); if (*(char **)c->var != NULL) xfree (*(char **)c->var); *(char **)c->var = tilde_expand(arg); break; case var_boolean: *(int *)c->var = parse_binary_operation(arg); break; case var_auto_boolean: *(enum auto_boolean *)c->var = parse_auto_binary_operation(arg); break; case var_uinteger: if (arg == NULL) error_no_arg(_("integer to set it to.")); *(unsigned int *)c->var = (unsigned int)parse_and_eval_long(arg); if (*(unsigned int *)c->var == 0) *(unsigned int *)c->var = UINT_MAX; break; case var_integer: { unsigned int val; if (arg == NULL) error_no_arg(_("integer to set it to.")); val = (unsigned int)parse_and_eval_long(arg); if (val == 0) *(int *)c->var = INT_MAX; else if (val >= INT_MAX) error(_("integer %u out of range"), val); else *(int *)c->var = val; break; } case var_zinteger: if (arg == NULL) error_no_arg(_("integer to set it to.")); *(int *)c->var = (int)parse_and_eval_long(arg); break; case var_enum: { int i; int len; int nmatches = 0; const char *match = NULL; char *p; /* APPLE LOCAL: Give the valid options for all error messages for enum type commands. */ /* If an argument was supplied, parse it. */ if (arg != NULL) { p = strchr(arg, ' '); if (p) len = (p - arg); else len = strlen(arg); nmatches = 0; for (i = 0; c->enums[i]; i++) if (strncmp(arg, c->enums[i], len) == 0) { if (c->enums[i][len] == '\0') { match = c->enums[i]; nmatches = 1; break; /* exact match. */ } else { match = c->enums[i]; nmatches++; } } } if (nmatches == 1) *(const char **)c->var = match; else { /* If there was an error, print an informative error message. */ struct ui_file *tmp_error_stream = mem_fileopen(); make_cleanup_ui_file_delete (tmp_error_stream); if (arg == NULL) fprintf_unfiltered(tmp_error_stream, "Requires an argument."); else if (nmatches <= 0) fprintf_unfiltered(tmp_error_stream, "Undefined item: \"%s\".", arg); else if (nmatches > 1) fprintf_unfiltered(tmp_error_stream, "Ambiguous item \"%s\".", arg); fprintf_unfiltered(tmp_error_stream, " Valid arguments are "); for (i = 0; c->enums[i]; i++) { if (i != 0) fprintf_unfiltered(tmp_error_stream, ", "); fputs_unfiltered(c->enums[i], tmp_error_stream); } fprintf_unfiltered(tmp_error_stream, "."); error_stream(tmp_error_stream); } /* END APPLE LOCAL */ } break; default: error(_("gdb internal error: bad var_type in do_setshow_command")); } } else if (c->type == show_cmd) { struct cleanup *old_chain; struct ui_stream *stb; stb = ui_out_stream_new(uiout); old_chain = make_cleanup_ui_out_stream_delete(stb); /* Possibly call the pre hook: */ if (c->pre_show_hook) (c->pre_show_hook)(c); switch (c->var_type) { case var_string: { if (*(unsigned char **)c->var) fputstr_filtered(*(char **)c->var, '"', stb->stream); } break; case var_string_noescape: case var_optional_filename: case var_filename: case var_enum: if (*(char **)c->var) fputs_filtered(*(char **)c->var, stb->stream); break; case var_boolean: fputs_filtered(*(int *)c->var ? "on" : "off", stb->stream); break; case var_auto_boolean: switch (*(enum auto_boolean*)c->var) { case AUTO_BOOLEAN_TRUE: fputs_filtered("on", stb->stream); break; case AUTO_BOOLEAN_FALSE: fputs_filtered("off", stb->stream); break; case AUTO_BOOLEAN_AUTO: fputs_filtered("auto", stb->stream); break; default: internal_error(__FILE__, __LINE__, _("do_setshow_command: invalid var_auto_boolean")); break; } break; case var_uinteger: if (*(unsigned int *)c->var == UINT_MAX) { fputs_filtered("unlimited", stb->stream); break; } /* else fall through */ case var_zinteger: fprintf_filtered(stb->stream, "%u", *(unsigned int *)c->var); break; case var_integer: if (*(int *)c->var == INT_MAX) { fputs_filtered("unlimited", stb->stream); } else fprintf_filtered(stb->stream, "%d", *(int *)c->var); break; default: error(_("gdb internal error: bad var_type in do_setshow_command")); } /* FIXME: cagney/2005-02-10: Need to split this in half: code to convert the value into a string (esentially the above); and code to print the value out. For the latter there should be MI and CLI specific versions. */ if (ui_out_is_mi_like_p(uiout)) ui_out_field_stream(uiout, "value", stb); else { long length; char *value = ui_file_xstrdup(stb->stream, &length); make_cleanup(xfree, value); if (c->show_value_func != NULL) c->show_value_func(gdb_stdout, from_tty, c, value); else deprecated_show_value_hack(gdb_stdout, from_tty, c, value); } do_cleanups(old_chain); } else error(_("gdb internal error: bad cmd_type in do_setshow_command")); c->func(c, NULL, from_tty); if ((c->type == set_cmd) && deprecated_set_hook) deprecated_set_hook(c); }
/** * Print a char in a certain console. * * @param con The console to which the char is printed. * @param ch The char to print. *****************************************************************************/ PUBLIC void out_char(TTY* tty, char ch) { CONSOLE * con = tty->tty_dev; u8* pch = (u8*)(V_MEM_BASE + con->cursor * 2); assert(con->cursor - con->orig < con->con_size); /* * calculate the coordinate of cursor in current console (not in * current screen) */ int cursor_x = (con->cursor - con->orig) % SCR_WIDTH; int cursor_y = (con->cursor - con->orig) / SCR_WIDTH; if (con->c_esc_state > 0) { /* check for escape sequences */ parse_escape(con, ch); return; } switch(ch) { case 000: return; case 007: /* beep */ //beep(); break; case '\b': /* backspace */ if (con->cursor > con->orig) { con->cursor--; *(pch - 2) = ' '; *(pch - 1) = DEFAULT_CHAR_COLOR; } break; case '\n': /* line feed */ if ((con->con_tty->tty_termios.c_oflag & (OPOST|ONLCR)) == (OPOST|ONLCR)) { con->cursor = con->orig + SCR_WIDTH * cursor_y; } case 013: /* CTRL-K */ case 014: /* CTRL-L */ con->cursor = con->cursor + SCR_WIDTH; break; case '\r': /* carriage return */ con->cursor = con->orig + SCR_WIDTH * cursor_y; break; case '\t': /* tab */ con->cursor = con->orig + SCR_WIDTH * cursor_y + ((cursor_x + TAB_SIZE) & ~TAB_MASK); break; case 033: /* ESC - start of an escape sequence */ con->c_esc_state = 1; return; default: *pch++ = ch; *pch++ = DEFAULT_CHAR_COLOR; con->cursor++; break; } if (con->cursor - con->orig >= con->con_size) { cursor_x = (con->cursor - con->orig) % SCR_WIDTH; cursor_y = (con->cursor - con->orig) / SCR_WIDTH; int cp_orig = con->orig + (cursor_y + 1) * SCR_WIDTH - SCR_SIZE; w_copy(con->orig, cp_orig, SCR_SIZE - SCR_WIDTH); con->crtc_start = con->orig; con->cursor = con->orig + (SCR_SIZE - SCR_WIDTH) + cursor_x; clear_screen(con->cursor, SCR_WIDTH); if (!con->is_full) con->is_full = 1; } assert(con->cursor - con->orig < con->con_size); while (con->cursor >= con->crtc_start + SCR_SIZE || con->cursor < con->crtc_start) { scroll_screen(con, SCR_UP); clear_screen(con->cursor, SCR_WIDTH); } flush(con); }