home *** CD-ROM | disk | FTP | other *** search
/ DOS/V Power Report 1996 February / VPR9602A.ISO / fwindows / tmedt090 / toold101 / xargs.c < prev   
C/C++ Source or Header  |  1995-11-19  |  14KB  |  510 lines

  1. #include <windows.h>
  2. #include <io.h>
  3.  
  4. typedef LPSTR FAR *LPLPSTR;
  5.  
  6. LPLPSTR FAR PASCAL CreateArgs(LPSTR);
  7. BOOL    FAR PASCAL DeleteArgs(LPLPSTR);
  8.  
  9. #define SIZE   256
  10. INT FAR PASCAL MakeArgument(HINSTANCE, LPSTR, LPSTR, LPINT, LPSTR, INT);
  11. char **AllocWildArgument(int argc, char **argv);
  12. int FreeWildArgument(char **wargs);
  13.  
  14. LPLPSTR FAR PASCAL CreateArgs(LPSTR lpszCmdParam)
  15. {
  16.     int argc;
  17.     int aArgv[SIZE];
  18.     char *argv[SIZE];
  19.     char szReturn[SIZE*2];
  20.     char szPath[MAX_PATH];
  21.     char *pszFile;
  22.     char *pszPriod;
  23.     int i;
  24.     char **wargv = NULL;
  25.  
  26.     /*------------------------*/
  27.     /* モジュール名を取得する */
  28.     /*------------------------*/
  29.     lstrcpy(szPath, lpszCmdParam);
  30.     pszFile = szPath;
  31.     pszPriod = strchr(pszFile, ' ');
  32.     if (pszPriod != NULL) *pszPriod = '\0';
  33.  
  34.     /*----------------------------------------*/
  35.     /* 引数を作成する(ワイルドカード展開なし) */
  36.     /*----------------------------------------*/
  37.     argc = MakeArgument(NULL, pszFile, lpszCmdParam,
  38.                         aArgv, szReturn, sizeof(szReturn));
  39.     for (i = 0; i <= argc; i++) {
  40.         argv[i] = szReturn + aArgv[i];
  41.     }
  42.  
  43.     /*--------------------*/
  44.     /* ワイルドカード展開 */
  45.     /*--------------------*/
  46.     return AllocWildArgument(argc, argv);
  47. }
  48.  
  49. BOOL FAR PASCAL DeleteArgs(LPLPSTR wargv)
  50. {
  51.     return (FreeWildArgument(wargv) == 0) ? TRUE : FALSE;
  52. }
  53.  
  54. char *cwStrrchr(char *s, int c)
  55. {
  56.     unsigned char *p;
  57.     unsigned char *pr;
  58.  
  59.     pr = NULL;
  60.     for (p = s; *p != '\0'; p++) {
  61.         /* for DBCS */
  62.         if (IsDBCSLeadByte(*p) == TRUE) {
  63.             p++;
  64.             if (*p == '\0') {
  65.                 break;
  66.             }
  67.             continue;
  68.         }
  69.         if (*p == c) {
  70.             pr = p;
  71.         }
  72.     }
  73.     return pr;
  74. }
  75.  
  76. /*--------------------------------------------*/
  77. /* AllocWildArgument ワイルドカード展開を行う */
  78. /*--------------------------------------------*/
  79. char **AllocWildArgument(int argc, char **argv)
  80. {
  81.     long lFind;
  82.     struct _finddata_t finddata;
  83.     int i;
  84.     char cStack;
  85.     char *pArgsNew;
  86.     char *pStr;
  87.     int nHeadLen;
  88.     int nBodyLen;
  89.     int nPos;
  90.     char **pArgv;
  91.     char *pArgs;
  92.  
  93.     /*-------------------------------------------------------*/
  94.     /* 環境変数形式("arg0\0arg2\0arg3\0...argvx\0\0") に展開 */
  95.     /*-------------------------------------------------------*/
  96.  
  97.     /*-------------------------------*/
  98.     /* 最初の引き数 (実行ファイル名) */
  99.     /*-------------------------------*/
  100.     nPos = 0;
  101.     nHeadLen = 0;
  102.     nBodyLen = strlen(argv[0]);
  103.  
  104.     pArgsNew = malloc(nPos + nHeadLen + nBodyLen + 1);
  105.     if (pArgsNew == NULL) {
  106.         return NULL;
  107.     }
  108.     pArgs = pArgsNew;
  109.     strcpy(pArgs + nPos, argv[0]);
  110.     nPos += nHeadLen + nBodyLen + 1;
  111.  
  112.     /*--------------------*/
  113.     /* ワイルドカード展開 */
  114.     /*--------------------*/
  115.     for (i = 1; i < argc; i++) {
  116.  
  117.         /*--------------*/
  118.         /* ドライブ文字 */
  119.         /*--------------*/
  120.         if (lstrlen(argv[i]) == 2 && argv[i][1] == ':') {
  121.             nHeadLen = 0;
  122.             nBodyLen = strlen(argv[i]);
  123.  
  124.             pArgsNew = realloc(pArgs, nPos + nHeadLen + nBodyLen + 1);
  125.             if (pArgsNew == NULL) {
  126.                 free(pArgs);
  127.                 return NULL;
  128.             }
  129.             pArgs = pArgsNew;
  130.  
  131.             strcpy(pArgs + nPos, argv[i]);
  132.             nPos += nHeadLen + nBodyLen + 1;
  133.  
  134.             continue;
  135.         }
  136.         finddata.attrib = _A_NORMAL;
  137.         lFind = _findfirst(argv[i], &finddata);
  138.  
  139.         /*------------------------*/
  140.         /* ワイルドカード文字なし */
  141.         /*------------------------*/
  142.         if (lFind == -1 || cwStrrchr(argv[i], '*') == NULL &&
  143.                            cwStrrchr(argv[1], '?') == NULL) {
  144.  
  145.             nHeadLen = 0;
  146.             nBodyLen = strlen(argv[i]);
  147.  
  148.             pArgsNew = realloc(pArgs, nPos + nHeadLen + nBodyLen + 1);
  149.             if (pArgsNew == NULL) {
  150.                 free(pArgs);
  151.                 return NULL;
  152.             }
  153.             pArgs = pArgsNew;
  154.  
  155.             strcpy(pArgs + nPos, argv[i]);
  156.             nPos += nHeadLen + nBodyLen + 1;
  157.  
  158.             continue;
  159.         }
  160.  
  161.         /*------------------------*/
  162.         /* ワイルドカード文字あり */
  163.         /*------------------------*/
  164.  
  165.         /*------------------------*/
  166.         /* ディレクトリ部分を分離 */
  167.         /*------------------------*/
  168.         pStr = cwStrrchr(argv[i], '\\');
  169.         if (pStr == NULL) {
  170.             pStr = cwStrrchr(argv[i], '/');
  171.             if (pStr == NULL) {
  172.                 pStr = (argv[i][1] == ':') ? &argv[i][2] : &argv[i][0];
  173.             } else {
  174.                 pStr++;
  175.             }
  176.         } else {
  177.             pStr++;
  178.         }
  179.  
  180.         do {
  181.             if (lstrcmp(finddata.name, ".") == 0 ||
  182.                 lstrcmp(finddata.name, "..") == 0) {
  183.                 continue;
  184.             }
  185.  
  186.             cStack = *pStr; *pStr = '\0';
  187.  
  188.             /*--------------*/
  189.             /* 領域にコピー */
  190.             /*--------------*/
  191.             nHeadLen = strlen(argv[i]);
  192.             nBodyLen = strlen(finddata.name);
  193.  
  194.             pArgsNew = realloc(pArgs, nPos + nHeadLen + nBodyLen + 1);
  195.             if (pArgsNew == NULL) {
  196.                 free(pArgs);
  197.                 return NULL;
  198.             }
  199.             pArgs = pArgsNew;
  200.             strcpy(pArgs + nPos, argv[i]);
  201.             strcat(pArgs + nPos, finddata.name);
  202.             nPos += nHeadLen + nBodyLen + 1;
  203.  
  204.             *pStr = cStack;
  205.         } while (_findnext(lFind, &finddata) == 0);
  206.         _findclose(lFind);
  207.     }
  208.     /*-------------------------*/
  209.     /* 終端文字列を確保 ("\0") */
  210.     /*-------------------------*/
  211.     pArgs = realloc(pArgs, nPos + 1);
  212.     pArgs[nPos] = '\0';
  213.  
  214.     /*--------------------------------*/
  215.     /* 環境変数形式から引数形式に変換 */
  216.     /*--------------------------------*/
  217.     for (i = 0, pStr = pArgs; *pStr != '\0'; i++, pStr += strlen(pStr) + 1);
  218.     pArgv = malloc((i + 1) * sizeof(char *));
  219.     if (pArgv == NULL) {
  220.         free(pArgs);
  221.         return NULL;
  222.     }
  223.     for (i = 0, pStr = pArgs; *pStr != '\0'; i++, pStr += strlen(pStr) + 1) {
  224.         pArgv[i] = pStr;
  225.     }
  226.     pArgv[i] = pStr;
  227.     return pArgv;
  228. }
  229.  
  230. /*--------------------------------------------*/
  231. /* ワイルドカード展開用に確保された領域を解放 */
  232. /*--------------------------------------------*/
  233. int FreeWildArgument(char **wargs)
  234. {
  235.     if (wargs == NULL) {
  236.         return -1;
  237.     }
  238.     free(wargs[0]);
  239.     free(wargs);
  240.     return 0;
  241. }
  242.  
  243. /*=============================================================*/
  244. /*------------------------------------------------*/
  245. /* 付録 << MakeArgument API >>                    */
  246. /* コマンドラインの引き数を展開します。           */
  247. /* ComWin からの引用です。日本語対応は不十分です。*/
  248. /* "" で囲まれた文字列は一つのトークンです。      */
  249. /* '^' をエスケープ文字として扱っています。       */
  250. /*------------------------------------------------*/
  251. /*------------------*/
  252. /* 引き数を作成する */
  253. /*------------------*/
  254. static LPSTR SkipHat(LPSTR s)
  255. {
  256.     s++;
  257.     if (*s != '\0') {
  258.         s++;
  259.     }
  260.     return s;
  261. }
  262.  
  263. static LPSTR SkipSpace(LPSTR s)
  264. {
  265.     while (*s != '\0') {
  266.         if (*s == ' ' || *s == '\t') {
  267.             s++;
  268.         } else {
  269.             break;
  270.         }
  271.     }
  272.     return s;
  273. }
  274.  
  275. static LPSTR SearchSpace(LPSTR s)
  276. {
  277.     while (*s != '\0') {
  278.         if (*s == ' ' || *s == '\t') {
  279.             break;
  280.         } else {
  281.             s++;
  282.         }
  283.     }
  284.     return s;
  285. }
  286.  
  287. static int lstrcmpni(LPSTR s1, LPSTR s2, int nLength)
  288. {
  289.     int i;
  290.     int c1, c2;
  291.     int cs1, cs2;
  292.  
  293.     for (i = 0; i < nLength && *s1 != '\0' && *s2 != '\0'; i++, s1++, s2++) {
  294.         cs1 = (int)(unsigned char)*s1;
  295.         cs2 = (int)(unsigned char)*s2;
  296.         c1 = (cs1 < 'a') ? cs1 : cs1 - 'a' + 'A';
  297.         c2 = (cs2 < 'a') ? cs2 : cs2 - 'a' + 'A';
  298.         if (c1 != c2) {
  299.             return c2 - c1;
  300.         }
  301.     }
  302.     if (i == nLength) {
  303.         return 0;
  304.     }
  305.     return *s2 - *s1;
  306. }
  307.  
  308. static LPSTR SearchDQuoto(LPSTR s)
  309. {
  310.     s++;
  311.     while (*s != '\0') {
  312.         if (*s == '^') {
  313.             s = SkipHat(s);
  314.         } else if (*s == '\"') {
  315.             s++;
  316.             break;
  317.         } else {
  318.             s++;
  319.         }
  320.     }
  321.     return s;
  322. }
  323.  
  324. static int GetLastChar(char *s)
  325. {
  326.     int c;
  327.     unsigned char *p;
  328.  
  329.     c = '\0';
  330.     for (p = s; *p != '\0'; p++) {
  331.         if (IsDBCSLeadByte(*p) == TRUE) {
  332.             c = '\0';
  333.             p++;
  334.             if (*p == '\0') {
  335.                 break;
  336.             }
  337.             continue;
  338.         }
  339.         c = *p;
  340.     }
  341.     return c;
  342. }
  343.  
  344. static BOOL CheckCutChar(int c)
  345. {
  346.     switch (c) {
  347.         case '\0':
  348.         case ' ':
  349.         case '\t':
  350.         case '/':
  351.         case '\\':
  352.         case '.':
  353.             return TRUE;
  354.         default:
  355.             return FALSE;
  356.     }
  357. }
  358.  
  359. static LPSTR ConvertHatChar(LPSTR lpStr, int nMode)
  360. {
  361.     LPSTR lpSrc;
  362.     LPSTR lpDst;
  363.     int nSrc;
  364.     int nSrcNew;
  365.     int nSrcLen;
  366.     int nDst;
  367.  
  368.     lpDst = lpStr;
  369.     nDst = 0;
  370.     for (lpSrc = lpStr; *lpSrc != '\0'; lpSrc += nSrcLen + 1) {
  371.         nSrcLen = lstrlen(lpSrc);
  372.         for (nSrc = 0; nSrc < nSrcLen; nSrc++) {
  373.             if (nMode == 1) {
  374.                 if (lpSrc[nSrc] != '\"') {
  375.                     lpDst[nDst] = lpSrc[nSrc]; nDst++;
  376.                     continue;
  377.                 }
  378.                 nSrcNew = SearchDQuoto(&lpSrc[nSrc]) - lpSrc;
  379.                 for (; nSrc < nSrcNew; nSrc++) {
  380.                     if (lpSrc[nSrc] == '\"') {
  381.                         continue;
  382.                     }
  383.                     if (lpSrc[nSrc] == '^') {
  384.                         int nSrcNew2;
  385.                         char cStack, cLast;
  386.                         /* for non ASCII char set */
  387.                         cStack = lpSrc[nSrc+1]; lpSrc[nSrc+1] = '\0';
  388.                         cLast = GetLastChar(lpSrc);
  389.                         lpSrc[nSrc+1] = cStack;
  390.                         if (cLast != '^') {
  391.                             lpDst[nDst] = lpSrc[nSrc]; nDst++;
  392.                             continue;
  393.                         }
  394.                         nSrcNew2 = SkipHat(&lpSrc[nSrc]) - lpSrc;
  395.                         for (nSrc++; nSrc < nSrcNew2; nSrc++) {
  396.                             lpDst[nDst] = lpSrc[nSrc]; nDst++;
  397.                         }
  398.                         nSrc = nSrcNew2 - 1;
  399.                         continue;
  400.                     }
  401.                     lpDst[nDst] = lpSrc[nSrc]; nDst++;
  402.                 }
  403.                 nSrc = nSrcNew - 1;
  404.                 continue;
  405.             }
  406.             if (lpSrc[nSrc] == '\"') {
  407.                 nSrcNew = SearchDQuoto(&lpSrc[nSrc]) - lpSrc;
  408.                 for (; nSrc < nSrcNew; nSrc++) {
  409.                     lpDst[nDst] = lpSrc[nSrc]; nDst++;
  410.                 }
  411.                 nSrc = nSrcNew - 1;
  412.                 continue;
  413.             }
  414.             if (lpSrc[nSrc] == '^') {
  415.                 char cStack, cLast;
  416.                 /* for non ASCII char set */
  417.                 cStack = lpSrc[nSrc+1]; lpSrc[nSrc+1] = '\0';
  418.                 cLast = GetLastChar(lpSrc);
  419.                 lpSrc[nSrc+1] = cStack;
  420.                 if (cLast != '^') {
  421.                     lpDst[nDst] = lpSrc[nSrc]; nDst++;
  422.                     continue;
  423.                 }
  424.                 nSrcNew = SkipHat(&lpSrc[nSrc]) - lpSrc;
  425.                 for (nSrc++; nSrc < nSrcNew; nSrc++) {
  426.                     lpDst[nDst] = lpSrc[nSrc]; nDst++;
  427.                 }
  428.                 nSrc = nSrcNew - 1;
  429.                 continue;
  430.             }
  431.             lpDst[nDst] = lpSrc[nSrc]; nDst++;
  432.         }
  433.         lpDst[nDst] = '\0'; nDst++;
  434.     }
  435.     lpDst[nDst] = '\0';
  436.     return lpDst;
  437. }
  438.  
  439. static int GetArgument(LPSTR lpSrc, LPSTR lpReturn, int nSize)
  440. {
  441.      LPSTR lpB;
  442.      LPSTR lpE;
  443.      LPSTR lpD;
  444.  
  445.      lpD = lpReturn;
  446.      for (lpB = SkipSpace(lpSrc); *lpB != '\0'; lpB = SkipSpace(lpE)) {
  447.         lpE = (*lpB != '\"') ? SearchSpace(lpB) : SearchDQuoto(lpB);
  448.         if (lpReturn + nSize - 1 < lpD + (lpE - lpB)) {
  449.             break;
  450.         }
  451.         lstrcpyn(lpD, lpB, lpE - lpB + 1);
  452.         lpD += lpE - lpB; *lpD = '\0'; lpD++;
  453.      }
  454.      *lpD = '\0';
  455.      return 0;
  456. }
  457.  
  458. int FAR PASCAL MakeArgument(HINSTANCE hInstance,
  459.                             LPSTR lpCmd,
  460.                             LPSTR lpParam,
  461.                             LPINT lpArgv,
  462.                             LPSTR lpRet,
  463.                             int nSize)
  464. {
  465.     LPSTR lpB;
  466.     LPSTR lpP;
  467.     LPSTR lpE;
  468.     LPSTR lpD;
  469.     int nArgc;
  470.  
  471.     lpB = SkipSpace(lpCmd);
  472.     lpE = (*lpB != '\"') ? SearchSpace(lpB) : SearchDQuoto(lpB);
  473.     lpP = lpParam;
  474.     lpD = lpRet;
  475.  
  476.     if (hInstance == NULL) {
  477.         lpP = SkipSpace(lpP);
  478.         if (lstrcmpni(lpB, lpP, lpE - lpB) == 0 &&
  479.                 CheckCutChar(lpP[lpE - lpB]) == TRUE) {
  480.             if (lpRet + nSize - 1 < lpD + (lpE - lpB)) {
  481.                 lpRet[0] = '\0';
  482.                 lpArgv[0] = 0;
  483.                 return 0;
  484.             }
  485.             lstrcpyn(lpD, lpB, lpE - lpB + 1);
  486.             lpP += lpE - lpB;
  487.             lpD += lpE - lpB; *lpD = '\0'; lpD++;
  488.         }
  489.     } else {
  490.         if (lpRet + nSize - 1 < lpD + (lpE - lpB)) {
  491.            lpRet[0] = '\0';
  492.            lpArgv[0] = 0;
  493.            return 0;
  494.         }
  495.         lstrcpyn(lpD, lpB, lpE - lpB + 1);
  496.         lpD += lpE - lpB; *lpD = '\0'; lpD++;
  497.     }
  498.  
  499.     GetArgument(lpP, lpD, lpRet + nSize - lpD);
  500.     ConvertHatChar(lpRet, 1);
  501.  
  502.     nArgc = 0;
  503.     for (lpD = lpRet; *lpD != '\0'; lpD += lstrlen(lpD) + 1) {
  504.         lpArgv[nArgc] = lpD - lpRet; nArgc++;
  505.     }
  506.     lpArgv[nArgc] = '\0';
  507.     return nArgc;
  508. }
  509. /*=============================================================*/
  510.