home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / comm / term33so.lha / termTranslate.c < prev    next >
C/C++ Source or Header  |  1993-04-30  |  21KB  |  1,040 lines

  1. /*
  2. **    termTranslate.c
  3. **
  4. **    Character translation support routines
  5. **
  6. **    Copyright © 1990-1993 by Olaf `Olsen' Barthel & MXM
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termGlobal.h"
  11.  
  12.     /* Translation chunk header types. */
  13.  
  14. enum    {    TYPE_NONE, TYPE_SEND, TYPE_RECEIVE };
  15.  
  16.     /* Master translation table entry types. */
  17.  
  18. enum    {    TRANSLATION_VERBATIM, TRANSLATION_IGNORE, TRANSLATION_OTHER };
  19.  
  20.     /* Symbolic names for character codes. */
  21.  
  22. STATIC struct { STRPTR Name; UBYTE Value; } CodeTab[44] =
  23. {
  24.     {    "NUL",    0    },
  25.     {    "SOH",    1    },
  26.     {    "STX",    2    },
  27.     {    "ETX",    3    },
  28.     {    "EOT",    4    },
  29.     {    "ENQ",    5    },
  30.     {    "ACK",    6    },
  31.     {    "BEL",    7    },
  32.     {    "BS",    8    },
  33.     {    "HT",    9    },
  34.     {    "LF",    10    },
  35.     {    "VT",    11    },
  36.     {    "FF",    12    },
  37.     {    "CR",    13    },
  38.     {    "SO",    14    },
  39.     {    "SI",    15    },
  40.     {    "DLE",    16    },
  41.     {    "DC1",    17    },
  42.     {    "DC2",    18    },
  43.     {    "DC3",    19    },
  44.     {    "DC4",    20    },
  45.     {    "NAK",    21    },
  46.     {    "SYN",    22    },
  47.     {    "ETB",    23    },
  48.     {    "CAN",    24    },
  49.     {    "EM",    25    },
  50.     {    "SUB",    26    },
  51.     {    "ESC",    27    },
  52.     {    "FS",    28    },
  53.     {    "GS",    29    },
  54.     {    "RS",    30    },
  55.     {    "US",    31    },
  56.     {    "SP",    32    },
  57.     {    "DEL",    127    },
  58.     {    "SS2",    142    },
  59.     {    "SS3",    143    },
  60.     {    "DCS",    144    },
  61.     {    "CSI",    155    },
  62.     {    "ST",    156    },
  63.     {    "OSC",    157    },
  64.     {    "PM",    158    },
  65.     {    "APC",    159    },
  66.     {    "NBS",    160    },
  67.     {    "SHY",    173    }
  68. };
  69.  
  70.     /* TranslateSetup():
  71.      *
  72.      *    Set up for buffer translation.
  73.      */
  74.  
  75. VOID __regargs
  76. TranslateSetup(struct TranslationHandle *Handle,STRPTR SourceBuffer,LONG SourceLen,STRPTR DestinationBuffer,LONG DestinationLen,struct TranslationEntry **Table)
  77. {
  78.     Handle -> LocalBuffer        = NULL;
  79.     Handle -> LocalLen        = 0;
  80.  
  81.     Handle -> SourceBuffer        = SourceBuffer;
  82.     Handle -> SourceLen        = SourceLen;
  83.  
  84.     Handle -> DestinationBuffer    = DestinationBuffer;
  85.     Handle -> DestinationLen    = DestinationLen;
  86.  
  87.     Handle -> Table            = Table;
  88. }
  89.  
  90.     /* TranslateBuffer(struct TranslationHandle *Handle):
  91.      *
  92.      *    Translate buffer contents according to
  93.      *    translation table contents.
  94.      */
  95.  
  96. LONG __regargs
  97. TranslateBuffer(struct TranslationHandle *Handle)
  98. {
  99.     register STRPTR                 Data        = Handle -> DestinationBuffer;
  100.     register LONG                 BytesWritten    = 0;
  101.     register struct TranslationEntry    *Entry;
  102.  
  103.         /* Are we to return any translated data? */
  104.  
  105.     while(Handle -> LocalLen && BytesWritten < Handle -> DestinationLen)
  106.     {
  107.             /* Decrement number of bytes in buffer. */
  108.  
  109.         Handle -> LocalLen--;
  110.  
  111.             /* Return next character. */
  112.  
  113.         *Data++ = *Handle -> LocalBuffer++;
  114.  
  115.             /* Add another byte. */
  116.  
  117.         BytesWritten++;
  118.     }
  119.  
  120.         /* Loop until done. */
  121.  
  122.     while(Handle -> SourceLen && BytesWritten < Handle -> DestinationLen)
  123.     {
  124.             /* Another byte eaten. */
  125.  
  126.         Handle -> SourceLen--;
  127.  
  128.             /* Get table entry. */
  129.  
  130.         if(Entry = Handle -> Table[*Handle -> SourceBuffer++])
  131.         {
  132.                 /* Copy to local data area. */
  133.  
  134.             Handle -> LocalBuffer    = Entry -> String;
  135.             Handle -> LocalLen    = Entry -> Len;
  136.  
  137.                 /* Translate the data. */
  138.  
  139.             while(Handle -> LocalLen && BytesWritten < Handle -> DestinationLen)
  140.             {
  141.                     /* Decrement number of bytes in buffer. */
  142.  
  143.                 Handle -> LocalLen--;
  144.  
  145.                     /* Return next character. */
  146.  
  147.                 *Data++ = *Handle -> LocalBuffer++;
  148.  
  149.                     /* Add another byte. */
  150.  
  151.                 BytesWritten++;
  152.             }
  153.         }
  154.     }
  155.  
  156.     return(BytesWritten);
  157. }
  158.  
  159.     /* NameToCode(STRPTR Name):
  160.      *
  161.      *    Translate a symbolic character code name of numeral.
  162.      */
  163.  
  164. UBYTE __regargs
  165. NameToCode(STRPTR Name)
  166. {
  167.     WORD i;
  168.  
  169.     for(i = 0 ; i < 44 ; i++)
  170.     {
  171.         if(!Stricmp(CodeTab[i] . Name,Name))
  172.             return(CodeTab[i] . Value);
  173.     }
  174.  
  175.     return((UBYTE)atoi(Name));
  176. }
  177.  
  178.     /* CodeToName(UBYTE Code):
  179.      *
  180.      *    Translate a character code into a symbolic
  181.      *    name or numeral.
  182.      */
  183.  
  184. STRPTR __regargs
  185. CodeToName(UBYTE Code)
  186. {
  187.     STATIC UBYTE Name[6];
  188.  
  189.     WORD i;
  190.  
  191.     for(i = 0 ; i < 44 ; i++)
  192.     {
  193.         if(CodeTab[i] . Value == Code)
  194.             return(CodeTab[i] . Name);
  195.     }
  196.  
  197.     SPrintf(Name,"%03ld",Code);
  198.  
  199.     return(Name);
  200. }
  201.  
  202.     /* FreeTranslationTable(struct TranslationEntry **Table):
  203.      *
  204.      *    Free a character translation table.
  205.      */
  206.  
  207. VOID
  208. FreeTranslationTable(struct TranslationEntry **Table)
  209. {
  210.     WORD i;
  211.  
  212.     for(i = 0 ; i < 256 ; i++)
  213.     {
  214.         if(Table[i])
  215.             FreeTranslationEntry(Table[i]);
  216.     }
  217.  
  218.     FreeVec(Table);
  219. }
  220.  
  221.     /* AllocTranslationTable():
  222.      *
  223.      *    Allocate a character translation table.
  224.      */
  225.  
  226. struct TranslationEntry **
  227. AllocTranslationTable()
  228. {
  229.     return((struct TranslationEntry **)AllocVec(sizeof(struct TranslationEntry *) * 256,MEMF_ANY|MEMF_CLEAR));
  230. }
  231.  
  232.     /* FreeTranslationEntry(struct TranslationEntry *Entry):
  233.      *
  234.      *    Free a character translation table entry.
  235.      */
  236.  
  237. VOID
  238. FreeTranslationEntry(struct TranslationEntry *Entry)
  239. {
  240.     FreeVec(Entry);
  241. }
  242.  
  243.     /* TranslateString(STRPTR From,STRPTR To):
  244.      *
  245.      *    Translate a string to contain control codes
  246.      *    into a string to contain the real codes.
  247.      */
  248.  
  249. LONG __regargs
  250. TranslateString(STRPTR From,STRPTR To)
  251. {
  252.     BYTE    GotControl    = FALSE,
  253.         GotEscape    = FALSE;
  254.  
  255.     LONG    Len    = strlen(From),
  256.         Count    = 0,
  257.         i;
  258.  
  259.     for(i = 0 ; i < Len ; i++)
  260.     {
  261.         if(!GotControl && !GotEscape)
  262.         {
  263.             if(From[i] == '\\')
  264.             {
  265.                 GotControl = TRUE;
  266.  
  267.                 continue;
  268.             }
  269.  
  270.             if(From[i] == '^')
  271.             {
  272.                 GotEscape = TRUE;
  273.  
  274.                 continue;
  275.             }
  276.  
  277.             To[Count++] = From[i];
  278.         }
  279.         else
  280.         {
  281.             if(GotEscape)
  282.             {
  283.                 if(ToUpper(From[i]) >= 'A' && ToUpper(From[i]) <= '_')
  284.                     To[Count++] = ToUpper(From[i]) - '@';
  285.                 else
  286.                     To[Count++] = From[i];
  287.  
  288.                 GotEscape = FALSE;
  289.             }
  290.             else
  291.             {
  292.                 if(GotControl)
  293.                 {
  294.                     switch(ToUpper(From[i]))
  295.                     {
  296.                             /* These macro commands are plainly
  297.                              * ignored.
  298.                              */
  299.  
  300.                         case '0':
  301.                         case '1':
  302.                         case '2':
  303.                         case '3':
  304.                         case '4':
  305.                         case '5':
  306.                         case '6':
  307.  
  308.                             break;
  309.  
  310.                             /* These are macro commands and
  311.                              * not supported.
  312.                              */
  313.  
  314.                         case 'A':
  315.                         case 'C':
  316.                         case 'D':
  317.                         case 'G':
  318.                         case 'H':
  319.                         case 'I':
  320.                         case 'P':
  321.                         case 'U':
  322.                         case 'X':
  323.  
  324.                             To[Count++] = '\\';
  325.                             To[Count++] = From[i];
  326.                             break;
  327.  
  328.                             /* Translate code. */
  329.  
  330.                         case '*':
  331.  
  332.                             i++;
  333.  
  334.                             while(i < Len && From[i] == ' ')
  335.                                 i++;
  336.  
  337.                             if(i < Len)
  338.                             {
  339.                                 UBYTE DummyBuffer[5],j = 0,Char;
  340.  
  341.                                 if(From[i] >= '0' && From[i] <= '9')
  342.                                 {
  343.                                     while(j < 3 && i < Len)
  344.                                     {
  345.                                         Char = From[i++];
  346.  
  347.                                         if(Char >= '0' && Char <= '9')
  348.                                             DummyBuffer[j++] = Char;
  349.                                         else
  350.                                         {
  351.                                             i--;
  352.  
  353.                                             break;
  354.                                         }
  355.                                     }
  356.                                 }
  357.                                 else
  358.                                 {
  359.                                     while(j < 4 && i < Len)
  360.                                     {
  361.                                         Char = ToLower(From[i++]);
  362.  
  363.                                         if((Char >= '0' && Char <= '9') || (Char >= 'a' && Char <= 'z'))
  364.                                             DummyBuffer[j++] = Char;
  365.                                         else
  366.                                         {
  367.                                             i--;
  368.  
  369.                                             break;
  370.                                         }
  371.                                     }
  372.                                 }
  373.  
  374.                                 DummyBuffer[j] = 0;
  375.  
  376.                                 To[Count++] = NameToCode(DummyBuffer);
  377.                             }
  378.  
  379.                             i--;
  380.  
  381.                             break;
  382.  
  383.                             /* This is a backspace. */
  384.  
  385.                         case 'B':
  386.  
  387.                             To[Count++] = '\b';
  388.                             break;
  389.  
  390.                             /* This is a form feed. */
  391.  
  392.                         case 'F':
  393.  
  394.                             To[Count++] = '\f';
  395.                             break;
  396.  
  397.                             /* This is a line feed. */
  398.  
  399.                         case 'N':
  400.  
  401.                             To[Count++] = '\n';
  402.                             break;
  403.  
  404.                             /* This is a carriage return. */
  405.  
  406.                         case 'R':
  407.  
  408.                             To[Count++] = '\r';
  409.                             break;
  410.  
  411.                             /* This is a tab. */
  412.  
  413.                         case 'T':
  414.  
  415.                             To[Count++] = '\t';
  416.                             break;
  417.  
  418.                             /* Produce the escape character. */
  419.  
  420.                         case 'E':
  421.  
  422.                             To[Count++] = ESC;
  423.                             break;
  424.  
  425.                             /* Stuff the character into the buffer. */
  426.  
  427.                         default:
  428.  
  429.                             To[Count++] = From[i];
  430.                             break;
  431.                     }
  432.  
  433.                     GotControl = FALSE;
  434.                 }
  435.             }
  436.         }
  437.     }
  438.  
  439.     return(Count);
  440. }
  441.  
  442.     /* AllocTranslationEntry(STRPTR String):
  443.      *
  444.      *    Allocate a character translation table entry.
  445.      */
  446.  
  447. struct TranslationEntry *
  448. AllocTranslationEntry(STRPTR String)
  449. {
  450.     LONG Count = TranslateString(String,SharedBuffer);
  451.  
  452.     if(Count > 0)
  453.     {
  454.         struct TranslationEntry    *Entry;
  455.         UBYTE             Type;
  456.  
  457.         if(Count > 1)
  458.         {
  459.             Type = TRANSLATE_STRING;
  460.  
  461.             if(Entry = (struct TranslationEntry *)AllocVec(sizeof(struct TranslationEntry) + Count + 1,MEMF_ANY|MEMF_CLEAR))
  462.             {
  463.                 Entry -> String    = (STRPTR)(Entry + 1);
  464.  
  465.                 memcpy(Entry -> String,SharedBuffer,Count);
  466.             }
  467.         }
  468.         else
  469.         {
  470.             Type = TRANSLATE_SINGLE;
  471.  
  472.             if(Entry = (struct TranslationEntry *)AllocVec(sizeof(struct TranslationEntry),MEMF_ANY|MEMF_CLEAR))
  473.             {
  474.                 Entry -> String    = &Entry -> Extra;
  475.                 Entry -> Extra    = SharedBuffer[0];
  476.             }
  477.         }
  478.  
  479.         if(Entry)
  480.         {
  481.             Entry -> Type    = Type;
  482.             Entry -> Len    = Count;
  483.  
  484.             return(Entry);
  485.         }
  486.     }
  487.  
  488.     return(NULL);
  489. }
  490.  
  491.     /* FillTranslationTable(struct TranslationEntry **Table):
  492.      *
  493.      *    Fill the translation table with defaults.
  494.      */
  495.  
  496. BYTE
  497. FillTranslationTable(struct TranslationEntry **Table)
  498. {
  499.     BYTE Success = TRUE;
  500.     WORD i;
  501.  
  502.     for(i = 0 ; Success && i < 256 ; i++)
  503.     {
  504.         if(Table[i] = (struct TranslationEntry *)AllocVec(sizeof(struct TranslationEntry),MEMF_ANY|MEMF_CLEAR))
  505.         {
  506.             Table[i] -> Type    = TRANSLATE_SINGLE;
  507.             Table[i] -> String    = &Table[i] -> Extra;
  508.             Table[i] -> Extra    = i;
  509.             Table[i] -> Len        = 1;
  510.         }
  511.         else
  512.             Success = FALSE;
  513.     }
  514.  
  515.     if(!Success)
  516.     {
  517.         for(i = 0 ; i < 256 ; i++)
  518.         {
  519.             if(Table[i])
  520.             {
  521.                 FreeVec(Table[i]);
  522.  
  523.                 Table[i] = NULL;
  524.             }
  525.         }
  526.     }
  527.  
  528.     return(Success);
  529. }
  530.  
  531.     /* IsStandardTable(struct TranslationEntry **Table):
  532.      *
  533.      *    Checks a translation table to see if it contains
  534.      *    standard data.
  535.      */
  536.  
  537. BYTE __regargs
  538. IsStandardTable(struct TranslationEntry **Table)
  539. {
  540.     WORD i;
  541.  
  542.     for(i = 0 ; i < 256 ; i++)
  543.     {
  544.         if(Table[i])
  545.         {
  546.             if(Table[i] -> Type != TRANSLATE_SINGLE || Table[i] -> Len != 1 || Table[i] -> String[0] != i)
  547.                 return(FALSE);
  548.         }
  549.         else
  550.             return(FALSE);
  551.     }
  552.  
  553.     return(TRUE);
  554. }
  555.  
  556.     /* TranslateBack(STRPTR From,LONG Len,STRPTR To):
  557.      *
  558.      *    Translate a precompiled translation string
  559.      *    back.
  560.      */
  561.  
  562. VOID
  563. TranslateBack(STRPTR From,LONG Len,STRPTR To)
  564. {
  565.     STATIC char TypeTable[256] =
  566.     {
  567.          1 , 1 , 1 , 1 , 1 , 1 , 1 ,1 ,'b','t','n', 1 ,'f','r', 1 , 1,
  568.          1 , 1 , 1 , 1 , 1 , 1 , 1 ,1 , 1 , 1 , 1 ,'e', 1 , 1 , 1 , 1,
  569.          0 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  570.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  571.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  572.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 ,'\\',2 , 2 , 2,
  573.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  574.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 0,
  575.          0 , 0 , 0 , 0 , 0 , 0 , 0 ,0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
  576.          0 , 0 , 0 , 0 , 0 , 0 , 0 ,0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
  577.          0 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 0 , 2 , 2,
  578.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  579.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  580.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  581.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  582.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2
  583.     };
  584.  
  585.     STRPTR     Buffer;
  586.     LONG    i,j,BufLen;
  587.  
  588.     for(i = j = 0 ; i < Len ; i++)
  589.     {
  590.         switch(TypeTable[From[i]])
  591.         {
  592.             case 0:    To[j++] = '\\';
  593.                 To[j++] = '*';
  594.  
  595.                 Buffer = CodeToName(From[i]);
  596.  
  597.                 BufLen = strlen(Buffer);
  598.  
  599.                 memcpy(&To[j],Buffer,BufLen);
  600.  
  601.                 j += BufLen;
  602.  
  603.                 break;
  604.  
  605.             case 1:    To[j++] = '^';
  606.                 To[j++] = From[i] + '@';
  607.                 break;
  608.  
  609.             case 2:    To[j++] = From[i];
  610.                 break;
  611.  
  612.             default:To[j++] = '\\';
  613.                 To[j++] = TypeTable[From[i]];
  614.                 break;
  615.         }
  616.     }
  617.  
  618.     To[j] = 0;
  619. }
  620.  
  621.     /* SaveTranslationTables():
  622.      *
  623.      *    Save a character translation table to a file.
  624.      */
  625.  
  626. BYTE
  627. SaveTranslationTables(STRPTR Name,struct TranslationEntry **SendTable,struct TranslationEntry **ReceiveTable)
  628. {
  629.     BYTE    Success = FALSE,
  630.         DoIt = FALSE;
  631.     WORD    i;
  632.  
  633.     for(i = 0 ; !DoIt && i < 256 ; i++)
  634.     {
  635.         if(SendTable[i] || ReceiveTable[i])
  636.             DoIt = TRUE;
  637.     }
  638.  
  639.     if(DoIt)
  640.     {
  641.         struct IFFHandle    *Handle;
  642.         UBYTE             MasterTable[256];
  643.  
  644.         for(i = 0 ; i < 256 ; i++)
  645.         {
  646.             if(SendTable[i])
  647.             {
  648.                 if(SendTable[i] -> Type == TRANSLATE_SINGLE && SendTable[i] -> Len == 1 && SendTable[i] -> String[0] == i)
  649.                     MasterTable[i] = TRANSLATION_VERBATIM;
  650.                 else
  651.                     MasterTable[i] = TRANSLATION_OTHER;
  652.             }
  653.             else
  654.                 MasterTable[i] = TRANSLATION_IGNORE;
  655.  
  656.             if(ReceiveTable[i])
  657.             {
  658.                 if(ReceiveTable[i] -> Type == TRANSLATE_SINGLE && ReceiveTable[i] -> Len == 1 && ReceiveTable[i] -> String[0] == i)
  659.                     MasterTable[i] |= TRANSLATION_VERBATIM << 4;
  660.                 else
  661.                     MasterTable[i] |= TRANSLATION_OTHER << 4;
  662.             }
  663.             else
  664.                 MasterTable[i] |= TRANSLATION_IGNORE << 4;
  665.         }
  666.  
  667.         if(Handle = AllocIFF())
  668.         {
  669.             if(Handle -> iff_Stream = Open(Name,MODE_NEWFILE))
  670.             {
  671.                 InitIFFasDOS(Handle);
  672.  
  673.                 if(!OpenIFF(Handle,IFFF_WRITE))
  674.                 {
  675.                     if(!PushChunk(Handle,ID_TERM,ID_CAT,IFFSIZE_UNKNOWN))
  676.                     {
  677.                         if(!PushChunk(Handle,ID_TERM,ID_FORM,IFFSIZE_UNKNOWN))
  678.                         {
  679.                             if(!PushChunk(Handle,0,ID_VERS,IFFSIZE_UNKNOWN))
  680.                             {
  681.                                 struct TermInfo TermInfo;
  682.  
  683.                                 TermInfo . Version    = TermVersion;
  684.                                 TermInfo . Revision    = TermRevision;
  685.  
  686.                                 if(WriteChunkRecords(Handle,&TermInfo,sizeof(struct TermInfo),1))
  687.                                 {
  688.                                     if(!PopChunk(Handle))
  689.                                     {
  690.                                         if(!PushChunk(Handle,0,ID_TRNS,256))
  691.                                         {
  692.                                             if(WriteChunkBytes(Handle,MasterTable,256) == 256)
  693.                                             {
  694.                                                 if(!PopChunk(Handle))
  695.                                                 {
  696.                                                     if(!PopChunk(Handle))
  697.                                                     {
  698.                                                         struct TranslationHeader Header;
  699.  
  700.                                                         Success = TRUE;
  701.  
  702.                                                         for(i = 0 ; Success && i < 256 ; i++)
  703.                                                         {
  704.                                                             if(SendTable[i] && (MasterTable[i] & 0xF) == TRANSLATION_OTHER)
  705.                                                             {
  706.                                                                 Header . Type    = SendTable[i] -> Type;
  707.                                                                 Header . Len    = SendTable[i] -> Len;
  708.                                                                 Header . Code    = i;
  709.                                                                 Header . Pad    = 0;
  710.  
  711.                                                                 if(!PushChunk(Handle,ID_TERM,ID_FORM,IFFSIZE_UNKNOWN))
  712.                                                                 {
  713.                                                                     if(!PushChunk(Handle,0,ID_SEND,sizeof(struct TranslationHeader)))
  714.                                                                     {
  715.                                                                         if(WriteChunkRecords(Handle,&Header,sizeof(struct TranslationHeader),1))
  716.                                                                         {
  717.                                                                             if(!PopChunk(Handle))
  718.                                                                             {
  719.                                                                                 if(!PushChunk(Handle,0,ID_CHRS,SendTable[i] -> Len))
  720.                                                                                 {
  721.                                                                                     if(WriteChunkRecords(Handle,SendTable[i] -> String,SendTable[i] -> Len,1))
  722.                                                                                     {
  723.                                                                                         if(PopChunk(Handle))
  724.                                                                                             Success = FALSE;
  725.                                                                                     }
  726.                                                                                     else
  727.                                                                                         Success = FALSE;
  728.                                                                                 }
  729.                                                                             }
  730.                                                                             else
  731.                                                                                 Success = FALSE;
  732.                                                                         }
  733.                                                                         else
  734.                                                                             Success = FALSE;
  735.                                                                     }
  736.  
  737.                                                                     if(PopChunk(Handle))
  738.                                                                         Success = FALSE;
  739.                                                                 }
  740.                                                                 else
  741.                                                                     Success = FALSE;
  742.                                                             }
  743.  
  744.                                                             if(ReceiveTable[i] && (MasterTable[i] >> 4) == TRANSLATION_OTHER)
  745.                                                             {
  746.                                                                 Header . Type    = ReceiveTable[i] -> Type;
  747.                                                                 Header . Len    = ReceiveTable[i] -> Len;
  748.                                                                 Header . Code    = i;
  749.                                                                 Header . Pad    = 0;
  750.  
  751.                                                                 if(!PushChunk(Handle,ID_TERM,ID_FORM,IFFSIZE_UNKNOWN))
  752.                                                                 {
  753.                                                                     if(!PushChunk(Handle,0,ID_RECV,sizeof(struct TranslationHeader)))
  754.                                                                     {
  755.                                                                         if(WriteChunkRecords(Handle,&Header,sizeof(struct TranslationHeader),1))
  756.                                                                         {
  757.                                                                             if(!PopChunk(Handle))
  758.                                                                             {
  759.                                                                                 if(!PushChunk(Handle,0,ID_CHRS,ReceiveTable[i] -> Len))
  760.                                                                                 {
  761.                                                                                     if(WriteChunkRecords(Handle,ReceiveTable[i] -> String,ReceiveTable[i] -> Len,1))
  762.                                                                                     {
  763.                                                                                         if(PopChunk(Handle))
  764.                                                                                             Success = FALSE;
  765.                                                                                     }
  766.                                                                                     else
  767.                                                                                         Success = FALSE;
  768.                                                                                 }
  769.                                                                             }
  770.                                                                             else
  771.                                                                                 Success = FALSE;
  772.                                                                         }
  773.                                                                         else
  774.                                                                             Success = FALSE;
  775.                                                                     }
  776.  
  777.                                                                     if(PopChunk(Handle))
  778.                                                                         Success = FALSE;
  779.                                                                 }
  780.                                                                 else
  781.                                                                     Success = FALSE;
  782.                                                             }
  783.                                                         }
  784.                                                     }
  785.                                                 }
  786.                                             }
  787.                                         }
  788.                                     }
  789.                                 }
  790.                             }
  791.                         }
  792.  
  793.                         if(PopChunk(Handle))
  794.                             Success = FALSE;
  795.                     }
  796.  
  797.                     CloseIFF(Handle);
  798.                 }
  799.  
  800.                 Close(Handle -> iff_Stream);
  801.  
  802.                 if(Success)
  803.                     AddProtection(Name,FIBF_EXECUTE);
  804.                 else
  805.                     DeleteFile(Name);
  806.             }
  807.  
  808.             FreeIFF(Handle);
  809.         }
  810.     }
  811.  
  812.     return(Success);
  813. }
  814.  
  815.     /* LoadTranslationTable()s:
  816.      *
  817.      *    Load a translation table from a file.
  818.      */
  819.  
  820. BYTE
  821. LoadTranslationTables(STRPTR Name,struct TranslationEntry **SendTable,struct TranslationEntry **ReceiveTable)
  822. {
  823.     STATIC ULONG Stops[5 * 2] =
  824.     {
  825.         ID_TERM,    ID_VERS,
  826.         ID_TERM,    ID_TRNS,
  827.         ID_TERM,    ID_SEND,
  828.         ID_TERM,    ID_RECV,
  829.         ID_TERM,    ID_CHRS
  830.     };
  831.  
  832.     struct IFFHandle    *Handle;
  833.     BYTE             Success = FALSE;
  834.     WORD             i;
  835.  
  836.     UBYTE             MasterTable[256];
  837.     BYTE             GotMasterTable = FALSE;
  838.  
  839.     if(Handle = AllocIFF())
  840.     {
  841.         if(Handle -> iff_Stream = Open(Name,MODE_OLDFILE))
  842.         {
  843.             InitIFFasDOS(Handle);
  844.  
  845.             if(!OpenIFF(Handle,IFFF_READ))
  846.             {
  847.                 if(!StopChunks(Handle,Stops,5))
  848.                 {
  849.                     struct ContextNode        *Chunk;
  850.                     struct TermInfo             TermInfo;
  851.                     struct TranslationHeader     Header;
  852.                     BYTE                 LastType = TYPE_NONE;
  853.  
  854.                     Success = TRUE;
  855.  
  856.                     while(Success && !ParseIFF(Handle,IFFPARSE_SCAN))
  857.                     {
  858.                         Chunk = CurrentChunk(Handle);
  859.  
  860.                         switch(Chunk -> cn_ID)
  861.                         {
  862.                             case ID_VERS:
  863.  
  864.                                 if(ReadChunkBytes(Handle,&TermInfo,sizeof(struct TermInfo)) == sizeof(struct TermInfo))
  865.                                 {
  866.                                     if(TermInfo . Version > TermVersion || (TermInfo . Version == TermVersion && TermInfo . Revision > TermRevision))
  867.                                         Success = FALSE;
  868.                                 }
  869.                                 else
  870.                                     Success = FALSE;
  871.  
  872.                                 break;
  873.  
  874.                             case ID_TRNS:
  875.  
  876.                                 if(ReadChunkBytes(Handle,MasterTable,256) == 256)
  877.                                     GotMasterTable = TRUE;
  878.                                 else
  879.                                     Success = FALSE;
  880.  
  881.                                 break;
  882.  
  883.                             case ID_SEND:
  884.  
  885.                                 if(LastType != TYPE_NONE)
  886.                                     Success = FALSE;
  887.                                 else
  888.                                 {
  889.                                     if(!ReadChunkRecords(Handle,&Header,MIN(sizeof(struct TranslationHeader),Chunk -> cn_Size),1))
  890.                                         Success = FALSE;
  891.                                     else
  892.                                         LastType = TYPE_SEND;
  893.                                 }
  894.  
  895.                                 break;
  896.  
  897.                             case ID_RECV:
  898.  
  899.                                 if(LastType != TYPE_NONE)
  900.                                     Success = FALSE;
  901.                                 else
  902.                                 {
  903.                                     if(!ReadChunkRecords(Handle,&Header,MIN(sizeof(struct TranslationHeader),Chunk -> cn_Size),1))
  904.                                         Success = FALSE;
  905.                                     else
  906.                                         LastType = TYPE_RECEIVE;
  907.                                 }
  908.  
  909.                                 break;
  910.  
  911.                             case ID_CHRS:
  912.  
  913.                                 if(LastType == TYPE_NONE)
  914.                                     Success = FALSE;
  915.                                 else
  916.                                 {
  917.                                     if(ReadChunkRecords(Handle,SharedBuffer,Header . Len,1))
  918.                                     {
  919.                                         struct TranslationEntry *Entry;
  920.  
  921.                                         if(Header . Type == TRANSLATE_SINGLE)
  922.                                         {
  923.                                             if(Entry = (struct TranslationEntry *)AllocVec(sizeof(struct TranslationEntry),MEMF_ANY|MEMF_CLEAR))
  924.                                             {
  925.                                                 Entry -> String    = &Entry -> Extra;
  926.                                                 Entry -> Extra    = SharedBuffer[0];
  927.                                             }
  928.                                         }
  929.                                         else
  930.                                         {
  931.                                             if(Entry = (struct TranslationEntry *)AllocVec(sizeof(struct TranslationEntry) + Header . Len + 1,MEMF_ANY|MEMF_CLEAR))
  932.                                             {
  933.                                                 Entry -> String    = (STRPTR)(Entry + 1);
  934.  
  935.                                                 memcpy(Entry -> String,SharedBuffer,Header . Len);
  936.                                             }
  937.                                         }
  938.  
  939.                                         if(Entry)
  940.                                         {
  941.                                             Entry -> Type    = Header . Type;
  942.                                             Entry -> Len    = Header . Len;
  943.  
  944.                                             if(LastType == TYPE_SEND)
  945.                                                 SendTable[Header . Code]    = Entry;
  946.                                             else
  947.                                                 ReceiveTable[Header . Code]    = Entry;
  948.  
  949.                                             LastType = TYPE_NONE;
  950.                                         }
  951.                                         else
  952.                                             Success = FALSE;
  953.                                     }
  954.                                     else
  955.                                         Success = FALSE;
  956.                                 }
  957.  
  958.                                 break;
  959.                         }
  960.                     }
  961.                 }
  962.  
  963.                 CloseIFF(Handle);
  964.             }
  965.  
  966.             Close(Handle -> iff_Stream);
  967.         }
  968.  
  969.         FreeIFF(Handle);
  970.     }
  971.  
  972.     if(Success && GotMasterTable)
  973.     {
  974.         struct TranslationEntry *Entry;
  975.  
  976.         for(i = 0 ; i < 256 ; i++)
  977.         {
  978.             if((MasterTable[i] & 0xF) == TRANSLATION_VERBATIM)
  979.             {
  980.                 if(Entry = (struct TranslationEntry *)AllocVec(sizeof(struct TranslationEntry),MEMF_ANY|MEMF_CLEAR))
  981.                 {
  982.                     Entry -> Type    = TRANSLATE_SINGLE;
  983.                     Entry -> String    = &Entry -> Extra;
  984.                     Entry -> Extra    = i;
  985.                     Entry -> Len    = 1;
  986.  
  987.                     SendTable[i] = Entry;
  988.                 }
  989.                 else
  990.                 {
  991.                     Success = FALSE;
  992.  
  993.                     break;
  994.                 }
  995.             }
  996.  
  997.             if((MasterTable[i] >> 4) == TRANSLATION_VERBATIM)
  998.             {
  999.                 if(Entry = (struct TranslationEntry *)AllocVec(sizeof(struct TranslationEntry),MEMF_ANY|MEMF_CLEAR))
  1000.                 {
  1001.                     Entry -> Type    = TRANSLATE_SINGLE;
  1002.                     Entry -> String    = &Entry -> Extra;
  1003.                     Entry -> Extra    = i;
  1004.                     Entry -> Len    = 1;
  1005.  
  1006.                     ReceiveTable[i] = Entry;
  1007.                 }
  1008.                 else
  1009.                 {
  1010.                     Success = FALSE;
  1011.  
  1012.                     break;
  1013.                 }
  1014.             }
  1015.         }
  1016.     }
  1017.  
  1018.     if(!Success)
  1019.     {
  1020.         for(i = 0 ; i < 256 ; i++)
  1021.         {
  1022.             if(SendTable[i])
  1023.             {
  1024.                 FreeTranslationEntry(SendTable[i]);
  1025.  
  1026.                 SendTable[i] = NULL;
  1027.             }
  1028.  
  1029.             if(ReceiveTable[i])
  1030.             {
  1031.                 FreeTranslationEntry(ReceiveTable[i]);
  1032.  
  1033.                 ReceiveTable[i] = NULL;
  1034.             }
  1035.         }
  1036.     }
  1037.  
  1038.     return(Success);
  1039. }
  1040.