VALUE rb_ary_new_with_len(long len) { VALUE ary = INT2FIX(len); VALUE block = push_block(); ary = rb_class_new_instance(1, &ary, rb_cArray); pop_block(block); return ary; }
static inline int execute_if (node *stmt, exec_env *env) { int ret; value val; ret = eval_expression(&val, stmt->left, env); if(ret < 0) { return ret; } else { ret = 0; } if(is_true(&val)) { ret = push_block(env, stmt->right); if(ret >= 0) { env->skip_advance = 1; return 0; } env->error.code = ERROR_BAD_ALLOC; env->error.line = stmt->loc.line; env->error.col = stmt->loc.col; env->error.file = env->lib->label; env->error.static_msg = "unable to push block."; return ret; } return 1; }
static void decision_tree( unsigned int s, unsigned int e, char *var, void (*leaf)(unsigned int)) { if ( s == (e-1) ) { (*leaf)(s); return; } push_block("If", "And(%s, 0x%02x)", var, (e-s)/2); decision_tree((s+e)/2, e, var, leaf); pop_block(); push_block("Else", NULL); decision_tree(s, (s+e)/2, var, leaf); pop_block(); }
int Message_Unit::recover_ptr_body(Unit_Message *ptr_data) { if (!ptr_data->ptr_data) return CALL_RETURN; if (ptr_data->data_type == Unit_Message::TYPE_DATA_BUFFER) { push_block(ptr_data->pool_gid, (Block_Buffer *)ptr_data->ptr_data); return CALL_RETURN; } return CALL_CONTINUE; }
void blockchain::create_genesis_block() { genesis_block_.header_.prev_hash = "0000000000000000000000000000000000000000000000000000000000000000"; genesis_block_.header_.timestamp = get_now_timestamp(); genesis_block_.header_.tx_count = 1; genesis_block_.header_.difficulty = 1; genesis_block_.header_.hash = to_sha256(genesis_block_.to_json()); push_block(genesis_block_); }
int handlefunction(astree node, FILE* outfile){ astree type = node->first; astree ident = node->first->first; astree param = node->first->next->first; bitset_t newattrs = bitlookup(type->symbol); node->attrs = newattrs; cstring funcname = peek_stringtable(ident->lexinfo); sym_noderef lookup = search_sym_table(ident,gident_tbl); if (lookup != NULL){ if (lookup->attributes & ATTR_PROTOTYPE){ //found previous func declaration, it's a prototype if (lookup->attributes == ((newattrs | ATTR_PROTOTYPE))){ if(paramcheck(param,lookup->nextparam,funcname)){ return 1; } } else { print_attributes(stdout,(ATTR_PROTOTYPE + ATTR_BOOL)); eprintf("\n"); print_attributes(stdout,(newattrs|ATTR_PROTOTYPE)); eprintf("\n"); //func declaration does not match prototype's type eprintf( "prototype's type does not match function declaration %s\n", funcname); } } else { //found previous func declaration, it's not a prototype eprintf( "redeclaring function %s at line %d\n", peek_stringtable(ident->lexinfo),ident->linenr-1); eprintf( "(previously declared at line %d)\n",lookup->linenr-1); return 1; } } else { ident->attrs = ATTR_FUNCTION | bitlookup(type->symbol); sym_noderef temp = intern_sym_table(ident,gident_tbl,outfile); push_block(gblock_stk); for(;param != NULL; param = param->next){ param->first->attrs = bitlookup(param->symbol) | ATTR_PARAM; param->first->blocknr = gblock_stk->top->blocknr; temp->nextparam = intern_sym_table(param->first,gident_tbl,outfile); temp = temp->nextparam; } pop_idents(gident_tbl,gblock_stk->top->blocknr); pop_block(gblock_stk); } return 0; }
void database::debug_update( const fc::variant_object& update ) { block_id_type head_id = head_block_id(); auto it = _node_property_object.debug_updates.find( head_id ); if( it == _node_property_object.debug_updates.end() ) it = _node_property_object.debug_updates.emplace( head_id, std::vector< fc::variant_object >() ).first; it->second.emplace_back( update ); optional<signed_block> head_block = fetch_block_by_id( head_id ); FC_ASSERT( head_block.valid() ); // What the last block does has been changed by adding to node_property_object, so we have to re-apply it pop_block(); push_block( *head_block ); }
/* checks a block and includes it in the database with synchronization, ruturs non-zero value in case of error */ int xdag_sync_add_block(struct xdag_block *b, void *conn) { int res, ttl = b->field[0].transport_header >> 8 & 0xff; res = xdag_add_block(b); if (res >= 0) { xdag_sync_pop_block(b); if (res > 0 && ttl > 2) { b->field[0].transport_header = ttl << 8; xdag_send_packet(b, (void*)((uintptr_t)conn | 1l)); } } else if (g_xdag_sync_on && ((res = -res) & 0xf) == 5) { res = (res >> 4) & 0xf; if (push_block(b, conn, res, ttl)) { struct sync_block **p, *q; uint64_t *hash = b->field[res].hash; time_t t = time(0); pthread_mutex_lock(&g_sync_hash_mutex); begin: for (p = get_list_r(hash); (q = *p); p = &q->next_r) { if (!memcmp(hash, q->hash, sizeof(xdag_hashlow_t))) { if (t - q->t < REQ_PERIOD) { pthread_mutex_unlock(&g_sync_hash_mutex); return 0; } q->t = t; hash = q->b.field[q->nfield].hash; goto begin; } } pthread_mutex_unlock(&g_sync_hash_mutex); xdag_request_block(hash, (void*)(uintptr_t)1l); xdag_info("ReqBlk: %016llx%016llx%016llx%016llx", hash[3], hash[2], hash[1], hash[0]); } }
signed_block database::_generate_block( fc::time_point_sec when, witness_id_type witness_id, const fc::ecc::private_key& block_signing_private_key ) { try { uint32_t skip = get_node_properties().skip_flags; uint32_t slot_num = get_slot_at_time( when ); FC_ASSERT( slot_num > 0 ); witness_id_type scheduled_witness = get_scheduled_witness( slot_num ); FC_ASSERT( scheduled_witness == witness_id ); const auto& witness_obj = witness_id(*this); if( !(skip & skip_witness_signature) ) FC_ASSERT( witness_obj.signing_key == block_signing_private_key.get_public_key() ); static const size_t max_block_header_size = fc::raw::pack_size( signed_block_header() ) + 4; auto maximum_block_size = get_global_properties().parameters.maximum_block_size; size_t total_block_size = max_block_header_size; signed_block pending_block; // // The following code throws away existing pending_tx_session and // rebuilds it by re-applying pending transactions. // // This rebuild is necessary because pending transactions' validity // and semantics may have changed since they were received, because // time-based semantics are evaluated based on the current block // time. These changes can only be reflected in the database when // the value of the "when" variable is known, which means we need to // re-apply pending transactions in this method. // _pending_tx_session.reset(); _pending_tx_session = _undo_db.start_undo_session(); uint64_t postponed_tx_count = 0; // pop pending state (reset to head block state) for( const processed_transaction& tx : _pending_tx ) { size_t new_total_size = total_block_size + fc::raw::pack_size( tx ); // postpone transaction if it would make block too big if( new_total_size >= maximum_block_size ) { postponed_tx_count++; continue; } try { auto temp_session = _undo_db.start_undo_session(); processed_transaction ptx = _apply_transaction( tx ); temp_session.merge(); // We have to recompute pack_size(ptx) because it may be different // than pack_size(tx) (i.e. if one or more results increased // their size) total_block_size += fc::raw::pack_size( ptx ); pending_block.transactions.push_back( ptx ); } catch ( const fc::exception& e ) { // Do nothing, transaction will not be re-applied wlog( "Transaction was not processed while generating block due to ${e}", ("e", e) ); wlog( "The transaction was ${t}", ("t", tx) ); } } if( postponed_tx_count > 0 ) { wlog( "Postponed ${n} transactions due to block size limit", ("n", postponed_tx_count) ); } _pending_tx_session.reset(); // We have temporarily broken the invariant that // _pending_tx_session is the result of applying _pending_tx, as // _pending_tx now consists of the set of postponed transactions. // However, the push_block() call below will re-create the // _pending_tx_session. pending_block.previous = head_block_id(); pending_block.timestamp = when; pending_block.transaction_merkle_root = pending_block.calculate_merkle_root(); pending_block.witness = witness_id; if( !(skip & skip_witness_signature) ) pending_block.sign( block_signing_private_key ); // TODO: Move this to _push_block() so session is restored. if( !(skip & skip_block_size_check) ) { FC_ASSERT( fc::raw::pack_size(pending_block) <= get_global_properties().parameters.maximum_block_size ); } push_block( pending_block, skip ); return pending_block; } FC_CAPTURE_AND_RETHROW( (witness_id) ) }
int FIAL_interpret (struct FIAL_exec_env *env) { block *b = NULL; node *stmt = NULL; if(!env || !env->block_stack) return -1; if(!env->block_stack->stmt) return 1; for(;;) { b = env->block_stack; stmt = b->stmt->left; assert(stmt); switch(stmt->type) { case AST_VAR_DECL: ER(declare_variable(stmt, env)); break; case AST_ASSIGN: ER(assign_variable(stmt, env)); break; case AST_IF: ER(execute_if(stmt, env)); break; case AST_BLOCK: ER(push_block(env, stmt)); env->skip_advance = 1; break; case AST_CALL_A: ER(execute_call_A(stmt, env)); break; case AST_CALL_B: ER(execute_call_B(stmt, env)); break; case AST_BREAK: ER(execute_break(stmt, env)); break; case AST_CONTINUE: ER(execute_continue(stmt, env)); break; default: assert(0); /*is this an error? I could just skip unknown * statements...*/ break; } if(!env->block_stack) break; if(env->skip_advance) env->skip_advance = 0; else env->block_stack->stmt = env->block_stack->stmt->right; while(!env->block_stack->stmt) { pop_block(env); if(!env->block_stack) { return 0; } assert(env->block_stack->stmt); env->block_stack->stmt = env->block_stack->stmt->right; } } return 0; }
int main(int argc, char **argv) { unsigned int slot, dev, intx, link, cpu, max_cpus = HVM_MAX_VCPUS; /* Extract optional maximum-cpu specification from invocation name. */ sscanf(argv[0], "%*[^0-9]%u", &max_cpus); /* e.g., ./mk_dsdt15 */ /**** DSDT DefinitionBlock start ****/ /* (we append to existing DSDT definition block) */ indent_level++; /**** Processor start ****/ push_block("Scope", "\\_SB"); /* MADT checksum */ stmt("OperationRegion", "MSUM, SystemMemory, \\_SB.MSUA, 1"); push_block("Field", "MSUM, ByteAcc, NoLock, Preserve"); indent(); printf("MSU, 8\n"); pop_block(); /* Define processor objects and control methods. */ for ( cpu = 0; cpu < max_cpus; cpu++) { push_block("Processor", "PR%02X, %d, 0x0000b010, 0x06", cpu, cpu); stmt("Name", "_HID, \"ACPI0007\""); /* Name this processor's MADT LAPIC descriptor. */ stmt("OperationRegion", "MATR, SystemMemory, Add(\\_SB.MAPA, %d), 8", cpu*8); push_block("Field", "MATR, ByteAcc, NoLock, Preserve"); indent(); printf("MAT, 64\n"); pop_block(); push_block("Field", "MATR, ByteAcc, NoLock, Preserve"); indent(); printf("Offset(4),\n"); indent(); printf("FLG, 1\n"); pop_block(); push_block("Method", "_MAT, 0"); stmt("Return", "ToBuffer(MAT)"); pop_block(); push_block("Method", "_STA"); push_block("If", "FLG"); stmt("Return", "0xF"); pop_block(); push_block("Else", NULL); stmt("Return", "0x0"); pop_block(); pop_block(); push_block("Method", "_EJ0, 1, NotSerialized"); stmt("Sleep", "0xC8"); pop_block(); pop_block(); } /* Operation Region 'PRST': bitmask of online CPUs. */ stmt("OperationRegion", "PRST, SystemIO, 0xaf00, 32"); push_block("Field", "PRST, ByteAcc, NoLock, Preserve"); indent(); printf("PRS, %u\n", max_cpus); pop_block(); /* Control method 'PRSC': CPU hotplug GPE handler. */ push_block("Method", "PRSC, 0"); stmt("Store", "ToBuffer(PRS), Local0"); for ( cpu = 0; cpu < max_cpus; cpu++ ) { /* Read a byte at a time from the PRST online-CPU bitmask. */ if ( (cpu & 7) == 0 ) stmt("Store", "DerefOf(Index(Local0, %u)), Local1", cpu/8); else stmt("ShiftRight", "Local1, 1, Local1"); /* Extract current CPU's status: 0=offline; 1=online. */ stmt("And", "Local1, 1, Local2"); /* Check if status is up-to-date in the relevant MADT LAPIC entry... */ push_block("If", "LNotEqual(Local2, \\_SB.PR%02X.FLG)", cpu); /* ...If not, update it and the MADT checksum, and notify OSPM. */ stmt("Store", "Local2, \\_SB.PR%02X.FLG", cpu); push_block("If", "LEqual(Local2, 1)"); stmt("Notify", "PR%02X, 1", cpu); /* Notify: Device Check */ stmt("Subtract", "\\_SB.MSU, 1, \\_SB.MSU"); /* Adjust MADT csum */ pop_block(); push_block("Else", NULL); stmt("Notify", "PR%02X, 3", cpu); /* Notify: Eject Request */ stmt("Add", "\\_SB.MSU, 1, \\_SB.MSU"); /* Adjust MADT csum */ pop_block(); pop_block(); } stmt("Return", "One"); pop_block(); pop_block(); /* Define GPE control method '_L02'. */ push_block("Scope", "\\_GPE"); push_block("Method", "_L02"); stmt("Return", "\\_SB.PRSC()"); pop_block(); pop_block(); /**** Processor end ****/ /**** PCI0 start ****/ push_block("Scope", "\\_SB.PCI0"); /*** PCI-ISA link definitions ***/ /* BUFA: List of ISA IRQs available for linking to PCI INTx. */ stmt("Name", "BUFA, ResourceTemplate() { " "IRQ(Level, ActiveLow, Shared) { 5, 10, 11 } }"); /* BUFB: IRQ descriptor for returning from link-device _CRS methods. */ stmt("Name", "BUFB, Buffer() { " "0x23, 0x00, 0x00, 0x18, " /* IRQ descriptor */ "0x79, 0 }"); /* End tag, null checksum */ stmt("CreateWordField", "BUFB, 0x01, IRQV"); /* Create four PCI-ISA link devices: LNKA, LNKB, LNKC, LNKD. */ for ( link = 0; link < 4; link++ ) { push_block("Device", "LNK%c", 'A'+link); stmt("Name", "_HID, EISAID(\"PNP0C0F\")"); /* PCI interrupt link */ stmt("Name", "_UID, %u", link+1); push_block("Method", "_STA, 0"); push_block("If", "And(PIR%c, 0x80)", 'A'+link); stmt("Return", "0x09"); pop_block(); push_block("Else", NULL); stmt("Return", "0x0B"); pop_block(); pop_block(); push_block("Method", "_PRS"); stmt("Return", "BUFA"); pop_block(); push_block("Method", "_DIS"); stmt("Or", "PIR%c, 0x80, PIR%c", 'A'+link, 'A'+link); pop_block(); push_block("Method", "_CRS"); stmt("And", "PIR%c, 0x0f, Local0", 'A'+link); stmt("ShiftLeft", "0x1, Local0, IRQV"); stmt("Return", "BUFB"); pop_block(); push_block("Method", "_SRS, 1"); stmt("CreateWordField", "ARG0, 0x01, IRQ1"); stmt("FindSetRightBit", "IRQ1, Local0"); stmt("Decrement", "Local0"); stmt("Store", "Local0, PIR%c", 'A'+link); pop_block(); pop_block(); } /*** PCI interrupt routing definitions***/ /* _PRT: Method to return routing table. */ push_block("Method", "_PRT, 0"); push_block("If", "PICD"); stmt("Return", "PRTA"); pop_block(); stmt("Return", "PRTP"); pop_block(); /* PRTP: PIC routing table (via ISA links). */ printf("Name(PRTP, Package() {\n"); for ( dev = 1; dev < 32; dev++ ) for ( intx = 0; intx < 4; intx++ ) /* INTA-D */ printf("Package(){0x%04xffff, %u, \\_SB.PCI0.LNK%c, 0},\n", dev, intx, 'A'+((dev+intx)&3)); printf("})\n"); /* PRTA: APIC routing table (via non-legacy IOAPIC GSIs). */ printf("Name(PRTA, Package() {\n"); for ( dev = 1; dev < 32; dev++ ) for ( intx = 0; intx < 4; intx++ ) /* INTA-D */ printf("Package(){0x%04xffff, %u, 0, %u},\n", dev, intx, ((dev*4+dev/8+intx)&31)+16); printf("})\n"); /* * Each PCI hotplug slot needs at least two methods to handle * the ACPI event: * _EJ0: eject a device * _STA: return a device's status, e.g. enabled or removed * Other methods are optional: * _PS0/3: put them here for debug purpose * * Eject button would generate a general-purpose event, then the * control method for this event uses Notify() to inform OSPM which * action happened and on which device. * * Pls. refer "6.3 Device Insertion, Removal, and Status Objects" * in ACPI spec 3.0b for details. * * QEMU provides a simple hotplug controller with some I/O to handle * the hotplug action and status, which is beyond the ACPI scope. */ for ( slot = 0; slot < 0x100; slot++ ) { push_block("Device", "S%02X", slot); /* _ADR == dev:fn (16:16) */ stmt("Name", "_ADR, 0x%08x", ((slot & ~7) << 13) | (slot & 7)); /* _SUN == dev */ stmt("Name", "_SUN, 0x%08x", slot >> 3); push_block("Method", "_PS0, 0"); stmt("Store", "0x%02x, \\_GPE.DPT1", slot); stmt("Store", "0x80, \\_GPE.DPT2"); pop_block(); push_block("Method", "_PS3, 0"); stmt("Store", "0x%02x, \\_GPE.DPT1", slot); stmt("Store", "0x83, \\_GPE.DPT2"); pop_block(); push_block("Method", "_EJ0, 1"); stmt("Store", "0x%02x, \\_GPE.DPT1", slot); stmt("Store", "0x88, \\_GPE.DPT2"); stmt("Store", "0x%02x, \\_GPE.PH%02X", /* eject */ (slot & 1) ? 0x10 : 0x01, slot & ~1); pop_block(); push_block("Method", "_STA, 0"); stmt("Store", "0x%02x, \\_GPE.DPT1", slot); stmt("Store", "0x89, \\_GPE.DPT2"); if ( slot & 1 ) stmt("ShiftRight", "0x4, \\_GPE.PH%02X, Local1", slot & ~1); else stmt("And", "\\_GPE.PH%02X, 0x0f, Local1", slot & ~1); stmt("Return", "Local1"); /* IN status as the _STA */ pop_block(); pop_block(); } pop_block(); /**** PCI0 end ****/ /**** GPE start ****/ push_block("Scope", "\\_GPE"); stmt("OperationRegion", "PHP, SystemIO, 0x10c0, 0x82"); push_block("Field", "PHP, ByteAcc, NoLock, Preserve"); indent(); printf("PSTA, 8,\n"); /* hotplug controller event reg */ indent(); printf("PSTB, 8,\n"); /* hotplug controller slot reg */ for ( slot = 0; slot < 0x100; slot += 2 ) { indent(); /* Each hotplug control register manages a pair of pci functions. */ printf("PH%02X, 8,\n", slot); } pop_block(); stmt("OperationRegion", "DG1, SystemIO, 0xb044, 0x04"); push_block("Field", "DG1, ByteAcc, NoLock, Preserve"); indent(); printf("DPT1, 8, DPT2, 8\n"); pop_block(); push_block("Method", "_L03, 0, Serialized"); /* Detect slot and event (remove/add). */ stmt("Name", "SLT, 0x0"); stmt("Name", "EVT, 0x0"); stmt("Store", "PSTA, Local1"); stmt("And", "Local1, 0xf, EVT"); stmt("Store", "PSTB, Local1"); /* XXX: Store (PSTB, SLT) ? */ stmt("And", "Local1, 0xff, SLT"); /* Debug */ stmt("Store", "SLT, DPT1"); stmt("Store", "EVT, DPT2"); /* Decision tree */ decision_tree(0x00, 0x100, "SLT", pci_hotplug_notify); pop_block(); pop_block(); /**** GPE end ****/ pop_block(); /**** DSDT DefinitionBlock end ****/ return 0; }
void visit_tree(astree node, FILE* outfile){ switch(node->symbol){ case TOK_STRUCT: handlestruct(node, outfile); return; case TOK_BLOCK: push_block(gblock_stk); break; case TOK_FUNCTION: if (handlefunction(node, outfile)){ return; } else { push_block(gblock_stk); break; } case TOK_PROTOTYPE: handleprototype(node,outfile); break; case TOK_VARDECLINIT: handlevardecl(node,outfile); break; } astree temp; for(temp = node->first; temp != NULL; temp = temp->next){ visit_tree(temp, outfile); } switch(node->symbol){ case TOK_BLOCK: case TOK_FUNCTION: pop_idents(gident_tbl,gblock_stk->top->blocknr); pop_block(gblock_stk); break; case TOK_INTCON: node->attrs = ATTR_INT | ATTR_CONST; break; case TOK_CHARCON: node->attrs = ATTR_CHAR | ATTR_CONST; break; case TOK_STRINGCON: node->attrs = ATTR_STRING | ATTR_CONST; break; case TOK_FALSE: case TOK_TRUE: case TOK_BOOL: node->attrs = ATTR_BOOL | ATTR_CONST; node->blocknr = gblock_stk->top->blocknr; break; case TOK_ARRAY: node->attrs = ATTR_ARRAY | bitlookup(node->first->symbol); node->blocknr = gblock_stk->top->blocknr; break; case TOK_INT: node->attrs = ATTR_INT; node->blocknr = gblock_stk->top->blocknr; break; case TOK_CHAR: node->attrs = ATTR_CHAR; node->blocknr = gblock_stk->top->blocknr; break; case TOK_STRING: node->attrs = ATTR_STRING; node->blocknr = gblock_stk->top->blocknr; break; case TOK_TYPEID: node->attrs = ATTR_TYPEID; node->blocknr = gblock_stk->top->blocknr; break; case TOK_VOID: node->attrs = ATTR_VOID; node->blocknr = gblock_stk->top->blocknr; break; } }
void l_scan (SOURCE_FILE * sf) { int r = 1,in_sub = FALSE; int block_stack[STACK_SIZE],block_size = 0; list_init(&list_sub); list_init(&list_var); list_init(&list_array); while(r) { r = l_get_line(sf); pline = line; l_get_token (); // skip empty line if (token_type==TT_LINE_END) continue; // check command if (IS_KEYWORD(token_type)) { if (token_type==KEY_SUB) { USER_SUB * sub; if(in_sub) { merror_msg("sub procedure can not be nested"); } in_sub = TRUE; match_type(TT_ID); sub = (USER_SUB*)calloc(sizeof(USER_SUB),1); sub->name = s_strdup(token); sub->pos = sf->pos; list_push(&list_sub,sub); match_type(TT_LINE_END); push_block(B_SUB); continue; } else if (token_type==KEY_END) { if (block_size<=0 || block_top==B_REPEAT) merror_illegal_token(); match_type(TT_LINE_END); if(pop_block==B_SUB) { in_sub = FALSE; } continue; } else if(token_type==KEY_VAR) { while(1) { match_type(TT_ID); l_get_token(); if (token_type==TT_END) break; else if (token_type==TT_COM) continue; else merror_illegal_token(); } } if (!in_sub) merror_illegal_token(); if(token_type==KEY_IF) { match_exp(pline); match_type(TT_LINE_END); push_block(B_IF); } else if (token_type==KEY_ELSEIF) { if (block_size<=0 || block_top!=B_IF) merror_illegal_token(); match_exp(pline); match_type(TT_LINE_END); } else if (token_type==KEY_ELSE) { if (block_size<=0 || !(block_top==B_IF || block_top==B_CASE)) merror_illegal_token(); match_type(TT_LINE_END); } else if (token_type==KEY_WHILE) { match_exp(pline); match_type(TT_LINE_END); push_block(B_WHILE); } else if (token_type==KEY_FOR) { // 'for' ID '=' EXP 'to' EXP match_type(TT_ID); match_type(OPR_EQ); match_exp(pline); match_str("to"); match_exp(pline); l_get_token(); if (token_type!=TT_LINE_END) { if (!str_eq(token,"step")) merror_expect("step"); match_exp(pline); match_type(TT_LINE_END); } push_block(B_FOR); } else if (token_type==KEY_CASE) { match_type(TT_ID); match_type(TT_LINE_END); push_block(B_CASE); } else if (token_type==KEY_REPEAT) { match_type(TT_LINE_END); push_block(B_REPEAT); } else if (token_type==KEY_UNTIL) { if (block_size<=0 || block_top!=B_REPEAT) merror_illegal_token(); match_exp(pline); match_type(TT_LINE_END); pop_block; } else if (token_type==KEY_WHEN) { if (block_size<=0 || block_top!=B_CASE) merror_illegal_token(); match_exp(pline); match_type(TT_LINE_END); } else if (token_type==KEY_GOSUB) { match_type(TT_ID); match_type(TT_LINE_END); } else if (token_type==KEY_EXIT) { match_type(TT_LINE_END); } else if (token_type==KEY_BREAK) { match_type(TT_LINE_END); } else if (token_type==KEY_RETURN) { match_type(TT_LINE_END); } else if (token_type==KEY_DIM) { while(1) { match_type (TT_ID); match_type (TT_LBK); match_exp (pline); match_type (TT_RBK); l_get_token(); if (token_type==TT_COM) continue; else if (token_type==TT_LINE_END) break; else merror_illegal_token(); } } } else if (token_type==TT_ID) { if (!in_sub) merror_illegal_token(); if (str_eq(token,"print")) { while(1) { l_get_token(); if(token_type!=TT_STRING) { l_put_back(); match_exp(pline); } l_get_token(); if(token_type==TT_LINE_END) break; else if (token_type==TT_COM) continue; else merror_expect(","); } } else if (str_eq(token,"input")) { while(1) { match_type(TT_ID); l_get_token(); if(token_type==TT_LINE_END) break; else if (token_type==TT_COM) continue; else merror_expect(","); } } else { // match: [var][=][exp] l_get_token(); if (token_type==OPR_EQ) { match_exp(pline); match_type(TT_LINE_END); } else { if (token_type!=TT_LBK)merror_expect("("); match_exp(pline); match_type(TT_RBK); match_type(OPR_EQ); match_exp(pline); match_type(TT_LINE_END); } } } else merror_illegal_token (); } if (block_size>0) merror_msg("incompleted '%s' block!",BLOCK_NAME[block_top]); }
// Convert a node_block list to HTML. Returns 0 on success, and sets result. static void blocks_to_html(strbuf *html, node_block *b) { struct ListData *data; render_stack* rstack = NULL; bool visit_children = false; bool tight = false; while(b != NULL) { visit_children = false; switch(b->tag) { case BLOCK_DOCUMENT: rstack = push_block(rstack, b->next, "", false, false); visit_children = true; break; case BLOCK_PARAGRAPH: if (tight) { inlines_to_html(html, b->inline_content); } else { cr(html); strbuf_puts(html, "<p>"); inlines_to_html(html, b->inline_content); strbuf_puts(html, "</p>\n"); } break; case BLOCK_BQUOTE: cr(html); strbuf_puts(html, "<blockquote>\n"); rstack = push_block(rstack, b->next, "</blockquote>\n", tight, false); tight = false; visit_children = true; break; case BLOCK_LIST_ITEM: cr(html); strbuf_puts(html, "<li>"); rstack = push_block(rstack, b->next, "</li>\n", tight, true); visit_children = true; break; case BLOCK_LIST: // make sure a list starts at the beginning of the line: cr(html); data = &(b->as.list); if (data->start > 1) { strbuf_printf(html, "<%s start=\"%d\">\n", data->list_type == bullet ? "ul" : "ol", data->start); } else { strbuf_puts(html, data->list_type == bullet ? "<ul>\n" : "<ol>\n"); } rstack = push_block(rstack, b->next, data->list_type == bullet ? "\n</ul>\n" : "\n</ol>\n", tight, false); tight = data->tight; visit_children = true; break; case BLOCK_ATX_HEADER: case BLOCK_SETEXT_HEADER: cr(html); strbuf_printf(html, "<h%d>", b->as.header.level); inlines_to_html(html, b->inline_content); strbuf_printf(html, "</h%d>\n", b->as.header.level); break; case BLOCK_INDENTED_CODE: case BLOCK_FENCED_CODE: cr(html); strbuf_puts(html, "<pre><code"); if (b->tag == BLOCK_FENCED_CODE) { strbuf *info = &b->as.code.info; if (strbuf_len(info) > 0) { int first_tag = strbuf_strchr(info, ' ', 0); if (first_tag < 0) first_tag = strbuf_len(info); strbuf_puts(html, " class=\"language-"); escape_html(html, info->ptr, first_tag); strbuf_putc(html, '"'); } } strbuf_putc(html, '>'); escape_html(html, b->string_content.ptr, b->string_content.size); strbuf_puts(html, "</code></pre>\n"); break; case BLOCK_HTML: strbuf_put(html, b->string_content.ptr, b->string_content.size); break; case BLOCK_HRULE: strbuf_puts(html, "<hr />\n"); break; case BLOCK_REFERENCE_DEF: break; default: assert(false); } if (visit_children) { b = b->children; } else { b = b->next; } while (b == NULL && rstack != NULL) { strbuf_puts(html, rstack->literal); if (rstack->trim) { strbuf_rtrim(html); } tight = rstack->tight; b = rstack->next_sibling.block; rstack = pop_render_stack(rstack); } } free_render_stack(rstack); }