Exemplo n.º 1
0
/** check if the line we're looking at is a header/body delimiter */
static bool is_hb_delim(const char *line, size_t len, bool strict_body)
{
    if (strict_body)
	return len == 0;

    return is_blank_line(line, len);
}
Exemplo n.º 2
0
static void save_dump(global_conf_st *g_conf)
{
    FILE *fp = NULL;
    xode msg = NULL;
    char *msg_str = NULL;
    int i;
    if (g_conf->reload_file)
    {
	fp = fopen(g_conf->reload_file, "a+");
	if (fp == NULL)
	{
	    jlog(L_DEBUG, "try to create %s error\n", g_conf->reload_file);
	    global_conf_free(g_conf);
	    exit(-1);
	}
	for (i = 0; i < g_conf->max_thread; i++)
	{
	    while (g_async_queue_length(threads[i].msg_queue) > 0)
	    {
		msg = (xode) g_async_queue_pop(threads[i].msg_queue);
		decrMsgProcNum();
		msg_str = xode_to_str(msg);
		if (msg_str && (!is_blank_line(msg_str)))
		{
		    fprintf(fp, "%s\n", msg_str);
		    jlog(L_DEBUG, "save %s\n", msg_str);
		}
		xode_free(msg);
	    }
	}
	fclose(fp);
    }
}
Exemplo n.º 3
0
/**
 * gnome_theme_file_new_from_string:
 * @data:  the string used to create a #GnomeThemeFile.
 * @error: location to store the error occuring, or NULL to ignore errors 
 *
 * Creates a #GnomeThemeFile from the data string passed.
 * 
 * Returns: a #GnomeThemeFile.
 * 
 * Since: 2.2
 **/
GnomeThemeFile *
gnome_theme_file_new_from_string (char                       *data,
				  GError                    **error)
{
  GnomeThemeFileParser parser;

  parser.df = g_new0 (GnomeThemeFile, 1);
  parser.current_section = -1;

  parser.n_allocated_lines = 0;
  parser.n_allocated_sections = 0;
  parser.line_nr = 1;

  parser.line = data;

  /* Put any initial comments in a NULL segment */
  open_section (&parser, NULL);
  
  while (parser.line && *parser.line)
    {
      if (*parser.line == '[') {
	if (!parse_section_start (&parser, error))
	  return NULL;
      } else if (is_blank_line (&parser) ||
		 *parser.line == '#')
	parse_comment_or_blank (&parser);
      else
	{
	  if (!parse_key_value (&parser, error))
	    return NULL;
	}
    }

  return parser.df;
}
Exemplo n.º 4
0
/* 
** This routine alters a check-in message to make it more readable
** in a timeline.  The following changes are made:
**
** *:  Remove all leading whitespace.  This prevents the text from
**     being display verbatim.
**
** *:  If the message begins with "*:" or "N:" (where N is a number)
**     then convert the ":" into "." to disable the bullet or enumeration.
**
** *:  Change all newlines to spaces.  This will disable paragraph
**     breaks, verbatim paragraphs, enumerations, and bullet lists.
**
** *:  Collapse contiguous whitespace into a single space character
**
** *:  Truncate the string at the first whitespace character that
**     is more than mxChar characters from the beginning of the string.
**     Or if the string is longer than mxChar character and but there
**     was a paragraph break after mnChar characters, truncate at the
**     paragraph break.
**
** This routine changes the message in place.  It returns non-zero if
** the message was truncated and zero if the original text is still
** all there (though perhaps altered.)
*/
int output_trim_message(char *zMsg, int mnChar, int mxChar){
  int i, j, k;
  int brkpt = 0;    /* First paragraph break after zMsg[mnChar] */

  if( zMsg==0 ) return 0;
  for(i=0; isspace(zMsg[i]); i++){}
  i += is_list_elem(&zMsg[i], &k);
  for(j=0; zMsg[i]; i++){
    int c = zMsg[i];
    if( c=='\n' ){
      if( j>mnChar && is_blank_line(&zMsg[i+1]) && brkpt==0 ){
        brkpt = j;
      }
      c = ' ';
    }
    if( isspace(c) ){
      if( j>=mxChar ){
        zMsg[j] = 0;
        if( brkpt>0 ) zMsg[brkpt] = 0;
        return 1;
      }
      if( j>0 && !isspace(zMsg[j-1]) ){
        zMsg[j++] = ' ';
      }
    }else{
      zMsg[j++] = c;
    }
  }
  zMsg[j] = 0;
  return 0;
}
/**
 * anjuta_plugin_description_new_from_string:
 * @data: The data to parse. The format of the data is .ini style.
 *
 * Parses the given plugin description data (usally read from the plugin
 * description file and creates an instance of #AnjutaPluginDescription.
 * The format of the content string is similar to .ini format.
 *
 * Return value: a new #AnjutaPluginDescription object
 */
