home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / fontutils-0.6-base.tgz / fontutils-0.6-base.tar / fsf / fontutils / charspace / cmi.y < prev    next >
Text File  |  1992-08-17  |  8KB  |  340 lines

  1. %{
  2. /* cmi.y: parse a character metric information file, entering what we
  3.    find into the symbol table.
  4.  
  5. Copyright (C) 1992 Free Software Foundation, Inc.
  6.  
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2, or (at your option)
  10. any later version.
  11.  
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.  
  21. #include "config.h"
  22.  
  23. #include <ctype.h>
  24. #include "libfile.h"
  25. #include "varstring.h"
  26.  
  27. #include "input-cmi.h"
  28. #include "main.h"
  29. #include "symtab.h"
  30.  
  31.  
  32. static void yyerror (string);
  33. static int yylex (void);
  34. %}
  35.  
  36. %union
  37. {
  38.   real realval;
  39.   symval_type symval;
  40.   string strval;
  41. }
  42.  
  43. %token TR_CHAR TR_CHAR_WIDTH TR_CODINGSCHEME TR_DEFINE TR_FONTDIMEN TR_KERN
  44. %token <strval> T_IDENTIFIER T_STRING
  45. %token <realval> T_REAL
  46.  
  47. /* A <symval> is not a symbol, it's the value of a symbol.  */
  48. %type <symval> expr
  49.  
  50. %%
  51. statements:
  52.       /* empty */
  53.     | statements statement
  54.     ;
  55.  
  56. statement:
  57.       char
  58.         | char_width
  59.     | codingscheme
  60.         | define
  61.     | fontdimen
  62.         | kern
  63.         ;
  64.  
  65. /* The two expr's are the left and right side bearings.  We have to
  66.    preserve any existing kerns.  */
  67. char:
  68.       TR_CHAR T_IDENTIFIER expr ',' expr
  69.         { symval_type *old_sv = symtab_lookup ($2);
  70.               symval_type new_sv = symtab_char_node ($3, $5);
  71.  
  72.           if (old_sv != NULL && SYMVAL_TAG (*old_sv) == symval_char)
  73.                 CHAR_KERNS (SYMVAL_CHAR (new_sv))
  74.               = CHAR_KERNS (SYMVAL_CHAR (*old_sv));
  75.  
  76.           symtab_define ($2, new_sv);
  77.         }
  78.     ;
  79.  
  80. /* The two expr's here are the set width and the percentage of
  81.    (set width - bitmap width) to make the left side bearing.  We cheat
  82.    and use the rsb to store the width expression in the interest of not
  83.    complicating the `char_type' structure even more.  We use the symbol
  84.    tag to distinguish the different ways of defining characters.  */
  85. char_width:
  86.       TR_CHAR_WIDTH T_IDENTIFIER expr ',' expr
  87.             { symval_type *old_sv = symtab_lookup ($2);
  88.               symval_type new_sv = symtab_char_node ($5, $3);
  89.               SYMVAL_TAG (new_sv) = symval_char_width;
  90.  
  91.           if (old_sv != NULL && SYMVAL_TAG (*old_sv) == symval_char)
  92.                 CHAR_KERNS (SYMVAL_CHAR (new_sv))
  93.               = CHAR_KERNS (SYMVAL_CHAR (*old_sv));
  94.  
  95.           symtab_define ($2, new_sv);
  96.         }
  97.         ;
  98.  
  99. codingscheme:
  100.       TR_CODINGSCHEME T_STRING
  101.             { symtab_define ("codingscheme", symtab_string_node ($2)); }
  102.     ;
  103.  
  104. define:
  105.       TR_DEFINE T_IDENTIFIER expr
  106.             { symtab_define ($2, $3); }
  107.     ;
  108.  
  109. fontdimen:
  110.       TR_FONTDIMEN T_IDENTIFIER expr
  111.             { if (tfm_fontdimen_number ($2) == 0)
  112.                 WARNING1 ("%s: Not the name of a fontdimen", $2);
  113.                
  114.               symtab_define ($2, $3);
  115.             }
  116.     ;
  117.  
  118. kern:
  119.       TR_KERN T_IDENTIFIER T_IDENTIFIER expr
  120.             { symtab_define_kern ($2, $3, $4); }
  121.     ;
  122.  
  123. expr:
  124.       T_REAL
  125.             { $$ = symtab_real_node ($1); }
  126.     | T_IDENTIFIER
  127.         { $$ = symtab_string_node ($1); }
  128.         | T_REAL T_IDENTIFIER
  129.             { $$ = symtab_real_string_node ($1, $2); }
  130.     ;
  131. %%
  132.  
  133. /* Let's hope Bison will never use this value as a token code.  */
  134. #define NOT_A_TOKEN (-1)
  135.  
  136. /* Keep track of line numbers for error messages.  */
  137. static unsigned lineno = 1;
  138.  
  139. static int get_numeric_token (FILE *);
  140. static int get_word_token (FILE *);
  141. static int get_string_token (FILE *);
  142. static int token_number (string);
  143.  
  144.  
  145. /* Return the next token from `cmi_file'.  */
  146.  
  147. static int
  148. yylex (void)
  149. {
  150.   int t = NOT_A_TOKEN;
  151.   
  152.   do
  153.     {
  154.       int c = getc (cmi_file);
  155.  
  156.       /* Skip whitespace.  */
  157.       while (c != EOF && isspace (c))
  158.         {
  159.           if (c == '\n') lineno++;
  160.           c = getc (cmi_file);
  161.     }
  162.         
  163.       switch (c)
  164.         {
  165.         case EOF: 
  166.           t = 0;
  167.           lineno = 1; /* For the next file.  */
  168.           break;
  169.  
  170.         /* Comments begin with % and go to the end of the line.  */
  171.         case '%': 
  172.           while ((c = getc (cmi_file)) != '\n' && c != EOF)
  173.             ;
  174.           if (c == '\n') lineno++;
  175.           break;
  176.  
  177.         case '0': case '1': case '2': case '3': case '4':
  178.         case '5': case '6': case '7': case '8': case '9':
  179.         case '.': case '-': case '+':
  180.           ungetc (c, cmi_file);
  181.           t = get_numeric_token (cmi_file);
  182.           break;
  183.  
  184.         case '"':
  185.           t = get_string_token (cmi_file);
  186.           break;
  187.  
  188.         case ',':
  189.           t = c;
  190.           break;
  191.  
  192.         default:
  193.           ungetc (c, cmi_file);
  194.           t = get_word_token (cmi_file);
  195.           break;
  196.         }
  197.     }
  198.   while (t == NOT_A_TOKEN);
  199.  
  200.   return t;
  201. }
  202.  
  203.  
  204. /* Assume we've opened the file with `libfile_start'.  We've been
  205.    keeping track of the line numbers ourselves, though.  */
  206.  
  207. static void
  208. yyerror (string s)
  209. {
  210.   fprintf (stderr, "%s:%u: %s\n", libfilename (), lineno, s);
  211. }
  212.  
  213. /* Read a numeric decimal constant from the file F.  Always return T_REAL
  214.    and set yylval.realval.  */
  215.  
  216. static int
  217. get_numeric_token (FILE *f)
  218. {
  219.   variable_string vs = vs_init ();
  220.   int c = getc (f);
  221.   
  222.   /* Look for a sign.  */
  223.   if (c == '+' || c == '-')
  224.     {
  225.       vs_append_char (&vs, c);
  226.       c = getc (f);
  227.     }
  228.  
  229.   /* Collect leading digits.  */
  230.   while (isdigit (c))
  231.     {
  232.       vs_append_char (&vs, c);
  233.       c = getc (f);
  234.     }
  235.   
  236.   /* If we're at a decimal point, keep going.  */
  237.   if (c == '.')
  238.     {
  239.       /* Collect more digits.  Append first, so we grab the `.'.  */
  240.       do
  241.         {
  242.           vs_append_char (&vs, c);
  243.           c = getc (f);
  244.         }
  245.       while (isdigit (c));
  246.       
  247.       /* Don't bother to allow `e<exponent>' at the end.  */
  248.     }
  249.   
  250.   /* Add the terminating null and convert the string to a number.  */
  251.   vs_append_char (&vs, 0);
  252.   
  253.   yylval.realval = atof (VS_CHARS (vs));
  254.   vs_free (&vs);
  255.   
  256.   return T_REAL;
  257. }
  258.  
  259. /* Read a string constant from the file F.  We make no provision for
  260.    quoting " characters; the string just consists of everything from one
  261.    " to the next.  We return T_STRING and set yylval.strval.  */
  262.  
  263. static int
  264. get_string_token (FILE *f)
  265. {
  266.   int c;
  267.   variable_string vs = vs_init ();
  268.  
  269.   while ((c = getc (f)) != EOF && c != '"')
  270.     vs_append_char (&vs, c);
  271.  
  272.   if (c == EOF)
  273.     FATAL ("CMI file ended in the midst of a string");
  274.  
  275.   /* Add the terminating null.  */
  276.   vs_append_char (&vs, 0);
  277.  
  278.   yylval.strval = VS_CHARS (vs);
  279.   
  280.   return T_STRING;
  281. }
  282.  
  283. /* Return the Bison-defined value for the token equal to the
  284.    next (space-delimited) identifier in the file F.  That is, if it's a
  285.    reserved word return the corresponding value TR_..., else return
  286.    T_IDENTIFIER.  */
  287.    
  288. static int
  289. get_word_token (FILE *f)
  290. {
  291.   int c, t;
  292.   variable_string word = vs_init ();
  293.  
  294.   while ((c = getc (f)) != EOF && !isspace (c))
  295.     vs_append_char (&word, c);
  296.   
  297.   if (c != EOF)
  298.     ungetc (c, f);
  299.  
  300.   /* Add the terminating null.  */
  301.   vs_append_char (&word, 0);
  302.  
  303.   t = token_number (VS_CHARS (word));
  304.   
  305.   /* We don't need the characters in the identifier again.  */
  306.   vs_free (&word);
  307.   
  308.   return t;
  309. }
  310.  
  311.  
  312. /* Return the token code corresponding to the word STR.  If STR is not
  313.    one of the reserved words, return T_IDENTIFIER.  */
  314.  
  315. static int
  316. token_number (string word)
  317. {
  318.   int t;
  319.   
  320.   if (STREQ (word, "char"))
  321.     t = TR_CHAR;
  322.   else if (STREQ (word, "char-width"))
  323.     t = TR_CHAR_WIDTH;
  324.   else if (STREQ (word, "codingscheme"))
  325.     t = TR_CODINGSCHEME;
  326.   else if (STREQ (word, "define"))
  327.     t = TR_DEFINE;
  328.   else if (STREQ (word, "fontdimen"))
  329.     t = TR_FONTDIMEN;
  330.   else if (STREQ (word, "kern"))
  331.     t = TR_KERN;
  332.   else
  333.     {
  334.       t = T_IDENTIFIER;
  335.       yylval.strval = xstrdup (word);
  336.     }
  337.  
  338.   return t;
  339. }
  340.