⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 language.l

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 L
字号:
%{

/*
 *  lang_scan.l - Foreign language lexical scanner for Waterloo TCP/IP
 *
 *  Gisle Vanem 1997
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <setjmp.h>

#include "wattcp.h"
#include "strings.h"
#include "sock_ini.h"
#include "misc.h"
#include "crc.h"

#if defined(USE_LANGUAGE)

#if defined(TEST_PROG)
  #include <conio.h>
  #define INCLINE()   fprintf (stderr, "<line %lu>\n", lang.line++)
  #define DEBUG(s,a)  fprintf (stderr, s, a)
#else
  #define INCLINE()   lang.line++
  #define DEBUG(s,a)  ((void)0)
#endif

#define BUF_SIZE    500

static int   yylex      (void);
static void  AddChar    (int ch);
static void  AddDecimal (const char *buf);
static void  AddHexcode (const char *buf);
static void  AddOctal   (const char *buf);
static void  AddEntry   (void);
static void  Abort      (const char *s1, const char *s2);
static void  error      (const char *err);

static char    buf [BUF_SIZE];
static char   *ptr       = NULL;
static char   *end       = buf+BUF_SIZE;
static int     line_cont = 0;
static DWORD   crc_ref   = 0;
static DWORD   do_ref    = 1;
static jmp_buf bail_out;

struct Node {
       DWORD        crc;
       char        *string;
       struct Node *next;
     };

struct Elem {
       DWORD  crc;
       char  *string;
     };

static struct Language {
       struct Node *list;
       struct Elem *array;
       char         prefix[4];     /* "en:"         */
       DWORD        entries;
       DWORD        line;
     } lang = {
       NULL, NULL, "en",
       0L, 0L
     };

/*---------------------------------------------------------------------*/

%}

/*
 * Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
 * as well as gratuitiously global symbol names, so we can have multiple
 * yacc generated parsers in the same program.  Note that these are only
 * the variables produced by yacc.  If other parser generators (bison,
 * byacc, etc) produce additional global names that conflict at link time,
 * then those parser generators need to be fixed instead of adding those
 * names to this list.
 */

%option prefix = "watt"

%x STRING EO_LINE PREFIX

NL                   \r?\n
WS                   [\t ]+
HEX                  (x[0-9a-fA-F]{1,2})
OCTAL                (0[0-7]{1,3})
DECIMAL              ([0-9]{1,3})
LANG                 "de"|"no"|"sv"

/*
 *  Possible LANG codes are according to ISO 3166
 *
 *  Ref. ftp://ftp.informatik.uni-erlangen.de/pub/doc/ISO/
 *
 *  aa Afar          ba Bashkir           ca Catalan
 *  ab Abkhazian     be Byelorussian      co Corsican
 *  af Afrikaans     bg Bulgarian         cs Czech
 *  am Amharic       bh Bihari            cy Welsh
 *  ar Arabic        bi Bislama
 *  as Assamese      bn Bengali; Bangla   da Danish
 *  ay Aymara        bo Tibetan           de German
 *  az Azerbaijani   br Breton            dz Bhutani
 *
 *  el Greek         fa Persian           ga Irish
 *  en English       fi Finnish           gd Scots Gaelic
 *  eo Esperanto     fj Fiji              gl Galician
 *  es Spanish       fo Faroese           gn Guarani
 *  et Estonian      fr French            gu Gujarati
 *  eu Basque        fy Frisian
 *
 *  ha Hausa         ia Interlingua       ja Japanese
 *  he Hebrew        id Indonesian        jw Javanese
 *  hi Hindi         ie Interlingue
 *  hr Croatian      ik Inupiak
 *  hu Hungarian     is Icelandic
 *  hy Armenian      it Italian
 *                   iu Inuktitut
 *  ka Georgian                           mg Malagasy
 *  kk Kazakh        la Latin             mi Maori
 *  kl Greenlandic   ln Lingala           mk Macedonian
 *  km Cambodian     lo Laothian          ml Malayalam
 *  kn Kannada       lt Lithuanian        mn Mongolian
 *  ko Korean        lv Latvian, Lettish  mo Moldavian
 *  ks Kashmiri                           mr Marathi
 *  ku Kurdish                            ms Malay
 *  ky Kirghiz                            mt Maltese
 *                                        my Burmese
 *  na Nauru         oc Occitan
 *  ne Nepali        om (Afan) Oromo      pa Punjabi
 *  nl Dutch         or Oriya             pl Polish
 *  no Norwegian                          ps Pashto, Pushto
 *                                        pt Portuguese
 *  qu Quechua
 *
 *  rm Rhaeto-Romance  sa Sanskrit        ta Tamil
 *  rn Kirundi         sd Sindhi          te Telugu
 *  ro Romanian        sg Sangro          tg Tajik
 *  ru Russian         sh Serbo-Croatian  th Thai
 *  rw Kinyarwanda     si Sinhalese       ti Tigrinya
 *                     sk Slovak          tk Turkmen
 *  ug Uighur          sl Slovenian       tl Tagalog
 *  uk Ukrainian ??    sm Samoan          tn Setswana
 *  ur Urdu            sn Shona           to Tonga
 *  uz Uzbek           so Somali          tr Turkish
 *                     sq Albanian        ts Tsonga
 *  vi Vietnamese      sr Serbian         tt Tatar
 *  vo Volapuk         ss Siswati         tw Twi
 *                     st Sesotho
 *  wo Wolof           su Sundanese
 *                     sv Swedish
 *  xh Xhosa           sw Swahili
 *
 *  yi Yiddish (formerly ji)
 *  yo Yoruba
 *
 *  za Zhuang
 *  zh Chinese
 *  zu Zulu
 */

