sectionfile.c

来自「kaffe Java 解释器语言,源码,Java的子集系统,开放源代码」· C语言 代码 · 共 1,220 行 · 第 1/2 页

C
1,220
字号
	return( retval );}/* * Write out the internal data to the file */static int writeFile(struct parse_state *ps){	int retval = 0, temp_fd = -1;	FILE *in_file, *out_file;	struct section_file *sf;	char *temp_name = 0;	sf = ps->ps_section_file;	in_file = ps->ps_in_file;	/* Create a temporary file for the output */	if( (temp_name = (char *)KMALLOC(10)) &&	    strcpy(temp_name, "sf.XXXXXX") &&	    ((temp_fd = mkstemp(temp_name)) >= 0) &&	    (out_file = fdopen(temp_fd, "w+")) )	{		ps->ps_out_file = out_file;		/* Parse the old file and update with current data */		if( (retval = parseFile(ps)) )		{			if( !ps->ps_parent )			{				/*				 * Write out any sections that don't have peers				 * in the input file				 */				retval = writeNewSections(ps);			}		}		else		{			dprintf(				"Error: Unable to sync file %s\n",				ps->ps_filename);		}		fclose(out_file);		/*		 * If there weren't any errors we rename the temporary file		 * so that it overwrites the input file.  Otherwise, we remove		 * the bad output file, and leave the input file intact.		 */		if( retval )		{			rename(temp_name, ps->ps_filename);		}		else		{			remove(temp_name);		}	}	else	{		dprintf(			"Error: Unable to create temporary file for "			"rewriting %s.\n",			ps->ps_filename);		if( temp_fd >= 0 )		{			remove(temp_name);			close(temp_fd);		}	}	KFREE(temp_name);	return( retval );}/* * Internal file sync function.  This allows for included files to be processed * and their data contained in the root section file. */static int syncFile(struct parse_state *parent, struct section_file *sf,		    char *filename){	struct stat file_stat;	time_t file_time = 0;	int retval = 0;	FILE *file;	/* Make sure theres a file to sync with */	if( !filename || !filename[0] )		return( 0 );	/* Get the file's time stamp so we know whether its new or old */	if( !stat(filename, &file_stat) )	{		file_time = file_stat.st_mtime;	}	else	{		/* Make an empty file if it doesn't exist */		if( (file = fopen(filename, "w+")) )		{			fclose(file);		}	}	if( (file = fopen(filename, "r")) )	{		struct parse_state ps;		/* Initialize the parser state */		ps.ps_parent = parent;		ps.ps_filename = filename;		ps.ps_section_file = sf;		ps.ps_in_file = file;		ps.ps_out_file = 0;		ps.ps_section = 0;		ps.ps_line = 0;		ps.ps_column = 0;		ps.ps_data = 0;		ps.ps_len = 0;		if( sf->sf_time < file_time )		{			/* The file is newer, read it in */			if( (retval = parseFile(&ps)) )			{				if( !parent )					sf->sf_time = time(0);			}		}		else		{			/* The file is older, write out our data */			if( (retval = writeFile(&ps)) )			{				if( !parent )					sf->sf_time = time(0);			}		}		fclose(file);	}	return( retval );}struct section_file *createSectionFile(){	struct section_file *retval;	/* Allocate the structure and do any initialization */	if( (retval = (struct section_file *)	     KMALLOC(sizeof(struct section_file))) )	{		int lpc;		retval->lock = 0;		retval->sf_filename = 0;		retval->sf_time = 0;		retval->sf_ordered_sections = 0;		retval->sf_last_section = &retval->sf_ordered_sections;		for( lpc = 0; lpc < SECTION_FILE_HASH_SIZE; lpc++ )		{			retval->sf_sections[lpc] = 0;		}	}	return( retval );}void deleteSectionFile(struct section_file *sf){	if( sf )	{		struct section_file_data *sfd, *sfd_next;		int lpc;		/*		 * Walk through the section and have their handlers delete the		 * section data objects.		 */		for( lpc = 0; lpc < SECTION_FILE_HASH_SIZE; lpc++ )		{			sfd = sf->sf_sections[lpc];			while( sfd )			{				sfd_next = sfd->sfd_next;				sfd->sfd_type->fs_handler(sfd->sfd_type,							  sf,							  SFM_DELETE,							  sfd);				sfd = sfd_next;			}		}		KFREE(sf);	}}void setSectionFileName(struct section_file *sf, char *name){	sf->sf_filename = name;}/* * States for parsing a section line made up of an identifier followed by * white space, and a data string */enum {	SS_TAG,		/* Getting the tag */	SS_GUTTER,	/* White space between tag and value */	SS_VALUE,	/* Value to the end of the line, minus ws, comments */};int parseSectionLine(struct parse_state *ps, char **tag, char **value,		     FILE *out_file){	int state, tag_start = -1, tag_end = -1;	int value_start = -1, value_end = -1;	int retval = 1, curr, line_len;	char *line, *save;	line = ps->ps_data;	line_len = ps->ps_len;	save = ps->ps_save;	/* We start out looking for the tag */	state = SS_TAG;	/* Walk through the line */	for( curr = 0; curr < line_len; curr++ )	{		switch(line[curr])		{		case '#':			/* Its a comment */			if( out_file )			{				/* Write out value */				fwrite(*value, 1, strlen(*value), out_file);				if( value_end > 0 )				{					/*					 * Reset the trampled character at the					 * end of value					 */					line[value_end + 1] = save[1];					/* Write out the comment */					fwrite(&line[value_end + 1],					       1,					       line_len - (value_end + 1),					       out_file);				}				else				{					fwrite(&line[curr], 1, line_len - curr,					       out_file);				}			}			/* Nothing left to parse, jump to the end */			curr = line_len;			break;		case 0: /* Trampled white space */		case ' ':		case '\t':			switch(state)			{			case SS_TAG:				if( tag_start != -1 )				{					/* Found the gutter */					if( out_file )					{						/* Write the tag out */						fwrite(*tag,						       1,						       strlen(*tag),						       out_file);						/*						 * Write out the trampled char						 */						fwrite(&save[0],						       1, 1, out_file);					}					state = SS_GUTTER;				}				else if( out_file )				{					/* Write out the space */					fwrite(&line[curr], 1, 1, out_file);				}				break;			case SS_GUTTER:				if( out_file )				{					/* Write out the space */					fwrite(&line[curr], 1, 1, out_file);				}				break;			case SS_VALUE:				if( out_file )				{					/*					 * If the trampled char was a linefeed					 * then we need to write the value and					 * the linefeed.					 */					if( (line[curr] == 0) &&					    (curr == line_len - 1) )					{						fwrite(*value, 1,						       strlen(*value),						       out_file);						fwrite("\n", 1, 1, out_file);					}				}				break;			default:				break;			}			break;		case '\n':			if( out_file )			{				/* Write out value and the linefeed */				fwrite(*value, 1, strlen(*value), out_file);				fwrite(&line[curr], 1, 1, out_file);			}			break;		default:			switch(state)			{			case SS_TAG:				if( tag_start == -1 )					tag_start = curr;				tag_end = curr;				break;			case SS_GUTTER:				state = SS_VALUE;				/* Fallthrough */			case SS_VALUE:				if( value_start == -1 )					value_start = curr;				value_end = curr;				break;			}			break;		}		ps->ps_column++;	}	if( (tag_start != -1) && (tag_end != -1) )	{		/* Save the char we're gonna trample */		save[0] = line[tag_end + 1];		line[tag_end + 1] = 0;		*tag = &line[tag_start];	}	else	{		*tag = ""; /* better than NULL... */	}	if( (value_start != -1) && (value_end != -1) )	{		/* Save the char we're gonna trample */		save[1] = line[value_end + 1];		line[value_end + 1] = 0;		*value = &line[value_start];	}	else	{		*value = "";	}	/* Check for I/O error */	if( out_file && ferror(out_file) )		retval = 0;	return( retval );}/* * Silly function to restore the characters that parseLine tramples */static void restoreLine(struct parse_state *ps){	int save_idx = 0, lpc;	for( lpc = 0; lpc < ps->ps_len; lpc++ )	{		/* Find any nulls and replace with saved chars */		if( !ps->ps_data[lpc] )		{			ps->ps_data[lpc] = ps->ps_save[save_idx];			save_idx++;		}	}}/* Strings that represent `true' */static char *trueStrings[] = {	"1",	"true",	"yes",	"y",	"t",	0};/* Strings that represent `false' */static char *falseStrings[] = {	"0",	"false",	"no",	"n",	"f",	0};/* * Note:  The order of the values in trueStrings and falseStrings is important, * and should be of consistent style. */unsigned long parseFlagString(char *value,			      unsigned long flags,			      unsigned long flag_bit){	int retval = flags;	int lpc;	for( lpc = 0; trueStrings[lpc]; lpc++ )	{		/* If `value' is true, then set the bit */		if( !strcasecmp(value, trueStrings[lpc]) )		{			retval |= flag_bit;			break;		}		/* If `value' is false, then clear the bit */		if( !strcasecmp(value, falseStrings[lpc]) )		{			retval &= ~flag_bit;			break;		}	}	return( retval );}char *makeFlagString(unsigned long flags, unsigned long flag_bit, char *value){	/* Default to the old value */	char *retval = value;	/* Check for a change from the old value */	if( parseFlagString(value, flags, flag_bit) != flags )	{		int lpc;		/* Loop through all the strings */		for( lpc = 0; trueStrings[lpc]; lpc++ )		{			/*			 * If this true matches, then return the corresponding			 * false string			 */			if( !strcasecmp(value, trueStrings[lpc]) )			{				retval = falseStrings[lpc];				break;			}			/*			 * If this false matches, then return the corresponding			 * true string			 */			if( !strcasecmp(value, falseStrings[lpc]) )			{				retval = trueStrings[lpc];				break;			}		}	}	return( retval );}int syncSectionFile(struct section_file *sf){	int iLockRoot, retval;	lockMutex(sf);	retval = syncFile(0, sf, sf->sf_filename);	unlockMutex(sf);	return( retval );}void addSectionType(struct file_section *fs){	int hash;	hash = hashName(fs->fs_name, FILE_SECTION_TYPES_SIZE);	fs->fs_next = file_section_types[hash];	file_section_types[hash] = fs;}struct file_section *findSectionType(char *name){	struct file_section *retval = 0, *fs;	int hash;	hash = hashName(name, FILE_SECTION_TYPES_SIZE);	fs = file_section_types[hash];	while( fs && !retval )	{		if( !strcmp(name, fs->fs_name) )		{			retval = fs;		}		fs = fs->fs_next;	}	return( retval );}void addSectionToFile(struct section_file *sf, struct section_file_data *sfd){	int iLockRoot, hash;	hash = hashName(sfd->sfd_name, SECTION_FILE_HASH_SIZE);	lockMutex(sf);	sfd->sfd_next = sf->sf_sections[hash];	/* The section is new to this file so we set the dirty bit */	sfd->sfd_flags |= SFDF_DIRTY;	sf->sf_sections[hash] = sfd;	*sf->sf_last_section = sfd;	sf->sf_last_section = &sfd->sfd_order;	sfd->sfd_order = 0;	unlockMutex(sf);}void remSectionFromFile(struct section_file *sf, struct section_file_data *sfd){	sfd->sfd_flags |= SFDF_REMOVED;}struct section_file_data *findSectionInFile(struct section_file *sf,					    struct file_section *type,					    char *name){	struct section_file_data *retval = 0, *sfd;	int iLockRoot, hash;	lockMutex(sf);	hash = hashName(name, SECTION_FILE_HASH_SIZE);	sfd = sf->sf_sections[hash];	while( sfd && !retval )	{		if( (type == sfd->sfd_type) &&		    !strcmp(name, sfd->sfd_name) )			retval = sfd;		sfd = sfd->sfd_next;	}	unlockMutex(sf);	return( retval );}int walkFileSections(struct section_file *sf,		     int (*handler)(void *arg,				    struct section_file *sf,				    struct section_file_data *sfd),		     void *arg){	struct section_file_data *sfd;	int iLockRoot, retval = 1;	if( !sf )		return( 0 );	lockMutex(sf);	/* Walk over the ordered links */	sfd = sf->sf_ordered_sections;	while( sfd && retval )	{		retval = handler(arg, sf, sfd);		sfd = sfd->sfd_order;	}	unlockMutex(sf);	return( retval );}struct section_file_data *createFileSection(char *section_type,					    char *section_name,					    ...){	struct section_file_data *retval = 0;	struct file_section *fs;	char *new_name;	va_list args;	va_start(args, section_name);	/* Get the section type and ask it to create a section data object */	if( (fs = findSectionType(section_type)) &&	    (new_name = (char *)KMALLOC(strlen(section_name) + 1)) )	{		strcpy(new_name, section_name);		if( !fs->fs_handler(fs, 0, SFM_CREATE,				    &retval, new_name, &args) )		{			KFREE(new_name);			retval = 0;		}	}	va_end(args);	return( retval );}void deleteFileSection(struct section_file_data *sfd){	if( sfd )	{		KFREE(sfd->sfd_name);		/* Ask the handler to clean up the object */		sfd->sfd_type->fs_handler(sfd->sfd_type, 0, SFM_DELETE, sfd);	}}#endif /* KAFFE_FEEDBACK */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?