struct nvhost_job *nvhost_job_alloc(struct nvhost_channel *ch,
		struct nvhost_hwctx *hwctx,
		struct nvhost_submit_hdr_ext *hdr,
		struct nvmap_client *nvmap,
		int priority,
		int clientid)
{
	struct nvhost_job *job = NULL;
	int num_cmdbufs = hdr ? hdr->num_cmdbufs : 0;
	int err = 0;

	job = vzalloc(job_size(hdr));
	if (!job)
		goto error;

	kref_init(&job->ref);
	job->ch = ch;
	job->hwctx = hwctx;
	if (hwctx)
		hwctx->h->get(hwctx);
	job->nvmap = nvmap ? nvmap_client_get(nvmap) : NULL;

	err = alloc_gathers(job, num_cmdbufs);
	if (err)
		goto error;

	init_fields(job, hdr, priority, clientid);

	return job;

error:
	if (job)
		nvhost_job_put(job);
	return NULL;
}
예제 #2
0
파일: stubs.c 프로젝트: ybouret/iics
void
ui_raz_clicked(void *cbdata)
{
    init_fields();
    VisItTimeStepChanged();
    VisItUpdatePlots();
}
예제 #3
0
struct nvhost_job *nvhost_job_alloc(struct nvhost_channel *ch,
		struct nvhost_hwctx *hwctx,
		struct nvhost_submit_hdr_ext *hdr,
		struct mem_mgr *memmgr,
		int priority,
		int clientid)
{
	struct nvhost_job *job = NULL;

	job = vzalloc(job_size(hdr));
	if (!job)
		goto error;

	kref_init(&job->ref);
	job->ch = ch;
	job->hwctx = hwctx;
	if (hwctx)
		hwctx->h->get(hwctx);
	job->memmgr = memmgr ? mem_op().get_mgr(memmgr) : NULL;

	init_fields(job, hdr, priority, clientid);

	return job;

error:
	if (job)
		nvhost_job_put(job);
	return NULL;
}
예제 #4
0
파일: klient.c 프로젝트: tmachows/statki
void game_function(){
	
/*	request_t response;
	strcpy(response.name,client_name);
	response.lobby = GAME;
	response.action = START_GAME;	
	pthread_mutex_lock(&mutex);
	if(send(socket_fd, (void*) &response, sizeof(response), 0) == -1)
			error("send() redy");
	pthread_mutex_unlock(&mutex);
*/	
	
	pthread_mutex_lock(&game_mutex);
	while(wait==0)
		pthread_cond_wait(&waiting_cond, &game_mutex);
	pthread_mutex_unlock(&game_mutex);
	init_fields();
	char bufor[2];
	
	pthread_mutex_lock(&game_mutex);
	printf("Oczekiwanie na gotowosc przeciwnika..\n");
	while(enemy_ready==0)
		pthread_cond_wait(&waiting_cond, &game_mutex);
	pthread_mutex_unlock(&game_mutex);
	printf("Przeciwnik gotowy - gra rozpoczyna sie!\n");
	int x,y;
	while(!my_turn)
		pthread_cond_wait(&waiting_cond, &game_mutex);
	while(game_state==1&&thread_is_alive==1){
			printf("Podaj pole do zaatakowania: ");
			do{					
				scanf("%s",bufor);	
			}while(parse_field(bufor,&x,&y)==0);
			request_t response;
			strcpy(response.name,client_name);
			response.lobby = GAME;
			response.action = FIELD;
			response.field.x=x;
			response.field.y=y;	
			response.opponent_socket=opponent_socket;
			pthread_mutex_lock(&mutex);
			if(send(socket_fd, (void*) &response, sizeof(response), 0) == -1)
					error("send() game");
			pthread_mutex_unlock(&mutex);
			
		pthread_mutex_lock(&game_mutex);
		do {
			pthread_cond_wait(&waiting_cond, &game_mutex);
		} while(!my_turn);
		pthread_mutex_unlock(&game_mutex);
		if(game_state==1)
			game_state=status();
	}
	printf("Koniec gry\n");

	return ;
}
예제 #5
0
파일: dialog.cpp 프로젝트: aquileia/wesnoth
bool tdialog::show(CVideo& video, const unsigned auto_close_time)
{
	if(video.faked() && !show_even_without_video_) {
		if(!allow_plugin_skip_) {
			return false;
		}

		plugins_manager* pm = plugins_manager::get();
		if (pm && pm->any_running())
		{
			plugins_context pc("Dialog");
			pc.set_callback("skip_dialog", [this](config) { retval_ = twindow::OK; }, false);
			pc.set_callback("quit", [](config) {}, false);
			pc.play_slice();
		}

		return false;
	}

	std::unique_ptr<twindow> window(build_window(video));
	assert(window.get());

	post_build(*window);

	window->set_owner(this);

	init_fields(*window);

	pre_show(*window);

	retval_ = window->show(restore_, auto_close_time);

	/*
	 * It can happen that when two clicks follow each other fast that the event
	 * handling code in events.cpp generates a DOUBLE_CLICK_EVENT. For some
	 * reason it can happen that this event gets pushed in the queue when the
	 * window is shown, but processed after the window is closed. This causes
	 * the next window to get this pending event.
	 *
	 * This caused a bug where double clicking in the campaign selection dialog
	 * directly selected a difficulty level and started the campaign. In order
	 * to avoid that problem, filter all pending DOUBLE_CLICK_EVENT events after
	 * the window is closed.
	 */
	SDL_FlushEvent(DOUBLE_CLICK_EVENT);

	finalize_fields(*window, (retval_ == twindow::OK || always_save_fields_));

	post_show(*window);

	// post_show may have updated the windoe retval. Update it here.
	retval_ = window->get_retval();

	return retval_ == twindow::OK;
}
예제 #6
0
파일: stubs.c 프로젝트: ybouret/iics
/* Called to handle case 3 from VisItDetectInput where we have console
 * input that needs to be processed in order to accomplish an action.
 */