AnjutaPluginDescription *
anjuta_plugin_description_new_from_string (char *data, GError **error)
{
  AnjutaPluginDescriptionParser parser;

  parser.df = g_new0 (AnjutaPluginDescription, 1);
  parser.current_section = -1;

  parser.n_allocated_lines = 0;
  parser.n_allocated_sections = 0;
  parser.line_nr = 1;

  parser.line = data;

	/* Put any initial comments in a NULL segment */
	open_section (&parser, NULL);
	while (parser.line != NULL && strlen(parser.line))
	{ 
		if (*parser.line == '[') {
			if (!parse_section_start (&parser, error))
				return NULL;
		} else if (is_blank_line (&parser) ||
		           *parser.line == '#')
			parse_comment_or_blank (&parser);
		else
		{
			if (!parse_key_value (&parser, error))
				return NULL;
		}
	}
 
  return parser.df;
}
Exemplo n.º 6
0
int		execute_line(char *line)
{
  t_ast_list	*list_ast;

  if (is_blank_line(line))
    return (0);
  list_ast = parse_line(line);
  if (!list_ast)
    return (PARSING_ERROR);
  return (execute_list_ast(list_ast));
}
Exemplo n.º 7
0
const char *skip_blank_lines(const char *msg)
{
	for (;;) {
		int linelen = get_one_line(msg);
		int ll = linelen;
		if (!linelen)
			break;
		if (!is_blank_line(msg, &ll))
			break;
		msg += linelen;
	}
	return msg;
}
Exemplo n.º 8
0
void Stencil::parse_body(std::ifstream& infile)
{
  std::string line;
  int row = 0;
  while ( getline (infile, line) ) {
    if (is_comment_line(line) || is_blank_line(line)) {
      continue;
    } else {
      parse_stencil_line(line, row);
      row++;
    }
  }
}
Exemplo n.º 9
0
 int read_gjf_match_ff(char *gjffile, char *suffix, structGraphic *g)
 {
   FILE *fp;
   char matchfile[50];
   char line[200], name[10], file[50];
   char *p;
   int i;

   i = 0;

   strcpy(file, gjffile);
   p = strtok(file, ".");
   sprintf(matchfile, "%s_%s.txt", p, suffix);

   fp = fopen(matchfile, "r");
   if(fp == NULL)
   {
     printf("fatal error: match file of gjf not exist! \nfilename: %s\n", matchfile);
	 exit(1);
   }

   //JmpOrNot(fp, '#');
   //fscanf(fp, "%s", name);
   //strcpy(g->name, name);
   JmpOrNot(fp, '#');

   while(fgets(line, sizeof(line), fp) != NULL)
   {
      if(is_blank_line(line))
          break;
      else
      {
          sscanf(line, "%s", name);
         
          strcpy(g->vex[i].ffname, name);
          //printf("%s\n", name);
          i++;
      }                     
    }

   return i;
 }
