prdecl.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 1,179 行 · 第 1/2 页
C
1,179 行
#ifndef lintstatic char *sccsid = "@(#)prdecl.c 4.1 (ULTRIX) 7/17/90";#endif lint/************************************************************************ * * * Copyright (c) 1986 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//** File: prdecl.c** Pascal to C translator - Parser for declarations* - Const, type & variable declarations*//* * TO DO * * types of: array of complex type, array bounds of * enumeration in place: [(red,blue,green)] *//* Modification History * * 21-July-87 afd * If a const value is more than 1 char, then call it a string (STRINGTY) * */#include <stdio.h>#include "ptoc.h"#ifdef PRDEBUGint prdebug = 1;#define printd if (prdebug) fprintf#define printd10 if (prdebug >= 10) fprintf#endifextern enum token nexttoken; /* next Pascal token obtained as input */extern struct scaninfo scandata;extern char tokenahead;extern struct stentry *stindex[MAXLEV]; /* sym table pts by lexic level */extern int lexlev; /* current lexical level */extern int savecmt; /* True when comment saved */extern int linecounter; /* for myexit() */extern char currfile[LINELENGTH]; /* file name for myexit() */enum token holdtoken;char *malloc();struct stentry *getstentry();char *getname();struct pairs *getpairs();struct stentry *findany();struct treenode *gettn();struct cmtinfo *getcmtinfo();/* * constseg: Get a constant segment. */constseg(tn) struct treenode *tn; /* ptr to decl begin block */{ struct stentry *st; /* current type symbol */ char negative; if (nexttoken == CONSTT) {# ifdef PRDEBUG printd(stderr,"constseg: got CONST token\n");# endif savecmt = 1; scanner(0); /* get const id */ savecmt = 0; commentseg(tn); do { st = getstentry(); st->st_name = getname(scandata.si_idlen); strcpy(st->st_name, scandata.si_name); st->st_class = CONSTC; addsymbol(st); if (tn->firstsym == NULL) tn->firstsym = st; tn->lastsym = st; savecmt = 0; scanner(0); /* get = */ scanner(0); negative = 0; if (nexttoken == PLUS) { scanner(0); } else if (nexttoken == MINUS) { negative = 1; scanner(0); } if (nexttoken != IDENT) switch (nexttoken) { case NUMCONST: if (scandata.si_dflag == 2) { st->st_fcval = scandata.si_cvalue; if (negative) st->st_fcval = -st->st_fcval; st->st_tipe = REALTY; } else { st->st_cval = scandata.si_cvalue; if (negative) st->st_cval = -st->st_cval; st->st_tipe = INTTY; } break; case CHARCONST: if (scandata.si_idlen != 1) { /* string */ st->st_string = getname(scandata.si_idlen); strcpy(st->st_string, scandata.si_name); st->st_tipe = STRINGTY; } else { st->st_string = NULL; st->st_cval = scandata.si_name[0]; st->st_tipe = CHARTY; } break; case TRUET: st->st_cval = 1; st->st_tipe = INTTY; break; case FALSET: st->st_cval = 0; st->st_tipe = INTTY; break; case PERCENT: scanner(0); if (nexttoken != IDENT) myexit(3,"bad constant"); if ((strcmp(scandata.si_name,"o") == 0) || (strcmp(scandata.si_name,"O") == 0)) st->st_tipe = OCTALTY; else if ((strcmp(scandata.si_name,"x") == 0) || (strcmp(scandata.si_name,"X") == 0)) st->st_tipe = HEXTY; else myexit(3,"bad constant"); /* * Call scanner to get octal or hex const within * apostrophes. Use st_uptr to point to the * constant string. */ scanner(0); if (nexttoken != CHARCONST) myexit(3,"bad constant"); st->st_uptr = (struct stentry *) getname(scandata.si_idlen); strcpy(st->st_uptr, scandata.si_name); st->st_cval = 0; break; default: myexit(3,"bad constant"); } else { st->st_tipe = USERTYPE; st->st_uptr = findany(scandata.si_name); } scanner(0); /* get SEMI */ if (nexttoken != SEMICOLON) myexit(2,";"); savecmt = 1; scanner(0); /* get next token */ savecmt = 0; if (nexttoken == COMMENT) { st->st_cmt = scandata.si_cmtptr; /* comment loop here ? to get multiple comments in a row */ savecmt = 1; scanner(0); savecmt = 0; commentseg(tn); } } while (nexttoken == IDENT); return(1); } else return(0);}/* * typeseg: Get a type segment. */typeseg(tn) struct treenode *tn; /* ptr to decl begin block */{ struct stentry *st; /* current type symbol */ struct stentry *tmpst; /* temporary stptr */ if (nexttoken == TYPET) {# ifdef PRDEBUG printd(stderr,"typeseg: got TYPE token\n");# endif savecmt = 1; scanner(0); /* get type id */ savecmt = 0; commentseg(tn); do { st = getstentry(); inittvf(st); st->st_name = getname(scandata.si_idlen); strcpy(st->st_name, scandata.si_name); st->st_class = TYPEC; addsymbol(st); if (tn->firstsym == NULL) tn->firstsym = st; tn->lastsym = st; savecmt = 0; scanner(0); /* get = */ scanner(0); /* * Check for VMS format of: "id = [attributes] type;" */ if (nexttoken == LEFTBRACKET) { while (nexttoken != RIGHTBRACKET) scanner(0); scanner(0); } if (!datatype(st)) myexit(3,"data type not recognized"); /* * If the type was an enumerated type we must update * tn->lastsym to point to the last enumeration constant. */ if (st->st_dstruct == UDEFS && st->st_tipe == ENUMTY) { for (tmpst = st->st_uptr; tmpst->st_link != NULL; tmpst = tmpst->st_link) ; tn->lastsym = tmpst; } scanner(0); /* get SEMI */ if (nexttoken != SEMICOLON) myexit(2,";"); savecmt = 1; scanner(0); /* get next token */ savecmt = 0; if (nexttoken == COMMENT) { st->st_cmt = scandata.si_cmtptr; /* comment loop here to get multiple comments in a row */ savecmt = 1; scanner(0); savecmt = 0; commentseg(tn); } } while (nexttoken == IDENT); return(1); } /* if (nexttoken == TYPET) */ else return(0);}/* * varseg: Get a var segment. */varseg(tn, functn) struct treenode *tn; /* ptr to decl begin block */ struct treenode *functn; /* ptr to func/proc tree node */{ struct stentry *st; /* current var symbol */ struct stentry *secthead; /* head of a section of var decls: eg: v1,v2,v3: data-type */ struct stentry *sect; /* ptr to current stentry */ struct stentry *funcst; /* ptr to func/proc stentry */ struct stentry *dupst; /* to fill out dupvar st_entryies */ char buf[LINELENGTH]; /* to hold init value */ /* * If function (not proc or main) then set up a dummy var with * same name as the function name to take Pascal assignments to the * function. */ if (functn->type == FDECLNODE) { st = getstentry(); inittvf(st); funcst = functn->stdecl; st->st_name = getname(strlen(funcst->st_name)); strcpy(st->st_name, funcst->st_name); funcst = functn->ftype; st->st_lexlev = lexlev; st->st_dstruct = funcst->st_dstruct; st->st_tipe = funcst->st_tipe; st->st_class = VARC; st->st_uptr = funcst->st_uptr; st->st_numdims = funcst->st_numdims; st->st_bounds = funcst->st_bounds; st->st_funcvar = 1; addsymbol(st); if (tn->firstsym == NULL) tn->firstsym = st; tn->lastsym = st; } if (nexttoken == VART) {# ifdef PRDEBUG printd(stderr,"typeseg: got VAR token\n");# endif savecmt = 1; scanner(0); /* get var id */ savecmt = 0; commentseg(tn); do { secthead = NULL; do { /* * Check for VMS/Pascal "mechanism-specifier" */ if (nexttoken == PERCENT) { scanner(0); if (nexttoken == MECHT) scanner(0); else myexit(2, "mechanism-specifier"); } st = getstentry(); inittvf(st); /* * String together constructs like v1, v2, v3: type; */ if (secthead == NULL) { secthead = st; sect = st; } else { sect->st_dupvar = st; sect = st; } st->st_name = getname(scandata.si_idlen); strcpy(st->st_name, scandata.si_name); st->st_class = VARC; addsymbol(st); if (tn->firstsym == NULL) tn->firstsym = st; tn->lastsym = st; savecmt = 0; scanner(0); /* get next token */ if (nexttoken == COMMA) scanner(0); } while (nexttoken != COLON); scanner(0); /* * Check for VMS format of: "id: [attributes] type;" */ if (nexttoken == LEFTBRACKET) { while (nexttoken != RIGHTBRACKET) scanner(0); scanner(0); } /* * Fill in data type for head variable in this `section': * eg. v1, v2, v3: data-type; */ if (!datatype(secthead)) myexit(3,"data type not recognized"); /* * If the type was an enumerated type we must update * tn->lastsym to point to the last enumeration constant. */ if (secthead->st_dstruct == UDEFS && secthead->st_tipe == ENUMTY) { for (dupst = secthead->st_uptr; dupst->st_link != NULL; dupst = dupst->st_link) ; tn->lastsym = dupst; } /* * Make dupvar's "st_next" field's point to same place as * the secthead's st_next. Needed to find subfields under the * dupvar, if the dupvar is of type record and gets used in a * "with" stmt. * * Also save other "type" fields for help in processing "with" * statements. */ for (dupst = secthead->st_dupvar; dupst != NULL; dupst = dupst->st_dupvar) { dupst->st_next = secthead->st_next; dupst->st_lexlev = secthead->st_lexlev; dupst->st_dstruct = secthead->st_dstruct; dupst->st_tipe = secthead->st_tipe; dupst->st_class = secthead->st_class; dupst->st_uptr = secthead->st_uptr; dupst->st_numdims = secthead->st_numdims; dupst->st_bounds = secthead->st_bounds; } scanner(0); /* get SEMI */ if (nexttoken != SEMICOLON) if (nexttoken == ASSIGNOP) { scanner(0); /* * Check for VMS/Pascal "mechanism-specifier" */ if (nexttoken == PERCENT) { scanner(0); if (nexttoken == MECHT) scanner(0); else myexit(2, "mechanism-specifier"); } buf[0] = '\0'; getexpr(buf,0); secthead->st_value = malloc(strlen(buf) + 1); if (secthead->st_value == NULL) myexit(-1,""); if (buf[0] == '(') { buf[0] = '{'; if (buf[strlen(buf)-1] == ')') buf[strlen(buf)-1] = '}'; } strcpy(secthead->st_value,buf); } else myexit(2,";"); savecmt = 1; scanner(0); /* get next token */ savecmt = 0; if (nexttoken == COMMENT) { secthead->st_cmt = scandata.si_cmtptr; /* comment loop here ? to get multiple comments in a row */ savecmt = 1; scanner(0); savecmt = 0; commentseg(tn); } } while (nexttoken == IDENT || nexttoken == PERCENT); return(1); } else return(0);}/* * datatype: Get a datatype. * <data_type> ::= <simple_type> | <array_type> | ^<id> | file of <data_type> | * set of <simple_type> | record <filedlist> end */datatype(st) struct stentry *st;{ if (nexttoken == PACKED) scanner(0); if (!simpletype(st)) if (!arraytype(st)) if (nexttoken == UPARROW) { st->st_dstruct = PTRS; scanner(0); /* get id */ if (!simpletype(st)) myexit(3,"bad pointer type"); } else if (nexttoken == FILET) { scanner(0); /* get 'of' */ scanner(0); if (!datatype(st)) myexit(3,"data type not recognized"); st->st_dstruct = FILESTR; /* MUST follow call for type to set back struct type */ } else if (nexttoken == SETT) { scanner(0); /* get 'of' */ if (nexttoken != OFT) myexit(2,"of"); scanner(0); if (!simpletype(st)) /* get type of the set */ myexit(3,"bad set type"); st->st_dstruct = SETS; /* MUST follow call for type to set back struct type */ } else if (nexttoken == RECORDT) { st->st_dstruct = RECORDS; lexlev++; fieldlist(st,0); stindex[lexlev] = NULL; /* terminate inner level */ lexlev--; } else return(0); /* no datatype */ return(1);}/* * <simple_type> ::= integer | boolean | char | real | <id> | ( <id> {,<id>}*) | * <constant> .. <constant> | <const-id> .. <const-id> */simpletype(st) struct stentry *st;{ struct stentry *hold; /* hold a ptr to the enum sym table entry */ char holdname[LINELENGTH]; /* hold last symbol name for 'look-ahead' */ int i; /* number of enum constants */ if (nexttoken == MINUS || nexttoken == PLUS) scanner(1); /* could be negative subrange */ switch (nexttoken) { case BOOLEANT: st->st_tipe = BOOLTY; break; case DOUBLE: st->st_tipe = DOUBLETY; break; case CHART: st->st_tipe = CHARTY; break; case INTEGERT: st->st_tipe = INTTY; break; case REALT: st->st_tipe = REALTY; break; case UNSIGNT: st->st_tipe = UNSIGNEDTY; break; case IDENT: holdtoken = nexttoken; strcpy(holdname,scandata.si_name); scanner(1); /* 1 for no reals, despite '.' */ if (nexttoken == DOTDOT) { st->st_dstruct = SUBRANGES; nexttoken = holdtoken; getrange(st,1); /* 1=lower bound */ scanner(0); /* get next const */ if (nexttoken == MINUS) scanner(1); getrange(st,0); /* 0=upper bound */ }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?