void
ProcessConsoleCommand(simulation_data *sim)
{
    /* Read A Command */
    char cmd[1000];
    
    
    VisItUI_valueChanged("Mu", ui_Mu_changed, &sim);
    VisItUI_valueChanged("A", ui_A_changed, &sim);
    
    if (sim->par_rank == 0)
    {
        int iseof = (fgets(cmd, 1000, stdin) == NULL);
        if (iseof)
        {
            sprintf(cmd, "quit");
            printf("quit\n");
        }
        
        if (strlen(cmd)>0 && cmd[strlen(cmd)-1] == '\n')
            cmd[strlen(cmd)-1] = '\0';
    }
    
    /* Broadcast the command to all processors. */
    MPI_Bcast(cmd, 1000, MPI_CHAR, 0, MPI_COMM_WORLD);
    
    if(strcmp(cmd, "quit") == 0)
        sim->done = 1;
    else if(strcmp(cmd, "halt") == 0)
        sim->runMode = SIM_STOPPED;
    else if(strcmp(cmd, "step") == 0)
        simulate_one_timestep(sim);
    else if(strcmp(cmd, "run") == 0)
        sim->runMode = SIM_RUNNING;
    else if(strcmp(cmd, "raz") == 0)
        init_fields();
    else if(strcmp(cmd, "update") == 0)
    {
        VisItTimeStepChanged();
        VisItUpdatePlots();
    }
    else if(strcmp(cmd, "saveon") == 0)
        sim->savingFiles = 1;
    else if(strcmp(cmd, "saveoff") == 0)
        sim->savingFiles = 0;
    else if(strcmp(cmd, "addplot") == 0)
    {
        VisItExecuteCommand("AddPlot(\"Pseudocolor\", \"zonal\")\n");
        VisItExecuteCommand("DrawPlots()\n");
    }
}
예제 #7
0
파일: stubs.c 프로젝트: ybouret/iics
/**************************************************************************
 *Callback function for control commands, which are the buttons in the
 * GUI's Simulation window. This type of command is handled automatically
 * provided that you have registered a command callback such as this.
 **************************************************************************/
