home *** CD-ROM | disk | FTP | other *** search
/ Resource Library: Multimedia / Resource Library: Multimedia.iso / sgml / unix / rexxsgml / rexxsgml.c next >
Encoding:
C/C++ Source or Header  |  1991-07-03  |  16.3 KB  |  438 lines

  1. /*****************************************************************************/
  2. /* REXX SGML interpreter.                                                    */
  3. /*     Provides an SGML "application environment" for Personal REXX.         */
  4. /*                                                                           */
  5. /* Author:  Roy Engehausen                                                   */
  6. /* Mods:    Jack Steitz          1. Bring code to ANSI Standard              */
  7. /* Mods:    Charles F. Goldfarb  2. Convert to Borland C                     */
  8. /*                                                                           */
  9. /*                                                                           */
  10. /*****************************************************************************/
  11.  
  12. /*===========================================================================*/
  13. /* External files                                                            */
  14. /*===========================================================================*/
  15.  
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <dos.h>
  20.  
  21. #pragma option -a-            /* Borland C: force byte alignment */
  22. #include "rexxcall.h"
  23. #pragma option -a.            /* Borland C: restore previous alignment */
  24.  
  25. /*****************************************************************************/
  26. /* REXX SGML interpreter.                                                    */
  27. /*     Subroutines                                                           */
  28. /*****************************************************************************/
  29.  
  30. int words(char *);
  31.  
  32. char *subword(char *, int, int);
  33.  
  34. /*---------------------------------------------------------------------------*/
  35. /* Defines                                                                   */
  36. /*---------------------------------------------------------------------------*/
  37.  
  38. #define MAKE_LONG(hi, low) \
  39.  ((long) ((((unsigned long) (unsigned) (hi)) << 16) + \
  40.  (unsigned long) (unsigned) (low)))
  41. #define HIGH_WORD(l) ((unsigned) (((unsigned long) (l)) >> 16))
  42. #define LOW_WORD(l) ((unsigned) (((unsigned long) (l)) & 0xffff))
  43.  
  44. #ifdef __SMALL__  /* small model */
  45. #define FINDINT findints
  46. #endif
  47. #ifdef __MEDIUM__  /* medium model */
  48. #define FINDINT findintm
  49. #endif
  50. #ifdef __LARGE__  /* large model */
  51. #define FINDINT findintl
  52. #endif
  53.  
  54. /*---------------------------------------------------------------------------*/
  55. /* These are assembler language interfaces to REXX supplied as part          */
  56. /* of Mansfield's Personal REXX                                              */
  57. /*---------------------------------------------------------------------------*/
  58.  
  59. int rexxcall(void),
  60.     FINDINT(int *);
  61.  
  62. /*---------------------------------------------------------------------------*/
  63. /* Prototype for SGML                                                        */
  64. /*---------------------------------------------------------------------------*/
  65.  
  66. void sgmlapir(int, char **);
  67.  
  68. /*---------------------------------------------------------------------------*/
  69. /* Function prototypes                                                       */
  70. /*---------------------------------------------------------------------------*/
  71.  
  72. unsigned showsp(void);
  73.  
  74. int proc(char *, char *, int *);
  75.  
  76. int execute(FARP, size_t);
  77.  
  78. void rexxerr(char *);
  79.  
  80. /*---------------------------------------------------------------------------*/
  81. /* Global variables                                                          */
  82. /*---------------------------------------------------------------------------*/
  83.  
  84. unsigned data_segment;
  85.  
  86. char *arg_array[5];
  87. char  arg_array1[20];
  88. char  arg_array2[20];
  89.  
  90. /*===========================================================================*/
  91. /* Main entry point                                                          */
  92. /*===========================================================================*/
  93.  
  94. int main(int argc, char **argv)
  95.   {
  96.  
  97.     char *execn = NULL;
  98.     int  retcode;
  99.  
  100.     /*-----------------------------------------------------------------------*/
  101.     /* Check parameter count                                                 */
  102.     /*-----------------------------------------------------------------------*/
  103.  
  104.     if (argc < 2)
  105.       {
  106.         printf("\nExec name parameter is missing -- %d\n", argc);
  107.         exit(1);
  108.       };
  109.  
  110.     /*-----------------------------------------------------------------------*/
  111.     /* The exec name is the first item.                                      */
  112.     /*-----------------------------------------------------------------------*/
  113.  
  114.     execn = argv[1];
  115.  
  116.     proc(execn,argv[2],&retcode);
  117.  
  118.     return(retcode);
  119.  
  120.   }
  121.  
  122. /*===========================================================================*/
  123. /* Interface to REXX interpreter                                             */
  124. /*===========================================================================*/
  125.  
  126. int proc(char *name, char *argstring, int *rcode)
  127.   {
  128.     char   result[257];
  129.  
  130.     union  REGS  inregs,
  131.                  outregs;
  132.  
  133.     struct SREGS segregs;
  134.  
  135.     /*-----------------------------------------------------------------------*/
  136.     /* REXX control blocks                                                   */
  137.     /*-----------------------------------------------------------------------*/
  138.  
  139.     struct call_block cb, *cbp = &cb;
  140.     struct arg_block  arg_list;
  141.     struct env_block  eb;
  142.  
  143.     /*-----------------------------------------------------------------------*/
  144.     /* REXX information                                                      */
  145.     /*-----------------------------------------------------------------------*/
  146.  
  147.     int rexx_interrupt,
  148.         unload = 0,
  149.         interrupt_status;
  150.  
  151.     /*-----------------------------------------------------------------------*/
  152.     /* Find REXX                                                             */
  153.     /*-----------------------------------------------------------------------*/
  154.  
  155.     rexx_interrupt = FINDINT(&interrupt_status);
  156.  
  157.     if (interrupt_status != 0)
  158.        rexxerr("RXINTMGR not installed.\n");
  159.  
  160.     /*-----------------------------------------------------------------------*/
  161.     /* Verify REXX is loaded                                                 */
  162.     /*-----------------------------------------------------------------------*/
  163.  
  164.     inregs.h.ah = REXX_VERSION;
  165.     inregs.h.al = 0;
  166.     int86(rexx_interrupt, &inregs, &outregs);
  167.  
  168.     if (outregs.h.al == 0)
  169.     {
  170.         if (system("REXX /R") !=0)
  171.           rexxerr("REXX not loaded\n");
  172.         else
  173.           unload = 1;
  174.     }
  175.  
  176.     /*-----------------------------------------------------------------------*/
  177.     /* Build the CALL BLOCK                                                  */
  178.     /*-----------------------------------------------------------------------*/
  179.  
  180.     segread(&segregs);
  181.     data_segment = segregs.ds;
  182.  
  183.     memset(&cb, 0, sizeof(struct call_block));
  184.  
  185.     cb.arg_list_addr = (FARP) &arg_list;
  186.     cb.arg_count     = 1;
  187.     cb.ret_size      = 256;
  188.     cb.ret_count     = 0;
  189.     cb.ret_addr      = (FARP) result;
  190.     cb.envblock_addr = (FARP) &eb;
  191.     cb.name_addr     = (FARP) name;
  192.     cb.name_length   = strlen(name);
  193.  
  194.     /*-----------------------------------------------------------------------*/
  195.     /* Build the argument block                                              */
  196.     /*-----------------------------------------------------------------------*/
  197.  
  198.     arg_list.arg_addr   = (FARP) argstring;
  199.     arg_list.arg_length = strlen(argstring);
  200.  
  201.     /*-----------------------------------------------------------------------*/
  202.     /* Build the environment block                                           */
  203.     /*-----------------------------------------------------------------------*/
  204.  
  205.     memset(&eb, 0, sizeof(struct env_block));
  206.     memcpy(eb.env_name,      "SGML    ", 8);  /* name of our environment     */
  207.     memcpy(eb.env_extension, "REX"     , 3);  /* extension of our macros     */
  208.     eb.env_entry_addr = (FARP) rexxcall;      /* interface to command handler*/
  209.     /*-----------------------------------------------------------------------*/
  210.     /* Set the address of the command handler.  If this is small model then  */
  211.     /* we use a SEGMENT of zero to indicate that NEAR CALLs are to be used.  */
  212.     /*-----------------------------------------------------------------------*/
  213.  
  214. #ifdef __SMALL__
  215.     eb.env_exec_addr = (FARP) MAKE_LONG(0, execute);
  216. #else
  217. #if 0
  218.     eb.env_exec_addr = (FARP) execute;
  219. #endif
  220.     eb.env_exec_addr = execute;
  221. #endif
  222.  
  223.     /*-----------------------------------------------------------------------*/
  224.     /* Set the segment addresses                                             */
  225.     /*-----------------------------------------------------------------------*/
  226.  
  227.     eb.env_dseg = data_segment;
  228.     eb.env_sseg = segregs.ss;
  229.  
  230.     /*-----------------------------------------------------------------------*/
  231.     /* Set the address of the stack.  Take off a few byte to make sure we    */
  232.     /* never overlay anything                                                */
  233.     /*-----------------------------------------------------------------------*/
  234.  
  235.     eb.env_sp = showsp() - 40;
  236.  
  237.     /*-----------------------------------------------------------------------*/
  238.     /* Now call REXX                                                         */
  239.     /*-----------------------------------------------------------------------*/
  240.  
  241.     inregs.h.ah = REXX_CALL;
  242. #ifdef __LARGE__
  243.     inregs.x.bx = FP_SEG(cbp);
  244.     inregs.x.dx = FP_OFF(cbp);
  245. #else
  246.     inregs.x.bx = data_segment;
  247.     inregs.x.dx = (unsigned) cbp;
  248. #endif
  249.  
  250.     int86x(rexx_interrupt, &inregs, &outregs, &segregs);
  251.  
  252.     /*-----------------------------------------------------------------------*/
  253.     /* Set the results                                                       */
  254.     /*-----------------------------------------------------------------------*/
  255.  
  256.     result[(int)cb.ret_count] = '\0';
  257.     *rcode = atoi(result);
  258.  
  259.     /*-----------------------------------------------------------------------*/
  260.     /* We are done!                                                          */
  261.     /*-----------------------------------------------------------------------*/
  262.     if (unload)
  263.     {
  264.         inregs.h.ah = REXX_UNLOAD;
  265.         inregs.h.al = 0;
  266.         inregs.x.bx = _psp;
  267.         int86(rexx_interrupt, &inregs, &outregs);
  268.     }
  269.     return(0);
  270.  
  271.   }
  272.  
  273. /*===========================================================================*/
  274. /* Return the current stack pointer                                          */
  275. /*===========================================================================*/
  276.  
  277. unsigned showsp(void)
  278.     {
  279. #ifdef __LARGE__
  280.       int dummy, *dummyp = &dummy;
  281.  
  282.       return (FP_OFF(dummyp));
  283. #else
  284.       int dummy; /* dummy variable allocated on stack so we can get its address */
  285.  
  286.       return ((unsigned) &dummy);
  287. #endif
  288.     }
  289.  
  290. /*===========================================================================*/
  291. /* Execute a command.  This routine is called (via the REXXCALL assembler    */
  292. /* interface) when REXX encounters a command to be processed by our          */
  293. /* environment                                                               */
  294. /*===========================================================================*/
  295.  
  296. int execute(FARP s, size_t l)
  297.   {
  298.     char *command;
  299.     int  arg_cnt;
  300.  
  301.     /*-----------------------------------------------------------------------*/
  302.     /* Copy the command into a C-style null terminated string                */
  303.     /*-----------------------------------------------------------------------*/
  304.  
  305.      command = malloc(l + 1);
  306.  
  307. #ifdef __LARGE__
  308.     strncpy(command, s, l);
  309. #else
  310.     movedata(HIGH_WORD(s), LOW_WORD(s), data_segment, (unsigned)command, l);
  311. #endif
  312.     command[l] = '\0';
  313.  
  314.     /*-----------------------------------------------------------------------*/
  315.     /* Change the command format                                             */
  316.     /*-----------------------------------------------------------------------*/
  317.  
  318.     arg_cnt = words(command) + 1;
  319.     if (arg_cnt > 3)
  320.       arg_cnt = 3;
  321.  
  322.     strcpy(arg_array1, subword(command, 1, 1));
  323.     strcpy(arg_array2, subword(command, 2, 1));
  324.  
  325.     arg_array[0] = command;
  326.     arg_array[1] = arg_array1;
  327.     arg_array[2] = arg_array2;
  328.  
  329.     /*-----------------------------------------------------------------------*/
  330.     /* OK.  Call the SGMLAPI for REXX                                        */
  331.     /*-----------------------------------------------------------------------*/
  332.     sgmlapir(arg_cnt, arg_array);
  333.  
  334.     /*-----------------------------------------------------------------------*/
  335.     /* All done                                                              */
  336.     /*-----------------------------------------------------------------------*/
  337.  
  338.     return(0);
  339.  
  340.     }
  341.  
  342. /*===========================================================================*/
  343. /* Display error message and terminate                                       */
  344. /*===========================================================================*/
  345.  
  346. void rexxerr(char *s)
  347.   {
  348.     printf("ABORT:- %s\n",s);
  349.     exit(255);
  350.   }
  351. /*****************************************************************************/
  352. /* REXX SGML interpreter.                                                    */
  353. /*     Subroutines                                                           */
  354. /*                                                                           */
  355. /* Author:  Roy Engehausen                                                   */
  356. /* Mods:    Jack Steitz          1. Bring code to ANSI standard              */
  357. /*                                                                           */
  358. /*                                                                           */
  359. /*****************************************************************************/
  360.  
  361. /*===========================================================================*/
  362. /* Local Macros                                                              */
  363. /*===========================================================================*/
  364.  
  365. #define skip2nb(p)  while( *p == ' ') ++p
  366. #define skip2ws(p)  while( (*p != ' ') && (*p != '\0') )++p
  367.  
  368. /*===========================================================================*/
  369. /* WORDS                                                                     */
  370. /*===========================================================================*/
  371.  
  372. int words(char *input_string)
  373.   {
  374.     int word_count = 0;
  375.  
  376.     skip2nb(input_string);
  377.     if (*input_string)
  378.       while(*input_string)
  379.       {
  380.         ++word_count;
  381.         skip2ws(input_string);
  382.         skip2nb(input_string);
  383.       }
  384.  
  385.     return (word_count);
  386.   }
  387.  
  388. /*===========================================================================*/
  389. /* SUBWORD                                                                   */
  390. /*===========================================================================*/
  391.  
  392. char *subword(char *input_string, int start_word, int number_words)
  393.   {
  394.     static char answer[100];
  395.  
  396.     char *substart;
  397.     int out_index = 0;
  398.     int end_word;
  399.     int word_count = 0;
  400.  
  401.     answer[0] = '\0';  /* Start with a zero-length string */
  402.  
  403.     if (number_words == 0)
  404.       end_word = words(input_string) + 1;
  405.     else
  406.       end_word = start_word + number_words;
  407.  
  408.     /* Skip leading white space */
  409.     skip2nb(input_string);
  410.  
  411.     if (*input_string && start_word > 0 )
  412.                  /* Do the rest only if we don't have an empty string */
  413.     {
  414.  
  415.         while (++word_count < start_word) /* Find the starting word */
  416.         {
  417.           skip2ws(input_string); /* Find the next blank or end of string */
  418.           skip2nb(input_string); /* Find the start of the next word */
  419.         }
  420.         substart = input_string;
  421.  
  422.         while ( (word_count < end_word) &&
  423.                 *input_string )           /* Find end of substring */
  424.         {
  425.           skip2ws(input_string);
  426.           if (++word_count < end_word)
  427.             skip2nb(input_string);
  428.         }
  429.         /* Now extract the substring into answer */
  430.         out_index = min(input_string - substart, sizeof(answer) - 1);
  431.         strncpy(answer, substart, out_index);
  432.         answer[out_index] = '\0';
  433.     }
  434.  
  435.     return answer;
  436.   }
  437.  
  438.