/* Copyright (C) 1999-2004 David Essex, Rildo Pragana This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this software; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA TinyCOBOL Pre-Processor program used as a front end to the main compiler. */ #include #include #include #include #include #include #include #include #include #include "cobpp.h" #include "htconfig.h" #include "tcppversion.h" #include "tcpphelp.h" #include "mwindows.h" extern FILE *pp_yyin; extern FILE *pp_yyout; FILE *yylist; extern int pp_yyparse(void); extern char *filename; char HTG_COPYDIR[PATHMAX3 + 2] = ""; char HTG_FNAME_SUFFIX[PATHMAX1] = ""; char fpath[PATHMAX3 + 2] = ""; char fsuffix[PATHMAX] = ""; char *prg_name; /* #define DEBUG_COBPP_PP 1 */ #ifdef DEBUG_COBPP_PP char errppbuf[1024*8]; void debug_pp_rtn (const char *s1, const char *s2, const char *s3, int w1, int cw); #define DEBUG_PPRTN_STR1(msg1) debug_pp_rtn (msg1, NULL, NULL, 0, 1); #define DEBUG_PPRTN_STR3(msg1, msg2) debug_pp_rtn (msg1, msg2, NULL, 0, 3); #define DEBUG_PPRTN_STR7(msg1, i1) debug_pp_rtn (msg1, NULL, NULL, i1, 7); #define DEBUG_PPRTN_STR15(msg1, msg2, msg3) debug_pp_rtn (msg1, msg2, msg3, 0, 15); #define DEBUG_PPRTN_STR21(msg1, msg2, i1) debug_pp_rtn (msg1, msg2, NULL, i1, 21); #define DEBUG_PPRTN_STR105(msg1, msg2, msg3, i1) debug_pp_rtn (msg1, msg2, msg3, i1, 105); #else #define DEBUG_PPRTN_STR1(msg1) #define DEBUG_PPRTN_STR3(msg1, msg2) #define DEBUG_PPRTN_STR7(msg1, i1) #define DEBUG_PPRTN_STR15(msg1, msg2, msg3) #define DEBUG_PPRTN_STR21(msg1, msg2, i1) #define DEBUG_PPRTN_STR105(msg1, msg2, msg3, i1) #endif /* Global Env struct due to yywrap, yylex */ int main( int argc , char** argv ) { int rc = 0; prg_name = argv[0]; globalEnvPtr = &globalEnv; setDefaults(); /* error, or help/version printed */ rc = setOptions(&globalEnv, argc, argv); if (rc != 0) { if ((rc > 0) && (rc < 100)) { printHelp(); CleanUp(); } return rc; } /* If everything is OK parse file */ filename = strdup (globalEnv.ifname); pp_yyin = fopen(globalEnv.ifname, "r"); if ( pp_yyin == NULL ) { fprintf(stderr, "Error opening input file: %s\n", globalEnv.ifname); rc = 3; return rc; } if (globalEnv.ofname != NULL) { pp_yyout = fopen(globalEnv.ofname, "w"); if ( pp_yyout == NULL ) { fprintf(stderr, "Error opening output file: %s\n" ,globalEnv.ofname ); fclose(pp_yyin); rc = 9; return rc; } } else { pp_yyout = stdout; } if (globalEnv.lfname != NULL) { yylist = fopen(globalEnv.lfname, "w"); if ( yylist == NULL ) { fprintf(stderr, "Error opening listing file: %s\n" ,globalEnv.lfname ); fclose(pp_yyin); if ( pp_yyout != stdout ) { fclose(pp_yyout); } rc = 11; return rc; } } setup_scanner_state(); /* pp_yylex(); */ /* rc = pp_yyparse(); */ (void) pp_yyparse(); rc = globalEnv.errFlag; DEBUG_PPRTN_STR7("Program return code=%d\n", rc) return rc; } /* * Initalize the Env struct passed to this function */ void setDefaults(void) { Env *gEnv = globalEnvPtr; gEnv->codeFormat = -1; /* 1 is free , 0 is fixed */ gEnv->debugFlag = 0; /* debug flag */ gEnv->IncDebugLines = 0; gEnv->verboseFlag = 0; /* set verbose flag off */ gEnv->errFlag = 0; /* no error state by default */ gEnv->tab2space = 0; /* expand tabs to 0 spaces */ gEnv->progName = NULL; gEnv->ofname = NULL; gEnv->ifname = NULL; gEnv->lfname = NULL; } /* * Function to clean up memory allocated in program. * */ void CleanUp(void) { Env *gEnv = globalEnvPtr; globalEnvPtr = NULL; if (gEnv->progName != NULL) free(gEnv->progName); if (gEnv->ifname != NULL) free(gEnv->ifname); if (gEnv->ofname != NULL) free(gEnv->ofname); if (gEnv->lfname != NULL) free(gEnv->lfname); } /* * Read in command line options and set up the Env struct passed in * Alloc memory for program name string in Env struct. * */ int setOptions(Env* gEnv, int argc, char** argv) { /* Read in args for option settings. */ int r = 0, len, sw, i; char tbuf[PATHMAX1] = ""; len = strlen(argv[0]); gEnv->progName = malloc(len + 1); if (gEnv->progName == NULL) { gEnv->errFlag++; r = 2; return r; } strncpy(gEnv->progName, argv[0], len); /* * Check argc for number of args */ /* if (( argc < 2 ) || (argc > 5 )){ */ if ( argc < 2 ){ /* printHelp(); */ gEnv->errFlag++; r = 1; return r; } /* opterr = 0; */ while ((sw = getopt(argc, argv, option_list)) != EOF) { switch (sw) { /* Include debug lines from sources */ case TCOBPP_CMDOPT_INC_DEBUG: gEnv->IncDebugLines = 1; break; /* Not currently used */ case TCOBPP_CMDOPT_DEBUG: gEnv->debugFlag = 1; break; /* Set input file format to FIXED */ case TCOBPP_CMDOPT_FRM_FIXED: if (gEnv->ifname != NULL) { fprintf(stderr, "error: duplicate input file name '%s' ... aborting\n", optarg); gEnv->errFlag++; r = 20; return r; } len = strlen(optarg); /* fprintf(stderr, "cobpp debug: optarg=%s: len=%d\n", optarg, len); */ gEnv->ifname = (char*)malloc(len + 2); if (gEnv->ifname == NULL) { gEnv->errFlag++; r = 21; return r; } strncpy(gEnv->ifname, optarg, len+1); /* fprintf(stderr, "cobpp debug: input file name :%s:, len=%d\n", gEnv->ifname, len); */ gEnv->codeFormat = 0; /* 1 is free, 0 is fixed */ break; /* Add path to copybooks search path */ case TCOBPP_CMDOPT_INC_PATH: append_include_path(optarg); break; /* Set output file name */ case TCOBPP_CMDOPT_OUTFILE: if (gEnv->ofname != NULL) { fprintf(stderr, "error: duplicate output file name '%s' ... aborting\n", optarg); gEnv->errFlag++; r = 40; return r; } len = strlen(optarg); gEnv->ofname = (char*)malloc(len + 2); if (gEnv->ofname == NULL) { gEnv->errFlag++; r = 41; return r; } strncpy(gEnv->ofname, optarg, len+1); /* fprintf(stderr, "cobpp debug: output file name '%s', len=%d\n", gEnv->ofname, len); */ break; /* Set output listinf file name */ case TCOBPP_CMDOPT_LIST: if (gEnv->lfname != NULL) { fprintf(stderr, "error: duplicate listing file name '%s' ... aborting\n", optarg); gEnv->errFlag++; r = 50; return r; } len = strlen(optarg); gEnv->lfname = (char*)malloc(len + 2); if (gEnv->lfname == NULL) { gEnv->errFlag++; r = 51; return r; } strncpy(gEnv->lfname, optarg, len+1); /* fprintf(stderr, "cobpp debug: print file name '%s', len=%d\n", gEnv->lfname, len); */ break; /* Set tab to space conversion length */ case TCOBPP_CMDOPT_TAB_LEN: if (gEnv->tab2space != 0) { fprintf(stderr, "error: duplicate tabs2space argument '%s' specified ... aborting\n", optarg); gEnv->errFlag++; r = 60; return r; } strcpy(tbuf, optarg); /* len = strlen(optarg); */ len = strlen(tbuf); for (i=0; ierrFlag++; r = 61; return r; } } /* sscanf(optarg, "%d", &gEnv->tab2space); */ sscanf(tbuf, "%d", &gEnv->tab2space); if ((gEnv->tab2space < 1) || (gEnv->tab2space > 99)) { fprintf(stderr, "error: invalid tabs2space argument '%s' specified, max=99 min=1 ... aborting\n", optarg); gEnv->errFlag++; r = 62; return r; } /* fprintf(stderr, "cobpp debug: input tab string :%s:, gEnv->tab2space=%d\n", optarg, gEnv->tab2space); fprintf(stderr, "cobpp debug: input tab string :%s:, gEnv->tab2space=%d\n", tbuf, gEnv->tab2space); */ break; /* Set input file format to FREE */ case TCOBPP_CMDOPT_FRM_FREE: if (gEnv->ifname != NULL) { fprintf(stderr, "error: duplicate input file name '%s' ... aborting\n", optarg); gEnv->errFlag++; r = 70; return r; } len = strlen(optarg); /* fprintf(stderr, "cobpp debug: optarg=%s: len=%d\n", optarg, len); */ gEnv->ifname = (char*)malloc(len + 2); /* gEnv->ifname = malloc(len + 2); */ if (gEnv->ifname == NULL) { gEnv->errFlag++; r = 71; return r; } strncpy(gEnv->ifname, optarg, len+1); /* strcpy(gEnv->ifname, optarg); */ /* fprintf(stderr, "cobpp debug: input file name=%s:, len=%d\n", gEnv->ifname, len); */ gEnv->codeFormat = 1; /* 1 is free, 0 is fixed */ break; /* Display version number */ case TCOBPP_CMDOPT_VERSION: printVersion(); r = 197; break; /* Set verbose option on */ case TCOBPP_CMDOPT_VERBOSE: gEnv->verboseFlag = 1; break; /* Display command line help */ case TCOBPP_CMDOPT_HELP1: case TCOBPP_CMDOPT_HELP: default: r = 5; /* printHelp(); */ break; } } if (r == 0) { if (gEnv->ifname == NULL) { fprintf(stderr, "error: no input file name selected ... aborting\n"); gEnv->errFlag++; r = 80; } } /* If tabs not set default to 8 spaces */ if (gEnv->tab2space == 0) gEnv->tab2space = 8; return r; } /* Print out extended help */ void printHelp(void){ /* fprintf (stdout, */ fprintf (stderr, "Usage: %s %s%s", globalEnvPtr->progName, usage_list0, usage_list1 ); } /* * Print pre-processor version and copyright */ void printVersion(void) { fprintf(stdout, "%s - %s\n%s\n", TCOBPP_TITLE, TCOBPP_PGM_VERSION, TCOBPP_COPYWR ); } int find_copybook_file (char *fname, char *lname) { int r = 1, len, sw = 0; char *pt, tpath[PATHMAX1], fname1[PATHMAX], lname1[PATHMAX1]; if (lname == NULL) { if ((*fname == CHR_SQUOTE) || (*fname == CHR_DQUOTE)) { sw = STATE_FLIT_LNONE; strcpy(fname1, fname+1); len = strlen(fname1); fname1[len - 1] = CHR_EOS; r = find_filename_literal(fname1, HTG_COPYDIR); } else { sw = STATE_FNAME_LNONE; strcpy(fname1, fname); strcpy(HTG_FNAME_SUFFIX, STR_SEARCH_SUFFIXES); r = find_filename_text(fname1, HTG_COPYDIR, HTG_FNAME_SUFFIX); } } else { if ((*lname == CHR_SQUOTE) || (*lname == CHR_DQUOTE)) { strcpy(lname1, lname+1); len = strlen(lname1); lname1[len - 1] = CHR_EOS; strcpy(tpath, lname1); len = strlen(tpath); if (len > 0) { if (tpath[len - 1] != CHR_COLEN) { strcat(tpath, STR_COLEN); } } if ((*fname == CHR_SQUOTE) || (*fname == CHR_DQUOTE)) { sw = STATE_FLIT_LLIT; strcpy(fname1, fname+1); len = strlen(fname1); fname1[len - 1] = CHR_EOS; r = find_filename_literal(fname1, tpath); } else { sw = STATE_FNAME_LLIT; strcpy(fname1, fname); strcpy(HTG_FNAME_SUFFIX, STR_SEARCH_SUFFIXES); r = find_filename_text(fname1, tpath, HTG_FNAME_SUFFIX); } } else { if ((*fname == CHR_SQUOTE) || (*fname == CHR_DQUOTE)) { sw = STATE_FLIT_LNAME; strcpy(fname1, fname+1); len = strlen(fname1); fname1[len - 1] = CHR_EOS; strcpy(lname1, lname); pt = find_env_variable(lname1); if (pt != NULL) { strcpy(tpath, pt); } else { strcpy(tpath, ""); } len = strlen(tpath); if (len > 0) { if (tpath[len - 1] != CHR_COLEN) { strcat(tpath, STR_COLEN); } } r = find_filename_literal(fname1, tpath); } else { sw = STATE_FNAME_LNAME; strcpy(fname1, fname); strcpy(lname1, lname); strcpy(HTG_FNAME_SUFFIX, STR_SEARCH_SUFFIXES); pt = find_env_variable(lname1); if (pt != NULL) { strcpy(tpath, pt); } else { strcpy(tpath, ""); } len = strlen(tpath); if (len > 0) { if (tpath[len - 1] != CHR_COLEN) { strcat(tpath, STR_COLEN); } } r = find_filename_text(fname1, tpath, HTG_FNAME_SUFFIX); } } } return r; } int find_filename_literal (char *fname, char *fp) { int r = 1, len, sw1=0; char *pt1; struct stat sbuf; strcpy(fpath, fp); len = strlen(fpath); if (len == 0) { sprintf(include_full_filename, "%s", fname); if (stat(include_full_filename, &sbuf) == 0) { if (S_ISREG(sbuf.st_mode) && ((S_IRUSR & sbuf.st_mode) || (S_IRGRP & sbuf.st_mode) || (S_IROTH & sbuf.st_mode))) { r = 0; if (globalEnvPtr->verboseFlag == 1) { printf("found copybook name \'%s\'\n", include_full_filename); } } else { if (globalEnvPtr->verboseFlag == 1) { printf("copybook file \'%s\' not readable\n", include_full_filename); } } } else { if (globalEnvPtr->verboseFlag == 1) { printf("copybook file \'%s\' not found\n", include_full_filename); } } } else { // If filename is an absolute path ignore library path if (*fname == CHR_SLASH) { if (globalEnvPtr->verboseFlag == 1) { printf("warning: ignoring other search path(s) in absolute path copybook name \'%s\'\n", fname); } sprintf(include_full_filename, "%s", fname); if (stat(include_full_filename, &sbuf) == 0) { if (S_ISREG(sbuf.st_mode) && ((S_IRUSR & sbuf.st_mode) || (S_IRGRP & sbuf.st_mode) || (S_IROTH & sbuf.st_mode))) { r = 0; if (globalEnvPtr->verboseFlag == 1) { printf("found copybook name \'%s\'\n", include_full_filename); } } else { if (globalEnvPtr->verboseFlag == 1) { printf("copybook file \'%s\' not readable\n", include_full_filename); } } } else { if (globalEnvPtr->verboseFlag == 1) { printf("copybook file \'%s\' not found\n", include_full_filename); } } } else { sw1 = 0; strcpy(fpath, fp); pt1 = find_token(fpath, STR_COLEN, 0); if (pt1 == NULL) { pt1 = fpath; } while (sw1 == 0) { sprintf(include_full_filename, "%s", pt1); if (stat(include_full_filename, &sbuf) == 0) { if (S_ISDIR(sbuf.st_mode) && ((S_IRUSR & sbuf.st_mode) || (S_IRGRP & sbuf.st_mode) || (S_IROTH & sbuf.st_mode))) { if (globalEnvPtr->verboseFlag == 1) { printf("searching directory path \'%s\'\n", include_full_filename); } sprintf(include_full_filename, "%s/%s", pt1, fname); if (stat(include_full_filename, &sbuf) == 0) { if (S_ISREG(sbuf.st_mode) && ((S_IRUSR & sbuf.st_mode) || (S_IRGRP & sbuf.st_mode) || (S_IROTH & sbuf.st_mode))) { r = 0; if (globalEnvPtr->verboseFlag == 1) { printf("found copybook name \'%s\'\n", include_full_filename); } sw1 = 1; } else { if (globalEnvPtr->verboseFlag == 1) { printf("copybook file \'%s\' not readable\n", include_full_filename); } } } else { if (globalEnvPtr->verboseFlag == 1) { printf("copybook file \'%s\' not found\n", include_full_filename); } } } else { if (globalEnvPtr->verboseFlag == 1) { printf("directory path \'%s\' not readable\n", include_full_filename); } } } else { if (globalEnvPtr->verboseFlag == 1) { printf("directory path \'%s\' not found\n", include_full_filename); } } pt1 = find_token(pt1, STR_COLEN, 1); if (pt1 == NULL) { sw1 = 1; } } } } return r; } int find_filename_text (char *fname, char *fp, char *fs) { int r = 1, len, sw1, sw2; char *pt1, *pt2; struct stat sbuf; strcpy(fpath, fp); strcpy(fsuffix, fs); len = strlen(fpath); if (len == 0) { sw1 = 0; pt1 = find_token(fsuffix, STR_COLEN, 0); if (pt1 == NULL) { pt1 = fsuffix; } while (sw1 == 0) { sprintf(include_full_filename, "%s%s", fname, pt1); if (stat(include_full_filename, &sbuf) == 0) { if (S_ISREG(sbuf.st_mode) && ((S_IRUSR & sbuf.st_mode) || (S_IRGRP & sbuf.st_mode) || (S_IROTH & sbuf.st_mode))) { r = 0; if (globalEnvPtr->verboseFlag == 1) { printf("found copybook name \'%s\'\n", include_full_filename); } sw1 = 1; } else { if (globalEnvPtr->verboseFlag == 1) { printf("copybook file \'%s\' not readable\n", include_full_filename); } } sw1 = 1; } else { if (globalEnvPtr->verboseFlag == 1) { printf("copybook file \'%s\' not found\n", include_full_filename); } } pt1 = find_token(pt1, STR_COLEN, 1); if (pt1 == NULL) { sw1 = 1; } } } else { sw1 = 0; sw2 = 0; strcpy(fpath, fp); strcpy(fsuffix, fs); pt1 = find_token(fpath, STR_COLEN, 0); if (pt1 == NULL) { pt1 = fpath; } while (sw1 == 0) { sprintf(include_full_filename, "%s", pt1); if (stat(include_full_filename, &sbuf) == 0) { if (S_ISDIR(sbuf.st_mode) && ((S_IRUSR & sbuf.st_mode) || (S_IRGRP & sbuf.st_mode) || (S_IROTH & sbuf.st_mode))) { if (globalEnvPtr->verboseFlag == 1) { printf("searching directory path \'%s\'\n", include_full_filename); } strcpy(fsuffix, fs); sw2 = 0; pt2 = find_token(fsuffix, STR_COLEN, 0); while (sw2 == 0) { sprintf(include_full_filename, "%s/%s%s", pt1, fname, pt2); if (stat(include_full_filename, &sbuf) == 0) { if (S_ISREG(sbuf.st_mode) && ((S_IRUSR & sbuf.st_mode) || (S_IRGRP & sbuf.st_mode) || (S_IROTH & sbuf.st_mode))) { r = 0; if (globalEnvPtr->verboseFlag == 1) { printf("found copybook name \'%s\'\n", include_full_filename); } sw1 = 1; sw2 = 1; } else { if (globalEnvPtr->verboseFlag == 1) { printf("copybook file \'%s\' not readable\n", include_full_filename); } } sw2 = 1; } else { if (globalEnvPtr->verboseFlag == 1) { printf("copybook file \'%s\' not found\n", include_full_filename); } } pt2 = find_token(pt2, STR_COLEN, 1); if (pt2 == NULL) { sw2 = 1; } } } else { if (globalEnvPtr->verboseFlag == 1) { printf("directory path \'%s\' not readable\n", include_full_filename); } } } else { if (globalEnvPtr->verboseFlag == 1) { printf("directory path \'%s\' not found\n", include_full_filename); } } pt1 = find_token(pt1, STR_COLEN, 1); if (pt1 == NULL) { sw1 = 1; } } } return r; } char *find_env_variable (char *ev) { char *pt, ev1[PATHMAX]; int i, len; len = strlen(ev); for (i=0; iverboseFlag == 1) { printf("envoromental variable \'%s\' found, setting search path(s) to \'%s\'\n", ev1, pt); } return pt; } if (globalEnvPtr->verboseFlag == 1) { printf("warning: envoromental variable \'%s\' not found\n", ev1); } return NULL; } char *find_token(char *p, const char *d, int sw) { int i, len; DEBUG_PPRTN_STR105("find_token trace(1): p=%s; d=%s, sw=%d\n", p, d, sw) if (sw == 0) { len = strlen(p); *(p+len+1) = CHR_EOS; for (i=0; iverboseFlag == 1) { fprintf (stdout, "Appending '%s' to include (copybooks) search path\n", ap); } if (rc != 0) { fprintf (stderr, "%s: *** Buffer overflow error while appending '%s' to include (copybooks) search path. Abort.\n", prg_name, ap); exit(rc); } } #ifdef DEBUG_COBPP_PP void debug_pp_rtn (const char *s1, const char *s2, const char *s3, int w1, int cw) { switch (cw) { case 3: sprintf(errppbuf, s1, s2); break; case 5: sprintf(errppbuf, s1, s3); break; case 7: sprintf(errppbuf, s1, w1); break; case 15: sprintf(errppbuf, s1, s2, s3); break; case 21: sprintf(errppbuf, s1, s2, w1); break; case 35: sprintf(errppbuf, s1, s3, w1); break; case 105: sprintf(errppbuf, s1, s2, s3, w1); break; default: sprintf(errppbuf, "%s", s1); break; } fprintf(stderr, "%s", errppbuf); } #endif