stmt_ty * stmt_if_alloc(blob_list_ty *condition, stmt_ty *then_clause, stmt_ty *else_clause) { stmt_if_ty *result; blob_list_ty *c2; table_ty *tp; trace(("stmt_if_alloc()\n{\n")); result = (stmt_if_ty *)stmt_alloc(&method); assert(condition->length >= 1); for (tp = table; tp < ENDOF(table); ++tp) { if (!tp->fast) tp->fast = str_from_c(tp->name); if (str_equal(condition->list[0]->text, tp->fast)) break; } assert(tp < ENDOF(table)); if (tp >= ENDOF(table)) tp = &table[0]; c2 = tp->rewrite(condition, &result->ref); blob_list_free(condition); result->condition = c2; result->then_clause = then_clause; result->else_clause = else_clause; stmt_variable_merge((stmt_ty *)result, then_clause); if (else_clause) stmt_variable_merge((stmt_ty *)result, else_clause); trace(("}\n")); return (stmt_ty *)result; }
static void version_copyright() { static char *text[] = { "All rights reserved.", "", "The %s program comes with ABSOLUTELY NO WARRANTY;", "for details use the '%s -VERSion License' command.", "The %s program is free software, and you are welcome", "to redistribute it under certain conditions; for", "details use the '%s -VERSion License' command.", }; char **cpp; char *progname; progname = progname_get(); printf("%s version %s\n", progname, version_stamp()); printf("Copyright (C) %s Peter Miller;\n", copyright_years()); for (cpp = text; cpp < ENDOF(text); ++cpp) { printf(*cpp, progname); fputc('\n', stdout); } }
bool json_t_parse_string(t_json_parser *p, t_json_t_value const *t, void *data) { t_sub val_string; t_sub *value; if (p->token != JSON_VALUE || p->value_type != JSON_VALUE_STRING) return (ft_json_fail(p, SUBC("Expecting string"))); val_string = JSON_VAL_STRING(p); value = MALLOC(sizeof(t_sub) + val_string.length); *value = SUB(ENDOF(value), val_string.length); memcpy(ENDOF(value), val_string.str, val_string.length); *(t_sub**)data = value; return (true); (void)t; }
t_file_in *ft_in_fdopen(int fd) { t_file_in *in; in = MALLOC(sizeof(t_file_in) + F_IN_BUFF_SIZE); *in = F_IN(fd, ENDOF(in), F_IN_BUFF_SIZE); return (in); }
void builtin_initialize(void) { builtin_ty **fpp; string_ty *s; for (fpp = func; fpp < ENDOF(func); ++fpp) { s = str_from_c((*fpp)->name); symtab_assign(id_global_stp(), s, id_builtin_new(*fpp)); str_free(s); } }
t_texture const *load_texture1(uint32_t color, uint32_t flags) { t_hmap *const cache = texture_cache(); uint32_t key[2]; t_texture *tmp; key[0] = flags; key[1] = color; if ((tmp = ft_hmapget(cache, SUBV(key)).value) != NULL) return (tmp); tmp = ft_hmapput(cache, SUBV(key), NULL, sizeof(t_texture) + sizeof(uint32_t)).value; ft_logf(LOG_DEBUG, "Solid texture created: #%.8x", color); *tmp = (t_texture){&texture_solid, (t_img){ENDOF(tmp), 1, 1}}; *tmp->img.data = color; if (flags & TEXTURE_GAMMA) correct_gamma(&tmp->img); return (tmp); }
char * arglex_token_name(arglex_token_ty n) { arglex_table_ty *tp; switch (n) { case arglex_token_eoln: return "end of command line"; case arglex_token_number: return "number"; case arglex_token_option: return "option"; case arglex_token_stdio: return "standard input or output"; case arglex_token_string: return "string"; default: break; } for (tp = table; tp < ENDOF(table); tp++) { if (tp->token == n) return tp->name; } if (utable) { for (tp = utable; tp->name; tp++) { if (tp->token == n) return tp->name; } } assert(0); return "unknown command line token"; }
/* * lexescape - parse an ARE backslash escape (backslash already eaten) * Note slightly nonstandard use of the CCLASS type code. */ static int /* not actually used, but convenient for RETV */ lexescape(struct vars * v) { chr c; static const chr alert[] = { CHR('a'), CHR('l'), CHR('e'), CHR('r'), CHR('t') }; static const chr esc[] = { CHR('E'), CHR('S'), CHR('C') }; const chr *save; assert(v->cflags & REG_ADVF); assert(!ATEOS()); c = *v->now++; if (!iscalnum(c)) RETV(PLAIN, c); NOTE(REG_UNONPOSIX); switch (c) { case CHR('a'): RETV(PLAIN, chrnamed(v, alert, ENDOF(alert), CHR('\007'))); break; case CHR('A'): RETV(SBEGIN, 0); break; case CHR('b'): RETV(PLAIN, CHR('\b')); break; case CHR('B'): RETV(PLAIN, CHR('\\')); break; case CHR('c'): NOTE(REG_UUNPORT); if (ATEOS()) FAILW(REG_EESCAPE); RETV(PLAIN, (chr) (*v->now++ & 037)); break; case CHR('d'): NOTE(REG_ULOCALE); RETV(CCLASS, 'd'); break; case CHR('D'): NOTE(REG_ULOCALE); RETV(CCLASS, 'D'); break; case CHR('e'): NOTE(REG_UUNPORT); RETV(PLAIN, chrnamed(v, esc, ENDOF(esc), CHR('\033'))); break; case CHR('f'): RETV(PLAIN, CHR('\f')); break; case CHR('m'): RET('<'); break; case CHR('M'): RET('>'); break; case CHR('n'): RETV(PLAIN, CHR('\n')); break; case CHR('r'): RETV(PLAIN, CHR('\r')); break; case CHR('s'): NOTE(REG_ULOCALE); RETV(CCLASS, 's'); break; case CHR('S'): NOTE(REG_ULOCALE); RETV(CCLASS, 'S'); break; case CHR('t'): RETV(PLAIN, CHR('\t')); break; case CHR('u'): c = lexdigits(v, 16, 4, 4); if (ISERR()) FAILW(REG_EESCAPE); RETV(PLAIN, c); break; case CHR('U'): c = lexdigits(v, 16, 8, 8); if (ISERR()) FAILW(REG_EESCAPE); RETV(PLAIN, c); break; case CHR('v'): RETV(PLAIN, CHR('\v')); break; case CHR('w'): NOTE(REG_ULOCALE); RETV(CCLASS, 'w'); break; case CHR('W'): NOTE(REG_ULOCALE); RETV(CCLASS, 'W'); break; case CHR('x'): NOTE(REG_UUNPORT); c = lexdigits(v, 16, 1, 255); /* REs >255 long outside spec */ if (ISERR()) FAILW(REG_EESCAPE); RETV(PLAIN, c); break; case CHR('y'): NOTE(REG_ULOCALE); RETV(WBDRY, 0); break; case CHR('Y'): NOTE(REG_ULOCALE); RETV(NWBDRY, 0); break; case CHR('Z'): RETV(SEND, 0); break; case CHR('1'): case CHR('2'): case CHR('3'): case CHR('4'): case CHR('5'): case CHR('6'): case CHR('7'): case CHR('8'): case CHR('9'): save = v->now; v->now--; /* put first digit back */ c = lexdigits(v, 10, 1, 255); /* REs >255 long outside spec */ if (ISERR()) FAILW(REG_EESCAPE); /* ugly heuristic (first test is "exactly 1 digit?") */ if (v->now == save || ((int) c > 0 && (int) c <= v->nsubexp)) { NOTE(REG_UBACKREF); RETV(BACKREF, (chr) c); } /* oops, doesn't look like it's a backref after all... */ v->now = save; /* and fall through into octal number */ case CHR('0'): NOTE(REG_UUNPORT); v->now--; /* put first digit back */ c = lexdigits(v, 8, 1, 3); if (ISERR()) FAILW(REG_EESCAPE); if (c > 0xff) { /* out of range, so we handled one digit too much */ v->now--; c >>= 3; } RETV(PLAIN, c); break; default: assert(iscalpha(c)); FAILW(REG_EESCAPE); /* unknown alphabetic escape */ break; }
/* * next - get next token */ static int /* 1 normal, 0 failure */ next(struct vars * v) { chr c; /* errors yield an infinite sequence of failures */ if (ISERR()) return 0; /* the error has set nexttype to EOS */ /* remember flavor of last token */ v->lasttype = v->nexttype; /* REG_BOSONLY */ if (v->nexttype == EMPTY && (v->cflags & REG_BOSONLY)) { /* at start of a REG_BOSONLY RE */ RETV(SBEGIN, 0); /* same as \A */ } /* if we're nested and we've hit end, return to outer level */ if (v->savenow != NULL && ATEOS()) { v->now = v->savenow; v->stop = v->savestop; v->savenow = v->savestop = NULL; } /* skip white space etc. if appropriate (not in literal or []) */ if (v->cflags & REG_EXPANDED) switch (v->lexcon) { case L_ERE: case L_BRE: case L_EBND: case L_BBND: skip(v); break; } /* handle EOS, depending on context */ if (ATEOS()) { switch (v->lexcon) { case L_ERE: case L_BRE: case L_Q: RET(EOS); break; case L_EBND: case L_BBND: FAILW(REG_EBRACE); break; case L_BRACK: case L_CEL: case L_ECL: case L_CCL: FAILW(REG_EBRACK); break; } assert(NOTREACHED); } /* okay, time to actually get a character */ c = *v->now++; /* deal with the easy contexts, punt EREs to code below */ switch (v->lexcon) { case L_BRE: /* punt BREs to separate function */ return brenext(v, c); break; case L_ERE: /* see below */ break; case L_Q: /* literal strings are easy */ RETV(PLAIN, c); break; case L_BBND: /* bounds are fairly simple */ case L_EBND: switch (c) { case CHR('0'): case CHR('1'): case CHR('2'): case CHR('3'): case CHR('4'): case CHR('5'): case CHR('6'): case CHR('7'): case CHR('8'): case CHR('9'): RETV(DIGIT, (chr) DIGITVAL(c)); break; case CHR(','): RET(','); break; case CHR('}'): /* ERE bound ends with } */ if (INCON(L_EBND)) { INTOCON(L_ERE); if ((v->cflags & REG_ADVF) && NEXT1('?')) { v->now++; NOTE(REG_UNONPOSIX); RETV('}', 0); } RETV('}', 1); } else FAILW(REG_BADBR); break; case CHR('\\'): /* BRE bound ends with \} */ if (INCON(L_BBND) && NEXT1('}')) { v->now++; INTOCON(L_BRE); RET('}'); } else FAILW(REG_BADBR); break; default: FAILW(REG_BADBR); break; } assert(NOTREACHED); break; case L_BRACK: /* brackets are not too hard */ switch (c) { case CHR(']'): if (LASTTYPE('[')) RETV(PLAIN, c); else { INTOCON((v->cflags & REG_EXTENDED) ? L_ERE : L_BRE); RET(']'); } break; case CHR('\\'): NOTE(REG_UBBS); if (!(v->cflags & REG_ADVF)) RETV(PLAIN, c); NOTE(REG_UNONPOSIX); if (ATEOS()) FAILW(REG_EESCAPE); (DISCARD) lexescape(v); switch (v->nexttype) { /* not all escapes okay here */ case PLAIN: return 1; break; case CCLASS: switch (v->nextvalue) { case 'd': lexnest(v, brbackd, ENDOF(brbackd)); break; case 's': lexnest(v, brbacks, ENDOF(brbacks)); break; case 'w': lexnest(v, brbackw, ENDOF(brbackw)); break; default: FAILW(REG_EESCAPE); break; } /* lexnest done, back up and try again */ v->nexttype = v->lasttype; return next(v); break; } /* not one of the acceptable escapes */ FAILW(REG_EESCAPE); break; case CHR('-'): if (LASTTYPE('[') || NEXT1(']')) RETV(PLAIN, c); else RETV(RANGE, c); break; case CHR('['): if (ATEOS()) FAILW(REG_EBRACK); switch (*v->now++) { case CHR('.'): INTOCON(L_CEL); /* might or might not be locale-specific */ RET(COLLEL); break; case CHR('='): INTOCON(L_ECL); NOTE(REG_ULOCALE); RET(ECLASS); break; case CHR(':'): INTOCON(L_CCL); NOTE(REG_ULOCALE); RET(CCLASS); break; default: /* oops */ v->now--; RETV(PLAIN, c); break; } assert(NOTREACHED); break; default: RETV(PLAIN, c); break; } assert(NOTREACHED); break; case L_CEL: /* collating elements are easy */ if (c == CHR('.') && NEXT1(']')) { v->now++; INTOCON(L_BRACK); RETV(END, '.'); } else RETV(PLAIN, c); break; case L_ECL: /* ditto equivalence classes */ if (c == CHR('=') && NEXT1(']')) { v->now++; INTOCON(L_BRACK); RETV(END, '='); } else RETV(PLAIN, c); break; case L_CCL: /* ditto character classes */ if (c == CHR(':') && NEXT1(']')) { v->now++; INTOCON(L_BRACK); RETV(END, ':'); } else RETV(PLAIN, c); break; default: assert(NOTREACHED); break; } /* that got rid of everything except EREs and AREs */ assert(INCON(L_ERE)); /* deal with EREs and AREs, except for backslashes */ switch (c) { case CHR('|'): RET('|'); break; case CHR('*'): if ((v->cflags & REG_ADVF) && NEXT1('?')) { v->now++; NOTE(REG_UNONPOSIX); RETV('*', 0); } RETV('*', 1); break; case CHR('+'): if ((v->cflags & REG_ADVF) && NEXT1('?')) { v->now++; NOTE(REG_UNONPOSIX); RETV('+', 0); } RETV('+', 1); break; case CHR('?'): if ((v->cflags & REG_ADVF) && NEXT1('?')) { v->now++; NOTE(REG_UNONPOSIX); RETV('?', 0); } RETV('?', 1); break; case CHR('{'): /* bounds start or plain character */ if (v->cflags & REG_EXPANDED) skip(v); if (ATEOS() || !iscdigit(*v->now)) { NOTE(REG_UBRACES); NOTE(REG_UUNSPEC); RETV(PLAIN, c); } else { NOTE(REG_UBOUNDS); INTOCON(L_EBND); RET('{'); } assert(NOTREACHED); break; case CHR('('): /* parenthesis, or advanced extension */ if ((v->cflags & REG_ADVF) && NEXT1('?')) { NOTE(REG_UNONPOSIX); v->now++; if (ATEOS()) FAILW(REG_BADRPT); switch (*v->now++) { case CHR(':'): /* non-capturing paren */ RETV('(', 0); break; case CHR('#'): /* comment */ while (!ATEOS() && *v->now != CHR(')')) v->now++; if (!ATEOS()) v->now++; assert(v->nexttype == v->lasttype); return next(v); break; case CHR('='): /* positive lookahead */ NOTE(REG_ULOOKAROUND); RETV(LACON, LATYPE_AHEAD_POS); break; case CHR('!'): /* negative lookahead */ NOTE(REG_ULOOKAROUND); RETV(LACON, LATYPE_AHEAD_NEG); break; case CHR('<'): if (ATEOS()) FAILW(REG_BADRPT); switch (*v->now++) { case CHR('='): /* positive lookbehind */ NOTE(REG_ULOOKAROUND); RETV(LACON, LATYPE_BEHIND_POS); break; case CHR('!'): /* negative lookbehind */ NOTE(REG_ULOOKAROUND); RETV(LACON, LATYPE_BEHIND_NEG); break; default: FAILW(REG_BADRPT); break; } assert(NOTREACHED); break; default: FAILW(REG_BADRPT); break; } assert(NOTREACHED); } if (v->cflags & REG_NOSUB) RETV('(', 0); /* all parens non-capturing */ else RETV('(', 1); break; case CHR(')'): if (LASTTYPE('(')) NOTE(REG_UUNSPEC); RETV(')', c); break; case CHR('['): /* easy except for [[:<:]] and [[:>:]] */ if (HAVE(6) && *(v->now + 0) == CHR('[') && *(v->now + 1) == CHR(':') && (*(v->now + 2) == CHR('<') || *(v->now + 2) == CHR('>')) && *(v->now + 3) == CHR(':') && *(v->now + 4) == CHR(']') && *(v->now + 5) == CHR(']')) { c = *(v->now + 2); v->now += 6; NOTE(REG_UNONPOSIX); RET((c == CHR('<')) ? '<' : '>'); } INTOCON(L_BRACK); if (NEXT1('^')) { v->now++; RETV('[', 0); } RETV('[', 1); break; case CHR('.'): RET('.'); break; case CHR('^'): RET('^'); break; case CHR('$'): RET('$'); break; case CHR('\\'): /* mostly punt backslashes to code below */ if (ATEOS()) FAILW(REG_EESCAPE); break; default: /* ordinary character */ RETV(PLAIN, c); break; } /* ERE/ARE backslash handling; backslash already eaten */ assert(!ATEOS()); if (!(v->cflags & REG_ADVF)) { /* only AREs have non-trivial escapes */ if (iscalnum(*v->now)) { NOTE(REG_UBSALNUM); NOTE(REG_UUNSPEC); } RETV(PLAIN, *v->now++); } (DISCARD) lexescape(v); if (ISERR()) FAILW(REG_EESCAPE); if (v->nexttype == CCLASS) { /* fudge at lexical level */ switch (v->nextvalue) { case 'd': lexnest(v, backd, ENDOF(backd)); break; case 'D': lexnest(v, backD, ENDOF(backD)); break; case 's': lexnest(v, backs, ENDOF(backs)); break; case 'S': lexnest(v, backS, ENDOF(backS)); break; case 'w': lexnest(v, backw, ENDOF(backw)); break; case 'W': lexnest(v, backW, ENDOF(backW)); break; default: assert(NOTREACHED); FAILW(REG_ASSERT); break; } /* lexnest done, back up and try again */ v->nexttype = v->lasttype; return next(v); } /* otherwise, lexescape has already done the work */ return !ISERR(); }
/* * lexword - interpolate a bracket expression for word characters * Possibly ought to inquire whether there is a "word" character class. */ static void lexword(struct vars * v) { lexnest(v, backw, ENDOF(backw)); }
static int reserved(string_ty *s) { typedef struct table_ty table_ty; struct table_ty { char *name; int token; }; static table_ty table[] = { { "override", OVERRIDE }, { "include", INCLUDE2 }, { "-include", INCLUDE3 }, { ".include", INCLUDE }, { "vpath", VPATH }, { "VPATH", VPATH2 }, { "ifdef", IF }, { "ifndef", IF }, { "ifeq", IF }, { "ifneq", IF }, { "else", ELSE }, { "endif", ENDIF }, { "endef", ENDDEF }, { "define", DEFINE }, { "export", EXPORT }, { "unexport", UNEXPORT }, }; static symtab_ty *symtab; int *data; string_ty *name; char *cp; if (!symtab) { table_ty *tp; symtab = symtab_alloc(SIZEOF(table)); for (tp = table; tp < ENDOF(table); ++tp) { name = str_from_c(tp->name); symtab_assign(symtab, name, &tp->token); str_free(name); } } cp = strchr(s->str_text, '('); if (cp) { name = str_n_from_c(s->str_text, cp - s->str_text); data = symtab_query(symtab, name); str_free(name); } else data = symtab_query(symtab, s); if (data) return *data; return 0; }
arglex_token_ty arglex(void) { arglex_table_ty *tp; int j; arglex_table_ty *hit[20]; int nhit; char *arg; static char *pushback[3]; static int pushback_depth; trace(("arglex()\n{\n")); if (pushback_depth) { /* * the second half of a "-foo=bar" style argument. */ arg = pushback[--pushback_depth]; } else { if (argc <= 0) { arglex_token = arglex_token_eoln; arg = ""; goto done; } arg = argv[0]; argc--; argv++; /* * See if it looks like a GNU "-foo=bar" option. * Split it at the '=' to make it something the * rest of the code understands. */ if (arg[0] == '-' && arg[1] != '=') { char *eqp; eqp = strchr(arg, '='); if (eqp) { pushback[pushback_depth++] = eqp + 1; *eqp = 0; } } /* * Turn the GNU-style leading "--" * into "-" if necessary. */ if (arg[0] == '-' && arg[1] == '-' && arg[2] && !is_a_number(arg + 1)) ++arg; } /* * see if it is a number */ if (is_a_number(arg)) { arglex_token = arglex_token_number; goto done; } /* * scan the tables to see what it matches */ nhit = 0; partial = 0; for (tp = table; tp < ENDOF(table); tp++) { if (arglex_compare(tp->name, arg)) hit[nhit++] = tp; } if (utable) { for (tp = utable; tp->name; tp++) { if (arglex_compare(tp->name, arg)) hit[nhit++] = tp; } } /* * deal with unknown or ambiguous options */ switch (nhit) { case 0: /* * not found in the tables */ if (*arg == '-') arglex_token = arglex_token_option; else arglex_token = arglex_token_string; break; case 1: if (partial) pushback[pushback_depth++] = (char *)partial; arg = hit[0]->name; arglex_token = hit[0]->token; break; default: { string_ty *s1; string_ty *s2; sub_context_ty *scp; s1 = str_from_c(hit[0]->name); for (j = 1; j < nhit; ++j) { s2 = str_format("%s, %s", s1->str_text, hit[j]->name); str_free(s1); s1 = s2; } scp = sub_context_new(); sub_var_set_charstar(scp, "Name", arg); sub_var_set_string(scp, "Guess", s1); fatal_intl(scp, i18n("option \"$name\" ambiguous ($guess)")); /* NOTREACHED */ } } /* * here for all exits */ done: arglex_value.alv_string = arg; trace(("return %d; /* \"%s\" */\n", arglex_token, arg)); trace(("}\n")); return arglex_token; }