Annotation of uae/src/od-amiga/ami-rexx.c, revision 1.1

1.1     ! root        1:  /*
        !             2:   * UAE - The Un*x Amiga Emulator
        !             3:   * 
        !             4:   * ami-rexx.c
        !             5:   * 
        !             6:   * Copyright 1996 Samuel Devulder.
        !             7:   *
        !             8:   * History:
        !             9:   *     05/09/97: Added UAEEXE support.
        !            10:   */
        !            11: 
        !            12: #include <proto/exec.h>
        !            13: #include <proto/rexxsyslib.h>
        !            14: #include <proto/dos.h>
        !            15: #ifndef __SASC
        !            16: #include <proto/alib.h>
        !            17: #endif
        !            18: 
        !            19: #include <rexx/storage.h>
        !            20: #include <rexx/errors.h>
        !            21: 
        !            22: /* this prevent a conflict between <rexx/rexxio.h> and <sys/dirent.h> */
        !            23: #undef DT_DIR 
        !            24: 
        !            25: /****************************************************************************/
        !            26: 
        !            27: #include "sysconfig.h"
        !            28: #include "sysdeps.h"
        !            29: 
        !            30: #include "uae.h"
        !            31: #include "config.h"
        !            32: #include "options.h"
        !            33: #ifdef __GNUC__
        !            34: #include "../include/memory.h" /* or else gcc includes machdep/memory.h */
        !            35: #endif
        !            36: #include "custom.h"
        !            37: #include "readcpu.h"
        !            38: #include "newcpu.h"
        !            39: #include "disk.h"
        !            40: #include "gui.h"
        !            41: #include "sound.h"
        !            42: #include "gensound.h"
        !            43: #include "uaeexe.h"
        !            44: #include "threaddep/penguin.h"
        !            45: #include "xwin.h"
        !            46: 
        !            47: #include <ctype.h>
        !            48: 
        !            49: /****************************************************************************/
        !            50: 
        !            51: #define UAE_PORTNAME    "UAE"
        !            52: #define RESULT_LEN      1024
        !            53: #define PORT_LEN        80
        !            54: #define CMD_LEN         1024
        !            55: 
        !            56: typedef struct
        !            57: {
        !            58:     char port[PORT_LEN];
        !            59:     char cmd_on[CMD_LEN];
        !            60:     char cmd_off[CMD_LEN];
        !            61: } gui_rexx_s;
        !            62: 
        !            63: enum {LED_POW, LED_DF0, LED_DF1, LED_DF2, LED_DF3,
        !            64:       NAME_DF0, NAME_DF1, NAME_DF2, NAME_DF3,
        !            65:       ON_EXIT,
        !            66:       GUI_REXX_MAX};
        !            67: 
        !            68: /****************************************************************************/
        !            69: 
        !            70: int  rexx_init(void);
        !            71: void rexx_exit(void);
        !            72: void rexx_led(int led, int on);
        !            73: void rexx_filename(int num, char *name);
        !            74: void rexx_handle_events(void);
        !            75: 
        !            76: /****************************************************************************/
        !            77: 
        !            78: #ifdef __GNUC__
        !            79: struct RxsLib
        !            80: #else
        !            81: struct Library
        !            82: #endif
        !            83:                         *RexxSysBase;
        !            84: static struct MsgPort   *ARexxPort;
        !            85: static gui_rexx_s        gui_rexx[GUI_REXX_MAX];
        !            86: static char              RESULT[RESULT_LEN];
        !            87: static int               led_state[5];
        !            88: 
        !            89: static int   ADDRESS(char *hostname, char *cmd);
        !            90: static int   matchstr(char **line,char *pat);
        !            91: static void  extractstr(char **line, char *result, int len);
        !            92: static int   matchnum(char **line);
        !            93: 
        !            94: /****************************************************************************/
        !            95: 
        !            96: extern int quit_program;                                 /* ami-gui.c */
        !            97: extern void activate_debugger(void);                     /* debug.c */
        !            98: extern char *to_unix_path(char *s);                      /* ami-disk.c */
        !            99: extern char *from_unix_path(char *s);                    /* ami-disk.c */
        !           100: 
        !           101: /****************************************************************************/
        !           102: 
        !           103: int rexx_init(void)
        !           104: {
        !           105:     quit_program = 0;
        !           106:     RexxSysBase = (void*)OpenLibrary("rexxsyslib.library",0L);
        !           107:     if(!RexxSysBase) {
        !           108:         fprintf(stderr, "Can't find rexxsyslib.library!\n");
        !           109:         return 1;
        !           110:     }
        !           111:     if(FindPort(UAE_PORTNAME)) {
        !           112:         fprintf(stderr, "Port \"%s\" already exists!\n",UAE_PORTNAME);
        !           113:         return 1;    
        !           114:     }
        !           115:     ARexxPort = CreatePort(UAE_PORTNAME,0);
        !           116:     if(!ARexxPort) {
        !           117:         fprintf(stderr, "Failed to open AREXX port \"%s\"!\n",UAE_PORTNAME);
        !           118:         return 1;
        !           119:     }
        !           120:     fprintf(stderr,"Rexx port \"%s\" installed.\n", UAE_PORTNAME);
        !           121:     rexx_handle_events();
        !           122:     return 0;
        !           123: }
        !           124: 
        !           125: /****************************************************************************/
        !           126: 
        !           127: void rexx_exit(void)
        !           128: {
        !           129:     if(ARexxPort) {
        !           130:         struct RexxMsg *msg;
        !           131:         gui_rexx_s *gui = &gui_rexx[ON_EXIT];
        !           132: 
        !           133:         if(gui->port[0] && gui->cmd_on[0]) {
        !           134:             if(ADDRESS(gui->port, gui->cmd_on) != RC_OK) {
        !           135:                 fprintf(stderr,"%s:%s:%s\n", gui->port,
        !           136:                                              gui->cmd_on,
        !           137:                                              RESULT);
        !           138:             }
        !           139:             gui->port[0] = '\0';
        !           140:          }
        !           141:         Forbid();
        !           142:         while((msg = (struct RexxMsg*)GetMsg(ARexxPort))) {
        !           143:            msg->rm_Result1 = RC_ERROR;
        !           144:            msg->rm_Result2 = NULL;
        !           145:            ReplyMsg((void*)msg);
        !           146:         }
        !           147:         DeletePort(ARexxPort);
        !           148:         Permit();
        !           149:         ARexxPort = NULL;
        !           150:     }
        !           151:     if(RexxSysBase) {
        !           152:         CloseLibrary((void*)RexxSysBase);
        !           153:         RexxSysBase = NULL;
        !           154:     }
        !           155: }
        !           156: 
        !           157: /****************************************************************************/
        !           158: 
        !           159: static int EJECT(char *line)
        !           160: {
        !           161:     int drive = matchnum(&line);
        !           162:     if(drive<0 || drive>3) return RC_WARN;
        !           163:     disk_eject(drive);
        !           164:     sprintf(RESULT,"Drive %d ejected",drive);
        !           165:     return RC_OK;
        !           166: }
        !           167: 
        !           168: /****************************************************************************/
        !           169: 
        !           170: static int INSERT(char *line)
        !           171: {
        !           172:     int drive = matchnum(&line);
        !           173:     if(drive<0 || drive>3) return RC_WARN;
        !           174:     if(disk_empty(drive)) {
        !           175:         char buff[256];
        !           176:         char *name;
        !           177:         extractstr(&line, buff, 256);
        !           178:         name = to_unix_path(buff);
        !           179:         disk_insert(drive, name);
        !           180:         free(name);
        !           181:     } else {
        !           182:         sprintf(RESULT,"Drive %d not empty!",drive);
        !           183:         return RC_WARN;
        !           184:     }
        !           185:     return RC_OK;
        !           186: }
        !           187: 
        !           188: /****************************************************************************/
        !           189: 
        !           190: static void QUIT(void)
        !           191: {
        !           192:     broken_in = 1;
        !           193:     regs.spcflags |= SPCFLAG_BRK;
        !           194:     quit_program = 1;
        !           195: }
        !           196: 
        !           197: /****************************************************************************/
        !           198: 
        !           199: static int QUERY(char *line)
        !           200: {
        !           201:     char *res = NULL;
        !           202:     int   alc = 0;
        !           203: 
        !           204:     if     (matchstr(&line, "LED_POW"))  res = led_state[0]?"1":"0";
        !           205:     else if(matchstr(&line, "LED_DF0"))  res = led_state[1]?"1":"0";
        !           206:     else if(matchstr(&line, "LED_DF1"))  res = led_state[2]?"1":"0";
        !           207:     else if(matchstr(&line, "LED_DF2"))  res = led_state[3]?"1":"0";
        !           208:     else if(matchstr(&line, "LED_DF3"))  res = led_state[4]?"1":"0";
        !           209:     else if(matchstr(&line, "NAME_DF0")) res = from_unix_path(currprefs.df[0]), alc = 1;
        !           210:     else if(matchstr(&line, "NAME_DF1")) res = from_unix_path(currprefs.df[1]), alc = 1;
        !           211:     else if(matchstr(&line, "NAME_DF2")) res = from_unix_path(currprefs.df[2]), alc = 1;
        !           212:     else if(matchstr(&line, "NAME_DF3")) res = from_unix_path(currprefs.df[3]), alc = 1;
        !           213:     else if(matchstr(&line, "FAKEJOYSTICK")) res = currprefs.fake_joystick?"1":"0";
        !           214:     else if(matchstr(&line, "DISPLAY"))  res = inhibit_frame?"0":"1";
        !           215:     else if(matchstr(&line, "FRAMERATE")) {
        !           216:         sprintf(RESULT,"%d",currprefs.framerate);
        !           217:         return RC_OK;
        !           218:     } else if(matchstr(&line, "SOUND")) {
        !           219:         sprintf(RESULT,"%d",sound_available?currprefs.produce_sound:-1);
        !           220:         return RC_OK;
        !           221:     } 
        !           222:     else return RC_ERROR;
        !           223: 
        !           224:     if(res) {
        !           225:         strncpy(RESULT, res, RESULT_LEN);
        !           226:         if(alc) free(res);
        !           227:     }
        !           228:     return RC_OK;
        !           229: }
        !           230: 
        !           231: /****************************************************************************/
        !           232: 
        !           233: static int FEEDBACK(char *line)
        !           234: {
        !           235:     gui_rexx_s *gui = NULL;
        !           236: 
        !           237:     if     (matchstr(&line,"LED_POW"))  gui = &gui_rexx[LED_POW];
        !           238:     else if(matchstr(&line,"LED_DF0"))  gui = &gui_rexx[LED_DF0];
        !           239:     else if(matchstr(&line,"LED_DF1"))  gui = &gui_rexx[LED_DF1];
        !           240:     else if(matchstr(&line,"LED_DF2"))  gui = &gui_rexx[LED_DF2];
        !           241:     else if(matchstr(&line,"LED_DF3"))  gui = &gui_rexx[LED_DF3];
        !           242:     else if(matchstr(&line,"NAME_DF0")) gui = &gui_rexx[NAME_DF0];
        !           243:     else if(matchstr(&line,"NAME_DF1")) gui = &gui_rexx[NAME_DF1];
        !           244:     else if(matchstr(&line,"NAME_DF2")) gui = &gui_rexx[NAME_DF2];
        !           245:     else if(matchstr(&line,"NAME_DF3")) gui = &gui_rexx[NAME_DF3];
        !           246:     else if(matchstr(&line,"ON_EXIT"))  gui = &gui_rexx[ON_EXIT];
        !           247:     else return RC_ERROR;
        !           248: 
        !           249:     while(1) {
        !           250:         if(matchstr(&line, "ADDRESS") ||
        !           251:            matchstr(&line, "PORT")) {
        !           252:             extractstr(&line, gui->port, PORT_LEN);
        !           253:         } else if(matchstr(&line,"COMMAND") ||
        !           254:                   matchstr(&line,"CMD") ||
        !           255:                   matchstr(&line,"CMD_ON")) {
        !           256:             extractstr(&line, gui->cmd_on,  CMD_LEN);
        !           257:         } else if(matchstr(&line,"CMD_OFF")) {
        !           258:             extractstr(&line, gui->cmd_off, CMD_LEN);
        !           259:         } else break;
        !           260:     }
        !           261:     return RC_OK;
        !           262: }
        !           263: 
        !           264: /****************************************************************************/
        !           265: 
        !           266: static int VERSION(char *line)
        !           267: {
        !           268:     if(matchstr(&line,"STRING")) {
        !           269:         sprintf(RESULT,
        !           270:                 "UAE-%d.%d.%d � by Bernd Schmidt & contributors, "
        !           271:                 "Amiga Port by Samuel Devulder.",
        !           272:                 (version / 100) % 10, (version / 10) % 10, version % 10);
        !           273:     } else if(matchstr(&line,"NUM")) {
        !           274:         sprintf(RESULT,"%d",version);
        !           275:     } else if(matchstr(&line,"AUTHOR")) {
        !           276:         sprintf(RESULT,"� by Bernd Schmidt & contributors");
        !           277:     } else if(matchstr(&line,"PORT")) {
        !           278:         sprintf(RESULT,"Amiga Port by Samuel Devulder");
        !           279:     } else return RC_ERROR;
        !           280:     return RC_OK;
        !           281: }
        !           282: 
        !           283: /****************************************************************************/
        !           284: 
        !           285: static int FRAMERATE(char *line)
        !           286: {
        !           287:     int num;
        !           288:     num = matchnum(&line);
        !           289:     if(num>=1 && num<=20) {
        !           290:         currprefs.framerate = num;
        !           291:     } else {
        !           292:         sprintf(RESULT,"Invalid frame rate: %d\n", num);
        !           293:         return RC_WARN;
        !           294:     }
        !           295:     return RC_OK;
        !           296: }
        !           297: 
        !           298: /****************************************************************************/
        !           299: 
        !           300: static int FAKEJOYSTICK(char *line)
        !           301: {
        !           302:     if     (matchstr(&line,"ON"))     currprefs.fake_joystick = 2;
        !           303:     else if(matchstr(&line,"OFF"))    currprefs.fake_joystick = 0;
        !           304:     else if(matchstr(&line,"TOGGLE")) currprefs.fake_joystick =
        !           305:                                       currprefs.fake_joystick?0:2;
        !           306:     else return RC_ERROR;
        !           307:     return RC_OK;
        !           308: }
        !           309: 
        !           310: /****************************************************************************/
        !           311: 
        !           312: static int DISPLAY(char *line)
        !           313: {
        !           314:     if     (matchstr(&line,"ON"))     inhibit_frame = 0;
        !           315:     else if(matchstr(&line,"OFF"))    inhibit_frame = 1;
        !           316:     else if(matchstr(&line,"TOGGLE")) inhibit_frame = inhibit_frame?0:1;
        !           317:     else return RC_ERROR;
        !           318:     return RC_OK;
        !           319: }
        !           320: 
        !           321: /****************************************************************************/
        !           322: 
        !           323: static int SOUND(char *line)
        !           324: {
        !           325:     if(!sound_available) {
        !           326:         sprintf(RESULT,"Sound not available!");
        !           327:         return RC_WARN;
        !           328:     }
        !           329: 
        !           330:     if     (matchstr(&line,"ON"))     currprefs.produce_sound = 2;
        !           331:     else if(matchstr(&line,"OFF"))    currprefs.produce_sound = 1;
        !           332:     else if(matchstr(&line,"BEST"))   currprefs.produce_sound = 3;
        !           333:     else if(matchstr(&line,"TOGGLE")) currprefs.produce_sound =
        !           334:                                       currprefs.produce_sound<=1?2:1;
        !           335:     else return RC_ERROR;
        !           336:     return RC_OK;
        !           337: }
        !           338: 
        !           339: /****************************************************************************/
        !           340: 
        !           341: static int UAEEXE(char *line)
        !           342: {
        !           343:     if(uaeexe(line)) {
        !           344:         sprintf(RESULT,"Remote CLI failed!");
        !           345:         return RC_WARN;
        !           346:     }
        !           347:     return RC_OK;
        !           348: }
        !           349: 
        !           350: /****************************************************************************/
        !           351: 
        !           352: static int process_cmd(char *line)
        !           353: {
        !           354:     RESULT[0] = '\0';
        !           355:     if     (matchstr(&line, "EJECT"))        return EJECT(line);
        !           356:     else if(matchstr(&line, "INSERT"))       return INSERT(line);
        !           357:     else if(matchstr(&line, "QUERY"))        return QUERY(line);
        !           358:     else if(matchstr(&line, "FEEDBACK"))     return FEEDBACK(line);
        !           359:     else if(matchstr(&line, "VERSION"))      return VERSION(line);
        !           360:     else if(matchstr(&line, "BYE"))          QUIT();
        !           361:     else if(matchstr(&line, "QUIT"))         QUIT();
        !           362:     else if(matchstr(&line, "DEBUG"))        activate_debugger();
        !           363:     else if(matchstr(&line, "RESET"))        m68k_reset();
        !           364:     else if(matchstr(&line, "DISPLAY"))      return DISPLAY(line);
        !           365:     else if(matchstr(&line, "FRAMERATE"))    return FRAMERATE(line);
        !           366:     else if(matchstr(&line, "FAKEJOYSTICK")) return FAKEJOYSTICK(line);
        !           367:     else if(matchstr(&line, "SOUND"))        return SOUND(line);
        !           368:     else if(matchstr(&line, "UAEEXE"))       return UAEEXE(line);
        !           369:     else return RC_ERROR;
        !           370:     return RC_OK;
        !           371: }
        !           372: 
        !           373: /****************************************************************************/
        !           374: 
        !           375: void rexx_handle_events(void)
        !           376: {
        !           377:     struct RexxMsg *msg;
        !           378:     while((msg = (struct RexxMsg*)GetMsg(ARexxPort))) {
        !           379:         if(!(msg->rm_Action & RXCOMM)) {
        !           380:             fprintf(stderr,"Unknown action '%08X' recieved!\n",
        !           381:                     msg->rm_Action);
        !           382:             continue;
        !           383:         }
        !           384:         msg->rm_Result1 = process_cmd(msg->rm_Args[0]);
        !           385:         msg->rm_Result2 = NULL;
        !           386:         if(msg->rm_Action & RXFF_RESULT) {
        !           387:             msg->rm_Result2 = (LONG)CreateArgstring(RESULT,strlen(RESULT));
        !           388:         }
        !           389:         ReplyMsg((void*)msg);
        !           390:     }
        !           391: }
        !           392: 
        !           393: /****************************************************************************/
        !           394: 
        !           395: void rexx_led(int led, int on)
        !           396: {
        !           397:     gui_rexx_s *gui = NULL;
        !           398: 
        !           399:     if(led < 0 || led > 4) return;
        !           400:     led_state[led] = on;
        !           401: 
        !           402:     if(led == 0) gui = &gui_rexx[LED_POW];
        !           403:     if(led == 1) gui = &gui_rexx[LED_DF0];
        !           404:     if(led == 2) gui = &gui_rexx[LED_DF1];
        !           405:     if(led == 3) gui = &gui_rexx[LED_DF2];
        !           406:     if(led == 4) gui = &gui_rexx[LED_DF3];
        !           407: 
        !           408:     if(gui->port[0] && gui->cmd_on[0] && gui->cmd_off[0]) {
        !           409:         if(ADDRESS(gui->port, on ? gui->cmd_on : gui->cmd_off) != RC_OK) {
        !           410:             fprintf(stderr,"%s:%s:%s\n", gui->port,
        !           411:                                          on ? gui->cmd_on : gui->cmd_off,
        !           412:                                          RESULT);
        !           413:         }
        !           414:     }
        !           415: }
        !           416: 
        !           417: /****************************************************************************/
        !           418: 
        !           419: void rexx_filename(int num, char *filename)
        !           420: {
        !           421:     gui_rexx_s *gui = NULL;
        !           422:     if(num < 0 || num > 3) return;
        !           423:     gui = &gui_rexx[NAME_DF0 + num];
        !           424:     if(gui->port[0] && gui->cmd_on[0]) {
        !           425:         char buf[CMD_LEN];
        !           426:         if(!(filename = from_unix_path(filename))) return;
        !           427:         sprintf(buf, gui->cmd_on, filename);
        !           428:         free(filename);
        !           429:         if(ADDRESS(gui->port, buf) != RC_OK) {
        !           430:             fprintf(stderr,"%s:%s:%s\n", gui->port, buf, RESULT);
        !           431:         }
        !           432:     }
        !           433: }
        !           434: 
        !           435: /****************************************************************************/
        !           436: /* send a message to an AREXX port.
        !           437:  */
        !           438: static int ADDRESS(char *hostname, char *cmd)
        !           439: {
        !           440:     struct MsgPort *RexxPort,
        !           441:                    *ReplyPort;
        !           442:     struct RexxMsg *HostMsg,
        !           443:                    *answer;
        !           444:     int result = RC_WARN;
        !           445: 
        !           446:     if(!stricmp(hostname, "COMMAND")) {
        !           447:         return SystemTagList(cmd,NULL);
        !           448:     }
        !           449: 
        !           450:     if((RexxPort = (void *)FindPort(hostname))) {
        !           451:         if((ReplyPort = (void *)CreateMsgPort())) {
        !           452:             if((HostMsg = CreateRexxMsg(ReplyPort, NULL, hostname))) {
        !           453:                 if((HostMsg->rm_Args[0] = CreateArgstring(cmd,strlen(cmd)))) {
        !           454:                     HostMsg->rm_Action  = RXCOMM | RXFF_RESULT;
        !           455:                     PutMsg(RexxPort, (void*)HostMsg);
        !           456:                     WaitPort(ReplyPort);
        !           457:                     while(!(answer = (void *)GetMsg(ReplyPort)));
        !           458:                     result = answer->rm_Result1;
        !           459:                     if(result == RC_OK) {
        !           460:                         if(answer->rm_Result2) {
        !           461:                         strncpy(RESULT,(char *)answer->rm_Result2,RESULT_LEN);
        !           462:                         DeleteArgstring((char *)answer->rm_Result2);
        !           463:                         } else RESULT[0] = '\0';
        !           464:                     }
        !           465:                     DeleteArgstring(HostMsg->rm_Args[0]);
        !           466:                 } else strcpy(RESULT, "Can't create argstring!");
        !           467:                 DeleteRexxMsg(HostMsg);
        !           468:             } else strcpy(RESULT, "Can't create rexx message!");
        !           469:             DeleteMsgPort(ReplyPort);
        !           470:         } else strcpy(RESULT, "Can't alloc reply port!");
        !           471:     } else sprintf(RESULT, "Port \"%s\" not found!",hostname);
        !           472:     return result;
        !           473: }
        !           474: 
        !           475: /****************************************************************************/
        !           476: /* argument parsing routines
        !           477:  */
        !           478: static int matchstr(char **line,char *pat)
        !           479: {
        !           480:     char *s = *line;
        !           481:     char match = 0;
        !           482:     while(isspace(*s)) ++s;
        !           483:     if(*s=='\"' || *s== '\'') match = *s++;
        !           484:     while(*s && (tolower(*s)==tolower(*pat)) && (!match || *s!=match)) {++s;++pat;}
        !           485:     if(match && *s==match && s[1]) ++s;
        !           486:     if(!*pat && (!*s || isspace(*s))) {
        !           487:         while(isspace(*s)) ++s;
        !           488:         *line = s;
        !           489:         return 1;
        !           490:     }
        !           491:     return 0;
        !           492: }
        !           493: 
        !           494: /****************************************************************************/
        !           495: 
        !           496: static void extractstr(char **line, char *result, int len)
        !           497: {
        !           498:     char *s    = *line;
        !           499:     char match = 0;
        !           500: 
        !           501:     while(isspace(*s)) ++s;
        !           502: 
        !           503:     if(*s=='\"' || *s=='\'') match = *s++;
        !           504:     while(*s && *s != match) {
        !           505:         if(*s == '\\' && (s[1] == '\'' || s[1] == '\"')) ++s;
        !           506:         if(len > 1) {*result++ = *s;--len;}
        !           507:         ++s;
        !           508:         if(!match && isspace(*s)) break;
        !           509:     }
        !           510:     if(match && *s == match) ++s;
        !           511:     while(isspace(*s)) ++s;
        !           512: 
        !           513:     *result  = '\0';
        !           514:     *line    = s;
        !           515: }
        !           516: 
        !           517: /****************************************************************************/
        !           518: 
        !           519: static int matchnum(char **line)
        !           520: {
        !           521:     char *s = *line, match = 0;
        !           522:     int sign = 1, num = 0;
        !           523: 
        !           524:     while(isspace(*s)) ++s;
        !           525:     if(*s=='\"' || *s=='\'') match = *s++;
        !           526:     if(*s=='-') {sign = -1;++s;}
        !           527:     if(*s=='+') ++s;
        !           528:     while(isspace(*s)) ++s;
        !           529:     while(*s>='0' && *s<='9') num = num*10 + (*s++ - '0');
        !           530:     if(match && *s==match && s[1]) ++s;
        !           531:     while(isspace(*s)) ++s;
        !           532:     *line = s;
        !           533:     return sign>0?num:-num;
        !           534: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.