home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / p / p2c.zip / P2C.C < prev    next >
C/C++ Source or Header  |  1987-03-27  |  11KB  |  417 lines

  1. /*----------------------------------------------------------------------
  2.   PAS2C.C  Version 1.1
  3.   Translate Pascal keywords and operators to C.
  4.   useage:  pas2c < pascal_source  > c_source
  5.     i.e., this is a filter program which filters out the Pascal.
  6.   By James A Mullens <jcm@ornl-msr.arpa>    29-Jan-87
  7.  
  8.   Revisions:
  9.     Version 1.1  17-Feb-87  Changed several keyword translations on the
  10.     advice of James R. Van Zandt <jrv@mitre-bedford.ARPA>.  Added many
  11.     more translations.  Added a source for function strcmpi for the
  12.     unfortunates who don't have this case-insensitive string comparison
  13.     in their C library.
  14.  
  15.     Dan Kegel     15 Mar 87    Made it work on Sun workstation.  Ripped out
  16.     translations that hurt translation of a large (20,000 line) Turbo program.
  17. ----------------------------------------------------------------------*/
  18.  
  19. #include <stdio.h>    /* standard I/O */
  20. #include <ctype.h>    /* character macros */
  21. #include <string.h>    /* string functions */
  22. #include "p2c.h"
  23. #include "ktypes.h"    /* keyword type definitions */
  24.  
  25. boolean WasSemi;    /* kludge to avoid duplicating semicolons */
  26.  
  27. /* Change these translations to fit your desires, but the Pascal names must 
  28.    be written in lower case and must be in alphabetical order.  If you include 
  29.    a C comment in your translation output as a HINT to the programmer, write 
  30.    it in CAPITALs, else write the comment in lower case, eh?
  31. */
  32.  
  33. wnode xlate[] = {
  34.   {T_ZIP,    "and",        "&&"    },
  35.   {T_ARRAY,    "array",    ""    },    /* see parseTypeDecl */
  36.   {T_BEGIN,    "begin",    "{"    },
  37.   {T_ZIP,    "boolean",    "boolean"},
  38.   {T_ZIP,    "byte",        "char"    },    /* Turbo */
  39.   {T_CASE,    "case",        "switch"},
  40.   {T_CONST,    "const",    "/* CONST */"},
  41.   {T_ZIP,    "div",        "/"    },
  42.   {T_ZIP,    "do",        ")"    },
  43.   {T_ZIP,    "downto",    ";/*DOWNTO*/"},
  44.   {T_ZIP,    "else",        "; else"},
  45.   {T_END,    "end",        "}"    },
  46.   {T_ZIP,    "false",    "FALSE"    },    
  47.   {T_FILE,    "file",        ""    },    /* see parseTypeDecl() */
  48.   {T_ZIP,    "for",        "for ("    },
  49.   {T_FORWARD,    "forward",    ""    },
  50.   {T_FUNC,    "function",    ""    },    /* see parseProcedure() */
  51.   {T_ZIP,    "if",        "if ("    },
  52.   {T_ZIP,    "implementation", "/* private (static) section */"},
  53.   {T_ZIP,    "input",    "stdin"    },
  54.   {T_ZIP,    "integer",    "int"    },
  55.   {T_ZIP,    "interface",    "/* exported symbol section */"},
  56.   {T_ZIP,    "ioresult",    "errno"    },    /* UCSD, Turbo */
  57.   {T_LABEL,    "label",    ""    },    /* see parseLabel() */
  58.   {T_ZIP,    "mod",        "%"    },
  59.   {T_ZIP,    "not",        "!"    },
  60.   {T_OF,    "of",        ""    },    /* see parseTypeDecl() */
  61.   {T_ZIP,    "or",        "||"    },
  62.   {T_ZIP,    "output",    "stdout"},
  63.   {T_ZIP,    "packed",    "/* PACKED */"},
  64.   {T_PROC,    "procedure",    "void"    },    /* see parseProcedure() */
  65.   {T_ZIP,    "program",    "main"    },
  66.   {T_ZIP,    "read",        "scanf"    },
  67.   {T_ZIP,    "readln",    "/*LINE*/scanf"},/* hint - read end-of-line */
  68.   {T_ZIP,    "real",        "double"},    /* or "float" */
  69.   {T_RECORD,    "record",    ""    },    /* see parseTypeDecl() */
  70.   {T_ZIP,    "repeat",    "do {"    },
  71.   {T_STRINGTYPE,"string",    ""    },    /* UCSD, Turbo string type */
  72.   {T_ZIP,    "text",        "FILE *"},    /* UCSD, Turbo file type */
  73.   {T_ZIP,    "then",        ")"    },
  74.   {T_ZIP,    "to",        ";"    },
  75.   {T_ZIP,    "true",        "TRUE"    },    
  76.   {T_TYPE,    "type",        ""    },    /* see parseType() */
  77.   {T_ZIP,    "until",    "} until ("},
  78.   {T_ZIP,    "uses",        "/* USES */\n#include"},
  79.   {T_VAR,    "var",        "/* VAR */"},    /* see parseProc, parseVar() */
  80.   {T_ZIP,    "while",    "while ("},
  81.   {T_ZIP,    "with",        "/* WITH */"},    /*hint-set pointer to struct*/
  82.   {T_ZIP,    "write",    "printf"},
  83.   {T_ZIP,    "writeln",    "/*LINE*/printf"},/* hint - write newline */
  84.   {T_ZIP,    "",        ""    }    /* marks end of xlate table */
  85. };
  86.  
  87. wnode theend = {T_ZIP,    "", ""};
  88.  
  89. wnode *hash[26];        /* quick index into the translation array */
  90.  
  91. /* Fill in the quick index ("hash") array 
  92. */
  93. void init_hash()
  94. {
  95.     int ch, cmp;
  96.     wnode *nptr = xlate;
  97.  
  98.     for (ch='a'; ch<='z'; ch++) {
  99.     while (nptr->pname[0] && (cmp = ch - *nptr->pname) > 0) 
  100.         nptr++;
  101.     hash[ch-'a'] = (cmp==0) ? nptr : &theend;
  102.     }
  103. }
  104.  
  105.  
  106. /* compare two strings without regard to case,
  107.    the equivalent of this function may already be in your C library 
  108.    Used to fail on Suns because it used tolower on lowercase chars...
  109.    Assumes second argument already lowercase.
  110. */
  111. int strcmpi(s1,s2)
  112.     register char *s1, *s2;
  113.     register char c1;
  114.  
  115.     while ((c1= *s1++) && *s2) {    /* get char, advance ptr */
  116.     if (isupper(c1)) c1 = tolower(c1);
  117.     if (c1 != *s2) break;
  118.     s2++;
  119.     }
  120.     return(c1 - *s2);
  121. }
  122.  
  123.  
  124. /* Pass an identifier through the translation table; return its
  125.    keyword type.  Translated keyword left in same buffer.
  126. */
  127. int
  128. translate(word)
  129.     register char *word;
  130.     register wnode *xptr;
  131.     int nomatch;
  132.     int c;
  133.  
  134.     c = *word;
  135.     if (isalpha(c)) {
  136.     if (isupper(c)) c=tolower(c);
  137.     xptr = hash[c - 'a'];
  138.     while ( xptr->pname[0] && (nomatch = strcmpi(word,xptr->pname)) > 0 ) 
  139.         xptr++;
  140.     if (!nomatch) {
  141.         word[0]=0;
  142.         if (!WasSemi && xptr->ktype == T_END)
  143.         strcpy(word, ";");
  144.         strcat(word, xptr->cname);
  145.         return(xptr->ktype);
  146.     }
  147.     }
  148.     return(T_ZIP);
  149. }
  150.  
  151. #define Q_NOQUOTE  1
  152. #define Q_ONEQUOTE 2
  153. #define Q_DONE     3
  154. #define Q_ERR      4
  155.  
  156. #define Q_C_ESCAPES  FALSE   /* Set true if your Pascal knows backslashes */
  157.  
  158. /*---- parseQuotedString -------------------------------------------------
  159. Accepts Pascal quoted string from stdin, converts to C quoted string, and 
  160. places in buf.
  161. Examples:
  162.   'hi' -> "hi"    'hi''' -> "hi'"  'hi''''' -> "hi''"
  163.   ''   -> ""      ''''   -> "'"    ''''''   -> "''"
  164.   ''hi' -> ERROR  '''hi' -> "'hi"  '''''hi' -> "''hi"
  165.   'I''m'  -> "I'm"
  166. Double quotes and backslashes are preceded with backslashes, except that
  167. if Q_C_ESCAPES is TRUE, backslashes are left naked.
  168. --------------------------------------------------------------------------*/
  169. void
  170. parseQuotedString(buf)
  171. char *buf;
  172. {
  173.     register char c;
  174.     register char *letter=buf;
  175.     int qstate;
  176.  
  177.     *letter++ = '"';
  178.     qstate = Q_NOQUOTE;
  179.     while (qstate < Q_DONE) {
  180.     switch (c=getchar()) {
  181.     case '\'':
  182.         switch (qstate) {
  183.         case Q_NOQUOTE:  
  184.         qstate = Q_ONEQUOTE; break;
  185.         case Q_ONEQUOTE: 
  186.         *letter++ = c; qstate = Q_NOQUOTE; break;
  187.         }
  188.         break;
  189.     case EOF:
  190.     case '\n':
  191.         qstate= (qstate==Q_ONEQUOTE) ? Q_DONE : Q_ERR;
  192.         ungetc(c,stdin);
  193.         break;
  194.     default:
  195.         switch (qstate) {
  196.         case Q_ONEQUOTE: 
  197.         ungetc(c,stdin); qstate = Q_DONE; break;
  198.         case Q_NOQUOTE:
  199.         if (c=='\\' && !Q_C_ESCAPES) *letter++ = c;
  200.         if (c=='"') *letter++ = '\\';
  201.         *letter++ = c; 
  202.         break; 
  203.         }
  204.     }
  205.     }
  206.     *letter++ = '"';
  207.     *letter++ = '\0';
  208.     if (qstate == Q_ERR) {
  209.     fprintf(stderr,"Newline in string constant: %s\n",buf);
  210.     fprintf(stdout," %c*** \\n IN STRING ***%c ",
  211.         '/', buf, '/');
  212.     }
  213. }
  214.  
  215. void
  216. getTok()
  217. {
  218.     register char *letter = cTok.str;
  219.     register char *sEnd = letter + MAXTOKLEN-3;
  220.     register int c;
  221.  
  222.     c = getchar();
  223.     if (isalnum(c)) {
  224.     while (c != EOF && isalnum(c)) {
  225.         *letter++ = c;
  226.         c = getchar();
  227.     }
  228.     ungetc(c,stdin);
  229.     *letter++ = 0;
  230.     cTok.kind = translate(cTok.str);
  231.     } else {
  232.     switch(c) {
  233.     case '\n':    /* newline */
  234.     case 0x20:    /* space */
  235.     case 0x9:    /* tab */
  236.         do        /* Gather a string of blank space into one token */
  237.         *letter++ = c;
  238.         while ((c=getchar()) != EOF && isspace(c));
  239.         ungetc(c, stdin);
  240.         *letter++ = '\0';
  241.         cTok.kind = T_SPACE;
  242.         break;
  243.     case '\'':                 /* Quoted String */
  244.         parseQuotedString(cTok.str);
  245.         cTok.kind = T_STRING;
  246.         break;
  247.     case '{' :                 /* Curly Comment */
  248.         *letter++='/'; 
  249.         *letter++='*';
  250.         while ((c=getchar()) != EOF && c!='}' && letter!=sEnd)
  251.         *letter++ = c;
  252.         if (letter == sEnd) {
  253.         printf("/***ERROR: Comment too long (sorry) ***/");
  254.         while ((c=getchar()) != EOF && c!='}')
  255.             ;
  256.         }
  257.         strcpy(letter, "*/");
  258.         cTok.kind = T_COMMENT;
  259.         break;
  260.     case '(' : 
  261.         if ((c=getchar())!='*') {        /* Parenthesis */
  262.         ungetc(c,stdin);
  263.         strcpy(letter, "(");
  264.         cTok.kind = T_LPAREN;
  265.         } else {
  266.         register int lastc = '\0';    /* (* Comment *) */
  267.         *letter++='/'; 
  268.         *letter++='*';
  269.         while ((c=getchar())!=EOF && !(c==')' && lastc == '*') && 
  270.             letter != sEnd) {
  271.             lastc = c;
  272.             *letter++ = c;
  273.         }
  274.         if (letter == sEnd) {
  275.             printf("/***ERROR: Comment too long (sorry) ***/");
  276.             while ((c=getchar())!=EOF && !(c==')' && lastc == '*'))
  277.             lastc = c;
  278.         }
  279.         strcpy(letter, "/");        /* * already there! */
  280.         cTok.kind = T_COMMENT;
  281.         }
  282.         break;
  283.     case ')' :
  284.         strcpy(letter, ")");
  285.         cTok.kind = T_RPAREN;
  286.         break;
  287.     case ':' : 
  288.         if ((c=getchar())=='=') {        /* Assignment */
  289.         strcpy(letter, "=");
  290.         cTok.kind = T_ASSIGN;
  291.         } else {                /* Colon */
  292.         ungetc(c,stdin);
  293.         strcpy(letter, ":");
  294.         cTok.kind = T_COLON;
  295.         }
  296.         break;
  297.     case '=':
  298.         strcpy(letter, "==");        /* Might be equality test...*/
  299.         cTok.kind = T_EQUALS;        /* depends on parse state */
  300.         break;
  301.     case '<' : 
  302.         switch (c=getchar()) {
  303.         case '>':  
  304.         strcpy(letter, "!=");
  305.         break;
  306.         case '=':  
  307.         strcpy(letter, "<=");
  308.         break;
  309.         default :  
  310.         ungetc(c,stdin);
  311.         strcpy(letter,"<");
  312.         }
  313.         cTok.kind = T_COMPARE;
  314.         break;
  315.     case '>' : 
  316.         if ((c=getchar()) == '=')
  317.         strcpy(letter, ">=");
  318.         else {
  319.         ungetc(c,stdin);
  320.         strcpy(letter, ">");
  321.         }
  322.         cTok.kind = T_COMPARE;
  323.         break;
  324.     case '^' :
  325.         if ((c=getchar()) == '.') {    /* perhaps we should skip blanks? */
  326.         strcpy(letter, "->");
  327.         cTok.kind = T_STRUCTMEMBER;
  328.         } else {
  329.         ungetc(c,stdin);
  330.         strcpy(letter, "[0]");    /* '*' would have to go in front */
  331.         cTok.kind = T_DEREF;
  332.         }
  333.         break;
  334.     case '$' :            /* Turbo Pascal extension */ 
  335.         strcpy(letter, "0x");
  336.         cTok.kind = T_ZIP;
  337.         break;
  338.     case ';' :             /* Semicolon- translation depends on */
  339.         strcpy(letter, ";");    /* parse state... */
  340.         cTok.kind = T_SEMI;
  341.         break;
  342.     case '.':
  343.         if ((c=getchar()) == '.') {
  344.         cTok.kind = T_RANGE;
  345.         letter[0]=0;
  346.         } else {
  347.         ungetc(c,stdin);
  348.         strcpy(letter, ".");
  349.         cTok.kind = T_ZIP;
  350.         }
  351.         break;
  352.     case '[':
  353.         *letter++ = c; *letter = '\0';
  354.         cTok.kind = T_LBRACKET;
  355.         break;
  356.     case ']':
  357.         *letter++ = c; *letter = '\0';
  358.         cTok.kind = T_RBRACKET;
  359.         break;
  360.     case ',':
  361.         *letter++ = c; *letter = '\0';
  362.         cTok.kind = T_COMMA;
  363.         break;
  364.     case EOF:            /* end of file */
  365.         cTok.kind = T_EOF;
  366.         break;
  367.     default: 
  368.         *letter++ = c;        /* Pass unknown chars thru as tokens */
  369.         *letter = '\0';
  370.         cTok.kind = T_ZIP;
  371.     }
  372.     }
  373. }
  374.  
  375. main(argc, argv)
  376. int argc;
  377. char **argv;
  378. {
  379.     int debug;
  380.     
  381.     debug = (argc > 1);
  382.     init_hash();
  383.     WasSemi = FALSE;
  384.  
  385.     getTok(); 
  386.     do {
  387.     switch(cTok.kind) {
  388.     case T_VAR:
  389.         parseVar();
  390.         break;
  391.     case T_PROC:
  392.     case T_FUNC:
  393.         parseProcedure();
  394.         break;
  395.     case T_LABEL:
  396.         parseLabel();
  397.         break;
  398.     case T_TYPE:
  399.         parseType();
  400.         break;
  401.     default:
  402.         if (debug)
  403.         printf("'%s' %d\n", cTok.str, cTok.kind);
  404.         else {    /* fancy stuff to avoid duplicating semicolons */
  405.         if (cTok.kind != T_SEMI || !WasSemi)
  406.             fputs(cTok.str, stdout);
  407.         if (cTok.kind != T_SPACE && cTok.kind != T_COMMENT)
  408.             WasSemi = (cTok.kind == T_SEMI);
  409.         }
  410.         getTok();
  411.     }
  412.     } while (cTok.kind != T_EOF);
  413. }
  414.  
  415.