Exemplo n.º 10
0
static void reload_dump(global_conf_st *g_conf)
{
    FILE *fp = NULL;
    char line[2048];
    if (g_conf->reload_file)
    {
	if ((fp = fopen(g_conf->reload_file, "r")) == NULL)
	{
	    jlog(L_ERR, "reload file is not exist ");
	    return;
	}
	while (!feof(fp))
	{
	    memset(line, 0, sizeof(line));
	    fgets(line, sizeof(line), fp);
	    jlog(L_DEBUG, "reload %s\n", line);
	    if (is_blank_line(line))
		break;
	    jlog(L_DEBUG, "reload %s\n", line);
	    msg_st *msg = (msg_st *) calloc(sizeof(msg_st), 1);
	    if (msg == NULL)
	    {
		jlog(L_ERR, "out of memory");
		exit(1);
	    }
	    if (-1 == init_msg(msg, line))
	    {
		if (msg)
		    free(msg);
		return ;
	    }

	    int thread_index = g_str_hash(msg->src_pnum) % g_conf->max_thread;
	    g_async_queue_push(threads[thread_index].msg_queue, msg);
	    incrMsgProcNum();
	}
	fclose(fp);
	fp = fopen(g_conf->reload_file, "w");
	fclose(fp);
    }
}
Exemplo n.º 11
0
void pp_remainder(struct pretty_print_context *pp,
		  const char **msg_p,
		  struct strbuf *sb,
		  int indent)
{
	int first = 1;
	for (;;) {
		const char *line = *msg_p;
		int linelen = get_one_line(line);
		*msg_p += linelen;

		if (!linelen)
			break;

		if (is_blank_line(line, &linelen)) {
			if (first)
				continue;
			if (pp->fmt == CMIT_FMT_SHORT)
				break;
		}
		first = 0;

		strbuf_grow(sb, linelen + indent + 20);
		if (indent)
			pp_handle_indent(pp, sb, indent, line, linelen);
		else if (pp->expand_tabs_in_log)
			strbuf_add_tabexpand(sb, pp->expand_tabs_in_log,
					     line, linelen);
		else {
			if (pp->fmt == CMIT_FMT_MBOXRD &&
					is_mboxrd_from(line, linelen))
				strbuf_addch(sb, '>');

			strbuf_add(sb, line, linelen);
		}
		strbuf_addch(sb, '\n');
	}
}
Exemplo n.º 12
0
const char *format_subject(struct strbuf *sb, const char *msg,
			   const char *line_separator)
{
	int first = 1;

	for (;;) {
		const char *line = msg;
		int linelen = get_one_line(line);

		msg += linelen;
		if (!linelen || is_blank_line(line, &linelen))
			break;

		if (!sb)
			continue;
		strbuf_grow(sb, linelen + 2);
		if (!first)
			strbuf_addstr(sb, line_separator);
		strbuf_add(sb, line, linelen);
		first = 0;
	}
	return msg;
}
Exemplo n.º 13
0
 /*
  read gjf Cartesian file.
 */
void read_gjf_cartesian(char *file, structGraphic *g)
{
   FILE *fp;
   int flag;
   int i, k,  nedge;
   int ncount, key[20];
   decimal value[20];
   char line[300], name[15];
   
   flag = 0;   i = k = 0;   nedge = 0;
   
   init_graphic(g);

   fp = fopen(file, "r");
     
   JmpOrNot(fp, '%');
   JmpOrNot(fp, '#');
   JmpSpace(fp);
   toss(fp, 3);
   
   while(fgets(line, sizeof(line), fp) != NULL)
   {
      if(is_blank_line(line))
          break;
      else
      {
          sscanf(line, "%s", name);
          g->vex[i].id = i+1;
         
          strcpy(g->vex[i].element_name, name);
          //printf("%s\n", name);
          i++;
      }                     
    }
    
    g->n = i;
    
    while(fgets(line, sizeof(line), fp) != NULL)
    {
         if(is_blank_line(line))
             break;
                      
         ncount = count_tokens(ltrim(line), " ");  
		 //printf("%d\n\n", ncount);
         nedge += ncount/2; 
		 k = 0;
         for(i = 0; i < ncount; i++)
         {
             if(i == 0 || i%2 == 1)             
                 key[k++] = atoi(gettoken(line," ",i+1)); 
             else
                 value[0] = (decimal)atof(gettoken(line," ",i+1));              
         }                
          
         //g->edge[key[0]-1][key[0]-1] = INFINITY;
		 //printf("%d\n", k);
         for(i = 1; i < k; i++)
         {
            g->edge[key[0]-1][key[i]-1] = 1;
            g->edge[key[i]-1][key[0]-1] = 1;
			
         }  
                
     }
     
     g->e = nedge;
	 //printf("%d\n", nedge);

    if(read_gjf_match_ff(file, "match", g) != g->n)
	{
	  printf("ERROR OCCURED... FILE:%s LINE:%s\n", __FILE__, __LINE__);
	  exit(1);
	}

  return;

 }
