home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / hensa / programming / motasm / motasmdoc / src / c / as next >
Encoding:
Text File  |  1995-09-10  |  22.9 KB  |  602 lines

  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include <stdio.h>
  4.  
  5. /* #include <kernel.h> */
  6.  
  7. #include "mselect.h"            /* external selection of microprocessor
  8.                                  * symbol table */
  9. #include "proto.h"
  10. #include "as.h"
  11. #include "structs.h"
  12. #include "glovars.h"
  13.  
  14. void            stable(struct nlist * ptr);
  15. void            cross(struct nlist * point);
  16.  
  17. /*
  18.  * as --- cross assembler main program
  19.  *
  20.  * Note: Compile with define DEBUG for function module debug statements. Compile
  21.  * with define DEBUG2 for version 2 debug statements only.  Compile with
  22.  * define IBM to use original, non- Amiga, non-MAC, non-UNIX fgets()
  23.  * function.  Amiga version will accept IBM generated source code but not the
  24.  * other way around. Note added version (TER) 2.01 19 June 1989.
  25.  */
  26.  
  27. int
  28. main(int argc, char **argv)
  29. {
  30.         char          **np,**npthrow;
  31.         char           *i;
  32.         int             j = 0, l = 0;
  33.  
  34.         fprintf(stderr, "Freeware 8 bit Microcontroller Assembler -  (c) Motorola\n");
  35.         fprintf(stderr, "Archimedes porting by Maurizio Ferrari   -  version 3.04");
  36. #if     (defined MC68HC11)
  37.         fprintf (stderr, " - MC68HC11\n\n");
  38. #else
  39. #if   (defined MC68HC05)
  40.         fprintf (stderr, " - MC68HC05\n\n");
  41. #else
  42. #if   (defined MC6809)
  43.         fprintf (stderr, " - MC6809\n\n");
  44. #else
  45.         #error undefined target processor, please define MICRO
  46. #endif /*68hc11*/
  47. #endif /*68HC05*/
  48. #endif /*6809*/
  49.  
  50.         if (argc < 2) {
  51.                 fprintf(stderr, "Usage:   %s [files] [-options]\n", argv[j]);
  52.                 fprintf(stderr, "Example: %s FILE1.ASM FILE2.ASM -o <Obj_name> -cpp <cpp_options> -noasm -x|cre -list|l <List_name> -cyc -p 50 -crlf -split -end\n", argv[j]);
  53.                 exit(1);
  54.         }
  55.         Argv = argv;
  56.         while ((*argv[j] != '-') && (j < argc)) {
  57. #ifdef DEBUG
  58.                 printf("%s\n", argv[j]);
  59. #endif
  60.                 j++;
  61.         }
  62.         N_files = j - 1;
  63.         /*
  64.          * cppnp = (char **) malloc(sizeof(char *)*(N_files)); if (cppnp ==
  65.          * NULL) fatal("Cannot allocate space for cpp file name");
  66.          */
  67.         Lflag = 0;
  68.         Cflag = 0;
  69.         Sflag = 0;
  70.         Pflag = 0;
  71.         CREflag = 0;
  72.         Splitflag = 0;
  73.         if (j < argc) {
  74.                 while (j < argc) {
  75.                         for (i = argv[j]; *i != 0; i++)
  76.                                 if ((*i <= 'Z') && (*i >= 'A'))
  77.                                         *i = *i + 32;
  78.                         if (strcmp(argv[j], "-list") == 0) {
  79.                                 Lflag = 1;
  80.                         } else if (strcmp(argv[j], "-l") == 0) {
  81.                                 Lflag = 1;
  82.                         } else if (strcmp(argv[j], "-cyc") == 0) {
  83.                                 Cflag = 1;
  84.                         } else if (strcmp(argv[j], "-sym") == 0) {
  85.                                 Sflag = 1;
  86.                         } else if (strcmp(argv[j], "-s") == 0) {
  87.                                 Sflag = 1;
  88.                         } else if (strcmp(argv[j], "-noasm") == 0) {
  89.                                 NoAflag = 1;
  90.                         } else if (strcmp(argv[j], "-split") == 0) {
  91.                                 Splitflag = 1;
  92.                         } else if (strcmp(argv[j], "-cpp") == 0) {
  93.                                 Pflag = 1;
  94.                         } else if (strcmp(argv[j], "-x") == 0) {
  95.                                 CREflag = 1;
  96.                         } else if (strcmp(argv[j], "-cre") == 0) {
  97.                                 CREflag = 1;
  98.                         } else if (strcmp(argv[j], "-end") == 0) {
  99.                                 ENDflag = 1;
  100.                         } else if (strcmp(argv[j], "-crlf") == 0) {     /* test for crlf option */
  101.                                 CRflag = 1;
  102.                         } else if (strcmp(argv[j], "-p") == 0) {        /* page every <PageLen>
  103.                                                                          * lines */
  104.                                 Pflag50 = 1;
  105.                                 PageLen = atoi(argv[++j]);
  106.                         } else if (strcmp(argv[j], "-o") == 0) {
  107.                                 ObjFilePos = ++j;
  108.                         } else if (strcmp(argv[j], "-c") == 0) {
  109.                                 cppargpos[l++] = j;
  110.                                 cppargc++;
  111.                         } else if (strcmp(argv[j], "-e") == 0) {
  112.                                 cppargpos[l++] = j;
  113.                                 cppargc++;
  114.                         } else if (strcmp(argv[j], "-n") == 0) {
  115.                                 cppargpos[l++] = j;
  116.                                 cppargc++;
  117.                         } else if ((argv[j][0] == '-') && (argv[j][1] == 'x') && (strlen(argv[j]) > 2)) {
  118.                                 cppargpos[l++] = j;
  119.                                 cppargc++;
  120.                         } else if ((argv[j][0] == '-') && (argv[j][1] == 'i') && (strlen(argv[j]) > 2)) {
  121.                                 cppargpos[l++] = j;
  122.                                 cppargc++;
  123.                         } else if ((argv[j][0] == '-') && (argv[j][1] == 'd') && (strlen(argv[j]) > 2)) {
  124.                                 cppargpos[l++] = j;
  125.                                 cppargc++;
  126.                         } else if ((argv[j][0] == '-') && (argv[j][1] == 's') && (strlen(argv[j]) > 2)) {
  127.                                 cppargpos[l++] = j;
  128.                                 cppargc++;
  129.                         } else if ((argv[j][0] == '-') && (argv[j][1] == 'u') && (strlen(argv[j]) > 2)) {
  130.                                 cppargpos[l++] = j;
  131.                                 cppargc++;
  132.                         } else if (*argv[j]) {
  133.                                 fprintf(stderr, "\nUnrecognized option '%s' on command line\n", argv[j]);
  134.                                 fprintf(stderr, "Valid options are:");
  135.                                 fprintf(stderr, "  -list|l  -cyc  -sym  -x|cre  -cpp <cpp_options> -crlf -p <pages> -o <Obj name> -split\n\n");
  136.                                 exit(1);
  137.                         }
  138.                         j++;
  139.                 }
  140.         }
  141.         if (ObjFilePos == 0)
  142.                 fatal("\nmust specify output file");
  143.         /* errorInit(throwback,SourceFileName); */
  144.         fwdinit();              /* forward ref init */
  145.         initialize();
  146.         root = NULL;
  147.         Cfn = 0;
  148.         np = argv;
  149.         Line_num = 0;           /* reset line number */
  150.         Local_Line_num = 0;     /* reset line number */
  151.         if (Pflag != 0) {
  152.                 preprocess();
  153.                 if (NoAflag !=0 ) {
  154.                         fprintf(stderr, "preprocessing complete - exiting");
  155.                         exit(0);}
  156.                 np = cppnp;
  157.         }
  158.         else {
  159.                if (NoAflag != 0) {warn("No c preprocessing, -noasm flag with no effect");}
  160.         }
  161.         while (++Cfn <= N_files)
  162.                 if ((Fd = fopen(*++np, "r")) == NULL) {
  163.                         fprintf(stderr, "as: can't open %s\n", *np);
  164.                         fatal("\n");
  165.                 } else {
  166.                         npthrow=&argv[Cfn];
  167.                         errorInit(1, /* *npthrow */ *np);
  168.                         make_pass();
  169.                         fclose(Fd);
  170.                         errorFinish();
  171.                         Local_Line_num = 0;     /* reset line number */
  172.                 }
  173.         if (Err_count == 0) {
  174.                 Pass++;
  175.                 re_init();
  176.                 Cfn = 0;
  177.                 np = argv;
  178.                 if (Pflag != 0) {
  179.                         np = cppnp;
  180.                 }
  181.                 Line_num = 0;
  182.                 Local_Line_num = 0;
  183.                 FdCount = 0;    /* Resets INCLUDE file nesting ver TER_2.0
  184.                                  * 6/17/89 */
  185.                 while (++Cfn <= N_files)
  186.                         if ((Fd = fopen(*++np, "r")) != NULL) {
  187.                                 fprintf(stderr, "\nAssembling %s\n", *np);
  188.                 npthrow=&argv[Cfn];
  189.                                 errorInit(1, /* *npthrow */ *np);
  190.                                 make_pass();
  191.                                 fclose(Fd);
  192.                                 errorFinish();
  193.                                 if ((!end_found) && ENDflag) {warn ("END directive not found");}
  194.                                 end_found=NO;
  195.                                 Local_Line_num = 0;     /* reset Line_num for
  196.                                                          * throwback */
  197.                         }
  198.                 fprintf(stderr, "\nProgram + Init Data = %d bytes\n", F_total); /* print total bytes */
  199.                 fprintf(stderr, "Error count = %d\n\n", Err_count);     /* rel TER_2.0 */
  200.                 if (Sflag == 1) {
  201.                         fprintf(stderr, "Writing Symbols file\n");
  202.                         stable(root);
  203.                         if (Splitflag != 0) {
  204.                                 fclose(Mapfil);
  205.                         }
  206.                 }
  207.                 if (CREflag == 1) {
  208.                         fprintf(stderr, "Writing Xref file\n");
  209.                         cross(root);
  210.                         if (Splitflag != 0) {
  211.                                 fclose(Xfil);
  212.                         }
  213.                 }
  214.                 if (CRflag == 1)
  215.                         fprintf(Objfil, "S9030000FC%c\n", CR);  /* ver TER_1.1 print w
  216.                                                                  * <CR> */
  217.                 else
  218.                         fprintf(Objfil, "S9030000FC\n");        /* at least give a
  219.                                                                  * decent ending */
  220.                 fclose(Objfil); /* close file correctly ver TER_1.1 */
  221.                 fclose(Listfil);/* close file */
  222.         } else {                /* just note errors, TER_2.0 */
  223.                 fprintf(stderr, "\nProgram + Init Data = %d bytes\n", F_total); /* print total bytes */
  224.                 fprintf(stderr, "Error count = %d\n\n", Err_count);
  225.                 fclose(Listfil);/* close file */
  226.         }
  227.         fwd_done();
  228.         errorFinish();
  229.         exit(Err_count);        /* neat for UNIX cuz can test return value in
  230.                                  * script but on other systems like Amiga,
  231.                                  * mostly just makes further script
  232.                                  * statements fail if >10, else nothing.
  233.                                  * Therefore, printed out byte count and
  234.                                  * error level. ver (TER) 2.02 19 Jun 89 */
  235. }
  236.  
  237. void
  238. preprocess(void)
  239. {
  240.         char           *proot, *leafname, *cppstring;   /* !cpp command line
  241.                                                          * shell commands */
  242.         int             i = 0, j = 0, cppsize = 0, appoCfn, maxlenCfn = 0;
  243.  
  244.  
  245.         for (appoCfn = 1; appoCfn <= N_files; appoCfn++) {
  246.                 maxlenCfn = (maxlenCfn >= strlen(Argv[appoCfn])) ? maxlenCfn : strlen(Argv[appoCfn]);
  247.         }
  248.         proot = (char *) malloc(maxlenCfn + 10);
  249.         if (proot == NULL) {
  250.                 fatal("Cannot allocate space for cpp file name");
  251.         }
  252.         for (appoCfn = 1; appoCfn <= N_files; appoCfn++) {
  253.                 cppnp[appoCfn] = (char *) malloc(maxlenCfn + 10);
  254.                 if (cppnp[appoCfn] == NULL) {
  255.                         fatal("Cannot allocate space for .p file name");
  256.                 }
  257.         }
  258.         cppsize = 0;
  259.         for (j = 0; j < cppargc; j++) {
  260.                 cppsize += strlen(Argv[cppargpos[j]]);
  261.         }
  262.         cppsize = cppsize + 2 * maxlenCfn + strlen("<asmcpp$dir>.!cpp ") + 100;
  263.         /* + 100 allows for spaces and errors... */
  264. #ifdef DEBUG
  265.         for (j = 0; j < cppargc; j++) {
  266.                 printf("cppargpos = %d\n", cppargpos[j]);
  267.         }
  268. #endif
  269.         cppstring = (char *) malloc(cppsize);
  270.         if (cppstring == NULL) {
  271.                 fatal("Cannot allocate space for cpp command line");
  272.         }
  273.         for (appoCfn = 1; appoCfn <= N_files; appoCfn++) {
  274.                 leafname = strrchr(Argv[appoCfn], '.');
  275.                 if (leafname == NULL) {
  276.                         fatal("cannot decipher leafname: empty ?");
  277.                 }
  278.                 i = strlen(Argv[appoCfn]);
  279.                 do {
  280.                         i--;
  281.                 } while (Argv[appoCfn][i - 1] != '.');
  282.                 do {
  283.                         i--;
  284.                 } while (Argv[appoCfn][i - 1] != '.');
  285.                 strncpy(proot, Argv[appoCfn], i - 1);
  286.                 proot[i - 1] = EOS;
  287.                 proot = strcat(proot, ".p");
  288.                 proot = strcat(proot, leafname);
  289.  
  290.                 strcpy(cppnp[appoCfn], proot);
  291.  
  292.                 cppstring[0] = '\0';
  293.                 cppstring = strcat(cppstring, "call: <asmcpp$dir>.!cpp ");
  294.                 for (j = 0; j < cppargc; j++) {
  295.                         cppstring = strcat(cppstring, " ");
  296.                         cppstring = strcat(cppstring, Argv[cppargpos[j]]);
  297.                 }
  298.                 cppstring = strcat(cppstring, " ");
  299.                 cppstring = strcat(cppstring, Argv[appoCfn]);
  300.                 cppstring = strcat(cppstring, " > ");
  301.                 cppstring = strcat(cppstring, proot);
  302.                 fprintf(stderr, "Preprocessing:\n %s\n", cppstring);
  303.                 switch (system(cppstring)) {
  304.                 case -2:
  305.                         fatal("Not enough space to run !cpp or unknown <asmcpp$dir>\n Try to increase overall WimpSlot size and check if <asmcpp$dir> exists.\n");
  306.                         break;
  307.                 case 1:
  308.                         fatal("!cpp errors detected, compilation aborted\n");
  309.                         break;
  310.                 case 0:
  311.                 default:
  312.                         break;
  313.                 }
  314.         }
  315.         return;
  316. }
  317.  
  318.  
  319.  
  320. void
  321. initialize()
  322. {
  323.         char            c;
  324.         char           *leafname, *maproot, *xroot, *lroot;
  325.         /* input file leaf and output names */
  326.         int             i = 0;
  327.  
  328. #ifdef DEBUG
  329.         printf("Initializing\n");
  330. #endif
  331.         Err_count = 0;
  332.         Pc = 0;
  333.         Pass = 1;
  334.         Ctotal = 0;
  335.         N_page = 0;
  336.         Line[MAXBUF - 1] = NEWLINE;
  337.         if (strlen(Argv[ObjFilePos]) > FILENAME_MAX)
  338.                 fatal("obj_file name too long ");
  339.         Obj_name = (char *) malloc(strlen(Argv[ObjFilePos]));
  340.         lroot = (char *) malloc(strlen(Argv[1]));
  341.         maproot = (char *) malloc(strlen(Argv[1]));
  342.         xroot = (char *) malloc(strlen(Argv[1]));
  343.         if (Obj_name == NULL)
  344.                 fatal("Cannot allocate space for obj name");
  345.         if (lroot == NULL)
  346.                 fatal("Cannot allocate space for list file name");
  347.         if (maproot == NULL)
  348.                 fatal("Cannot allocate space for  map file name");
  349.         if (xroot == NULL)
  350.                 fatal("Cannot allocate space for xref file name");
  351. #ifdef DEBUG
  352.         printf("%d, %d\n", strlen(Argv[ObjFilePos]), sizeof(char));
  353.         printf("Oun =%s-\n", Obj_name);
  354.  
  355. #endif
  356.         do {                    /* copy -o <file name> into Obj_name */
  357.                 c = Obj_name[i] = Argv[ObjFilePos][i];
  358.                 i++;
  359.         } while (c && (i < FILENAME_MAX));
  360.  
  361. #ifdef DEBUG
  362.         printf("Fwd =%s\n", Fwd_name);
  363.         printf("Obj =%s\n", Obj_name);
  364. #endif
  365.         Obj_name[--i] = EOS;
  366.         printf("S19 Obj file:  %s\n", Obj_name);
  367.         if ((Objfil = fopen(Obj_name, "w")) == NULL) {
  368.                 fatal("Can't create object file");
  369.         }
  370.         leafname = strrchr(Argv[1], '.');
  371.         if (leafname == NULL) {
  372.                 fatal("cannot decipher leafname: empty ?");
  373.         }
  374.         i = strlen(Argv[1]);
  375.         do {
  376.                 i--;
  377.         } while (Argv[1][i - 1] != '.');
  378.         do {
  379.                 i--;
  380.         } while (Argv[1][i - 1] != '.');
  381.         /* if (Lflag != 0) */
  382.         {
  383.                 strncpy(lroot, Argv[1], i - 1);
  384.                 lroot[i - 1] = EOS;
  385.                 lroot = strcat(lroot, ".l");
  386.                 lroot = strcat(lroot, leafname);
  387.         }
  388.         /* if (Sflag != 0 ) */
  389.         {
  390.                 strncpy(maproot, Argv[1], i - 1);
  391.                 maproot[i - 1] = EOS;
  392.                 maproot = strcat(maproot, ".m");
  393.                 maproot = strcat(maproot, leafname);
  394.         }
  395.         /* if (CREflag != 0) */
  396.         {
  397.                 strncpy(xroot, Argv[1], i - 1);
  398.                 xroot[i - 1] = EOS;
  399.                 xroot = strcat(xroot, ".x");
  400.                 xroot = strcat(xroot, leafname);
  401.         }
  402.  
  403.         if (Splitflag == 0) {
  404.                 if ((Sflag != 0) || (Lflag != 0) || (CREflag != 0)) {
  405.                         if ((Listfil = fopen(lroot, "w")) == NULL) {
  406.                                 fatal("Panic! Can't create listing file. Does 'l' dir exist? File open?");
  407.                         }
  408.                         Mapfil = Listfil;
  409.                         Xfil = Listfil;
  410.                         if (Lflag != 0) {
  411.                                 printf("Listing file: %s\n", lroot);
  412.                         }
  413.                         if (CREflag != 0) {
  414.                                 printf("Xref file   : %s\n", lroot);
  415.                         }
  416.                         if (Sflag != 0) {
  417.                                 printf("Symbols file: %s\n", lroot);
  418.                         }
  419.                 } else {
  420.                         printf("No List, Xref or Symbols file selected\n");
  421.                 }
  422.         } else {
  423.                 if (Lflag != 0) {
  424.                         if ((Listfil = fopen(lroot, "w")) == NULL) {
  425.                                 fatal("Panic! Can't create listing file. Does 'l' dir exist? File open?");
  426.                         }
  427.                         printf("Listing file: %s\n", lroot);
  428.                 }
  429.                 if (Sflag != 0) {
  430.                         if ((Mapfil = fopen(maproot, "w")) == NULL) {
  431.                                 fatal("Panic! Can't create symbols map file. Does 'm' dir exist? File open?");
  432.                         }
  433.                         printf("Symbols file: %s\n", maproot);
  434.                 }
  435.                 if (CREflag != 0) {
  436.                         if ((Xfil = fopen(xroot, "w")) == NULL) {
  437.                                 fatal("Panic! Can't create xref file. Does 'x' dir exist? File open?");
  438.                         }
  439.                         printf("Xref file   : %s\n", xroot);
  440.                 }
  441.         }
  442.  
  443.         localinit();            /* target machine specific init. */
  444. }
  445.  
  446. void
  447. re_init(void)
  448. {
  449. #ifdef DEBUG
  450.         printf("Reinitializing\n");
  451. #endif
  452.         Pc = 0;
  453.         E_total = 0;
  454.         P_total = 0;
  455.         Ctotal = 0;
  456.         N_page = 0;
  457.         fwdreinit();
  458. }
  459.  
  460. void
  461. make_pass(void)
  462. {
  463.         /*
  464.          * #ifdef IBM char *fgets();
  465.          *//* the original line */
  466.         /* #else */
  467.         /* char *FGETS(); *//* use own FGETS which is rewrite of lib function */
  468.         /* such that it discards <CR> so can read code */
  469.         /* generated on IBM */
  470.         /* June 3, 1989 rev TER_1.1 */
  471.         /* #endif */
  472.  
  473. #ifdef DEBUG
  474.         printf("Pass %d\n", Pass);
  475. #endif
  476.         while (FGETS(Line, MAXBUF - 1, Fd) != (char *) NULL) {  /* changed to FGETS */
  477.                 /* which does not pass on <CR>  June 3, 1989 */
  478.                 /* rev TER_1.1 */
  479.                 Line_num++;
  480.                 Local_Line_num++;
  481.                 P_force = 0;    /* No force unless bytes emitted */
  482.                 N_page = 0;
  483.                 if (parse_line())
  484.                         process();
  485.                 if (Pass == 2 && Lflag && !N_page)
  486.                         print_line();
  487.                 P_total = 0;    /* reset byte count */
  488.                 Cycles = 0;     /* and per instruction cycle count */
  489.         }
  490.         f_record();
  491. }
  492.  
  493.  
  494. /*
  495.  * parse_line --- split input line into label, op and operand
  496.  */
  497. int
  498. parse_line(void)
  499. {
  500.         register char  *ptrfrm = Line;
  501.         register char  *ptrto = Label;
  502.         /* char *skip_white(); */
  503.  
  504.         if (*ptrfrm == '*' || *ptrfrm == '\n' || *ptrfrm == ';')
  505.                 /* added check for ';' ver TER_1.1 */
  506.                 /* June 3, 1989 */
  507.                 return (0);     /* a comment line */
  508.  
  509.         while (delim(*ptrfrm) == NO)    /* parsing Label */
  510.                 *ptrto++ = *ptrfrm++;
  511.         if (*--ptrto != ':')
  512.                 ptrto++;        /* allow trailing : */
  513.         *ptrto = EOS;
  514.  
  515.         ptrfrm = skip_white(ptrfrm);
  516.         if (*ptrfrm == ';') {   /* intercept comment after label, ver TER_2.0 */
  517.                 *Op = *Operand = EOS;   /* comment, no Opcode or Operand */
  518.                 return (1);
  519.         }
  520.         ptrto = Op;
  521.  
  522.         while (delim(*ptrfrm) == NO)    /* parsing Opcode */
  523.                 *ptrto++ = mapdn(*ptrfrm++);
  524.         *ptrto = EOS;
  525.  
  526.         ptrfrm = skip_white(ptrfrm);
  527.         if (*ptrfrm == ';') {   /* intercept comment, ver TER_2.0 */
  528.                 *Operand = EOS; /* comment, no Operand */
  529.                 return (1);
  530.         }
  531.         ptrto = Operand;
  532.         while ((*ptrfrm != NEWLINE) && ((*ptrfrm != ';') || (Op != "fcc")))    /* ver TER_2.0 */
  533.                 *ptrto++ = *ptrfrm++;   /* kill comments *//* buggy: if FCC
  534.                                          * ';' error reported removed 27/6/93 */
  535.         *ptrto = EOS;
  536.  
  537. #ifdef DEBUG
  538.         printf("Label-%s-\n", Label);
  539.         printf("Op----%s-\n", Op);
  540.         printf("Operand-%s-\n", Operand);
  541. #endif
  542.         return (1);
  543. }
  544.  
  545. /*
  546.  * process --- determine mnemonic class and act on it
  547.  */
  548. void
  549. process(void)
  550. {
  551.         register struct oper *i;
  552.         /* struct oper *mne_look(); */
  553.  
  554.         Old_pc = Pc;            /* setup `old' program counter */
  555.         Optr = Operand;         /* point to beginning of operand field */
  556.  
  557.         if (*Op == EOS) {       /* no mnemonic */
  558.                 if (*Label != EOS)
  559.                         install(Label, Pc);
  560.         } else if ((i = mne_look(Op)) == NULL)
  561.                 error("Unrecognized Mnemonic");
  562.         else if (i->class == PSEUDO)
  563.                 do_pseudo(i->opcode);
  564.         else {
  565.                 if (*Label)
  566.                         install(Label, Pc);
  567.                 if (Cflag)
  568.                         Cycles = i->cycles;
  569.                 do_op(i->opcode, i->class);
  570.                 if (Cflag)
  571.                         Ctotal += Cycles;
  572.         }
  573. }
  574.  
  575. #ifndef IBM
  576. char           *
  577. FGETS(char *s, int n, register FILE * iop)
  578. {                               /* get at most n chars from iop */
  579.         /* Added rev TER_1.1 June 3, 1989 */
  580.         /* Adapted from Kernighan & Ritchie */
  581.         /*
  582.          * An fgets() that is IBM proof. Not needed if this IS an IBM
  583.          */
  584.         register int    c;
  585.         register char  *cs;
  586.  
  587.         cs = s;
  588.         while (--n > 0 && (c = getc(iop)) != EOF) {     /* read chars if not
  589.                                                          * file end */
  590.                 if ((*cs = c) != CR)
  591.                         cs++;   /* incr buffer pointer if not CR */
  592.                 /* If CR, leave to be written over */
  593.                 if (c == '\n')
  594.                         break;
  595.         }
  596.         *cs = '\0';             /* replace NEWLINE with NULL as in standard
  597.                                  * fgets() */
  598.         return ((c == EOF && cs == s) ? NULL : s);      /* return NULL if this
  599.                                                          * is EOF */
  600. }
  601. #endif
  602.