%%

<INITIAL>{                               /* get reference string */
        {WS}         /* discard */
        [#;].*{NL}   lang.line++;
        {NL}         INCLINE();
        \"           {
                       if (!line_cont)
                          ptr = buf;
                       BEGIN (STRING);
                     }
        .            {
                       unput (yytext[0]);
                       BEGIN (PREFIX);
                     }
}

<STRING>{
        \"           line_cont = 0; BEGIN (EO_LINE);
        \\a          AddChar ('\7');
        \\b          AddChar ('\b');
        \\t          AddChar ('\t');
        \\f          AddChar ('\f');
        \\e          AddChar (27);
        \\r          AddChar ('\r');
        \\n          AddChar ('\n');
        \\\\         AddChar ('\\');
        \\\"         AddChar ('\"');
        \\{HEX}      AddHexcode (yytext+2);
        \\{OCTAL}    AddOctal   (yytext+1);
        \\{DECIMAL}  AddDecimal (yytext+1);
        \\.          Abort ("Unknown ESC code: ", yytext);
        {NL}         Abort ("unterminated line", NULL);
        .            AddChar (yytext[0]);
        <<EOF>>      Abort ("Unexpected end-of-file", NULL);
}

<EO_LINE>{
        \\\\         {
                       line_cont = 1;
                       BEGIN (INITIAL);
                     }
        {NL}         {
                       *ptr = 0;
                       ptr  = NULL;
                       if (do_ref)
                            crc_ref = watt_crc_bytes (buf, strlen(buf));
                       else AddEntry();
                       INCLINE();
                       BEGIN (INITIAL);
                     }
        .            /* discard */
        <<EOF>>      Abort ("Unexpected end-of-string", NULL);
}

