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 / bzrto / ccc.y < prev    next >
Text File  |  1992-10-11  |  11KB  |  392 lines

  1. %{
  2. /* ccc.y -- Bison and C code to parse a CCC file.
  3.  
  4. Copyright (C) 1992 Free Software Foundation, Inc.
  5.  
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #include "config.h"
  21.  
  22. #include <ctype.h>
  23. #include "encoding.h"
  24. #include "filename.h"
  25. #include "varstring.h"
  26.  
  27. #include "char.h"
  28. #include "input-ccc.h"
  29. #include "main.h"
  30.  
  31.  
  32. /* Set the return value RET to either the dimension DIM, if NAME is a
  33.    valid character name, or an invalid sentinel.  Used in the
  34.    `unit_of_measure' rule.  */
  35. #define DO_CHAR_DIMEN(ret, dimen, name)                    \
  36.   if (char_known_p (name))                        \
  37.     ret = dimen_init (dimen);                        \
  38.   else                                    \
  39.     DIMEN_VALID (ret) = false
  40.  
  41.  
  42. static ccc_cmd_list_type *append_cmd (ccc_cmd_list_type *, ccc_cmd_type);
  43. static ccc_cmd_list_type *init_cmd_list (ccc_cmd_type);
  44. static boolean char_known_p (charname_type);
  45. static dimen_type dimen_init (real);
  46. static int token_number (string);
  47. static void yyerror (string);
  48. static int yylex ();
  49. %}
  50.  
  51. %union
  52. {
  53.   int int_val;
  54.   real real_val;
  55.   dimen_type dimen_val;
  56.   charname_type charname_val;
  57.   ccc_cmd_type cmd_val;
  58.   ccc_cmd_list_type *cmd_list_val;
  59. }
  60. %token <int_val> TR_DEFINE TR_END TR_SETCHAR TR_SETCHARBB TR_HMOVE TR_VMOVE
  61. %token <real_val> T_REAL
  62. %token <dimen_val> TR_PT TR_XHEIGHT TR_CAPHEIGHT TR_FONTDEPTH
  63. %token <dimen_val> TR_DESIGNSIZE TR_EM TR_HEIGHT TR_WIDTH TR_DEPTH
  64. %token <dimen_val> TR_BBHEIGHT TR_BBWIDTH
  65. %token <charname_val> T_CHARNAME
  66. %type <cmd_list_val> statements
  67. %type <cmd_val> statement
  68. %type <int_val> set_cmd move_cmd
  69. %type <dimen_val> dimension unit_of_measure
  70.  
  71. %%
  72. chardefs:      /* empty  */
  73.         | chardefs chardef
  74.         ;
  75.  
  76. chardef:    TR_DEFINE T_CHARNAME '=' statements TR_END
  77.                   { 
  78.                     /* It doesn't hurt to define a character that won't
  79.                        be used, so we don't call `char_known_p' here.  */
  80.                     ccc_chars[$2.code] = $4;
  81.                   }
  82.         ;
  83.  
  84. statements:      statement
  85.             { $$ = init_cmd_list ($1); }
  86.         | statements statement
  87.             { $$ = append_cmd ($1, $2); }
  88.         ;
  89.  
  90. statement:      set_cmd '(' T_CHARNAME ')'    
  91.             {
  92.                       CCC_VALID ($$) = char_known_p ($3);
  93.                       if (CCC_VALID ($$))
  94.                         {
  95.                           CCC_OPCODE ($$) = $1;
  96.                       CCC_CHARCODE ($$) = $3.code;
  97.                         }
  98.                     }
  99.         | move_cmd dimension
  100.             {
  101.                       CCC_VALID ($$) = DIMEN_VALID ($2);
  102.                       if (CCC_VALID ($$))
  103.                         {
  104.                           CCC_OPCODE ($$) = $1;
  105.                     CCC_DIMEN ($$) = $2;
  106.                         }
  107.                     }
  108.         ;
  109.  
  110. set_cmd:    TR_SETCHAR | TR_SETCHARBB ;
  111.         
  112. move_cmd:    TR_HMOVE | TR_VMOVE ;
  113.  
  114. dimension:       unit_of_measure
  115.             { $$ = $1; }
  116.         | T_REAL unit_of_measure    
  117.             {
  118.                       DIMEN_AMOUNT ($$) = $1 * DIMEN_AMOUNT ($2);
  119.               DIMEN_ABSOLUTE ($$) = DIMEN_ABSOLUTE ($2);
  120.                       DIMEN_VALID ($$) = DIMEN_VALID ($2);
  121.             }
  122.         ;
  123.  
  124. unit_of_measure:  TR_PT                
  125.             {
  126.                       $$ = dimen_init (1);
  127.                       DIMEN_ABSOLUTE ($$) = true;
  128.                     }
  129.                 | TR_CAPHEIGHT  { $$ = dimen_init (ccc_fontinfo.cap_height); }
  130.                 | TR_DESIGNSIZE { $$ = dimen_init (ccc_fontinfo.design_size); }
  131.                 | TR_EM         { $$ = dimen_init (ccc_fontinfo.em); }
  132.                 | TR_FONTDEPTH  { $$ = dimen_init (ccc_fontinfo.font_depth); }
  133.                 | TR_XHEIGHT    { $$ = dimen_init (ccc_fontinfo.xheight); }
  134.                 | TR_HEIGHT '(' T_CHARNAME ')'
  135.                     {
  136.                       DO_CHAR_DIMEN ($$, CHAR_HEIGHT (*chars[$3.code]), $3);
  137.                     }
  138.         | TR_WIDTH '(' T_CHARNAME ')'
  139.                     {
  140.                       DO_CHAR_DIMEN ($$, CHAR_SET_WIDTH (*chars[$3.code]), $3);
  141.                     }
  142.         | TR_DEPTH '(' T_CHARNAME ')'
  143.                     {
  144.                       DO_CHAR_DIMEN ($$, CHAR_DEPTH (*chars[$3.code]), $3);
  145.                     }
  146.                 | TR_BBHEIGHT '(' T_CHARNAME ')'    
  147.                     {
  148.                       DO_CHAR_DIMEN
  149.                         ($$, BB_HEIGHT (CHAR_BB (*chars[$3.code])), $3);
  150.                     }
  151.                 | TR_BBWIDTH '(' T_CHARNAME ')'    
  152.                     {
  153.                       DO_CHAR_DIMEN
  154.                         ($$, BB_WIDTH (CHAR_BB (*chars[$3.code])), $3);
  155.                     }
  156.         ;
  157. %%
  158.  
  159. /* Let's hope Bison will never use this value as a token code.  */
  160. #define NOT_A_TOKEN (-1)
  161.  
  162. /* Keep track of line numbers for error messages.  */
  163. static unsigned lineno = 1;
  164.  
  165. static int get_word_token (FILE *);
  166.  
  167.  
  168. /* We don't want to use the libfile routines for CCC files, since
  169.    there's no reason for them to be in the system data directories.  So
  170.    we must have our own error routines.  */
  171. #define CCC_WARN1(fmt, e1) \
  172.   fprintf (stderr, "%s:%u: " fmt ".\n", ccc_filename, lineno, e1)
  173. #define CCC_WARN2(fmt, e1, e2) \
  174.   fprintf (stderr, "%s:%u: " fmt ".\n", ccc_filename, lineno, e1, e2)
  175.  
  176. static void
  177. yyerror (string s)
  178. {
  179.   fprintf (stderr, "%s:%u: %s\n", ccc_filename, lineno, s);
  180. }
  181.  
  182. /* Return the next token in `ccc_file'.  */
  183.  
  184. static int
  185. yylex (void)
  186. {
  187.   int t = NOT_A_TOKEN;
  188.  
  189.   do
  190.     {
  191.       int c = getc (ccc_file);
  192.  
  193.       /* Skip whitespace.  */
  194.       while (c != EOF && isspace (c))
  195.         {
  196.           if (c == '\n') lineno++;
  197.           c = getc (ccc_file);
  198.     }
  199.         
  200.       switch (c)
  201.         {
  202.         case EOF:
  203.           t = 0;
  204.           lineno = 1; /* For the next file (if we ever allow one).  */
  205.           break;
  206.  
  207.         /* Comments begin with % and go to the end of the line.  */
  208.         case '%':
  209.           while ((c = getc (ccc_file)) != '\n' && c != EOF)
  210.             ;
  211.           if (c == '\n') lineno++;
  212.           break;
  213.  
  214.         case '0': case '1': case '2': case '3': case '4':
  215.     case '5': case '6': case '7': case '8': case '9':
  216.     case '.': case '-': case '+':
  217.           ungetc (c, ccc_file);
  218.           fscanf (ccc_file, "%lf", &yylval.real_val);
  219.           t = T_REAL;
  220.           break;
  221.  
  222.         default:
  223.           if (isalpha (c))
  224.             {
  225.               ungetc (c, ccc_file);
  226.               t = get_word_token (ccc_file);
  227.             }
  228.           else
  229.             t = c;
  230.           break;
  231.         }
  232.     }
  233.   while (t == NOT_A_TOKEN);
  234.  
  235.   return t;
  236. }
  237.  
  238. /* Return either the Bison-defined value for the token equal to the
  239.    next nonalpha-delimited word in F, or if the word is
  240.    the encoding name of a character, return T_CHARNAME.
  241.  
  242.    Sets the global `yylval.charname_val' to the encoding number of a
  243.    character encoding name, if the word is an encoding name.
  244.  
  245.    Assumes the first character is valid (i.e., alpha).  */
  246.  
  247. static int
  248. get_word_token (FILE *f)
  249. {
  250.   int token_value, encoding_value;
  251.   int c;
  252.   variable_string word = vs_init ();
  253.  
  254.   while ((c = getc (f)) != EOF && isalpha (c))
  255.     vs_append_char (&word, c);
  256.  
  257.   if (c != EOF)
  258.     ungetc (c, f);
  259.  
  260.   /* Add the terminating null.  */
  261.   vs_append_char (&word, 0);
  262.  
  263.   token_value = token_number (VS_CHARS (word));
  264.   encoding_value = encoding_number (encoding_info, VS_CHARS (word));
  265.  
  266.   /* If the identifier is neither a reserved word nor a known character
  267.      name, return T_CHARNAME and call it character zero.  */
  268.   if (token_value == NOT_A_TOKEN && encoding_value == -1)
  269.     {
  270.       CCC_WARN1 ("Unknown identifier `%s'", VS_CHARS (word));
  271.       encoding_value = 0;
  272.     }
  273.  
  274.   if (token_value != NOT_A_TOKEN && encoding_value != -1)
  275.     CCC_WARN1 ("`%s' both a reserved word and a character name",
  276.            VS_CHARS (word));
  277.  
  278.   if (token_value == NOT_A_TOKEN)
  279.     {
  280.       yylval.charname_val.code = encoding_value;
  281.       yylval.charname_val.name = VS_CHARS (word);
  282.       token_value = T_CHARNAME;
  283.     }
  284.   else
  285.     {
  286.       yylval.int_val = token_value;
  287.       vs_free (&word);
  288.     }
  289.   
  290.   return token_value;
  291. }
  292.  
  293.  
  294. /* If WORD is a reserved word, return the corresponding token code;
  295.    otherwise, return `NOT_A_TOKEN'.  */
  296.  
  297. static int
  298. token_number (string word)
  299. {
  300.   if (STREQ (word, "define"))        return TR_DEFINE;
  301.   else if (STREQ (word, "bbheight"))    return TR_BBWIDTH;
  302.   else if (STREQ (word, "bbwidth"))    return TR_BBWIDTH;
  303.   else if (STREQ (word, "capheight"))    return TR_CAPHEIGHT;
  304.   else if (STREQ (word, "depth"))    return TR_DEPTH;
  305.   else if (STREQ (word, "designsize"))    return TR_DESIGNSIZE;
  306.   else if (STREQ (word, "em"))        return TR_EM;
  307.   else if (STREQ (word, "end"))        return TR_END;
  308.   else if (STREQ (word, "fontdepth"))    return TR_FONTDEPTH;
  309.   else if (STREQ (word, "height"))    return TR_HEIGHT;
  310.   else if (STREQ (word, "hmove"))    return TR_HMOVE;
  311.   else if (STREQ (word, "pt"))        return TR_PT;
  312.   else if (STREQ (word, "setchar"))    return TR_SETCHAR;
  313.   else if (STREQ (word, "setcharbb"))    return TR_SETCHARBB;
  314.   else if (STREQ (word, "vmove"))    return TR_VMOVE;
  315.   else if (STREQ (word, "width"))    return TR_WIDTH;
  316.   else if (STREQ (word, "xheight"))    return TR_XHEIGHT;
  317.   else
  318.     return NOT_A_TOKEN;
  319. }
  320.  
  321. /* Return a new list of CCC commands, initialized to contain CMD.  If
  322.    CMD is invalid, return NULL.  */
  323.  
  324. static ccc_cmd_list_type *
  325. init_cmd_list (ccc_cmd_type cmd)
  326. {
  327.   ccc_cmd_list_type *l;
  328.   
  329.   if (CCC_VALID (cmd))
  330.     {
  331.       l = XTALLOC1 (ccc_cmd_list_type);
  332.       *l = list_init ();
  333.       l = append_cmd (l, cmd);
  334.     }
  335.   else
  336.     l = NULL;
  337.  
  338.   return l;
  339. }
  340.  
  341.  
  342. /* Add CMD to CMD_LIST and return CMD_LIST.  If CMD is invalid, don't
  343.    add it.  If CMD_LIST is NULL, initialize it.  */
  344.  
  345. static ccc_cmd_list_type *
  346. append_cmd (ccc_cmd_list_type *cmd_list, ccc_cmd_type cmd)
  347. {
  348.   if (CCC_VALID (cmd))
  349.     {
  350.       if (cmd_list == NULL)
  351.         cmd_list = init_cmd_list (cmd);
  352.       else
  353.         {
  354.           address new_element_addr = LIST_TAPPEND (cmd_list, ccc_cmd_type);
  355.           *(ccc_cmd_type *) new_element_addr = cmd;
  356.         }
  357.     }
  358.  
  359.   return cmd_list;
  360. }
  361.  
  362.  
  363. /* Return an initialized dimension.  */
  364.  
  365. static dimen_type
  366. dimen_init (real amount)
  367. {
  368.   dimen_type d;
  369.   
  370.   DIMEN_VALID (d) = true;
  371.   DIMEN_ABSOLUTE (d) = false;
  372.   DIMEN_AMOUNT (d) = amount;
  373.   
  374.   return d;
  375. }
  376.  
  377. /* Return true if the character C is defined; otherwise, give a warning.  */
  378.  
  379. static boolean
  380. char_known_p (charname_type c)
  381. {
  382.   boolean ok = false;
  383.   
  384.   if (chars[c.code] == NULL)
  385.     CCC_WARN2 ("Character %d (%s) undefined", c.code, c.name);
  386.  
  387.   else
  388.     ok = true;
  389.   
  390.   return ok;
  391. }
  392.