home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / devel / tcl / tclx7_31.z / tclx7_31 / tcldev / tclX7.3a-p1 / src / tclXmsgcat.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-01-05  |  9.8 KB  |  345 lines

  1. /* 
  2.  * tclXmsgcat.c --
  3.  *
  4.  *      Contains commands for accessing XPG/3 message catalogs.  If real XPG/3
  5.  * message catalogs are not available, the default string is returned.
  6.  *-----------------------------------------------------------------------------
  7.  * Copyright 1991-1993 Karl Lehenbauer and Mark Diekhans.
  8.  *
  9.  * Permission to use, copy, modify, and distribute this software and its
  10.  * documentation for any purpose and without fee is hereby granted, provided
  11.  * that the above copyright notice appear in all copies.  Karl Lehenbauer and
  12.  * Mark Diekhans make no representations about the suitability of this
  13.  * software for any purpose.  It is provided "as is" without express or
  14.  * implied warranty.
  15.  *-----------------------------------------------------------------------------
  16.  * $Id: tclXmsgcat.c,v 3.1 1993/12/13 15:12:01 markd Exp $
  17.  *-----------------------------------------------------------------------------
  18.  */
  19.  
  20. #include "tclExtdInt.h"
  21.  
  22. #ifdef HAVE_CATGETS
  23.  
  24. #include <nl_types.h>
  25.  
  26. #else
  27.  
  28. typedef int nl_catd;
  29.  
  30. #endif /* HAVE_CATGETS */
  31.  
  32. static int
  33. ParseFailOption _ANSI_ARGS_((Tcl_Interp *interp,
  34.                              CONST char *optionStr,
  35.                              int        *failPtr));
  36.  
  37. static int
  38. CatOpFailed _ANSI_ARGS_((Tcl_Interp *interp,
  39.                          CONST char *errorMsg));
  40.  
  41. static void
  42. MsgCatCleanUp _ANSI_ARGS_((ClientData  clientData,
  43.                            Tcl_Interp *interp));
  44.  
  45. /*
  46.  * Message catalog table is global, so it is shared between all interpreters
  47.  * in the same process.
  48.  */
  49. static void_pt msgCatTblPtr = NULL;
  50.  
  51. #ifndef HAVE_CATGETS
  52.  
  53. /*
  54.  *-----------------------------------------------------------------------------
  55.  * catopen --
  56.  *
  57.  *   A stub to use when message catalogs are not available.  Always returns
  58.  * the default string.
  59.  *-----------------------------------------------------------------------------
  60.  */
  61. static nl_catd
  62. catopen (name, oflag)
  63.     char *name;
  64.     int   oflag;
  65. {
  66.     return (nl_catd) -1;
  67. }
  68.  
  69. /*
  70.  *-----------------------------------------------------------------------------
  71.  * catgets --
  72.  *
  73.  *   A stub to use when message catalogs are not available. Always returns -1.
  74.  *-----------------------------------------------------------------------------
  75.  */
  76. static char *
  77. catgets (catd, set_num, msg_num, defaultStr)
  78.     nl_catd catd;
  79.     int     set_num, msg_num;
  80.     char   *defaultStr;
  81. {
  82.     return defaultStr;
  83. }
  84.  
  85. /*
  86.  *-----------------------------------------------------------------------------
  87.  * catclose --
  88.  *
  89.  *   A stub to use when message catalogs are not available. Always returns -1.
  90.  *-----------------------------------------------------------------------------
  91.  */
  92. static int
  93. catclose (catd)
  94.     nl_catd catd;
  95. {
  96.     return -1;
  97. }
  98. #endif /* HAVE_CATGETS */
  99.  
  100. /*
  101.  *-----------------------------------------------------------------------------
  102.  * ParseFailOption --
  103.  *
  104.  *   Parse the -fail/-nofail option, if specified.
  105.  *-----------------------------------------------------------------------------
  106.  */
  107. static int
  108. ParseFailOption (interp, optionStr, failPtr)
  109.     Tcl_Interp *interp;
  110.     CONST char *optionStr;
  111.     int        *failPtr;
  112. {
  113.     if (STREQU ("-fail", ((char *) optionStr)))
  114.         *failPtr = TRUE;
  115.     else if (STREQU ("-nofail", ((char *) optionStr)))
  116.         *failPtr = FALSE;
  117.     else {
  118.         Tcl_AppendResult (interp, "Expected option of `-fail' or ",
  119.                           "`-nofail', got: `", optionStr, "'",
  120.                           (char *) NULL);
  121.         return TCL_ERROR;
  122.     }
  123.     return TCL_OK;
  124. }
  125.  
  126. /*
  127.  *-----------------------------------------------------------------------------
  128.  * CatOpFailed --
  129.  *
  130.  *    Handles failures of catopen and catclose.  If message catalogs are
  131.  * available, if returns the supplied message.  If message are not
  132.  * available, it returns a message indicating that message stubs are used.
  133.  * It is not specified by XPG/3 how to get the details of a message catalog
  134.  * open or close failure. Always returns TCL_ERROR;
  135.  *-----------------------------------------------------------------------------
  136.  */
  137. static int
  138. CatOpFailed (interp, errorMsg)
  139.     Tcl_Interp *interp;
  140.     CONST char *errorMsg;
  141. {
  142. #ifdef HAVE_CATGETS
  143.  
  144.     Tcl_AppendResult (interp, errorMsg, (char *) NULL);
  145.  
  146. #else
  147.  
  148.     Tcl_AppendResult (interp, "the message catalog facility is not available,",
  149.                       " default string is always returned", (char *) NULL);
  150.  
  151. #endif /* HAVE_CATGETS */
  152.  
  153.     return TCL_ERROR;
  154. }
  155.  
  156. /*
  157.  *-----------------------------------------------------------------------------
  158.  * Tcl_CatopenCmd --
  159.  *
  160.  *    Implements the TCL echo command:
  161.  *        catopen ?-fail|-nofail? catname
  162.  *-----------------------------------------------------------------------------
  163.  */
  164. static int
  165. Tcl_CatopenCmd (clientData, interp, argc, argv)
  166.     ClientData  clientData;
  167.     Tcl_Interp *interp;
  168.     int         argc;
  169.     char      **argv;
  170. {
  171.     int      fail;
  172.     nl_catd  catDesc;
  173.     nl_catd *catDescPtr;
  174.  
  175.     if ((argc < 2) || (argc > 3)) {
  176.         Tcl_AppendResult (interp, tclXWrongArgs, argv [0],
  177.                           " ?-fail|-nofail? catname",
  178.                           (char *) NULL);
  179.         return TCL_ERROR;
  180.     }
  181.     if (argc == 3) {
  182.         if (ParseFailOption (interp, argv [1], &fail) != TCL_OK)
  183.             return TCL_ERROR;
  184.     } else
  185.         fail = FALSE;
  186.  
  187.     catDesc = catopen (argv [argc - 1], 0);
  188.     if ((catDesc == (nl_catd) -1) && fail)
  189.         return CatOpFailed (interp, "open of message catalog failed");
  190.  
  191.     catDescPtr = (nl_catd *) Tcl_HandleAlloc (msgCatTblPtr, interp->result);
  192.     *catDescPtr = catDesc;
  193.  
  194.     return TCL_OK;
  195. }
  196.  
  197. /*
  198.  *-----------------------------------------------------------------------------
  199.  * Tcl_CatgetsCmd --
  200.  *
  201.  *    Implements the TCL echo command:
  202.  *        catgets catHandle setnum msgnum defaultstr
  203.  *-----------------------------------------------------------------------------
  204.  */
  205. static int
  206. Tcl_CatgetsCmd (clientData, interp, argc, argv)
  207.     ClientData  clientData;
  208.     Tcl_Interp *interp;
  209.     int         argc;
  210.     char      **argv;
  211. {
  212.     nl_catd   *catDescPtr;
  213.     int        msgSetNum, msgNum;
  214.     char      *localMsg;
  215.  
  216.     if (argc != 5) {
  217.         Tcl_AppendResult (interp, tclXWrongArgs, argv [0],
  218.                           " catHandle setnum msgnum ",
  219.                           "defaultstr", (char *) NULL);
  220.         return TCL_ERROR;
  221.     }
  222.     catDescPtr = (nl_catd *) Tcl_HandleXlate (interp, msgCatTblPtr, argv [1]);
  223.     if (catDescPtr == NULL)
  224.         return TCL_ERROR;
  225.     if (Tcl_GetInt (interp, argv [2], &msgSetNum) != TCL_OK)
  226.         return TCL_ERROR;
  227.     if (Tcl_GetInt (interp, argv [3], &msgNum) != TCL_OK)
  228.         return TCL_ERROR;
  229.  
  230.     localMsg = catgets (*catDescPtr, msgSetNum, msgNum, argv [4]);
  231.  
  232.     Tcl_SetResult (interp, localMsg, TCL_VOLATILE);
  233.     return TCL_OK;
  234. }
  235.  
  236. /*
  237.  *-----------------------------------------------------------------------------
  238.  * Tcl_CatcloseCmd --
  239.  *
  240.  *    Implements the TCL echo command:
  241.  *        catclose ?-fail|-nofail? catHandle
  242.  *-----------------------------------------------------------------------------
  243.  */
  244. static int
  245. Tcl_CatcloseCmd (clientData, interp, argc, argv)
  246.     ClientData  clientData;
  247.     Tcl_Interp *interp;
  248.     int         argc;
  249.     char      **argv;
  250. {
  251.     int      fail;
  252.     nl_catd *catDescPtr;
  253.  
  254.     if ((argc < 2) || (argc > 3)) {
  255.         Tcl_AppendResult (interp, tclXWrongArgs, argv [0],
  256.                           " ?-fail|-nofail? catHandle",
  257.                           (char *) NULL);
  258.         return TCL_ERROR;
  259.     }
  260.     if (argc == 3) {
  261.         if (ParseFailOption (interp, argv [1], &fail) != TCL_OK)
  262.             return TCL_ERROR;
  263.     } else
  264.         fail = FALSE;
  265.  
  266.     catDescPtr = (nl_catd *) Tcl_HandleXlate (interp, msgCatTblPtr,
  267.                                               argv [argc - 1]);
  268.     if (catDescPtr == NULL)
  269.         return TCL_ERROR;
  270.  
  271.     if ((catclose (*catDescPtr) < 0) && fail)
  272.         return CatOpFailed (interp, "close of message catalog failed");
  273.  
  274.     Tcl_HandleFree (msgCatTblPtr, catDescPtr);
  275.     return TCL_OK;
  276. }
  277.  
  278. /*
  279.  *-----------------------------------------------------------------------------
  280.  * MsgCatCleanUp --
  281.  *
  282.  *    Called at interpreter deletion.  Releases all resources when no more
  283.  * interpreters are using the message catalog table.
  284.  *-----------------------------------------------------------------------------
  285.  */
  286. static void
  287. MsgCatCleanUp (clientData, interp)
  288.     ClientData  clientData;
  289.     Tcl_Interp *interp;
  290. {
  291.     nl_catd *catDescPtr;
  292.     int      walkKey;
  293.     
  294.     if (Tcl_HandleTblUseCount (msgCatTblPtr, -1) > 0)
  295.         return;
  296.  
  297.     walkKey = -1;
  298.     while (TRUE) {
  299.         catDescPtr = (nl_catd *) Tcl_HandleWalk (msgCatTblPtr, &walkKey);
  300.         if (catDescPtr == NULL)
  301.             break;
  302.         catclose (*catDescPtr);
  303.     }
  304.     Tcl_HandleTblRelease (msgCatTblPtr);
  305.     msgCatTblPtr = NULL;
  306. }
  307.  
  308. /*
  309.  *-----------------------------------------------------------------------------
  310.  * Tcl_InitMsgCat --
  311.  *
  312.  *   Initialize the Tcl XPG/3 message catalog support faility.
  313.  *-----------------------------------------------------------------------------
  314.  */
  315. void
  316. Tcl_InitMsgCat (interp)
  317.     Tcl_Interp *interp;
  318. {
  319.     int incrUseCount;
  320.  
  321.     /*
  322.      * Set up the table.  It is shared between all interpreters, so the use
  323.      * count reflects the number of interpreters.
  324.      */
  325.     if (msgCatTblPtr == NULL) {
  326.         msgCatTblPtr = Tcl_HandleTblInit ("msgcat", sizeof (nl_catd), 6);
  327.     } else {
  328.         (void) Tcl_HandleTblUseCount (msgCatTblPtr, 1);
  329.     }
  330.  
  331.     Tcl_CallWhenDeleted (interp, MsgCatCleanUp, (ClientData) NULL);
  332.  
  333.     /*
  334.      * Initialize the commands.
  335.      */
  336.  
  337.     Tcl_CreateCommand (interp, "catopen", Tcl_CatopenCmd, 
  338.                        (ClientData) NULL, (void (*)()) NULL);
  339.     Tcl_CreateCommand (interp, "catgets", Tcl_CatgetsCmd, 
  340.                        (ClientData) NULL, (void (*)()) NULL);
  341.     Tcl_CreateCommand (interp, "catclose", Tcl_CatcloseCmd,
  342.                        (ClientData) NULL, (void (*)()) NULL);
  343. }
  344.  
  345.