<PREFIX>{
        {LANG}":"    {
                       DEBUG ("lang `%s',\n", yytext);
                       if (!strncmp(yytext,lang.prefix,3))
                       {
                         ptr    = buf;
                         do_ref = 0;
                       }
                       else
                       {
                         ptr    = NULL;
                         do_ref = 1;
                       }
                       BEGIN (INITIAL);
                     }
        [#;].*{NL}   lang.line++;
        {NL}         INCLINE();
        .            Abort ("unknown language prefix: ", yytext);
}

%%

/*---------------------------------------------------------------------*/

/*
 *  terminate yylex() when EOF reached
 */
int yywrap (void)
{
  return (1);
}

/*
 *  Add a character to output buffer
 */
static void AddChar (int ch)
{
  if (ptr)
  {
    DEBUG ("%c", ch);
    *ptr++ = ch;
    if (ptr >= end)
       error ("string too large");
  }
}

/*
 *  Add a decimal code to output buffer
 */
static void AddDecimal (const char *buf)
{
  if (ptr)
  {
    int dec;
    sscanf (buf, "%d", &dec);
    DEBUG ("dec <%d>", dec);
    *ptr++ = dec;
    if (dec > 255)
       Abort ("Illegal decimal", NULL);
    if (ptr >= end)
       error ("string too large");
  }
}

/*
 *  Add a hex code to output buffer
 */
static void AddHexcode (const char *buf)
{
  if (ptr)
  {
    WORD hex;
    sscanf (buf, "%hx", &hex);
    DEBUG ("hex <%X>", hex);
    *ptr++ = hex;
    if (ptr >= end)
       error ("string too large");
  }
}

/*
 *  Add an octal code to output buffer
 */
static void AddOctal (const char *buf)
{
  if (ptr)
  {
    unsigned oct;
    sscanf (buf, "%o", &oct);
    DEBUG ("oct <%o>", oct);
    *ptr++ = oct;
    if (ptr >= end)
       error ("string too large");
  }
}

/*
 *  Add an language entry for translation
 */
static void AddEntry (void)
{
  char        *str;
  struct Node *list = NULL;

  if ((str = strdup(buf)) == NULL ||
     (list = malloc(sizeof(*list))) == NULL)
  {
    outsnl ("Language file too big!");
    longjmp (bail_out, 1);
  }

  list->next   = lang.list;
  list->crc    = crc_ref;
  list->string = str;
  lang.list    = list;
  lang.entries++;
  do_ref = 1;
}

/*
 * Comparision routine needed by quick-sort and bsearch routines.
 * Don't use unsigned arithmetic
 */
static int Compare (const struct Elem *a, const struct Elem *b)
{
  if (a->crc > b->crc) return (1);
  if (a->crc < b->crc) return (-1);
  return (0);
}

/*
 * Sort the linked list in accending order of CRC value
 */
static int SortLanguageEntries (DWORD num)
{ 
  struct Node *lng, *next;
  struct Elem *array = malloc ((size_t)(num * sizeof(*array)));

  lang.array = array;
  if (!array)
     return (0);

  for (lng = lang.list; lng; lng = next, array++)
  {
    array->crc    = lng->crc;
    array->string = lng->string;
    next = lng->next;
    free (lng);
  }
  lang.list = NULL;
  qsort (lang.array, (size_t)num, (size_t)sizeof(*array), (int(*)())Compare);
  return (1);
}

/*
 *  Initialize the linked list for language.
 *
 *  The wattcp.cfg entry has format LANGUAGE = lang,language-file
 *  e.g. "LANGUAGE = de,$(ETC)\language.txt"
 *
 *  Country-code MUST be two characters (see ISO639 list above)
 *
 *  May be called multiple times to extend language entries from
 *  more than 1 file.
 */
void lang_init (const char *value)
{
  FILE *langf;
  char *s, *fname;

  if (!value)
     return;

  s = strchr (value, ',');
  if (!s || (s - value) != 2)
     Abort ("Illegal LANGUAGE syntax", NULL);

  lang.line = 1;
  lang.prefix[0] = value[0];
  lang.prefix[1] = value[1];
  lang.prefix[2] = ':';
  lang.prefix[3] = 0;
  strlwr (lang.prefix);

  if (!strnicmp(lang.prefix,"en",2))  /* english is default language */
     return;

  if (!watt_crc_init())
  {
    outsnl ("CRC init failed");
    return;
  }

  fname = ++s;
  langf = fopen (fname, "rb");
  if (!langf)
  {
    outs ("Cannot open language file ");
    outsnl (fname);
    return;
  }

  if (!setjmp(bail_out))
  {
    yyin = langf;
    yylex();
    fclose (langf);

    if (!SortLanguageEntries(lang.entries))
    {
      outsnl ("Could not sort LANGUAGE entries");
      lang.entries = 0;
    }
#if defined(TEST_PROG)
    printf ("file-name    = `%s'\n",   fname);
    printf ("lang.prefix  = `%s'\n",   lang.prefix);
    printf ("lang.entries = %lu\n",    lang.entries);
    printf ("lang.lines   = %lu\n",    lang.line);
    printf ("lang.list    = %08lX\n",  (DWORD)lang.list);
    printf ("lang.array   = %08lX\n\n",(DWORD)lang.array);
    {
      struct Elem *elem;
      int    i;
      for (i = 0, elem = lang.array; i < lang.entries; i++, elem++)
          printf ("CRC = %08lX, <%s>\n", elem->crc, elem->string);
    }
#endif
  }
}

/*
 * return foreign translation of string str
 */
const char *_LANG (const char *str)
{
  struct Elem *elem;
  DWORD  hash;
  int    len;

  if (!lang.entries || !str)
     return (str);

  len = strlen (str);
  if (len == 0)
     return (str);

  hash = watt_crc_bytes (str, len);

  elem = (struct Elem*) bsearch (&hash, lang.array, (size_t)lang.entries,
                                 (size_t)sizeof(*elem), (int(*)())Compare);

  if (!elem || !elem->string || !elem->string[0])
     return (str);

  return (const char*)elem->string;
}

/*
 * Print message and abort program
 */
static void Abort (const char *s1, const char *s2)
{
  if (lang.line > 0)
  {
#ifdef __DJGPP__
    (*_printf) ("\r\nline %lu: ", lang.line);
#else
    char buf [15];
    ltoa (lang.line, buf, 10);
    outs ("\r\nline ");
    outs (buf);
    outs (": ");
#endif
  }
  else
    outs ("\r\n");

  outs (s1);
  if (s2)
     outsnl (s2);
  outs ("\r\n");
  exit (1);
}

/*
 * Print error message for current line
 */
static void error (const char *err)
{
#ifdef __DJGPP__
  (*_printf) ("%s at line %lu\r\n", err, lang.line);
#else
  char buf [15];
  ltoa (lang.line, buf, 10);
  outs (err);
  outs (" at line ");
  outs (buf);
  outs ("\r\n");
#endif
}

#if defined(TEST_PROG)
int main (void)
{
  puts ("You must define a non-english language to parse language-file.\n"
        "Use e.g: \"language = no,$(ETC)\\watlang.txt\" in WATTCP.CFG\n"
        "Press any key to initialise Watt-32.");
  getch();
  sock_init();
  return (0);
}
#endif  /* TEST_PROG    */
#endif  /* USE_LANGUAGE */

⌨️ 快捷键说明

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