/* cee.ft - Felix Gaertner's first pretzel formatted token file for simple C
 *
 * target formatter: LaTeX
 *
 * $Id: cee.ft,v 1.3 1996/12/16 19:28:54 gaertner Exp $
 *
 * History at end.
 */

ALPH	[a-zA-Z]
ALPHNUM	[a-zA-Z0-9_]
ALPHNUMDOT	[a-zA-Z0-9\.]
DECDIGIT	[0-9]
HEXDIGIT	[0-9A-Fa-f]
EXP		([eE][+-]?[0-9]+)

%{

#include<assert.h>

  // forward declaration of a function that replaces `_'
  // with `\_' in a copy of s

char* escaped_underlines(char* s);

%}

%%

	// unary or binary operators for math mode

"+"		|
"-"		UNORBINOP
"*"		UNORBINOP	{ "\\hbox{$\\ast$}" }
"/"		|
"<"		|
"="		|
">"		|
"."		|
"|"		BINOP
"%"		BINOP		{ "\\hbox{\\tt\\%}" }
"?"		QUESTION
"!"		UNOP
"~"		UNOP		{ "\\hbox{\\verb+~+}" }
"&"		UNORBINOP	{ "\\&" }
","		COMMA		{ "\\mathout, "}

"("		LPAR
"["		LBRACK
")"		RPAR
"]"		RBRACK
"{"		LBRACE		{ "\\{" }
"}"		RBRACE		{ "\\}" }
";"		SEMI
":"		COLON

"++"		|
"--"		UNOP		{ "\\mbox{\\tt" ** "}" }

	// binary operators for math mode

"!="		BINOP		{ "\\neq" }
"<="		BINOP		{ "\\leq" }
">="		BINOP		{ "\\geq" }
"=="		BINOP		{ "\\equiv" }
"&&"		BINOP		{ "\\land" }
"||"		BINOP		{ "\\lor" }
"->"		BINOP		{ "\\to" }
">>"		BINOP           { "\\gg" }
"<<"		BINOP           { "\\ll" }

"+="		BINOP		{ "\\hbox{{\\tt +}=}" }
"-="		BINOP		{ "\\hbox{{\\tt -}=}" }
"*="		BINOP		{ "\\hbox{{\\tt *}=}" }
"/="		BINOP		{ "\\hbox{{\\tt /}=}" }


	// preprocessor directives:

"#"		INSERT		{ "\\#" }


"#include"	|
"#ifdef"	|
"#ifndef"	|
"#undef"	|
"#elif"		|
"#error"	|
"#pragma"	|
"#endif"	LPROC		{ "{\\bf \\" + ** + "}" }

"this"		|
"NULL"	        NUMBER		{ "{\\tt " ** "}" }

	// reserved words:

  // types and alike:

"auto"		|
"char"		|
"const"		|
"double"	|
"extern"	|
"FILE"		|
"float"		|
"int"		|
"long"		|
"register"	|
"short"		|
"static"	|
"unsigned"	|
"volatile"	|
"void"		|
"friend"	|
"inline"	|
"virtual"	|
"signed"	INT_LIKE	{ "{\\bf " + ** + "}" }

"enum"		|
"union"		|
"class"		|
"struct"	STRUCT_LIKE	{ "{\\bf " + ** + "}" }

"delete"	|
"new"		|
"operator"	|
"sizeof"	SIZEOF_LIKE	{ "{\\bf " + ** + "}" }

"define"	DEFINE_LIKE	{ "{\\bf " + ** + "}" }

  // case statement handling:

"break"		|
"case"		|
"continue"	|
"default"	|
"private"	|
"protected"	|
"public"	|
"template"	|
"return"	CASE_LIKE	{ "{\\bf " + ** + "}" }

"switch"	IF_LIKE		{ "{\\bf " + ** + "}" }



  // control structures:

"do"		DO_LIKE		{ "{\\bf " + ** + "}" }
"else"		ELSE_LIKE	{ "{\\bf " + ** + "}" }
"for"		|
"if"		|
"while"		IF_LIKE		{ "{\\bf " + ** + "}" }

  // type constructors

"typedef"	TYPEDEF_LIKE	{ "{\\bf " + ** + "}" }


  // comments:

"/*"[^\*]*"*/"	INSERT

  // what's this?

"<"{ALPHNUMDOT}+">" LPROC   { "\n@literal \\verb|" ** "|\n" }

  // identifiers and constants:

[1-9]{DECDIGIT}*[uU]?[lL]?		NUMBER
0{DECDIGIT}*[uU]?[lL]?		NUMBER		// octal
0[xX]{HEXDIGIT}+[uU]?[lL]?		NUMBER		// hex
{DECDIGIT}+"."{DECDIGIT}*{EXP}?[fdFD]?		|
"."{DECDIGIT}*{EXP}?[fdFD]?			|
{DECDIGIT}+{EXP}?[fdFD]?	|
{EXP}[fdFD]?			NUMBER

  // font is added in formatted grammar

{ALPH}{ALPHNUM}*	ID	{ [create(escaped_underlines(yytext))] }

  // strings  (relies upon that ^^K is active character in TeX)

'([^']|\\')*'		|
\"([^\"]|\\\")*\"	STRING	{ "\\verb*\013" ** "\013" }



[\ \t\n]		// gobble up whitespace

.			// forget all non-standard characters
			// somehow some strange characters are
			// sent to pretzel (TODO). forget them.

%%

  // escaped_underines replaces every occurrence of `_' by
  // the two characters `\_' in a copy of the string pointed to
  // by s
  //
  // the implementation first counts the number of underlines in
  // the string s and allocates new memory for the string. It then
  // copies the string byte after byte into the new place and
  // takes care to insert a `\' before any underline.
  //
  // this is a bit dirty as we don't have a chance to free the
  // allocated space later on, but it's still better than messing
  // around with yytext. To minimize the amount of memory I have
  // added a test whether copying is needed or not.

char* escaped_underlines(char* s)
{
    char* tmp = s;
    int number_of_ul = 0;
    int left = 0;   // s[left] is the next char to copy
    int right = 0;  // place s[left] in tmp[right]

    // fprintf(stderr, "call of escaped_underlines\n");

    // count underlines in s
    while (*tmp != 0) {
	if (*tmp == '_') number_of_ul++;
	tmp++;
    }

    // fprintf(stderr, "escaped_underlines: Number of ul's in %s is %d\n", s, number_of_ul);

    if (number_of_ul == 0) {
      tmp = s;  // skip copying
    } else {

      tmp = new char[strlen(s) + number_of_ul + 1];
      assert(tmp!=NULL);

      // now start to copy
      while (s[left] != 0) { // should be `!= NULL', shouldn,t it, but
                             // some compilers choke on it
          if (s[left] == '_') {
              tmp[right] = '\\';
              right++;
          }
          tmp[right] = s[left];
          left++; right++;
      }
      tmp[right] = s[left];  /* terminate string */
    }

    // fprintf(stderr, "escaped_underlines: in: %s, out: %s\n", s, tmp);

    return(tmp);
}


/*
 * $Log: cee.ft,v $
 * Revision 1.3  1996/12/16 19:28:54  gaertner
 * c without noweb
 *
 * Revision 1.1  1996/12/16 19:02:09  gaertner
 * Initial revision
 *
 * Revision 1.1  1996/03/28  11:28:32  gaertner
 * Initial revision
 *
 * Revision 1.2  1996/03/26  14:36:11  gaertner
 * Getting really ugly now. Maybe I should start with an existing grammar.
 *
 * Revision 1.1  1996/03/22  11:25:26  gaertner
 * Initial revision
 *
 */
