home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / D / CLISP / CLISPSRC.TAR / clisp-1995-01-01 / utils / dedefined.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-23  |  22.2 KB  |  725 lines

  1. /* Programm zum Eliminieren von defined(...)-Ausdrⁿcken in #if -
  2.    PrΣprozessor-Anweisungen in C-Programmen, fⁿr VAX C.
  3.    Bruno Haible 26.2.1993
  4. */
  5.  
  6. /* Methode:
  7.    Erkenne die PrΣprozessor-Anweisung #if.
  8.    Der folgende Ausdruck wird in seine Bestandteile zerlegt. Liefert einen
  9.    Syntaxbaum. Fⁿr jeden Teilbaum, der einen defined(...)-Ausdruck enthΣlt,
  10.    wird eine temporΣre PrΣprozessor-Variable eingefⁿhrt.
  11.    Die Ausgabe besteht aus "#undef tmp_var_xx" zu Beginn, dann kurzen
  12.    #if's bzw. #ifdef's fⁿr jeden nΣchstumfangreicheren Teilbaum.
  13.  
  14.    Dieser PrΣprozessor setzt deelif.d voraus.
  15. */
  16.  
  17. /* Noch zu tun: #line-Anweisungen erkennen und selber emittieren. */
  18.  
  19. #define local static
  20. #define global
  21. #define var
  22. #define loop  while (1)
  23. #define until(exp)  while (!(exp))
  24. typedef unsigned char  uintB;
  25. typedef unsigned short  uintW;
  26. typedef unsigned long  uintL;
  27. typedef int  boolean;
  28. #define FALSE 0
  29. #define TRUE 1
  30.  
  31. #if defined(__TURBOC__) || defined(__GO32__) || defined(__WATCOMC__)
  32. #define STDC_HEADERS 1
  33. #else
  34. #if defined(unix) || defined(__unix)
  35. #include "unixconf.h"
  36. #endif
  37. #endif
  38. #ifdef STDC_HEADERS
  39. #include <stdlib.h> /* fⁿr malloc(), realloc(), exit() */
  40. #endif
  41.  
  42. #include <stdio.h>
  43. #include <setjmp.h> /* fⁿr setjmp(), longjmp() */
  44.  
  45. /* Einfache Ein-/Ausgaben: */
  46.  
  47. local var FILE* infile;
  48. local var FILE* outfile;
  49.  
  50. #define get() getc(infile)
  51. #define put(x) putc(x,outfile)
  52. #define puts(x) fputs(x,outfile)
  53.  
  54. #define NL 10
  55.  
  56. /* Es wird gebuffert: */
  57.  
  58. local char* buffer;
  59. local uintL bufsize;
  60. local char* bufend;
  61.  
  62. local void putbuffer(c)
  63.   var char c;
  64.   { if (bufend == buffer+bufsize)
  65.       { buffer = realloc(buffer,2*bufsize);
  66.         bufend = buffer+bufsize;
  67.         bufsize = 2*bufsize;
  68.       }
  69.     *bufend++ = c;
  70.   }
  71.  
  72. /* Syntax-Analyse im Buffer zwischen buffer und bufend: */
  73.  
  74. local boolean whitespacep(c)
  75.   var char c;
  76.   { return (c==' ') || (c=='\v') || (c=='\t'); }
  77.  
  78. /* Beenden der Analyse */
  79. local jmp_buf abort_line_jmpbuf;
  80. local void abort_line()
  81.   { longjmp(abort_line_jmpbuf,1); }
  82.  
  83. /* Syntax konstanter C-Expressions:
  84.    16  name
  85.    16  defined(...)
  86.    16  f(...)
  87.    14  ~ ...
  88.    14  ! ...
  89.    14  - ...
  90.    13L * / %
  91.    12L + -
  92.    11L << >>
  93.    10L < > <= >=
  94.     9L == !=
  95.     8L &
  96.     7L ^
  97.     6L |
  98.     5L &&
  99.     4L ||
  100.     3R ? :
  101.     1L ,
  102. */
  103.  
  104. /* Lexikalische Analyse: */
  105. typedef enum { TT_ident, /* identifier */
  106.                TT_number, /* number */
  107.                TT_lparen, /* ( */
  108.                TT_rparen, /* ) */
  109.                TT_plus, /* + */
  110.                TT_minus, /* - */
  111.                TT_mul, /* * */
  112.                TT_div, /* / */
  113.                TT_mod, /* % */
  114.                TT_lshift, /* << */
  115.                TT_rshift, /* >> */
  116.                TT_less, /* < */
  117.                TT_greater, /* > */
  118.                TT_less_equal, /* <= */
  119.                TT_greater_equal, /* >= */
  120.                TT_equal, /* == */
  121.                TT_not_equal, /* != */
  122.                TT_not, /* ~ */
  123.                TT_and, /* & */
  124.                TT_or, /* | */
  125.                TT_xor, /* ^ */
  126.                TT_lognot, /* ! */
  127.                TT_logand, /* && */
  128.                TT_logor, /* || */
  129.                TT_if, /* ? */
  130.                TT_else, /* : */
  131.                TT_comma, /* , */
  132.                TT_eof
  133.              }
  134.         tokentype;
  135. typedef struct { tokentype type; /* Typ */
  136.                  char* startptr; char* endptr; /* Pointer in den Buffer */
  137.                }
  138.         token_;
  139. typedef token_* Token;
  140. local token_ token_eof = {TT_eof,NULL,NULL};
  141. #define Token_EOF  &token_eof
  142.  
  143. local Token make_token(type,startptr,endptr)
  144.   var tokentype type;
  145.   var char* startptr;
  146.   var char* endptr;
  147.   { var Token token = malloc(sizeof(token_));
  148.     token->type = type;
  149.     token->startptr = startptr;
  150.     token->endptr = endptr;
  151.     return token;
  152.   }
  153.  
  154. local void free_token(token)
  155.   var Token token;
  156.   { free(token); }
  157.  
  158. /* Pointer in den Buffer, so weit die lexikalische Analyse gelangt ist. */
  159. local char* bufptr;
  160.  
  161. local int peek_char()
  162.   { if (bufptr==bufend) return EOF; else return *bufptr; }
  163.  
  164. local int next_char()
  165.   { if (bufptr==bufend) return EOF; else return *bufptr++; }
  166.  
  167. /* Holt das nΣchste Token, rⁿckt bufptr weiter: */
  168. local Token nexttoken()
  169.   { var int c;
  170.     restart:
  171.    {var char* startptr = bufptr;
  172.     c = next_char();
  173.     switch (c)
  174.       { case ' ': case '\v': case '\t':
  175.           goto restart; /* Whitespace ⁿberlesen */
  176.         case '/':
  177.           if (peek_char() == '*')
  178.             /* Kommentar */
  179.             { next_char();
  180.               loop
  181.                 { c = next_char();
  182.                   if (c==EOF) { fprintf(stderr,"Unbeendeter Kommentar\n"); abort_line(); }
  183.                   if ((c=='*') && (peek_char()=='/')) { next_char(); break; }
  184.                 }
  185.               goto restart;
  186.             }
  187.             else
  188.             return make_token(TT_div,startptr,bufptr);
  189.         case '*':
  190.           if (peek_char() == '/')
  191.             /* illegales Kommentar-Ende */
  192.             { fprintf(stderr,"Kommentar-Ende au▀erhalb Kommentar\n"); abort_line(); }
  193.           return make_token(TT_mul,startptr,bufptr);
  194.         case '(': return make_token(TT_lparen,startptr,bufptr);
  195.         case ')': return make_token(TT_rparen,startptr,bufptr);
  196.         case '+': return make_token(TT_plus,startptr,bufptr);
  197.         case '-': return make_token(TT_minus,startptr,bufptr);
  198.         case '%': return make_token(TT_mod,startptr,bufptr);
  199.         case '<':
  200.           c = peek_char();
  201.           if (c=='<') { next_char(); return make_token(TT_lshift,startptr,bufptr); }
  202.           if (c=='=') { next_char(); return make_token(TT_less_equal,startptr,bufptr); }
  203.           return make_token(TT_less,startptr,bufptr);
  204.         case '>':
  205.           c = peek_char();
  206.           if (c=='>') { next_char(); return make_token(TT_rshift,startptr,bufptr); }
  207.           if (c=='=') { next_char(); return make_token(TT_greater_equal,startptr,bufptr); }
  208.           return make_token(TT_greater,startptr,bufptr);
  209.         case '=':
  210.           c = peek_char();
  211.           if (c=='=') { next_char(); return make_token(TT_equal,startptr,bufptr); }
  212.           abort_line();
  213.         case '~': return make_token(TT_not,startptr,bufptr);
  214.         case '!':
  215.           c = peek_char();
  216.           if (c=='=') { next_char(); return make_token(TT_not_equal,startptr,bufptr); }
  217.           return make_token(TT_lognot,startptr,bufptr);
  218.         case '&':
  219.           c = peek_char();
  220.           if (c=='&') { next_char(); return make_token(TT_logand,startptr,bufptr); }
  221.           return make_token(TT_and,startptr,bufptr);
  222.         case '|':
  223.           c = peek_char();
  224.           if (c=='|') { next_char(); return make_token(TT_logor,startptr,bufptr); }
  225.           return make_token(TT_or,startptr,bufptr);
  226.         case '^': return make_token(TT_xor,startptr,bufptr);
  227.         case '?': return make_token(TT_if,startptr,bufptr);
  228.         case ':': return make_token(TT_else,startptr,bufptr);
  229.         case ',': return make_token(TT_comma,startptr,bufptr);
  230.         case '.':
  231.           c = peek_char();
  232.           if (!(((c>='0') && (c<='9')) || (c=='.'))) { abort_line(); }
  233.         case '0': case '1': case '2': case '3': case '4':
  234.         case '5': case '6': case '7': case '8': case '9':
  235.           /* Zahl. Weiterlesen, solange alphanumerisches Zeichen oder '.': */
  236.           loop
  237.             { c = peek_char();
  238.               if (((c>='0') && (c<='9'))
  239.                   || ((c>='A') && (c<='Z')) || ((c>='a') && (c<='z'))
  240.                   || (c=='.')
  241.                  )
  242.                 { next_char(); }
  243.                 else
  244.                 break;
  245.             }
  246.           return make_token(TT_number,startptr,bufptr);
  247.         case '\'':
  248.           /* Character-Konstante */
  249.           loop
  250.             { c = next_char();
  251.               if (c==EOF) { fprintf(stderr,"Unbeendete Character-Konstante"); abort_line(); }
  252.               if (c=='\'') break;
  253.               if (c=='\\') { c = next_char(); }
  254.             }
  255.           return make_token(TT_number,startptr,bufptr);
  256.         case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
  257.         case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
  258.         case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
  259.         case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
  260.         case 'Y': case 'Z':
  261.         case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
  262.         case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
  263.         case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
  264.         case 's': case 't': case 'u': case 'v': case 'w': case 'x':
  265.         case 'y': case 'z':
  266.         case '_': case '$':
  267.           /* Identifier. alles alphanumerische ⁿberlesen. */
  268.           loop
  269.             { c = peek_char();
  270.               if (   ((c>='0') && (c<='9'))
  271.                   || ((c>='A') && (c<='Z')) || ((c>='a') && (c<='z'))
  272.                   || (c=='_') || (c=='$')
  273.                  )
  274.                 { next_char(); }
  275.                 else
  276.                 break;
  277.             }
  278.           return make_token(TT_ident,startptr,bufptr);
  279.         case EOF:
  280.           return Token_EOF;
  281.         default:
  282.           abort_line();
  283.       }
  284.   }}
  285.  
  286. local void print_token(token)
  287.   var Token token;
  288.   { var char* ptr = token->startptr;
  289.     var char* endptr = token->endptr;
  290.     until (ptr==endptr) { char c = *ptr++; put(c); }
  291.   }
  292.  
  293. /* Ausdrucks-Analyse: */
  294. typedef enum { ET_literal, /* identifier, number, literal */
  295.                ET_paren, /* (expr) */
  296.                ET_call, /* expr1(expr2) */
  297.                ET_unary, /* ~ expr, ! expr, - expr */
  298.                ET_mulop, /* expr1 * expr2, expr1 / expr2, expr1 % expr2 */
  299.                ET_addop, /* expr1 + expr2, expr1 - expr2 */
  300.                ET_shiftop, /* expr1 << expr2, expr1 >> expr2 */
  301.                ET_cmpop, /* expr1 < expr2, expr1 > expr2 etc. */
  302.                ET_relop, /* expr1 == expr2, expr1 != expr2 */
  303.                ET_andop, /* expr1 & expr2 */
  304.                ET_xorop, /* expr1 ^ expr2 */
  305.                ET_orop, /* expr1 | expr2 */
  306.                ET_logandop, /* expr1 && expr2 */
  307.                ET_logorop, /* expr1 || expr2 */
  308.                ET_condop, /* expr1 ? expr2 : expr3 */
  309.                ET_seqop, /* expr1 , expr2 */
  310.                ET_defined /* DEFINED_xxx */
  311.              }
  312.         exprtype;
  313. typedef struct expr_ * Expr;
  314. typedef struct expr_ { exprtype type; /* Typ */
  315.                        Token token1, token2;
  316.                        Expr expr1, expr2, expr3;
  317.                        uintL counter;
  318.                      }
  319.         expr_;
  320.  
  321. local Expr make_expr(type,token1,token2,expr1,expr2,expr3)
  322.   var exprtype type;
  323.   var Token token1;
  324.   var Token token2;
  325.   var Expr expr1;
  326.   var Expr expr2;
  327.   var Expr expr3;
  328.   { var Expr expr = malloc(sizeof(expr_));
  329.     expr->type = type;
  330.     expr->token1 = token1;
  331.     expr->token2 = token2;
  332.     expr->expr1 = expr1;
  333.     expr->expr2 = expr2;
  334.     expr->expr3 = expr3;
  335.     return expr;
  336.   }
  337.  
  338. local void free_expr(expr)
  339.   var Expr expr;
  340.   { if (expr->token1) free_token(expr->token1);
  341.     if (expr->token2) free_token(expr->token2);
  342.     if (expr->expr1) free_expr(expr->expr1);
  343.     if (expr->expr2) free_expr(expr->expr2);
  344.     if (expr->expr3) free_expr(expr->expr3);
  345.     free(expr);
  346.   }
  347.  
  348. local Token last_token;
  349.  
  350. local Token peek_token()
  351.   { if (last_token) return last_token;
  352.     return last_token = nexttoken(); /* Token_EOF bedeutet EOF */
  353.   }
  354.  
  355. local Token next_token()
  356.   { if (last_token)
  357.       { var Token result = last_token; last_token = NULL; return result; }
  358.     return nexttoken(); /* Token_EOF bedeutet EOF */
  359.   }
  360.  
  361. local Expr parse_expr();
  362.  
  363. local Expr parse_expr_16()
  364.   { var Token token = next_token();
  365.     switch (token->type)
  366.       { case TT_ident:
  367.           { var Expr expr = make_expr(ET_literal, token,NULL, NULL,NULL,NULL);
  368.             var Token token2 = peek_token();
  369.             if (token2->type==TT_lparen)
  370.               { next_token();
  371.                {var Expr expr2 = parse_expr();
  372.                 var Token token3 = next_token();
  373.                 if (!(token3->type==TT_rparen)) abort_line();
  374.                 return make_expr(ET_call, token2,token3, expr,expr2,NULL);
  375.               }}
  376.               else
  377.               return expr;
  378.           }
  379.         case TT_number:
  380.           return make_expr(ET_literal, token,NULL, NULL,NULL,NULL);
  381.         case TT_lparen:
  382.           { var Expr expr = parse_expr();
  383.             var Token token2 = next_token();
  384.             if (!(token2->type==TT_rparen)) abort_line();
  385.             return make_expr(ET_paren, token,token2, expr,NULL,NULL);
  386.           }
  387.         default:
  388.           abort_line();
  389.   }   }
  390.  
  391. local Expr parse_expr_14()
  392.   { var Token token = peek_token();
  393.     switch (token->type)
  394.       { case TT_not:
  395.         case TT_lognot:
  396.         case TT_minus:
  397.           next_token();
  398.           { var Expr expr = parse_expr_14();
  399.             return make_expr(ET_unary, token,NULL, expr,NULL,NULL);
  400.           }
  401.         default:
  402.           return parse_expr_16();
  403.   }   }
  404.  
  405. local Expr parse_expr_13()
  406.   { var Expr expr = parse_expr_14();
  407.     loop
  408.       { var Token token = peek_token();
  409.         switch (token->type)
  410.           { default:
  411.               return expr;
  412.             case TT_mul:
  413.             case TT_div:
  414.             case TT_mod:
  415.               next_token();
  416.               expr = make_expr(ET_mulop, token,NULL, expr,parse_expr_14(),NULL);
  417.       }   }
  418.   }
  419.  
  420. local Expr parse_expr_12()
  421.   { var Expr expr = parse_expr_13();
  422.     loop
  423.       { var Token token = peek_token();
  424.         switch (token->type)
  425.           { default:
  426.               return expr;
  427.             case TT_plus:
  428.             case TT_minus:
  429.               next_token();
  430.               expr = make_expr(ET_addop, token,NULL, expr,parse_expr_13(),NULL);
  431.       }   }
  432.   }
  433.  
  434. local Expr parse_expr_11()
  435.   { var Expr expr = parse_expr_12();
  436.     loop
  437.       { var Token token = peek_token();
  438.         switch (token->type)
  439.           { default:
  440.               return expr;
  441.             case TT_lshift:
  442.             case TT_rshift:
  443.               next_token();
  444.               expr = make_expr(ET_shiftop, token,NULL, expr,parse_expr_12(),NULL);
  445.       }   }
  446.   }
  447.  
  448. local Expr parse_expr_10()
  449.   { var Expr expr = parse_expr_11();
  450.     loop
  451.       { var Token token = peek_token();
  452.         switch (token->type)
  453.           { default:
  454.               return expr;
  455.             case TT_less:
  456.             case TT_greater:
  457.             case TT_less_equal:
  458.             case TT_greater_equal:
  459.               next_token();
  460.               expr = make_expr(ET_cmpop, token,NULL, expr,parse_expr_11(),NULL);
  461.       }   }
  462.   }
  463.  
  464. local Expr parse_expr_9()
  465.   { var Expr expr = parse_expr_10();
  466.     loop
  467.       { var Token token = peek_token();
  468.         switch (token->type)
  469.           { default:
  470.               return expr;
  471.             case TT_equal:
  472.             case TT_not_equal:
  473.               next_token();
  474.               expr = make_expr(ET_relop, token,NULL, expr,parse_expr_10(),NULL);
  475.       }   }
  476.   }
  477.  
  478. local Expr parse_expr_8()
  479.   { var Expr expr = parse_expr_9();
  480.     loop
  481.       { var Token token = peek_token();
  482.         switch (token->type)
  483.           { default:
  484.               return expr;
  485.             case TT_and:
  486.               next_token();
  487.               expr = make_expr(ET_andop, token,NULL, expr,parse_expr_9(),NULL);
  488.       }   }
  489.   }
  490.  
  491. local Expr parse_expr_7()
  492.   { var Expr expr = parse_expr_8();
  493.     loop
  494.       { var Token token = peek_token();
  495.         switch (token->type)
  496.           { default:
  497.               return expr;
  498.             case TT_xor:
  499.               next_token();
  500.               expr = make_expr(ET_xorop, token,NULL, expr,parse_expr_8(),NULL);
  501.       }   }
  502.   }
  503.  
  504. local Expr parse_expr_6()
  505.   { var Expr expr = parse_expr_7();
  506.     loop
  507.       { var Token token = peek_token();
  508.         switch (token->type)
  509.           { default:
  510.               return expr;
  511.             case TT_or:
  512.               next_token();
  513.               expr = make_expr(ET_orop, token,NULL, expr,parse_expr_7(),NULL);
  514.       }   }
  515.   }
  516.  
  517. local Expr parse_expr_5()
  518.   { var Expr expr = parse_expr_6();
  519.     loop
  520.       { var Token token = peek_token();
  521.         switch (token->type)
  522.           { default:
  523.               return expr;
  524.             case TT_logand:
  525.               next_token();
  526.               expr = make_expr(ET_logandop, token,NULL, expr,parse_expr_6(),NULL);
  527.       }   }
  528.   }
  529.  
  530. local Expr parse_expr_4()
  531.   { var Expr expr = parse_expr_5();
  532.     loop
  533.       { var Token token = peek_token();
  534.         switch (token->type)
  535.           { default:
  536.               return expr;
  537.             case TT_logor:
  538.               next_token();
  539.               expr = make_expr(ET_logorop, token,NULL, expr,parse_expr_5(),NULL);
  540.       }   }
  541.   }
  542.  
  543. local Expr parse_expr_3()
  544.   { var Expr expr = parse_expr_4();
  545.     var Token token = peek_token();
  546.     if (token->type==TT_if)
  547.       { next_token();
  548.        {var Expr expr2 = parse_expr_3();
  549.         var Token token2 = next_token();
  550.         if (!(token2->type==TT_else)) abort_line();
  551.         return make_expr(ET_condop, token,token2, expr,expr2,parse_expr_3());
  552.       }}
  553.       else
  554.       return expr;
  555.   }
  556.  
  557. local Expr parse_expr_1()
  558.   { var Expr expr = parse_expr_3();
  559.     loop
  560.       { var Token token = peek_token();
  561.         switch (token->type)
  562.           { default:
  563.               return expr;
  564.             case TT_comma:
  565.               next_token();
  566.               expr = make_expr(ET_seqop, token,NULL, expr,parse_expr_3(),NULL);
  567.       }   }
  568.   }
  569.  
  570. local Expr parse_expr()
  571.   { return parse_expr_1(); }
  572.  
  573. /* Ausdruck ausgeben: */
  574. local void print_expr(expr)
  575.   var Expr expr;
  576.   { switch (expr->type)
  577.       { case ET_literal:
  578.           print_token(expr->token1); break;
  579.         case ET_paren:
  580.           print_token(expr->token1); print_expr(expr->expr1); print_token(expr->token2); break;
  581.         case ET_call:
  582.           print_expr(expr->expr1); print_token(expr->token1); print_expr(expr->expr2); print_token(expr->token2); break;
  583.         case ET_unary:
  584.           print_token(expr->token1); print_expr(expr->expr1); break;
  585.         case ET_mulop:
  586.         case ET_addop:
  587.         case ET_shiftop:
  588.         case ET_cmpop:
  589.         case ET_relop:
  590.         case ET_andop:
  591.         case ET_xorop:
  592.         case ET_orop:
  593.         case ET_logandop:
  594.         case ET_logorop:
  595.         case ET_seqop:
  596.            print_expr(expr->expr1); print_token(expr->token1); print_expr(expr->expr2); break;
  597.         case ET_condop:
  598.            print_expr(expr->expr1); print_token(expr->token1); print_expr(expr->expr2); print_token(expr->token2); print_expr(expr->expr3); break;
  599.         case ET_defined:
  600.            fprintf(outfile,"DEFINED_%lu",expr->counter); break;
  601.   }   }
  602.  
  603. /* Ausdruck rekursiv durchgehen und defined(...)-Ausdrⁿcke ersetzen: */
  604. local uintL defined_counter;
  605. local boolean definedp(expr)
  606.   var Expr expr;
  607.   { if (!(expr->type==ET_literal)) return FALSE;
  608.    {var Token token = expr->token1;
  609.     if (!(token->type==TT_ident)) return FALSE;
  610.     {var char* ptr = token->startptr;
  611.      if (!(token->endptr == ptr+7)) return FALSE;
  612.      if (   (ptr[0]=='d') && (ptr[1]=='e') && (ptr[2]=='f') && (ptr[3]=='i')
  613.          && (ptr[4]=='n') && (ptr[5]=='e') && (ptr[6]=='d')
  614.         )
  615.        return TRUE;
  616.        else
  617.        return FALSE;
  618.   }}}
  619. local void defined_replace(expr)
  620.   var Expr expr;
  621.   { if (expr->type==ET_call)
  622.       if (definedp(expr->expr1))
  623.         if (expr->expr2->type==ET_literal)
  624.           if (expr->expr2->token1->type==TT_ident)
  625.             { var Token ident = expr->expr2->token1;
  626.               /* expr vom Typ ET_call in Typ ET_defined umwandeln: */
  627.               expr->expr2->token1 = NULL;
  628.               free_expr(expr->expr1); free_expr(expr->expr2);
  629.               free_token(expr->token1); free_token(expr->token2);
  630.               expr->type = ET_defined; expr->counter = ++defined_counter;
  631.               puts("#undef "); print_expr(expr); puts("\n");
  632.               puts("#ifdef "); print_token(ident); puts("\n");
  633.               puts("#define "); print_expr(expr); puts(" 1\n");
  634.               puts("#else\n");
  635.               puts("#define "); print_expr(expr); puts(" 0\n");
  636.               puts("#endif\n");
  637.               free_token(ident);
  638.               return;
  639.             }
  640.     if (expr->expr1) defined_replace(expr->expr1);
  641.     if (expr->expr2) defined_replace(expr->expr2);
  642.     if (expr->expr3) defined_replace(expr->expr3);
  643.   }
  644.  
  645. /* Zeile im Buffer behandeln: Falls sie eine #if-Anweisung ist, werden alle
  646.    defined(...) durch Tokens ersetzt, die vorher entsprechend definiert werden.
  647. */
  648. local void process_line()
  649.   { if (setjmp(abort_line_jmpbuf)==0)
  650.       { bufptr = buffer;
  651.         if ((next_char()=='#') && (next_char()=='i') && (next_char()=='f')
  652.             && whitespacep(next_char())
  653.            )
  654.           { /* Rest der Zeile lesen: */
  655.             last_token = NULL;
  656.            {var Expr expr = parse_expr();
  657.             if (!(peek_token()==Token_EOF)) abort_line();
  658.             /* defined(...) ersetzen: */
  659.             defined_counter = 0; defined_replace(expr);
  660.             /* Zeile ausgeben: */
  661.             puts("#if "); print_expr(expr); puts("\n");
  662.             return;
  663.       }   }}
  664.     /* Keine passende PrΣprozessor-Zeile oder Abbruch wegen Syntaxfehler -> */
  665.     /* Zeile unverΣndert ausgeben: */
  666.    {var char* ptr = buffer;
  667.     until (ptr==bufend) { var char c = *ptr++; put(c); }
  668.     put('\n');
  669.   }}
  670.  
  671. global int main(argc,argv)
  672.   var int argc;
  673.   var char** argv;
  674.   { /* Argumente behandeln: */
  675.     if (argc > 3)
  676.       { fprintf(stderr,"Usage: dedefined [infile [outfile]]\n"); return 1; }
  677.     if (argc >= 2)
  678.       { if ((infile = fopen(argv[1],"r")) == NULL)
  679.           { fprintf(stderr,"dedefined: unable to open input file `%s'",argv[1]);
  680.             return 1;
  681.       }   }
  682.       else
  683.       { infile = stdin; }
  684.     if (argc >= 3)
  685.       { if ((outfile = fopen(argv[2],"w")) == NULL)
  686.           { fprintf(stderr,"dedefined: unable to open output file `%s'",argv[2]);
  687.             return 1;
  688.       }   }
  689.       else
  690.       { outfile = stdout; }
  691.     /* Buffer initialisieren: */
  692.     buffer = malloc(bufsize = 1024);
  693.     /* Zeilen lesen: */
  694.     loop
  695.       { var int c = get();
  696.         if (c==EOF) break;
  697.         if (c=='#')
  698.           /* m÷gliche PrΣprozessor-Anweisung */
  699.           { bufend = buffer;
  700.             loop
  701.               { putbuffer(c);
  702.                 c = get();
  703.                 if ((c==EOF) || (c==NL)) break;
  704.               }
  705.             process_line();
  706.           }
  707.           else
  708.           /* normale Zeile, unverΣndert durchlassen */
  709.           { loop
  710.               { put(c);
  711.                 c = get();
  712.                 if ((c==EOF) || (c==NL)) break;
  713.               }
  714.             put(NL);
  715.             if (c==EOF) break;
  716.       }   }
  717.     /* Files schlie▀en: */
  718.     if (ferror(infile) || ferror(outfile))
  719.       { fclose(infile); fclose(outfile); exit(1); }
  720.     fclose(infile);
  721.     fclose(outfile);
  722.     exit(0);
  723.   }
  724.  
  725.