/[gxemul]/upstream/0.4.4/src/machine.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /upstream/0.4.4/src/machine.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

trunk/src/machine.c revision 24 by dpavlin, Mon Oct 8 16:19:56 2007 UTC upstream/0.4.4/src/machine.c revision 35 by dpavlin, Mon Oct 8 16:21:26 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2003-2006  Anders Gavare.  All rights reserved.   *  Copyright (C) 2003-2007  Anders Gavare.  All rights reserved.
3   *   *
4   *  Redistribution and use in source and binary forms, with or without   *  Redistribution and use in source and binary forms, with or without
5   *  modification, are permitted provided that the following conditions are met:   *  modification, are permitted provided that the following conditions are met:
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: machine.c,v 1.671 2006/06/16 18:31:24 debug Exp $   *  $Id: machine.c,v 1.693 2007/01/28 14:15:29 debug Exp $
29   */   */
30    
31  #include <stdio.h>  #include <stdio.h>
32  #include <stdlib.h>  #include <stdlib.h>
33  #include <stdarg.h>  #include <stdarg.h>
 #ifdef SOLARIS  
 /*  TODO: is this strings vs string separation really necessary?  */  
 #include <strings.h>  
 #else  
34  #include <string.h>  #include <string.h>
 #endif  
35  #include <time.h>  #include <time.h>
36  #include <unistd.h>  #include <unistd.h>
37    
# Line 44  Line 39 
39  #include "bus_isa.h"  #include "bus_isa.h"
40  #include "bus_pci.h"  #include "bus_pci.h"
41  #include "cpu.h"  #include "cpu.h"
42    #include "debugger.h"
43  #include "device.h"  #include "device.h"
44  #include "devices.h"  #include "devices.h"
45  #include "diskimage.h"  #include "diskimage.h"
46  #include "emul.h"  #include "emul.h"
47  #include "machine.h"  #include "machine.h"
 #include "machine_interrupts.h"  