Exemplo n.º 14
0
static int get_line	/* returns # of items read, or -1 if error */
(
    FILE *f,		/* file to read from */
    long *i,		/* row index */
    long *j,		/* column index */
    double *x,		/* real part */
    double *z,		/* imaginary part */
    Int *stype)		/* stype, as determined from Matrix Market header,
			 * but with additional options for the skew-symmetric
	* and complex symmetric cases:
	* 1: symmetric, with upper part stored (not in Matrix Market format
	* 0: unsymmetric (Matrix Market "general")
	* -1: real symmetric or complex Hermitian, with lower part stored
	*	(Matrix Market "real symmetric" or "complex hermitian")
	* -2: real or complex skew symmetric
	* -3: complex symmetric
	*/
{
    char *p, s [MAXLINE+1] ;
    int k, c, c2, nitems, is_complex ;
    *i = 0 ;
    *j = 0 ;
    *x = 0 ;
    *z = 0 ;
    for ( ; ; )
    {
	s [0] = '\0' ;
	s [1] = '\0' ;
	s [MAXLINE] = '\0' ;
	if (fgets (s, MAXLINE, f) == NULL)
	{
	    /* end of file */
	    return (EMPTY) ;
	}
	if (s [0] == '%')
	{
	    /* a comment line */
	    if (strncmp (s, "%%MatrixMarket", 14) == 0)
	    {
		/* this is a Matrix Market header, with the format:
		 * %%MatrixMarket matrix coord type storage */
		p = s ;

		/* get "matrix" token */
		while (*p && !isspace (*p)) p++ ;
		while (*p &&  isspace (*p)) p++ ;
		c = tolower (*p) ;
		if (c != 'm')
		{
		    /* bad format */
		    return (EMPTY) ;
		}

		/* get "coord" token */
		while (*p && !isspace (*p)) p++ ;
		while (*p &&  isspace (*p)) p++ ;
		c = tolower (*p) ;
		if (c != 'c')
		{
		    /* bad format, only "coordinate" is supported;
		     * "array" is not supported */
		    return (EMPTY) ;
		}

		/* get type token (real, pattern, complex, integer) */
		while (*p && !isspace (*p)) p++ ;
		while (*p &&  isspace (*p)) p++ ;
		c = tolower (*p) ;
		if (!(c == 'r' || c == 'p' || c == 'c' || c == 'i'))
		{
		    /* bad format */
		    return (EMPTY) ;
		}

		is_complex = (c == 'c') ;

		/* get storage token (general, hermitian, symmetric, or
		 * skew-symmetric) */
		while (*p && !isspace (*p)) p++ ;
		while (*p &&  isspace (*p)) p++ ;
		c = tolower (*p) ;
		c2 = tolower (*(p+1)) ;
		if (c == 'g')
		{
		    /* "general" storage (unsymmetric matrix) */
		    *stype = 0 ;
		}
		else if (c == 's' && c2 == 'y')
		{
		    /* "symmetric" */
		    if (is_complex)
		    {
			/* complex symmetric, lower triangular part present */
			*stype = -3 ;
		    }
		    else
		    {
			/* real symmetric, lower triangular part present */
			*stype = -1 ;
		    }
		}
		else if (c == 'h')
		{
		    /* "hermitian" matrix, lower triangular part present */
		    *stype = -1 ;
		}
		else if (c == 's' && c2 == 'k')
		{
		    /* "skew-symmetric" (real or complex) */
		    *stype = -2 ;
		}
		else
		{
		    /* bad format */
		    return (EMPTY) ;
		}
	    }
	}
	else
	{
	    /* an entry, or a blank line */
	    if (is_blank_line (s))
	    {
		/* the line is blank, continue and get the next line */
		continue ;
	    }
	    /* this line contains an entry */
	    return (sscanf (s, "%ld %ld %lg %lg\n", i, j, x, z)) ;
	}
    }
}
BusDesktopFile*
bus_desktop_file_load (DBusString *filename,
		       DBusError  *error)
{
  DBusString str;
  BusDesktopFileParser parser;
  DBusStat sb;

  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
  
  /* Clearly there's a race here, but it's just to make it unlikely
   * that we do something silly, we still handle doing it below.
   */
  if (!_dbus_stat (filename, &sb, error))
    return NULL;

  if (sb.size > _DBUS_ONE_KILOBYTE * 128)
    {
      dbus_set_error (error, DBUS_ERROR_FAILED,
                      "Desktop file size (%ld bytes) is too large", (long) sb.size);
      return NULL;
    }
  
  if (!_dbus_string_init (&str))
    return NULL;
  
  if (!_dbus_file_get_contents (&str, filename, error))
    {
      _dbus_string_free (&str);
      return NULL;
    }

  if (!_dbus_string_validate_utf8 (&str, 0, _dbus_string_get_length (&str)))
    {
      _dbus_string_free (&str);
      dbus_set_error (error, DBUS_ERROR_FAILED,
                      "invalid UTF-8");   
      return NULL;
    }
  
  parser.desktop_file = dbus_new0 (BusDesktopFile, 1);
  if (parser.desktop_file == NULL)
    {
      _dbus_string_free (&str);
      BUS_SET_OOM (error);
      return NULL;
    }
  
  parser.data = str;
  parser.line_num = 1;
  parser.pos = 0;
  parser.len = _dbus_string_get_length (&parser.data);
  parser.current_section = -1;

  while (parser.pos < parser.len)
    {
      if (_dbus_string_get_byte (&parser.data, parser.pos) == '[')
	{
	  if (!parse_section_start (&parser, error))
            {
              return NULL;
            }
	}
      else if (is_blank_line (&parser) ||
	       _dbus_string_get_byte (&parser.data, parser.pos) == '#')
	parse_comment_or_blank (&parser);
      else
	{
	  if (!parse_key_value (&parser, error))
            {
              return NULL;
            }
	}
    }

  _dbus_string_free (&parser.data);

  return parser.desktop_file;
}
Exemplo n.º 16
0
/* Read a value from the given section from .INI file.  File should be opened
 * and seeking will be performed on it.  Return the malloc()ed value or NULL
 * if not present or error occurred. */
