home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 2: PC / frozenfish_august_1995.bin / bbs / d07xx / d0770.lha / Uedit / Kienitz.LZH / frx / frx.c < prev    next >
C/C++ Source or Header  |  1991-03-14  |  9KB  |  355 lines

  1. /* frx -- like rx but different -- see frx.doc */
  2.  
  3.  
  4. #include <exec/exec.h>
  5. #include <libraries/dosextens.h>
  6. #include <rexx/storage.h>
  7. #include <rexx/rxslib.h>
  8. #include <paul.h>
  9.  
  10.  
  11. struct RxsLib *RexxSysBase;
  12.  
  13.  
  14. struct RexxMsg * CreateRexxMsg(struct MsgPort *reply, str extension, str host);
  15. void             DeleteRexxMsg(struct RexxMsg *message);
  16. long         FillRexxMsg(struct RexxMsg *message, long count, long mask);
  17. void         ClearRexxMsg(struct RexxMsg *message, long count);
  18. void /* ubyte */ StrcpyU(str dest, str source, long length);
  19. short            StrcmpU(str a, str b, long length);
  20. char             ToUpper(char c);
  21. struct RexxRsrc *FindRsrcNode(struct List *list, char *name, long type);
  22. void             DeleteArgstring(str argstring);
  23.  
  24. #pragma amicall(RexxSysBase, 0x90, CreateRexxMsg(a0, a1, d0))
  25. #pragma amicall(RexxSysBase, 0x96, DeleteRexxMsg(a0))
  26. #pragma amicall(RexxSysBase, 0xA2, FillRexxMsg(a0, d0, d1))
  27. #pragma amicall(RexxSysBase, 0x9C, ClearRexxMsg(a0, d0))
  28. #pragma amicall(RexxSysBase, 0x114, StrcpyU(a0, a1, d0))
  29. #pragma amicall(RexxSysBase, 0x102, StrcmpU(a0, a1, d0))
  30. #pragma amicall(RexxSysBase, 0x126, ToUpper(d0))
  31. #pragma amicall(RexxSysBase, 0xB4, FindRsrcNode(a0, a1, d0))
  32. #pragma amicall(RexxSysBase, 0x84, DeleteArgstring(a0))
  33.  
  34. #asm
  35.         public        _ErrorMsg     ; glue routine
  36. _ErrorMsg:    move.l        _RexxSysBase,a6
  37.         jsr        -$60(a6)
  38.         move.l        a0,d0
  39.         addq.l        #8,d0         ; NexxStr *  =>  str 
  40.         rts
  41.  
  42.         public        _CVa2i        ; glue routine
  43. _CVa2i:        move.l        _RexxSysBase,a6
  44.         jsr        -$12C(a6)
  45.         move.l        d1,(a3)        ; number of digits scanned
  46.         rts
  47. #endasm
  48.  
  49. str ErrorMsg(long code);
  50. long CVa2i(str buf, long *digits);
  51.  
  52. #pragma regcall(ErrorMsg(d0))
  53. #pragma regcall(CVa2i(a0,a3))
  54.  
  55.  
  56.  
  57. typedef struct {
  58.     short argc, bargc;
  59.     char argline[600];        /* bigger than necessary */
  60.     str argv[32];        /* all we can use */
  61.     str barg[16];
  62.     ubyte bits[16];
  63. } glob;
  64.  
  65. #define NOGOBBLE  2
  66. #define MATCHONLY 4
  67. #define REQUIRED  8
  68.  
  69.  
  70.  
  71. void spew(str s)
  72. {
  73.     register BPTR o = ThisProcess()->pr_COS;
  74.     if (o) Write(o, s, (long) strlen(s));
  75. }
  76.  
  77.  
  78.  
  79. /* This version of cliparse features handling of internal quotes BCPL-style
  80.    with *" instead of Manx "".  *N and *E are supported.  With all args
  81.    except argv[0] (the command name) you can see if it was quoted by looking
  82.    at whether argv[n][-1] is a double-quote or a nul. */
  83.  
  84. void cliparse(glob *g, long alen, register str ap, bool skippy)
  85. {
  86.     register short coml, al;
  87.     bool quoted, star;
  88.     register ubyte c;
  89.     register str poik;
  90.  
  91.     if (skippy) {
  92.     g->argc = 2;
  93.     coml = strlen(g->argline) + 1;
  94.     coml += strlen(g->argline + coml);
  95.     } else {
  96.     poik = bip(char, bip(struct CommandLineInterface,
  97.                  ThisProcess()->pr_CLI)->cli_CommandName);
  98.     coml = *poik;
  99.     strncpy(g->argline, poik + 1, (size_t) coml);
  100.     g->argline[coml] = '\0';
  101.     *g->argv = &g->argline[0];
  102.     g->argc = 1;
  103.     }
  104.     if (al = alen) {
  105.     poik = g->argline + coml + 1;
  106.     for (;;) {
  107.         while (al && *ap <= ' ') ap++, al--;
  108.         if (!al) break;
  109.         star = false;
  110.         if (quoted = *ap == '"')
  111.         *(poik++) = *(ap++), al--;
  112.         g->argv[g->argc] = poik;
  113.         if (++g->argc > 30) break;
  114.         while (al && (c = (ubyte) *ap) &&
  115.                 (quoted ? star || c != '"' : c > ' ')) {
  116.         if (star) {
  117.             if (ToUpper(c) == 'E') c = 27;
  118.             else if (ToUpper(c) == 'N') c = '\n';
  119.             star = false;
  120.             *(poik++) = c;
  121.         } else if (!(star = quoted && c == '*'))
  122.             *(poik++) = c;
  123.         ap++, al--;
  124.         }
  125.         if (*ap == '"') ap++, al--;
  126.         *(poik++) = '\0';
  127.     }
  128.     }
  129. }
  130.  
  131.  
  132.  
  133. str ClipNodeVal(str name)        /* why wasn't this provided? */
  134. {
  135.     struct RexxRsrc *cn = FindRsrcNode(&RexxSysBase->rl_ClipList, name, 0);
  136.     if (cn) return (str) cn->rr_Arg1;        /****** ?????? ******/
  137.     else return null;            /* What about the arg's LENGTH? */
  138. }
  139.  
  140.  
  141.  
  142. short WhatKeyword(str word, register str plate, glob *g)
  143. {
  144.     short w;
  145.     bool start = true;
  146.     for (w = 0; *plate; plate++) {
  147.     if (start && !g->barg[w]) {
  148.         short l = 0;
  149.         register str p = plate;
  150.         while (*p && *p != '/' && *p != ',' && *p != '=')
  151.         p++, l++;
  152.         if (l == strlen(word) && !StrcmpU(word, plate, (long) l))
  153.         return w;
  154.         start = false;
  155.     } else if (*plate == '=')
  156.         start = true;
  157.     else if (*plate == ',')
  158.         start = true, w++;
  159.     else start = false;
  160.     }
  161.     return -1;
  162. }
  163.  
  164.  
  165.  
  166. void Chew(glob *g, str plate)
  167. {
  168.     short i, n;
  169.     str t;
  170.     bool slash = false;
  171.  
  172.     for (t = plate; *t; t++)
  173.         if (*t == ',')
  174.         g->bargc++;
  175.     else if (*t == '/')
  176.         slash = true;
  177.     else if (slash) {
  178.         char tt = ToUpper(*t);
  179.         if (tt == 'S')
  180.         g->bits[g->bargc] |= NOGOBBLE | MATCHONLY;
  181.         else if (tt == 'K')
  182.         g->bits[g->bargc] |= MATCHONLY;
  183.         else if (tt == 'A')
  184.         g->bits[g->bargc] |= REQUIRED;
  185.         slash = false;
  186.     }
  187.     g->bargc++;
  188.     for (i = 2; i < g->argc; i++)
  189.     if (!g->argv[i][-1] && ~(n = WhatKeyword(g->argv[i], plate, g))) {
  190.         if (!(g->bits[n] & NOGOBBLE)) {
  191.         g->argv[i] = null;
  192.         if (!g->argv[++i]) {
  193.             g->argc = 1001;
  194.             spew("Bad arguments:  no value after template keyword.\n");
  195.             return;
  196.         }
  197.         } else {            /*  /S  */
  198.         register str a = g->argv[i];
  199.         while (*a) *(a++) = ToUpper(*a);
  200.         }
  201.         g->barg[n] = g->argv[i];
  202.         g->argv[i] = null;
  203.     }
  204.     for (i = 2; i < g->argc; i++)
  205.     if (g->argv[i]) {
  206.         for (n = 0; n < g->bargc; n++)
  207.         if (!g->barg[n] && !(g->bits[n] & MATCHONLY)) break;
  208.         if (n >= g->bargc) {
  209.         g->argc = 1002;
  210.         spew("Bad arguments:  too many for template.\n");
  211.         return;
  212.         }
  213.         g->barg[n] = g->argv[i];
  214.     }
  215.     for (n = 0; n < g->bargc; n++)
  216.     if (!g->barg[n] && g->bits[n] & REQUIRED) {
  217.         g->argc = 1003;
  218.         spew("Bad arguments:  required argument not given.\n");
  219.         return;
  220.     }
  221.     g->argc = g->bargc + 2;
  222.     for (n = 0; n < g->bargc; n++)
  223.     g->argv[n + 2] = g->barg[n];
  224.     g->argv[g->argc] = null;
  225. }
  226.  
  227.  
  228.  
  229. long _main(long alen, str aptr)
  230. {
  231.     struct MsgPort *duh, *zex;
  232.     struct RexxMsg *mess, *m2;
  233.     long air = 0, ret = 0;
  234.     short i;
  235.     glob g;
  236.     char clipname[300], newargline[300];
  237.     str a1, template;
  238.  
  239.     memset(&g, 0, sizeof(g));
  240.     if (!(zex = FindPort("REXX")) ||
  241.         !(RexxSysBase = (adr) OpenLibrary("rexxsyslib.library", 0))) {
  242.     spew("No ARexx!\n");
  243.     air = ERROR_INVALID_RESIDENT_LIBRARY;
  244.     ret = 20;
  245.     goto quit5;
  246.     }
  247.     cliparse(&g, alen, aptr, false);
  248.     if (!g.argv[1] || (*g.argv[1] == '?' && !g.argv[1][1]
  249.                     && !g.argv[1][-1] && !g.argv[2])) {
  250.     spew("Usage: ");
  251.     spew(*g.argv);
  252.     spew(" RexxFunction [arg] [arg] ...\n");
  253.     ret = 20;
  254.     air = ERROR_LINE_TOO_LONG;
  255.     goto quit3;
  256.     }
  257.  
  258.     a1 = g.argv[1];
  259.     if (!StrcmpU(a1, "REXX:", 5))
  260.     a1 += 5;
  261.     i = strlen(a1);
  262.     StrcpyU(clipname, a1, (long) i);
  263.     strcpy(clipname + i, "-TEMPLATE");
  264.     i = 0;
  265.     template = ClipNodeVal(clipname);
  266.     while (*g.argv[2] == '?' && !g.argv[2][1] && !g.argv[2][-1] && !g.argv[3]) {
  267.     if (Input()) {
  268.         if (template) {
  269.         spew(template);
  270.         spew(": ");
  271.         } else {
  272.         spew(clipname);
  273.         spew(" not found\nArguments: ");
  274.         }
  275.         alen = Read(Input(), newargline, 299);
  276.         if (alen < 0) alen = 0;
  277.     } else
  278.         alen = 0;
  279.     cliparse(&g, alen, newargline, true);
  280.     g.argv[g.argc] = null;
  281.     }
  282.  
  283.     if (template)
  284.     Chew(&g, template);
  285.     /* we'll just ASSUME nobody deletes the template while we're using it */
  286.     if (g.argc > 17) {
  287.     if (g.argc < 100) spew("Fifteen function arguments maximum!\n");
  288.     air = ERROR_LINE_TOO_LONG;
  289.     ret = 20;
  290.     goto quit3;
  291.     }
  292.     if (!(duh = CreatePort(null, 0))) {
  293.     spew("Can't open message port!\n");
  294.     air = ERROR_NO_FREE_STORE;
  295.     ret = 20;
  296.     goto quit3;
  297.     }
  298.     if (!(mess = CreateRexxMsg(duh, null, null))) {
  299.     spew("Can't create RexxMsg!\n");
  300.     air = ERROR_NO_FREE_STORE;
  301.     ret = 20;
  302.     goto quit2;
  303.     }
  304.  
  305.     for (i = 0; i < g.argc - 1; i++)
  306.     mess->rm_Args[i] = (adr) g.argv[i + 1];
  307.     if (!FillRexxMsg(mess, (long) g.argc - 1, 0)) {
  308.     spew("No memory!\n");
  309.     air = ERROR_NO_FREE_STORE;
  310.     ret = 20;
  311.     goto quit1;
  312.     }
  313.     mess->rm_Action = RXFUNC | RXFF_RESULT | g.argc - 1;
  314.     PutMsg(zex, (adr) mess);
  315.     WaitPort(duh);
  316.     while (!(m2 = (adr) GetMsg(duh)) || m2 != mess)
  317.     if (!m2) WaitPort(duh);
  318.  
  319.     if (mess->rm_Result2)
  320.     if (mess->rm_Result1) {
  321.         str s = ErrorMsg(mess->rm_Result2);
  322.         spew("ARexx error: ");
  323.         spew((str) s);
  324.         spew(".\n");
  325.         ret = mess->rm_Result1;
  326.         if ((air = mess->rm_Result2) == 1)        /* program not found */
  327.         ret = 10;                /* instead of 5 */
  328.     } else {
  329.         struct RexxArg *r = (adr) ((str) mess->rm_Result2 - 8);
  330.         long l;
  331.         long x = CVa2i(r->ra_Buff, &l);
  332.         if (l == r->ra_Length)
  333.         ret = air = x;
  334.         else {
  335.         air = 47;
  336.         ret = 10;
  337.         spew("ARexx error: arithmetic conversion error.\n");
  338.         }
  339.         DeleteArgstring((str) mess->rm_Result2);
  340.     }
  341.     else
  342.     air = ret = mess->rm_Result1;
  343.  
  344.     ClearRexxMsg(mess, (long) g.argc - 1);
  345. quit1:
  346.     DeleteRexxMsg(mess);
  347. quit2:
  348.     DeletePort(duh);
  349. quit3:
  350.     CloseLibrary((adr) RexxSysBase);
  351. quit5:
  352.     ThisProcess()->pr_Result2 = air;
  353.     return ret;
  354. }
  355.