home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / uucp / duucp-1.17 / AU-117b-upd1.lha / upd1 / adj / adj.c next >
Encoding:
C/C++ Source or Header  |  1993-06-11  |  15.7 KB  |  757 lines

  1. /*
  2.                              Adjust DMakefile
  3.  
  4.                              Chris Hind Genly
  5.  
  6.                                  6/10/93
  7.  
  8.                              Chris Hind Genly
  9.  
  10.                          Eggplant Software Tools
  11.  
  12.                       chris@Eggplant.New-Haven.CT.US
  13.  
  14. This is a public domain file.
  15.  
  16. */
  17.  
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <stdio.h>
  21.  
  22. #define TRUE 1
  23. #define FALSE 0
  24.  
  25. int lineNum;
  26.  
  27. int  filecnt = 0;
  28. char *files[100];
  29.  
  30. typedef enum {C_NONE, C_DICE, C_SASC} CompilerType;
  31.  
  32. CompilerType compiler = C_NONE;
  33. int force = FALSE;
  34.  
  35. int commentsOn = FALSE;
  36. int inFor = FALSE;
  37.  
  38. #define LINE_MAX 200
  39.  
  40. char *skip_ws(char *p)
  41. {
  42.     while(*p == ' ' || *p == '\t')
  43.         ++p;
  44.  
  45.     return p;
  46. }
  47.  
  48. void CopyBlanks(char **pl, char **pa)
  49. {
  50.     char *l = *pl;
  51.     char *a = *pa;
  52.  
  53.     while(*l == ' ' || *l == '\t')
  54.         *a++ = *l++;
  55.  
  56.     *a = 0;
  57.  
  58.     *pl = l;
  59.     *pa = a;
  60. }
  61.  
  62. int IsOptChar(char c, int eq)
  63. {
  64.     return 'a' <= c && c <= 'z'
  65.        ||  'A' <= c && c <= 'Z'
  66.        ||  '0' <= c && c <= '9'
  67.        ||  c == '-'
  68.        ||  c == '_'
  69.        ||  c == '.'
  70.        ||  c == ':'
  71.        ||  c == '/'
  72.        ||  c == '=' && eq;
  73. }
  74.  
  75. void CopyToMatch(char **pl, char**pt, char endchar)
  76. {
  77.     char *l = *pl;
  78.     char *t = *pt;
  79.     char c;
  80.  
  81.     while(c = *l) {
  82.         *t++ = *l++;
  83.         if (c == endchar) break;
  84.     }
  85.  
  86.     *t = 0;
  87.  
  88.     *pl = l;
  89.     *pt = t;
  90. }
  91.  
  92.  
  93. typedef enum {T_EOL, T_MACRO, T_EQUAL, T_FILE, T_STRING, T_OTHER} TokenType;
  94.  
  95. TokenType GetToken(char **pl, char *token, int eq)
  96. {
  97.     char *l = *pl;
  98.     char *t = token;
  99.     TokenType type;
  100.  
  101.     switch(*l) {
  102.     case '\n':
  103.         type = T_EOL;
  104.         *t++ = *l++;
  105.         break;
  106.     case '$':
  107.     case '%':
  108.         type = T_MACRO;
  109.         *t++ = *l++;
  110.         if (*l == '(')
  111.             CopyToMatch(&l, &t, ')');
  112.         else
  113.         if (*l == '{')
  114.             CopyToMatch(&l, &t, '}');
  115.         else
  116.             *t++ = *l++;
  117.         break;
  118.     case '"':
  119.         type = T_STRING;
  120.         *t++ = *l++;
  121.         CopyToMatch(&l, &t, '"');
  122.         break;
  123.     case '=':
  124.         if (eq) {
  125.             type = T_EQUAL;
  126.             *t++ = *l++;
  127.             break;
  128.         }
  129.  
  130.     default:
  131.         while(IsOptChar(*l, !eq))
  132.             *t++ = *l++;
  133.  
  134.         if (t >= token+2 && t[-2] == '.')
  135.             type = T_FILE;
  136.         else
  137.             type = T_OTHER;
  138.         break;
  139.     }
  140.  
  141.     *t = 0;
  142.     *pl = l;
  143.  
  144.     return type;
  145. }
  146.  
  147. struct opt_tag {
  148.     char *sasc;
  149.     char *dcc;
  150.     enum {C_PRESENT, C_MISSING, C_ALWAYS} copt;
  151. } optvec[] = {
  152.     "AddSymbols",       "-s",      C_ALWAYS,
  153.     "Code=near",        "-mc",     C_ALWAYS,
  154.     "Code=far",         "-mC",     C_ALWAYS,
  155.     "CPU=68020",        "-020",    C_ALWAYS,
  156.     "CPU=68030",        "-030",    C_ALWAYS,
  157.     "Data=near",        "-md",     C_ALWAYS,
  158.     "Data=far",         "-mD",     C_ALWAYS,
  159.     "IDIR=",            "-I_",     C_ALWAYS,
  160.     "Define=",          "-D_",     C_ALWAYS,
  161.     "Library=",         "-l_",     C_ALWAYS,
  162.     "Math=68881",       "-881",    C_ALWAYS,
  163.     "Math=68882",       "-882",    C_ALWAYS,
  164.     "ObjectName=",      "-o_",     C_PRESENT,
  165.     "ProgramName=",     "-o_",     C_MISSING,
  166.     "StackExtend",      "-gs",     C_ALWAYS,
  167.     "Startup=cres",     "-r",      C_ALWAYS,
  168.     "Verbose",          "-v",      C_ALWAYS,
  169.     0
  170. };
  171.  
  172. /*
  173.  
  174.  SASC options are case insensitive.
  175.  DICE options are case sensitive.
  176.  
  177.  When scanning an SASC option, '=' in the table implies an optional
  178.  '=' optionally surrounded by blanks in line.
  179.  
  180.  When scanning an SASC option, if the '=' is the last char in the
  181.  table, then the following token on the line is to be copied to
  182.  adjustedLine.
  183.  
  184.  When scanning a DICE option, '_' means optional spaces.  The '_'
  185.  should not be placed in to the adjusted line when generating
  186.  DICE options.  The following token on the line is to be copied
  187.  to adjustedLine.
  188.  
  189.  When reading a dcc line, the qualifiers C_PRESENT and C_MISSING apply.
  190.  
  191.     C_PRESENT      Entry applies when '-c' is present.
  192.     C_MISSING      Entry applies when '-c' is missing.
  193.     C_ALWAYS       Entry always applies regardless of whether or not
  194.                      '-c' is present, and regardless if this is a dcc or
  195.                      sc line.
  196.  
  197. */
  198. struct opt_tag * SascFindOption(char **pl, int cflag)
  199. {
  200.     struct opt_tag *opt;
  201.     char *l, *d;
  202.  
  203.     for(opt = optvec; opt->sasc; ++opt) {
  204.         if (opt->copt == C_PRESENT && cflag
  205.         ||  opt->copt == C_MISSING && !cflag
  206.         ||  opt->copt == C_ALWAYS)
  207.             ;
  208.         else
  209.             continue;
  210.  
  211.         l=*pl;
  212.         d=opt->dcc;
  213.  
  214.         while(1) {
  215.             if (*d == '\0') {
  216.                 if (*l == ' ' || *l == '\t' || *l == 0 || *l == '\n') {
  217.                     *pl = l;
  218.                     return opt;
  219.                 } else
  220.                     break;
  221.             } else
  222.             if (*d == '_') {
  223.                 *pl = skip_ws(l);
  224.                 return opt;
  225.             } else
  226.             if (*d != *l)
  227.                 break;
  228.  
  229.             ++d;
  230.             ++l;
  231.         }
  232.     }
  233.  
  234.     return 0;
  235. }
  236.  
  237. struct opt_tag * DccFindOption(char **pl, int flag)
  238. {
  239.     struct opt_tag *opt;
  240.     char *l, *s;
  241.  
  242.     for(opt = optvec; opt->sasc; ++opt) {
  243.         l = *pl;
  244.         s = opt->sasc;
  245.  
  246.         while(1) {
  247.             if (*s == '\0') {
  248.                 if (*l == ' ' || *l == '\t' || *l == 0 || *l == '\n') {
  249.                     *pl = l;
  250.                     return opt;
  251.                 } else
  252.                     break;
  253.             } else
  254.             if (*s == '=') {
  255.                 if (*l != ' ' && *l != '=' && *l != '\0') break;
  256.                 l = skip_ws(l);
  257.                 if (*l == '=') {
  258.                     ++l;
  259.                     l = skip_ws(l);
  260.                 }
  261.                 if (s[1] == '\0') {
  262.                     *pl = l;
  263.                     return opt;
  264.                 }
  265.                 --l;
  266.             } else
  267.             if (strnicmp(s, l, 1) != 0)
  268.                 break;
  269.  
  270.             ++s;
  271.             ++l;
  272.         }
  273.     }
  274.  
  275.     return 0;
  276. }
  277.  
  278. struct opt_tag * FindOption(char **pl, int flag)
  279. {
  280.     switch(compiler) {
  281.     case C_DICE:
  282.         return DccFindOption(pl, flag);
  283.     case C_SASC:
  284.         return SascFindOption(pl, flag);
  285.     }
  286. }
  287.  
  288. void SascCopyOption(struct opt_tag *opt, char **pl, char **pa)
  289. {
  290.     char *l = *pl;
  291.     char *a = *pa;
  292.  
  293.     strcat(a, opt->sasc);
  294.     a += strlen(a);
  295.  
  296.     /* If option ends with '=', an argument is expected to follow */
  297.     if (a[-1] == '=') {
  298.         l = skip_ws(l);
  299.         GetToken(&l, a, FALSE);
  300.         a += strlen(a);
  301.     }
  302.  
  303.     *pl = l;
  304.     *pa = a;
  305. }
  306.  
  307. void DccCopyOption(struct opt_tag *opt, char **pl, char **pa)
  308. {
  309.     char *l = *pl;
  310.     char *a = *pa;
  311.  
  312.     strcpy(a, opt->dcc);
  313.     a += strlen(a);
  314.     if (a[-1] == '_')  {
  315.         a[-1] = ' ';
  316.         l = skip_ws(l);
  317.         GetToken(&l, a, FALSE);
  318.         a += strlen(a);
  319.     }
  320.  
  321.     *pl = l;
  322.     *pa = a;
  323. }
  324.  
  325. void CopyOption(struct opt_tag *opt, char **pl, char **pa)
  326. {
  327.     switch(compiler) {
  328.     case C_DICE:
  329.         return DccCopyOption(opt, pl, pa);
  330.     case C_SASC:
  331.         return SascCopyOption(opt, pl, pa);
  332.     }
  333. }
  334.  
  335. int SascPreScan(char *line, char **pa, int isCommand)
  336. {
  337.     char *a = *pa;
  338.     char *p;
  339.     int cflag;
  340.  
  341.     p = strstr(line, "-c");
  342.     if (p && (p[2] == ' ' || p[2] == '\t' || p[2] == '\0' || p[2] == '\n')) {
  343.         cflag = TRUE;
  344.         if (p[-1] == ' ' || p[-1] == '\t')
  345.             strcpy(p-1, p+2);
  346.         else
  347.         if (p[2] != 0)
  348.             strcpy(p, p+3);
  349.         else
  350.             strcpy(p, p+2);
  351.     } else
  352.         cflag = FALSE;
  353.  
  354.     if (isCommand) {
  355.         strcpy(a, " NoIcons ANSI");
  356.         if (!cflag)
  357.             strcat(a, " Link");
  358.         a += strlen(a);
  359.     } else
  360.     if (cflag) {
  361.         fprintf(stderr, "Line %d: -c found on line other than dcc line\n", lineNum);
  362.     }
  363.  
  364.     *pa = a;
  365.  
  366.     return cflag;
  367. }
  368.  
  369. int DccPreScan(char *line, char **pa, int isCommand)
  370. {
  371.     char *a = *pa;
  372.     char *p;
  373.     int linkflag;
  374.  
  375.     p = strstr(line, "Link");
  376.     if (p && (p[4] == ' ' || p[4] == '\t' || p[4] == '\0' || p[4] == '\n')) {
  377.         linkflag = TRUE;
  378.         if (p[-1] == ' ')
  379.             --p;
  380.         strcpy(p, p+5);
  381.     } else
  382.         linkflag = FALSE;
  383.  
  384.     p = strstr(line, "NoIcons");
  385.     if (p) {
  386.         if (p[-1] == ' ')
  387.             --p;
  388.         strcpy(p, p+8);
  389.     }
  390.  
  391.     p = strstr(line, "ANSI");
  392.     if (p) {
  393.         if (p[-1] == ' ')
  394.             --p;
  395.         strcpy(p, p+5);
  396.     }
  397.  
  398.     if (isCommand) {
  399.         if (!linkflag) {
  400.             strcat(a, " -c");
  401.             a += strlen(a);
  402.         }
  403.     } else
  404.     if (linkflag) {
  405.         fprintf(stderr, "Line %d: Link found on line other than sc line\n", lineNum);
  406.     }
  407.  
  408.     *pa = a;
  409.  
  410.     return linkflag;
  411. }
  412.  
  413. int PreScan(char *line, char **pa, int isCommand)
  414. {
  415.     switch(compiler) {
  416.     case C_DICE:
  417.         return DccPreScan(line, pa, isCommand);
  418.     case C_SASC:
  419.         return SascPreScan(line, pa, isCommand);
  420.     }
  421. }
  422.  
  423. int adjustOptions(char *line, char *adjustedLine, int isCommand)
  424. {
  425.     static char token[200];
  426.     struct opt_tag *opt;
  427.     char *l, *a = adjustedLine;
  428.     char *oldl;
  429.     int flag;
  430.  
  431.     flag = PreScan(line, &a, isCommand);
  432.  
  433.     for(l=line; *l; ) {
  434.         CopyBlanks(&l, &a);
  435.         oldl = l;
  436.         switch(GetToken(&l, token, TRUE)) {
  437.         case T_EOL:
  438.         case T_MACRO:
  439.         case T_FILE:
  440.         case T_STRING:
  441.         case T_EQUAL:
  442.             strcpy(a, token);
  443.             a += strlen(a);
  444.             break;
  445.         default:
  446.             l = oldl;
  447.             opt = FindOption(&l, flag);
  448.             if (opt == 0) {
  449.                 if (force) {
  450.                     fprintf(stderr, "Line %d: Ignoring unknown %s option %s\n",
  451.                         lineNum,
  452.                         compiler==C_DICE ? "sc":"dcc",
  453.                         token);
  454.                     GetToken(&l, token, TRUE);
  455.                     continue;
  456.                 } else {
  457.                     fprintf(stderr, "Line %d: Unknown %s option %s\n",
  458.                         lineNum,
  459.                         compiler==C_DICE ? "sc":"dcc",
  460.                         token);
  461.                     fprintf(stderr, "    File will remain unchanged\n");
  462.                     return FALSE;
  463.                 }
  464.             }
  465.             CopyOption(opt, &l, &a);
  466.         }
  467.     }
  468.  
  469.     return TRUE;
  470. }
  471.  
  472. int doFor(char *p, char *line, char *adjustedLine)
  473. {
  474.     strcpy(adjustedLine, line);
  475.  
  476.     if (inFor) {
  477.         fprintf(stderr, "Line %d: Nested '#for' not legal.\n", lineNum);
  478.         return FALSE;
  479.     }
  480.  
  481.     p = skip_ws(p);
  482.     if (strnicmp(p, "sasc", 4) == 0)
  483.         commentsOn = compiler != C_SASC;
  484.     else
  485.     if (strnicmp(p, "dice", 4) == 0)
  486.         commentsOn = compiler != C_DICE;
  487.     else {
  488.         fprintf(stderr, "Line %d: Unrecognized compiler: %s\n", lineNum, p);
  489.         return FALSE;
  490.     }
  491.  
  492.     inFor = TRUE;
  493.  
  494.     return TRUE;
  495. }
  496.  
  497. int doEnd(char *p, char *line, char *adjustedLine)
  498. {
  499.     strcpy(adjustedLine, line);
  500.  
  501.     if (!inFor) {
  502.         fprintf(stderr, "Line %d: '#end' without '#for'\n", lineNum);
  503.         return FALSE;
  504.     }
  505.  
  506.     inFor = commentsOn = FALSE;
  507.  
  508.     return TRUE;
  509. }
  510.  
  511. int doMacroDef(char *p, char *line, char *adjustedLine)
  512. {
  513.     int len = p - line;
  514.  
  515.     strncpy(adjustedLine, line, len);
  516.     adjustedLine[len] = 0;
  517.  
  518.     return adjustOptions(p, adjustedLine+len, FALSE);
  519. }
  520.  
  521. int doDcc(char *p, char *line, char *adjustedLine)
  522. {
  523.     char *l, *a;
  524.  
  525.     if (compiler == C_DICE) {
  526.         strcpy(adjustedLine, line);
  527.         return TRUE;
  528.     } else {
  529.         l = line;
  530.         a = adjustedLine;
  531.         CopyBlanks(&l, &a);
  532.         strcpy(a, "sc");
  533.         a += strlen(a);
  534.         return adjustOptions(p, a, TRUE);
  535.     }
  536. }
  537.  
  538. int doSc(char *p, char *line, char *adjustedLine)
  539. {
  540.     char *l, *a;
  541.  
  542.     if (compiler == C_SASC) {
  543.         strcpy(adjustedLine, line);
  544.         return TRUE;
  545.     } else {
  546.         l = line;
  547.         a = adjustedLine;
  548.         CopyBlanks(&l, &a);
  549.         strcpy(a, "dcc");
  550.         a += strlen(a);
  551.         return adjustOptions(p, a, TRUE);
  552.     }
  553. }
  554.  
  555. struct key_tag {
  556.     char *text;
  557.     int (*func)(char*, char*, char*);
  558. } keys[] = {
  559.  "# for.",      doFor,
  560.  "# end",       doEnd,
  561.  "CFLAGS =",    doMacroDef,
  562.  "LIBS =",      doMacroDef,
  563.  "dcc.",        doDcc,
  564.  "sc.",         doSc,
  565.  0
  566. };
  567.  
  568. int adjustLine(char *line, char *adjustedLine)
  569. {
  570.     char *p, *t;
  571.     struct key_tag *kp;
  572.  
  573.     for(kp=keys; kp->text; ++kp) {
  574.         p = skip_ws(line);
  575.  
  576.         for(t = kp->text; ; ++t) {
  577.             if (*t == 0) {
  578.                 return (kp->func)(p, line, adjustedLine);
  579.             } else
  580.             if (*t == ' ') p = skip_ws(p);
  581.             else
  582.             if (*t == '.') {
  583.                 if (p == skip_ws(p))
  584.                     break;
  585.             } else
  586.             if (*t != *p)
  587.                 break;
  588.             else
  589.                 ++p;
  590.         }
  591.     }
  592.  
  593.     if (inFor) {
  594.         if (commentsOn) {
  595.             if (line[0] == '#') {
  596.                 strcpy(adjustedLine, line);
  597.             } else {
  598.                 strcpy(adjustedLine, "#");
  599.                 strcat(adjustedLine, line);
  600.             }
  601.         } else {
  602.             if (line[0] == '#') {
  603.                 strcpy(adjustedLine, line+1);
  604.             } else {
  605.                 strcpy(adjustedLine, line);
  606.             }
  607.         }
  608.     } else
  609.         strcpy(adjustedLine, line);
  610.  
  611.     return TRUE;
  612. }
  613.  
  614. void adjust(char *fileName)
  615. {
  616.     FILE *ifp=0, *ofp=0;
  617.     static char line[LINE_MAX+1];
  618.     static char adjustedLine[LINE_MAX+1];
  619.     static char tmp1Name[LINE_MAX+1];
  620.     static char tmp2Name[LINE_MAX+1];
  621.  
  622.     ifp = fopen(fileName, "r");
  623.     if (ifp == 0) {
  624.         perror(fileName);
  625.         goto out;
  626.     }
  627.  
  628.     strcpy(tmp1Name, fileName);
  629.     strcat(tmp1Name, ".1.tmp");
  630.  
  631.     ofp = fopen(tmp1Name, "w");
  632.     if (ofp == 0) {
  633.         perror(tmp1Name);
  634.         goto out;
  635.     }
  636.  
  637.     lineNum = 0;
  638.     while(fgets(line, LINE_MAX, ifp)) {
  639.         ++lineNum;
  640.  
  641.         if (!adjustLine(line, adjustedLine))
  642.             goto out;
  643.  
  644.         if (fputs(adjustedLine, ofp) == EOF) {
  645.             perror(tmp1Name);
  646.             goto out;
  647.         }
  648.     }
  649.  
  650.     fclose(ifp);
  651.     fclose(ofp);
  652.     ifp = ofp = 0;
  653.  
  654.     strcpy(tmp2Name, fileName);
  655.     strcat(tmp2Name, ".2.tmp");
  656.  
  657.     if (rename(fileName, tmp2Name) != 0) {
  658.         perror(fileName);
  659.         goto out;
  660.     }
  661.  
  662.     if (rename(tmp1Name, fileName) != 0) {
  663.         perror(fileName);
  664.         if (rename(tmp2Name, fileName) != 0) {
  665.             perror(tmp2Name);
  666.         }
  667.         goto out;
  668.     }
  669.  
  670.     if (unlink(tmp2Name) != 0) {
  671.         perror(tmp2Name);
  672.     }
  673.  
  674. out:
  675.     if (ifp)
  676.         fclose(ifp);
  677.  
  678.     if (ofp) {
  679.         fclose(ofp);
  680.         unlink(tmp1Name);
  681.     }
  682. }
  683.  
  684. char *uvec[] = {
  685.    " adj <switches> <files>",
  686.    "",
  687.    "<files>,"
  688.    "  DMakefiles to adjust.  Default DMakefile.",
  689.    "",
  690.    "  -dice     Adjust DMakefile to use DICE.",
  691.    "  -sasc     Adjust DMakefile to use SASC.",
  692.    "  -force    Adjust even if unrecognized compiler options encountered.",
  693.    "  -help     This message",
  694.    "  ?         Same as -help",
  695.    0
  696. };
  697.  
  698. void usage(void)
  699. {
  700.     char **pp;
  701.  
  702.     for(pp=uvec; *pp; ++pp) {
  703.         printf("%s\n", *pp);
  704.     }
  705. }
  706.  
  707.  
  708. int main(int argc, char *argv[])
  709. {
  710.     int i;
  711.     int help = FALSE;
  712.  
  713.     for(i=1; i<argc; ++i) {
  714.         if (strcmp(argv[i], "-dice") == 0)
  715.             compiler = C_DICE;
  716.         else
  717.         if (strcmp(argv[i], "-sasc") == 0)
  718.             compiler = C_SASC;
  719.         else
  720.         if (strcmp(argv[i], "-force") == 0)
  721.             force = TRUE;
  722.         else
  723.         if (strcmp(argv[i], "-help") == 0)
  724.             help = TRUE;
  725.         else
  726.         if (strcmp(argv[i], "-h") == 0)
  727.             help = TRUE;
  728.         else
  729.         if (strcmp(argv[i], "?") == 0)
  730.             help = TRUE;
  731.         else
  732.         if (argv[i][0] == '-') {
  733.             fprintf(stderr, "Unrecognized switch %s\n", argv[i]);
  734.             exit(10);
  735.         } else
  736.             files[filecnt++] = argv[i];
  737.     }
  738.  
  739.     if (help) {
  740.         usage();
  741.         exit(0);
  742.     }
  743.  
  744.     if (compiler == C_NONE) {
  745.         fprintf(stderr, "Requires -dice, or -sasc\n");
  746.         exit(10);
  747.     }
  748.  
  749.     if (filecnt == 0) {
  750.         files[filecnt++] = "DMakefile";
  751.     }
  752.  
  753.     for(i=0; i<filecnt; ++i) {
  754.         adjust(files[i]);
  755.     }
  756. }
  757.