C:/Users/Dennis/src/lang/russell.orig/src/delab/delab.c

Go to the documentation of this file.
00001 /*
00002  * this program is supposed to scan a RIC file and change uses
00003  * of the UNIX assembler's local labels (i.e. the 1f and 2b things)
00004  * to globally unique labels.
00005  *
00006  * Note: all labels generated herein are of the form "L_XnnX_" where nn
00007  * is a number.
00008  *
00009  * The way it works:
00010  *      case plain ol' instruction:
00011  *          if no unresolved forward refs then
00012  *              output instr
00013  *          else
00014  *              save instr
00015  *      case "n:"
00016  *          replace current definition of n with next global name;
00017  *          for each forward reference to "n" do
00018  *              change the reference to n's global name;
00019  *              remove reference from list;
00020  *          if no more forward refs then
00021  *              output saved instr list;
00022  *      case forward reference to "n":
00023  *          put the reference on list of references to "n";
00024  *      case backward reference to "n":
00025  *          replace the reference with n's global name;
00026  *
00027  * While this is a nice little algorithm, the implementation is
00028  * greatly complicated by the way LBA is defined.  
00029  */
00030 
00031 # include <stdio.h>
00032 # include <strings.h>
00033 # include "codegen.h"
00034 # include "op_codes.h"
00035 
00036 # define TRUE 1
00037 # define FALSE 0
00038 # define MAX_TEMP_LAB 20        /* max index used for temp labels */
00039 
00040 int last_type;                  /* type of last numerical label seen */
00041 # define REF 0                  /*      reference to a numerical label */
00042 # define DEF 1                  /*      definition of a numerical label */
00043 
00044 int last_num;                   /* number of last numerical label */
00045 
00046 int last_dir;                   /* last numerical reference direction */
00047 # define FWD 0                  /*      fwd ref */
00048 # define BCK 1                  /*      back ref */
00049 
00050 /*
00051  * used to save lists of instructions which can't be output yet
00052  * because of unresolved forward references.
00053  */
00054 struct instr {
00055     int opc, arg[3];            /* opcode and args */
00056     char *label;                /* label pointer */
00057     struct instr *next;         /* next instruction */
00058 };
00059 
00060 struct instr *instr_list = (struct instr *) 0;
00061                                 /* list of saved instructions */
00062 struct instr *tail_il = (struct instr *) 0;
00063                                 /* last elt of instr_list */
00064 
00065 /*
00066  * lists of unresolved forward references for each index number
00067  */
00068 struct fwd_ref {
00069     struct instr *inst;
00070     struct fwd_ref *next;
00071 };
00072 
00073 struct fwd_ref *fwd_refs[MAX_TEMP_LAB+1] =
00074         { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
00075 
00076 
00077 extern char *op_code_table[];   /* names of RIC opcodes */
00078 
00079 char label_buf[MAXLABELSZ+1];   /* temp buffer to store labels in */
00080 char save_label[MAXLABELSZ+1];  /* buffer to save labels in for future use */
00081 
00082 char * crud[20];                /* used to calculate next globally unique lbl*/
00083 
00084 /* global label names for each local label index number */
00085 char * cur_name[MAX_TEMP_LAB+1] = 
00086         { "..............", "..............", "..............",
00087           "..............", "..............", "..............",
00088           "..............", "..............", "..............",
00089           "..............", "..............", "..............",
00090           "..............", "..............", "..............",
00091           "..............", "..............", "..............",
00092           "..............", ".............." };
00093 
00094 int num_fwd_refs = 0;           /* total number of unresolved fwd refs */
00095 int lbl_num = 0;                /* used to generate labels */
00096 int read_ahead = FALSE;         /* => already read next opcode */
00097 int saved_opc;                  /* opcode which was read */
00098 
00099 FILE *in_file, *out_file;       /* input file, output file */
00100 
00101 /*#define DEBUG         generate voluminous output */
00102 
00103 #ifdef DEBUG
00104 #   define dbg_msg(s)           printf(s);              fflush(stdout)
00105 #   define dbg_msg2(s,x)        printf(s,x);            fflush(stdout)
00106 #   define dbg_msg3(s,x,y)      printf(s,x,y);          fflush(stdout)
00107 #   define dbg_msg4(s,x,y,z)    printf(s,x,y,z);        fflush(stdout)
00108 #else
00109 #   define dbg_msg(x)
00110 #   define dbg_msg2(s,x)
00111 #   define dbg_msg3(s,x,y)
00112 #   define dbg_msg4(s,x,y,z)
00113 #endif
00114 
00115 
00116 
00117 
00118 main(argc, argv)
00119 int argc;
00120 char ** argv;
00121 {
00122     int opc,                    /* current opcode */
00123         arg[3];                 /* args */
00124     char * op_mnem;             /* mnemonic for current opcode */
00125     struct instr *newone;       /* used to allocate new instr structs */
00126     struct fwd_ref *cur_ref;    /* used to resolve fwd refs */
00127 
00128     int last_was_def= FALSE,    /* => last instr defined a local label */
00129         last_was_lba= FALSE;    /* => last instr was LBA */
00130     int input_index = 1,
00131         i;
00132     char *temp;                 /* used to free heap space */
00133 
00134   /* process command-line arguments */
00135     if (argc == 1) {
00136         in_file = stdin;
00137         out_file = stdout;
00138     } else if (argc <= 3) {
00139         if (argv[1][0] == '-') {
00140             int res = 0;
00141 
00142             for (i = 1; i < strlen(argv[1])-1; i++) {
00143                 if (argv[1][i] < '0' || argv[1][i] > '9') {
00144                     fprintf(stderr,"invalid label num argument\n");
00145                     usage(argv[0]);
00146                 } else {
00147                     res = (10 * res) + (argv[1][i] - '0');
00148                 }
00149             }
00150             lbl_num = res;
00151         }
00152         in_file = fopen(argv[1], "r");
00153         out_file =
00154             (argc == 2) ? stdout : fopen(argv[2], "w");
00155 
00156         if (in_file == NULL || out_file == NULL) {
00157             fprintf(stderr, "Can't open %s\n", argv[1]);
00158             usage(argv[0]);
00159         }
00160     } else {
00161         fprintf(stderr, "Usage: %s [%s]\n", argv[0], argv[1]);
00162     }
00163 
00164   /* read through file and translate */
00165     while (!feof(in_file)) {
00166         int i;
00167 
00168         if (read_ahead) {
00169             opc = saved_opc;
00170             read_ahead = FALSE;
00171         } else {
00172             opc = getw(in_file);                /* get opcode */
00173         }
00174         if (feof(in_file)) {
00175             /* compensate for strange feof semantics */
00176             exit(0);
00177         }
00178 
00179       /* get name of opcode */
00180         if (opc >= 0 && opc <= N_OP_CODES) op_mnem = op_code_table[opc];
00181 
00182       /* init potential arguments */
00183         *label_buf = '\0';
00184         for (i = 0; i < 3; i++) arg[i] = 0;
00185 
00186       /* output preceding LBA, changing label if necessary */
00187         if (last_was_lba) {
00188             char *lba_lbl;
00189 
00190             if (last_was_def) {
00191                 lba_lbl = cur_name[last_num];
00192             } else {
00193                 lba_lbl = save_label;
00194             }
00195             if (num_fwd_refs == 0) {
00196                 put_lbl_op(LBA,lba_lbl);
00197                 dbg_msg2("LBA %s\n",lba_lbl);
00198             } else {
00199                 newone = (struct instr *) malloc(sizeof(struct instr));
00200                 save_it(newone,LBA,arg,lba_lbl);
00201             }
00202         }
00203 
00204       /* opcode has one operand which is a label */
00205         last_was_lba = FALSE;
00206         if (opc <= MAX_LABEL_OP) {
00207             char *p = label_buf;
00208             int c;
00209             int i = 0;
00210             
00211             while ((c = getc(in_file)) != '\0' && c != EOF) {
00212                 *p++ = c;
00213                 if (++i >= MAXLABELSZ) {
00214                     fprintf(stderr, "Label too long\n");
00215                     p = label_buf;
00216                 }
00217             }
00218             *p = '\0';
00219 
00220             if (opc == LBA) {
00221                 last_was_lba = TRUE;
00222                 dbg_msg("opc == LBA\n");
00223                 dbg_msg2("label_buf = %s\n",label_buf);
00224                 strcpy(save_label,label_buf);
00225             }
00226 
00227             if (normal_label(opc,label_buf)) {
00228                 if (opc != LBA) {
00229                     if (num_fwd_refs == 0) {
00230                         put_lbl_op(opc,label_buf);
00231                         dbg_msg3("%s %s\t(normal)\n",op_mnem,label_buf);
00232                     } else {
00233                         newone = (struct instr *) malloc(sizeof(struct instr));
00234                         save_it(newone,opc,arg,label_buf);
00235                     }
00236                 } else {
00237                     last_was_def = FALSE;
00238                 }
00239             } else {
00240                 if (last_type == DEF) {
00241                     last_was_def = (opc == LBA);
00242 
00243                     dbg_msg3("assigned L_X%dX_ to %d\n",lbl_num,last_num);
00244                     sprintf(crud,"L_X%dX_",lbl_num++);
00245                     strcpy(cur_name[last_num],crud);
00246                     cur_ref = fwd_refs[last_num];
00247 
00248                   /* output labelling op unless == LBA */
00249                     if (opc != LBA) {
00250                         if (num_fwd_refs == 0) {
00251                             put_lbl_op(opc,cur_name[last_num]);
00252                         } else {
00253                             newone = 
00254                                 (struct instr *) malloc(sizeof(struct instr));
00255                             save_it(newone,opc,arg,cur_name[last_num]);
00256                         }
00257                     }
00258                     dbg_msg3("resolving fwd refs %d to %s\n",
00259                                         last_num,cur_name[last_num]);
00260 
00261                   /* resolve earlier references to this (now known) label */
00262                     while (cur_ref != (struct fwd_ref *) NULL) {
00263                         strcpy( (cur_ref->inst)->label, cur_name[last_num]);
00264                         temp = (char *) cur_ref;
00265                         cur_ref = cur_ref->next;
00266                         free(temp);
00267                         num_fwd_refs--;
00268                     }
00269                     fwd_refs[last_num] = (struct fwd_ref *) NULL;
00270 
00271                     if (num_fwd_refs == 0) {
00272                         struct instr *cur = instr_list;
00273                         while (cur != (struct instr *) NULL) {
00274                             if (cur->opc < MAX_LABEL_OP) {
00275                                 put_lbl_op(cur->opc,cur->label);
00276                                 dbg_msg3("%s %s\t(saved)\n",
00277                                         op_code_table[cur->opc],cur->label);
00278                             } else if (cur->opc < N_OP_CODES) {
00279                                 put_reg_op(cur->opc,cur->arg);
00280                                 dbg_msg2("%s ",op_code_table[cur->opc]);
00281                                 dbg_msg4("%d %d %d\t(saved)\n",
00282                                         cur->arg[0],cur->arg[1],cur->arg[2]);
00283                             } else {
00284                                 fprintf(stderr,
00285                                         "Bad op code in instr_list = %d\n",
00286                                         cur->opc);
00287                             }
00288                             instr_list = tail_il = (struct instr *) NULL;
00289                             temp = (char *) cur;
00290                             cur = cur->next;
00291                             free(temp);
00292                         }
00293                     } else {
00294                         dbg_msg2("now num_fwd_refs = %d\n",num_fwd_refs);
00295                     }
00296                 } else if (opc != LBA) {
00297                     if (last_dir == FWD) {
00298                         newone =
00299                             (struct instr *) malloc(sizeof(struct instr));
00300                         i = (int) malloc(sizeof(struct fwd_ref));
00301                         cur_ref = (struct fwd_ref *) i;
00302 
00303                         cur_ref->inst = newone;
00304                         cur_ref->next = fwd_refs[last_num];
00305                         fwd_refs[last_num] = cur_ref;
00306                         save_it(newone,opc,arg,label_buf);
00307                         num_fwd_refs++;
00308                     } else {
00309                         dbg_msg3("resolved back ref to %d = %s\n",last_num,
00310                                                 cur_name[last_num]);
00311                         strcpy(label_buf, cur_name[last_num]);
00312                         if (num_fwd_refs == 0) {
00313                             put_lbl_op(opc,label_buf);
00314                             dbg_msg3("%s %s\t(back ref)\n",op_mnem,label_buf);
00315                         } else {
00316                             newone =
00317                                 (struct instr *) malloc(sizeof(struct instr));
00318                             save_it(newone,opc,arg,label_buf);
00319                         }
00320                     }
00321                 }
00322             } /* end if (normal...) */
00323 
00324       /* opcode has registers as arguments */
00325         } else {
00326             for ( i = 0; i < 3; i++ ) {
00327                 arg[i] = getw(in_file);
00328             }
00329             if (num_fwd_refs == 0) {
00330                 put_reg_op(opc,arg);
00331                 dbg_msg2("%s ",op_mnem);
00332                 dbg_msg4("%d %d %d\t(plain)\n",arg[0],arg[1],arg[2]);
00333             } else {
00334                 newone = (struct instr *) malloc(sizeof(struct instr));
00335                 save_it(newone,opc,arg,label_buf);
00336             }
00337         }
00338 
00339     }
00340 }
00341 
00342 
00343 /* save instruction in instr_list */
00344 
00345 save_it(newone,opc,arg,label_buf)
00346     struct instr *newone;
00347     int opc,arg[3];
00348     char *label_buf;
00349 {
00350     struct instr *temp;
00351 
00352   /* save instruction at head of instr_list */
00353     if (newone == (struct instr *) NULL) {
00354         fprintf(stderr,"Internal: (nil) newone passed to save_it\n");
00355         fflush(stderr);
00356         exit(1);
00357     } else {
00358         newone->next = (struct instr *) NULL;
00359         newone->opc = opc;
00360         newone->arg[0] = arg[0];
00361         newone->arg[1] = arg[1];
00362         newone->arg[2] = arg[2];
00363         newone->label = (char *) malloc(MAXLABELSZ+1);  /*will change if fwd*/
00364         strcpy(newone->label,label_buf);
00365 
00366         if (tail_il != (struct instr *) NULL) tail_il->next = newone;
00367         tail_il = newone;
00368         if (instr_list == (struct instr *) NULL) instr_list = tail_il;
00369     }
00370 
00371     dbg_msg("il = ");
00372     for(temp = instr_list; temp != NULL; temp = temp->next) {
00373         dbg_msg2("(%s",op_code_table[temp->opc]);
00374         dbg_msg4(" %d %d %d ",temp->arg[0],temp->arg[1],temp->arg[2]);
00375         dbg_msg2("%s), ",temp->label);
00376     }
00377     dbg_msg("\n");
00378 }
00379 
00380 /*
00381  * return next opcode in input
00382  * used for lookahead by normal_label
00383  */
00384 int next_opc() {
00385     if (read_ahead) {
00386         fprintf(stderr,"tried to read ahead when read_ahead already set!\n");
00387         exit(1);
00388     }
00389     read_ahead = TRUE;
00390     saved_opc = getw(in_file);
00391     return(saved_opc);
00392 }
00393 
00394 /*
00395  * return TRUE if label is not a "local reference" label (i.e. we should
00396  * leave it alone).
00397  */
00398 int normal_label(opc,p)
00399     int opc;
00400     char *p;
00401 {
00402     char *s;
00403 
00404   /* if this is an LBA for an LDS, then it's data, not a label */
00405     if (opc == LBA && next_opc() == LDS) return(TRUE);
00406     
00407     last_num = 0;
00408     for (s = p; *s != '\0'; s++) {
00409         if (*s >= '0' && *s <= '9') {
00410             last_num = 10 * last_num + *s - '0';
00411         } else if (s != p && (*s == 'f' || *s == 'b') && (*(s+1) == '\0')) {
00412             last_type = REF;
00413             last_dir = (*s == 'f') ? FWD : BCK;
00414             dbg_msg3("found a %s ref to %d\n",
00415                         (last_dir==FWD)?"fwd":"back",last_num);
00416             return(FALSE);
00417         } else {
00418             return(TRUE);       /* any non-numerical char => normal label */
00419         }
00420     }
00421     if (opc == LBA || opc == LBL) {
00422         last_type = DEF;
00423         dbg_msg2("found a def of %d\n",last_num);
00424         dbg_msg3("%s %s\n",op_code_table[opc],p);
00425         return(FALSE);
00426     } else {
00427         return(TRUE);
00428     }
00429 }
00430 
00431 /*
00432  * put a RIC statement with registers args
00433  */
00434 put_reg_op(opc,arg)
00435     int opc, arg[];
00436 {
00437     putw(opc,out_file);
00438     putw(arg[0],out_file);
00439     putw(arg[1],out_file);
00440     putw(arg[2],out_file);
00441 }
00442 
00443 /*
00444  * put a RIC statement with label arg
00445  *
00446  * because the RT adb chokes on "_.", I substitute "__" for it everywhere
00447  */
00448 put_lbl_op(opc,label)
00449     int opc;
00450     char *label;
00451 {
00452     char *fixit();
00453 
00454     putw(opc,out_file);
00455     fputs(fixit(label),out_file);
00456     putc('\0',out_file);
00457 }
00458 
00459 
00460 /* replace "_." by "__" everywhere in str */
00461 char *fixit(str)
00462 char *str;
00463 {
00464     char *p;
00465     char *q = (char *) malloc(strlen(str)+1);
00466     int state = 0, offset=0;
00467 
00468     for (p = str; *p != '\0'; p++, offset++) {
00469         if (state == 0) {
00470             if (*p == '_') state = 1;
00471             *(q+offset) = *p;
00472         } else {
00473             if (*p == '.') {
00474                 *(q+offset) = '_';
00475             } else
00476                 *(q+offset) = *p;
00477             if (*p != '_') state = 0;
00478         }
00479     }
00480     *(q+offset) = '\0';
00481 /*    fprintf(stderr,"changed %s to %s\n",str,q);*/
00482     return(q);
00483 }
00484 
00485 
00486 usage(name)
00487 char *name;
00488 {
00489     fprintf(stderr,"usage: %s [-nnn] infile [outfile]\n",name);
00490     exit(1);
00491 }

Generated on Fri Jan 25 10:39:45 2008 for russell by  doxygen 1.5.4