allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (02/04/89)
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