void ControlCommandCallback(const char *cmd, const char *args, void *cbdata)
{
    simulation_data *sim = (simulation_data *)cbdata;
    
    if(strcmp(cmd, "halt") == 0)
        sim->runMode = SIM_STOPPED;
    else if(strcmp(cmd, "step") == 0)
        simulate_one_timestep(sim);
    else if(strcmp(cmd, "run") == 0)
        sim->runMode = SIM_RUNNING;
    else if(strcmp(cmd, "raz") == 0)
    {
        init_fields();
        VisItUpdatePlots();
    }
    else if(strcmp(cmd, "addplot") == 0)
    {
        VisItExecuteCommand("AddPlot(\"Pseudocolor\", \"zonal\")\n");
        VisItExecuteCommand("DrawPlots()\n");
    }
}
struct nvhost_job *nvhost_job_realloc(
		struct nvhost_job *oldjob,
		struct nvhost_hwctx *hwctx,
		struct nvhost_submit_hdr_ext *hdr,
		struct nvmap_client *nvmap,
		int priority, int clientid)
{
	struct nvhost_job *newjob = NULL;
	int num_cmdbufs = hdr ? hdr->num_cmdbufs : 0;
	int err = 0;

	newjob = vzalloc(job_size(hdr));
	if (!newjob)
		goto error;
	kref_init(&newjob->ref);
	newjob->ch = oldjob->ch;
	newjob->hwctx = hwctx;
	if (hwctx)
		newjob->hwctx->h->get(newjob->hwctx);
	newjob->timeout = oldjob->timeout;
	newjob->nvmap = nvmap ? nvmap_client_get(nvmap) : NULL;

	err = realloc_gathers(oldjob, newjob, num_cmdbufs);
	if (err)
		goto error;

	nvhost_job_put(oldjob);

	init_fields(newjob, hdr, priority, clientid);

	return newjob;

error:
	if (newjob)
		nvhost_job_put(newjob);
	if (oldjob)
		nvhost_job_put(oldjob);
	return NULL;
}
예제 #9
0
파일: fdisk-list.c 프로젝트: gg0/util-linux
void list_disklabel(struct fdisk_context *cxt)
{
	struct fdisk_table *tb = NULL;
	struct fdisk_partition *pa = NULL;
	struct fdisk_iter *itr = NULL;
	struct fdisk_label *lb;
	struct libscols_table *out = NULL;
	const char *bold = NULL;
	int *ids = NULL;		/* IDs of fdisk_fields */
	size_t	nids = 0, i;
	int post = 0;

	/* print label specific stuff by libfdisk FDISK_ASK_INFO API */
	fdisk_list_disklabel(cxt);

	/* get partitions and generate output */
	if (fdisk_get_partitions(cxt, &tb) || fdisk_table_get_nents(tb) <= 0)
		goto done;

	ids = init_fields(cxt, NULL, &nids);
	if (!ids)
		goto done;

	itr = fdisk_new_iter(FDISK_ITER_FORWARD);
	if (!itr) {
		fdisk_warn(cxt, _("faild to allocate iterator"));
		goto done;
	}

	out = scols_new_table();
	if (!out) {
		fdisk_warn(cxt, _("faild to allocate output table"));
		goto done;
	}

	if (colors_wanted()) {
		scols_table_enable_colors(out, 1);
		bold = color_scheme_get_sequence("header", UL_COLOR_BOLD);
	}

	lb = fdisk_get_label(cxt, NULL);
	assert(lb);

	/* define output table columns */
	for (i = 0; i < nids; i++) {
		int fl = 0;
		struct libscols_column *co;
		const struct fdisk_field *field =
				fdisk_label_get_field(lb, ids[i]);
		if (!field)
			continue;
		if (fdisk_field_is_number(field))
			fl |= SCOLS_FL_RIGHT;
		if (fdisk_field_get_id(field) == FDISK_FIELD_TYPE)
			fl |= SCOLS_FL_TRUNC;

		co = scols_table_new_column(out,
				fdisk_field_get_name(field),
				fdisk_field_get_width(field), fl);
		if (!co)
			goto done;

		/* set colum header color */
		if (bold)
			scols_cell_set_color(scols_column_get_header(co), bold);
	}

	/* fill-in output table */
	while (fdisk_table_next_partition(tb, itr, &pa) == 0) {
		struct libscols_line *ln = scols_table_new_line(out, NULL);

		if (!ln) {
			fdisk_warn(cxt, _("faild to allocate output line"));
			goto done;
		}

		for (i = 0; i < nids; i++) {
			char *data = NULL;

			if (fdisk_partition_to_string(pa, cxt, ids[i], &data))
				continue;
			scols_line_refer_data(ln, i, data);
		}
	}

	/* print */
	if (!scols_table_is_empty(out)) {
		fputc('\n', stdout);
		scols_print_table(out);
	}

	/* print warnings */
	fdisk_reset_iter(itr, FDISK_ITER_FORWARD);
	while (itr && fdisk_table_next_partition(tb, itr, &pa) == 0) {
		if (!fdisk_partition_has_start(pa))
			continue;
		if (!fdisk_lba_is_phy_aligned(cxt, fdisk_partition_get_start(pa))) {
			if (!post)
				fputc('\n', stdout);
			fdisk_warnx(cxt, _("Partition %zu does not start on physical sector boundary."),
					  fdisk_partition_get_partno(pa) + 1);
			post++;
		}
	}

	if (fdisk_table_wrong_order(tb)) {
		if (!post)
			fputc('\n', stdout);
		fdisk_info(cxt, _("Partition table entries are not in disk order."));
	}
done:
	scols_unref_table(out);
	fdisk_unref_table(tb);
	fdisk_free_iter(itr);
}
// ---------------------------------------------------------------------------
// Std call
// ------------
void bXMapNetClean::process_network(bool log){
_bTrace_("bXMapNetClean::process_network(bool)",true);
bGenericType*	tp;
bool			badf=false;
char			name[__MESSAGE_STRING_LENGTH_MAX__];
it_prm			iter;
int				fields[_gapp->typesMgr()->count()];
nc_prm			prm;
bArray			nodes(sizeof(bGenericGeoElement*));
bArray			edges(sizeof(bGenericGeoElement*));

    b_message_string(kXMapNetCleanControlField,name,getbundle(),0);
// Liste des itérateurs
    iter.it=0;
    for(long i=1;i<=_nodes.count();i++){
        _nodes.get(i,&tp);
        if(tp){
            iter.tp=tp;
            iter.it=tp->iterator();
            iter.field=tp->fields()->get_index(name);
            _nitr.add(&iter);
            if(!iter.field&&_act_prm.check_nodes){
                badf=true;
            }
        }
    }
    for(long i=1;i<=_edges.count();i++){
        _edges.get(i,&tp);
        if(tp){
            iter.tp=tp;
            iter.it=tp->iterator();
            iter.field=tp->fields()->get_index(name);
            _eitr.add(&iter);
            if(!iter.field&&_act_prm.check_edges){
                badf=true;
            }
        }
    }
    
// Champs controle
    for(long i=1;i<=_gapp->typesMgr()->count();i++){
        fields[i-1]=0;
    }
    
// Listes d'objets
    prm.arr=&nodes;
    for(long i=1;i<=_nitr.count();i++){
        _nitr.get(i,&iter);
        iter.it->iterate(&prm,all_objects);
    }
    prm.arr=&edges;
    for(long i=1;i<=_eitr.count();i++){
        _eitr.get(i,&iter);
        iter.it->iterate(&prm,all_objects);
    }
    
    if(log){
bEventLog	log(_gapp,this);
        if(badf){
            b_message_string(kXMapNetCleanAskAddControlField,name,getbundle(),0);
bAlertWarningYes	alrt(name,"",_silent);
            if(!alrt.result()){
                _act_prm.check_edges=false;
                _act_prm.check_nodes=false;
            }
        }
        init_fields(&_act_prm);
        for(long i=1;i<=_nitr.count();i++){
            _nitr.get(i,&iter);
            fields[iter.tp->index()-1]=iter.field;
        }
        for(long i=1;i<=_eitr.count();i++){
            _eitr.get(i,&iter);
            fields[iter.tp->index()-1]=iter.field;
        }
        process_network(&_act_prm,fields,nodes,edges);
        log.close();
    }
    else{
        if(badf){
            b_message_string(kXMapNetCleanAskAddControlField,name,getbundle(),0);
bAlertWarningYes	alrt(name,"",_silent);
            if(!alrt.result()){
                _te_("coin coin");
                _act_prm.check_edges=false;
                _act_prm.check_nodes=false;
            }
        }
        init_fields(&_act_prm);
        for(long i=1;i<=_nitr.count();i++){
            _nitr.get(i,&iter);
            fields[iter.tp->index()-1]=iter.field;
        }
        for(long i=1;i<=_eitr.count();i++){
            _eitr.get(i,&iter);
            fields[iter.tp->index()-1]=iter.field;
        }
        process_network(&_act_prm,fields,nodes,edges);
    }
    _nitr.reset();
    _eitr.reset();
}
예제 #11
0
bool mysqld_help(THD *thd, const char *mask)
{
  Protocol *protocol= thd->protocol;
  SQL_SELECT *select;
  st_find_field used_fields[array_elements(init_used_fields)];
  TABLE_LIST *leaves= 0;
  TABLE_LIST tables[4];
  List<String> topics_list, categories_list, subcategories_list;
  String name, description, example;
  int count_topics, count_categories, error;
  uint mlen= strlen(mask);
  size_t i;
  MEM_ROOT *mem_root= thd->mem_root;
  DBUG_ENTER("mysqld_help");

  bzero((char *)((uchar*)tables),sizeof(tables));
  tables[0].alias= tables[0].table_name= (char*) "help_topic";
  tables[0].lock_type= TL_READ;
  tables[0].next_global= tables[0].next_local= 
    tables[0].next_name_resolution_table= &tables[1];
  tables[1].alias= tables[1].table_name= (char*) "help_category";
  tables[1].lock_type= TL_READ;
  tables[1].next_global= tables[1].next_local= 
    tables[1].next_name_resolution_table= &tables[2];
  tables[2].alias= tables[2].table_name= (char*) "help_relation";
  tables[2].lock_type= TL_READ;
  tables[2].next_global= tables[2].next_local= 
    tables[2].next_name_resolution_table= &tables[3];
  tables[3].alias= tables[3].table_name= (char*) "help_keyword";
  tables[3].lock_type= TL_READ;
  tables[0].db= tables[1].db= tables[2].db= tables[3].db= (char*) "mysql";

  Open_tables_state open_tables_state_backup;
  if (open_system_tables_for_read(thd, tables, &open_tables_state_backup))
    goto error2;

  /*
    Init tables and fields to be usable from items
    tables do not contain VIEWs => we can pass 0 as conds
  */
  thd->lex->select_lex.context.table_list=
    thd->lex->select_lex.context.first_name_resolution_table= &tables[0];
  if (setup_tables(thd, &thd->lex->select_lex.context,
                   &thd->lex->select_lex.top_join_list,
                   tables, &leaves, FALSE))
    goto error;
  memcpy((char*) used_fields, (char*) init_used_fields, sizeof(used_fields));
  if (init_fields(thd, tables, used_fields, array_elements(used_fields)))
    goto error;
  for (i=0; i<sizeof(tables)/sizeof(TABLE_LIST); i++)
    tables[i].table->file->init_table_handle_for_HANDLER();

  if (!(select=
	prepare_select_for_name(thd,mask,mlen,tables,tables[0].table,
				used_fields[help_topic_name].field,&error)))
    goto error;

  count_topics= search_topics(thd,tables[0].table,used_fields,
			      select,&topics_list,
			      &name, &description, &example);
  delete select;

  if (count_topics == 0)
  {
    int UNINIT_VAR(key_id);
    if (!(select=
          prepare_select_for_name(thd,mask,mlen,tables,tables[3].table,
                                  used_fields[help_keyword_name].field,
                                  &error)))
      goto error;

    count_topics= search_keyword(thd,tables[3].table, used_fields, select,
                                 &key_id);
    delete select;
    count_topics= (count_topics != 1) ? 0 :
                  get_topics_for_keyword(thd,tables[0].table,tables[2].table,
                                         used_fields,key_id,&topics_list,&name,
                                         &description,&example);
  }

  if (count_topics == 0)
  {
    int16 category_id;
    Field *cat_cat_id= used_fields[help_category_parent_category_id].field;
    if (!(select=
          prepare_select_for_name(thd,mask,mlen,tables,tables[1].table,
                                  used_fields[help_category_name].field,
                                  &error)))
      goto error;

    count_categories= search_categories(thd, tables[1].table, used_fields,
					select,
					&categories_list,&category_id);
    delete select;
    if (!count_categories)
    {
      if (send_header_2(protocol,FALSE))
	goto error;
    }
    else if (count_categories > 1)
    {
      if (send_header_2(protocol,FALSE) ||
	  send_variant_2_list(mem_root,protocol,&categories_list,"Y",0))
	goto error;
    }
    else
    {
      Field *topic_cat_id= used_fields[help_topic_help_category_id].field;
      Item *cond_topic_by_cat=
	new Item_func_equal(new Item_field(topic_cat_id),
			    new Item_int((int32)category_id));
      Item *cond_cat_by_cat=
	new Item_func_equal(new Item_field(cat_cat_id),
			    new Item_int((int32)category_id));
      if (!(select= prepare_simple_select(thd, cond_topic_by_cat,
                                          tables[0].table, &error)))
        goto error;
      get_all_items_for_category(thd,tables[0].table,
				 used_fields[help_topic_name].field,
				 select,&topics_list);
      delete select;
      if (!(select= prepare_simple_select(thd, cond_cat_by_cat,
                                          tables[1].table, &error)))
        goto error;
      get_all_items_for_category(thd,tables[1].table,
				 used_fields[help_category_name].field,
				 select,&subcategories_list);
      delete select;
      String *cat= categories_list.head();
      if (send_header_2(protocol, TRUE) ||
	  send_variant_2_list(mem_root,protocol,&topics_list,       "N",cat) ||
	  send_variant_2_list(mem_root,protocol,&subcategories_list,"Y",cat))
	goto error;
    }
  }
  else if (count_topics == 1)
  {
    if (send_answer_1(protocol,&name,&description,&example))
      goto error;
  }
  else
  {
    /* First send header and functions */
    if (send_header_2(protocol, FALSE) ||
	send_variant_2_list(mem_root,protocol, &topics_list, "N", 0))
      goto error;
    if (!(select=
          prepare_select_for_name(thd,mask,mlen,tables,tables[1].table,
                                  used_fields[help_category_name].field,&error)))
      goto error;
    search_categories(thd, tables[1].table, used_fields,
		      select,&categories_list, 0);
    delete select;
    /* Then send categories */
    if (send_variant_2_list(mem_root,protocol, &categories_list, "Y", 0))
      goto error;
  }
  my_eof(thd);

  close_system_tables(thd, &open_tables_state_backup);
  DBUG_RETURN(FALSE);

error:
  close_system_tables(thd, &open_tables_state_backup);

error2:
  DBUG_RETURN(TRUE);
}
예제 #12
0
파일: csv.cpp 프로젝트: nsan-jp/libcsv
csv::csv(csv_datasource* ds) {
  init_fields();
  this->ds = ds;
}
예제 #13
0
파일: csv.cpp 프로젝트: nsan-jp/libcsv
csv::csv() {
  init_fields();
  this->ds = NULL;
  eod = true;
  _lines = 0;
}
예제 #14
0
파일: main.c 프로젝트: gvlx/gawk
int
main(int argc, char **argv)
{
	/*
	 * The + on the front tells GNU getopt not to rearrange argv.
	 */
	const char *optlist = "+F:f:v:W;m:bcCd::D::e:E:gh:i:l:L:nNo::Op::MPrStVY";
	bool stopped_early = false;
	int old_optind;
	int i;
	int c;
	char *scan, *src;
	char *extra_stack;
	int have_srcfile = 0;
	SRCFILE *s;

	/* do these checks early */
	if (getenv("TIDYMEM") != NULL)
		do_flags |= DO_TIDY_MEM;

#ifdef HAVE_MCHECK_H
#ifdef HAVE_MTRACE
	if (do_tidy_mem)
		mtrace();
#endif /* HAVE_MTRACE */
#endif /* HAVE_MCHECK_H */

#if defined(LC_CTYPE)
	setlocale(LC_CTYPE, "");
#endif
#if defined(LC_COLLATE)
	setlocale(LC_COLLATE, "");
#endif
#if defined(LC_MESSAGES)
	setlocale(LC_MESSAGES, "");
#endif
#if defined(LC_NUMERIC) && defined(HAVE_LOCALE_H)
	/*
	 * Force the issue here.  According to POSIX 2001, decimal
	 * point is used for parsing source code and for command-line
	 * assignments and the locale value for processing input,
	 * number to string conversion, and printing output.
	 *
	 * 10/2005 --- see below also; we now only use the locale's
	 * decimal point if do_posix in effect.
	 *
	 * 9/2007:
	 * This is a mess. We need to get the locale's numeric info for
	 * the thousands separator for the %'d flag.
	 */
	setlocale(LC_NUMERIC, "");
	init_locale(& loc);
	setlocale(LC_NUMERIC, "C");
#endif
#if defined(LC_TIME)
	setlocale(LC_TIME, "");
#endif

#if MBS_SUPPORT
	/*
	 * In glibc, MB_CUR_MAX is actually a function.  This value is
	 * tested *a lot* in many speed-critical places in gawk. Caching
	 * this value once makes a speed difference.
	 */
	gawk_mb_cur_max = MB_CUR_MAX;
	/* Without MBS_SUPPORT, gawk_mb_cur_max is 1. */

	/* init the cache for checking bytes if they're characters */
	init_btowc_cache();
#endif

	(void) bindtextdomain(PACKAGE, LOCALEDIR);
	(void) textdomain(PACKAGE);

	(void) signal(SIGFPE, catchsig);
#ifdef SIGBUS
	(void) signal(SIGBUS, catchsig);
#endif

	(void) sigsegv_install_handler(catchsegv);
#define STACK_SIZE (16*1024)
	emalloc(extra_stack, char *, STACK_SIZE, "main");
	(void) stackoverflow_install_handler(catchstackoverflow, extra_stack, STACK_SIZE);
#undef STACK_SIZE

	myname = gawk_name(argv[0]);
	os_arg_fixup(&argc, &argv); /* emulate redirection, expand wildcards */

	if (argc < 2)
		usage(EXIT_FAILURE, stderr);

	/* initialize the null string */
	Nnull_string = make_string("", 0);

	/* Robustness: check that file descriptors 0, 1, 2 are open */
	init_fds();

	/* init array handling. */
	array_init();

	/* init the symbol tables */
	init_symbol_table();

	output_fp = stdout;

	/* we do error messages ourselves on invalid options */
	opterr = false;

	/* copy argv before getopt gets to it; used to restart the debugger */  
	save_argv(argc, argv);

	/* initialize global (main) execution context */
	push_context(new_context());

	/* option processing. ready, set, go! */
	for (optopt = 0, old_optind = 1;
	     (c = getopt_long(argc, argv, optlist, optab, NULL)) != EOF;
	     optopt = 0, old_optind = optind) {
		if (do_posix)
			opterr = true;

		switch (c) {
		case 'F':
			add_preassign(PRE_ASSIGN_FS, optarg);
			break;

		case 'E':
			disallow_var_assigns = true;
			/* fall through */
		case 'f':
			/*
			 * Allow multiple -f options.
			 * This makes function libraries real easy.
			 * Most of the magic is in the scanner.
			 *
			 * The following is to allow for whitespace at the end
			 * of a #! /bin/gawk line in an executable file
			 */
			scan = optarg;
			if (argv[optind-1] != optarg)
				while (isspace((unsigned char) *scan))
					scan++;
			src = (*scan == '\0' ? argv[optind++] : optarg);
			(void) add_srcfile((src && src[0] == '-' && src[1] == '\0') ?
					SRC_STDIN : SRC_FILE,
					src, srcfiles, NULL, NULL);

			break;

		case 'v':
			add_preassign(PRE_ASSIGN, optarg);
			break;

		case 'm':
			/*
			 * BWK awk extension.
			 *	-mf nnn		set # fields, gawk ignores
			 *	-mr nnn		set record length, ditto
			 *
			 * As of at least 10/2007, BWK awk also ignores it.
			 */
			if (do_lint)
				lintwarn(_("`-m[fr]' option irrelevant in gawk"));
			if (optarg[0] != 'r' && optarg[0] != 'f')
				warning(_("-m option usage: `-m[fr] nnn'"));
			break;

		case 'b':
			do_binary = true;
			break;

		case 'c':
			do_flags |= DO_TRADITIONAL;
			break;

		case 'C':
			copyleft();
			break;

		case 'd':
			do_flags |= DO_DUMP_VARS;
			if (optarg != NULL && optarg[0] != '\0')
				varfile = optarg;
			break;

		case 'D':
			do_flags |= DO_DEBUG;
			if (optarg != NULL && optarg[0] != '\0')
				command_file = optarg;
			break;

		case 'e':
			if (optarg[0] == '\0')
				warning(_("empty argument to `-e/--source' ignored"));
			else
				(void) add_srcfile(SRC_CMDLINE, optarg, srcfiles, NULL, NULL);
			break;

		case 'g':
			do_flags |= DO_INTL;
			break;

		case 'h':
			/* write usage to stdout, per GNU coding stds */
			usage(EXIT_SUCCESS, stdout);
			break;

		case 'i':
			(void) add_srcfile(SRC_INC, optarg, srcfiles, NULL, NULL);
			break;

		case 'l':
			(void) add_srcfile(SRC_EXTLIB, optarg, srcfiles, NULL, NULL);
			break;

		case 'L':
#ifndef NO_LINT
			do_flags |= DO_LINT_ALL;
			if (optarg != NULL) {
				if (strcmp(optarg, "fatal") == 0)
					lintfunc = r_fatal;
				else if (strcmp(optarg, "invalid") == 0) {
					do_flags &= ~DO_LINT_ALL;
					do_flags |= DO_LINT_INVALID;
				}
			}
			break;

		case 't':
			do_flags |= DO_LINT_OLD;
			break;
#else
		case 'L':
		case 't':
			break;
#endif

		case 'n':
			do_flags |= DO_NON_DEC_DATA;
			break;

		case 'N':
			use_lc_numeric = true;
			break;

		case 'O':
			do_optimize++;
			break;

		case 'p':
			do_flags |= DO_PROFILE;
			/* fall through */
		case 'o':
			do_flags |= DO_PRETTY_PRINT;
			if (optarg != NULL)
				set_prof_file(optarg);
			else
				set_prof_file(DEFAULT_PROFILE);
			break;

		case 'M':
#ifdef HAVE_MPFR
			do_flags |= DO_MPFR;
#endif
			break;

		case 'P':
			do_flags |= DO_POSIX;
			break;

		case 'r':
			do_flags |= DO_INTERVALS;
 			break;
 
		case 'S':
			do_flags |= DO_SANDBOX;
  			break;

		case 'V':
			do_version = true;
			break;

		case 'W':       /* gawk specific options - now in getopt_long */
			fprintf(stderr, _("%s: option `-W %s' unrecognized, ignored\n"),
				argv[0], optarg);
			break;

		case 0:
			/*
			 * getopt_long found an option that sets a variable
			 * instead of returning a letter. Do nothing, just
			 * cycle around for the next one.
			 */
			break;

		case 'Y':
#if defined(YYDEBUG) || defined(GAWKDEBUG)
			if (c == 'Y') {
				yydebug = 2;
				break;
			}
#endif
			/* if not debugging, fall through */
		case '?':
		default:
			/*
			 * If not posix, an unrecognized option stops argument
			 * processing so that it can go into ARGV for the awk
			 * program to see. This makes use of ``#! /bin/gawk -f''
			 * easier.
			 *
			 * However, it's never simple. If optopt is set,
			 * an option that requires an argument didn't get the
			 * argument. We care because if opterr is 0, then
			 * getopt_long won't print the error message for us.
			 */
			if (! do_posix
			    && (optopt == '\0' || strchr(optlist, optopt) == NULL)) {
				/*
				 * can't just do optind--. In case of an
				 * option with >= 2 letters, getopt_long
				 * won't have incremented optind.
				 */
				optind = old_optind;
				stopped_early = true;
				goto out;
			} else if (optopt != '\0') {
				/* Use POSIX required message format */
				fprintf(stderr,
					_("%s: option requires an argument -- %c\n"),
					myname, optopt);
				usage(EXIT_FAILURE, stderr);
			}
			/* else
				let getopt print error message for us */
			break;
		}
		if (c == 'E')	/* --exec ends option processing */
			break;
	}
out:

	if (do_nostalgia)
		nostalgia();

	/* check for POSIXLY_CORRECT environment variable */
	if (! do_posix && getenv("POSIXLY_CORRECT") != NULL) {
		do_flags |= DO_POSIX;
		if (do_lint)
			lintwarn(
	_("environment variable `POSIXLY_CORRECT' set: turning on `--posix'"));
	}

	if (do_posix) {
		use_lc_numeric = true;
		if (do_traditional)	/* both on command line */
			warning(_("`--posix' overrides `--traditional'"));
		else
			do_flags |= DO_TRADITIONAL;
			/*
			 * POSIX compliance also implies
			 * no GNU extensions either.
			 */
	}

	if (do_traditional && do_non_decimal_data) {
		do_flags &= ~DO_NON_DEC_DATA;
		warning(_("`--posix'/`--traditional' overrides `--non-decimal-data'"));
	}

	if (do_lint && os_is_setuid())
		warning(_("running %s setuid root may be a security problem"), myname);

#if MBS_SUPPORT
	if (do_binary) {
		if (do_posix)
			warning(_("`--posix' overrides `--characters-as-bytes'"));
		else
			gawk_mb_cur_max = 1;	/* hands off my data! */
#if defined(LC_ALL)
		setlocale(LC_ALL, "C");
#endif
	}
#endif

	if (do_debug)	/* Need to register the debugger pre-exec hook before any other */
		init_debug();

#ifdef HAVE_MPFR
	/* Set up MPFR defaults, and register pre-exec hook to process arithmetic opcodes */ 
	if (do_mpfr)
		init_mpfr(DEFAULT_PREC, DEFAULT_ROUNDMODE);
#endif

	/* load group set */
	init_groupset();

#ifdef HAVE_MPFR
	if (do_mpfr) {
		mpz_init(Nnull_string->mpg_i);
		Nnull_string->flags = (MALLOC|STRCUR|STRING|MPZN|NUMCUR|NUMBER);
	} else
#endif
	{
		Nnull_string->numbr = 0.0;
		Nnull_string->flags = (MALLOC|STRCUR|STRING|NUMCUR|NUMBER);
	}

	/*
	 * Tell the regex routines how they should work.
	 * Do this before initializing variables, since
	 * they could want to do a regexp compile.
	 */
	resetup();

	/* Set up the special variables */
	init_vars();

	/* Set up the field variables */
	init_fields();

	/* Now process the pre-assignments */
	for (i = 0; i <= numassigns; i++) {
		if (preassigns[i].type == PRE_ASSIGN)
			(void) arg_assign(preassigns[i].val, true);
		else	/* PRE_ASSIGN_FS */
			cmdline_fs(preassigns[i].val);
		efree(preassigns[i].val);
	}

	if (preassigns != NULL)
		efree(preassigns);

	if ((BINMODE & 1) != 0)
		if (os_setbinmode(fileno(stdin), O_BINARY) == -1)
			fatal(_("can't set binary mode on stdin (%s)"), strerror(errno));
	if ((BINMODE & 2) != 0) {
		if (os_setbinmode(fileno(stdout), O_BINARY) == -1)
			fatal(_("can't set binary mode on stdout (%s)"), strerror(errno));
		if (os_setbinmode(fileno(stderr), O_BINARY) == -1)
			fatal(_("can't set binary mode on stderr (%s)"), strerror(errno));
	}

#ifdef GAWKDEBUG
	setbuf(stdout, (char *) NULL);	/* make debugging easier */
#endif
	if (os_isatty(fileno(stdout)))
		output_is_tty = true;

	/* initialize API before loading extension libraries */
	init_ext_api();

	/* load extension libs */
        for (s = srcfiles->next; s != srcfiles; s = s->next) {
                if (s->stype == SRC_EXTLIB)
			load_ext(s->fullpath);
		else if (s->stype != SRC_INC)
			have_srcfile++;
        }

	/* do version check after extensions are loaded to get extension info */
	if (do_version)
		version();

	/* No -f or --source options, use next arg */
	if (! have_srcfile) {
		if (optind > argc - 1 || stopped_early) /* no args left or no program */
			usage(EXIT_FAILURE, stderr);
		(void) add_srcfile(SRC_CMDLINE, argv[optind], srcfiles, NULL, NULL);
		optind++;
	}

	/* Select the interpreter routine */
	init_interpret();

	init_args(optind, argc,
			do_posix ? argv[0] : myname,
			argv);

#if defined(LC_NUMERIC)
	/*
	 * FRAGILE!  CAREFUL!
	 * Pre-initing the variables with arg_assign() can change the
	 * locale.  Force it to C before parsing the program.
	 */
	setlocale(LC_NUMERIC, "C");
#endif
	/* Read in the program */
	if (parse_program(& code_block) != 0)
		exit(EXIT_FAILURE);
	
	if (do_intl)
		exit(EXIT_SUCCESS);

	if (do_lint)
		shadow_funcs();

	if (do_lint && code_block->nexti->opcode == Op_atexit)
		lintwarn(_("no program text at all!"));

	load_symbols();

	if (do_profile)
		init_profiling_signals();

#if defined(LC_NUMERIC)
	/*
	 * See comment above about using locale's decimal point.
	 *
	 * 10/2005:
	 * Bitter experience teaches us that most people the world over
	 * use period as the decimal point, not whatever their locale
	 * uses.  Thus, only use the locale's decimal point if being
	 * posixly anal-retentive.
	 *
	 * 7/2007:
	 * Be a little bit kinder. Allow the --use-lc-numeric option
	 * to also use the local decimal point. This avoids the draconian
	 * strictness of POSIX mode if someone just wants to parse their
	 * data using the local decimal point.
	 */
	if (use_lc_numeric)
		setlocale(LC_NUMERIC, "");
#endif
	
	init_io();
	output_fp = stdout;

	if (do_debug)
		debug_prog(code_block);
	else
		interpret(code_block);

	if (do_pretty_print) {
		dump_prog(code_block);
		dump_funcs();
	}

	if (do_dump_vars)
		dump_vars(varfile);

	if (do_tidy_mem)
		release_all_vars();
	
	/* keep valgrind happier */
	if (extra_stack)
		efree(extra_stack);

	final_exit(exit_val);
	return exit_val;	/* to suppress warnings */
}
예제 #15
0
파일: main.c 프로젝트: WndSks/msys
int
main(int argc, char **argv)
{
	int c;
	char *scan;
	/* the + on the front tells GNU getopt not to rearrange argv */
	const char *optlist = "+F:f:v:W;m:D";
	int stopped_early = FALSE;
	int old_optind;
	extern int optind;
	extern int opterr;
	extern char *optarg;
	int i;
	int stdio_problem = FALSE;

	/* do these checks early */
	if (getenv("TIDYMEM") != NULL)
		do_tidy_mem = TRUE;

	if (getenv("WHINY_USERS") != NULL)
		whiny_users = TRUE;

#ifdef HAVE_MCHECK_H
	if (do_tidy_mem)
		mtrace();
#endif /* HAVE_MCHECK_H */
	
#if defined(LC_CTYPE)
	setlocale(LC_CTYPE, "");
#endif
#if defined(LC_COLLATE)
	setlocale(LC_COLLATE, "");
#endif
#if defined(LC_MESSAGES)
	setlocale(LC_MESSAGES, "");
#endif
#if defined(LC_NUMERIC)
	/*
	 * Force the issue here.  According to POSIX 2001, decimal
	 * point is used for parsing source code and for command-line
	 * assignments and the locale value for processing input,
	 * number to string conversion, and printing output.
	 */
	setlocale(LC_NUMERIC, "C");
#endif
#if defined(LC_TIME)
	setlocale(LC_TIME, "");
#endif

#ifdef MBS_SUPPORT
	/*
	 * In glibc, MB_CUR_MAX is actually a function.  This value is
	 * tested *a lot* in many speed-critical places in gawk. Caching
	 * this value once makes a speed difference.
	 */
	gawk_mb_cur_max = MB_CUR_MAX;
	/* Without MBS_SUPPORT, gawk_mb_cur_max is 1. */
#endif

	(void) bindtextdomain(PACKAGE, LOCALEDIR);
	(void) textdomain(PACKAGE);

	(void) signal(SIGFPE, catchsig);
	(void) signal(SIGSEGV, catchsig);
#ifdef SIGBUS
	(void) signal(SIGBUS, catchsig);
#endif

	myname = gawk_name(argv[0]);
        argv[0] = (char *) myname;
	os_arg_fixup(&argc, &argv); /* emulate redirection, expand wildcards */

	/* remove sccs gunk */
	if (strncmp(version_string, "@(#)", 4) == 0)
		version_string += 4;

	if (argc < 2)
		usage(1, stderr);

	/* Robustness: check that file descriptors 0, 1, 2 are open */
	init_fds();

	/* init array handling. */
	array_init();

	/* we do error messages ourselves on invalid options */
	opterr = FALSE;

	/* option processing. ready, set, go! */
	for (optopt = 0, old_optind = 1;
	     (c = getopt_long(argc, argv, optlist, optab, NULL)) != EOF;
	     optopt = 0, old_optind = optind) {
		if (do_posix)
			opterr = TRUE;

		switch (c) {
		case 'F':
			preassigns_add(PRE_ASSIGN_FS, optarg);
			break;

		case 'S':
			disallow_var_assigns = TRUE;
			/* fall through */
		case 'f':
			/*
			 * a la MKS awk, allow multiple -f options.
			 * this makes function libraries real easy.
			 * most of the magic is in the scanner.
			 *
			 * The following is to allow for whitespace at the end
			 * of a #! /bin/gawk line in an executable file
			 */
			scan = optarg;
			if (argv[optind-1] != optarg)
				while (ISSPACE(*scan))
					scan++;
			srcfiles_add(SOURCEFILE,
				(*scan == '\0' ? argv[optind++] : optarg));
			break;

		case 'v':
			preassigns_add(PRE_ASSIGN, optarg);
			break;

		case 'm':
			/*
			 * Research awk extension.
			 *	-mf nnn		set # fields, gawk ignores
			 *	-mr nnn		set record length, ditto
			 */
			if (do_lint)
				lintwarn(_("`-m[fr]' option irrelevant in gawk"));
			if (optarg[0] != 'r' && optarg[0] != 'f')
				warning(_("-m option usage: `-m[fr] nnn'"));
			/*
			 * Set fixed length records for Tandem,
			 * ignored on other platforms (see io.c:get_a_record).
			 */
			if (optarg[0] == 'r') {
				if (ISDIGIT(optarg[1]))
					MRL = atoi(optarg+1);
				else {
					MRL = atoi(argv[optind]);
					optind++;
				}
			} else if (optarg[1] == '\0')
				optind++;
			break;

		case 'W':       /* gawk specific options - now in getopt_long */
			fprintf(stderr, _("%s: option `-W %s' unrecognized, ignored\n"),
				argv[0], optarg);
			break;

		/* These can only come from long form options */
		case 'C':
			copyleft();
			break;

		case 'd':
			do_dump_vars = TRUE;
			if (optarg != NULL && optarg[0] != '\0')
				varfile = optarg;
			break;

		case 'l':
#ifndef NO_LINT
			do_lint = LINT_ALL;
			if (optarg != NULL) {
				if (strcmp(optarg, "fatal") == 0)
					lintfunc = r_fatal;
				else if (strcmp(optarg, "invalid") == 0)
					do_lint = LINT_INVALID;
			}
#endif
			break;

		case 'p':
			do_profiling = TRUE;
			if (optarg != NULL)
				set_prof_file(optarg);
			else
				set_prof_file(DEFAULT_PROFILE);
			break;

		case 's':
			if (optarg[0] == '\0')
				warning(_("empty argument to `--source' ignored"));
			else
				srcfiles_add(CMDLINE, optarg);
			break;

		case 'u':
			usage(0, stdout);	/* per coding stds */
			break;

		case 'V':
			version();
			break;

		case 0:
			/*
			 * getopt_long found an option that sets a variable
			 * instead of returning a letter. Do nothing, just
			 * cycle around for the next one.
			 */
			break;

		case 'D':
#ifdef GAWKDEBUG
			yydebug = 2;
			break;
#endif
			/* if not debugging, fall through */

		case '?':
		default:
			/*
			 * New behavior.  If not posix, an unrecognized
			 * option stops argument processing so that it can
			 * go into ARGV for the awk program to see. This
			 * makes use of ``#! /bin/gawk -f'' easier.
			 *
			 * However, it's never simple. If optopt is set,
			 * an option that requires an argument didn't get the
			 * argument. We care because if opterr is 0, then
			 * getopt_long won't print the error message for us.
			 */
			if (! do_posix
			    && (optopt == '\0' || strchr(optlist, optopt) == NULL)) {
				/*
				 * can't just do optind--. In case of an
				 * option with >= 2 letters, getopt_long
				 * won't have incremented optind.
				 */
				optind = old_optind;
				stopped_early = TRUE;
				goto out;
			} else if (optopt != '\0')
				/* Use 1003.2 required message format */
				fprintf(stderr,
					_("%s: option requires an argument -- %c\n"),
					myname, optopt);
			/* else
				let getopt print error message for us */
			break;
		}
		if (c == 'S')	/* --exec ends option processing */
			break;
	}
out:

	if (do_nostalgia)
		nostalgia();

	/* check for POSIXLY_CORRECT environment variable */
	if (! do_posix && getenv("POSIXLY_CORRECT") != NULL) {
		do_posix = TRUE;
		if (do_lint)
			lintwarn(
	_("environment variable `POSIXLY_CORRECT' set: turning on `--posix'"));
	}

	if (do_posix) {
		if (do_traditional)	/* both on command line */
			warning(_("`--posix' overrides `--traditional'"));
		else
			do_traditional = TRUE;
			/*
			 * POSIX compliance also implies
			 * no GNU extensions either.
			 */
	}

	if (do_traditional && do_non_decimal_data) {
		do_non_decimal_data = FALSE;
		warning(_("`--posix'/`--traditional' overrides `--non-decimal-data'"));
	}

	if (do_lint && os_is_setuid())
		warning(_("running %s setuid root may be a security problem"), myname);

	/*
	 * Force profiling if this is pgawk.
	 * Don't bother if the command line already set profiling up.
	 */
	if (! do_profiling)
		init_profiling(& do_profiling, DEFAULT_PROFILE);

	/* load group set */
	init_groupset();

	/* initialize the null string */
	Nnull_string = make_string("", 0);
	Nnull_string->numbr = 0.0;
	Nnull_string->type = Node_val;
	Nnull_string->flags = (PERM|STRCUR|STRING|NUMCUR|NUMBER);

	/*
	 * Tell the regex routines how they should work.
	 * Do this before initializing variables, since
	 * they could want to do a regexp compile.
	 */
	resetup();

	/* Set up the special variables */
	init_vars();

	/* Set up the field variables */
	init_fields();

	/* Now process the pre-assignments */
	for (i = 0; i <= numassigns; i++)
		if (preassigns[i].stype == PRE_ASSIGN)
			(void) arg_assign(preassigns[i].val, TRUE);
		else	/* PRE_ASSIGN_FS */
			cmdline_fs(preassigns[i].val);
	free(preassigns);

	if ((BINMODE & 1) != 0)
		if (os_setbinmode(fileno(stdin), O_BINARY) == -1)
			fatal(_("can't set binary mode on stdin (%s)"), strerror(errno));
	if ((BINMODE & 2) != 0) {
		if (os_setbinmode(fileno(stdout), O_BINARY) == -1)
			fatal(_("can't set binary mode on stdout (%s)"), strerror(errno));
		if (os_setbinmode(fileno(stderr), O_BINARY) == -1)
			fatal(_("can't set binary mode on stderr (%s)"), strerror(errno));
	}

#ifdef GAWKDEBUG
	setbuf(stdout, (char *) NULL);	/* make debugging easier */
#endif
	if (isatty(fileno(stdout)))
		output_is_tty = TRUE;
	/* No -f or --source options, use next arg */
	if (numfiles == -1) {
		if (optind > argc - 1 || stopped_early) /* no args left or no program */
			usage(1, stderr);
		srcfiles_add(CMDLINE, argv[optind]);
		optind++;
	}

	init_args(optind, argc, (char *) myname, argv);
	(void) tokexpand();

#if defined(LC_NUMERIC)
	/*
	 * FRAGILE!  CAREFUL!
	 * Pre-initing the variables with arg_assign() can change the
	 * locale.  Force it to C before parsing the program.
	 */
	setlocale(LC_NUMERIC, "C");
#endif

	/* Read in the program */
	if (yyparse() != 0 || errcount != 0)
		exit(1);

	free(srcfiles);

	if (do_intl)
		exit(0);

	if (do_lint && begin_block == NULL && expression_value == NULL
	     && end_block == NULL)
		lintwarn(_("no program text at all!"));

	if (do_lint)
		shadow_funcs();

	init_profiling_signals();

#if defined(LC_NUMERIC)
	/* See comment above. */
	setlocale(LC_NUMERIC, "");
#endif

#if defined(HAVE_LOCALE_H)
	loc = *localeconv();	/* Make a local copy of locale numeric info */
#endif

	/* Whew. Finally, run the program. */
	if (begin_block != NULL) {
		in_begin_rule = TRUE;
		(void) interpret(begin_block);
	}
	in_begin_rule = FALSE;
	if (! exiting && (expression_value != NULL || end_block != NULL))
		do_input();
	if (end_block != NULL) {
		in_end_rule = TRUE;
		(void) interpret(end_block);
	}
	in_end_rule = FALSE;
	/*
	 * This used to be:
	 *
	 * if (close_io() != 0 && ! exiting && exit_val == 0)
	 * 	exit_val = 1;
	 *
	 * Other awks don't care about problems closing open files
	 * and pipes, in that it doesn't affect their exit status.
	 * So we no longer do either.
	 */
	(void) close_io(& stdio_problem);
	/*
	 * However, we do want to exit non-zero if there was a problem
	 * with stdout/stderr, so we reinstate a slightly different
	 * version of the above:
	 */
	if (stdio_problem && ! exiting && exit_val == 0)
		exit_val = 1;

	if (do_profiling) {
		dump_prog(begin_block, expression_value, end_block);
		dump_funcs();
	}

	if (do_dump_vars)
		dump_vars(varfile);

	if (do_tidy_mem)
		release_all_vars();

	exit(exit_val);		/* more portable */
	return exit_val;	/* to suppress warnings */
}