module * module_parser::parse(const module_source & source, istream & text_stream) { if (verbose<module_parser>::enabled()) cout << "Parsing " << source.path << endl; ast::node_ptr ast; { stream::parsing::driver parser(text_stream, cout, source); int error = parser.parse(); if (error) throw parser_error(); ast = parser.ast(); if (verbose<ast::output>::enabled()) { cout << endl << "## AST for file " << source.path << " ##" << endl; ast::printer p; p.print(ast.get()); cout << endl; } } auto & elems = ast->as_list()->elements; string mod_name; if (elems[0]) mod_name = elems[0]->as_leaf<string>()->value; else mod_name = "m"; #if 0 if (m_named_modules.find(mod_name) != m_named_modules.end()) { ostringstream msg; msg << "Module " << mod_name << " is already imported."; throw io_error(msg.str()); } #endif if (verbose<module_parser>::enabled()) cout << "Module name = " << mod_name << endl; auto mod = new module; mod->source = source; mod->name = mod_name; mod->ast = ast; m_named_modules.emplace(mod_name, mod); unordered_map<string, module*> imported_mods; auto imports_node = elems[1]; if (imports_node) { for (auto & import_node : imports_node->as_list()->elements) { auto import_decl = parse_import(mod, import_node); imported_mods.insert(import_decl); } } mod->imports = imported_mods; m_ordered_modules.push_back(mod); if (verbose<module_parser>::enabled()) cout << "Done parsing " << source.path << endl; return mod; }
static void config_parse_line(calipso_config_t *config , char *line, int nline) { char option[MAXOPTLEN]= {0}, value[MAXOPTLEN] = {0}; char *s, *delim = NULL; if(strlen(line) > MAXOPTLEN ) parser_error(nline, PERR_LINE); //printf("line '%s' %d\n", line, nline); if(block_begin(line)) { if(!strlen(_block)) { s = strtok(line, BLOCK_BEGIN); if(s) { strncpy(_block, s, MAXOPTLEN); trim(_block); //mark context begin config_mark_ctx(config, CTX_BLOCK_BEGIN); } else parser_error(nline, PERR_BLOCK); } else parser_error(nline, PERR_BEGIN); //printf("begin '%s'\n", _block); return; } if(block_end(line)) { if(strlen(_block) > 0) { //mark context end config_mark_ctx(config, CTX_BLOCK_END); memset(_block, 0 , MAXOPTLEN); } else parser_error(nline, PERR_END); //printf("end '%s'\n", _block); return; } if(strstr(line , DELIM_EQU)) delim = DELIM_EQU; else if(strstr(line , DELIM_SPACE)) delim = DELIM_SPACE; else if(strstr(line, DELIM_TAB)) delim = DELIM_TAB; else parser_error(nline, PERR_DELIM); s = strtok (line, delim); if (s) { strncpy (option, s, MAXOPTLEN); } s = strtok (NULL, delim); if (s) { strncpy (value, s, MAXOPTLEN); } if ( strlen(option) && strlen(value)) { trim(option); trim(value); config_set_option(config, option, value, strlen(_block) ? _block : NULL ); } else { parser_error(nline, PERR_PAIR); } }
static void check_identifier(parser & p, environment const & env, name const & ns, name const & id) { name full_id = ns + id; if (!env.find(full_id)) throw parser_error(sstream() << "invalid 'using' command, unknown declaration '" << full_id << "'", p.pos()); }
void Parser::parse() { std::string line; // Skip first line of input; SPICE syntax spec getline(file, line); this->line_no++; std::smatch matches; // Track highest node in file to determine matrix size int max_node = -1; while (!file.eof()) { // Get a line of input getline(file, line); // Flag for regex match bool match = false; try { // Check for line match match = this->match_line(line); // // Iterate through regex patterns; if match found, determine // // which component matched // for (auto r: this->regexes) { // if (regex_search(line, matches, r.reg)) { // switch (r.type) { // case EMPTY_LINE: case COMMENT_LINE: // break; // case R: // this->parse_line<Component>(matches, this->comps, r.type, &max_node); // break; // case VDC: case IDC: // this->parse_line<Source>(matches, this->sources, r.type, &max_node); // break; // } // // Once found a match, no need to search more // match = true; // break; // } //} if (!match) { throw parser_error("Syntax error", line, this->line_no); } } catch (parser_error& e) { this->error = e; this->state = parser_state::error; break; } this->line_no++; } // If really at EOF, then file has been parsed if (file.eof()) { this->state = parser_state::parsed; } }
double parser_read_builtin( parser_data *pd ){ double v0, v1; char c, token[PARSER_MAX_TOKEN_SIZE]; int pos=0; c = parser_peek( pd ); if( isalpha(c) || c == '_' ){ while( isalpha(c) || isdigit(c) || c == '-' ){ token[pos++] = parser_eat( pd ); c = parser_peek( pd ); } token[pos] = '\0'; // eat opening bracket if( parser_eat(pd) != '(' ) parser_error( pd, "Expected '(' in builtin call!" ); // start handling the specific builtin functions if( strcmp( token, "pow" ) == 0 ){ v0 = parser_read_argument( pd ); v1 = parser_read_argument( pd ); v0 = pow( v0, v1 ); } else if( strcmp( token, "sqrt" ) == 0 ){ v0 = parser_read_argument( pd ); if( v0 < 0.0 ) parser_error( pd, "sqrt(x) undefined for x < 0!" ); v0 = sqrt( v0 ); } else if( strcmp( token, "log" ) == 0 ){ v0 = parser_read_argument( pd ); if( v0 <= 0 ) parser_error( pd, "log(x) undefined for x <= 0!" ); v0 = log( v0 ); } else if( strcmp( token, "exp" ) == 0 ){ v0 = parser_read_argument( pd ); v0 = exp( v0 ); } else if( strcmp( token, "sin" ) == 0 ){ v0 = parser_read_argument( pd ); v0 = sin( v0 ); } else if( strcmp( token, "asin" ) == 0 ){ v0 = parser_read_argument( pd ); if( fabs(v0) > 1.0 ) parser_error( pd, "asin(x) undefined for |x| > 1!" ); v0 = asin( v0 ); } else if( strcmp( token, "cos" ) == 0 ){ v0 = parser_read_argument( pd ); if( fabs(v0 ) > 1.0 ) parser_error( pd, "acos(x) undefined for |x| > 1!" ); v0 = cos( v0 ); } else if( strcmp( token, "acos" ) == 0 ){ v0 = parser_read_argument( pd ); v0 = acos( v0 ); } else if( strcmp( token, "tan" ) == 0 ){ v0 = parser_read_argument( pd ); v0 = tan( v0 ); } else if( strcmp( token, "atan" ) == 0 ){ v0 = parser_read_argument( pd ); v0 = atan( v0 ); } else if( strcmp( token, "atan2" ) == 0 ){ v0 = parser_read_argument( pd ); v1 = parser_read_argument( pd ); v0 = atan2( v0, v1 ); } else if( strcmp( token, "abs" ) == 0 ){ v0 = parser_read_argument( pd ); v0 = abs( v0 ); } else if( strcmp( token, "fabs" ) == 0 ){ v0 = parser_read_argument( pd ); v0 = fabs( v0 ); } else if( strcmp( token, "floor" ) == 0 ){ v0 = parser_read_argument( pd ); v0 = floor( v0 ); } else if( strcmp( token, "ceil" ) == 0 ){ v0 = parser_read_argument( pd ); v0 = floor( v0 ); } else if( strcmp( token, "round" ) == 0 ){ v0 = parser_read_argument( pd ); v0 = round( v0 ); } else { parser_error( pd, "Tried to call unknown builtin function!" ); } // eat closing bracket of function call if( parser_eat( pd ) != ')' ) parser_error( pd, "Expected ')' in builtin call!" ); } else { // not a builtin function call, just read a literal double v0 = parser_read_double( pd ); } // consume whitespace parser_eat_whitespace( pd ); // return the value return v0; }
void decl_attributes::parse(parser & p) { buffer<char const *> attr_tokens; get_attribute_tokens(attr_tokens); while (true) { auto pos = p.pos(); if (auto it = parse_priority(p)) { m_prio = *it; bool has_prio_attr = false; for (auto const & entry : m_entries) { if (get_attribute_kind(entry.m_attr.c_str()) == attribute_kind::Prioritized) { has_prio_attr = true; break; } } if (!has_prio_attr) { throw parser_error("invalid '[priority]' attribute, declaration has not been marked with a prioritized attribute", pos); } } else if (p.curr_is_token(get_parsing_only_tk())) { if (!m_is_abbrev) throw parser_error("invalid '[parsing_only]' attribute, only abbreviations can be " "marked as '[parsing_only]'", pos); m_parsing_only = true; p.next(); } else { bool found = false; for (char const * tk : attr_tokens) { if (p.curr_is_token(tk)) { p.next(); char const * attr = get_attribute_from_token(tk); for (auto const & entry : m_entries) { if (are_incompatible(entry.m_attr.c_str(), attr)) { throw parser_error(sstream() << "invalid attribute [" << attr << "], declaration was already marked with [" << entry.m_attr << "]", pos); } } switch (get_attribute_kind(attr)) { case attribute_kind::Default: case attribute_kind::Prioritized: m_entries = cons(entry(attr), m_entries); break; case attribute_kind::Parametric: { unsigned v = p.parse_small_nat(); if (v == 0) throw parser_error("invalid attribute parameter, value must be positive", pos); p.check_token_next(get_rbracket_tk(), "invalid attribute, ']' expected"); m_entries = cons(entry(attr, v-1), m_entries); break; } case attribute_kind::OptParametric: if (!p.curr_is_token(get_rbracket_tk())) { unsigned v = p.parse_small_nat(); if (v == 0) throw parser_error("invalid attribute parameter, value must be positive", pos); p.check_token_next(get_rbracket_tk(), "invalid attribute, ']' expected"); m_entries = cons(entry(attr, v-1), m_entries); } else { p.check_token_next(get_rbracket_tk(), "invalid attribute, ']' expected"); m_entries = cons(entry(attr), m_entries); } break; case attribute_kind::MultiParametric: { buffer<unsigned> vs; while (true) { unsigned v = p.parse_small_nat(); if (v == 0) throw parser_error("invalid attribute parameter, value must be positive", pos); vs.push_back(v-1); if (p.curr_is_token(get_rbracket_tk())) break; } p.next(); m_entries = cons(entry(attr, to_list(vs)), m_entries); break; } } found = true; break; } } if (!found) break; } } }
ani_curico_t *new_ani_curico(enum res_e type, raw_data_t *rd, int *memopt) { ani_curico_t *ani = xmalloc(sizeof(ani_curico_t)); riff_tag_t *rtp; int isswapped = 0; int doswap; const char *anistr = type == res_aniico ? "icon" : "cursor"; assert(!memcmp(rd->data, riff, sizeof(riff))); assert(type == res_anicur || type == res_aniico); rtp = (riff_tag_t *)rd->data; if(BYTESWAP_DWORD(rtp->size) + 2*sizeof(DWORD) == rd->size) isswapped = 1; else if(rtp->size + 2*sizeof(DWORD) == rd->size) isswapped = 0; else parser_error("Animated %s has an invalid RIFF length", anistr); switch(byteorder) { #ifdef WORDS_BIGENDIAN case WRC_BO_LITTLE: #else case WRC_BO_BIG: #endif doswap = !isswapped; break; default: doswap = isswapped; } /* * When to swap what: * isswapped | doswap | * ----------+--------+--------------------------------- * 0 | 0 | read native; don't convert * 1 | 0 | read swapped size; don't convert * 0 | 1 | read native; convert * 1 | 1 | read swapped size; convert * Reading swapped size if necessary to calculate in native * format. E.g. a little-endian source on a big-endian * processor. */ if(doswap) { /* We only go through the RIFF file if we need to swap * bytes in words/dwords. Else we couldn't care less * what the file contains. This is consistent with * MS' rc.exe, which doesn't complain at all, even though * the file format might not be entirely correct. */ rtp++; /* Skip the "RIFF" tag */ while((char *)rtp < (char *)rd->data + rd->size) { if(!memcmp(rtp->tag, acon, sizeof(acon))) { rtp = SKIP_TAG(rtp,4); } else if(!memcmp(rtp->tag, list, sizeof(list))) { handle_ani_list(rtp, type, isswapped); rtp = NEXT_TAG(rtp); } else if(!memcmp(rtp->tag, anih, sizeof(anih))) { aniheader_t *ahp = (aniheader_t *)((char *)(rtp+1)); ahp->structsize = BYTESWAP_DWORD(ahp->structsize); ahp->frames = BYTESWAP_DWORD(ahp->frames); ahp->steps = BYTESWAP_DWORD(ahp->steps); ahp->cx = BYTESWAP_DWORD(ahp->cx); ahp->cy = BYTESWAP_DWORD(ahp->cy); ahp->bitcount = BYTESWAP_DWORD(ahp->bitcount); ahp->planes = BYTESWAP_DWORD(ahp->planes); ahp->rate = BYTESWAP_DWORD(ahp->rate); ahp->flags = BYTESWAP_DWORD(ahp->flags); rtp = NEXT_TAG(rtp); } else if(!memcmp(rtp->tag, rate, sizeof(rate))) { int cnt = rtp->size / sizeof(DWORD); DWORD *dwp = (DWORD *)(rtp+1); int i; for(i = 0; i < cnt; i++) dwp[i] = BYTESWAP_DWORD(dwp[i]); rtp = NEXT_TAG(rtp); } else if(!memcmp(rtp->tag, seq, sizeof(seq))) { int cnt = rtp->size / sizeof(DWORD); DWORD *dwp = (DWORD *)(rtp+1); int i; for(i = 0; i < cnt; i++) dwp[i] = BYTESWAP_DWORD(dwp[i]); rtp = NEXT_TAG(rtp); } else internal_error(__FILE__, __LINE__, "Unknown tag \"%c%c%c%c\" in RIFF file", isprint(rtp->tag[0]) ? rtp->tag[0] : '.', isprint(rtp->tag[1]) ? rtp->tag[1] : '.', isprint(rtp->tag[2]) ? rtp->tag[2] : '.', isprint(rtp->tag[3]) ? rtp->tag[3] : '.'); if((UINT_PTR)rtp & 1) rtp = SKIP_TAG(rtp,1); } /* We must end correctly here */ if((char *)rtp != (char *)rd->data + rd->size) parser_error("Animated %s contains invalid field size(s)", anistr); } ani->data = rd; if(memopt) { ani->memopt = *memopt; free(memopt); } else ani->memopt = WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE; return ani; }
void parser_imp::check_next(scanner::token t, char const * msg) { if (curr() == t) next(); else throw parser_error(msg, pos()); }
static void split_icons(raw_data_t *rd, icon_group_t *icog, int *nico) { int cnt; int i; icon_t *ico; icon_t *list = NULL; icon_header_t *ih = (icon_header_t *)rd->data; int swap = 0; if(ih->type == 1) swap = 0; else if(BYTESWAP_WORD(ih->type) == 1) swap = 1; else parser_error("Icon resource data has invalid type id %d", ih->type); cnt = swap ? BYTESWAP_WORD(ih->count) : ih->count; for(i = 0; i < cnt; i++) { icon_dir_entry_t ide; BITMAPINFOHEADER info; memcpy(&ide, rd->data + sizeof(icon_header_t) + i*sizeof(icon_dir_entry_t), sizeof(ide)); ico = new_icon(); ico->id = alloc_icon_id(icog->lvc.language); ico->lvc = icog->lvc; if(swap) { ide.offset = BYTESWAP_DWORD(ide.offset); ide.ressize= BYTESWAP_DWORD(ide.ressize); } if(ide.offset > rd->size || ide.offset + ide.ressize > rd->size) parser_error("Icon resource data corrupt"); ico->width = ide.width; ico->height = ide.height; ico->nclr = ide.nclr; ico->planes = swap ? BYTESWAP_WORD(ide.planes) : ide.planes; ico->bits = swap ? BYTESWAP_WORD(ide.bits) : ide.bits; memcpy(&info, rd->data + ide.offset, sizeof(info)); convert_bitmap((char *) &info, 0); memcpy(rd->data + ide.offset, &info, sizeof(info)); if(!ico->planes) { /* Argh! They did not fill out the resdir structure */ /* The bitmap is in destination byteorder. We want native for our structures */ switch(byteorder) { #ifdef WORDS_BIGENDIAN case WRC_BO_LITTLE: #else case WRC_BO_BIG: #endif ico->planes = BYTESWAP_WORD(info.biPlanes); break; default: ico->planes = info.biPlanes; } } if(!ico->bits) { /* Argh! They did not fill out the resdir structure */ /* The bitmap is in destination byteorder. We want native for our structures */ switch(byteorder) { #ifdef WORDS_BIGENDIAN case WRC_BO_LITTLE: #else case WRC_BO_BIG: #endif ico->bits = BYTESWAP_WORD(info.biBitCount); break; default: ico->bits = info.biBitCount; } } ico->data = new_raw_data(); copy_raw_data(ico->data, rd, ide.offset, ide.ressize); if(!list) { list = ico; } else { ico->next = list; list->prev = ico; list = ico; } } icog->iconlist = list; *nico = cnt; }
static void split_cursors(raw_data_t *rd, cursor_group_t *curg, int *ncur) { int cnt; int i; cursor_t *cur; cursor_t *list = NULL; cursor_header_t *ch = (cursor_header_t *)rd->data; int swap = 0; if(ch->type == 2) swap = 0; else if(BYTESWAP_WORD(ch->type) == 2) swap = 1; else parser_error("Cursor resource data has invalid type id %d", ch->type); cnt = swap ? BYTESWAP_WORD(ch->count) : ch->count; for(i = 0; i < cnt; i++) { cursor_dir_entry_t cde; BITMAPINFOHEADER info; memcpy(&cde, rd->data + sizeof(cursor_header_t) + i*sizeof(cursor_dir_entry_t), sizeof(cde)); cur = new_cursor(); cur->id = alloc_cursor_id(curg->lvc.language); cur->lvc = curg->lvc; if(swap) { cde.offset = BYTESWAP_DWORD(cde.offset); cde.ressize= BYTESWAP_DWORD(cde.ressize); } if(cde.offset > rd->size || cde.offset + cde.ressize > rd->size) parser_error("Cursor resource data corrupt"); cur->width = cde.width; cur->height = cde.height; cur->nclr = cde.nclr; memcpy(&info, rd->data + cde.offset, sizeof(info)); convert_bitmap((char *)&info, 0); memcpy(rd->data + cde.offset, &info, sizeof(info)); /* The bitmap is in destination byteorder. We want native for our structures */ switch(byteorder) { #ifdef WORDS_BIGENDIAN case WRC_BO_LITTLE: #else case WRC_BO_BIG: #endif cur->planes = BYTESWAP_WORD(info.biPlanes); cur->bits = BYTESWAP_WORD(info.biBitCount); break; default: cur->planes = info.biPlanes; cur->bits = info.biBitCount; } if(!win32 && (cur->planes != 1 || cur->bits != 1)) parser_warning("Win16 cursor contains colors\n"); cur->xhot = swap ? BYTESWAP_WORD(cde.xhot) : cde.xhot; cur->yhot = swap ? BYTESWAP_WORD(cde.yhot) : cde.yhot; cur->data = new_raw_data(); copy_raw_data(cur->data, rd, cde.offset, cde.ressize); if(!list) { list = cur; } else { cur->next = list; list->prev = cur; list = cur; } } curg->cursorlist = list; *ncur = cnt; }
static int convert_bitmap(char *data, int size) { BITMAPINFOHEADER *bih = (BITMAPINFOHEADER *)data; BITMAPV4HEADER *b4h = (BITMAPV4HEADER *)data; BITMAPOS2HEADER *boh = (BITMAPOS2HEADER *)data; int type = 0; int returnSize = 0; /* size to be returned */ #ifdef WORDS_BIGENDIAN DWORD bisizel = BYTESWAP_DWORD(sizeof(BITMAPINFOHEADER)); DWORD b4sizel = BYTESWAP_DWORD(sizeof(BITMAPV4HEADER)); DWORD bosizel = BYTESWAP_DWORD(sizeof(BITMAPOS2HEADER)); DWORD bisizeb = sizeof(BITMAPINFOHEADER); DWORD b4sizeb = sizeof(BITMAPV4HEADER); DWORD bosizeb = sizeof(BITMAPOS2HEADER); #else DWORD bisizel = sizeof(BITMAPINFOHEADER); DWORD b4sizel = sizeof(BITMAPV4HEADER); DWORD bosizel = sizeof(BITMAPOS2HEADER); DWORD bisizeb = BYTESWAP_DWORD(sizeof(BITMAPINFOHEADER)); DWORD b4sizeb = BYTESWAP_DWORD(sizeof(BITMAPV4HEADER)); DWORD bosizeb = BYTESWAP_DWORD(sizeof(BITMAPOS2HEADER)); #endif /* * Originally the bih and b4h pointers were simply incremented here, * and memmoved at the end of the function. This causes alignment * issues on solaris, so we do the memmove here rather than at the end. */ if(data[0] == 'B' && data[1] == 'M') { /* Little endian signature */ memmove(data, data+sizeof(BITMAPFILEHEADER), size - sizeof(BITMAPFILEHEADER)); returnSize = sizeof(BITMAPFILEHEADER); } else if(data[0] == 'M' && data[1] == 'B') { type |= FL_SIGBE; /* Big endian signature */ memmove(data, data+sizeof(BITMAPFILEHEADER), size - sizeof(BITMAPFILEHEADER)); returnSize = sizeof(BITMAPFILEHEADER); } if(bih->biSize == bisizel) { /* Little endian */ } else if(bih->biSize == bisizeb) { type |= FL_SIZEBE; } else if(bih->biSize == b4sizel) { type |= FL_V4; } else if(bih->biSize == b4sizeb) { type |= FL_SIZEBE | FL_V4; } else if(!bih->biSize || bih->biSize == bosizel) { type |= FL_OS2; } else if(bih->biSize == bosizeb) { type |= FL_SIZEBE | FL_OS2; } else parser_error("Invalid bitmap format, bih->biSize = %d", bih->biSize); switch(type) { default: break; case FL_SIZEBE: case FL_SIZEBE | FL_V4: case FL_SIZEBE | FL_OS2: parser_warning("Bitmap v%c signature little-endian, but size big-endian\n", type & FL_V4 ? '4' : '3'); break; case FL_SIGBE: case FL_SIGBE | FL_V4: case FL_SIGBE | FL_OS2: parser_warning("Bitmap v%c signature big-endian, but size little-endian\n", type & FL_V4 ? '4' : '3'); break; } switch(byteorder) { #ifdef WORDS_BIGENDIAN default: #endif case WRC_BO_BIG: if(!(type & FL_SIZEBE)) { if(type & FL_V4) convert_bitmap_swap_v4(b4h); else if(type & FL_OS2) { convert_bitmap_swap_os2(boh); } else convert_bitmap_swap_v3(bih); } break; #ifndef WORDS_BIGENDIAN default: #endif case WRC_BO_LITTLE: if(type & FL_SIZEBE) { if(type & FL_V4) convert_bitmap_swap_v4(b4h); else if(type & FL_OS2) { convert_bitmap_swap_os2(boh); } else convert_bitmap_swap_v3(bih); } break; } if(size && (void *)data != (void *)bih) { /* We have the fileheader still attached, remove it */ memmove(data, data+sizeof(BITMAPFILEHEADER), size - sizeof(BITMAPFILEHEADER)); return sizeof(BITMAPFILEHEADER); } return returnSize; }
static void types_new_rec_handler(struct ir_unit *iu, int op, unsigned int argc, const ir_arg_t *argv) { ir_type_t it; const char *ctx = "types"; assert(iu->iu_types_created == 0); switch(op) { case TYPE_CODE_NUMENTRY: if(argc < 1) parser_error(iu, "%s: Short NUMENTRY record", ctx); VECTOR_SET_CAPACITY(&iu->iu_types, argv[0].i64); return; case TYPE_CODE_VOID: it.it_code = IR_TYPE_VOID; break; case TYPE_CODE_FLOAT: it.it_code = IR_TYPE_FLOAT; break; case TYPE_CODE_DOUBLE: it.it_code = IR_TYPE_DOUBLE; break; case TYPE_CODE_INTEGER: if(argv[0].i64 == 1) { it.it_code = IR_TYPE_INT1; } else if(argv[0].i64 == 8) { it.it_code = IR_TYPE_INT8; } else if(argv[0].i64 == 16) { it.it_code = IR_TYPE_INT16; } else if(argv[0].i64 == 32) { it.it_code = IR_TYPE_INT32; } else if(argv[0].i64 == 64) { it.it_code = IR_TYPE_INT64; } else if(argv[0].i64 < 64) { it.it_code = IR_TYPE_INTx; it.it_bits = argv[0].i64; } else { parser_error(iu, "%s: Integer width %d bit not supported", ctx, (int)argv[0].i64); } break; case TYPE_CODE_ARRAY: it.it_code = IR_TYPE_ARRAY; it.it_array.num_elements = argv[0].i64; it.it_array.element_type = argv[1].i64; break; case TYPE_CODE_STRUCT_NAME: free(iu->iu_current_struct_name); iu->iu_current_struct_name = read_str_from_argv(argc, argv); return; case TYPE_CODE_STRUCT_NAMED: it.it_struct.name = iu->iu_current_struct_name; iu->iu_current_struct_name = NULL; if(0) case TYPE_CODE_STRUCT_ANON: it.it_struct.name = NULL; it.it_code = IR_TYPE_STRUCT; it.it_struct.num_elements = argc - 1; it.it_struct.elements = malloc(it.it_struct.num_elements * sizeof(it.it_struct.elements[0])); { const int packed = !!argv[0].i64; int offset = 0; int ba = 1; // Biggest alignment for(int i = 0; i < it.it_struct.num_elements; i++) { int t = argv[i + 1].i64; it.it_struct.elements[i].type = t; int s = type_sizeof(iu, t); if(!packed) { int a = type_alignment(iu ,t); offset = VMIR_ALIGN(offset, a); ba = MAX(ba, a); } it.it_struct.elements[i].offset = offset; offset += s; } it.it_struct.size = packed ? offset : VMIR_ALIGN(offset, ba); it.it_struct.alignment = ba; } break; case TYPE_CODE_POINTER: it.it_code = IR_TYPE_POINTER; it.it_pointer.pointee = argv[0].i64; break; case TYPE_CODE_FUNCTION: if(argc < 2) parser_error(iu, "%s: Invalid # of args (%d) for function type", ctx, argc); it.it_code = IR_TYPE_FUNCTION; it.it_function.varargs = argv[0].i64; it.it_function.return_type = argv[1].i64; it.it_function.num_parameters = argc - 2; it.it_function.parameters = malloc(it.it_function.num_parameters * sizeof(int)); for(int i = 0; i < it.it_function.num_parameters; i++) it.it_function.parameters[i] = argv[2 + i].i64; break; case TYPE_CODE_METADATA: it.it_code = IR_TYPE_METADATA; break; case TYPE_CODE_LABEL: it.it_code = IR_TYPE_LABEL; break; case TYPE_CODE_OPAQUE: it.it_code = IR_TYPE_OPAQUE; break; case TYPE_CODE_VECTOR: printf("Vector of %s x %d\n", type_str_index(iu, argv[1].i64), (int)argv[0].i64); // break; default: printargs(argv, argc); parser_error(iu, "%s: Unknown op %d", ctx, op); } VECTOR_PUSH_BACK(&iu->iu_types, it); }
char parser_eat( parser_data *pd ){ if( pd->pos < pd->len ) return pd->str[pd->pos++]; parser_error( pd, "Tried to read past end of string!" ); return '\0'; }
void config_parse(char *filename) { int fd , nameStart , nameStop , valueStart , valueStop , lineR // Counting \r's , lineN // Counting \n's , lineT // Highest of \r's and \n's , lineC // Character in line , pos; // Byte position in file char *name , *value , *config; state state; letter l; size_t filesize; filesize = getFilesize(filename); /* Open file */ fd = open(filename, O_RDONLY, 0); if (fd == -1) { /* Do not throw an error on EACCES, to allow blindly reading * the 'global' followed by the 'root only' configurations to * simplify overall code. */ if (errno != EACCES) { parser_error("readable file", "unreadable file", -1, -1); } return; } /* Execute mmap */ config = mmap(NULL, filesize, PROT_READ, MAP_PRIVATE | MAP_POPULATE, fd, 0); if (config == MAP_FAILED) { parser_error("mmapable file", "error mmapping file", -1, -1); goto abort_mmap; } name = value = NULL; nameStart = nameStop = valueStart = valueStop = pos = 0; lineR = lineN = lineC = lineT = 1; state = STATE_START_OF_LINE; do { switch(config[pos]) { case '\r': lineR++; lineT = max(lineR, lineN); lineC = 1; l = LETTER_END_OF_LINE; break; case '\n': lineN++; lineT = max(lineR, lineN); lineC = 1; l = LETTER_END_OF_LINE; break; case ' ': case '\t': l = LETTER_WHITESPACE; break; case '=': l = LETTER_EQUAL; break; case '#': l = LETTER_COMMENT; break; default: if ((config[pos] < ' ') || (config[pos] > '~')) { l = LETTER_INVALID; parser_error("valid character", "invalid character", lineT, lineC); state = STATE_COMMENT_OR_ERROR; break; } l = LETTER_LETTER; break; } switch(state) { case STATE_COMMENT_OR_ERROR: switch(l) { case LETTER_END_OF_LINE: state = STATE_START_OF_LINE; break; default: break; } break; case STATE_START_OF_LINE: switch(l) { case LETTER_END_OF_LINE: case LETTER_WHITESPACE: break; case LETTER_EQUAL: parser_error("option name", "=", lineT, lineC); state = STATE_COMMENT_OR_ERROR; break; case LETTER_COMMENT: state = STATE_COMMENT_OR_ERROR; break; case LETTER_LETTER: default: nameStart = pos; nameStop = pos; state = STATE_NAME; break; } break; case STATE_NAME: switch(l) { case LETTER_END_OF_LINE: parser_error("=", "end of line", lineT, lineC); state = STATE_COMMENT_OR_ERROR; break; case LETTER_WHITESPACE: state = STATE_PRE_EQUAL; break; case LETTER_EQUAL: state = STATE_POST_EQUAL; break; case LETTER_COMMENT: parser_error("=", "comment", lineT, lineC); state = STATE_COMMENT_OR_ERROR; break; case LETTER_LETTER: default: nameStop = pos; break; } break; case STATE_PRE_EQUAL: switch(l) { case LETTER_WHITESPACE: break; case LETTER_EQUAL: state = STATE_POST_EQUAL; break; default: parser_error("= or more whitespace", "gibberish", lineT, lineC); state = STATE_COMMENT_OR_ERROR; break; } break; case STATE_POST_EQUAL: switch(l) { case LETTER_END_OF_LINE: parser_error("option value or more whitespace", "end of line", lineT, lineC); state = STATE_COMMENT_OR_ERROR; break; case LETTER_WHITESPACE: break; case LETTER_EQUAL: case LETTER_COMMENT: case LETTER_LETTER: default: valueStart = pos; valueStop = pos; state = STATE_VALUE; break; } break; case STATE_VALUE: switch(l) { case LETTER_END_OF_LINE: name = strndup((char *)config + nameStart, nameStop - nameStart + 1); value = strndup((char *)config + valueStart, valueStop - valueStart + 1); option_set(name, value); free(name); free(value); state = STATE_START_OF_LINE; break; case LETTER_WHITESPACE: case LETTER_EQUAL: case LETTER_COMMENT: case LETTER_LETTER: default: valueStop = pos; break; } break; } pos++; lineC++; } while (pos < filesize); /* End-of-File handling. */ switch(state) { case STATE_NAME: case STATE_PRE_EQUAL: parser_error("=", "end of file", lineT, lineC); break; case STATE_POST_EQUAL: parser_error("option value", "end of file", lineT, lineC); break; case STATE_START_OF_LINE: case STATE_COMMENT_OR_ERROR: case STATE_VALUE: default: /* Valid end of file location, no issue. */ break; } /* Cleanup */ munmap(config, filesize); abort_mmap: close(fd); }
messagetable_t *new_messagetable(raw_data_t *rd, int *memopt) { messagetable_t *msg = xmalloc(sizeof(messagetable_t)); msgtab_block_t *mbp; DWORD nblk; DWORD i; WORD lo; WORD hi; msg->data = rd; if(memopt) { msg->memopt = *memopt; free(memopt); } else msg->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE; if(rd->size < sizeof(DWORD)) parser_error("Invalid messagetable, size too small"); nblk = *(DWORD *)rd->data; lo = WRC_LOWORD(nblk); hi = WRC_HIWORD(nblk); /* FIXME: * This test will fail for all n*2^16 blocks in the messagetable. * However, no sane person would want to have so many blocks * and have a table of megabytes attached. * So, I will assume that we have less than 2^16 blocks in the table * and all will just work out fine. Otherwise, we would need to test * the ID, offset and length (and flag) fields to be very sure. */ if(hi && lo) internal_error(__FILE__, __LINE__, "Messagetable contains more than 65535 blocks; cannot determine endian\n"); if(!hi && !lo) parser_error("Invalid messagetable block count 0"); if(!hi && lo) /* Messagetable byteorder == native byteorder */ { #ifdef WORDS_BIGENDIAN if(byteorder != WRC_BO_LITTLE) goto out; #else if(byteorder != WRC_BO_BIG) goto out; #endif /* Resource byteorder != native byteorder */ mbp = (msgtab_block_t *)&(((DWORD *)rd->data)[1]); if(MSGTAB_BAD_PTR(mbp, rd->data, rd->size, nblk * sizeof(*mbp))) parser_error("Messagetable's blocks are outside of defined data"); for(i = 0; i < nblk; i++) { msgtab_entry_t *mep, *next_mep; DWORD id; mep = (msgtab_entry_t *)(((char *)rd->data) + mbp[i].offset); for(id = mbp[i].idlo; id <= mbp[i].idhi; id++) { if(MSGTAB_BAD_PTR(mep, rd->data, rd->size, mep->length)) parser_error("Messagetable's data for block %d, ID 0x%08x is outside of defined data", i, id); if(mep->flags == 1) /* Docu says 'flags == 0x0001' for unicode */ { WORD *wp = (WORD *)&mep[1]; int l = mep->length/2 - 2; /* Length included header */ int n; if(mep->length & 1) parser_error("Message 0x%08x is unicode (block %d), but has odd length (%d)", id, i, mep->length); for(n = 0; n < l; n++) wp[n] = BYTESWAP_WORD(wp[n]); } next_mep = (msgtab_entry_t *)(((char *)mep) + mep->length); mep->length = BYTESWAP_WORD(mep->length); mep->flags = BYTESWAP_WORD(mep->flags); mep = next_mep; } mbp[i].idlo = BYTESWAP_DWORD(mbp[i].idlo); mbp[i].idhi = BYTESWAP_DWORD(mbp[i].idhi); mbp[i].offset = BYTESWAP_DWORD(mbp[i].offset); } } if(hi && !lo) /* Messagetable byteorder != native byteorder */ { #ifdef WORDS_BIGENDIAN if(byteorder == WRC_BO_LITTLE) goto out; #else if(byteorder == WRC_BO_BIG) goto out; #endif /* Resource byteorder == native byteorder */ mbp = (msgtab_block_t *)&(((DWORD *)rd->data)[1]); nblk = BYTESWAP_DWORD(nblk); if(MSGTAB_BAD_PTR(mbp, rd->data, rd->size, nblk * sizeof(*mbp))) parser_error("Messagetable's blocks are outside of defined data"); for(i = 0; i < nblk; i++) { msgtab_entry_t *mep; DWORD id; mbp[i].idlo = BYTESWAP_DWORD(mbp[i].idlo); mbp[i].idhi = BYTESWAP_DWORD(mbp[i].idhi); mbp[i].offset = BYTESWAP_DWORD(mbp[i].offset); mep = (msgtab_entry_t *)(((char *)rd->data) + mbp[i].offset); for(id = mbp[i].idlo; id <= mbp[i].idhi; id++) { mep->length = BYTESWAP_WORD(mep->length); mep->flags = BYTESWAP_WORD(mep->flags); if(MSGTAB_BAD_PTR(mep, rd->data, rd->size, mep->length)) parser_error("Messagetable's data for block %d, ID 0x%08x is outside of defined data", i, id); if(mep->flags == 1) /* Docu says 'flags == 0x0001' for unicode */ { WORD *wp = (WORD *)&mep[1]; int l = mep->length/2 - 2; /* Length included header */ int n; if(mep->length & 1) parser_error("Message 0x%08x is unicode (block %d), but has odd length (%d)", id, i, mep->length); for(n = 0; n < l; n++) wp[n] = BYTESWAP_WORD(wp[n]); } mep = (msgtab_entry_t *)(((char *)mep) + mep->length); } } } out: return msg; }
pointer parse_number(parser* parse) { size_t len = 0; bool isFloat = false; bool isHex = false; bool isBinary = false; const char* Start = parse->curr; while(!is_delimiter(*parse->curr)) { if(*parse->curr == '.') isFloat = true; if(is_number_char(*parse->curr) || (isHex && is_extended_hex_char(*parse->curr))) len++; else if(len == 1 && *parse->curr == 'x' && *Start == '0') { len++; isHex = true; } else if(len == 0 && *parse->curr == 'b') isBinary = true; else return parser_error(parse, "Unexpected char '%c' in number literal.", *parse->curr); parse->curr++; } { int TotalIs = isHex + isBinary + isFloat; if(TotalIs > true) { char* buffer = new char[len+1]; strncpy(buffer, Start, len); buffer[len] = '\0'; parser_error(parse, "Unexpected number literal: %s.", buffer); delete buffer; return NIL; } } if(isFloat) { char* buffer = new char[len+1]; strncpy(buffer, Start, len); buffer[len] = '\0'; float ret = atof(buffer); delete buffer; return create_real(ret); } else { // Might be smart to use a buffer here, in case strtol doesn't see all delimiters as we do. int ret; if(isHex) ret = strtol(Start + 2, NULL, 16); else if(isBinary) ret = strtol(Start + 1, NULL, 2); else ret = strtol(Start, NULL, 10); return create_int(ret); } }
/* Invoke the argument FTL function with <addr> <buf> arguments for each of the ELF file's program segments */ static const value_t * elf_load_with_fn(const value_t *this_fn, parser_state_t *state, const char *filename, int binfd, Elf *e, GElf_Ehdr *ehdr, void *arg) { elf_loadfn_args_t *fnarg = (elf_loadfn_args_t *)arg; const value_t *hdrcheckfn = fnarg->hdrcheckfn; const value_t *memwrfn = fnarg->memwrfn; const value_t *resval = value_false; size_t n; if (elf_getphdrnum(e, &n) != 0) parser_report(state, "ELF file has unknown number of segments - %s\n", elf_errmsg(-1)); else { size_t i; bool ok = FALSE; if (hdrcheckfn != NULL) { const value_t *ehdrval = elf_get_ehdr(this_fn, state, filename, binfd, e, ehdr, /*arg*/NULL); if (ehdrval != NULL) { const value_t *code = value_closure_bind(hdrcheckfn, ehdrval); if (code == NULL) { parser_error(state, "couldn't apply " "header argument to check function\n"); } else { const value_t *fnres = invoke(code, state); /* we expect this to return a TRUE/FALSE value */ ok = (fnres == value_true); /*if (!ok) printf("%s: check fn returns non-TRUE\n", codeid());*/ } } } else ok = TRUE; resval = ok? value_true: value_false; if (ok && memwrfn != NULL) { for (i = 0; ok && i < n; i++) { GElf_Phdr phdr; if (gelf_getphdr(e, i, &phdr) != &phdr) parser_report(state, "ELF segment %d unretrievable - %s\n", i, elf_errmsg(-1)); else { long offset = (long)phdr.p_offset; if (phdr.p_offset != (Elf64_Off)offset) parser_report(state, "ELF segment %d - " "offset does not fit in 32-bits\n", i); else if (-1 == fe_lseek(binfd, offset)) parser_report(state, "ELF segment %d - " "offset 0X%lX is outside file\n", i, offset); else if (phdr.p_memsz < phdr.p_filesz) parser_report(state, "ELF segment %d - smaller size in memory (%d)" "than on file (%d) - corrupt header?\n", i, phdr.p_memsz, phdr.p_filesz); else { number_t addr = phdr.p_vaddr; /* where to load segment */ char *buf = NULL; size_t buflen = (size_t)phdr.p_memsz; value_t *addrval = value_int_new(addr); value_t *dataval = value_string_alloc_new(buflen, &buf); if (phdr.p_memsz != (Elf64_Xword)buflen) parser_report(state, "ELF segment %d - " "size does not fit in 32-bits\n", i); else if (dataval == NULL) parser_report(state, "ELF segment %d - no memory for " "next %d bytes\n", i, buflen); else { ssize_t readbytes = fe_read(binfd, buf, buflen); if (readbytes < buflen) parser_report(state, "ELF segment %d - " "only %d bytes of %d read\n", i, readbytes); else { const value_t *code; ok = TRUE; /* zero any uninitialized area */ if (phdr.p_memsz > phdr.p_filesz) { size_t extra_bytes = (size_t) (phdr.p_memsz - phdr.p_filesz); if ((Elf64_Xword)extra_bytes != phdr.p_memsz-phdr.p_filesz) { ok = FALSE; parser_report(state, "ELF segment %d - " "BSS area larger than 32-bits\n", i); } else memset(&buf[phdr.p_filesz], '\0', extra_bytes); } code = value_closure_bind_2(state, memwrfn, "address", addrval, "data", dataval); if (NULL != code) { const value_t *fnres = invoke(code, state); /* we expect this to return a TRUE/FALSE value */ if (fnres != value_true) { /*printf("%s: seg fn returns non-TRUE\n", codeid());*/ ok = FALSE; } /* we rely on garbage collection to collect the data * buffer */ } else value_delete(&dataval); } } } } } if (!ok) resval = value_false; } } return resval; }
[[ noreturn ]] void parser_imp::not_implemented_yet() { // TODO(Leo) throw parser_error("not implemented yet", pos()); }
/* * Parse next entry from ini-file. */ const parser_entry * parser_get_next(struct inifile *inf) { token_data data; memset(&data, 0, sizeof(token_data)); /* * Label where we continue if end of string or * multiline token is found in input stream. */ next: if(data.prev != MLINE) { /* * Reset scan data. */ if(inf->entry->key) { free(inf->entry->key); inf->entry->key = NULL; } if(inf->entry->val) { free(inf->entry->val); inf->entry->val = NULL; } } /* * Get next line from input stream. */ while((inf->len = getline(&(inf->str), &(inf->size), inf->fs)) != -1) { /* * Count up one more line. */ inf->entry->line++; /* * Skip empty and commented lines. */ if(inf->str[0] == '\n' || strchr(inf->comment, inf->str[0])) { continue; } if(inf->str[inf->len - 1] == '\n') { inf->str[inf->len - 1] = '\0'; } /* * Fill line scanning data object. */ data.pos = 0; data.line = inf->entry->line; if(data.prev != MLINE) { data.curr = NONE; data.prev = NONE; data.seen = NONE; data.cls = GLOBAL; memset(&data.quote, 0, sizeof(token_quote)); } switch(parser_tokenize(inf, &data, inf->entry)) { case PARSE_ERROR: return NULL; case PARSE_NEXT: goto next; case PARSE_DONE: if(inf->options & INIFILE_CHECK_SYNTAX) { /* * Handle syntax error that would require more context (i.e. look-ahead) * than whats available to the lexer when its doing its syntax check. */ if(data.seen == ASSIGN && (inf->entry->val == NULL || strlen(inf->entry->val) == 0)) { return parser_error(inf, &data, "assign without value"); } } return inf->entry; } } /* * Nothing found. */ return NULL; }