| plan 9 kernel history: overview | file list | diff list |
1999/0218/pc/main.c (diff list | history)
| pc/main.c on 1991/0702 | ||
| 1991/0702 | #include "u.h" | |
| 1992/0321 | #include "../port/lib.h" | |
| 1991/0706 | #include "mem.h" | |
| 1991/0702 | #include "dat.h" #include "fns.h" | |
| 1991/0706 | #include "io.h" | |
| 1991/0716 | #include "ureg.h" #include "init.h" | |
| 1997/1101 | #include "pool.h" | |
| 1991/0629 | ||
| 1997/0327 | Mach *m; | |
| 1992/0904 | ||
| 1997/0327 | static uchar *sp; /* stack pointer for /boot */ | |
| 1992/0903 | ||
| 1997/0327 | /* * Where configuration info is left for the loaded programme. * This will turn into a structure as more is done by the boot loader * (e.g. why parse the .ini file twice?). * There are 1024 bytes available at CONFADDR. */ | |
| 1997/0329 | #define BOOTLINE ((char*)CONFADDR) | |
| 1997/0327 | #define BOOTLINELEN 64 #define BOOTARGS ((char*)(CONFADDR+BOOTLINELEN)) #define BOOTARGSLEN (1024-BOOTLINELEN) | |
| 1993/0330 | #define MAXCONF 32 | |
| 1993/0915 | char bootdisk[NAMELEN]; | |
| 1993/0330 | char *confname[MAXCONF]; char *confval[MAXCONF]; int nconf; | |
| 1997/0327 | extern void ns16552install(void); /* botch: config */ | |
| 1993/0915 | ||
| 1997/0327 | static int isoldbcom; | |
| 1997/0403 | static int getcfields(char* lp, char** fields, int n, char* sep) { int i; for(i = 0; lp && *lp && i < n; i++){ while(*lp && strchr(sep, *lp) != 0) *lp++ = 0; if(*lp == 0) break; fields[i] = lp; while(*lp && strchr(sep, *lp) == 0){ if(*lp == '\\' && *(lp+1) == '\n') *lp++ = ' '; lp++; } } return i; } | |
| 1997/0327 | static void | |
| 1997/0403 | options(void) | |
| 1997/0327 | { uchar *bda; | |
| 1997/0403 | long i, n; char *cp, *line[MAXCONF], *p, *q; | |
| 1997/0327 | ||
| 1997/0403 | if(strncmp(BOOTARGS, "ZORT 0\r\n", 8)){ isoldbcom = 1; | |
| 1997/0327 | ||
| 1997/0403 | memmove(BOOTARGS, KADDR(1024), BOOTARGSLEN); memmove(BOOTLINE, KADDR(0x100), BOOTLINELEN); | |
| 1997/0327 | ||
| 1997/0403 | bda = KADDR(0x400); bda[0x13] = 639; bda[0x14] = 639>>8; } /* * parse configuration args from dos file plan9.ini */ cp = BOOTARGS; /* where b.com leaves its config */ cp[BOOTARGSLEN-1] = 0; /* * Strip out '\r', change '\t' -> ' '. */ p = cp; for(q = cp; *q; q++){ if(*q == '\r') continue; if(*q == '\t') *q = ' '; *p++ = *q; } *p = 0; n = getcfields(cp, line, MAXCONF, "\n"); for(i = 0; i < n; i++){ if(*line[i] == '#') continue; cp = strchr(line[i], '='); if(cp == 0) continue; *cp++ = 0; if(cp - line[i] >= NAMELEN+1) *(line[i]+NAMELEN-1) = 0; confname[nconf] = line[i]; confval[nconf] = cp; nconf++; } | |
| 1997/0327 | } | |
| 1991/0716 | void | |
| 1991/0702 | main(void) | |
| 1991/0625 | { | |
| 1997/0403 | outb(0x3F2, 0x00); /* botch: turn off the floppy motor */ | |
| 1997/0327 | /* * There is a little leeway here in the ordering but care must be * taken with dependencies: | |
| 1997/0329 | * function dependencies * ======== ============ * machinit depends on: m->machno, m->pdb | |
| 1997/0403 | * cpuidentify depends on: m | |
| 1997/0329 | * confinit calls: meminit * meminit depends on: cpuidentify (needs to know processor * type for caching, etc.) * archinit depends on: meminit (MP config table may be at the * top of system physical memory); | |
| 1997/0327 | * conf.nmach (not critical, mpinit will check); | |
| 1997/0329 | * arch->intrinit depends on: trapinit | |
| 1997/0327 | */ conf.nmach = 1; MACHP(0) = (Mach*)CPU0MACH; | |
| 1997/1101 | m->pdb = (ulong*)CPU0PDB; | |
| 1991/0711 | machinit(); | |
| 1991/1113 | active.machs = 1; | |
| 1997/0327 | active.exiting = 0; | |
| 1997/0403 | options(); | |
| 1997/0329 | screeninit(); | |
| 1997/0327 | cpuidentify(); | |
| 1991/0711 | confinit(); | |
| 1997/0329 | archinit(); | |
| 1992/0625 | xinit(); | |
| 1997/0327 | trapinit(); | |
| 1991/0716 | printinit(); | |
| 1997/0522 | cpuidprint(); | |
| 1997/0327 | if(isoldbcom) print(" ****OLD B.COM - UPGRADE****\n"); | |
| 1992/0625 | pageinit(); | |
| 1997/0327 | mmuinit(); if(arch->intrinit) arch->intrinit(); ns16552install(); /* botch: config */ | |
| 1991/0906 | mathinit(); | |
| 1992/0409 | kbdinit(); | |
| 1997/0327 | if(arch->clockenable) arch->clockenable(); | |
| 1991/0716 | procinit0(); initseg(); | |
| 1995/0329 | links(); | |
| 1997/1101 | conf.monitor = 1; | |
| 1991/0716 | chandevreset(); swapinit(); userinit(); schedinit(); | |
| 1991/0712 | } | |
| 1991/0706 | ||
| 1991/0716 | void machinit(void) | |
| 1991/0712 | { | |
| 1997/0327 | int machno; | |
| 1997/1101 | ulong *pdb; | |
| 1991/0712 | ||
| 1997/0327 | machno = m->machno; pdb = m->pdb; | |
| 1991/0716 | memset(m, 0, sizeof(Mach)); | |
| 1997/0327 | m->machno = machno; m->pdb = pdb; | |
| 1991/0625 | } | |
| 1991/0716 | void | |
| 1993/1013 | ksetterm(char *f) { char buf[2*NAMELEN]; sprint(buf, f, conffile); ksetenv("terminal", buf); } void | |
| 1991/0716 | init0(void) | |
| 1991/0712 | { | |
| 1993/0330 | int i; | |
| 1992/0918 | char tstr[32]; | |
| 1993/0915 | up->nerrlab = 0; | |
| 1991/0712 | ||
| 1991/0720 | spllo(); | |
| 1991/0716 | /* * These are o.k. because rootinit is null. * Then early kproc's will have a root and dot. */ | |
| 1993/0915 | up->slash = namec("#/", Atodir, 0, 0); | |
| 1997/0327 | up->dot = cclone(up->slash, 0); | |
| 1991/0712 | ||
| 1991/0716 | chandevinit(); | |
| 1991/0926 | if(!waserror()){ | |
| 1992/0923 | strcpy(tstr, arch->id); | |
| 1992/0918 | strcat(tstr, " %s"); ksetterm(tstr); | |
| 1991/0927 | ksetenv("cputype", "386"); | |
| 1997/0329 | if(cpuserver) ksetenv("service", "cpu"); else ksetenv("service", "terminal"); | |
| 1993/0915 | for(i = 0; i < nconf; i++) | |
| 1997/0329 | if(confname[i] && confname[i][0] != '*') | |
| 1993/0915 | ksetenv(confname[i], confval[i]); | |
| 1991/0926 | poperror(); } | |
| 1993/0915 | kproc("alarm", alarmkproc, 0); | |
| 1992/0323 | touser(sp); | |
| 1991/0712 | } | |
| 1991/0629 | void | |
| 1991/0716 | userinit(void) | |
| 1991/0711 | { | |
| 1991/0716 | Proc *p; Segment *s; KMap *k; | |
| 1992/0323 | Page *pg; | |
| 1991/0905 | ||
| 1991/0716 | p = newproc(); p->pgrp = newpgrp(); | |
| 1992/0625 | p->egrp = smalloc(sizeof(Egrp)); p->egrp->ref = 1; | |
| 1997/0606 | p->fgrp = dupfgrp(nil); | |
| 1994/0812 | p->rgrp = newrgrp(); | |
| 1991/1112 | p->procmode = 0640; | |
| 1991/0716 | strcpy(p->text, "*init*"); | |
| 1991/1109 | strcpy(p->user, eve); | |
| 1991/0716 | p->fpstate = FPinit; | |
| 1991/0906 | fpoff(); | |
| 1991/0716 | /* * Kernel Stack | |
| 1991/0717 | * | |
| 1991/0719 | * N.B. The -12 for the stack pointer is important. * 4 bytes for gotolabel's return PC | |
| 1991/0716 | */ p->sched.pc = (ulong)init0; | |
| 1993/0915 | p->sched.sp = (ulong)p->kstack+KSTACK-(1+MAXSYSARG)*BY2WD; | |
| 1991/0716 | /* * User Stack */ | |
| 1993/0915 | s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG); | |
| 1991/0716 | p->seg[SSEG] = s; | |
| 1992/0323 | pg = newpage(1, 0, USTKTOP-BY2PG); segpage(s, pg); k = kmap(pg); bootargs(VA(k)); kunmap(k); | |
| 1991/0716 | /* * Text */ s = newseg(SG_TEXT, UTZERO, 1); | |
| 1993/0915 | s->flushme++; | |
| 1991/0716 | p->seg[TSEG] = s; | |
| 1993/0915 | pg = newpage(1, 0, UTZERO); memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl)); segpage(s, pg); | |
| 1991/0716 | k = kmap(s->map[0]->pages[0]); memmove((ulong*)VA(k), initcode, sizeof initcode); kunmap(k); ready(p); | |
| 1992/0323 | } uchar * pusharg(char *p) { int n; n = strlen(p)+1; sp -= n; memmove(sp, p, n); return sp; } void bootargs(ulong base) { int i, ac; uchar *av[32]; uchar **lsp; | |
| 1992/0903 | char *cp = BOOTLINE; char buf[64]; | |
| 1992/0323 | sp = (uchar*)base + BY2PG - MAXSYSARG*BY2WD; ac = 0; | |
| 1994/0219 | av[ac++] = pusharg("/386/9dos"); | |
| 1997/0327 | cp[BOOTLINELEN-1] = 0; | |
| 1993/0915 | buf[0] = 0; | |
| 1992/0903 | if(strncmp(cp, "fd!", 3) == 0){ | |
| 1998/0825 | sprint(buf, "local!#f/fd%lddisk", strtol(cp+3, 0, 0)); | |
| 1992/0903 | av[ac++] = pusharg(buf); | |
| 1993/0915 | } else if(strncmp(cp, "h!", 2) == 0){ | |
| 1998/0825 | sprint(buf, "local!#H/hd%ldfs", strtol(cp+2, 0, 0)); | |
| 1993/0915 | av[ac++] = pusharg(buf); | |
| 1992/0903 | } else if(strncmp(cp, "hd!", 3) == 0){ | |
| 1998/0825 | sprint(buf, "local!#H/hd%lddisk", strtol(cp+3, 0, 0)); | |
| 1992/0903 | av[ac++] = pusharg(buf); | |
| 1993/0915 | } else if(strncmp(cp, "s!", 2) == 0){ | |
| 1998/0825 | sprint(buf, "local!#w/sd%ldfs", strtol(cp+2, 0, 0)); | |
| 1993/0915 | av[ac++] = pusharg(buf); } else if(strncmp(cp, "sd!", 3) == 0){ | |
| 1998/0825 | sprint(buf, "local!#w/sd%lddisk", strtol(cp+3, 0, 0)); | |
| 1993/0915 | av[ac++] = pusharg(buf); | |
| 1994/1111 | } else if(strncmp(cp, "e!", 2) == 0) av[ac++] = pusharg("-n"); | |
| 1993/0915 | if(buf[0]){ cp = strchr(buf, '!'); if(cp){ strcpy(bootdisk, cp+1); addconf("bootdisk", bootdisk); } } | |
| 1992/0323 | /* 4 byte word align stack */ sp = (uchar*)((ulong)sp & ~3); /* build argc, argv on stack */ sp -= (ac+1)*sizeof(sp); lsp = (uchar**)sp; for(i = 0; i < ac; i++) *lsp++ = av[i] + ((USTKTOP - BY2PG) - base); *lsp = 0; sp += (USTKTOP - BY2PG) - base - sizeof(ulong); | |
| 1991/0711 | } | |
| 1991/0716 | Conf conf; | |
| 1991/0711 | void | |
| 1993/0915 | addconf(char *name, char *val) { if(nconf >= MAXCONF) return; confname[nconf] = name; confval[nconf] = val; nconf++; } char* getconf(char *name) { int i; for(i = 0; i < nconf; i++) | |
| 1997/0403 | if(cistrcmp(confname[i], name) == 0) | |
| 1993/0915 | return confval[i]; return 0; } | |
| 1994/1210 | void | |
| 1991/0711 | confinit(void) { | |
| 1997/0403 | char *p; | |
| 1998/1120 | int i, userpcnt; ulong kpages, maxmem; | |
| 1997/0403 | extern int defmaxmsg; | |
| 1991/0711 | ||
| 1997/0403 | if(p = getconf("*maxmem")) maxmem = strtoul(p, 0, 0); else maxmem = 0; if(p = getconf("*kernelpercent")) | |
| 1998/1120 | userpcnt = 100 - strtol(p, 0, 0); | |
| 1997/0403 | else | |
| 1998/1120 | userpcnt = 0; | |
| 1997/0403 | if(p = getconf("*defmaxmsg")){ i = strtol(p, 0, 0); if(i < defmaxmsg && i >=128) defmaxmsg = i; | |
| 1993/0416 | } | |
| 1994/0814 | ||
| 1997/0329 | meminit(maxmem); | |
| 1993/0915 | ||
| 1991/0711 | conf.npage = conf.npage0 + conf.npage1; | |
| 1998/1124 | conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5; if(cpuserver) conf.nproc *= 3; if(conf.nproc > 2000) conf.nproc = 2000; conf.nimage = 200; conf.nswap = conf.nproc*80; conf.nswppo = 4096; | |
| 1997/1101 | if(cpuserver) { | |
| 1998/1120 | if(userpcnt < 10) userpcnt = 70; kpages = conf.npage - (conf.npage*userpcnt)/100; /* * Hack for the big boys. Only good while physmem < 4GB. * Give the kernel a max. of 16MB + enough to allocate the * page pool. * This is an overestimate as conf.upages < conf.npages. | |
| 1998/1124 | * The patch of nimage is a band-aid, scanning the whole * page list in imagereclaim just takes too long. | |
| 1998/1120 | */ | |
| 1998/1124 | if(kpages > (16*MB + conf.npage*sizeof(Page))/BY2PG){ | |
| 1998/1120 | kpages = (16*MB + conf.npage*sizeof(Page))/BY2PG; | |
| 1998/1124 | conf.nimage = 2000; } | |
| 1997/1101 | } else { | |
| 1998/1120 | if(userpcnt < 10) { | |
| 1997/1101 | if(conf.npage*BY2PG < 16*MB) | |
| 1998/1120 | userpcnt = 40; | |
| 1997/1101 | else | |
| 1998/1120 | userpcnt = 60; | |
| 1997/1101 | } | |
| 1998/1120 | kpages = conf.npage - (conf.npage*userpcnt)/100; | |
| 1998/0420 | /* * Make sure terminals with low memory get at least * 4MB on the first Image chunk allocation. */ | |
| 1997/1101 | if(conf.npage*BY2PG < 16*MB) | |
| 1999/0129 | poolsetparam("Image", 0, 0, 4*1024*1024, nil); | |
| 1997/1101 | } | |
| 1998/1120 | conf.upages = conf.npage - kpages; | |
| 1998/1124 | conf.ialloc = (kpages/2)*BY2PG; | |
| 1998/1120 | /* * Guess how much is taken by the large permanent * datastructures. Mntcache and Mntrpc are not accounted for * (probably ~300KB). */ kpages *= BY2PG; kpages -= conf.upages*sizeof(Page) + conf.nproc*sizeof(Proc) + conf.nimage*sizeof(Image) + conf.nswap + conf.nswppo*sizeof(Page); | |
| 1999/0129 | poolsetparam("Main", kpages, 0, 0, nil); | |
| 1998/1120 | if(!cpuserver){ /* * give terminals lots of image memory, too; the dynamic * allocation will balance the load properly, hopefully. * be careful with 32-bit overflow. */ | |
| 1999/0129 | poolsetparam("Image", kpages, 0, 0, nil); | |
| 1998/1120 | } | |
| 1991/0711 | } | |
| 1998/0910 | static char* mathmsg[] = | |
| 1991/0906 | { | |
| 1991/0913 | "invalid", "denormalized", "div-by-zero", "overflow", "underflow", "precision", "stack", "error", }; | |
| 1991/0906 | ||
| 1998/0916 | static void mathnote(void) { int i; ulong status; char *msg, note[ERRLEN]; status = up->fpsave.status; /* * Some attention should probably be paid here to the * exception masks and error summary. */ msg = "unknown"; for(i = 0; i < 8; i++){ if(!((1<<i) & status)) continue; msg = mathmsg[i]; break; } sprint(note, "sys: fp: %s fppc=0x%lux", msg, up->fpsave.pc); postnote(up, 1, note, NDebug); } | |
| 1991/0906 | /* | |
| 1991/0912 | * math coprocessor error */ | |
| 1998/0910 | static void | |
| 1997/0327 | matherror(Ureg *ur, void*) | |
| 1991/0912 | { | |
| 1991/0913 | /* * a write cycle to port 0xF0 clears the interrupt latch attached * to the error# line from the 387 */ | |
| 1998/0916 | if(!(m->cpuiddx & 0x01)) outb(0xF0, 0xFF); | |
| 1991/0913 | ||
| 1992/0806 | /* * save floating point state to check out error */ | |
| 1993/0915 | fpenv(&up->fpsave); | |
| 1998/0916 | mathnote(); | |
| 1992/0806 | if(ur->pc & KZERO) | |
| 1998/0916 | panic("fp: status %lux fppc=0x%lux pc=0x%lux", up->fpsave.status, up->fpsave.pc, ur->pc); | |
| 1991/0912 | } /* | |
| 1991/0906 | * math coprocessor emulation fault */ | |
| 1998/0910 | static void | |
| 1997/0327 | mathemu(Ureg*, void*) | |
| 1991/0906 | { | |
| 1993/0915 | switch(up->fpstate){ | |
| 1991/0906 | case FPinit: fpinit(); | |
| 1993/0915 | up->fpstate = FPactive; | |
| 1991/0906 | break; case FPinactive: | |
| 1998/0916 | /* * Before restoring the state, check for any pending * exceptions, there's no way to restore the state without * generating an unmasked exception. * More attention should probably be paid here to the * exception masks and error summary. */ if((up->fpsave.status & ~up->fpsave.control) & 0x07F){ mathnote(); break; } | |
| 1993/0915 | fprestore(&up->fpsave); up->fpstate = FPactive; | |
| 1991/0906 | break; case FPactive: | |
| 1992/0805 | panic("math emu", 0); | |
| 1991/0906 | break; } } /* * math coprocessor segment overrun */ | |
| 1998/0910 | static void | |
| 1997/0327 | mathover(Ureg*, void*) | |
| 1991/0906 | { | |
| 1992/0805 | pexit("math overrun", 0); | |
| 1991/0906 | } void mathinit(void) { | |
| 1998/0910 | trapenable(VectorCERR, matherror, 0); | |
| 1997/0327 | if(X86FAMILY(m->cpuidax) == 3) | |
| 1998/0910 | intrenable(IrqIRQ13, matherror, 0, BUSUNKNOWN); trapenable(VectorCNA, mathemu, 0); trapenable(VectorCSO, mathover, 0); | |
| 1991/0906 | } /* | |
| 1991/0716 | * set up floating point for a new process */ | |
| 1991/0703 | void | |
| 1991/0716 | procsetup(Proc *p) | |
| 1991/0703 | { | |
| 1991/0716 | p->fpstate = FPinit; | |
| 1991/0906 | fpoff(); | |
| 1991/0705 | } | |
| 1991/0712 | /* | |
| 1991/0906 | * Save the mach dependent part of the process state. | |
| 1991/0712 | */ | |
| 1991/0705 | void | |
| 1992/0122 | procsave(Proc *p) | |
| 1991/0705 | { | |
| 1992/0805 | if(p->fpstate == FPactive){ if(p->state == Moribund) fpoff(); | |
| 1998/0916 | else{ /* * Fpsave() stores without handling pending * unmasked exeptions. Postnote() can't be called * here as sleep() already has up->rlock, so * the handling of pending exceptions is delayed * until the process runs again and generates an * emulation fault to activate the FPU. */ | |
| 1993/0915 | fpsave(&up->fpsave); | |
| 1998/0916 | } | |
| 1992/0805 | p->fpstate = FPinactive; | |
| 1991/0906 | } | |
| 1998/0605 | /* * Switch to the prototype page tables for this processor. * While this processor is in the scheduler, the process could run * on another processor and exit, returning the page tables to * the free list where they could be reallocated and overwritten. * When this processor eventually has to get an entry from the * trashed page tables it will crash. */ mmuflushtlb(PADDR(m->pdb)); | |
| 1991/0712 | } | |
| 1991/0716 | void | |
| 1997/0327 | exit(int ispanic) | |
| 1991/0712 | { | |
| 1997/0327 | int ms, once; | |
| 1991/0712 | ||
| 1997/0327 | lock(&active); if(ispanic) active.ispanic = ispanic; else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0) active.ispanic = 0; once = active.machs & (1<<m->machno); active.machs &= ~(1<<m->machno); active.exiting = 1; unlock(&active); | |
| 1991/0803 | ||
| 1997/0327 | if(once) print("cpu%d: exiting\n", m->machno); | |
| 1996/01171 | spllo(); | |
| 1997/0327 | for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){ delay(TK2MS(2)); if(active.machs == 0 && consactive() == 0) break; } if(active.ispanic && m->machno == 0){ | |
| 1993/1113 | if(cpuserver) | |
| 1993/0915 | delay(10000); else for(;;); | |
| 1997/0327 | } else | |
| 1996/01171 | delay(1000); | |
| 1992/0903 | ||
| 1997/0327 | arch->reset(); | |
| 1991/0803 | } | |
| 1991/1210 | int | |
| 1993/0915 | isaconfig(char *class, int ctlrno, ISAConf *isa) { | |
| 1995/0920 | char cc[NAMELEN], *p, *q, *r; | |
| 1993/0915 | int n; sprint(cc, "%s%d", class, ctlrno); for(n = 0; n < nconf; n++){ | |
| 1997/0327 | if(cistrncmp(confname[n], cc, NAMELEN)) | |
| 1993/0915 | continue; | |
| 1995/0920 | isa->nopt = 0; | |
| 1993/0915 | p = confval[n]; while(*p){ while(*p == ' ' || *p == '\t') p++; if(*p == '\0') break; | |
| 1997/0327 | if(cistrncmp(p, "type=", 5) == 0){ | |
| 1993/0915 | p += 5; for(q = isa->type; q < &isa->type[NAMELEN-1]; q++){ if(*p == '\0' || *p == ' ' || *p == '\t') break; *q = *p++; } *q = '\0'; } | |
| 1997/0327 | else if(cistrncmp(p, "port=", 5) == 0) | |
| 1993/0915 | isa->port = strtoul(p+5, &p, 0); | |
| 1997/0327 | else if(cistrncmp(p, "irq=", 4) == 0) | |
| 1993/0915 | isa->irq = strtoul(p+4, &p, 0); | |
| 1997/0327 | else if(cistrncmp(p, "dma=", 4) == 0) | |
| 1996/0425 | isa->dma = strtoul(p+4, &p, 0); | |
| 1997/0327 | else if(cistrncmp(p, "mem=", 4) == 0) | |
| 1993/0915 | isa->mem = strtoul(p+4, &p, 0); | |
| 1997/0327 | else if(cistrncmp(p, "size=", 5) == 0) | |
| 1993/0915 | isa->size = strtoul(p+5, &p, 0); | |
| 1997/0327 | else if(cistrncmp(p, "freq=", 5) == 0) | |
| 1994/0823 | isa->freq = strtoul(p+5, &p, 0); | |
| 1995/0920 | else if(isa->nopt < NISAOPT){ r = isa->opt[isa->nopt]; while(*p && *p != ' ' && *p != '\t'){ *r++ = *p++; if(r-isa->opt[isa->nopt] >= ISAOPTLEN-1) break; } *r = '\0'; isa->nopt++; } | |
| 1993/0915 | while(*p && *p != ' ' && *p != '\t') p++; } return 1; } return 0; | |
| 1991/0803 | } | |
| 1995/0222 | int iprint(char *fmt, ...) { char buf[PRINTSIZE]; int n; | |
| 1996/0214 | va_list arg; | |
| 1995/0222 | ||
| 1996/0214 | va_start(arg, fmt); n = doprint(buf, buf+sizeof(buf), fmt, arg) - buf; va_end(arg); | |
| 1995/0222 | screenputs(buf, n); return n; } int cistrcmp(char *a, char *b) { int ac, bc; for(;;){ ac = *a++; bc = *b++; if(ac >= 'A' && ac <= 'Z') ac = 'a' + (ac - 'A'); if(bc >= 'A' && bc <= 'Z') bc = 'a' + (bc - 'A'); ac -= bc; if(ac) return ac; if(bc == 0) break; } | |
| 1997/0327 | return 0; } int cistrncmp(char *a, char *b, int n) { unsigned ac, bc; while(n > 0){ ac = *a++; bc = *b++; n--; if(ac >= 'A' && ac <= 'Z') ac = 'a' + (ac - 'A'); if(bc >= 'A' && bc <= 'Z') bc = 'a' + (bc - 'A'); ac -= bc; if(ac) return ac; if(bc == 0) break; } | |
| 1995/0222 | return 0; } | |