48  #include "memory.h"  #include "memory.h"
49  #include "misc.h"  #include "misc.h"
50  #include "net.h"  #include "net.h"
51    #include "settings.h"
52  #include "symbol.h"  #include "symbol.h"
53    
54    
# Line 70  struct machine_entry *first_machine_entr Line 66  struct machine_entry *first_machine_entr
66   *   *
67   *  Returns a reasonably initialized struct machine.   *  Returns a reasonably initialized struct machine.
68   */   */
69  struct machine *machine_new(char *name, struct emul *emul)  struct machine *machine_new(char *name, struct emul *emul, int id)
70  {  {
71          struct machine *m;          struct machine *m;
72          m = malloc(sizeof(struct machine));          m = malloc(sizeof(struct machine));
# Line 81  struct machine *machine_new(char *name, Line 77  struct machine *machine_new(char *name,
77    
78          memset(m, 0, sizeof(struct machine));          memset(m, 0, sizeof(struct machine));
79    
80          /*  Back pointer:  */          /*  Pointer back to the emul object that this machine belongs to:  */
81          m->emul = emul;          m->emul = emul;
82    
83          m->name = strdup(name);          m->name = strdup(name);
84    
85            /*  Full path, e.g. "emul[0].machine[0]":  */
86            m->path = malloc(strlen(emul->path) + 20);
87            if (m->path == NULL) {
88                    fprintf(stderr, "out of memory\n");
89                    exit(1);
90            }
91            snprintf(m->path, strlen(emul->path) + 20, "%s.machine[%i]",
92                emul->path, id);
93    
94          /*  Sane default values:  */          /*  Sane default values:  */
95          m->serial_nr = 1;          m->serial_nr = 1;
96          m->machine_type = MACHINE_NONE;          m->machine_type = MACHINE_NONE;
97          m->machine_subtype = MACHINE_NONE;          m->machine_subtype = MACHINE_NONE;
98          m->arch_pagesize = 4096;        /*  Should be overriden in          m->arch_pagesize = 4096;        /*  Should be overriden in
99                                              emul.c for other pagesizes.  */                                              emul.c for other pagesizes.  */
         m->dyntrans_alignment_check = 1;  
100          m->prom_emulation = 1;          m->prom_emulation = 1;
101          m->speed_tricks = 1;          m->allow_instruction_combinations = 1;
102          m->byte_order_override = NO_BYTE_ORDER_OVERRIDE;          m->byte_order_override = NO_BYTE_ORDER_OVERRIDE;
103          m->boot_kernel_filename = "";          m->boot_kernel_filename = "";
104          m->boot_string_argument = NULL;          m->boot_string_argument = NULL;
         m->automatic_clock_adjustment = 1;  
105          m->x11_scaledown = 1;          m->x11_scaledown = 1;
106          m->x11_scaleup = 1;          m->x11_scaleup = 1;
107          m->n_gfx_cards = 1;          m->n_gfx_cards = 1;
# Line 106  struct machine *machine_new(char *name, Line 109  struct machine *machine_new(char *name,
109          m->show_symbolic_register_names = 1;          m->show_symbolic_register_names = 1;
110          symbol_init(&m->symbol_context);          symbol_init(&m->symbol_context);
111    
112            /*  Settings:  */
113            m->settings = settings_new();
114            settings_add(m->settings, "name", 0,
115                SETTINGS_TYPE_STRING, SETTINGS_FORMAT_STRING,
116                (void *) &m->name);
117            settings_add(m->settings, "serial_nr", 0,
118                SETTINGS_TYPE_INT, SETTINGS_FORMAT_DECIMAL,
119                (void *) &m->serial_nr);
120            settings_add(m->settings, "arch_pagesize", 0,
121                SETTINGS_TYPE_INT, SETTINGS_FORMAT_DECIMAL,
122                (void *) &m->arch_pagesize);
123            settings_add(m->settings, "prom_emulation", 0,
124                SETTINGS_TYPE_INT, SETTINGS_FORMAT_YESNO,
125                (void *) &m->prom_emulation);
126            settings_add(m->settings, "allow_instruction_combinations", 0,
127                SETTINGS_TYPE_INT, SETTINGS_FORMAT_YESNO,
128                (void *) &m->allow_instruction_combinations);
129            settings_add(m->settings, "n_gfx_cards", 0,
130                SETTINGS_TYPE_INT, SETTINGS_FORMAT_DECIMAL,
131                (void *) &m->n_gfx_cards);
132            settings_add(m->settings, "show_symbolic_register_names", 1,
133                SETTINGS_TYPE_INT, SETTINGS_FORMAT_YESNO,
134                (void *) &m->show_symbolic_register_names);
135            settings_add(m->settings, "statistics_enabled", 1,
136                SETTINGS_TYPE_INT, SETTINGS_FORMAT_YESNO,
137                (void *) &m->statistics_enabled);
138    
139          return m;          return m;
140  }  }
141    
142    
143  /*  /*
144     *  machine_destroy():
145     *
146     *  Destroys a machine object.
147     */
148    void machine_destroy(struct machine *machine)
149    {
150            int i;
151    
152            for (i=0; i<machine->ncpus; i++)
153                    cpu_destroy(machine->cpus[i]);
154    
155            if (machine->name != NULL)
156                    free(machine->name);
157    
158            if (machine->path != NULL)
159                    free(machine->path);
160    
161            /*  Remove any remaining level-1 settings:  */
162            settings_remove_all(machine->settings);
163            settings_destroy(machine->settings);
164    
165            free(machine);
166    }
167    
168    
169    /*
170   *  machine_name_to_type():   *  machine_name_to_type():
171   *   *
172   *  Take a type and a subtype as strings, and convert them into numeric   *  Take a type and a subtype as strings, and convert them into numeric
# Line 235  void machine_add_tickfunction(struct mac Line 291  void machine_add_tickfunction(struct mac
291          if (!machine->cycle_accurate) {          if (!machine->cycle_accurate) {
292                  /*                  /*
293                   *  The dyntrans subsystem wants to run code in relatively                   *  The dyntrans subsystem wants to run code in relatively
294                   *  large chunks without checking for external interrupts,                   *  large chunks without checking for external interrupts;
295                   *  so we cannot allow too low tickshifts:                   *  too low tickshifts are not allowed.
296                   */                   */
297                  if (tickshift < N_SAFE_DYNTRANS_LIMIT_SHIFT) {                  if (tickshift < N_SAFE_DYNTRANS_LIMIT_SHIFT) {
298                          fatal("ERROR! tickshift = %i, less than "                          fatal("ERROR! tickshift = %i, less than "
# Line 257  void machine_add_tickfunction(struct mac Line 313  void machine_add_tickfunction(struct mac
313    
314    
315  /*  /*
316   *  machine_bus_register():   *  machine_statistics_init():
317     *
318     *  Initialize the parts of a machine struct that deal with instruction
319     *  statistics gathering.
320   *   *
321   *  Registers a bus in a machine.   *  Note: The fname argument contains "flags:filename".
322   */   */
323  void machine_bus_register(struct machine *machine, char *busname,  void machine_statistics_init(struct machine *machine, char *fname)
         void (*debug_dump)(void *), void *extra)  
324  {  {
325          struct machine_bus *tmp, *last = NULL, *new;          int n_fields = 0;
326            char *pcolon = fname;
327            char *mode = "a";       /*  Append by default  */
328    
329          new = zeroed_alloc(sizeof(struct machine_bus));          machine->allow_instruction_combinations = 0;
         new->name = strdup(busname);  
         new->debug_dump = debug_dump;  
         new->extra = extra;  
330    
331          /*  Register last in the bus list:  */          if (machine->statistics_fields != NULL) {
332          tmp = machine->first_bus;                  fprintf(stderr, "Only one -s option is allowed.\n");
333          while (tmp != NULL) {                  exit(1);
                 last = tmp;  
                 tmp = tmp->next;  
334          }          }
335    
336          if (last == NULL)          machine->statistics_fields = malloc(MAX_STATISTICS_FIELDS + 1);
337                  machine->first_bus = new;          machine->statistics_enabled = 1;
         else  
                 last->next = new;  
338    
339          machine->n_busses ++;          while (*pcolon && *pcolon != ':')
340  }                  pcolon ++;
341    
342            if (*pcolon != ':') {
343                    fprintf(stderr, "The syntax for the -s option is:    "
344                        "-s flags:filename\nYou omitted the flags. Run g"
345                        "xemul -h for a list of available flags.\n");
346                    exit(1);
347            }
348    
349  /*          while (*fname != ':') {
350   *  machine_dump_bus_info():                  switch (*fname) {
  *  
  *  Dumps info about registered busses.  
  */  
 void machine_dump_bus_info(struct machine *m)  
 {  
         struct machine_bus *bus = m->first_bus;  
         int iadd = DEBUG_INDENTATION;  
351    
352          if (m->n_busses > 0)                  /*  Type flags:  */
353                  debug("busses:\n");                  case 'v':
354          debug_indentation(iadd);                  case 'i':
355          while (bus != NULL) {                  case 'p':
356                  bus->debug_dump(bus->extra);                          machine->statistics_fields[n_fields ++] = *fname;
357                  bus = bus->next;                          if (n_fields >= MAX_STATISTICS_FIELDS) {
358                                    fprintf(stderr, "Internal error: Too many "
359                                        "statistics fields used. Increase "
360                                        "MAX_STATISTICS_FIELDS.\n");
361                                    exit(1);
362                            }
363                            machine->statistics_fields[n_fields] = '\0';
364                            break;
365    
366                    /*  Optional flags:  */
367                    case 'o':
368                            mode = "w";
369                            break;
370                    case 'd':
371                            machine->statistics_enabled = 0;
372                            break;
373    
374                    default:fprintf(stderr, "Unknown flag '%c' used with the"
375                                " -s option. Aborting.\n", *fname);
376                            exit(1);
377                    }
378                    fname ++;
379          }          }
380          debug_indentation(-iadd);  
381            fname ++;       /*  point to the filename after the colon  */
382    
383            machine->statistics_filename = strdup(fname);
384            machine->statistics_file = fopen(machine->statistics_filename, mode);
385  }  }
386    
387    
# Line 332  void machine_dumpinfo(struct machine *m) Line 409  void machine_dumpinfo(struct machine *m)
409                  debug(", dbe_on_nonexistant_memaccess");                  debug(", dbe_on_nonexistant_memaccess");
410          debug("\n");          debug("\n");
411    
         debug("clock: ");  
         if (m->automatic_clock_adjustment)  
                 debug("adjusted automatically");  
         else  
                 debug("fixed at %i Hz", m->emulated_hz);  
         debug("\n");  
   
412          if (!m->prom_emulation)          if (!m->prom_emulation)
413                  debug("PROM emulation disabled\n");                  debug("PROM emulation disabled\n");
414    
# Line 367  void machine_dumpinfo(struct machine *m) Line 437  void machine_dumpinfo(struct machine *m)
437                  debug("\n");                  debug("\n");
438          }          }
439    
         machine_dump_bus_info(m);  
   
