📄 proc.c
字号:
/* @(#)proc.c 1.18 97/03/05 *//* * ==================================================== * Copyright (C) 1995 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */#include <stdio.h>#include <unistd.h> /* for access() */#include "fpp.h"#include "service.h"#include "lex.h"#include "symtab.h"#include "rgram.h" /* for ST_FPP, st_is() */#include "sb.h"#if DEBUGint debug; /* debug level */#endifunsigned mmode; /* main mode of input processing */int line_width0; /* predefined line width */int line_width; /* current input line maximum width */int oline_width; /* current output line maximum width */int f77fl; /* 1 - F77, 0 - F90 */int fixedformfl; /* 1 - fixed form, 0 - free form */int outfl; /* prohibits output when non zero */int falselvl; /* false level in nested #if's */int substfl; /* macro substitution mode (plain text): * 0 - never, 1 - no comments, 2 - always */int dosubstfl; /* force macro substitution, no matter what * value the flag above has */int rmcommfl; /* remove comments */int no_ccom_fl; /* don't recognize c style comments */int linefl; /* output # file, line information */int ignorelinefl; /* ignore input # file directives */int sbfl; /* output for sbrowser */int predefinefl; /* do predefining */int mdepfl; /* generate make dependencies */void *onequalsym; /* assignment substitution */int onequalline; /* assignment substitution line */int ctrl_mode; /* control chars processing mode */int inactive; /* is current line inactive */StrList include_path = { NULL, "."}; /* list of include directories */Comment *comments = NULL; /* list of comments to be outputed by fpp */SymPtr filesymp, FILEsymp; /* fpp dynamic macro */SymPtr linesymp, LINEsymp;typedef struct _ifnode { /* stack of nested #if..s */ int flvlsaved; int elsefl; unsigned ifline; struct _ifnode *popif;} IfNode;static IfNode *curif; /* current #if.. node *//*************************************************************** Bufers */#define INBUFSIZE 1+BUFSIZE+1typedef struct _inbuf { struct _inbuf *next; uchar *psaved; uchar buffer[INBUFSIZE]; } InBuffer;#define INBUF_BEG(buf) ((buf)->buffer + 1)#define INBUF_NEXT(buf) ((buf)->next)#define INBUF_PSAVED(buf) ((buf)->psaved)static InBuffer *curbuf;uchar *curp;InBuffer *new_inbuf() { return (InBuffer *)my_alloc(sizeof(InBuffer),1);}voidfree_inbuf(InBuffer *p) { free(p);}/*typedef struct _outbuf { struct _outbuf *next; char buffer[INBUFSIZE]; } OutBuffer;static OutBuffer *outbuf;static OutBuffer *free_outbufs = NULL;static char outp;OutBuffer *new_outbuf() { OutBuffer *res; if (free_outbufs != NULL) { res = free_outbufs; free_outbufs = free_outbufs->next; } else { res = my_alloc(sizeof(OutBuffer),1); } return res;}voidfree_outbuf(OutBuffer *p) { p->next = free_outbufs; free_outbufs = p;}*//*************************************************************** Input */typedef struct _infile { char *fname; char *dir; unsigned id; unsigned line; FILE *fp; struct _infile *popfile; IfNode *ifnode; InBuffer *inbuf;} InFile;#define INFILE_FP(infile) ((infile)->fp)#define INFILE_EOF(infile) (feof(INFILE_FP(infile)))static InFile *curfile = NULL;static InFile *outfile = NULL;static InFile *mfile = NULL;static char *mdfname = NULL;static unsigned curfileid = 0; /* simple file identification */unsigned line; /* current line of the current file */int colm; /* current column in the line , may be < 0 */static int errline = -1; /* error line number */voidset_pos(int eline) { errline = eline;}char *get_cur_fname() { if (curfile) return curfile->fname; return NULL;}get_err_lineno() { int res; if (line == 0) return 0; if (errline <0) return get_cur_tok()->lineno; res = errline; errline = -1; return res;}InFile *my_fopen(char *fn, char *mod) { InFile *res; FILE *fp; char *s, *s0; fp = fopen(fn,mod); if (fp == NULL) fppmess(FERR_FOPEN,fn); res = my_alloc(sizeof(InFile),1); res->fp = fp; res->id = curfileid++; res->inbuf = new_inbuf(); s0 = my_strdup(fn); s = s0 + strlen(s0); while (s > s0 && *--s != '/'); if ((s == s0) && (*s != '/')) { res->dir = my_strdup(CURDIR); res->fname = s; } else { CHECK(*s == '/'); res->dir = s0; *s = '\0'; res->fname = s+1; } return res;}voidmy_fclose(InFile *fn) { free_inbuf(fn->inbuf); if (strcmp(fn->fname,STDINNAME)) fclose(fn->fp); free(fn);}InFile *fopen_stdfile(FILE *fn) { InFile *res; res = my_alloc(sizeof(InFile),1); res->fp = fn; res->id = curfileid++; res->inbuf = new_inbuf(); if (fn == stdin) res->fname = my_strdup(STDINNAME); else if (fn == stdout) res->fname = my_strdup(STDOUTNAME); else if (fn == stderr) res->fname = my_strdup(STDERRNAME); else CHECK(0); res->dir = my_strdup(CURDIR); return res;}voidmy_fread(uchar *b) { char *res; CHECK(b>=INBUF_BEG(curbuf)&&(b<INBUF_BEG(curbuf)+BUFSIZE)); res = fgets((char *)b,BUFSIZE-(b-INBUF_BEG(curbuf)),curfile->fp); if (res == NULL) { if (ferror(curfile->fp)) fppmess(FERR_FREAD,curfile->fname); else *b = '\0'; } return;}voidmy_fwrite(char *b, int c) { int res; res = fwrite(b,1,c,outfile->fp); if (res != c) fppmess(FERR_FWRITE,outfile->fname); return;}voidmd_fwrite(char *b) { int res; res = fprintf(mfile->fp,"%s.o: %s\n",mdfname,b); if (res < 0) fppmess(FERR_FWRITE,mfile->fname); return;}voidmy_fflush(int status) { if (outfile) { if (status) fprintf(outfile->fp,"\n"); fflush(outfile->fp); } return;}voidrefill() { InBuffer *tmp; CHECK(*curp==0); if (curbuf->next != NULL) { tmp = curbuf; curbuf = curbuf->next; curp = curbuf->psaved; free_inbuf(tmp); } else { curp = INBUF_BEG(curbuf) + BUFSIZE/2; /* to reduce ungetstr time */ my_fread(curp); if (INFILE_EOF(curfile)) { curp[0] = SYM_EOF >> 8; curp[1] = SYM_EOF & 0xff; curp[2] = 0; ctrl_mode++; } if (sbfl) sb_lineid((char *)curp, inactive); }}static voidhide_buffer() { InBuffer *tmp; /* If the current buffer is overflown * we use this function to go on with * a new buffer. */ tmp = new_inbuf(); curbuf->psaved = curp; tmp->next = curbuf; curbuf = tmp; curp = INBUF_BEG(curbuf)+INBUFSIZE;}/*void ungetstr( char *s, int len ) { CHECK(len >= 0); if (len && s[len-1] == '\n') { line--; colm = line_width - len; } else colm -= len; s += len; while (len--) { if (curp <= INBUF_BEG(curbuf)) { hide_buffer(); } *--curp = *--s; }}*/void ungetsym(wchar c) { if (c == '\n') { line--; colm = line_width; } else if (c == SYM_EOF) { colm = line_width; } else colm--; if (curp <= INBUF_BEG(curbuf)) { hide_buffer(); } *--curp = c & 0xff; if (is_special(c)) { ctrl_mode++; if (curp <= INBUF_BEG(curbuf)) { hide_buffer(); } *--curp = SYM_CTRL; } else if (c == SYM_CTRL && ctrl_mode) { if (curp <= INBUF_BEG(curbuf)) { hide_buffer(); } *--curp = SYM_CTRL; }}void ungetstr( char *s, int len ) { CHECK(len >= 0); s += len; while (len--) { ungetsym((wchar) (*--s & 0xff)); }} /************************************************************** Output */static unsigned ofileid = (unsigned)-1;static int ocolm = 0;static int oline = -1; /* output line number */#define NOINCL ""#define PUSHINCL "1"#define POPINCL "2"voidoutpos(int lineno, char *pushpop) { static char buf[BUFSIZE]; static int firsttime = 1; CHECK(curfile); if (firsttime) { firsttime = 0; if (sbfl) sb_version(); ofileid = curfile->id; oline = lineno; if (linefl) { if (!strcmp(curfile->dir,CURDIR)) { sprintf(buf, "# %d \"%s\"\n", oline, curfile->fname); } else { sprintf(buf, "# %d \"%s/%s\"\n", oline, curfile->dir, curfile->fname); } } } else if (curfile->id != ofileid) { ofileid = curfile->id; oline = lineno; if (sbfl) sb_sayline(); if (linefl) { if (curfile->popfile == NULL && !strcmp(curfile->dir,CURDIR)) sprintf(buf, "# %d \"%s\" %s \n", oline, curfile->fname, pushpop); else sprintf(buf, "# %d \"%s/%s\" %s \n", oline, curfile->dir, curfile->fname, pushpop); } } else if (lineno != oline) { oline = lineno; if (sbfl) { sb_lineno(oline); return; } else if (linefl) sprintf(buf, "# %d\n", oline); } else return; if (linefl) my_fwrite(buf,strlen(buf)); return;}voidoutcomm(Comment *com) { if (substfl == 2) { Token *tokp; char *s; int len; int line_width_sav; /* Well, well. Here we are going to * implement "smart" macro expansion * in comments. We'll see. */ if (com->lineno != oline) { if (ocolm != 0) { my_fwrite("\n",1); oline++; ocolm = 0; } outpos(com->lineno, NOINCL); } s = com->str; len = com->length; CHECK(s[len-1] == '\n'); if (s[0] != '\n' && !is_blank(s[0])) { /* The first char is something * like '!', 'C' etc. Output it * as is. */ my_fwrite(s, 1); ocolm++; s++; len--; } ungetsym(SYM_EOC); ungetstr(s, len-1); /* No continuation card until we have finished */ line_width_sav = oline_width; oline_width = LINE_WIDTH_MAX; for (;;) { tokp = get_token(MOD_RAW | MOD_NOGRAM | MOD_COM); if (tokp->val == TK_EOC) { /* We changed \n to SYM_EOC and * now we are paying our debt. */ my_fwrite("\n",1); oline++; ocolm = 0; break; } /* Adjust lineno info */ tokp->lineno = com->lineno; my_fwrite(tokp->token, tokp->length); ocolm += tokp->length; } /* Restore the saved value */ oline_width = line_width_sav; } else { if (com->lineno != oline) { if (ocolm != 0) { my_fwrite("\n",1); oline++; ocolm = 0; } outpos(com->lineno, NOINCL); } else if ((ocolm + com->length > oline_width) && (com->length <= oline_width) ) { /* Try not to loose commented stuf if it * doesn't fit in the remaining of the line. * But if the comment is too long then since * we can't use continuation card for comments * we can do nothing but output it as is. */ my_fwrite("\n",1); oline++; ocolm = 0; outpos(com->lineno, NOINCL); } my_fwrite(com->str, com->length); if (com->str[com->length - 1] == '\n') { oline++; ocolm = 0; } else { ocolm += com->length; } }}voidouttok(Token *tokp) { static char contline[] = "\n *"; static char contline90[] = "&\n&"; static int last_stid = -1; int i; char *p, *endp; CHECK(outfl==0); if (tokp->length == 0) goto exit; if (!outfl && !falselvl) { if (!f77fl && !fixedformfl && tokp->val != TK_NL && tokp->stid == last_stid ) { if (tokp->lineno != oline || ocolm >= oline_width - 1) { my_fwrite("&",1); ocolm++; } } for (;comments;) { Comment *prev; if ((comments->lineno < tokp->lineno) || (comments->lineno == tokp->lineno && tokp->val == TK_NL)) { pushtok(); outcomm(comments); poptok(); prev = comments; comments = comments->next; free(prev); } else break; } if ( tokp->lineno != oline || tokp->stid != last_stid || ocolm >= oline_width ) { if (ocolm != 0) { my_fwrite("\n",1); oline++; ocolm = 0; } if (tokp->val == TK_NL && tokp->lineno < oline) goto exit; outpos(tokp->lineno, NOINCL); } if (fixedformfl && (ocolm == 0) && tokp->stid == last_stid && (tokp->val != TK_NL) && (tokp->val != TK_BOS) ) { my_fwrite(contline+1+ocolm, 6-ocolm); ocolm = 6; } if (tokp->val == TK_NL) { if (tokp->token[0] == '\n') { oline++; ocolm = -1; } else goto exit; /* EOF */ } else if (tokp->val == TK_BOS) { if (ocolm >= 6) { fppmess(ERR_LONGLBL); tokp->token[0] = ' '; tokp->length = 1; } else if (tokp->token[0] == '\t') { ocolm = 5; } else { for (i=0; i < 6-ocolm; i++) tokp->token[i] = ' '; tokp->length = 6 - ocolm; } } p = tokp->token; endp = tokp->token + tokp->length; if (!f77fl && !fixedformfl) { while (ocolm +(endp - p) >= oline_width) { my_fwrite(p, oline_width - ocolm -1); p += oline_width - ocolm -1; my_fwrite(contline90, 3); ocolm = 1; oline++; } } else { while (ocolm +(endp - p) > oline_width) { my_fwrite(p, oline_width - ocolm); p += oline_width - ocolm; my_fwrite(contline, 7); ocolm = 6; oline++; } } my_fwrite(p, endp - p); ocolm += endp - p; } exit: last_stid = tokp->stid; return;}/************************************************************** Tokens */voidskiptok(Token *tokp) { if (tokp) { tokp->length = 0; tokp->token[0] = 0; }}Token *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -