home *** CD-ROM | disk | FTP | other *** search
- From decwrl!labrea!rutgers!mailrus!tut.cis.ohio-state.edu!ucbvax!unisoft!uunet!allbery Sat Feb 4 10:50:10 PST 1989
- Article 811 of comp.sources.misc:
- Path: granite!decwrl!labrea!rutgers!mailrus!tut.cis.ohio-state.edu!ucbvax!unisoft!uunet!allbery
- From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
- Newsgroups: comp.sources.misc
- Subject: v06i036: JCL emulator
- Message-ID: <48165@uunet.UU.NET>
- Date: 4 Feb 89 03:18:19 GMT
- Sender: allbery@uunet.UU.NET
- Reply-To: lupton@uhccux.uhcc.Hawaii.Edu (Robert Lupton)
- Lines: 1150
- Approved: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
-
- Posting-number: Volume 6, Issue 36
- Submitted-by: lupton@uhccux.uhcc.Hawaii.Edu (Robert Lupton)
- Archive-name: jcl
-
- [You always knew someone would do this...! ;-) ++bsa]
-
- I wrote this a while ago, and have just found it on an old tape, so
- here it is. It emulates our favourite operating system, JCL. To use
- it, unpack the shar file, run make, then "JCL < deck" as a demo.
-
- As it says in the README, I bequeath this code to the net. In particular
- I don't intend to handle any bugfixes/improvements.
-
- Robert Lupton
-
- : =-=-=-=-=-=-=-=-=-=-= Cut Here =-=-=-=-=-=-=-=-=-=-=
- PATH=/bin:/usr/bin:/usr/ucb:/etc:$PATH
- export PATH
- echo Extracting CC
- if [ -w CC ]; then
- echo File already exists - saving as CC.old
- mv CC CC.old
- chmod 444 CC.old
- fi
- sed 's/^X//' <<'//go.sysin dd *' >CC
- mv $SYSIN $SYSIN.c
- cc -c $* $SYSIN.c
- mv $SYSIN.o $SYSOUT
- mv $SYSIN.c $SYSIN
- //go.sysin dd *
- if [ `wc -c < CC` != 76 ]; then
- made=FALSE
- echo error transmitting CC --
- echo length should be 76, not `wc -c < CC`
- else
- made=TRUE
- fi
- if [ $made = TRUE ]; then
- chmod 755 CC
- echo -n ; ls -ld CC
- fi
- echo Extracting LKED
- if [ -w LKED ]; then
- echo File already exists - saving as LKED.old
- mv LKED LKED.old
- chmod 444 LKED.old
- fi
- sed 's/^X//' <<'//go.sysin dd *' >LKED
- mv $SYSIN $SYSIN.o
- cc $SYSIN.o $*
- mv a.out $SYSOUT
- mv $SYSIN.o $SYSIN
- //go.sysin dd *
- if [ `wc -c < LKED` != 70 ]; then
- made=FALSE
- echo error transmitting LKED --
- echo length should be 70, not `wc -c < LKED`
- else
- made=TRUE
- fi
- if [ $made = TRUE ]; then
- chmod 755 LKED
- echo -n ; ls -ld LKED
- fi
- echo Extracting Makefile
- if [ -w Makefile ]; then
- echo File already exists - saving as Makefile.old
- mv Makefile Makefile.old
- chmod 444 Makefile.old
- fi
- sed 's/^X//' <<'//go.sysin dd *' >Makefile
- #
- # Default rules for compiling code.
- #
- .c.o :
- cc $(CFLAGS) $*.c
- #
- CFLAGS = -c -g
- #
- # linker flags
- #
- LDFLAGS = -lg -lm
- #
- # define macros for the source files
- #
- SOURCE = \
- #
- OBJECT = \
- parser.o data_defs.o keyword.o main.o yylex.o
- #
- # cmp is used in issame (needed by VMS)
- #
- #cmp : cmp.o
- # cc cmp.o -o cmp
- #
- # Make JCL
- #
- JCL : $(OBJECT)
- cc -o JCL $(OBJECT) $(LDFLAGS)
- #
- # make parser.c from parser.y
- # issame sees if keyword.h is changed. if not, don't update it
- #
- parser.c : parser.y
- @- echo Expect 4 unreduced rules
- yacc -d parser.y
- @ mv y.tab.c parser.c
- @ csh -f issame y.tab.h keyword.h
- #
- # make keyword.c from the list of tokens in keyword.h
- #
- make_keyword : make_keyword.o
- cc make_keyword.o -o make_keyword
- #
- keyword.c : keyword.h make_keyword
- make_keyword keyword.h
- #
- clean :
- - rm *.o JCL cmp make_keyword parser.c keyword.h keyword.c \
- y.output *~ core
- #
- # Here are all the dependencies:
- #
- keyword.o : keyword.h
- data_defs.o : jcl.h
- main.o : yaccun.h
- parser.o : yaccun.h jcl.h
- yylex.o : yaccun.h keyword.h jcl.h
- //go.sysin dd *
- if [ `wc -c < Makefile` != 1036 ]; then
- made=FALSE
- echo error transmitting Makefile --
- echo length should be 1036, not `wc -c < Makefile`
- else
- made=TRUE
- fi
- if [ $made = TRUE ]; then
- chmod 644 Makefile
- echo -n ; ls -ld Makefile
- fi
- echo Extracting README
- if [ -w README ]; then
- echo File already exists - saving as README.old
- mv README README.old
- chmod 444 README.old
- fi
- sed 's/^X//' <<'//go.sysin dd *' >README
- This is something I wrote a few years ago in a fit of nostalgia, but
- never really quite got finished. It was intended to run as a login
- shell on my new shiny sun, to discourage other users from taking my
- CPU cycles.
-
- It is an emulator for for favourite operating system, JCL on an IBM 360.
- It works as far as it goes, but I never got around to implementing
- libraries (I was going to use "ar" via system() calls). The grammar
- is a bit of a hack, with the lex analysis doing a good deal of the work.
-
- To try it out, type "JCL < deck" after running make. I don't really want
- to deal with any enhancements or bug fixes (although I'd be happy to
- see the code improved). I therefore bequeath this code to the net, with
- no strings attached. On the other hand, I doubt if there is much money
- to be made out of it.
-
- One thing that I intended to do, but never did, was to make JCL accept
- input produced by "bcd" (i.e. real card images). I have a programme
- somewhere that's like bcd but writes paper tapes, if there were enough
- interest I could post it.
-
-
- Robert Lupton
- //go.sysin dd *
- if [ `wc -c < README` != 1121 ]; then
- made=FALSE
- echo error transmitting README --
- echo length should be 1121, not `wc -c < README`
- else
- made=TRUE
- fi
- if [ $made = TRUE ]; then
- chmod 644 README
- echo -n ; ls -ld README
- fi
- echo Extracting cmp.c
- if [ -w cmp.c ]; then
- echo File already exists - saving as cmp.c.old
- mv cmp.c cmp.c.old
- chmod 444 cmp.c.old
- fi
- sed 's/^X//' <<'//go.sysin dd *' >cmp.c
- X/*
- * This programme returns 1 (true) if the two files given as
- * arguments are identical, otherwise it returns 2 (false)
- */
- #include <stdio.h>
-
-
- main(ac,av)
- int ac;
- char *av[];
- {
- char c1,c2; /* characters read from files */
- int fil1,fil2; /* fd's for two files */
-
- if(ac < 3 || (fil1 = open(av[1],0)) < 0 || (fil2 = open(av[2],0)) < 0) {
- exit(2);
- }
-
- while(1) {
- if(read(fil1,&c1,1) == 1) {
- if(read(fil2,&c2,1) == 1) {
- if(c1 != c2) exit(2);
- else ;
- } else {
- exit(2);
- }
- } else if(read(fil2,&c2,1) == 1) {
- exit(2);
- } else {
- exit(1);
- }
- }
- }
- //go.sysin dd *
- if [ `wc -c < cmp.c` != 671 ]; then
- made=FALSE
- echo error transmitting cmp.c --
- echo length should be 671, not `wc -c < cmp.c`
- else
- made=TRUE
- fi
- if [ $made = TRUE ]; then
- chmod 755 cmp.c
- echo -n ; ls -ld cmp.c
- fi
- echo Extracting data_defs.c
- if [ -w data_defs.c ]; then
- echo File already exists - saving as data_defs.c.old
- mv data_defs.c data_defs.c.old
- chmod 444 data_defs.c.old
- fi
- sed 's/^X//' <<'//go.sysin dd *' >data_defs.c
- X/*
- * Maintain information about DD statements
- */
- #include <stdio.h>
- #include "jcl.h"
-
- #define NDD 20 /* Max. number of current DD sets */
- #define SIZE 80 /* length of character strings */
-
- typedef struct {
- char name[SIZE], /* name of DD set */
- file[SIZE], /* name of associated file */
- step[SIZE]; /* name of step */
- int disp[3]; /* DISP modes */
- } DD_SET;
-
- static DD_SET dds[NDD]; /* the available DDs */
-
- init_dd()
- {
- int i;
-
- for(i = 0;i < NDD;i++) {
- dds[i].name[0] = '\0';
- }
- }
-
- create_dd(name,file,step,disp)
- char *name,
- *file,
- *step;
- int disp[];
- {
- char msg[40];
- int i;
-
- for(i = 0;i < NDD;i++) {
- if(!strcmp(name,dds[i].name)) {
- sprintf(msg,"DD set %s already exists",name);
- yyerror(msg);
- break;
- } else if(dds[i].name[0] == '\0') {
- break;
- }
- }
- if(i == NDD) {
- yyerror("Too many DD sets");
- return(-1);
- }
-
- strcpy(dds[i].name,name);
- strcpy(dds[i].file,file);
- strcpy(dds[i].step,step);
-
- if(disp[0] != UNKNOWN) {
- dds[i].disp[0] = disp[0];
- } else {
- if(access(file,0) == -1) { /* file dosn't exist */
- dds[i].disp[0] = NEW;
- } else {
- dds[i].disp[0] = OLD;
- }
- }
-
- if(disp[1] != UNKNOWN) {
- dds[i].disp[1] = disp[1];
- } else {
- if(dds[i].disp[0] == NEW) {
- dds[i].disp[1] = DELETE;
- } else {
- dds[i].disp[1] = KEEP;
- }
- }
-
- if(disp[2] != UNKNOWN) {
- dds[i].disp[2] = disp[2];
- } else {
- if(dds[i].disp[0] == NEW) {
- dds[i].disp[2] = DELETE;
- } else {
- dds[i].disp[2] = KEEP;
- }
- }
- }
-
- X/******************************************************/
- X/*
- * Cleanup after a job step
- */
- step_clean_dd(step)
- char *step; /* name of step */
- {
- int i;
-
- for(i = 0;i < NDD;i++) {
- if(dds[i].name[0] != '\0' && !strcmp(step,dds[i].step)) {
- if(dds[i].disp[1] == DELETE) {
- unlink(dds[i].file);
- }
- }
- }
- }
-
- X/******************************************************/
- X/*
- * Cleanup after job terminates
- */
- job_clean_dd()
- {
- int i;
-
- for(i = 0;i < NDD;i++) {
- if(dds[i].name[0] != '\0') {
- if(dds[i].disp[2] == DELETE) {
- unlink(dds[i].file);
- }
- }
- }
- }
-
- X/******************************************************/
- X/*
- * Return a string defining all units used in a job step
- */
- char *
- define_dd(step)
- char *step; /* name of step */
- {
- static char string[200],
- *sptr;
- int i;
-
- sptr = string;
- for(i = 0;i < NDD;i++) {
- if(dds[i].name[0] != '\0' && !strcmp(step,dds[i].step)) {
- sprintf(sptr,"%s=%s;export %s;",dds[i].name,dds[i].file,dds[i].name);
- sptr += 10 + 2*strlen(dds[i].name) + strlen(dds[i].file);
- }
- }
- return(string);
- }
-
- //go.sysin dd *
- if [ `wc -c < data_defs.c` != 2689 ]; then
- made=FALSE
- echo error transmitting data_defs.c --
- echo length should be 2689, not `wc -c < data_defs.c`
- else
- made=TRUE
- fi
- if [ $made = TRUE ]; then
- chmod 644 data_defs.c
- echo -n ; ls -ld data_defs.c
- fi
- echo Extracting deck
- if [ -w deck ]; then
- echo File already exists - saving as deck.old
- mv deck deck.old
- chmod 444 deck.old
- fi
- sed 's/^X//' <<'//go.sysin dd *' >deck
- X//NAME JOB ROBERT.H.LUPTON,MSGLEVEL=(2,2), comments 78901
- X// MSGCLASS=A
- X//COMP EXEC PGM=CC,PARM='-g'
- X//SYSOUT DD DSN=TEMP,DISP=KEEP
- X//SYSIN DD *
- #include <stdio.h>
- main()
- {
- printf("Hello World\n");
- }
- X/*
- X//LKED EXEC PGM=LKED,PARM='-lc'
- X//SYSIN DD DSN=TEMP,DISP=(,KEEP,DELETE)
- X//SYSOUT DD DSN=TST,DISP=(,KEEP,DELETE)
- X//GO EXEC PGM=TST
- X//
- //go.sysin dd *
- if [ `wc -c < deck` != 390 ]; then
- made=FALSE
- echo error transmitting deck --
- echo length should be 390, not `wc -c < deck`
- else
- made=TRUE
- fi
- if [ $made = TRUE ]; then
- chmod 644 deck
- echo -n ; ls -ld deck
- fi
- echo Extracting issame
- if [ -w issame ]; then
- echo File already exists - saving as issame.old
- mv issame issame.old
- chmod 444 issame.old
- fi
- sed 's/^X//' <<'//go.sysin dd *' >issame
- # /bin/csh -f
- #
- # $1 contains a new version of $2
- # this programme compares the two files $1 and $2
- # if they are different, then replace $1 by $2
- # The programme is called by make
- #
- if({ cmp -s $1 $2 })then # The same
- /bin/rm $1
- else # different
- /bin/mv $1 $2
- endif
- //go.sysin dd *
- if [ `wc -c < issame` != 272 ]; then
- made=FALSE
- echo error transmitting issame --
- echo length should be 272, not `wc -c < issame`
- else
- made=TRUE
- fi
- if [ $made = TRUE ]; then
- chmod 755 issame
- echo -n ; ls -ld issame
- fi
- echo Extracting jcl.h
- if [ -w jcl.h ]; then
- echo File already exists - saving as jcl.h.old
- mv jcl.h jcl.h.old
- chmod 444 jcl.h.old
- fi
- sed 's/^X//' <<'//go.sysin dd *' >jcl.h
- X/*
- * Parameters defined for the `scheduler'
- */
- #define PSIZE 60 /* size of parm */
- #define UNKNOWN 0 /* DISP parameters */
- #define DELETE 1
- #define KEEP 2
- #define NEW 3
- #define OLD 4
-
- extern char parm[]; /* parameters for EXEC */
- extern FILE *msgout; /* output from `scheduler' */
- extern int msglevel1, /* MSGLEVEL=(msglevel1,msglevel2) */
- msglevel2;
- //go.sysin dd *
- if [ `wc -c < jcl.h` != 367 ]; then
- made=FALSE
- echo error transmitting jcl.h --
- echo length should be 367, not `wc -c < jcl.h`
- else
- made=TRUE
- fi
- if [ $made = TRUE ]; then
- chmod 644 jcl.h
- echo -n ; ls -ld jcl.h
- fi
- echo Extracting main.c
- if [ -w main.c ]; then
- echo File already exists - saving as main.c.old
- mv main.c main.c.old
- chmod 444 main.c.old
- fi
- sed 's/^X//' <<'//go.sysin dd *' >main.c
- #include <stdio.h>
- #include "yaccun.h"
-
- YYSTYPE yylval,yyval;
- int verbose = 0;
-
- main(ac,av)
- int ac;
- char *av[];
- {
- if(ac > 1) {
- sscanf(av[1],"-v=%d",&verbose);
- }
-
- while(yyparse());
- }
- //go.sysin dd *
- if [ `wc -c < main.c` != 197 ]; then
- made=FALSE
- echo error transmitting main.c --
- echo length should be 197, not `wc -c < main.c`
- else
- made=TRUE
- fi
- if [ $made = TRUE ]; then
- chmod 644 main.c
- echo -n ; ls -ld main.c
- fi
- echo Extracting make_keyword.c
- if [ -w make_keyword.c ]; then
- echo File already exists - saving as make_keyword.c.old
- mv make_keyword.c make_keyword.c.old
- chmod 444 make_keyword.c.old
- fi
- sed 's/^X//' <<'//go.sysin dd *' >make_keyword.c
- X/*
- * Syntax: av[0] inc_file
- *
- * This programme uses the file inc_file to construct a second stage lex
- * analyser called keyword() in file keyword.c.
- */
- #include <stdio.h>
- #include <ctype.h>
- #define NTOKEN 200 /* maximum number of tokens */
- #define OUTFILE "keyword.c" /* name of output file */
- #define POUT fprintf(outfil /* save space */
- #define SIZE 40 /* maximum size of token */
-
- static char token[NTOKEN][SIZE];
-
- main(ac,av)
- int ac;
- char *av[];
- {
- char c;
- FILE *infil, /* file descriptor for *.h */
- *outfil;
- int i,
- num_token; /* number of tokens */
- extern int *strcmp();
-
- if(ac < 2) {
- fprintf(stderr,"Syntax: make_keyword inc_file\n");
- exit(-2);
- }
- if((infil = fopen(av[1],"r")) == NULL) {
- fprintf(stderr,"Can't open %s\n",av[1]);
- exit(-2);
- }
-
- if((outfil = fopen(OUTFILE,"w")) == NULL) {
- fprintf(stderr,"Can't open %s\n",OUTFILE);
- fclose(infil);
- exit(-2);
- }
- X/*
- * Read in the tokens from av[1].
- * Use the val_tok field to give their value in each file
- */
- for(i = 0;i < NTOKEN;i++) {
- if(fscanf(infil,"%*s %*s %s %*d",token[i]) != 1) {
- break;
- }
- }
- fclose(infil);
- num_token = i;
-
- qsort(token,num_token,SIZE,strcmp); /* sort tokens */
-
- POUT,"/*\n");
- POUT," */\n");
- POUT,"#include <stdio.h>\n");
- POUT,"#include \"%s\"\n",av[1]);
- POUT,"\n");
- POUT,"extern int strcmp();\n");
- POUT,"\n");
- POUT,"keyword(word)\n");
- POUT,"char word[]; /* word to look for */\n");
- POUT,"{\n");
- POUT,"\n");
- POUT," switch (word[0]) {\n");
- for(i = 0,c = 'A';c <= 'Z' && i < num_token;c++) { /* assumes ascii */
- POUT," case '%c' :\n",c);
- while(token[i][0] <= c && i < num_token) {
- POUT," if(!strcmp(word,\"%s\")) {\n",token[i]);
- POUT," return(%s);\n",token[i]);
- POUT," } else\n");
- i++;
- }
- POUT," break;\n");
- }
-
- POUT," default : break;\n");
- POUT," }\n");
- POUT," return(WORD);\n");
- POUT,"\n");
- POUT,"}\n");
-
- fclose(outfil);
- #ifdef unix
- exit(0); /* success */
- #else
- exit(1); /* success in vmsese */
- #endif UniX
- }
- //go.sysin dd *
- if [ `wc -c < make_keyword.c` != 2164 ]; then
- made=FALSE
- echo error transmitting make_keyword.c --
- echo length should be 2164, not `wc -c < make_keyword.c`
- else
- made=TRUE
- fi
- if [ $made = TRUE ]; then
- chmod 755 make_keyword.c
- echo -n ; ls -ld make_keyword.c
- fi
- echo Extracting parser.y
- if [ -w parser.y ]; then
- echo File already exists - saving as parser.y.old
- mv parser.y parser.y.old
- chmod 444 parser.y.old
- fi
- sed 's/^X//' <<'//go.sysin dd *' >parser.y
- %{
- #include <stdio.h>
- #include "yaccun.h"
- #include "jcl.h"
- X/*
- * declare variables in jcl.h
- */
- char parm[PSIZE]; /* parameters on EXEC card */
- FILE *msgout=stderr; /* destination for output */
- int disp[3], /* 3 DISP parameters */
- msglevel1 = 1,msglevel2 = 1; /* MSGLEVEL=(msglevel1,msglevel2) */
-
- static char msg[50], /* used for composing error messages */
- step_name[40]; /* name of current step */
- extern char token[]; /* text of last token read */
- int pgm; /* true if current step is a PGM */
- extern int verbose;
- %}
-
- %start deck /* the complete deck of cards */
-
- %token <charval>
- EXEC WORD
-
- %token /* special characters */
- '\n' ',' '.' '/' '\'' '(' ')' '*' '&' '+' '-' '=' ' '
- %token /* control words */
- DD DSLASH ENDMARK JOB NULL_CARD SLASHSTAR
- %token /* keywords */
- COND /* Misc. */
- MSGCLASS MSGLEVEL /* JOB */
- PGM PROC PARM /* EXEC */
- DATA DCB DISP DSN DUMMY UNIT /* DD */
-
- %type <charval>
- apost_word /* string enclosed in ' ' */
- dd_file /* name of file for DD statement */
- dot_name /* name including '.'s */
- exec_card /* PGM/PROC run by exec step */
- opt_dot_name /* optional dot_name */
- opt_word /* optional word */
- pgm_or_proc /* name of PGM/PROC */
-
- %type <intval>
- disp_par /* DISP parameter */
- opt_disp /* optional disp_par */
- %% /* start of rules */
-
- deck : job_card steps null_card
- {
- job_clean_dd(); /* delete unwanted datasets */
- return(0);
- }
- ;
-
- steps : /* a collection of job steps */
- | steps step
- ;
-
- step : exec_card opt_dd_cards
- {
- char command[200],
- *define_dd();
-
- if(pgm) {
- sprintf(command,"%s%s %s",define_dd(step_name),$1,parm);
- if(verbose) printf("%s\n",command);
- system(command);
- } else {
- printf("Step %s runs proc %s\n",step_name,$1);
- printf("Parameters: %s\n",parm);
- }
- step_clean_dd(step_name);
- }
- | error '\n'
- {
- yyerrok;
- yyclearin;
- }
- ;
-
- opt_dd_cards :
- | opt_dd_cards dd_card
- ;
-
- dd_card : DSLASH opt_dot_name ' ' DD ' ' dd_file '\n'
- { create_dd($2,$6,step_name,disp); }
- ;
-
- dd_file : '*'
- {
- char line[81],
- *mktemp(),
- *tempname;
- FILE *fil;
-
- if((tempname = mktemp("DATXXXXXX")) == NULL) {
- yyerror("Can't create temporary file name");
- break;
- }
- if((fil = fopen(tempname,"w")) == NULL) {
- sprintf(msg,"Can't open %s",tempname);
- break;
- }
- strcpy($$,tempname);
-
- while(fgets(line,81,stdin) != NULL) {
- if(!strncmp("/*\n",line,3) || !strncmp("/* ",line,3)) {
- break;
- }
- fputs(line,fil);
- }
- fclose(fil);
-
- disp[0] = NEW;
- disp[1] = DELETE;
- disp[2] = DELETE;
- }
- | DUMMY dd_opts
- { strcpy($$,"/dev/null"); }
- | DSN '=' dot_name dd_opts
- { strcpy($$,$3); }
- ;
-
- dd_opts :
- {
- disp[0] = UNKNOWN;
- disp[1] = UNKNOWN;
- disp[2] = UNKNOWN;
- }
- | dd_opts ',' DCB '=' WORD
- | dd_opts ',' DISP '=' disp_par
- {
- disp[0] = $5;
- disp[1] = UNKNOWN;
- disp[2] = UNKNOWN;
- }
- | dd_opts ',' DISP '=' '(' opt_disp ',' opt_disp ')'
- {
- disp[0] = $6;
- disp[1] = $8;
- disp[2] = UNKNOWN;
- }
- | dd_opts ',' DISP '=' '(' opt_disp ',' opt_disp ',' opt_disp ')'
- {
- disp[0] = $6;
- disp[1] = $8;
- disp[2] = $10;
- }
- ;
-
- disp_par : WORD
- {
- if(!strcmp($1,"DELETE")) $$ = DELETE;
- else if(!strcmp($1,"KEEP")) $$ = KEEP;
- else if(!strcmp($1,"NEW")) $$ = NEW;
- else if(!strcmp($1,"OLD")) $$ = OLD;
- else {
- sprintf(msg,"Unknown DISP parameter %s",$1);
- $$ = UNKNOWN;
- }
- }
- ;
-
- opt_disp :
- { $$ = UNKNOWN; }
- | disp_par
- { $$ = $1; }
- ;
-
- exec_card : EXEC ' ' pgm_or_proc exec_opts '\n'
- {
- strcpy($$,$3);
- strcpy(step_name,$1);
- }
- ;
-
- exec_opts :
- | exec_opts ',' COND '=' '(' WORD ',' WORD ',' WORD ')'
- | exec_opts ',' PARM '=' apost_word
- { strcpy(parm,$5); }
- | exec_opts ',' PARM '=' WORD
- { strcpy(parm,$5); }
- ;
-
- apost_word : '\'' /* [^']' */
- {
- int i;
-
- for(i = 0;i < CHARMAX
- && ($$[i] = get_cchar()) != '\'' && $$[i] != '\n';i++) ;
- if($$[i] != '\'') put_cchar($$[i]);
- $$[i] = '\0';
- }
- ;
-
- pgm_or_proc : PGM '=' WORD
- {
- pgm = 1; /* it's a programme */
- strcpy($$,$3);
- }
- | PGM '=' apost_word
- {
- pgm = 1; /* it's a programme */
- strcpy($$,$3);
- }
- | PROC '=' WORD
- {
- pgm = 0; /* it's a procedure */
- strcpy($$,$3);
- }
- ;
-
- job_card : DSLASH opt_word ' ' JOB ' ' dot_name job_opts '\n'
- ;
-
- job_opts :
- | job_opts ',' MSGCLASS '=' WORD
- {
- if($5[0] == 'A') {
- if(msgout != stderr) fclose(msgout);
- msgout = stderr;
- } else if($5[0] == 'B') {
- if(msgout != stderr) fclose(msgout);
- if((msgout = fopen("JCL.out","w")) == NULL) {
- yyerror("Can't open JCL.out");
- msgout = stderr;
- }
- } else {
- sprintf(msg,"Unknown MSGCLASS %s",$5);
- yyerror(msg);
- }
- }
- | job_opts ',' MSGLEVEL '=' '(' WORD ',' WORD ')'
- {
- msglevel1 = atoi($6);
- msglevel2 = atoi($8);
- }
- ;
-
- dot_name : WORD
- { strcpy($$,$1); }
- | dot_name '.' WORD
- { sprintf($$,"%s.%s",$1,$3); }
- ;
-
- null_card : NULL_CARD
- | ENDMARK
- ;
-
- opt_word : WORD
- { sprintf($$,$1); }
- |
- { sprintf($$,""); }
- ;
-
- opt_dot_name : dot_name
- { sprintf($$,$1); }
- |
- { sprintf($$,""); }
- ;
-
- opt_lparen :
- | '('
- ;
-
- opt_rparen :
- | ')'
- ;
- %%
- yyerror(s)
- char *s;
- {
- if(!strcmp(s,"syntax error")) {
- fprintf(stderr,"Syntax error, last token read %s\n",token);
- } else {
- fprintf(stderr," %s\n",s);
- }
- }
- //go.sysin dd *
- if [ `wc -c < parser.y` != 5908 ]; then
- made=FALSE
- echo error transmitting parser.y --
- echo length should be 5908, not `wc -c < parser.y`
- else
- made=TRUE
- fi
- if [ $made = TRUE ]; then
- chmod 644 parser.y
- echo -n ; ls -ld parser.y
- fi
- echo Extracting yaccun.h
- if [ -w yaccun.h ]; then
- echo File already exists - saving as yaccun.h.old
- mv yaccun.h yaccun.h.old
- chmod 444 yaccun.h.old
- fi
- sed 's/^X//' <<'//go.sysin dd *' >yaccun.h
- X/*
- * these are the typedefs for the yacc union
- */
- #define CHARMAX 80 /* maximum size of word */
-
- typedef union { /* union for yacc variable stack */
- char charval[CHARMAX];
- int intval;
- } YYSTYPE;
-
- extern YYSTYPE yyval,yylval;
- //go.sysin dd *
- if [ `wc -c < yaccun.h` != 239 ]; then
- made=FALSE
- echo error transmitting yaccun.h --
- echo length should be 239, not `wc -c < yaccun.h`
- else
- made=TRUE
- fi
- if [ $made = TRUE ]; then
- chmod 755 yaccun.h
- echo -n ; ls -ld yaccun.h
- fi
- echo Extracting yylex.c
- if [ -w yylex.c ]; then
- echo File already exists - saving as yylex.c.old
- mv yylex.c yylex.c.old
- chmod 444 yylex.c.old
- fi
- sed 's/^X//' <<'//go.sysin dd *' >yylex.c
- #include <stdio.h>
- #include "yaccun.h"
- #include "keyword.h"
- #include "jcl.h"
-
- #define FORMAT "%[ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#$]"
- /* format for reading fields */
- #define YYCHARVAL (yylval.charval) /* an abbreviation */
- char token[CHARMAX]; /* text of last token read */
- static char card[83], /* current card */
- *cptr;
- extern int verbose; /* get debugging output */
- static int need_card = 1; /* Do I need to read a new card? */
-
- int
- yylex()
- {
- static char word[50]; /* error message */
- int ret;
-
- if(need_card) { /* so read one */
- if(fgets(&card[1],81,stdin) == NULL) {
- return(ENDMARK);
- }
- need_card = 0;
- if(msglevel1 > 0) {
- fputs(&card[1],msgout);
- }
- if(strlen(&card[1]) > 72) {
- card[0] = card[72]; /* save continuation character */
- } else {
- card[0] = ' '; /* no continuation character */
- }
- card[72] = '\0'; /* delete end of card */
- cptr = &card[72];
- while(*--cptr == ' ') ; /* find trailing blanks */
- *(cptr + 1) = '\0'; /* strip them */
- cptr = &card[1]; /* now find comments */
- while(*cptr++ != ' ') ; /* skip //name field */
- while(*cptr++ == ' ') ; /* and first blank field */
- while(*cptr++ != ' ') ; /* and JOB/DD/EXEC/etc field */
- while(*cptr++ == ' ') ; /* and second blank field */
- while(*cptr++ != ' ') ; /* and options field */
- *--cptr = '\0'; /* cut the comment off the card */
- cptr = card + strlen(card); /* 1 past last character */
- if(*(cptr - 1) != '\n') { /* check if card ends in \n */
- *cptr++ = '\n';
- *cptr = '\0';
- }
- cptr = &card[1];
- }
-
- if(*cptr == '\0') {
- need_card = 1;
- return(yylex());
- }
-
- if(cptr == &card[1]) {
- if(!strncmp(cptr,"//*",3)) { /* comment */
- need_card = 1;
- return(yylex());
- } else if(!strncmp(cptr,"//",2)) { /* May be EXEC */
- cptr += 2; /* skip // */
- if(sscanf(cptr,FORMAT,word) == 1) { /* read NAME field */
- cptr += strlen(word);
- } else if(*cptr == '\n') { /* null card */
- sprintf(token,"//\\n");
- return(NULL_CARD);
- } else {
- word[0] = '\0';
- }
- if(yylex() == ' ') { /* EXEC or null? */
- if((ret = yylex()) == EXEC) { /* yes, an EXEC card */
- strcpy(YYCHARVAL,word);
- sprintf(token,"//%s EXEC",word);
- return(ret);
- } else if(ret == '\n') { /* null card */
- sprintf(token,"//\\n");
- return(NULL_CARD);
- }
- }
- cptr = &card[3]; /* no, rewind and return // */
- sprintf(token,"//");
- ret = DSLASH;
- } else if(!strncmp(cptr,"/*",2)) {
- sprintf(token,"/*");
- cptr += 2;
- ret = SLASHSTAR;
- } else {
- sprintf(word,"Card begins %c%c",*cptr,*(cptr+1));
- yyerror(word);
- sprintf(YYCHARVAL,"%c%c",*cptr++,*cptr++);
- strcpy(token,YYCHARVAL);
- ret = WORD;
- }
- } else {
- if(sscanf(cptr,FORMAT,YYCHARVAL) == 1) {
- strcpy(token,YYCHARVAL);
- cptr += strlen(YYCHARVAL);
- ret = keyword(YYCHARVAL);
- } else {
- switch (*cptr) {
- case ',': case '.': case '/': case '\'': case '(': case ')':
- case '*': case '&': case '+': case '-': case '=':
- sprintf(token,"%c",*cptr);
- ret = *cptr++;
- break;
- case ' ':
- while(*cptr == ' ') {
- cptr++;
- }
- sprintf(token,"' '");
- ret = ' ';
- break;
- case '\n':
- if(card[0] != ' ' || *(cptr - 1) == ',') { /* Continuation */
- need_card = 1; /* skip newline */
- if(yylex() != DSLASH || /* card starts // */
- yylex() != ' ') { /* then spaces */
- sprintf(word,"Expected continuation card");
- yyerror(word);
- }
- return(yylex()); /* return next */
- } else {
- sprintf(token,"\\n");
- cptr++;
- ret = '\n';
- }
- break;
- default:
- sscanf(cptr,"%[^,./'()*&+-= ]",YYCHARVAL);
- if(YYCHARVAL[strlen(YYCHARVAL) - 1] == '\n') {
- YYCHARVAL[strlen(YYCHARVAL) - 1] = '\0';
- }
- strcpy(token,YYCHARVAL);
- cptr += strlen(YYCHARVAL);
- sprintf(word,"Illegal character in string \"%s\"",YYCHARVAL);
- yyerror(word);
- ret = WORD;
- break;
- }
- }
- }
- if(verbose) {
- fprintf(msgout,"TOKEN %s\n",token);
- }
- return(ret);
- }
-
- get_cchar() /* get next character off a card */
- {
- if(*cptr == '\n') { /* at end of card */
- return('\n');
- } else {
- return(*cptr++);
- }
- }
-
- put_cchar(c)
- int c;
- {
- if(cptr > &card[0]) {
- *--cptr = c;
- }
- }
- //go.sysin dd *
- if [ `wc -c < yylex.c` != 4445 ]; then
- made=FALSE
- echo error transmitting yylex.c --
- echo length should be 4445, not `wc -c < yylex.c`
- else
- made=TRUE
- fi
- if [ $made = TRUE ]; then
- chmod 644 yylex.c
- echo -n ; ls -ld yylex.c
- fi
-
-
-