static char *read_ini_value (FILE *file, const char *section, const char *key)
{
	char *line = NULL;
	int in_section = 0;
	char *value = NULL;
	int key_len;

	if (fseek(file, 0, SEEK_SET)) {
		error ("File fseek() error: %s", strerror(errno));
		return NULL;
	}

	key_len = strlen (key);

	while ((line = read_line(file))) {
		if (line[0] == '[') {
			if (in_section) {

				/* we are outside of the interesting section */
				free (line);
				break;
			}
			else {
				char *close = strchr (line, ']');

				if (!close) {
					error ("Parse error in the INI file");
					free (line);
					break;
				}

				if (!strncasecmp(line + 1, section,
							close - line - 1))
					in_section = 1;
			}
		}
		else if (in_section && line[0] != '#' && !is_blank_line(line)) {
			char *t, *t2;

			t2 = t = strchr (line, '=');

			if (!t) {
				error ("Parse error in the INI file");
				free (line);
				break;
			}

			/* go back to the last char in the name */
			while (t2 >= t && (isblank(*t2) || *t2 == '='))
				t2--;

			if (t2 == t) {
				error ("Parse error in the INI file");
				free (line);
				break;
			}

			if (!strncasecmp(line, key,
						MAX(t2 - line + 1, key_len))) {
				value = t + 1;

				while (isblank(value[0]))
					value++;

				if (value[0] == '"') {
					char *q = strchr (value + 1, '"');

					if (!q) {
						error ("Parse error in the INI"
								" file");
						free (line);
						break;
					}

					*q = 0;
				}

				value = xstrdup (value);
				free (line);
				break;
			}
		}

		free (line);
	}

	return value;
}
Exemplo n.º 17
0
/*
** Output Wiki text while inserting the proper HTML control codes.
** The following formatting conventions are implemented:
**
**    *    Characters with special meaning to HTML are escaped.
**
**    *    Blank lines results in a paragraph break.
**
**    *    Paragraphs where the first line is indented by two or more
**         spaces are shown verbatim.  None of the following rules apply
**         to verbatim text.
**
**    *    Lines beginning with "*: " begin a bullet in a bullet list.
**
**    *    Lines beginning with "1: " begin an item in an enumerated list.
**
**    *    Paragraphs beginning with "_: " are indented.
**
**    *    Multiple colons can be used in *:, 1:, and _: for multiple
**         levels of indentation.
**
**    *    Text within _..._ is italic and text in *...* is bold.  
**         Text with in **...** or ***...*** bold with a larger font.
**
**    *    Wiki pages names (Words in initial caps) are enclosed in an
**         appropriate hyperlink.
**
**    *    Words that begin with "http:", "https:", "ftp:", or "mailto:"
**         are enclosed in an appropriate hyperlink.
**
**    *    Text of the form "#NNN" where NNN is a valid ticket number
**         is converted into a hyperlink to the corresponding ticket.
**
**    *    Text of the form "[NNN]" where NNN is a valid check-in number
**         becomes a hyperlink to the checkin.
**
**    *    {quote: XYZ} renders XYZ with all special meanings for XYZ escaped.
**
**    *    {link: URL TEXT} renders TEXT with a link to URL.  URL can be 
**         relative.
**
**    *    {linebreak} renders a linebreak.
**
**    *    {image: URL ALT} renders an in-line image from URL.  URL can be
**         relative or it can be the name of an attachment to zPageId.
**         {leftimage: URL ALT} and {rightimage: URL ALT} create wrap-around
**         images at the left or right margin.
**
**    *    {clear} skips down the page far enough to clear any wrap-around
**         images.
**
**    *    Text between <html>...</html> is interpreted as HTML.  A restricted
**         subset of tags are supported - things like forms and javascript are
**         intentionally excluded.  The initial <html> must occur at the
**         beginning of a paragraph.
*/
void output_wiki(
  const char *zText,          /* The text to be formatted */
  const char *zLinkSuffix,    /* Suffix added to hyperlinks to Wiki */
  const char *zPageId         /* Name of current page */
){
  int i, j, k;
  int aList[20];         /* See adjust_list_nesting for details */
  int inPRE = 0;
  int inB = 0;
  int inI = 0;
  int v;
  int wordStart = 1;     /* At the start of a word */
  int lineStart = 1;     /* At the start of a line */
  int paraStart = 1;     /* At the start of a paragraph */
  const char *zEndB;     /* Text used to end a run of bold */
  char **azAttach;       /* Attachments to zPageId */
  static int once = 1;
  static int nTicket, nCommit;
  if( once ){
    nTicket = atoi(db_short_query("SELECT max(tn) FROM ticket"));
    nCommit = atoi(db_short_query("SELECT max(cn) FROM chng"));
    once = 0;
  }

  i = 0;
  aList[0] = 0;
  azAttach = 0;
  zEndB = "";
  while( zText[i] ){
    char *z;
    int n;
    Markup sMarkup;
    int c = zText[i];

    /* Text between <html>...</html> is interpreted as HTML.
    */
    if( c=='<' && (n = is_html(&zText[i]))>0 ){
      put_htmlized_text(&zText, i);
      zText += 6;
      output_restricted_html(zText, n-13);
      zText += n - 6;
      i = 0;
      continue;
    }

    /* Markup may consist of special strings contained in curly braces.
    ** Examples:  "{linebreak}"  or "{quote: *:}"
    */
    if( c=='{' && is_markup(&zText[i], &sMarkup) ){
      /*
      ** Markup of the form "{linebreak}" forces a line break.
      */
      if( sMarkup.lenType==9 && strncmp(sMarkup.zType,"linebreak",9)==0 ){
        put_htmlized_text(&zText, i);
        zText += sMarkup.lenTotal;
        i = 0;
        cgi_printf("<br>\n");
        wordStart = lineStart = paraStart = 0;
        continue;
      }

      /*
      ** Markup of the form "{clear}" moves down past any left or right
      ** aligned images.
      */
      if( sMarkup.lenType==5 && strncmp(sMarkup.zType,"clear",5)==0 ){
        put_htmlized_text(&zText, i);
        zText += sMarkup.lenTotal;
        i = 0;
        cgi_printf("<br clear=\"both\">\n");
        wordStart = lineStart = paraStart = 0;
        continue;
      }

      /*
      ** Markup of the form "{quote: ABC}" writes out the text ABC exactly
      ** as it appears.  This can be used to escape special meanings 
      ** associated with ABC.
      */
      if( sMarkup.lenType==5 && strncmp(sMarkup.zType,"quote",5)==0 ){
        int n;
        put_htmlized_text(&zText, i);
        if( sMarkup.zKey==sMarkup.zArgs ){
          n = sMarkup.lenKey;
        }else{
          n = &sMarkup.zArgs[sMarkup.lenArgs] - sMarkup.zKey;
        }
        put_htmlized_text(&sMarkup.zKey, n);
        zText += sMarkup.lenTotal;
        i = 0;
        wordStart = lineStart = paraStart = 0;
        continue;
      }

      /*
      ** Markup of the form "{link: TO TEXT}" creates a hyperlink to TO.
      ** The hyperlink appears on the screen as TEXT.  TO can be a any URL,
      ** including a relative URL such as "chngview?cn=123".
      */
      if( sMarkup.lenType==4 && strncmp(sMarkup.zType,"link",4)==0 ){
        put_htmlized_text(&zText, i);
        cgi_printf("<a href=\"%.*s\">", sMarkup.lenKey, sMarkup.zKey);
        put_htmlized_text(&sMarkup.zArgs, sMarkup.lenArgs);
        cgi_printf("</a>");
        zText += sMarkup.lenTotal;
        i = 0;
        wordStart = lineStart = paraStart = 0;
        continue;
      }

      /*
      ** Markup of the form "{image: URL ALT}" creates an in-line image to
      ** URL with ALT as the alternate text.  URL can be relative (for example
      ** the URL of an attachment.
      **
      ** If the URL is the name of an attachment, then automatically
      ** convert it to the correct URL for that attachment.
      */
      if( (sMarkup.lenType==5 && strncmp(sMarkup.zType,"image",5)==0)
       || (sMarkup.lenType==9 && strncmp(sMarkup.zType,"leftimage",9)==0)
       || (sMarkup.lenType==10 && strncmp(sMarkup.zType,"rightimage",10)==0)
      ){
        char *zUrl = 0;
        const char *zAlign;
        char *zAlt = htmlize(sMarkup.zArgs, sMarkup.lenArgs);
        if( azAttach==0 && zPageId!=0 ){
          azAttach = (char **)
                     db_query("SELECT fname, atn FROM attachment "
                              "WHERE tn='%q'", zPageId);
        }
        if( azAttach ){
          int ix;
          for(ix=0; azAttach[ix]; ix+=2){
            if( strncmp(azAttach[ix],sMarkup.zKey,sMarkup.lenKey)==0 ){
              free(zUrl);
              zUrl = mprintf("attach_get/%s/%h",
                            azAttach[ix+1], azAttach[ix]);
              break;
            }
          }
        }
        if( zUrl==0 ){
          zUrl = htmlize(sMarkup.zKey, sMarkup.lenKey);
        }
        put_htmlized_text(&zText, i);
        switch( sMarkup.zType[0] ){
          case 'l': case 'L':   zAlign = " align=\"left\"";  break;
          case 'r': case 'R':   zAlign = " align=\"right\""; break;
          default:              zAlign = "";                 break;
        }
        cgi_printf("<img src=\"%s\" alt=\"%s\"%s>", zUrl, zAlt, zAlign);
        free(zUrl);
        free(zAlt);
        zText += sMarkup.lenTotal;
        i = 0;
        wordStart = lineStart = paraStart = 0;
        continue;
      }
    }

    if( paraStart ){
      put_htmlized_text(&zText, i);

      /* Blank lines at the beginning of a paragraph are ignored.
      */
      if( isspace(c) && (j = is_blank_line(&zText[i]))>0 ){
        zText += j;
        continue;
      }

      /* If the first line of a paragraph begins with a tab or with two
      ** or more spaces, then that paragraph is printed verbatim.
      */
      if( c=='\t' || (c==' ' && (zText[i+1]==' ' || zText[i+1]=='\t')) ){
        if( !inPRE ){
          if( inB ){ cgi_printf(zEndB); inB=0; }
          if( inI ){ cgi_printf("</i>"); inI=0; }
          adjust_list_nesting(aList, 0);
          cgi_printf("<pre>\n");
          inPRE = 1;
        }
      }
    } /* end if( paraStart ) */

    if( lineStart ){
      /* Blank lines in the middle of text cause a paragraph break
      */
      if( isspace(c) && (j = is_blank_line(&zText[i]))>0 ){
        put_htmlized_text(&zText, i);
        zText += j;
        if( inB ){ cgi_printf(zEndB); inB=0; }
        if( inI ){ cgi_printf("</i>"); inI=0; }
        if( inPRE ){ cgi_printf("</pre>\n"); inPRE = 0; }
        is_list_elem(zText, &k);
        if( abs(k)<aList[0] ) adjust_list_nesting(aList, k);
        if( zText[0]!=0 ){ cgi_printf("\n<p>"); }
        wordStart = lineStart = paraStart = 1;
        i = 0;
        continue;
      }
    } /* end if( lineStart ) */

    if( lineStart && !inPRE ){
      /* If we are not in verbatim text and a line begins with "*:", then
      ** generate a bullet.  Or if the line begins with "NNN:" where NNN
      ** is a number, generate an enumeration item.
      */
      if( (j = is_list_elem(&zText[i], &k))>0 ){
        put_htmlized_text(&zText, i);
        adjust_list_nesting(aList, k);
        if( zText[0]!='_' ) cgi_printf("<li>");
        zText += j;
        i = 0;
        wordStart = 1;
        lineStart = paraStart = 0;
        continue;
      }

      /* Four or more "-" characters on at the beginning of a line that
      ** contains no other text results in a horizontal rule.
      */
      if( (c=='-' || c=='=') && (j = is_horizontal_rule(&zText[i]))>0 ){
        put_htmlized_text(&zText, i);
        adjust_list_nesting(aList, 0);
        cgi_printf("<hr>\n");
        zText += j;
        if( *zText ) zText++;
        i = 0;
        lineStart = wordStart = 1;
        paraStart = 1;
        continue;
      }
    } /* end if( lineStart && !inPre ) */

    if( wordStart && !inPRE ){
      /* A wiki name at the beginning of a word which is not in verbatim
      ** text generates a hyperlink to that wiki page.
      ** 
      ** Special case: If the name is in CamelCase but ends with a "_", then
      ** suppress the "_" and do not generate the hyperlink.  This allows
      ** CamelCase words that are not wiki page names to appear in text.
      */
      if( g.okRdWiki && isupper(c) && (j = is_wiki_name(&zText[i]))>0 ){
        put_htmlized_text(&zText, i);
        cgi_printf("<a href=\"wiki?p=%.*s%s\">%.*s</a>",
            j, zText, zLinkSuffix, j, zText);
        zText += j;
        i = 0;
        wordStart = lineStart = paraStart = 0;
        continue;
      }

      /* A "_" at the beginning of a word puts us into an italic font.
      */
      if( c=='_' && !inB && !inI && font_terminator(&zText[i+1],c,1) ){
        put_htmlized_text(&zText, i);
        i = 0;
        zText++;
        cgi_printf("<i>");
        inI = 1;
        continue;
      }

      /* A "*" at the beginning of a word puts us into a bold font.
      */
      if( c=='*' && !inB && !inI && (j = count_stars(&zText[i]))>=1
              && j<=3 && font_terminator(&zText[i+j],c,j) ){
        const char *zBeginB = "";
        put_htmlized_text(&zText, i);
        i = 0;
        zText += j;
        switch( j ){
          case 1: zBeginB = "<b>";           zEndB = "</b>";             break;
          case 2: zBeginB = "<big><b>";      zEndB = "</b></big>";       break;
          case 3: zBeginB = "<big><big><b>"; zEndB = "</b></big></big>"; break;
        }
        cgi_printf(zBeginB);
        inB = j;
        continue;
      }


      /* Words that begin with "http:" or "https:" or "ftp:" or "mailto:"
      ** become hyperlinks.
      */
      if( (c=='h' || c=='f' || c=='m') && (j=is_url(&zText[i]))>0 ){
        put_htmlized_text(&zText, i);
        z = htmlize(zText, j);
        if( is_image(z, strlen(z)) ){
          cgi_printf("<img src=\"%s\" alt=\"%s\">", z, z);
        }else{
          cgi_printf("<a href=\"%s\">%s</a>", z, z);
        }
        free(z);
        zText += j;
        i = 0;
        wordStart = lineStart = paraStart = 0;
        continue;
      }

      /* If the user has read permission on tickets and a word is of the
      ** form "#NNN" where NNN is a sequence of digits, then generate a
      ** hyperlink to ticket number NNN.
      */
      if( c=='#' && g.okRead && (j = ndigit(&zText[i+1]))>0 
                 && is_eow(&zText[i+1+j],0)
                 && (v = atoi(&zText[i+1]))>0 && v<=nTicket ){
        put_htmlized_text(&zText, i);
        cgi_printf("<a href=\"tktview?tn=%d\">#%d</a>", v, v);
        zText += j;
        if( *zText ) zText++;
        i = 0;
        wordStart = lineStart = paraStart = 0;
        continue;
      }

      /* If the user has checkout permissions and a word is of the form
      ** "[NNN]" where NNN is a checkin number, then generate a hyperlink
      ** to check-in NNN.
      */
      if( c=='[' && g.okCheckout && (j = ndigit(&zText[i+1]))>0
                 && is_eow(&zText[i+j+2],0)
                 && (v = atoi(&zText[i+1]))>0 && v<=nCommit 
                 && zText[i+j+1]==']' ){
        put_htmlized_text(&zText, i);
        cgi_printf("<a href=\"chngview?cn=%d\">[%d]</a>", v, v);
        zText += j+1;
        if( *zText ) zText++;
        i  = 0;
        wordStart = lineStart = paraStart = 0;
        continue;
      }
    } /* end if( wordStart && !inPre ) */

    /* A "*" or a "_" at the end of a word takes us out of bold or
    ** italic mode.
    */
    if( inB && c=='*' && !isspace(zText[i-1]) && zText[i-1]!='*' &&
            (j = count_stars(&zText[i]))==inB && is_eow(&zText[i+j],0) ){
      inB = 0;
      put_htmlized_text(&zText, i);
      i = 0;
      zText += j;
      cgi_printf(zEndB);
      continue;
    }
    if( inI && c=='_' && !isspace(zText[i-1]) && is_eow(&zText[i+1],0) ){
      put_htmlized_text(&zText, i);
      i = 0;
      zText++;
      inI = 0;
      cgi_printf("</i>");
      continue;
    }
    if( wordStart ){
      wordStart = isspace(c) || c=='(' || c=='"';
    }else{
      wordStart = isspace(c);
    }
    lineStart = c=='\n';
    paraStart = 0;
    i++;
  }
  if( zText[0] ) cgi_printf("%h", zText);
  if( inB ) cgi_printf("%s\n",zEndB);
  if( inI ) cgi_printf("</i>\n");
  adjust_list_nesting(aList, 0);
  if( inPRE ) cgi_printf("</pre>\n");
}