440          diskimage_dump_info(m);          diskimage_dump_info(m);
441    
442          if (m->force_netboot)          if (m->force_netboot)
# Line 515  int store_64bit_word(struct cpu *cpu, ui Line 583  int store_64bit_word(struct cpu *cpu, ui
583  int store_32bit_word(struct cpu *cpu, uint64_t addr, uint64_t data32)  int store_32bit_word(struct cpu *cpu, uint64_t addr, uint64_t data32)
584  {  {
585          unsigned char data[4];          unsigned char data[4];
586    
587            /*  TODO: REMOVE THIS once everything is more stable!  */
588          if (cpu->machine->arch == ARCH_MIPS && (addr >> 32) == 0)          if (cpu->machine->arch == ARCH_MIPS && (addr >> 32) == 0)
589                  addr = (int64_t)(int32_t)addr;                  addr = (int64_t)(int32_t)addr;
590    
591          data[0] = (data32 >> 24) & 255;          data[0] = (data32 >> 24) & 255;
592          data[1] = (data32 >> 16) & 255;          data[1] = (data32 >> 16) & 255;
593          data[2] = (data32 >> 8) & 255;          data[2] = (data32 >> 8) & 255;
# Line 540  int store_32bit_word(struct cpu *cpu, ui Line 611  int store_32bit_word(struct cpu *cpu, ui
611  int store_16bit_word(struct cpu *cpu, uint64_t addr, uint64_t data16)  int store_16bit_word(struct cpu *cpu, uint64_t addr, uint64_t data16)
612  {  {
613          unsigned char data[2];          unsigned char data[2];
614    
615            /*  TODO: REMOVE THIS once everything is more stable!  */
616          if (cpu->machine->arch == ARCH_MIPS && (addr >> 32) == 0)          if (cpu->machine->arch == ARCH_MIPS && (addr >> 32) == 0)
617                  addr = (int64_t)(int32_t)addr;                  addr = (int64_t)(int32_t)addr;
618    
619          data[0] = (data16 >> 8) & 255;          data[0] = (data16 >> 8) & 255;
620          data[1] = (data16) & 255;          data[1] = (data16) & 255;
621          if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {          if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
# Line 561  void store_buf(struct cpu *cpu, uint64_t Line 635  void store_buf(struct cpu *cpu, uint64_t
635  {  {
636          size_t psize = 1024;    /*  1024 256 64 16 4 1  */          size_t psize = 1024;    /*  1024 256 64 16 4 1  */
637    
638            /*  TODO: REMOVE THIS once everything is more stable!  */
639          if (cpu->machine->arch == ARCH_MIPS && (addr >> 32) == 0)          if (cpu->machine->arch == ARCH_MIPS && (addr >> 32) == 0)
640                  addr = (int64_t)(int32_t)addr;                  addr = (int64_t)(int32_t)addr;
641    
# Line 605  void store_pointer_and_advance(struct cp Line 680  void store_pointer_and_advance(struct cp
680    
681    
682  /*  /*
683     *  load_64bit_word():
684     *
685     *  Helper function. Emulated byte order is taken into account.
686     */
687    uint64_t load_64bit_word(struct cpu *cpu, uint64_t addr)
688    {
689            unsigned char data[8];
690    
691            cpu->memory_rw(cpu, cpu->mem,
692                addr, data, sizeof(data), MEM_READ, CACHE_DATA);
693    
694            if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
695                    int tmp = data[0]; data[0] = data[7]; data[7] = tmp;
696                    tmp = data[1]; data[1] = data[6]; data[6] = tmp;
697                    tmp = data[2]; data[2] = data[5]; data[5] = tmp;
698                    tmp = data[3]; data[3] = data[4]; data[4] = tmp;
699            }
700    
701            return
702                ((uint64_t)data[0] << 56) + ((uint64_t)data[1] << 48) +
703                ((uint64_t)data[2] << 40) + ((uint64_t)data[3] << 32) +
704                ((uint64_t)data[4] << 24) + ((uint64_t)data[5] << 16) +
705                ((uint64_t)data[6] << 8) + (uint64_t)data[7];
706    }
707    
708    
709    /*
710   *  load_32bit_word():   *  load_32bit_word():
711   *   *
712   *  Helper function.  Prints a warning and returns 0, if the read failed.   *  Helper function. Emulated byte order is taken into account.
  *  Emulated byte order is taken into account.  
713   */   */
714  uint32_t load_32bit_word(struct cpu *cpu, uint64_t addr)  uint32_t load_32bit_word(struct cpu *cpu, uint64_t addr)
715  {  {
716          unsigned char data[4];          unsigned char data[4];
717    
718            /*  TODO: REMOVE THIS once everything is more stable!  */
719          if (cpu->machine->arch == ARCH_MIPS && (addr >> 32) == 0)          if (cpu->machine->arch == ARCH_MIPS && (addr >> 32) == 0)
720                  addr = (int64_t)(int32_t)addr;                  addr = (int64_t)(int32_t)addr;
721    
722          cpu->memory_rw(cpu, cpu->mem,          cpu->memory_rw(cpu, cpu->mem,
723              addr, data, sizeof(data), MEM_READ, CACHE_DATA);              addr, data, sizeof(data), MEM_READ, CACHE_DATA);
724    
# Line 631  uint32_t load_32bit_word(struct cpu *cpu Line 734  uint32_t load_32bit_word(struct cpu *cpu
734  /*  /*
735   *  load_16bit_word():   *  load_16bit_word():
736   *   *
737   *  Helper function.  Prints a warning and returns 0, if the read failed.   *  Helper function. Emulated byte order is taken into account.
  *  Emulated byte order is taken into account.  
738   */   */
739  uint16_t load_16bit_word(struct cpu *cpu, uint64_t addr)  uint16_t load_16bit_word(struct cpu *cpu, uint64_t addr)
740  {  {
741          unsigned char data[2];          unsigned char data[2];
742    
743            /*  TODO: REMOVE THIS once everything is more stable!  */
744          if (cpu->machine->arch == ARCH_MIPS && (addr >> 32) == 0)          if (cpu->machine->arch == ARCH_MIPS && (addr >> 32) == 0)
745                  addr = (int64_t)(int32_t)addr;                  addr = (int64_t)(int32_t)addr;
746    
747          cpu->memory_rw(cpu, cpu->mem,          cpu->memory_rw(cpu, cpu->mem,
748              addr, data, sizeof(data), MEM_READ, CACHE_DATA);              addr, data, sizeof(data), MEM_READ, CACHE_DATA);
749    
# Line 783  void machine_setup(struct machine *machi Line 887  void machine_setup(struct machine *machi
887                  debug(" (%.2f MHz)", (float)machine->emulated_hz / 1000000);                  debug(" (%.2f MHz)", (float)machine->emulated_hz / 1000000);
888          debug("\n");          debug("\n");
889    
         /*  Default fake speed: 5 MHz  */  
         if (machine->emulated_hz < 1)  
                 machine->emulated_hz = 5000000;  
   
890          if (machine->bootstr != NULL) {          if (machine->bootstr != NULL) {
891                  debug("bootstring%s: %s", (machine->bootarg!=NULL &&                  debug("bootstring%s: %s", (machine->bootarg!=NULL &&
892                      strlen(machine->bootarg) >= 1)? "(+bootarg)" : "",                      strlen(machine->bootarg) >= 1)? "(+bootarg)" : "",
# Line 796  void machine_setup(struct machine *machi Line 896  void machine_setup(struct machine *machi
896                  debug("\n");                  debug("\n");
897          }          }
898    
         if (verbose >= 2)  
                 machine_dump_bus_info(machine);  
   
899          if (!machine->stable)          if (!machine->stable)
900                  fatal("!\n!  NOTE: This machine type is not implemented well"                  fatal("!\n!  NOTE: This machine type is not implemented well"
901                      " enough yet to run\n!  any real-world code!"                      " enough yet to run\n!  any real-world code!"
# Line 896  void machine_default_cputype(struct mach Line 993  void machine_default_cputype(struct mach
993  }  }
994    
995    
996    /*****************************************************************************/
997    
998    
999    /*
1000     *  machine_run():
1001     *
1002     *  Run one or more instructions on all CPUs in this machine. (Usually,
1003     *  around N_SAFE_DYNTRANS_LIMIT instructions will be run by the dyntrans
1004     *  system.)
1005     *
1006     *  Return value is 1 if any CPU in this machine is still running,
1007     *  or 0 if all CPUs are stopped.
1008     */
1009    int machine_run(struct machine *machine)
1010    {
1011            struct cpu **cpus = machine->cpus;
1012            int ncpus = machine->ncpus, cpu0instrs = 0, i, te;
1013    
1014            for (i=0; i<ncpus; i++) {
1015                    if (cpus[i]->running) {
1016                            int instrs_run = cpus[i]->run_instr(cpus[i]);
1017                            if (i == 0)
1018                                    cpu0instrs += instrs_run;
1019                    }
1020            }
1021    
1022            /*
1023             *  Hardware 'ticks':  (clocks, interrupt sources...)
1024             *
1025             *  Here, cpu0instrs is the number of instructions executed on cpu0.
1026             *
1027             *  TODO: This should be redesigned into some "mainbus" stuff instead!
1028             */
1029    
1030            machine->ninstrs += cpu0instrs;
1031    
1032            for (te=0; te<machine->n_tick_entries; te++) {
1033                    machine->ticks_till_next[te] -= cpu0instrs;
1034                    if (machine->ticks_till_next[te] <= 0) {
1035                            while (machine->ticks_till_next[te] <= 0) {
1036                                    machine->ticks_till_next[te] +=
1037                                        machine->ticks_reset_value[te];
1038                            }
1039    
1040                            machine->tick_func[te](cpus[0],
1041                                machine->tick_extra[te]);
1042                    }
1043            }
1044    
1045            /*  Is any CPU still alive?  */
1046            for (i=0; i<ncpus; i++)
1047                    if (cpus[i]->running)
1048                            return 1;
1049    
1050            return 0;
1051    }
1052    
1053    
1054    /*****************************************************************************/
1055    
1056    
1057  /*  /*
1058   *  machine_entry_new():   *  machine_entry_new():
1059   *   *
1060   *  This function creates a new machine_entry struct, and fills it with some   *  This function creates a new machine_entry struct, and fills it with some
1061   *  valid data; it is up to the caller to add additional data that weren't   *  valid data; it is up to the caller to add additional data that weren't
1062   *  passed as arguments to this function.   *  passed as arguments to this function, such as alias names and machine
1063     *  subtypes.
1064   */   */
1065  struct machine_entry *machine_entry_new(const char *name,  struct machine_entry *machine_entry_new(const char *name, int arch,
1066          int arch, int oldstyle_type, int n_aliases, int n_subtypes)          int oldstyle_type)
1067  {  {
1068          struct machine_entry *me;          struct machine_entry *me;
1069    
# Line 919  struct machine_entry *machine_entry_new( Line 1078  struct machine_entry *machine_entry_new(
1078          me->name = name;          me->name = name;
1079          me->arch = arch;          me->arch = arch;
1080          me->machine_type = oldstyle_type;          me->machine_type = oldstyle_type;
1081          me->n_aliases = n_aliases;          me->n_aliases = 0;
1082          me->aliases = malloc(sizeof(char *) * n_aliases);          me->aliases = NULL;
1083          if (me->aliases == NULL) {          me->n_subtypes = 0;
                 fprintf(stderr, "machine_entry_new(): out of memory (2)\n");  
                 exit(1);  
         }  
         me->n_subtypes = n_subtypes;  
1084          me->setup = NULL;          me->setup = NULL;
1085    
1086          if (n_subtypes > 0) {          return me;
1087                  me->subtype = malloc(sizeof(struct machine_entry_subtype *) *  }
1088                      n_subtypes);  
1089                  if (me->subtype == NULL) {  
1090                          fprintf(stderr, "machine_entry_new(): out of "  /*
1091                              "memory (3)\n");   *  machine_entry_add_alias():
1092                          exit(1);   *
1093                  }   *  This function adds an "alias" to a machine entry.
1094     */
1095    void machine_entry_add_alias(struct machine_entry *me, const char *name)
1096    {
1097            me->n_aliases ++;
1098            me->aliases = realloc(me->aliases, sizeof(char *) * me->n_aliases);
1099            if (me->aliases == NULL) {
1100                    fprintf(stderr, "out of memory\n");
1101                    exit(1);
1102          }          }
1103    
1104          return me;          me->aliases[me->n_aliases - 1] = (char *) name;
1105  }  }
1106    
1107    
1108  /*  /*
1109   *  machine_entry_subtype_new():   *  machine_entry_add_subtype():
1110   *   *
1111   *  This function creates a new machine_entry_subtype struct, and fills it with   *  This function adds a subtype to a machine entry. The argument list after
1112   *  some valid data; it is up to the caller to add additional data that weren't   *  oldstyle_subtype is a list of one or more char *, followed by NULL. E.g.:
  *  passed as arguments to this function.  
1113   *   *
1114   *  For internal use.   *      machine_entry_add_subtype(me, "Machine X", MACHINE_X,
1115     *          "machine-x", "x", NULL);
1116   */   */
1117  struct machine_entry_subtype *machine_entry_subtype_new(  void machine_entry_add_subtype(struct machine_entry *me, const char *name,
1118          const char *name, int oldstyle_type, int n_aliases)          int oldstyle_subtype, ...)
1119  {  {
1120            va_list argp;
1121          struct machine_entry_subtype *mes;          struct machine_entry_subtype *mes;
1122    
1123            /*  Allocate a new subtype struct:  */
1124          mes = malloc(sizeof(struct machine_entry_subtype));          mes = malloc(sizeof(struct machine_entry_subtype));
1125          if (mes == NULL) {          if (mes == NULL) {
1126                  fprintf(stderr, "machine_entry_subtype_new(): out "                  fprintf(stderr, "machine_entry_subtype_new(): out "
# Line 963  struct machine_entry_subtype *machine_en Line 1128  struct machine_entry_subtype *machine_en
1128                  exit(1);                  exit(1);
1129          }          }
1130    
1131            /*  Add the subtype to the machine entry:  */
1132            me->n_subtypes ++;
1133            me->subtype = realloc(me->subtype, sizeof(struct
1134                machine_entry_subtype *) * me->n_subtypes);
1135            if (me->subtype == NULL) {
1136                    fprintf(stderr, "out of memory\n");
1137                    exit(1);
1138            }
1139            me->subtype[me->n_subtypes - 1] = mes;
1140    
1141            /*  Fill the struct with subtype data:  */
1142          memset(mes, 0, sizeof(struct machine_entry_subtype));          memset(mes, 0, sizeof(struct machine_entry_subtype));
1143          mes->name = name;          mes->name = name;
1144          mes->machine_subtype = oldstyle_type;          mes->machine_subtype = oldstyle_subtype;
1145          mes->n_aliases = n_aliases;  
1146          mes->aliases = malloc(sizeof(char *) * n_aliases);          /*  ... and all aliases:  */
1147          if (mes->aliases == NULL) {          mes->n_aliases = 0;
1148                  fprintf(stderr, "machine_entry_subtype_new(): "          mes->aliases = NULL;
1149                      "out of memory (2)\n");  
1150                  exit(1);          va_start(argp, oldstyle_subtype);
1151    
1152            for (;;) {
1153                    char *s = va_arg(argp, char *);
1154                    if (s == NULL)
1155                            break;
1156    
1157                    mes->n_aliases ++;
1158                    mes->aliases = realloc(mes->aliases, sizeof(char *) *
1159                        mes->n_aliases);
1160                    if (mes->aliases == NULL) {
1161                            fprintf(stderr, "out of memory\n");
1162                            exit(1);
1163                    }
1164    
1165                    mes->aliases[mes->n_aliases - 1] = s;
1166          }          }
1167    
1168          return mes;          va_end(argp);
1169  }  }
1170    
1171    
1172  /*  /*
1173   *  machine_entry_add():   *  machine_entry_register():
1174   *   *
1175   *  Inserts a new machine_entry into the machine entries list.   *  Inserts a new machine_entry into the machine entries list.
1176   */   */
1177  void machine_entry_add(struct machine_entry *me, int arch)  void machine_entry_register(struct machine_entry *me, int arch)
1178  {  {
1179          struct machine_entry *prev, *next;          struct machine_entry *prev, *next;
1180    

Legend:
Removed from v.24  
changed lines
  Added in v.35

  ViewVC Help
Powered by ViewVC 1.1.26